From 9c18e5f056dfb84916a54dede63c9c7bc31e6315 Mon Sep 17 00:00:00 2001 From: seungwookc97 Date: Thu, 2 Oct 2025 17:37:19 +0900 Subject: [PATCH] Create README.md --- README.md | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..9df7777 --- /dev/null +++ b/README.md @@ -0,0 +1,230 @@ +# ๐Ÿน Ssoul - ์นตํ…Œ์ผ ๋ ˆ์‹œํ”ผ ๊ณต์œ  ํ”Œ๋žซํผ + +## ๐Ÿ”— ์„œ๋น„์Šค ๋งํฌ +**ํ™ˆํŽ˜์ด์ง€**: [https://ssoul.life](https://ssoul.life) + +## ๐Ÿ“Œ ๊ฐœ์š” +๋ณธ ์‹œ์Šคํ…œ์€ ์‚ฌ์šฉ์ž๊ฐ€ ์นตํ…Œ์ผ ๋ ˆ์‹œํ”ผ๋ฅผ ๊ณต์œ ํ•˜๊ณ , AI ๋ฐ”ํ…๋” '์‘ค๋ฆฌ'๋ฅผ ํ†ตํ•ด ๋งž์ถคํ˜• ์นตํ…Œ์ผ์„ ์ถ”์ฒœ๋ฐ›์œผ๋ฉฐ, ์นตํ…Œ์ผ ๋ฌธํ™”๋ฅผ ์ฆ๊ธธ ์ˆ˜ ์žˆ๋Š” ์›น ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค. +์นตํ…Œ์ผ ์ž…๋ฌธ์ž๋ถ€ํ„ฐ ์• ํ˜ธ๊ฐ€๊นŒ์ง€ ๋ชจ๋“  ์‚ฌ์šฉ์ž๋ฅผ ๋Œ€์ƒ์œผ๋กœ, ๋‹จ์ˆœํ•œ ๋ ˆ์‹œํ”ผ ์ œ๊ณต์„ ๋„˜์–ด AI ์ฑ—๋ด‡์„ ํ†ตํ•œ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒํ•œ ์นตํ…Œ์ผ ์ถ”์ฒœ๊ณผ ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. +๋˜ํ•œ ์‚ฌ์šฉ์ž ํ™œ๋™ ๊ธฐ๋ฐ˜ ๋“ฑ๊ธ‰ ์‹œ์Šคํ…œ(ABV ๋„์ˆ˜)๊ณผ MyBar(ํ‚ต) ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ๊พธ์ค€ํ•œ ์ฐธ์—ฌ๋ฅผ ์œ ๋„ํ•˜๋„๋ก ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค. +Spring Boot, Spring AI, OAuth2, SSE, AWS S3 ๋“ฑ์„ ํ†ตํ•ฉํ•ด ์šด์˜ํ•˜๋ฉฐ, +์นตํ…Œ์ผ ๋ฌธํ™” ํ™•์‚ฐ๊ณผ ์‚ฌ์šฉ์ž ๊ฐ„ ๋ ˆ์‹œํ”ผ ๊ณต์œ ๋ฅผ ํ†ตํ•œ ์ปค๋ฎค๋‹ˆํ‹ฐ ํ™œ์„ฑํ™”๋ฅผ ๋ชฉํ‘œ๋กœ ํ•ฉ๋‹ˆ๋‹ค. + +--- + +## ๐Ÿ‘ฅ ํŒ€์› ๋ฐ ์—ญํ•  + +| ํŒ€์› | ์—ญํ•  | ๋‹ด๋‹น ์—…๋ฌด | +|------|------|-----------| +| ์ •์šฉ์ง„ | Backend(PM) | AI ์ฑ—๋ด‡ '์‘ค๋ฆฌ', ๋‹จ๊ณ„๋ณ„ ์ถ”์ฒœ ์‹œ์Šคํ…œ | +| ์ด๊ด‘์› | Backend(ํŒ€์žฅ) / Frontend | ์นตํ…Œ์ผ ๋„๋ฉ”์ธ, ๊ฒ€์ƒ‰/ํ•„ํ„ฐ๋ง, ์ƒ์„ธ ์กฐํšŒ | +| ์„๊ทผํ˜ธ | Backend / Frontend | ์ปค๋ฎค๋‹ˆํ‹ฐ(๊ฒŒ์‹œํŒ/๋Œ“๊ธ€), S3, ํŒŒ์ผ ์—…๋กœ๋“œ | +| ์ตœ์Šน์šฑ | Backend / Frontend | ์ธ์ฆ/์ธ๊ฐ€, ์†Œ์…œ๋กœ๊ทธ์ธ(OAuth2), JWT, ํ…Œ๋ผํผ | +| ํ™๋ฏผ์•  | Backend | MyBar(ํ‚ต) ๊ธฐ๋Šฅ, ์•Œ๋ฆผ ์‹œ์Šคํ…œ(SSE) | + +--- + +## ๐Ÿ›  ๊ธฐ์ˆ  ์Šคํƒ +- **Backend**: Java 21, Spring Boot 3.5.5 +- **Database**: MySQL 8.x / JPA / H2 (๊ฐœ๋ฐœ) +- **AI ์—ฐ๋™**: Spring AI, Gemini API +- **์ธ์ฆ**: Spring Security, OAuth2 (Kakao, Google, Naver), JWT +- **ํŒŒ์ผ ์ €์žฅ**: AWS S3 +- **์‹ค์‹œ๊ฐ„ ํ†ต์‹ **: SSE (Server-Sent Events) +- **์บ์‹ฑ**: Redis +- **API ๋ฌธ์„œ**: Swagger (SpringDoc OpenAPI) + +--- + +## ๐Ÿ”„ ํ•ต์‹ฌ ๊ธฐ๋Šฅ ํ”„๋กœ์„ธ์Šค + +### 1๏ธโƒฃ AI ์ฑ—๋ด‡ '์‘ค๋ฆฌ' ์นตํ…Œ์ผ ์ถ”์ฒœ ํ”„๋กœ์„ธ์Šค + +```mermaid +sequenceDiagram + participant User as ์‚ฌ์šฉ์ž + participant Controller as ChatbotController + participant Service as ChatbotService + participant AI as Spring AI (Gemini) + participant DB as Database + participant Cocktail as CocktailRepository + + User->>Controller: ๋Œ€ํ™” ์‹œ์ž‘/๋ฉ”์‹œ์ง€ ์ „์†ก + Controller->>Service: ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ ์š”์ฒญ + + alt ๋‹จ๊ณ„๋ณ„ ์ถ”์ฒœ ๋ชจ๋“œ + Service->>Service: ์ถ”์ฒœ ๋‹จ๊ณ„ ํ™•์ธ + Service->>Cocktail: ํ•„ํ„ฐ ์กฐ๊ฑด๋ณ„ ์นตํ…Œ์ผ ์กฐํšŒ + Cocktail-->>Service: ์ถ”์ฒœ ์นตํ…Œ์ผ ๋ชฉ๋ก + Service->>DB: ๋Œ€ํ™” ์ด๋ ฅ ์ €์žฅ + else ์ผ๋ฐ˜ ๋Œ€ํ™” ๋ชจ๋“œ + Service->>DB: ์ตœ๊ทผ ๋Œ€ํ™” ์ด๋ ฅ ์กฐํšŒ (5๊ฑด) + DB-->>Service: ๋Œ€ํ™” ์ปจํ…์ŠคํŠธ + Service->>AI: ํ”„๋กฌํ”„ํŠธ + ์ปจํ…์ŠคํŠธ ์ „์†ก + AI-->>Service: AI ์‘๋‹ต ์ƒ์„ฑ + Service->>DB: ์‘๋‹ต ์ €์žฅ + end + + Service-->>Controller: ์‘๋‹ต DTO + Controller-->>User: ์นตํ…Œ์ผ ์ถ”์ฒœ/์ •๋ณด ์ œ๊ณต +``` + +### 2๏ธโƒฃ MyBar (ํ‚ต) ๊ธฐ๋Šฅ ํ”„๋กœ์„ธ์Šค + +```mermaid +sequenceDiagram + participant User as ์‚ฌ์šฉ์ž + participant Controller as MyBarController + participant Service as MyBarService + participant ABV as AbvScoreService + participant DB as MyBarRepository + + User->>Controller: ์นตํ…Œ์ผ ํ‚ต ์š”์ฒญ + Controller->>Service: keep(userId, cocktailId) + + Service->>DB: ๊ธฐ์กด ํ‚ต ํ™•์ธ + DB-->>Service: ํ‚ต ์ƒํƒœ ๋ฐ˜ํ™˜ + + alt ์‹ ๊ทœ ํ‚ต + Service->>DB: MyBar ์—”ํ‹ฐํ‹ฐ ์ƒ์„ฑ + Service->>ABV: ํ™œ๋™ ์ ์ˆ˜ +0.1 + else ํ‚ต ๋ณต์› (DELETED โ†’ ACTIVE) + Service->>DB: ์ƒํƒœ ๋ณ€๊ฒฝ & keptAt ๊ฐฑ์‹  + Service->>ABV: ํ™œ๋™ ์ ์ˆ˜ +0.1 + else ์ด๋ฏธ ํ‚ต๋œ ์ƒํƒœ + Service->>DB: keptAt๋งŒ ๊ฐฑ์‹  + end + + DB-->>Service: ์ €์žฅ ์™„๋ฃŒ + Service-->>Controller: ์„ฑ๊ณต ์‘๋‹ต + Controller-->>User: 201 Created +``` + +### 3๏ธโƒฃ ์‹ค์‹œ๊ฐ„ ์•Œ๋ฆผ ์‹œ์Šคํ…œ (SSE) + +```mermaid +sequenceDiagram + participant Client as ํด๋ผ์ด์–ธํŠธ + participant Controller as NotificationController + participant Service as NotificationService + participant Emitter as SseEmitter + participant EventBus as ApplicationEventPublisher + participant PostService as PostService + + Client->>Controller: SSE ๊ตฌ๋… ์š”์ฒญ + Controller->>Service: subscribe() + Service->>Service: ์‚ฌ์šฉ์ž๋ณ„ Emitter ์ƒ์„ฑ + Service->>Emitter: ์—ฐ๊ฒฐ ์ด๋ฒคํŠธ ์ „์†ก + Service-->>Controller: SseEmitter ๋ฐ˜ํ™˜ + Controller-->>Client: SSE ์ŠคํŠธ๋ฆผ ์—ฐ๊ฒฐ + + Note over Client,Emitter: SSE ์—ฐ๊ฒฐ ์œ ์ง€ + + PostService->>EventBus: ๋Œ“๊ธ€/์ข‹์•„์š” ์ด๋ฒคํŠธ ๋ฐœํ–‰ + EventBus-->>Service: ์ด๋ฒคํŠธ ์ˆ˜์‹  + Service->>Service: ์•Œ๋ฆผ ์ƒ์„ฑ ๋ฐ ์ €์žฅ + Service->>Emitter: ์‹ค์‹œ๊ฐ„ ์•Œ๋ฆผ ์ „์†ก + Emitter-->>Client: ์•Œ๋ฆผ ์ˆ˜์‹  +``` + +## ๐Ÿ“‚ ๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ +```plaintext +src +โ””โ”€โ”€ main + โ”œโ”€โ”€ java + โ”‚ โ””โ”€โ”€ com.back + โ”‚ โ”œโ”€โ”€ domain # ๋„๋ฉ”์ธ๋ณ„ ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง + โ”‚ โ”‚ โ”œโ”€โ”€ user # ์‚ฌ์šฉ์ž ๊ด€๋ จ + โ”‚ โ”‚ โ”œโ”€โ”€ cocktail # ์นตํ…Œ์ผ ๋ ˆ์‹œํ”ผ + โ”‚ โ”‚ โ”œโ”€โ”€ chatbot # AI ์ฑ—๋ด‡ '์‘ค๋ฆฌ' + โ”‚ โ”‚ โ”œโ”€โ”€ mybar # MyBar (ํ‚ต) ๊ธฐ๋Šฅ + โ”‚ โ”‚ โ”œโ”€โ”€ post # ๊ฒŒ์‹œํŒ ๊ด€๋ จ + โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ category # ์นดํ…Œ๊ณ ๋ฆฌ + โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ comment # ๋Œ“๊ธ€ + โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ post # ๊ฒŒ์‹œ๊ธ€ + โ”‚ โ”‚ โ””โ”€โ”€ notification # ์•Œ๋ฆผ ์‹œ์Šคํ…œ + โ”‚ โ””โ”€โ”€ global # ์ „์—ญ ๋ชจ๋“ˆ + โ”‚ โ”œโ”€โ”€ ai # Spring AI ์„ค์ • + โ”‚ โ”œโ”€โ”€ exception # ์˜ˆ์™ธ ์ฒ˜๋ฆฌ + โ”‚ โ”œโ”€โ”€ file # ํŒŒ์ผ ์—…๋กœ๋“œ (S3) + โ”‚ โ”œโ”€โ”€ jwt # JWT ์ธ์ฆ + โ”‚ โ”œโ”€โ”€ oauth2 # OAuth2 ์†Œ์…œ ๋กœ๊ทธ์ธ + โ”‚ โ”œโ”€โ”€ rq # Request ์ปจํ…์ŠคํŠธ + โ”‚ โ”œโ”€โ”€ rsData # Response ํ‘œ์ค€ํ™” + โ”‚ โ”œโ”€โ”€ security # Spring Security ์„ค์ • + โ”‚ โ””โ”€โ”€ util # ์œ ํ‹ธ๋ฆฌํ‹ฐ + โ””โ”€โ”€ resources + โ”œโ”€โ”€ prompts # AI ํ”„๋กฌํ”„ํŠธ + โ”‚ โ”œโ”€โ”€ chatbot-system-prompt.txt + โ”‚ โ””โ”€โ”€ chatbot-response-rules.txt + โ”œโ”€โ”€ application.yml # ๋ฉ”์ธ ์„ค์ • + โ”œโ”€โ”€ application-dev.yml # ๊ฐœ๋ฐœ ํ™˜๊ฒฝ + โ”œโ”€โ”€ application-prod.yml # ์šด์˜ ํ™˜๊ฒฝ + โ””โ”€โ”€ cocktails.csv # ์นตํ…Œ์ผ ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ +``` + +--- + +## ๐ŸŽฏ ์ฃผ์š” ๊ธฐ๋Šฅ + +### 1. ์นตํ…Œ์ผ ๋„๋ฉ”์ธ +- **์นตํ…Œ์ผ ์กฐํšŒ**: ๋ฌดํ•œ์Šคํฌ๋กค ๊ธฐ๋ฐ˜ ๋ชฉ๋ก ์กฐํšŒ +- **์ƒ์„ธ ์ •๋ณด**: ๋ ˆ์‹œํ”ผ, ์žฌ๋ฃŒ, ์ œ์กฐ๋ฒ•, ์Šคํ† ๋ฆฌ +- **๊ฒ€์ƒ‰/ํ•„ํ„ฐ๋ง**: ๋„์ˆ˜, ๋ฒ ์ด์Šค, ํƒ€์ž…๋ณ„ ํ•„ํ„ฐ๋ง +- **๊ณต์œ  ๊ธฐ๋Šฅ**: ์นตํ…Œ์ผ ๋ ˆ์‹œํ”ผ ๊ณต์œ  ๋งํฌ ์ƒ์„ฑ + +### 2. AI ์ฑ—๋ด‡ '์‘ค๋ฆฌ' +- **์ž์—ฐ์–ด ๋Œ€ํ™”**: ์นตํ…Œ์ผ ๊ด€๋ จ ์งˆ๋ฌธ ์‘๋‹ต +- **๋งž์ถค ์ถ”์ฒœ**: ๊ธฐ๋ถ„, ์ƒํ™ฉ, ์ทจํ–ฅ๋ณ„ ์นตํ…Œ์ผ ์ถ”์ฒœ +- **๋‹จ๊ณ„๋ณ„ ์ถ”์ฒœ**: ๋„์ˆ˜ โ†’ ๋ฒ ์ด์Šค โ†’ ์Šคํƒ€์ผ ์„ ํƒ +- **๋Œ€ํ™” ์ปจํ…์ŠคํŠธ**: ์ตœ๊ทผ 5๊ฐœ ๋Œ€ํ™” ๊ธฐ๋ฐ˜ ์‘๋‹ต + +### 3. MyBar (ํ‚ต) +- **์นตํ…Œ์ผ ํ‚ต**: ์ข‹์•„ํ•˜๋Š” ์นตํ…Œ์ผ ์ €์žฅ +- **๋ฌดํ•œ์Šคํฌ๋กค**: ์ปค์„œ ๊ธฐ๋ฐ˜ ํŽ˜์ด์ง€๋„ค์ด์…˜ +- **์†Œํ”„ํŠธ ์‚ญ์ œ**: ํ‚ต ํ•ด์ œ ํ›„ ๋ณต์› ๊ฐ€๋Šฅ +- **ํ™œ๋™ ์ ์ˆ˜**: ํ‚ต/์–ธํ‚ต ์‹œ ABV ์ ์ˆ˜ ๋ณ€๋™ + +### 4. ์ปค๋ฎค๋‹ˆํ‹ฐ +- **๊ฒŒ์‹œํŒ**: ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ๊ฒŒ์‹œ๊ธ€ CRUD +- **๋Œ“๊ธ€**: ๊ฒŒ์‹œ๊ธ€ ๋Œ“๊ธ€ ์ž‘์„ฑ/์กฐํšŒ +- **์ข‹์•„์š”**: ๊ฒŒ์‹œ๊ธ€ ์ถ”์ฒœ ๊ธฐ๋Šฅ +- **ํƒœ๊ทธ**: ํ•ด์‹œํƒœ๊ทธ ๊ธฐ๋ฐ˜ ๋ถ„๋ฅ˜ + +### 5. ์•Œ๋ฆผ ์‹œ์Šคํ…œ +- **์‹ค์‹œ๊ฐ„ ์•Œ๋ฆผ**: SSE ๊ธฐ๋ฐ˜ ์‹ค์‹œ๊ฐ„ ํ‘ธ์‹œ +- **์•Œ๋ฆผ ํƒ€์ž…**: ๋Œ“๊ธ€, ์ข‹์•„์š”, ํŒ”๋กœ์šฐ ๋“ฑ +- **์ฝ์Œ ์ฒ˜๋ฆฌ**: ์•Œ๋ฆผ ํ™•์ธ ํ›„ ์ž๋™ ์ด๋™ +- **๋ฌดํ•œ์Šคํฌ๋กค**: ์•Œ๋ฆผ ๋ชฉ๋ก ํŽ˜์ด์ง€๋„ค์ด์…˜ + +### 6. ์ธ์ฆ/์ธ๊ฐ€ +- **์†Œ์…œ ๋กœ๊ทธ์ธ**: Kakao, Google, Naver OAuth2 +- **JWT ํ† ํฐ**: Access/Refresh Token ๊ด€๋ฆฌ +- **Spring Security**: ๊ถŒํ•œ ๊ธฐ๋ฐ˜ ์ ‘๊ทผ ์ œ์–ด +- **์ฟ ํ‚ค ์ธ์ฆ**: Secure, HttpOnly, SameSite + +--- + +## ๐Ÿ” ๋ณด์•ˆ ์„ค์ • +- **CORS**: ํ”„๋ก ํŠธ์—”๋“œ ๋„๋ฉ”์ธ๋งŒ ํ—ˆ์šฉ +- **JWT**: 15๋ถ„ Access, 30์ผ Refresh +- **์ฟ ํ‚ค**: Secure(HTTPS), HttpOnly, SameSite +- **OAuth2**: ์†Œ์…œ ๋กœ๊ทธ์ธ ํ”„๋กœ๋ฐ”์ด๋”๋ณ„ ์„ค์ • +- **์˜ˆ์™ธ ์ฒ˜๋ฆฌ**: ์ „์—ญ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ + +--- + +## ๐Ÿ“ˆ ์„ฑ๋Šฅ ์ตœ์ ํ™” +- **๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ**: CompletableFuture ํ™œ์šฉ +- **์บ์‹ฑ**: Redis ์„ธ์…˜ ์Šคํ† ์–ด +- **์ปค์„œ ํŽ˜์ด์ง•**: Offset ๋Œ€์‹  ์ปค์„œ ๊ธฐ๋ฐ˜ +- **Lazy Loading**: JPA ์ง€์—ฐ ๋กœ๋”ฉ +- **์ธ๋ฑ์‹ฑ**: ๊ฒ€์ƒ‰ ํ•„๋“œ DB ์ธ๋ฑ์Šค + +--- + +## ๐Ÿ“Š ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ + +image + +---