1541268์ค๋ค์ธ (ํ์ฅ)1544345๊น๋์ฃผ
YumYumCoach ํ๋ก์ ํธ์, Spring AI + Google Gemini ๊ธฐ๋ฐ AI ์์ ์ฝ์น ๊ธฐ๋ฅ์ ์ถ๊ฐํ ๋ฒ์ ์ ๋๋ค.
- Spring AI๋ฅผ ์ ์ฉํ์ฌ ๋จ์ผ Tool ํธ์ถ, ๋ค์ค Tool ํธ์ถ, Tool ๊ฒฐ๊ณผ ๊ธฐ๋ฐ AI ์๋ต ์์ฑ ํ์ ์๊ตฌ์ฌํญ์ ๋ชจ๋ ๊ตฌํํ์์ต๋๋ค.
- Docker Compose๋ฅผ ๊ตฌ์ฑํด๋์์ผ๋, compose๋ฅผ ์คํํ๋ฉด ์๋น์ค๊ฐ ๋ฐ๋ก ์คํ๋ฉ๋๋ค.
- MySQL ์ํฌ๋ฒค์น ์์ด mysql ์ด๋ฏธ์ง๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค ์๋ฒ๋ฅผ ๊ตฌ์ฑํ์ค๋, ํฌํธ ์ถฉ๋์ ์ฃผ์ํด์ผํฉ๋๋ค.
- Dockerfile์ ์ด์ฉํ Spring Boot ์ดํ๋ฆฌ์ผ์ด์ ์ด๋ฏธ์ง ๊ตฌ์ฑ ์ , Multi-stage build๋ก Vue.js ํ๋ก์ ํธ๋ฅผ ๋น๋ํ์ฌ Spring Boot App์ static ํด๋์ ๋ฐฐ์นํ์ฌ ๋ฐํ์์ SPA๋ฅผ ์๋นํ๋ ํํ์ ๋๋ค.
GMS_API_KEYํ๊ฒฝ๋ณ์๋ฅผ ์ค์ ํ ๋ค ์คํํด์ผ AI ๊ธฐ๋ฅ์ด ์ ์ ๋์ํฉ๋๋ค. (.envํ์ผ์ ํตํ ๊ตฌ์ฑ ๊ถ์ฅ)
docker compose upYumYumCoach๋ ์ฌ์ฉ์์ ์๋จ ๊ธฐ๋ก๊ณผ ์์ ์์ ์ ๋ณด๋ฅผ ๊ด๋ฆฌํ๋ Spring Boot ๊ธฐ๋ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋๋ค.
์ด๋ฒ ๋ณ๊ฒฝ์ ํต์ฌ์ Spring AI 1.1.6๊ณผ **Google Gemini(GMS ํ๋ก์)**๋ฅผ ์ฐ๋ํ์ฌ AI ์์ ์ฝ์น ๊ธฐ๋ฅ์ ์ถ๊ฐํ ๊ฒ์
๋๋ค. ๊ธฐ์กด FoodCatalogRepository, UserRepository, MealService๋ฅผ Spring AI Tool๋ก ๊ฐ์ธ LLM์ด ์ค์ DB ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๋ต์ ์์ฑํฉ๋๋ค. Vue ์ฝ์น ํ์ด์ง์ AI ์ฑํ
์ธํฐํ์ด์ค๋ฅผ ์ถ๊ฐํ์ฌ ์ฌ์ฉ์๊ฐ ์์ฐ์ด๋ก ์๋จ ๋ถ์์ ์์ฒญํ ์ ์์ต๋๋ค.
์ผ๋ฐ ์ฌ์ฉ์ ํ๋ฉด์ client ๋๋ ํฐ๋ฆฌ์ Vue 3 + Vite SPA๊ฐ ๋ด๋นํฉ๋๋ค. Spring Boot๋ pnpm build๋ก ์์ฑ๋ src/main/resources/static/index.html์ /, /home, /auth/*, /meals*, /profile, /coach, /community, /challenges, /social ๊ฒฝ๋ก์ forwardํฉ๋๋ค. ๊ธฐ์กด JSP ํ๋ฉด ์ปจํธ๋กค๋ฌ์ JSP ํ์ผ์ ๋ ๊ฑฐ์ ํ์ธ์ฉ์ผ๋ก /legacy/** ๊ฒฝ๋ก์ ๋จ์ ์์ต๋๋ค.
Spring Batch ๊ธฐ๋ฐ ์์์ฑ๋ถ ๋ฐ์ดํฐ ์ ์ฌ ๊ธฐ๋ฅ์ ์ ์ง๋ฉ๋๋ค. ์ธ๋ถ ์์์ฑ๋ถ ์์ฒ ๋ฐ์ดํฐ ํ์ผ์ ์ฝ์ด staging ํ
์ด๋ธ์ ์ ์ฅํ ๋ค ์ ์ ์ ๊ฒ์ฆ์ ๊ฑฐ์ณ food_nutrition ํ
์ด๋ธ์ upsertํฉ๋๋ค.
Note
์ธ๋ถ ์์์ฑ๋ถ ๋ฐ์ดํฐ ์ถ์ฒ: ์ํ์์ฝํ์์ ์ฒ ์ํ์์์ฑ๋ถ๋ฐ์ดํฐ๋ฒ ์ด์ค
-
Spring AI ์ฐ๋ (์ด๋ฒ ๊ดํต ํ๋ก์ ํธ)
spring-ai-bom 1.1.6๊ณผspring-ai-starter-model-google-genai๋ฅผ ์์กด์ฑ์ ์ถ๊ฐํ์ต๋๋ค.- SSAFY GMS ํ๋ก์๋ฅผ ํตํด
gemini-2.5-flash-lite๋ชจ๋ธ์ ์ฌ์ฉํฉ๋๋ค. - Spring AI 1.1.6์์
base-urlํ๋กํผํฐ๊ฐ ์๋ ๊ตฌ์ฑ์ ์ ์ฉ๋์ง ์๋ ๋ฌธ์ ๋ฅผAiConfig์์Client๋ฅผ ์ง์ ์์ฑํด ํด๊ฒฐํ์ต๋๋ค. ChatClient์ ํ๊ตญ์ด ์์ฐ์ด ์๋ต์ ์ ๋ํ๋ System Prompt๋ฅผ ์ค์ ํ์ต๋๋ค.
-
Spring AI Tool ๊ตฌํ
FoodSearchTool: ๊ธฐ์กดFoodCatalogRepository.search()๋ฅผ ์ฌ์ฌ์ฉํด ์์ ์ด๋ฆ ํค์๋๋ก ์์์ฑ๋ถ์ ๊ฒ์ํฉ๋๋ค. ๋จ์ผ Tool ํธ์ถ ์๊ตฌ์ฌํญ์ ์ถฉ์กฑํฉ๋๋ค.UserProfileTool: ๊ธฐ์กดUserRepository.findById()๋ฅผ ์ฌ์ฌ์ฉํด ์ฌ์ฉ์ ํ๋กํ(๋๋ค์, ๋ชฉํ, ์ ์ฅ, ์ฒด์ค ๋ฑ)์ ์กฐํํฉ๋๋ค.TodayMealTool: ๊ธฐ์กดMealService๋ฅผ ์ฌ์ฌ์ฉํด ์ค๋ ์๋จ ๋ชฉ๋ก๊ณผ ์ด ์์ ์ญ์ทจ๋์ ์กฐํํฉ๋๋ค.DailyGoalTool: ๊ธฐ์กดMealService.calculateDailyGoal()์ ์ฌ์ฌ์ฉํด BMR ๊ธฐ๋ฐ ํ๋ฃจ ๊ถ์ฅ ์์ ๋ชฉํ๋ฅผ ๊ณ์ฐํฉ๋๋ค.UserProfileToolโTodayMealToolโDailyGoalTool3๊ฐ Tool ์ฐ์ ํธ์ถ๋ก ๋ค์ค Tool ํธ์ถ ์๊ตฌ์ฌํญ์ ์ถฉ์กฑํฉ๋๋ค.- ๊ฐ Tool์ ํธ์ถ ๋ฐ ๊ฒฐ๊ณผ ๋ก๊ทธ๋ฅผ ์ถ๊ฐํด ์คํ ํ๋ฆ์ ์๋ฒ ๋ก๊ทธ์์ ํ์ธํ ์ ์์ต๋๋ค.
-
AI API ์๋ํฌ์ธํธ ์ถ๊ฐ
GET /api/v1/ai/food:FoodSearchTool๋จ์ผ ํธ์ถ๋ก ์์ ์์์ฑ๋ถ์ ๊ฒ์ํ๊ณ AI ์๋ต์ ๋ฐํํฉ๋๋ค.GET /api/v1/ai/coach: 4๊ฐ Tool์ ๋ชจ๋ ๋ฑ๋กํด ์ฌ์ฉ์ ์๋จ ์ข ํฉ ๋ถ์ ์๋ต์ ๋ฐํํฉ๋๋ค.- ๋ ์๋ํฌ์ธํธ ๋ชจ๋ Swagger UI์์ ๋ฐ๋ก ํ ์คํธํ ์ ์์ต๋๋ค.
-
Vue AI ์ฑํ ์ธํฐํ์ด์ค ์ถ๊ฐ
- ์ฝ์น ํ์ด์ง(
/coach)์ AI ์ง๋ฌธ ์ ๋ ฅ์ฐฝ๊ณผ ์๋ต ํ์ ์์ญ์ ์ถ๊ฐํ์ต๋๋ค. - ์ง๋ฌธ ์ ์ก ์ค ๋ก๋ฉ ์คํผ๋์ ๋ฒํผ ๋นํ์ฑํ ์ฒ๋ฆฌ๋ก UX๋ฅผ ๊ฐ์ ํ์ต๋๋ค.
- ๊ธฐ์กด ์ฝ์น ๋์๋ณด๋ ๋ ์ด์์์ ๊ทธ๋๋ก ์ ์งํ๊ณ ํ๋จ์ AI ์ฑํ ์น์ ๋ง ์ถ๊ฐํ์ต๋๋ค.
- ์ฝ์น ํ์ด์ง(
-
Vue SPA ์ ํ (์ด์ ๊ดํต ํ๋ก์ ํธ)
client๋๋ ํฐ๋ฆฌ์ Vue 3 + Vite + TypeScript ํ๋ก์ ํธ๋ฅผ ์ถ๊ฐํ์ต๋๋ค.client/src/views์ Vue ํ๋ฉด์ด ๊ธฐ์กด JSP ์ฌ์ฉ์ ํ๋ฉด์ ๋์ฒดํฉ๋๋ค.- ๊ณตํต ๋ ์ด์์, Router, Pinia ์ธ์ store, alert ์ํ๋ฅผ Vue ๊ธฐ์ค์ผ๋ก ๊ตฌ์ฑํ์ต๋๋ค.
client/src/composables์ Axios API composable์ด/api/v1/**REST API๋ฅผ ํธ์ถํฉ๋๋ค.- ์ธ์ ๊ธฐ๋ฐ ์ธ์ฆ์ ์ ์งํ๋ฉฐ, JWT/token refresh/interceptor ๊ธฐ๋ฐ ์ธ์ฆ์ ์ฌ์ฉํ์ง ์์ต๋๋ค.
-
REST API ๋ณด๊ฐ
- ํ/์ฝ์น ๋์๋ณด๋ API๋ฅผ Vue ํ๋ฉด์์ ์ฌ์ฉํ ์ ์๋ JSON API๋ก ์ถ๊ฐํ์ต๋๋ค.
- ์ปค๋ฎค๋ํฐ ๊ฒ์๊ธ/๋๊ธ CRUD API๋ฅผ ์ถ๊ฐํ์ต๋๋ค.
- ์ฑ๋ฆฐ์ง ์์ฑ/์ฐธ์ฌ/์งํ๋ฅ ์์ /ํํด/์ญ์ API๋ฅผ ์ถ๊ฐํ์ต๋๋ค.
- ์์ ํ๋ก์ฐ/์ธํ๋ก์ฐ, ์ถ์ฒ ์ฌ์ฉ์, ํ๋ก์/ํ๋ก์, ๋ฆฌ๋๋ณด๋ API๋ฅผ ์ถ๊ฐํ์ต๋๋ค.
-
๊ฐ๋ฐ/์คํ ํ๊ฒฝ ์ ๋ฆฌ
- Vite ๊ฐ๋ฐ ์๋ฒ๊ฐ
/api,/batch,/swagger-ui,/v3/api-docs์์ฒญ์ Spring Boot๋ก proxyํฉ๋๋ค. client/Dockerfile๋ก Vue ๊ฐ๋ฐ ์๋ฒ ์คํ ํ๊ฒฝ์ ๋ถ๋ฆฌํ์ต๋๋ค.database/Dockerfile๋ก MySQL ์ด๊ธฐ ์คํค๋ง์ demo data ์ ์ฌ ํ๊ฒฝ์ ๊ตฌ์ฑํ์ต๋๋ค.
- Vite ๊ฐ๋ฐ ์๋ฒ๊ฐ
email: demo@yumyum.com
password: Demo1234!
- AI ๊ธฐ๋ฅ ์์ด ์ฌ์ฉ์๊ฐ ์ง์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฅํ๊ณ ์์น๋ฅผ ํ์ธํ๋ ๋ฐฉ์์ด์์ต๋๋ค.
- ์ฝ์น ํ์ด์ง๋ ์ ์ ์ธ ๋์๋ณด๋๋ก, ์์ ์กฐ์ธ์ ์ ๊ณต๋์ง ์์์ต๋๋ค.
- ์๋จยท์์์ฑ๋ถ ๋ฐ์ดํฐ๋ DB์ ์์์ง๋ง LLM์ด ์ด๋ฅผ ํด์ํ๊ฑฐ๋ ํ์ฉํ๋ ๊ธฐ๋ฅ์ด ์์์ต๋๋ค.
- ์ผ๋ฐ ์ฌ์ฉ์ ํ๋ฉด์ด JSP์ Spring MVC view controller์ ๋ฌถ์ฌ ์์์ต๋๋ค.
- SPA route ์ง์ ์ ๊ทผ๊ณผ ์๋ก๊ณ ์นจ์ ์ฒ๋ฆฌํ๋ Spring fallback ๊ตฌ์ฑ์ด ์์์ต๋๋ค.
FoodSearchTool,UserProfileTool,TodayMealTool,DailyGoalTool์ด ๊ธฐ์กด DB ๋ฐ์ดํฐ๋ฅผ LLM์ ์ ๊ณตํฉ๋๋ค.- Gemini๊ฐ Tool ์คํ ๊ฒฐ๊ณผ๋ง์ ๊ทผ๊ฑฐ๋ก ๊ฐ์ธํ๋ ํ๊ตญ์ด ์์ ์กฐ์ธ์ ์์ฑํฉ๋๋ค.
- ์ฝ์น ํ์ด์ง์์ ์์ฐ์ด ์ง๋ฌธ์ผ๋ก ์๋จ ๋ถ์๊ณผ ์์ ์์ ๊ฒ์์ ๋ชจ๋ ์ด์ฉํ ์ ์์ต๋๋ค.
- ๋จ์ผ Tool ํธ์ถ(
/api/v1/ai/food)๊ณผ ๋ค์ค Tool ํธ์ถ(/api/v1/ai/coach) ๋ ๊ฐ์ง ํ๋ฆ์ ์ ๊ณตํฉ๋๋ค. - ์ผ๋ฐ ์ฌ์ฉ์ ํ๋ฉด์ Vue 3 + Vite SPA๊ฐ ๋ด๋นํ๊ณ , Spring Boot๋ ์ ์ ์ฐ์ถ๋ฌผ๊ณผ REST API๋ฅผ ํจ๊ป ์ ๊ณตํฉ๋๋ค.
- ๊ธฐ์กด JSP ํ๋ฉด์
/legacy/**๊ฒฝ๋ก์์ ํ์ธ์ฉ์ผ๋ก๋ง ์ ์งํฉ๋๋ค.
| ์๊ตฌ์ฌํญ | ๋ฌ์ฑ | ๊ตฌํ ๋ด์ฉ |
|---|---|---|
| ๋จ์ผ Tool ํธ์ถ | โ | FoodSearchTool โ GET /api/v1/ai/food |
| ๋ค์ค Tool ํธ์ถ | โ | UserProfileTool + TodayMealTool + DailyGoalTool โ GET /api/v1/ai/coach |
| Tool ๊ฒฐ๊ณผ ๊ธฐ๋ฐ AI ์๋ต ์์ฑ | โ | Gemini๊ฐ Tool ๋ฐํ ๋ฐ์ดํฐ๋ง์ ๊ทผ๊ฑฐ๋ก ํ๊ตญ์ด ์์ฐ์ด ์๋ต ์์ฑ |
์ฌ์ฉ์ ์ง๋ฌธ โ FoodSearchTool์ด food_nutrition ํ
์ด๋ธ์ ๊ฒ์ โ Gemini๊ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ์ผ๋ก ์์ฐ์ด ์๋ต ์์ฑ
์ฌ์ฉ์ ์ง๋ฌธ โ Gemini๊ฐ ์์๋ฅผ ํ๋จ โ UserProfileTool๋ก ํ๋กํ ์กฐํ โ TodayMealTool๋ก ์ค๋ ์๋จ ์กฐํ โ DailyGoalTool๋ก ๋ชฉํ ์นผ๋ก๋ฆฌ ๊ณ์ฐ โ Gemini๊ฐ 3๊ฐ Tool ๊ฒฐ๊ณผ๋ฅผ ์ข
ํฉํด ์ต์ข
๋ถ์ ์๋ต ์์ฑ
Swagger UI์์ ๋ก๊ทธ์ธ ์์ด ๋ฐ๋ก ํ ์คํธํ ์ ์์ต๋๋ค.
- Swagger UI:
http://localhost:8080/swagger-ui/index.html AI APIํ๊ทธ์์GET /api/v1/ai/food์GET /api/v1/ai/coach๋ฅผ ํ์ธํฉ๋๋ค./coachํ ์คํธ ์userId์ DB์ ์กด์ฌํ๋ ์ฌ์ฉ์ ID(์:user_demo)๋ฅผ ์ ๋ ฅํฉ๋๋ค.
Swagger UI:
- OpenAPI Spec: openapi.json
- Swagger UI:
http://localhost:8080/swagger-ui/index.html
์คํ ๊ฒฐ๊ณผ:
- ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ MySQL์ด ์คํ ์ค์ด์ด์ผ ํฉ๋๋ค.
sourcePath๋ ์๋ฒ๊ฐ ์ ๊ทผํ ์ ์๋ ๋ก์ปฌ CSV/XLSX ํ์ผ ๊ฒฝ๋ก์ฌ์ผ ํฉ๋๋ค.- ๋ฐฐ์น API๋ ๋ก๊ทธ์ธ๋ ์ธ์ ์์ ์คํํ๋ ๊ฒ์ ๊ธฐ์ค์ผ๋ก ํฉ๋๋ค.
- Swagger์์ ํ
์คํธํ ๋๋ ๋จผ์
Auth API > POST /api/v1/auth/login์ ์คํํ๋ฉด ํธํฉ๋๋ค.
{
"email": "demo@yumyum.com",
"password": "Demo1234!"
}-
๋ก๊ทธ์ธ ํ ๊ฐ์ Swagger UI ํ๋ฉด์์ ๋ฐฐ์น API๋ฅผ ์คํํ๋ฉด ์ธ์ ์ฟ ํค๊ฐ ํจ๊ป ์ ๋ฌ๋ฉ๋๋ค.
-
spring.batch.job.enabled=false์ค์ ๋๋ฌธ์ ์๋ฒ ์์๋ง์ผ๋ก ๋ฐฐ์น๊ฐ ์๋ ์คํ๋์ง๋ ์์ต๋๋ค. -
Swagger UI ์บก์ฒ:
์์์ฑ๋ถ ๋ฐฐ์น ์คํ:
GET /batch/nutrition-import?sourcePath=data/์์์ฑ๋ถ DB/๋๋ฆผ์์ฐ์ํ๊ต์ก๋ฌธํ์ ๋ณด์_์นผ๋ก๋ฆฌ ์ ๋ณด_20190926.csv&chunkSize=100&runId=manual-001์ฃผ์ ํ๋ผ๋ฏธํฐ:
| ํ๋ผ๋ฏธํฐ | ์ค๋ช |
|---|---|
sourcePath |
์๋ฒ ๋ก์ปฌ ๊ธฐ์ค ์๋ณธ CSV/XLSX ํ์ผ ๊ฒฝ๋ก |
sourceName |
๋ฆฌํฌํธ์ ํ์ํ ์๋ณธ ์ด๋ฆ. ์๋ต ์ ํ์ผ๋ช ์ฌ์ฉ |
chunkSize |
chunk ์ฒ๋ฆฌ ๋จ์. ๊ธฐ๋ณธ๊ฐ 100, ์ต๋ 500 |
runId |
Spring Batch JobInstance ์๋ณ์ฉ ์คํ ID |
์คํจํ ๋ฐฐ์น ์ฌ์์:
GET /batch/nutrition-import/restart?executionId=123- ๋ฐฐ์น๊ฐ ์๋ฃ๋๋ฉด ์๋ต์
pdfReportPath์์น์ PDF ๋ฆฌํฌํธ๊ฐ ์์ฑ๋ฉ๋๋ค. - ๊ธฐ๋ณธ ์ ์ฅ ๊ฒฝ๋ก๋
reports/batch/nutrition/nutrition-import-{jobExecutionId}.pdf์ ๋๋ค. - PDF์๋ ์คํ ID, ์๋ณธ ํ์ผ ์ ๋ณด, ์ด ์ฒ๋ฆฌ ๊ฑด์, ์ฑ๊ณต/์คํจ/๋๊ธฐ ๊ฑด์, ์คํจ row ์ํ์ด ํฌํจ๋ฉ๋๋ค.
- DB์์๋
nutrition_import_reportํ ์ด๋ธ๋ก ์คํ๋ณ ์์ฝ์ ํ์ธํ ์ ์์ต๋๋ค. - ์คํจ row ์์ธ๋
nutrition_import_staging์์import_status = 'FAILED'์กฐ๊ฑด์ผ๋ก ํ์ธํ ์ ์์ต๋๋ค.
| ํ ์ด๋ธ | ์ค๋ช |
|---|---|
food_nutrition |
์ต์ข
์์์ฑ๋ถ ๋ฐ์ดํฐ โ FoodSearchTool์ด ์กฐํ |
users |
์ฌ์ฉ์ ์ ๋ณด โ UserProfileTool, DailyGoalTool์ด ์กฐํ |
diet_logs |
์ฌ์ฉ์ ์๋จ ๊ธฐ๋ก โ TodayMealTool์ด ์กฐํ |
diet_log_items |
์๋จ๋ณ ์ญ์ทจ ์์ ๋ชฉ๋ก โ TodayMealTool์ด ์กฐํ |
nutrition_import_staging |
์๋ณธ row์ ์ฒ๋ฆฌ ์ํ ์ ์ฅ |
nutrition_import_report |
๋ฐฐ์น ์คํ๋ณ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ ์์ฝ |
src/main/java/com/ssafy/yumyum
โโ config
โ โโ AiConfig.java # ChatModel, ChatClient Bean ์ค์ (GMS ํ๋ก์ ์ ์ฉ)
โโ tool
โ โโ FoodSearchTool.java # [F1203] ๋จ์ผ Tool โ ์์ ์์ ๊ฒ์
โ โโ UserProfileTool.java # [F1204] ๋ค์ค Tool โ ์ฌ์ฉ์ ํ๋กํ ์กฐํ
โ โโ TodayMealTool.java # [F1204] ๋ค์ค Tool โ ์ค๋ ์๋จ ์กฐํ
โ โโ DailyGoalTool.java # [F1204] ๋ค์ค Tool โ ์ผ์ผ ์์ ๋ชฉํ ๊ณ์ฐ
โโ batch/nutrition
โ โโ CsvNutritionItemReader.java
โ โโ XlsxNutritionItemReader.java
โ โโ NutritionImportJobConfig.java
โ โโ NutritionImportRepository.java
โ โโ NutritionNormalizeProcessor.java
โ โโ NutritionImportReportTasklet.java
โ โโ NutritionImportPdfReportTasklet.java
โโ controller/api
โ โโ AiApiController.java # /api/v1/ai/food, /api/v1/ai/coach
โ โโ AuthApiController.java
โ โโ ChallengeApiController.java
โ โโ CommunityApiController.java
โ โโ DashboardApiController.java
โ โโ FoodApiController.java
โ โโ HealthApiController.java
โ โโ MealApiController.java
โ โโ NutritionBatchApiController.java
โ โโ SocialApiController.java
โ โโ UserApiController.java
โโ controller
โ โโ SpaController.java
โ โโ *Controller.java # /legacy/** JSP ํ์ธ์ฉ MVC ์ปจํธ๋กค๋ฌ
โโ repository
โโ service
โโ model
โโ config
client
โโ src/views
โ โโ coach/CoachView.vue # AI ์ฑํ
UI ์ถ๊ฐ
โโ src/composables
โโ src/router
โโ src/stores
โโ Dockerfile
database
โโ Dockerfile
- Java 21
- Spring Boot 3.5.14
- Spring AI 1.1.6
- Google Gemini (
gemini-2.5-flash-lite, SSAFY GMS ํ๋ก์) - Spring Batch
- Maven
- MySQL
- Vue 3 + Vite
- pnpm
- JSP(
/legacy/**ํ์ธ์ฉ) - JDBC
- Swagger/OpenAPI
- Apache POI
GMS_API_KEYํ๊ฒฝ๋ณ์๋ฅผ ์ค์ ํฉ๋๋ค.- Docker Compose๋ก ํ ๋ฒ์ ์คํํฉ๋๋ค.
export GMS_API_KEY=your_gms_api_key
docker compose up๋ก์ปฌ ์ง์ ์คํ ์:
- MySQL์์
ssafy_yumyumcoach์คํค๋ง๋ฅผ ์ค๋นํฉ๋๋ค.
assets/ssafy_yumyumcoach.sql์ ์คํํฉ๋๋ค.
src/main/resources/application.properties์ DB ๊ณ์ ์ ๋ณด๋ฅผ ํ์ธํฉ๋๋ค.- Vue ์ ์ ์ฐ์ถ๋ฌผ์ ์์ฑํฉ๋๋ค.
cd client
pnpm install
pnpm buildGMS_API_KEYํ๊ฒฝ๋ณ์๋ฅผ ์ค์ ํ ๋คYumyumApplication.java๋ฅผ ์คํํฉ๋๋ค.- ๋ธ๋ผ์ฐ์ ์์
http://localhost:8080๋๋ Swagger UI์ ์ ์ํฉ๋๋ค.
๊ฐ๋ฐ ์ค์๋ Spring Boot๋ฅผ ์คํํ ๋ค ๋ณ๋ ํฐ๋ฏธ๋์์ Vite ๊ฐ๋ฐ ์๋ฒ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
cd client
pnpm devspring.application.name=springyum
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/ssafy_yumyumcoach?serverTimezone=Asia/Seoul&characterEncoding=UTF-8
spring.datasource.username=ssafy
spring.datasource.password=ssafy
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.batch.job.enabled=false
spring.batch.jdbc.initialize-schema=always
springdoc.swagger-ui.with-credentials=true
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true
# Spring AI - GMS Gemini
ssafy.gms.api-key=${GMS_API_KEY}
spring.ai.google.genai.api-key=${ssafy.gms.api-key}
spring.ai.google.genai.base-url=https://gms.ssafy.io/gmsapi/generativelanguage.googleapis.com
spring.ai.google.genai.chat.options.model=gemini-2.5-flash-liteGMS_API_KEYํ๊ฒฝ๋ณ์๊ฐ ์์ผ๋ฉด AI ๊ธฐ๋ฅ ์ ์ฒด๊ฐ ๋์ํ์ง ์์ต๋๋ค. Docker Compose ์คํ ์ ๋ฐ๋์ ์ค์ ํด์ผ ํฉ๋๋ค.- Spring AI 1.1.6์์
spring.ai.google.genai.base-urlํ๋กํผํฐ๋ ์๋ ๊ตฌ์ฑ์ ์ ์ฉ๋์ง ์์ต๋๋ค.AiConfig.java์์Client๋ฅผ ์ง์ ์์ฑํด ์ฒ๋ฆฌํ๋ฏ๋ก ํด๋น ํด๋์ค๋ฅผ ์ญ์ ํ์ง ์๋๋ก ์ฃผ์ํฉ๋๋ค. - ๊ธฐ์กด MySQL DB๊ฐ
users.user_id INT AUTO_INCREMENT๋ก ์์ฑ๋์ด ์๋ค๋ฉด ์คํค๋ง๋ฅผ ๋ค์ ์์ฑํด์ผ ํฉ๋๋ค.- ํ์ฌ ํ๋ก์ ํธ๋
user_demo๊ฐ์ ๋ฌธ์์ด ์ฌ์ฉ์ ID๋ฅผ ๊ธฐ์ค์ผ๋ก ํต์ผํ์ต๋๋ค. users.user_id,diet_logs.user_id๋VARCHAR(64)๊ธฐ์ค์ ๋๋ค.
- ํ์ฌ ํ๋ก์ ํธ๋
reports/๊ฒฝ๋ก๋ ๋ฐฐ์น ์คํ ์ฐ์ถ๋ฌผ์ด๋ฏ๋ก Git์ ํฌํจํ์ง ์์ต๋๋ค.- ๋ฐฐ์น metadata ํ ์ด๋ธ์ ๋ณ๋ DB๊ฐ ์๋๋ผ ๊ธฐ์กด ์ ํ๋ฆฌ์ผ์ด์ DB์ ์์ฑ๋ฉ๋๋ค.
spring.batch.job.enabled=false์ด๋ฏ๋ก ์๋ฒ ์์๋ง์ผ๋ก ๋ฐฐ์น๊ฐ ์๋ ์คํ๋์ง ์์ต๋๋ค.- ๋์ฉ๋ XLSX ํ์ผ์ ๋จผ์ ์์ CSV๋ก ๊ฒ์ฆํ ๋ค ์คํํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.
- Vue ์ ํ ๊ตฌํ ๊ณํ
- Vue ํ์ฉ ์ ํ
- API ๋ฌธ์
- ํ๋ก์ ํธ ๋ถ์
- DB ์คํค๋ง
- ERD ์ด๋ฏธ์ง
- Swagger ์บก์ฒ











