Skip to content

Malbit-Official/malbit_frontend

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

3 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿ—ฃ๏ธ ๋ง๋น› (Malbit) Frontend

"๋” ์ •ํ™•ํ•˜๊ณ  ์ž์—ฐ์Šค๋Ÿฌ์šด ๋น„์ฆˆ๋‹ˆ์Šค ์Šคํ”ผ์น˜, AI๋กœ ๋ง๋น›์„ ๋”ํ•˜๋‹ค"
'๋ง๋น›(Malbit)'์€ ์ง๋ฌด๋ณ„ ๋น„์ฆˆ๋‹ˆ์Šค ์ƒํ™ฉ๊ทน ์‹œ๋ฎฌ๋ ˆ์ด์…˜, AI ์‹ค์‹œ๊ฐ„ ๋ฌธ์žฅ ๊ต์ •(Remaster), ์ƒํ™ฉ๋ณ„ ๋ฐœํ™” ์ถ”์ฒœ, ๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž ์Œ์„ฑ ํ”„๋กœํ•„ ํ•™์Šต์„ ํ†ตํ•ด ์ง์žฅ ๋ฐ ๋น„์ฆˆ๋‹ˆ์Šค ํ˜„์žฅ์—์„œ์˜ ์˜์‚ฌ์†Œํ†ต ๋Šฅ๋ ฅ์„ ๊ทน๋Œ€ํ™”ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•˜๋Š” AI ๊ธฐ๋ฐ˜ ์Šคํ”ผ์น˜ ํŠธ๋ ˆ์ด๋‹ ๋ชจ๋ฐ”์ผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ž…๋‹ˆ๋‹ค.


๐Ÿ—๏ธ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜ ๋ฐ ํ•ต์‹ฌ ์›Œํฌํ”Œ๋กœ์šฐ

๋ณธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ Feature-First MVVM ๊ตฌ์กฐ๋ฅผ ์ฑ„ํƒํ•˜์—ฌ ๊ฐ ๋ชจ๋“ˆ(Feature)์ด ๋…๋ฆฝ์ ์ธ Model, Screen(View), Service(API Client)๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๊ธฐ๋Šฅ๋ณ„ ๋ชจ๋“ˆํ™”์™€ ๊ฒฐํ•ฉ๋„ ์ตœ์†Œํ™”๋ฅผ ๋‹ฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

1. AI ๋ฌธ์žฅ ๊ต์ • (AI Remaster) ํ๋ฆ„๋„

sequenceDiagram
    autonumber
    actor User as ์‚ฌ์šฉ์ž
    participant App as Flutter Client (Remaster)
    participant Storage as FlutterSecureStorage
    participant Serv as API Gateway (Remaster)
    participant TTS as Flutter TTS Engine

    User->>App: ๋…น์Œ ๋ฒ„ํŠผ ํด๋ฆญ (๋งˆ์ดํฌ ๊ถŒํ•œ ํš๋“)
    App->>App: WAV 16kHz, Mono, 128kbps ๋กœ์ปฌ ๋…น์Œ ๊ฐœ์‹œ
    User->>App: ์Œ์„ฑ ์ž…๋ ฅ ์ข…๋ฃŒ (๋…น์Œ ์ค‘์ง€)
    App->>Storage: Access Token ๋กœ๋“œ
    App->>Serv: POST /api/remaster (Multipart: WAV File & preferred_tone)
    Note over Serv: Backend: Whisper ASR ์ˆ˜ํ–‰<br/>LLM ๊ธฐ๋ฐ˜ ๋น„์ฆˆ๋‹ˆ์Šค ํ†ค ๊ต์ •
    Serv-->>App: HTTP 200 OK (original_speech & refined_text ๋ฐ˜ํ™˜)
    App->>App: ํ™”๋ฉด UI ์—…๋ฐ์ดํŠธ (๋“ค๋ฆฐ ๋Œ€๋กœ ํ‘œ์‹œ ๋ฐ ์ถ”์ฒœ ๋ฌธ์žฅ ์นด๋“œ ๋ Œ๋”๋ง)
    User->>App: '์žฌ์ƒ' ๋ฒ„ํŠผ ํด๋ฆญ
    App->>TTS: refined_text ์ „๋‹ฌ ๋ฐ ์žฌ์ƒ ์š”์ฒญ (ko-KR)
    TTS-->>User: ๋น„์ฆˆ๋‹ˆ์Šค ํ†ค์œผ๋กœ ๋ณด์ •๋œ ์Œ์„ฑ ์ถœ๋ ฅ
Loading

2. ์ง๋ฌด ์ƒํ™ฉ๊ทน ์‹œ๋ฎฌ๋ ˆ์ด์…˜ (Roleplay Session) ํ๋ฆ„๋„

sequenceDiagram
    autonumber
    actor User as ์‚ฌ์šฉ์ž
    participant App as Flutter Client (Order/Report/Call Screen)
    participant API as Training API
    participant STT as On-Device SpeechToText

    App->>API: POST /api/training/start (categoryId)
    API-->>App: Session ID ๋ฐ˜ํ™˜ (์„ธ์…˜ ์‹œ์ž‘ ๋ฐ ํŠธ๋ž˜ํ‚น ๊ฐœ์‹œ)
    loop ๊ฐ ๋‹จ๊ณ„ ์‹œ๋‚˜๋ฆฌ์˜ค ์ง„ํ–‰ (1 ~ N ๋‹จ๊ณ„)
        App->>User: ํ˜„์žฌ ์ƒํ™ฉ ๋ฌ˜์‚ฌ & ๊ณ ๊ฐ/์ƒ๋Œ€๋ฐฉ ๋Œ€์‚ฌ ๋ Œ๋”๋ง
        User->>App: '์ง์ ‘ ๋งํ•ด๋ณด๊ธฐ' ํƒญ (STT ๋…น์Œ ๊ฐœ์‹œ)
        User->>STT: ์Œ์„ฑ ๋ฐœํ™”
        STT-->>App: ์‹ค์‹œ๊ฐ„ ํ•œ๊ธ€ ํ…์ŠคํŠธ ๋ณ€ํ™˜ (ko_KR)
        User->>App: ๋ฐœํ™” ์™„๋ฃŒ
        App->>App: Dice Coefficient ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ๋ฐœ์Œ/ํ…์ŠคํŠธ ์œ ์‚ฌ๋„(F1) ์‹ค์‹œ๊ฐ„ ์—ฐ์‚ฐ
        App->>App: ๋‹จ๊ณ„๋ณ„ ์ฑ„์  ๋ฐ์ดํ„ฐ ๋กœ์ปฌ ์บ์‹ฑ ๋ฐ ๋‹ค์Œ ๋‹จ๊ณ„ ์ „ํ™˜
    end
    App->>API: PATCH /api/users/statistics/roleplay (ํ†ต๊ณ„ ๊ฐœ์ˆ˜ ์ฆ๋ถ„ ๋ฐ˜์˜)
    App->>API: POST /api/training/finish/{sessionId} (์„ธ์…˜ ์ข…๋ฃŒ)
    API-->>App: ์ „์ฒด ์„ฑ์  (Total Score, Average Accuracy, Evaluation) ๋ฐ˜ํ™˜
    App->>User: ์ตœ์ข… ๋ถ„์„ ๋ ˆํฌํŠธ ํŒ์—… ์ œ๊ณต (์ •ํ™•๋„๋ณ„ ์ปค์Šคํ…€ ํ”ผ๋“œ๋ฐฑ ๋ฆฌ์ŠคํŠธ ์ถœ๋ ฅ)
Loading

๐ŸŒŸ ํ•ต์‹ฌ ๊ธฐ์ˆ  ๊ธฐ๋Šฅ ๋ฐ ์•„ํ‚คํ…์ฒ˜ ์„ค๋ช…

1. AI ๋ฌธ์žฅ ๊ต์ • (AI Remaster) features/remaster

  • ์Œ์„ฑ ์ˆ˜์ง‘ ์ŠคํŽ™: ํ•˜๋“œ์›จ์–ด ๋งˆ์ดํฌ ๊ถŒํ•œ์„ ์•ˆ์ „ํ•˜๊ฒŒ ํš๋“ํ•˜๊ณ , record ํŒจํ‚ค์ง€๋ฅผ ์ด์šฉํ•ด **WAV ์ปจํ…Œ์ด๋„ˆ ํฌ๋งท(16,000Hz Sample Rate, ๋‹จ์ผ ์ฑ„๋„ Mono, 128,000bps Bit Rate)**์˜ ์ €์ง€์—ฐ ๊ณ ์Œ์งˆ ์Œ์„ฑ์„ ์บก์ฒ˜ํ•ฉ๋‹ˆ๋‹ค.
  • API ํ†ตํ•ฉ: http.MultipartRequest๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฐ”์ดํŠธ ๋ฐฐ์—ด๋กœ ์Œ์„ฑ ํŒŒ์ผ์„ ์บก์ฒ˜ํ•˜๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋ง์”จ(Gentle ๋“ฑ) ํ•„๋“œ์™€ ํ•จ๊ป˜ MultipartFile๋กœ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.
  • ์ข…๋‹จ๊ฐ„ ํ”ผ๋“œ๋ฐฑ ๋ฃจํ”„: ๋ฐฑ์—”๋“œ๊ฐ€ ์ „์†กํ•œ Whisper ASR ํ…์ŠคํŠธ(original_speech)์™€ LLM ๋ฌธ์žฅ ๊ต์ •๋ณธ(refined_text)์„ ๋ฐ›์•„ ์นด๋“œ ํ˜•ํƒœ๋กœ ์‹œ๊ฐํ™”ํ•ฉ๋‹ˆ๋‹ค. ๋””๋ฐ”์ด์Šค์˜ TTS ์—”์ง„(flutter_tts)๊ณผ ๋‹ค์ด๋ ‰ํŠธ๋กœ ๊ฒฐํ•ฉ๋˜์–ด ๋ฐœํ™” ๊ฐ€์ด๋“œ๋ฅผ ๊ธฐ๊ณ„์Œ ํ˜•ํƒœ๋กœ ์ •ํ™•ํžˆ ์ „๋‹ฌํ•˜๋ฉฐ, ์‹œ๋ ฅ์ด ๋‚ฎ์€ ์‚ฌ์šฉ์ž๋‚˜ ์ง‘์ค‘ ํ›ˆ๋ จ์„ ์œ„ํ•ด ํ…์ŠคํŠธ๋ฅผ ํฌ๊ฒŒ ๋„์›Œ์ฃผ๋Š” ExpandTextScreens ๋ทฐ ๋ชจ๋“œ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

2. ์ง๋ฌด ์ƒํ™ฉ๊ทน ์‹œ๋ฎฌ๋ ˆ์ด์…˜ (Job Roleplay) features/template

์‹ค์ œ ํ˜„์žฅ์—์„œ ๋งž๋‹ฅ๋œจ๋ฆฌ๋Š” ์˜์‚ฌ์†Œํ†ต ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๋‹จ๊ณ„๋ณ„ ์ƒํ˜ธ์ž‘์šฉ ๋ฐฉ์‹์œผ๋กœ ์—ฐ์Šตํ•ฉ๋‹ˆ๋‹ค.

  • 4๋Œ€ ๋น„์ฆˆ๋‹ˆ์Šค ํ…œํ”Œ๋ฆฟ:
    • ์ฃผ๋ฌธ ๋ฐ›๊ธฐ (Take Orders โ˜•): ์นดํŽ˜/๋งค์žฅ ๋“ฑ์—์„œ ๊ณ ๊ฐ์˜ ์Œ๋ฃŒ ์„ ํƒ, ์˜ต์…˜ ๋ณ€๊ฒฝ, ํ’ˆ์ ˆ ๋Œ€์ฒ˜, ๊ฒฐ์ œ ์•ˆ๋‚ด ๋ฐ ์ฃผ๋ฌธ ์ตœ์ข… ํ™•์ธ.
    • ์ƒํ’ˆ ์•ˆ๋‚ดํ•˜๊ธฐ (Product Guide ๐Ÿ‘œ): ๊ณ ๊ฐ ๋งž์ด, ์ œํ’ˆ ์ •๋ณด ์ „๋‹ฌ, ๊ฐ€๊ฒฉ/ํ˜œํƒ ๊ณ ์ง€, ์ถ”๊ฐ€ ์ถ”์ฒœ ๋“ฑ ๋Šฅ๋™์  ์•ˆ๋‚ด ์„ธ์ผ์ฆˆ ์Šคํ”ผ์น˜.
    • ์—…๋ฌด ๋ณด๊ณ ํ•˜๊ธฐ (Work Report ๐Ÿ“‘): ํ”„๋กœ์ ํŠธ ์ง„ํ–‰ ์‚ฌํ•ญ ๋ณด๊ณ , ๋ฌธ์ œ ์ƒํ™ฉ ๊ณต์œ  ๋ฐ ํ˜‘์—… ํ”ผ๋“œ๋ฐฑ ์ „๋‹ฌ.
    • ์ „ํ™” ๋ฐ›๊ธฐ (Call Support ๐Ÿ“ž): ํšŒ์‚ฌ ์ „ํ™” ์‘๋Œ€์˜ ๊ธฐ๋ณธ ํฌ๋งทํŒ…, ๋ฌธ์˜ ์‚ฌํ•ญ ๊ฒฝ์ฒญ ๋ฐ ๋‹ด๋‹น์ž ์ „๋‹ฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ํ›ˆ๋ จ.
  • ์„ธ์…˜ ๋ผ์ดํ”„์‚ฌ์ดํด ํŠธ๋ž˜ํ‚น: ์‹œ์ž‘ ์‹œ ๋ฐฑ์—”๋“œ TrainingApi.startSession ํ˜ธ์ถœ์„ ํ†ตํ•ด ๋ฐœ๊ธ‰๋ฐ›์€ sessionId๋ฅผ ์ปจํ…์ŠคํŠธ ๋‚ด์—์„œ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์‹œ๋ฎฌ๋ ˆ์ด์…˜์ด ์ข…๋ฃŒ๋˜๋ฉด finishSession ์š”์ฒญ์„ ๋‚ ๋ ค ์ „์ฒด ํ†ต๊ณ„๋ฅผ ๋ถ„์„ํ•˜๊ณ  ์„œ๋ฒ„์˜ ๋ถ„์„ ์„ฑ๊ณผ ์ง€ํ‘œ(์ข…ํ•ฉ ์ ์ˆ˜, ํ‰๊ท  ์ •ํ™•๋„, ์ •์„ฑ ํ‰๊ฐ€ ํ”ผ๋“œ๋ฐฑ)๋ฅผ ์ˆ˜์ง‘ํ•ฉ๋‹ˆ๋‹ค.

3. ์‹ค์‹œ๊ฐ„ ์ƒํ™ฉ๋ณ„ ๋ฐœํ™” ์ถ”์ฒœ features/roleplay

  • ์Œ์„ฑ ๊ธฐ๋ฐ˜ ์ƒํ™ฉ ํƒ์ง€ (Speech-to-Text): ์‚ฌ์šฉ์ž๊ฐ€ ์ฒ˜ํ•œ ์ƒํ™ฉ์„ ์ž…์œผ๋กœ ๋งํ•˜๋ฉด (speech_to_text), ์˜จ๋””๋ฐ”์ด์Šค ํ•œ๊ธ€ ์Œ์„ฑ ์—”์ง„์„ ํ†ตํ•ด ์ƒํ™ฉ์„ ์ธ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  • ์Šค๋งˆํŠธ ์นจ๋ฌต ํŠธ๋ฆฌ๊ฑฐ (Silence Detection): ์‚ฌ์šฉ์ž์˜ ๋ง์ด ๋Š๊ธฐ๋ฉด Timer๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘๋™ํ•˜๋Š” ์นจ๋ฌต ๊ฐ์ง€ ๋กœ์ง์ด ๊ฐœ์ž…ํ•˜์—ฌ, 3์ดˆ๊ฐ„ ์ž…๋ ฅ์ด ๊ฐ์ง€๋˜์ง€ ์•Š์„ ์‹œ ์ž๋™์œผ๋กœ ๋ถ„์„ API(/api/recommendations/suggest)๋กœ ์งˆ์˜๋ฅผ ๋‚ ๋ ค ์ƒํ™ฉ ๊ทน๋ณต์„ ์œ„ํ•œ ๋ชจ๋ฒ” ๋ฐœํ™” ์Šคํฌ๋ฆฝํŠธ์™€ ํŒ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • ๋‹ค์–‘ํ•œ ํ”„๋ฆฌ์…‹: ๋นˆ๋ฒˆํžˆ ์š”๊ตฌ๋˜๋Š” ์‹ค์ˆ˜ ์‚ฌ๊ณผ, ํšŒ์˜ ์ค‘ ๋ฐœ์–ธ, ์ฃผ๋ฌธ/๊ฒฐ์ œ, ์ฒซ ์ธ์‚ฌ ๋“ฑ์˜ ์ƒํ™ฉ์„ ์นดํ…Œ๊ณ ๋ฆฌ ํƒœ๊ทธ๋กœ ๋น ๋ฅด๊ฒŒ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

4. ๊ฐœ์ธํ™”๋œ AI ์Œ์„ฑ ํ”„๋กœํ•„ ํ•™์Šต features/voice_settings

  • ์Œ์„ฑ ์žฌ๋“ฑ๋ก ํŒŒ์ดํ”„๋ผ์ธ: ํฐํŠธ ๋ฐ ๋ชจ์Œ์ด ๊ท ํ˜• ์žกํžŒ 6๊ฐœ์˜ ํ‘œ์ค€ ๋Œ€์กฐ์šฉ ํ•œ๊ตญ์–ด ๋ฌธ์žฅ("๋‚˜๋Š” ์˜ค๋Š˜ ๊ธฐ์ฐจ๋ฅผ ํƒ€๊ณ ...", "๋‹ฌ์ฝคํ•œ ๋นต๊ณผ ๋”ฐ๋œปํ•œ...")์„ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ˆœ์ฐจ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • AI ํ›ˆ๋ จ ๋‹ค์ค‘ ํŒŒ์ผ ์ „์†ก: ๊ฐ ๋ฌธ์žฅ๋ณ„ ๋…น์Œ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ์ปฌ ์ž„์‹œ ํด๋”(.wav ํฌ๋งท)์— ์ €์žฅํ–ˆ๋‹ค๊ฐ€, ์‚ฌ์šฉ์ž๊ฐ€ ์™„๋ฃŒ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๋‹จ์ผ Multipart Request์˜ voiceFiles ์ŠคํŠธ๋ฆผ ๋ฆฌ์ŠคํŠธ์— ์‹ค์–ด /api/users/voice/re-register๋กœ ์ผ๊ด„ ์ „์†กํ•จ์œผ๋กœ์จ ๋ฐฑ์—”๋“œ ์ธก ๊ฐœ์ธํ™” AI ๋ณด์ด์Šค ๋ชจ๋ธ์„ ํŠœ๋‹ํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ์ดˆ ๋ฐ์ดํ„ฐ๋ฅผ ํ˜•์„ฑํ•ฉ๋‹ˆ๋‹ค.

5. ์ผ์ • ์กฐ์œจ ๋ฐ ํ†ต๊ณ„ ๋™๊ธฐํ™” features/home

  • ๊ณ ๊ธ‰ ์บ˜๋ฆฐ๋” ์ปค์Šคํ„ฐ๋งˆ์ด์ง•: table_calendar ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ, ๊ตญ๋ฌธ ๋กœ์ผ€์ผ ์ ์šฉ์€ ๋ฌผ๋ก  ํ† ์š”์ผ(ํŒŒ๋ž€์ƒ‰), ์ผ์š”์ผ/๊ณตํœด์ผ(๋นจ๊ฐ„์ƒ‰) ํ…์ŠคํŠธ ์Šคํƒ€์ผ์„ ๋ถ„๋ฆฌํ•œ ์ˆ˜๋ คํ•œ ์ปค์Šคํ…€ UI๋ฅผ ๊ตฌ์ถ•ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ณตํœด์ผ API ๊ฒฐํ•ฉ: ๋กœ์ปฌ ๊ณตํœด์ผ ์ •๋ณด ์กฐํšŒ ์„œ๋น„์Šค(HolidayService)๋ฅผ ๊ตฌ์ถ•ํ•ด ๊ตญ๊ฒฝ์ผ/๊ณตํœด์ผ ์ •๋ณด ๋ฐ์ดํ„ฐ๋ฅผ ์™ธ๋ถ€ ๊ณต๊ณต ๋ฐ์ดํ„ฐ API ํ˜น์€ ๋ฐฑ์—”๋“œ๋ฅผ ๊ฑฐ์ณ ๋ฐ›์•„์™€ ๋‹ฌ๋ ฅ ์ƒ์— ๊ธฐ๋…์ผ ๋งˆ์ปค ๋ฐ ๊ธฐ๋… ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
  • Task/Event CRUD: ์ผ์ • ๋“ฑ๋ก(manual), ์ˆ˜์ •, ์‚ญ์ œ ๋ฐ ์™„๋ฃŒ ์—ฌ๋ถ€ ํ† ๊ธ€ API(/api/calendar/{taskId}/completion)๋ฅผ ์™„๋ฒฝํžˆ ์—ฐ๋™ํ•ด ์ผ์ผ ์—…๋ฌด ๋ฐ ํ›ˆ๋ จ ์‹ค์ ์„ ๋‹ฌ๋ ฅ์œผ๋กœ ํ•œ๋ˆˆ์— ํŒŒ์•…ํ•˜๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿงฎ ํ•ต์‹ฌ ์ˆ˜ํ•™์  ์•Œ๊ณ ๋ฆฌ์ฆ˜: Dice Coefficient ๊ธฐ๋ฐ˜ ํ…์ŠคํŠธ ์œ ์‚ฌ๋„ ๊ณ„์‚ฐ

์‚ฌ์šฉ์ž๊ฐ€ ์ง๋ฌด ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ์ œ์‹œํ•œ ํžŒํŠธ ๋ฌธ์žฅ(Ideal Script)์„ ์–ผ๋งˆ๋‚˜ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋ฐœ์Œํ•˜๊ณ  ์˜๋ฏธ๋ฅผ ๋งž์ท„๋Š”์ง€ ์˜จ๋””๋ฐ”์ด์Šค์—์„œ 1์ฐจ ํ‰๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด, ํ˜•ํƒœ์†Œ ๋ฐ ๋‹จ์–ด ํ† ํฐ์˜ ๊ต์ง‘ํ•ฉ ๋น„์œจ์„ ์ธก์ •ํ•˜๋Š” Dice Coefficient (F1-Score) ๊ธฐ๋ฐ˜ ์œ ์‚ฌ๋„ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

1. ์ˆ˜ํ•™์  ๊ณต์‹

๋‹จ์–ด์˜ ์ง‘ํ•ฉ $X$(์‚ฌ์šฉ์ž ์ธ์‹ ํ…์ŠคํŠธ)์™€ $Y$(ํžŒํŠธ ํ…์ŠคํŠธ)์˜ ์œ ์‚ฌ๋„ $D(X, Y)$๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜๋ฉ๋‹ˆ๋‹ค.

$$D(X, Y) = \frac{2 \times |X \cap Y|}{|X| + |Y|}$$

์ด ๊ณต์‹์€ ์ •๋ฐ€๋„(Precision)์™€ ์žฌํ˜„์œจ(Recall)์˜ ์กฐํ™” ํ‰๊ท ์ธ F1-Score์™€ ์ˆ˜ํ•™์ ์œผ๋กœ ์™„์ „ํžˆ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

  • $\text{Recall} = \frac{|X \cap Y|}{|Y|}$ (ํžŒํŠธ ๋ฌธ์žฅ์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ๋น ๋œจ๋ฆฌ์ง€ ์•Š๊ณ  ๋งํ•œ ๋‹จ์–ด ๋น„์œจ)
  • $\text{Precision} = \frac{|X \cap Y|}{|X|}$ (์‚ฌ์šฉ์ž๊ฐ€ ๋ฑ‰์€ ๋ง ์ค‘์—์„œ ํžŒํŠธ ๋ฌธ์žฅ๊ณผ ๋งค์นญ๋˜๋Š” ๋น„์œจ)
  • $\text{F1-Score} = \frac{2 \times \text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}} = \frac{2 \times |X \cap Y|}{|X| + |Y|}$

2. Dart ์†Œ์Šค ์ฝ”๋“œ ๊ตฌํ˜„์ฒด (OrderScreen ๋‚ด ๋ฐœ์ทŒ)

double _similarity(String input, String hint) {
  if (input.trim().isEmpty) return 0.0;
  
  // 1. ํ•œ๊ตญ์–ด ์ž๋ชจ, ์˜์–ด ์•ŒํŒŒ๋ฒณ, ์ˆซ์ž, ๊ณต๋ฐฑ์„ ์ œ์™ธํ•œ ๋ฌธ์žฅ๋ถ€ํ˜ธ ๋ฐ ํŠน์ˆ˜๋ฌธ์ž ์ œ๊ฑฐ
  String clean(String s) => s
      .replaceAll(RegExp(r'[^\uAC00-\uD7A3\u1100-\u11FF\u3130-\u318F\s\w]'), '')
      .trim();
      
  // 2. ๊ณต๋ฐฑ ๊ธฐ์ค€ ํ† ํฐํ™” ๋ฐ ๊ณ ์œ  ๋‹จ์–ด ์„ธํŠธ(Set)ํ™” ์ˆ˜ํ–‰
  final inputWords = clean(input).split(RegExp(r'\s+')).where((w) => w.isNotEmpty).toSet();
  final hintWords = clean(hint).split(RegExp(r'\s+')).where((w) => w.isNotEmpty).toSet();
  
  if (hintWords.isEmpty || inputWords.isEmpty) return 0.0;
  
  // 3. ๊ต์ง‘ํ•ฉ(Intersection) ์—ฐ์‚ฐ
  final common = inputWords.intersection(hintWords);
  
  // 4. Recall, Precision ์—ฐ์‚ฐ
  final recall = common.length / hintWords.length;
  final precision = common.length / inputWords.length;
  
  if (recall + precision == 0) return 0.0;
  
  // 5. ์กฐํ™”ํ‰๊ท (F1-Score)์„ ์ตœ์ข… ๊ฒฐ๊ณผ๋กœ ๋„์ถœ
  return 2 * recall * precision / (recall + precision);
}

๐Ÿ› ๏ธ ๊ธฐ์ˆ  ์Šคํƒ (Tech Stacks)

๋ถ„๋ฅ˜ ๊ธฐ์ˆ  ๋ฐ ํŒจํ‚ค์ง€ ๋น„๊ณ 
SDK & ์–ธ์–ด Dart ^3.9.2, Flutter SDK ๋‹ค์ค‘ ํ”Œ๋žซํผ ํƒ€๊ฒŸํŒ… ๊ธฐ๋ฐ˜ ๊ตฌ์กฐ
๋ณด์•ˆ ์Šคํ† ๋ฆฌ์ง€ flutter_secure_storage ^9.0.0 Android: EncryptedSharedPreferences
iOS: Keychain ์—ฐ๋™ ๊ธฐ๋ฐ˜ ํ† ํฐ ์•”ํ˜ธํ™” ์ €์žฅ
๋กœ์ปฌ ์ €์žฅ์†Œ shared_preferences ^2.2.2 ๋น„์ •ํ˜• ์‚ฌ์šฉ์ž ๊ฐ€๋ฒผ์šด ์„ค์ • ๊ฐ’ ์ €์žฅ
์Œ์„ฑ ๋…น์Œ record ^6.2.0 ์˜ค๋””์˜ค ์ธ์ฝ”๋”ฉ ์ง€์› ํŒจํ‚ค์ง€ (WAV ํฌ๋งท ์ตœ์ ํ™”)
์Œ์„ฑ ๋ฌธ์ž ๋ณ€ํ™˜ speech_to_text ^7.0.0 ๋‹ค๋ฐ”์ด์Šค ๋„ค์ดํ‹ฐ๋ธŒ STT ํ•œ๊ธ€ ํŒจํ‚ค์ง€ ๋ชจ๋“ˆ
๋ฌธ์ž ์Œ์„ฑ ๋ณ€ํ™˜ flutter_tts ^4.2.2 ํ”ผ๋“œ๋ฐฑ ๊ตฌ๋ฌธ ์ฝ์–ด์ฃผ๊ธฐ ๊ธฐ๋Šฅ
๋„คํŠธ์›Œํฌ ํ†ต์‹  http ^1.2.0, http_parser ^4.1.2 ๋น„๋™๊ธฐ JSON REST API ์—ฐ๋™ ๋ฐ ํŒŒ์ผ ์—…๋กœ๋“œ ์ฒ˜๋ฆฌ
๊ฐ„ํŽธ ์ธ์ฆ(OAuth) kakao_flutter_sdk_user, google_sign_in ์†Œ์…œ ๋กœ๊ทธ์ธ ์ง€์› ์—ฐ๋™ ํŒจํ‚ค์ง€
๋‚ ์งœ ๋ฐ ์บ˜๋ฆฐ๋” table_calendar ^3.2.0, intl ^0.20.2 ๋‚ ์งœ ํ˜„์ง€ํ™”(ko_KR) ๋ฐ ์บ˜๋ฆฐ๋” ๋ Œ๋”๋Ÿฌ

๐Ÿ“‚ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ ๋ฐ ๋””๋ ‰ํ† ๋ฆฌ ๋ ˆ์ด์•„์›ƒ

์ฝ”๋“œ๋Š” ๋ชจ๋“ˆ ๊ฐ„ ๋…๋ฆฝ์„ฑ์„ ๋ณด์žฅํ•˜๊ณ  ๊ตฌ์กฐ์  ์œ ์—ฐํ•จ์„ ๊ฐ–์ถ”๊ธฐ ์œ„ํ•ด ํ”ผ์ฒ˜ ๋‹จ์œ„๋กœ ๋ถ„๋ฆฌ๋˜์–ด ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

lib/
โ”œโ”€โ”€ core/
โ”‚   โ””โ”€โ”€ services/
โ”‚       โ”œโ”€โ”€ storage.dart         # FlutterSecureStorage ๊ณตํ†ต ํŒฉํ† ๋ฆฌ ๊ตฌ์„ฑ ์„ค์ •
โ”‚       โ””โ”€โ”€ training_api.dart    # ๊ณตํ†ต ํ•™์Šต ์„ธ์…˜(์‹œ์ž‘/์ข…๋ฃŒ) ๊ด€๋ จ ์ „์—ญ ํ˜ธ์ถœ ํด๋ผ์ด์–ธํŠธ
โ”œโ”€โ”€ features/
โ”‚   โ”œโ”€โ”€ auth/
โ”‚   โ”‚   โ”œโ”€โ”€ screens/             # ๋กœ๊ทธ์ธ(Login), ํšŒ์›๊ฐ€์ž…(SignUp), ๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌ์„ค์ •
โ”‚   โ”‚   โ””โ”€โ”€ services/            # ์ด๋ฉ”์ผ/์†Œ์…œ์ธ์ฆ ์ฒ˜๋ฆฌ ์„œ๋น„์Šค (auth_service, social_login_service)
โ”‚   โ”œโ”€โ”€ home/
โ”‚   โ”‚   โ”œโ”€โ”€ models/              # CalendarEvent ๋ชจ๋ธ
โ”‚   โ”‚   โ”œโ”€โ”€ widgets/             # ์ผ์ • ์•„์ดํ…œ ์œ„์ ฏ, CRUD ๋ฐ”ํ†ฐ์‹œํŠธ ๋‹ค์ด์–ผ๋กœ๊ทธ
โ”‚   โ”‚   โ”œโ”€โ”€ services/            # calendar_service (์ผ์ • CRUD, ์™„๋ฃŒ ํ† ๊ธ€), holiday_service (๊ณตํœด์ผ)
โ”‚   โ”‚   โ””โ”€โ”€ screens/             # home_screen (๋ฉ”์ธ ๋Œ€์‹œ๋ณด๋“œ), calendar_screen (TableCalendar ํ™”๋ฉด)
โ”‚   โ”œโ”€โ”€ main_navigation/
โ”‚   โ”‚   โ””โ”€โ”€ screens/             # ๋ฉ”์ธ ํ•˜๋‹จ ๋„ค๋น„๊ฒŒ์ด์…˜ ์…ธ ์ฝ˜ํ…์ŠคํŠธ (MainScreen)
โ”‚   โ”œโ”€โ”€ profile/
โ”‚   โ”‚   โ””โ”€โ”€ screens/             # ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์นด๋“œ ์กฐํšŒ, ๋น„๋ฐ€๋ฒˆํ˜ธ/์ด๋ฉ”์ผ ๋ณ€๊ฒฝ, ์ง๋ฌด ํ™˜๊ฒฝ ์„ค์ •
โ”‚   โ”œโ”€โ”€ record/
โ”‚   โ”‚   โ”œโ”€โ”€ models/              # ํšŒ์˜๋ก ์ •๋ณด ๋ฐ์ดํ„ฐ ์ „์†ก ๊ฐ์ฒด (Log, LogDetail)
โ”‚   โ”‚   โ”œโ”€โ”€ services/            # log_service (ํšŒ์˜ ์ผ์ง€ ์กฐํšŒ, ๊ฐœ๋ณ„ ๋””ํ…Œ์ผ ๋กœ๋“œ, ๋ฉ”๋ชจ ๋ณด์กด API)
โ”‚   โ”‚   โ””โ”€โ”€ screens/             # record_screen (์˜ค๋Š˜/ํŠน์ •๋‚ ์งœ ์—…๋ฌด ๊ธฐ๋ก ๋ฆฌ์ŠคํŠธ), summary_screen (ํšŒ์˜๋ก ์ƒ์„ธ ๋ฐ ๋ฉ”๋ชจ)
โ”‚   โ”œโ”€โ”€ remaster/
โ”‚   โ”‚   โ”œโ”€โ”€ services/            # remaster_service (์Œ์„ฑ ์—…๋กœ๋“œ ๋ฐ ๋ณด์ • ํ…์ŠคํŠธ ํš๋“)
โ”‚   โ”‚   โ””โ”€โ”€ screens/             # remaster_screen (AI ๋ฌธ์žฅ ๊ต์ • ๋ฉ”์ธ ์ธํ„ฐํŽ˜์ด์Šค), expand_text_screens (ํฐํŠธ ์คŒ์ธ ํ™”๋ฉด)
โ”‚   โ”œโ”€โ”€ roleplay/
โ”‚   โ”‚   โ””โ”€โ”€ screens/             # roleplay_list_screen (์‹ค์‹œ๊ฐ„ ์Œ์„ฑ ์ž๋™๊ฐ์ง€ AI ๋ฐœํ™” ์ถ”์ฒœ๊ธฐ)
โ”‚   โ”œโ”€โ”€ template/
โ”‚   โ”‚   โ””โ”€โ”€ screens/             # template_screen (์ง๋ฌด ์ƒํ™ฉ๊ทน ์ง„์ž…๋กœ), 4๋Œ€ ์ง๋ฌด ์ƒํ™ฉ ๋ชจ์˜ ํ™”๋ฉด (Order, Product, Report, Call)
โ”‚   โ””โ”€โ”€ voice_settings/
โ”‚       โ””โ”€โ”€ screens/             # voice_register_screen (์‚ฌ์šฉ์ž AI ์Œ์„ฑ ํ”„๋กœํ•„ ์žฌ๋“ฑ๋ก ์—”์ง„)
โ””โ”€โ”€ main.dart                    # ์•ฑ์˜ ๋ถ€ํŒ… ๋ฐ ์ „์—ญ ์ƒํƒœ(์ธ์ฆ ํ† ํฐ ๊ธฐ๋ฐ˜ ์ดˆ๊ธฐ ์ง„๋กœ ์ฒดํฌ, ko_KR ๋กœ์ผ€์ผ) ์„ค์ • ์—”ํŠธ๋ฆฌํฌ์ธํŠธ

๐Ÿš€ ์‹œ์ž‘ํ•˜๊ธฐ ๋ฐ ์‹คํ–‰ ๋ฐฉ๋ฒ• (Getting Started)

Prerequisites

  • Flutter SDK ์„ค์น˜ (Dart SDK 3.9.2 ๋ฐ Flutter 3.29.x ์ด์ƒ ๊ถŒ์žฅ)
  • ๋ฌผ๋ฆฌ ๋ชจ๋ฐ”์ผ ๋””๋ฐ”์ด์Šค ๋˜๋Š” ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ / ์—๋ฎฌ๋ ˆ์ดํ„ฐ ํ™˜๊ฒฝ
  • ์นด์นด์˜ค ๊ฐœ๋ฐœ์ž ์ฝ˜์†” ๋ฐ Google Cloud Console์— ๊ธฐ๊ธฐ ํ”Œ๋žซํผ๋ณ„ ํŒจํ‚ค์ง€๋ช…(Android: com.example.malbit_frontend, iOS BundleID) ๋ฐ OAuth ํ‚ค ํ•ด์‹œ ์‚ฌ์ „ ๋“ฑ๋ก ์™„๋ฃŒ ํ•„์ˆ˜.

Installation

  1. Repository Clone

    git clone https://github.com/your-username/malbit_frontend.git
    cd malbit_frontend
  2. Flutter ํŒจํ‚ค์ง€ ์˜์กด์„ฑ ํ•ด๊ฒฐ

    flutter pub get
  3. ํ”Œ๋žซํผ๋ณ„ ์ดˆ๊ธฐํ™” ๊ฒ€์ฆ

    • Android: /android/local.properties์— Flutter SDK ๊ฒฝ๋กœ๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
    • iOS: CocoaPods ํ™˜๊ฒฝ ์„ค์น˜ ๋ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—ฐ๋™ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
      cd ios
      pod install
      cd ..
  4. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋””๋ฒ„๊ทธ ๋ชจ๋“œ ์‹คํ–‰

    flutter run
  5. Release ๋นŒ๋“œ ๋ฐฐํฌ๋ณธ ์ž‘์„ฑ

    • Android (APK)
      flutter build apk --release
    • iOS (App Bundle)
      flutter build ipa --release

๐Ÿ”’ ๋ผ์ด์„ ์Šค ๋ฐ ์œ ์˜์‚ฌํ•ญ

  • ๋ณธ ํ”„๋กœ์ ํŠธ๋Š” ์ƒ์—…์  ๋ฐฐํฌ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฉฐ ์™ธ๋ถ€ ๋ฆด๋ฆฌ์ฆˆ๋ฅผ ์ œํ•œํ•˜๋Š” publish_to: 'none' ์†์„ฑ์ด ์„ ์–ธ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • Kakao SDK ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ถ€๋ถ„์ด ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ๋นŒ๋“œ ์ „ main.dart ํŒŒ์ผ ๋‚ด์˜ nativeAppKey์™€ ํ”Œ๋žซํผ ๋„ค์ดํ‹ฐ๋ธŒ ์ˆ˜์ค€์˜ ์—ฐ๋™ ์„ค์ •(Kakao Scheme)์„ ํ™•์ธํ•ด ์ฃผ์‹ญ์‹œ์˜ค.
  • ๋งˆ์ดํฌ ์บก์ฒ˜(record) ๋ฐ ์‹ค์‹œ๊ฐ„ ์Œ์„ฑ์ธ์‹(speech_to_text) ์‚ฌ์šฉ์„ ์œ„ํ•ด ๋””๋ฐ”์ด์Šค ํ”Œ๋žซํผ ์„ค์ • ํŒŒ์ผ(AndroidManifest.xml, Info.plist)์˜ ๊ถŒํ•œ ํš๋“ ์ŠคํŽ™ ๊ธฐ์ˆ ์„ ์ค€์ˆ˜ํ•ด์•ผ ์ •์ƒ์ ์ธ ๋Ÿฐํƒ€์ž„ ๋™์ž‘์„ ๋ณด์žฅ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors