|
| 1 | +# 🍹 Ssoul - 칵테일 레시피 공유 플랫폼 |
| 2 | + |
| 3 | +## 🔗 서비스 링크 |
| 4 | +**홈페이지**: [https://ssoul.life](https://ssoul.life) |
| 5 | + |
| 6 | +## 📌 개요 |
| 7 | +본 시스템은 사용자가 칵테일 레시피를 공유하고, AI 바텐더 '쑤리'를 통해 맞춤형 칵테일을 추천받으며, 칵테일 문화를 즐길 수 있는 웹 서비스입니다. |
| 8 | +칵테일 입문자부터 애호가까지 모든 사용자를 대상으로, 단순한 레시피 제공을 넘어 AI 챗봇을 통한 인터랙티브한 칵테일 추천과 커뮤니티 기능을 제공합니다. |
| 9 | +또한 사용자 활동 기반 등급 시스템(ABV 도수)과 MyBar(킵) 기능을 통해 꾸준한 참여를 유도하도록 설계했습니다. |
| 10 | +Spring Boot, Spring AI, OAuth2, SSE, AWS S3 등을 통합해 운영하며, |
| 11 | +칵테일 문화 확산과 사용자 간 레시피 공유를 통한 커뮤니티 활성화를 목표로 합니다. |
| 12 | + |
| 13 | +--- |
| 14 | + |
| 15 | +## 👥 팀원 및 역할 |
| 16 | + |
| 17 | +| 팀원 | 역할 | 담당 업무 | |
| 18 | +|------|------|-----------| |
| 19 | +| 정용진 | Backend(PM) | AI 챗봇 '쑤리', 단계별 추천 시스템 | |
| 20 | +| 이광원 | Backend(팀장) / Frontend | 칵테일 도메인, 검색/필터링, 상세 조회 | |
| 21 | +| 석근호 | Backend / Frontend | 커뮤니티(게시판/댓글), S3, 파일 업로드 | |
| 22 | +| 최승욱 | Backend / Frontend | 인증/인가, 소셜로그인(OAuth2), JWT, 테라폼 | |
| 23 | +| 홍민애 | Backend | MyBar(킵) 기능, 알림 시스템(SSE) | |
| 24 | + |
| 25 | +--- |
| 26 | + |
| 27 | +## 🛠 기술 스택 |
| 28 | +- **Backend**: Java 21, Spring Boot 3.5.5 |
| 29 | +- **Database**: MySQL 8.x / JPA / H2 (개발) |
| 30 | +- **AI 연동**: Spring AI, Gemini API |
| 31 | +- **인증**: Spring Security, OAuth2 (Kakao, Google, Naver), JWT |
| 32 | +- **파일 저장**: AWS S3 |
| 33 | +- **실시간 통신**: SSE (Server-Sent Events) |
| 34 | +- **캐싱**: Redis |
| 35 | +- **API 문서**: Swagger (SpringDoc OpenAPI) |
| 36 | + |
| 37 | +--- |
| 38 | + |
| 39 | +## 🔄 핵심 기능 프로세스 |
| 40 | + |
| 41 | +### 1️⃣ AI 챗봇 '쑤리' 칵테일 추천 프로세스 |
| 42 | + |
| 43 | +```mermaid |
| 44 | +sequenceDiagram |
| 45 | + participant User as 사용자 |
| 46 | + participant Controller as ChatbotController |
| 47 | + participant Service as ChatbotService |
| 48 | + participant AI as Spring AI (Gemini) |
| 49 | + participant DB as Database |
| 50 | + participant Cocktail as CocktailRepository |
| 51 | +
|
| 52 | + User->>Controller: 대화 시작/메시지 전송 |
| 53 | + Controller->>Service: 메시지 처리 요청 |
| 54 | + |
| 55 | + alt 단계별 추천 모드 |
| 56 | + Service->>Service: 추천 단계 확인 |
| 57 | + Service->>Cocktail: 필터 조건별 칵테일 조회 |
| 58 | + Cocktail-->>Service: 추천 칵테일 목록 |
| 59 | + Service->>DB: 대화 이력 저장 |
| 60 | + else 일반 대화 모드 |
| 61 | + Service->>DB: 최근 대화 이력 조회 (5건) |
| 62 | + DB-->>Service: 대화 컨텍스트 |
| 63 | + Service->>AI: 프롬프트 + 컨텍스트 전송 |
| 64 | + AI-->>Service: AI 응답 생성 |
| 65 | + Service->>DB: 응답 저장 |
| 66 | + end |
| 67 | + |
| 68 | + Service-->>Controller: 응답 DTO |
| 69 | + Controller-->>User: 칵테일 추천/정보 제공 |
| 70 | +``` |
| 71 | + |
| 72 | +### 2️⃣ MyBar (킵) 기능 프로세스 |
| 73 | + |
| 74 | +```mermaid |
| 75 | +sequenceDiagram |
| 76 | + participant User as 사용자 |
| 77 | + participant Controller as MyBarController |
| 78 | + participant Service as MyBarService |
| 79 | + participant ABV as AbvScoreService |
| 80 | + participant DB as MyBarRepository |
| 81 | + |
| 82 | + User->>Controller: 칵테일 킵 요청 |
| 83 | + Controller->>Service: keep(userId, cocktailId) |
| 84 | + |
| 85 | + Service->>DB: 기존 킵 확인 |
| 86 | + DB-->>Service: 킵 상태 반환 |
| 87 | + |
| 88 | + alt 신규 킵 |
| 89 | + Service->>DB: MyBar 엔티티 생성 |
| 90 | + Service->>ABV: 활동 점수 +0.1 |
| 91 | + else 킵 복원 (DELETED → ACTIVE) |
| 92 | + Service->>DB: 상태 변경 & keptAt 갱신 |
| 93 | + Service->>ABV: 활동 점수 +0.1 |
| 94 | + else 이미 킵된 상태 |
| 95 | + Service->>DB: keptAt만 갱신 |
| 96 | + end |
| 97 | + |
| 98 | + DB-->>Service: 저장 완료 |
| 99 | + Service-->>Controller: 성공 응답 |
| 100 | + Controller-->>User: 201 Created |
| 101 | +``` |
| 102 | + |
| 103 | +### 3️⃣ 실시간 알림 시스템 (SSE) |
| 104 | + |
| 105 | +```mermaid |
| 106 | +sequenceDiagram |
| 107 | + participant Client as 클라이언트 |
| 108 | + participant Controller as NotificationController |
| 109 | + participant Service as NotificationService |
| 110 | + participant Emitter as SseEmitter |
| 111 | + participant EventBus as ApplicationEventPublisher |
| 112 | + participant PostService as PostService |
| 113 | + |
| 114 | + Client->>Controller: SSE 구독 요청 |
| 115 | + Controller->>Service: subscribe() |
| 116 | + Service->>Service: 사용자별 Emitter 생성 |
| 117 | + Service->>Emitter: 연결 이벤트 전송 |
| 118 | + Service-->>Controller: SseEmitter 반환 |
| 119 | + Controller-->>Client: SSE 스트림 연결 |
| 120 | + |
| 121 | + Note over Client,Emitter: SSE 연결 유지 |
| 122 | + |
| 123 | + PostService->>EventBus: 댓글/좋아요 이벤트 발행 |
| 124 | + EventBus-->>Service: 이벤트 수신 |
| 125 | + Service->>Service: 알림 생성 및 저장 |
| 126 | + Service->>Emitter: 실시간 알림 전송 |
| 127 | + Emitter-->>Client: 알림 수신 |
| 128 | +``` |
| 129 | + |
| 130 | +## 📂 디렉토리 구조 |
| 131 | +```plaintext |
| 132 | +src |
| 133 | +└── main |
| 134 | + ├── java |
| 135 | + │ └── com.back |
| 136 | + │ ├── domain # 도메인별 핵심 비즈니스 로직 |
| 137 | + │ │ ├── user # 사용자 관련 |
| 138 | + │ │ ├── cocktail # 칵테일 레시피 |
| 139 | + │ │ ├── chatbot # AI 챗봇 '쑤리' |
| 140 | + │ │ ├── mybar # MyBar (킵) 기능 |
| 141 | + │ │ ├── post # 게시판 관련 |
| 142 | + │ │ │ ├── category # 카테고리 |
| 143 | + │ │ │ ├── comment # 댓글 |
| 144 | + │ │ │ └── post # 게시글 |
| 145 | + │ │ └── notification # 알림 시스템 |
| 146 | + │ └── global # 전역 모듈 |
| 147 | + │ ├── ai # Spring AI 설정 |
| 148 | + │ ├── exception # 예외 처리 |
| 149 | + │ ├── file # 파일 업로드 (S3) |
| 150 | + │ ├── jwt # JWT 인증 |
| 151 | + │ ├── oauth2 # OAuth2 소셜 로그인 |
| 152 | + │ ├── rq # Request 컨텍스트 |
| 153 | + │ ├── rsData # Response 표준화 |
| 154 | + │ ├── security # Spring Security 설정 |
| 155 | + │ └── util # 유틸리티 |
| 156 | + └── resources |
| 157 | + ├── prompts # AI 프롬프트 |
| 158 | + │ ├── chatbot-system-prompt.txt |
| 159 | + │ └── chatbot-response-rules.txt |
| 160 | + ├── application.yml # 메인 설정 |
| 161 | + ├── application-dev.yml # 개발 환경 |
| 162 | + ├── application-prod.yml # 운영 환경 |
| 163 | + └── cocktails.csv # 칵테일 초기 데이터 |
| 164 | +``` |
| 165 | + |
| 166 | +--- |
| 167 | + |
| 168 | +## 🎯 주요 기능 |
| 169 | + |
| 170 | +### 1. 칵테일 도메인 |
| 171 | +- **칵테일 조회**: 무한스크롤 기반 목록 조회 |
| 172 | +- **상세 정보**: 레시피, 재료, 제조법, 스토리 |
| 173 | +- **검색/필터링**: 도수, 베이스, 타입별 필터링 |
| 174 | +- **공유 기능**: 칵테일 레시피 공유 링크 생성 |
| 175 | + |
| 176 | +### 2. AI 챗봇 '쑤리' |
| 177 | +- **자연어 대화**: 칵테일 관련 질문 응답 |
| 178 | +- **맞춤 추천**: 기분, 상황, 취향별 칵테일 추천 |
| 179 | +- **단계별 추천**: 도수 → 베이스 → 스타일 선택 |
| 180 | +- **대화 컨텍스트**: 최근 5개 대화 기반 응답 |
| 181 | + |
| 182 | +### 3. MyBar (킵) |
| 183 | +- **칵테일 킵**: 좋아하는 칵테일 저장 |
| 184 | +- **무한스크롤**: 커서 기반 페이지네이션 |
| 185 | +- **소프트 삭제**: 킵 해제 후 복원 가능 |
| 186 | +- **활동 점수**: 킵/언킵 시 ABV 점수 변동 |
| 187 | + |
| 188 | +### 4. 커뮤니티 |
| 189 | +- **게시판**: 카테고리별 게시글 CRUD |
| 190 | +- **댓글**: 게시글 댓글 작성/조회 |
| 191 | +- **좋아요**: 게시글 추천 기능 |
| 192 | +- **태그**: 해시태그 기반 분류 |
| 193 | + |
| 194 | +### 5. 알림 시스템 |
| 195 | +- **실시간 알림**: SSE 기반 실시간 푸시 |
| 196 | +- **알림 타입**: 댓글, 좋아요, 팔로우 등 |
| 197 | +- **읽음 처리**: 알림 확인 후 자동 이동 |
| 198 | +- **무한스크롤**: 알림 목록 페이지네이션 |
| 199 | + |
| 200 | +### 6. 인증/인가 |
| 201 | +- **소셜 로그인**: Kakao, Google, Naver OAuth2 |
| 202 | +- **JWT 토큰**: Access/Refresh Token 관리 |
| 203 | +- **Spring Security**: 권한 기반 접근 제어 |
| 204 | +- **쿠키 인증**: Secure, HttpOnly, SameSite |
| 205 | + |
| 206 | +--- |
| 207 | + |
| 208 | +## 🔐 보안 설정 |
| 209 | +- **CORS**: 프론트엔드 도메인만 허용 |
| 210 | +- **JWT**: 15분 Access, 30일 Refresh |
| 211 | +- **쿠키**: Secure(HTTPS), HttpOnly, SameSite |
| 212 | +- **OAuth2**: 소셜 로그인 프로바이더별 설정 |
| 213 | +- **예외 처리**: 전역 예외 핸들러 |
| 214 | + |
| 215 | +--- |
| 216 | + |
| 217 | +## 📈 성능 최적화 |
| 218 | +- **비동기 처리**: CompletableFuture 활용 |
| 219 | +- **캐싱**: Redis 세션 스토어 |
| 220 | +- **커서 페이징**: Offset 대신 커서 기반 |
| 221 | +- **Lazy Loading**: JPA 지연 로딩 |
| 222 | +- **인덱싱**: 검색 필드 DB 인덱스 |
| 223 | + |
| 224 | +--- |
| 225 | + |
| 226 | +## 📊 데이터베이스 스키마 |
| 227 | + |
| 228 | +<img width="1414" height="961" alt="image" src="https://github.com/user-attachments/assets/f5b9b8fb-3d90-46ee-af34-ce3c2db10105" /> |
| 229 | + |
| 230 | +--- |
0 commit comments