View on GitHub

capstone-2025-21

2025-1-cap-template created by GitHub Classroom

๐Ÿฑ Menu: ๋‹น์‹ ์˜ ์–ธ์–ด๋กœ, ๋‹น์‹ ์˜ ์ทจํ–ฅ์— ๋งž๊ฒŒ ๋ฉ”๋‰ด๋ฅผ ์ถ”์ฒœํ•ด๋“œ๋ฆฝ๋‹ˆ๋‹ค

๐Ÿ—‚๏ธํ”„๋กœ์ ํŠธ ์†Œ๊ฐœ

ํ•œ๊ตญ์„ ๋ฐฉ๋ฌธํ•˜๋Š” ์™ธ๊ตญ์ธ์„ ์œ„ํ•œ ์Œ์‹์  ๋ฉ”๋‰ดํŒ ๋ฒˆ์—ญ์„ ์ œ๊ณตํ•˜๊ณ , ์‚ฌ์šฉ์ž ์ทจํ–ฅ ๋ฐ ์•Œ๋Ÿฌ์ง€ ์ •๋ณด๋ฅผ ์ด์šฉํ•ด์„œ ์Œ์‹์„ ์ถ”์ฒœํ•ด์ฃผ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜

๐Ÿ“Œ ํ”„๋กœ์ ํŠธ ๋ฌธ์„œ


๐Ÿ—๏ธ ์‹œ์Šคํ…œ ์„ค๊ณ„

โœ… UseCase Diagram

โœ… Sequence Diagram

โœ… Architecture

๊ด€๋ จ ๋ฌธ์„œ

๐Ÿ—‚๏ธ ๊ฐœ๋ฐœ ๊ณผ์ • ์„ค๋ช…

AI

Task

๋ชจ๋ธ์— ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์€ ํฌ๊ฒŒ 3๊ฐ€์ง€๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๋ฉ”๋‰ดํŒ ํ…์ŠคํŠธ ์ธ์‹ ๋ฐ ์Œ์‹ ๋ฉ”๋‰ด ์ถ”์ถœ
  2. ์‚ฌ์šฉ์ž ์•Œ๋Ÿฌ์ง€ ๋ฐ ์ทจํ–ฅ ๊ธฐ๋ฐ˜ ์Œ์‹ ์ถ”์ฒœ
  3. ๋‹ค๊ตญ์–ด ๋ฉ”๋‰ด ๋ฒˆ์—ญ

1. ๋ฉ”๋‰ดํŒ ํ…์ŠคํŠธ ์ธ์‹ ๋ฐ ์Œ์‹ ๋ฉ”๋‰ด ์ถ”์ถœ

์ž์„ธํ•œ ๋‚ด์šฉ - ์ดˆ๊ธฐ์—๋Š” [AIHub ๋ฉ”๋‰ด ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ์…‹](https://www.aihub.or.kr/aihubdata/data/view.do?currMenu=&topMenu=&aihubDataSe=ty&dataSetSn=71553)์„ ํ™œ์šฉํ•˜์—ฌ `TrOCR` ๋ชจ๋ธ๋กœ ํ•™์Šต์„ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. [TrOCR ๋…ผ๋ฌธ](https://ojs.aaai.org/index.php/AAAI/article/view/26538) - ๊ทธ๋Ÿฌ๋‚˜ TrOCR๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ 1์ค„ ์ •๋„์˜ ๋‹จ์ˆœ ๋ฌธ์žฅ ์ธ์‹์— ์ตœ์ ํ™”๋˜์–ด ์žˆ์–ด, ์‹ค์ œ ๋ฉ”๋‰ดํŒ์ฒ˜๋Ÿผ **๋‹ค๋‹จ ๊ตฌ์„ฑ** ๋ฐ **๋น„์ •ํ˜• ๋ฐฐ์น˜**๋ฅผ ๊ฐ€์ง„ ์ด๋ฏธ์ง€์— ๋Œ€ํ•ด ํ•™์Šต loss๊ฐ€ ์ค„์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. - ์ดํ›„ `NAVER CRAFT` ๋ชจ๋ธ์„ ํ™œ์šฉํ•˜์—ฌ ๋ฉ”๋‰ดํŒ์—์„œ ํ…์ŠคํŠธ ์˜์—ญ์„ ์‚ฌ์ „์— ๊ฒ€์ถœํ•˜๊ณ  ์ด๋ฅผ TrOCR์˜ ์ž…๋ ฅ์œผ๋กœ ํ™œ์šฉํ•ด๋ณด์•˜์ง€๋งŒ, **์ถ”๋ก  ์‹œ๊ฐ„์ด ์ด๋ฏธ์ง€๋‹น ์•ฝ 5๋ถ„ ์ด์ƒ** ์†Œ์š”๋˜์–ด ์‹ค์šฉ์„ฑ์ด ๋–จ์–ด์กŒ์Šต๋‹ˆ๋‹ค. - ์ตœ์ข…์ ์œผ๋กœ `PaddleOCR`๋ฅผ ๋„์ž…ํ•˜์˜€์œผ๋ฉฐ, ํ•ด๋‹น ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๋น ๋ฅด๊ณ  ์•ˆ์ •์ ์ธ ํ…์ŠคํŠธ ์˜์—ญ ๊ฒ€์ถœ ๋ฐ ์ธ์‹์„ ๋™์‹œ์— ์ œ๊ณตํ•˜์—ฌ ์‹ค์ œ ์„œ๋น„์Šค ์ˆ˜์ค€์˜ ์ธ์‹ ์ •ํ™•๋„์™€ ์†๋„๋ฅผ ํ™•๋ณดํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. - **LLM**์„ ์ด์šฉํ•˜์—ฌ ์ธ์‹๋œ ํ…์ŠคํŠธ์—์„œ **๋ฉ”๋‰ด๋ช…๋งŒ ์ถ”์ถœ**ํ•˜๋Š” ๋ฐฉ์‹๋„ ์‹œ๋„ํ–ˆ์ง€๋งŒ, **๋น„๊ฒฐ์ •์„ฑ**์œผ๋กœ ์ธํ•ด ์ถ”์ถœ ๊ฒฐ๊ณผ๊ฐ€ ์ผ๊ด€๋˜์ง€ ์•Š๊ณ  ์ •ํ™•๋„๊ฐ€ ๋‚ฎ์•„ ์‹ค์ œ ์‚ฌ์šฉ์—๋Š” ์–ด๋ ค์›€์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. - ๋ฉ”๋‰ด๋ช… ์ถ”์ถœ์€ LLM ๋Œ€์‹  **2๋ฒˆ์—์„œ ์‚ฌ์šฉํ•œ KADx ์Œ์‹/์•Œ๋Ÿฌ์ง€ ๋ฐ์ดํ„ฐ์…‹์˜ ๋ฉ”๋‰ด๋ช… ๋ฆฌ์ŠคํŠธ**๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ถ”์ถœ๋œ ํ…์ŠคํŠธ๊ฐ€ ๋ฐ์ดํ„ฐ์…‹์— ์žˆ๋Š” ๊ฒฝ์šฐ ๋ฉ”๋‰ด๋กœ ์ธ์‹ํ•˜๋„๋ก **Rule-based ๋ฐฉ์‹**์œผ๋กœ ์ฒ˜๋ฆฌํ•˜์˜€์Šต๋‹ˆ๋‹ค.

2. ์‚ฌ์šฉ์ž ์•Œ๋Ÿฌ์ง€ ๋ฐ ์ทจํ–ฅ ๊ธฐ๋ฐ˜ ์Œ์‹ ์ถ”์ฒœ

์ž์„ธํ•œ ๋‚ด์šฉ - ์‚ฌ์šฉ์ž์˜ ์•Œ๋Ÿฌ์ง€ ์ •๋ณด ๋ฐ ์Œ์‹ ์ทจํ–ฅ์„ ๊ณ ๋ คํ•˜์—ฌ, ๋ฉ”๋‰ดํŒ์—์„œ ์ธ์‹๋œ ์Œ์‹ ์ค‘ **์•ˆ์ „ํ•˜๊ณ  ์„ ํ˜ธ ๊ฐ€๋Šฅํ•œ ๋ฉ”๋‰ด**๋ฅผ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค. - ์ถ”์ฒœ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ฐœ๋ฐœ์„ ์œ„ํ•ด [KADx ์•Œ๋Ÿฌ์ง€/์˜์–‘์ •๋ณด ํฌํ•จ ์Œ์‹ ๋ฐ์ดํ„ฐ](https://kadx.co.kr/opmk/frn/pmumkproductDetail/PMU_79c6f1a4-56dd-492e-ad67-c5acba0304d2/5)๋ฅผ ์ˆ˜์ง‘ ๋ฐ ์ „์ฒ˜๋ฆฌํ•˜์˜€์Šต๋‹ˆ๋‹ค. - ๊ฐ ์Œ์‹์˜ ๋ฉ”๋‰ด๋ช…๊ณผ ์žฌ๋ฃŒ ์ •๋ณด๋ฅผ **Sentence-BERT**๋ฅผ ์ด์šฉํ•ด ์ž„๋ฒ ๋”ฉํ•œ ํ›„, ์‚ฌ์šฉ์ž์˜ ์„ ํ˜ธ ์ž„๋ฒ ๋”ฉ ๋ฒกํ„ฐ์™€์˜ **์ฝ”์‚ฌ์ธ ์œ ์‚ฌ๋„**๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ๊ด€๋ จ์„ฑ ๋†’์€ ๋ฉ”๋‰ด๋ฅผ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค. - **Sentence-BERT**(**SBERT**)๋Š” **๋ฌธ์žฅ ์ž„๋ฒ ๋”ฉ**์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ๋”ฅ๋Ÿฌ๋‹ ๋ชจ๋ธ๋กœ, ๊ธฐ์กด์˜ **BERT**(Bidirectional Encoder Representations from Transformers)๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋˜, ๋ฌธ์žฅ ๊ฐ„์˜ ์˜๋ฏธ์  ์œ ์‚ฌ๋„ ๊ณ„์‚ฐ์„ ๋” ํšจ์œจ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํŠน๋ณ„ํžˆ ์„ค๊ณ„๋œ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค. - ์•Œ๋Ÿฌ์ง€ ์œ ๋ฐœ ์„ฑ๋ถ„์ด ํฌํ•จ๋œ ๋ฉ”๋‰ด๋Š” ํ•„ํ„ฐ๋งํ•˜์—ฌ ์‚ฌ์šฉ์ž์—๊ฒŒ ์•ˆ์ „ํ•œ ์„ ํƒ์ง€๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

3. ๋‹ค๊ตญ์–ด ๋ฉ”๋‰ด ๋ฒˆ์—ญ

์ž์„ธํ•œ ๋‚ด์šฉ - 1๋ฒˆ์—์„œ ์‚ฌ์šฉํ•œ AIHub ๋ฐ์ดํ„ฐ์…‹์—๋Š” 4๊ฐœ ๊ตญ์–ด(ํ•œ๊ตญ์–ด, ์˜์–ด, ์ผ๋ณธ์–ด, ์ค‘๊ตญ์–ด) ๋ณ‘๋ ฌ ๋ฌธ์žฅ์ด ์ผ๋ถ€ ์กด์žฌํ•˜์ง€๋งŒ, ๋ฒˆ์—ญ ํ’ˆ์งˆ์ด ๊ณ ๋ฅด์ง€ ๋ชปํ•ด ์ž์ฒด ๋ฒˆ์—ญ ๋ชจ๋ธ ํ•™์Šต์—๋Š” ์ ํ•ฉํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. - ๋˜ํ•œ, ๊ณต๊ฐœ๋œ ๊ณ ํ’ˆ์งˆ ์Œ์‹ ๋ฉ”๋‰ด ๋ฒˆ์—ญ ๋ฐ์ดํ„ฐ์…‹์ด ์—†์–ด ๋Œ€์•ˆ์œผ๋กœ **Google Translate API**๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค๊ตญ์–ด ๋ฒˆ์—ญ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. - ์ด ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ์™ธ๊ตญ์ธ ์‚ฌ์šฉ์ž๋„ ์ž๊ตญ์–ด๋กœ ์Œ์‹ ๋ฉ”๋‰ด๋ฅผ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์Œ์‹๋ช…๊ณผ ๊ฐ„๋‹จํ•œ ์„ค๋ช… ๋ฒˆ์—ญ์„ ํ•จ๊ป˜ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Front

์•„ํ‚คํ…์ณ ๊ทธ๋ž˜ํ”„

image

1. DIContainer๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์˜์กด์„ฑ ์ฃผ์ž…์„ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค

์ž์„ธํ•œ ๋‚ด์šฉ - NavigationRouter: ํŠน์ • ํ”Œ๋กœ์šฐ ๋‚ด์—์„œ์˜ ํ™”๋ฉด ์ด๋™ ๊ด€๋ฆฌ - WindowRouter: ์ฃผ์š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ™”๋ฉด/ํ”Œ๋กœ์šฐ ๊ฐ„์˜ ์ „ํ™˜ ๊ด€๋ฆฌ ```Swift import Foundation typealias NavigationRoutableType = NavigationRoutable & ObservableObjectSettable typealias WindowRoutableType = WindowRoutable & ObservableObjectSettable final class DIContainer: ObservableObject { var navigationRouter: NavigationRoutableType var windowRouter: WindowRoutableType private init( navigationRouter: NavigationRoutableType = NavigationRouter(), windowRouter: WindowRoutableType = WindowRouter() ) { self.navigationRouter = navigationRouter self.windowRouter = windowRouter navigationRouter.setObjectWillChange(objectWillChange) windowRouter.setObjectWillChange(objectWillChange) } } extension DIContainer { static let `default` = DIContainer() static let stub = DIContainer() } ```

2. ๋„ค๋น„๊ฒŒ์ด์…˜ ์‹œ์Šคํ…œ

์ž์„ธํ•œ ๋‚ด์šฉ ์•ฑ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋งž์ถคํ˜• ๋„ค๋น„๊ฒŒ์ด์…˜ ์•„ํ‚คํ…์ฒ˜๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค: **1. ์œˆ๋„์šฐ ๋ผ์šฐํŒ… - ์ฃผ์š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒํƒœ ์ฒ˜๋ฆฌ:** .splash - ์•ฑ ์ดˆ๊ธฐ ๋กœ๋”ฉ ํ™”๋ฉด .onboarding - ์‚ฌ์šฉ์ž ๋“ฑ๋ก ๋‹จ๊ณ„ .home - ๋ฉ”์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ธํ„ฐํŽ˜์ด์Šค ```Swift import Foundation import Combine protocol WindowRoutable { var destination: WindowDestination { get } func `switch`(to destination: WindowDestination) } class WindowRouter: WindowRoutable, ObservableObjectSettable { var objectWillChange: ObservableObjectPublisher? var destination: WindowDestination = .splash { didSet { objectWillChange?.send() } } func `switch`(to destination: WindowDestination) { self.destination = destination } } ``` **2. ๋‚ด๋น„๊ฒŒ์ด์…˜ ๋ผ์šฐํŒ… - ๊ฐ ํ”Œ๋กœ์šฐ ๋‚ด์—์„œ์˜ ํ™”๋ฉด ์ด๋™ ์ฒ˜๋ฆฌ:** ```Swift import Foundation import Combine protocol NavigationRoutable { var destinations: [NavigationDestination] { get set } func push(to view: NavigationDestination) func pop() func popToRootView() } class NavigationRouter: NavigationRoutable, ObservableObjectSettable { var objectWillChange: ObservableObjectPublisher? var destinations: [NavigationDestination] = [] { didSet { objectWillChange?.send() } } func push(to view: NavigationDestination) { destinations.append(view) } func pop() { _ = destinations.popLast() } func popToRootView() { destinations = [] } } ``` **3. ์Šคํƒ ๊ธฐ๋ฐ˜ ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ push/pop ์—ฐ์‚ฐ ์‚ฌ์šฉ** - ๋‚ด๋น„๊ฒŒ์ด์…˜ ๋ชฉ์ ์ง€๋Š” NavigationDestination ์—ด๊ฑฐํ˜•์— ์ •์˜ - NavigationRoutingView๊ฐ€ ๋ชฉ์ ์ง€๋ฅผ ๊ตฌ์ฒด์ ์ธ ๋ทฐ ์ธ์Šคํ„ด์Šค๋กœ ๋ณ€ํ™˜

3. MVVM ํŒจํ„ด

์ž์„ธํ•œ ๋‚ด์šฉ image ๊ฐ ํ™”๋ฉด์€ MVVM(Model-View-ViewModel) ํŒจํ„ด์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค: - ๋ทฐ: UI๋ฅผ ํ‘œ์‹œํ•˜๊ณ  ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ์บก์ฒ˜ํ•˜๋Š” SwiftUI ๋ทฐ - ๋ทฐ๋ชจ๋ธ: ์ƒํƒœ ๊ด€๋ฆฌ, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง, ์„œ๋น„์Šค์™€์˜ ํ†ต์‹  ๋‹ด๋‹น - ๋ชจ๋ธ: ๋„๋ฉ”์ธ ๊ฐ์ฒด๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ

4. ์ฃผ์š” ํ”Œ๋กœ์šฐ & ํ™ˆ ํƒญ ๊ตฌ์กฐ

์ž์„ธํ•œ ๋‚ด์šฉ ### ์„ธ ๊ฐœ์˜ ํƒญ์œผ๋กœ ๊ตฌ์„ฑ๋œ ๋ฉ”์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ธํ„ฐํŽ˜์ด์Šค: - **ArchivingView** - ์‚ฌ์šฉ์ž ์„ ํ˜ธ ์Œ์‹์„ ๊ธฐ๋ฐ˜ํ•œ ๋ง›์ง‘ ์ถ”์ฒœ ๋ฆฌ์ŠคํŠธ ์ œ๊ณต - **MenuImagePickerView** - ๋ฉ”์ธ ๋ฉ”๋‰ด ๋ถ„์„ ๊ธฐ๋Šฅ - **MyPageView** - ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ๋ฐ ์„ค์ • ### ์˜จ๋ณด๋”ฉ ํ”Œ๋กœ์šฐ ๋‹ค๋‹จ๊ณ„ ๋“ฑ๋ก ํ”„๋กœ์„ธ์Šค: - SelectNationalityView - ๊ตญ๊ฐ€ ์„ ํƒ - SelectAllergyView - ์•Œ๋ ˆ๋ฅด๊ธฐ ๋ฐ ๋งค์šด ์Œ์‹ ์„ ํ˜ธ๋„ ์ง€์ • - SelectKoreanFoodView - ์„ ํ˜ธํ•˜๋Š” ํ•œ๊ตญ ์Œ์‹ ์„ ํƒ - EnterIdPasswordView - ๊ณ„์ • ์ธ์ฆ ์ •๋ณด ์ƒ์„ฑ ### ๋ฉ”๋‰ด ๋ถ„์„ ํ”Œ๋กœ์šฐ ์‚ฌ์šฉ์ž๊ฐ€ ๋ฉ”๋‰ด ํ•ญ๋ชฉ์„ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ๋Š” ํ•ต์‹ฌ ๊ธฐ๋Šฅ: - MenuImagePickerView - ๋ฉ”๋‰ด ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ - MenuAnalysisLoadingView - ๋ฉ”๋‰ด ๋ถ„์„ ์ค‘ ๋กœ๋”ฉ ํ™”๋ฉด - MenuAnalysisResultView - ์‚ฌ์šฉ์ž ์„ ํ˜ธ๋„ ๊ธฐ๋ฐ˜ ์ถ”์ฒœ์„ ํฌํ•จํ•œ ๋ถ„์„ ๊ฒฐ๊ณผ ํ‘œ์‹œ

Back

1. MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค

์ž์„ธํ•œ ๋‚ด์šฉ database ๋ช… : menu_db DB ๊ด€๋ฆฌ์ž ๋ช… : admin - users table - id : ์‚ฌ์šฉ์ž id - nationality : ์‚ฌ์šฉ์ž ๊ตญ์  - password : ์‚ฌ์šฉ์ž ๋น„๋ฐ€๋ฒˆํ˜ธ - username : ์‚ฌ์šฉ์ž ์ด๋ฆ„ image - user_allergies table - user_id : ์‚ฌ์šฉ์ž id - allergy : ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์•Œ๋Ÿฌ์ง€ image - user_favorite_foods - user_id : ์‚ฌ์šฉ์ž id - food : ์‚ฌ์šฉ์ž๊ฐ€ ์ข‹์•„ํ•˜๋Š” ํ•œ๊ตญ ์Œ์‹ image - restaurants (ํ‰์ , ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ ์˜ˆ์ •) - id : ์‹๋‹น id - address : ์‹๋‹น ์ฃผ์†Œ - food_name : ์‹๋‹น ๋Œ€ํ‘œ๋ฉ”๋‰ด ์ด๋ฆ„ - restaurant_name : ์‹๋‹น ์ด๋ฆ„ image

2. API ๋ฌธ์„œ

์ž์„ธํ•œ ๋‚ด์šฉ ### POST /api/auth/signup ```jsx status: 200 respose: {"success": true, "message": "ํšŒ์›๊ฐ€์ž… ์„ฑ๊ณต", "data": {}} ``` ### POST /api/auth/login ```jsx status: 200 respose: { "success": true, "message": "๋กœ๊ทธ์ธ ์„ฑ๊ณต", "data": { "token": "string", "userId": โ€œstringโ€, "username": "string"}} ``` ### POST /api/auth/logout ```jsx status: 200 headers: {โ€Authorizationโ€: โ€œBearer โ€} respose: {"success": true,"message": "๋กœ๊ทธ์•„์›ƒ ์„ฑ๊ณต: ํด๋ผ์ด์–ธํŠธ๋Š” ํ† ํฐ ์‚ญ์ œ ์š”๋ง","data": null} ``` ### GET /api/user/profile ```jsx status: 200 headers: {โ€Authorizationโ€: โ€œBearer โ€} respose: {"success": true,"message": "์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ๋ฐ˜ํ™˜ ์„ฑ๊ณต", "data": { "username": "string", "nationality":โ€string"}} ``` ### GET /api/restaurant/recommend ```jsx status: 200 headers: {โ€Authorizationโ€: โ€œBearer โ€} respose: {"success": true,"message": "์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ๋ฐ˜ํ™˜ ์„ฑ๊ณต", "data": { "username": "string", "nationality":"string"}} ``` ### POST /api/gallery/upload ```jsx parameters: {โ€imageโ€: โ€œmultipart/form-data, fileโ€} headers: {โ€Authorizationโ€: โ€œBearer โ€} status: 200 respose: {โ€successโ€: true, โ€œmessageโ€: โ€œ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์„ฑ๊ณตโ€, โ€œdataโ€: {โ€urlโ€: โ€œ/api/gallery/images/{filename}โ€}} ``` ### GET /api/gallery/images/{filename} ```jsx parameters: {โ€filenameโ€: โ€œstringโ€} headers: {โ€Authorizationโ€: Bearer โ€} status: 200 respose: ์ด๋ฏธ์ง€ ํŒŒ์ผ ์ž์ฒด (image/jpeg ๋“ฑ) ``` ### POST /api/analysis/analyze-image ```jsx parameters: ์—†์Œ headers: {โ€Authorizationโ€: โ€œBearer โ€} status: 200 respose: {โ€successโ€: true, โ€œmessageโ€: โ€œAI ๋ถ„์„ ์š”์ฒญ ์„ฑ๊ณต ๋ฐ ๊ฒฐ๊ณผ ์บ์‹ฑ ์™„๋ฃŒโ€, โ€œdataโ€: โ€œokโ€} ``` ### GET /api/analysis/analyze ```jsx parameters: ์—†์Œ headers: {โ€Authorizationโ€: โ€œBearer โ€} status: 200 respose: {โ€œsuccessโ€: true, โ€œmessageโ€: โ€œ๋ถ„์„ ๊ฒฐ๊ณผ ์กฐํšŒ ์„ฑ๊ณตโ€} ``` ### GET /api/analysis/translate ```jsx parameters: ์—†์Œ headers: {โ€Authorizationโ€ :โ€Bearer โ€} status: 200 respose: {โ€successโ€: true, โ€œmessageโ€: โ€œ๋ฒˆ์—ญ ๊ฒฐ๊ณผ ์กฐํšŒ ์„ฑ๊ณตโ€} ``` </details> # ๐Ÿงฉ ๊ธฐ๋Šฅ ์„ค๋ช… ### โžก๏ธ ํšŒ์›๊ฐ€์ž… Flow ### 1. ์˜จ๋ณด๋”ฉ ๋ทฐ & ๋กœ๊ทธ์ธ ๋ทฐ ์•ฑ์„ ์ฒ˜์Œ ์‹คํ–‰ ์‹œ, ์•ฑ์„ ์„ค๋ช…ํ•˜๋Š” ์˜จ๋ณด๋”ฉ ํ™”๋ฉด์ด ๋‚˜ํƒ€๋‚˜๊ณ , start ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ฒŒ ๋˜๋ฉด ๋กœ๊ทธ์ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค!
### โžก๏ธ ํšŒ์›๊ฐ€์ž… Flow ๋กœ๊ทธ์ธ ํ™”๋ฉด์—์„œ sign up ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ํšŒ์›๊ฐ€์ž…์œผ๋กœ ์—ฐ๊ฒฐ๋œ๋‹ค ### 1. ๊ตญ์  & ์•Œ๋Ÿฌ์ง€ ์„ ํƒ ๋ทฐ ํ˜„์žฌ ๊ตญ์ ์€ ๋ฏธ๊ตญ, ์ผ๋ณธ, ์ค‘๊ตญ์œผ๋กœ ์„ธ ๋‚˜๋ผ๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์•Œ๋Ÿฌ์ง€๋Š” ์ด 25๊ฐœ ์ค‘์—์„œ ์ค‘๋ณต์ ์œผ๋กœ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
### 2. ์„ ํ˜ธํ•˜๋Š” ์Œ์‹ ์„ ํƒ & ๊ฐœ์ธ์ •๋ณด ์ž…๋ ฅ ๋ทฐ ๋ฉ”๋‰ดํŒ ๋ถ„์„์„ ํ†ตํ•ด์„œ ์„ ํ˜ธํ•˜๋Š” ์Œ์‹ ์ถ”์ฒœ ๋ฐ ๋ง›์ง‘ ์ถ”์ฒœ ์•„์นด์ด๋น™ ๋ทฐ์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์ •๋ณด์ธ ์„ ํ˜ธํ•˜๋Š” ํ•œ๊ตญ ์Œ์‹์„ ๋ฐ›๋Š”๋‹ค ๋งˆ์ง€๋ง‰์œผ๋กœ๋Š” username, password๋ฅผ ๋ฐ›๊ณ  ํšŒ์›๊ฐ€์ž…์„ ์‹คํ–‰ํ•œ๋‹ค.
### โžก๏ธ ๋ฉ”๋‰ด๋ถ„์„ Flow ### ๋ฉ”๋‰ดํŒ ์—…๋กœ๋“œ & ๋กœ๋”ฉ ๋ทฐ & ๋ฉ”๋‰ดํŒ ๋ถ„์„ ๊ฐค๋Ÿฌ๋ฆฌ์—์„œ ๋ฉ”๋‰ดํŒ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œ ํ•˜๊ณ  ๋ถ„์„ํ•˜๋Š” ๋™์•ˆ ๋กœ๋”ฉ๋ทฐ๋ฅผ ๋ณด์—ฌ์ค€๋‹ค ๋ฉ”๋‰ดํŒ ๋ถ„์„ ํŽ˜์ด์ง€์—์„œ๋Š” ํ•ด๋‹น ๋ฉ”๋‰ดํŒ์—์„œ ์ถ”์ฒœํ•˜๋Š” ์Œ์‹๊ณผ ์•Œ๋Ÿฌ์ง€์™€ ๊ด€๋ จ๋œ ๋ฉ”๋‰ด๋“ค์„ ํ•œ๋ˆˆ์— ๋ณด๊ธฐ ํŽธํ•˜๋„๋ก ๋ณด์—ฌ์ค€๋‹ค ๋˜ํ•œ ๋ฉ”๋‰ดํŒ ๋ฒˆ์—ญ ์ด๋ฏธ์ง€๋ฅผ ์ œ๊ณตํ•ด์คŒ์œผ๋กœ์จ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค
### โžก๏ธ ๋ง›์ง‘ ์•„์นด์ด๋น™ & ๋งˆ์ดํŽ˜์ด์ง€ Flow ### ๋งˆ์ดํŽ˜์ด์ง€ & ๋ง›์ง‘ ์•„์นด์ด๋น™ ๋ทฐ ๋งˆ์ดํŽ˜์ด์ง€์—์„œ ํšŒ์›์ •๋ณด ํ™•์ธ, ๋กœ๊ทธ์•„์›ƒ, ํšŒ์›ํƒˆํ‡ด ๋“ฑ์˜ ์ •๋ณด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋ง›์ง‘ ์•„์นด์ด๋น™ ๋ทฐ์—์„œ๋Š” ์ž์‹ ์˜ ์„ ํ˜ธ์Œ์‹์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ง›์ง‘ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ถ”์ฒœํ•ด์ฃผ๊ณ  ํ•ด๋‹น ๋ง›์ง‘์„ ๋ˆ„๋ฅด๋ฉด ์ธํ„ฐ๋„ท์„ ํ†ตํ•ด์„œ ์ •๋ณด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก ์—ฐ๊ฒฐํ•ด์ค€๋‹ค.
--- ## ์ปดํ“จํ„ฐ ๊ตฌ์„ฑ / ํ•„์ˆ˜ ์กฐ๊ฑด ์•ˆ๋‚ด (Prerequisites) * iOS >= 16.0 * swift >= 4.2 * MySQL 8.0 (AWS RDS) * Spring Boot 3.4.4 ## ๐Ÿ”จ๊ธฐ์ˆ  ์Šคํƒ (Technique Used) ### Server(back-end)
</a> </a>
Amazon RDS Springboot
### Front-end
Swift SwiftUI
### AI
</a> </a> </a> </a>
PyTorch Python FastAPI PaddleOCR
--- ## ๐Ÿ’ฝ์„ค์น˜ ์•ˆ๋‚ด (Installation Process) ### Swift #### Xcode ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ๋กœ ์‹คํ–‰ํ•˜๊ธฐ ```bash git clone https://github.com/kookmin-sw/capstone-2025-21 cd App/capstone21/capstone21 Xcode๋กœ ํ”„๋กœ์ ํŠธ ํŒŒ์ผ ์—ด๊ธฐ ์‹คํ–‰ํ•˜๊ธฐ ``` ### ์„œ๋ฒ„ ์‹คํ–‰ - Git clone ```bash # EC2๋กœ ์ ‘์† $ ssh -i ~/capstone2025-key.pem ubuntu@ # git clone $ git clone https://github.com/kookmin-sw/capstone-2025-21.git # ํ”„๋กœ์ ํŠธ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์ด๋™ ํ›„, ๋นŒ๋“œํ•œ JAR ํŒŒ์ผ ์—…๋กœ๋“œ ``` - Build - ๋กœ์ปฌ (intelliJ)์—์„œ ์‹คํ–‰ ```bash # Gradle ๋นŒ๋“œ ./gradlew bootJar # ์ƒ์„ฑ๋œ JAR ์œ„์น˜ (์˜ˆ์‹œ) build/libs/allergy-0.0.1-SNAPSHOT.jar ``` - EC2 ์„œ๋ฒ„์— JAR ์—…๋กœ๋“œ (SCP or FileZilla) ```bash # 1. scp ์‚ฌ์šฉ $ scp -i capstone2025-key.pem allergy-0.0.1-SNAPSHOT.jar ubuntu@:~/ # 2. ํ˜น์€ FileZilla์—์„œ ํ˜ธ์ŠคํŠธ์— IP, ์‚ฌ์šฉ์ž๋ช…, ํ‚ค ํŒŒ์ผ PEM ์„ค์ • ํ›„ ์ ‘์†ํ•ด์„œ ~/ ๊ฒฝ๋กœ์— ์—…๋กœ๋“œ ``` - ์„œ๋ฒ„ ์‹คํ–‰ ```bash # EC2์— ์ ‘์† $ ssh -i ~/capstone2025-key.pem ubuntu@ # JAR ์‹คํ–‰ (๋ฐฑ๊ทธ๋ผ์šด๋“œ ์‹คํ–‰) $ nohup java -jar allergy-0.0.1-SNAPSHOT.jar & # (prod profile๋กœ ์‹คํ–‰ํ•  ๊ฒฝ์šฐ) $ nohup java -jar -Dspring.profiles.active=prod.active allergy-0.0.1-SNAPSHOT.jar & ``` ### AI - Pytorch ์‹คํ–‰ ```bash # Python ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ ๋„๊ตฌ ์ตœ์‹ ํ™” (์„ ํƒ) pip install --upgrade pip # ํ•„์ˆ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜ pip install torch pip install fastapi pip install uvicorn pip install paddlepaddle-gpu # GPU ๋ฒ„์ „ ์‚ฌ์šฉ ์‹œ. CPU ์‚ฌ์šฉ์‹œ pip install paddlepaddle pip install paddleocr pip install sentence-transformers pip install scikit-learn pip install googletrans==4.0.0-rc1 ``` - ์„œ๋ฒ„ ์‹คํ–‰ ```bash uvicorn app:app --reload ``` --- ## ๐Ÿ“ฑํ”„๋กœ์ ํŠธ ์‚ฌ์šฉ๋ฒ• (Getting Started) ``` ์ž‘์„ฑ์˜ˆ์ • ``` --- ## ๐Ÿ•‹ํŒ€ ์ •๋ณด (Team Information)
Name Role github
๋ฐ•์ƒํ˜ Leader / AI
์†์›์ฒ  AI
๋ฅ˜ํฌ์žฌ Front-End (iOS)
๋ฐ•์„ธํ˜„ Back-End (Spring)
ํ—ˆ์„œ์˜ Back-End (Spring)
---