Skip to content

clainyun/springaiyum

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

163 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

YumYumCoach Spring AI

  • 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 up

ํ”„๋กœ์ ํŠธ ๊ฐœ์š”

YumYumCoach๋Š” ์‚ฌ์šฉ์ž์˜ ์‹๋‹จ ๊ธฐ๋ก๊ณผ ์Œ์‹ ์˜์–‘ ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” 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ํ•ฉ๋‹ˆ๋‹ค.

์ฃผ์š” ๋ณ€๊ฒฝ์ 

  • 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 โ†’ DailyGoalTool 3๊ฐœ 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 ์ ์žฌ ํ™˜๊ฒฝ์„ ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.
email: demo@yumyum.com
password: Demo1234!

AS-IS

  • AI ๊ธฐ๋Šฅ ์—†์ด ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ๋ฐ์ดํ„ฐ๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ์ˆ˜์น˜๋ฅผ ํ™•์ธํ•˜๋Š” ๋ฐฉ์‹์ด์—ˆ์Šต๋‹ˆ๋‹ค.
  • ์ฝ”์น˜ ํŽ˜์ด์ง€๋Š” ์ •์ ์ธ ๋Œ€์‹œ๋ณด๋“œ๋กœ, ์˜์–‘ ์กฐ์–ธ์€ ์ œ๊ณต๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.
  • ์‹๋‹จยท์˜์–‘์„ฑ๋ถ„ ๋ฐ์ดํ„ฐ๋Š” DB์— ์žˆ์—ˆ์ง€๋งŒ LLM์ด ์ด๋ฅผ ํ•ด์„ํ•˜๊ฑฐ๋‚˜ ํ™œ์šฉํ•˜๋Š” ๊ธฐ๋Šฅ์ด ์—†์—ˆ์Šต๋‹ˆ๋‹ค.
  • ์ผ๋ฐ˜ ์‚ฌ์šฉ์ž ํ™”๋ฉด์ด JSP์™€ Spring MVC view controller์— ๋ฌถ์—ฌ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
  • SPA route ์ง์ ‘ ์ ‘๊ทผ๊ณผ ์ƒˆ๋กœ๊ณ ์นจ์„ ์ฒ˜๋ฆฌํ•˜๋Š” Spring fallback ๊ตฌ์„ฑ์ด ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

TO-BE

  • 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/** ๊ฒฝ๋กœ์—์„œ ํ™•์ธ์šฉ์œผ๋กœ๋งŒ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

Spring AI ํ•„์ˆ˜ ์š”๊ตฌ์‚ฌํ•ญ ๋‹ฌ์„ฑ ํ˜„ํ™ฉ

์š”๊ตฌ์‚ฌํ•ญ ๋‹ฌ์„ฑ ๊ตฌํ˜„ ๋‚ด์šฉ
๋‹จ์ผ Tool ํ˜ธ์ถœ โœ… FoodSearchTool โ€” GET /api/v1/ai/food
๋‹ค์ค‘ Tool ํ˜ธ์ถœ โœ… UserProfileTool + TodayMealTool + DailyGoalTool โ€” GET /api/v1/ai/coach
Tool ๊ฒฐ๊ณผ ๊ธฐ๋ฐ˜ AI ์‘๋‹ต ์ƒ์„ฑ โœ… Gemini๊ฐ€ Tool ๋ฐ˜ํ™˜ ๋ฐ์ดํ„ฐ๋งŒ์„ ๊ทผ๊ฑฐ๋กœ ํ•œ๊ตญ์–ด ์ž์—ฐ์–ด ์‘๋‹ต ์ƒ์„ฑ

Spring AI ์‹คํ–‰ ํ๋ฆ„

๋‹จ์ผ Tool ํ๋ฆ„ (F1203)

์‚ฌ์šฉ์ž ์งˆ๋ฌธ โ†’ FoodSearchTool์ด food_nutrition ํ…Œ์ด๋ธ”์„ ๊ฒ€์ƒ‰ โ†’ Gemini๊ฐ€ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ž์—ฐ์–ด ์‘๋‹ต ์ƒ์„ฑ

๋‹ค์ค‘ Tool ํ๋ฆ„ (F1204)

์‚ฌ์šฉ์ž ์งˆ๋ฌธ โ†’ Gemini๊ฐ€ ์ˆœ์„œ๋ฅผ ํŒ๋‹จ โ†’ UserProfileTool๋กœ ํ”„๋กœํ•„ ์กฐํšŒ โ†’ TodayMealTool๋กœ ์˜ค๋Š˜ ์‹๋‹จ ์กฐํšŒ โ†’ DailyGoalTool๋กœ ๋ชฉํ‘œ ์นผ๋กœ๋ฆฌ ๊ณ„์‚ฐ โ†’ Gemini๊ฐ€ 3๊ฐœ Tool ๊ฒฐ๊ณผ๋ฅผ ์ข…ํ•ฉํ•ด ์ตœ์ข… ๋ถ„์„ ์‘๋‹ต ์ƒ์„ฑ

AI API ํ…Œ์ŠคํŠธ

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)๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

๋ฐฐ์น˜ ์‹คํ–‰ API

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 ์บก์ฒ˜:

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

์‹คํ–‰ ๋ฐฉ๋ฒ•

  1. GMS_API_KEY ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  2. Docker Compose๋กœ ํ•œ ๋ฒˆ์— ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
export GMS_API_KEY=your_gms_api_key
docker compose up

๋กœ์ปฌ ์ง์ ‘ ์‹คํ–‰ ์‹œ:

  1. MySQL์—์„œ ssafy_yumyumcoach ์Šคํ‚ค๋งˆ๋ฅผ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค.
  • assets/ssafy_yumyumcoach.sql์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  1. src/main/resources/application.properties์˜ DB ๊ณ„์ • ์ •๋ณด๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  2. Vue ์ •์  ์‚ฐ์ถœ๋ฌผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
cd client
pnpm install
pnpm build
  1. GMS_API_KEY ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•œ ๋’ค YumyumApplication.java๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  2. ๋ธŒ๋ผ์šฐ์ €์—์„œ http://localhost:8080 ๋˜๋Š” Swagger UI์— ์ ‘์†ํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ ์ค‘์—๋Š” Spring Boot๋ฅผ ์‹คํ–‰ํ•œ ๋’ค ๋ณ„๋„ ํ„ฐ๋ฏธ๋„์—์„œ Vite ๊ฐœ๋ฐœ ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

cd client
pnpm dev

application.properties ์ฃผ์š” ์„ค์ •

spring.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-lite

๋ณ€๊ฒฝ ์‹œ ์ฃผ์˜ํ•  ์ 

  • GMS_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๋กœ ๊ฒ€์ฆํ•œ ๋’ค ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

๊ด€๋ จ ํŒŒ์ผ


๋‹ค์ด์–ด๊ทธ๋žจ

ERD

ERD

ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ

Class Diagram


์‹คํ–‰ ํ™”๋ฉด

Swagger AI API

Swagger AI API

๋‹จ์ผ Tool ํ˜ธ์ถœ โ€” ์Œ์‹ ์˜์–‘ ๊ฒ€์ƒ‰ (F1203)

๋‹จ์ผ Tool ํ˜ธ์ถœ ํ™”๋ฉด

๋‹ค์ค‘ Tool ํ˜ธ์ถœ โ€” ์˜ค๋Š˜ ์‹๋‹จ ๋ถ„์„ (F1204)

๋‹ค์ค‘ Tool ํ˜ธ์ถœ ํ™”๋ฉด

Tool ํ˜ธ์ถœ ์„œ๋ฒ„ ๋กœ๊ทธ

Tool ํ˜ธ์ถœ ๋กœ๊ทธ

๋ฉ”์ธ ํ™”๋ฉด / ์†Œ์…œ ํ™”๋ฉด

๋ฉ”์ธ ํ™”๋ฉด ์†Œ์…œ ํ™”๋ฉด

์‹๋‹จ ๊ธฐ๋ก / ์ปค๋ฎค๋‹ˆํ‹ฐ ํ™”๋ฉด

์‹๋‹จ ๊ธฐ๋ก ํ™”๋ฉด ์ปค๋ฎค๋‹ˆํ‹ฐ ํ™”๋ฉด

์ฑŒ๋ฆฐ์ง€ ํ™”๋ฉด

์ฑŒ๋ฆฐ์ง€ ํ™”๋ฉด

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages