๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Vue

AI Chat ์ปดํผ๋„ŒํŠธ ์ฝ”๋“œ ๊ฐœ์„ 

by frontChoi 2026. 8. 3.
๋ฐ˜์‘ํ˜•

 

๐Ÿช Before / After

๊ธฐ์กด AI Chat ์ปดํฌ๋„ŒํŠธ๋Š” UI, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง, API ํ˜ธ์ถœ์ด ํ•˜๋‚˜์˜ ํŒŒ์ผ์— ์ง‘์ค‘๋˜์–ด ์žˆ์–ด ์ฝ”๋“œ์˜ ๋ณต์žก๋„๊ฐ€ ๋†’์•˜์Šต๋‹ˆ๋‹ค. ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋ ์ˆ˜๋ก ์œ ์ง€๋ณด์ˆ˜ ๋น„์šฉ์ด ์ฆ๊ฐ€ํ•˜๊ณ , ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ ์šฉํ•˜๊ฑฐ๋‚˜ ๋ฒ„๊ทธ๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์— ์˜ํ–ฅ์„ ์ค„ ๊ฐ€๋Šฅ์„ฑ์ด ์กด์žฌํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฒˆ ๋ฆฌํŒฉํ† ๋ง์—์„œ๋Š” ์—ญํ• ์„ ๋ช…ํ™•ํ•˜๊ฒŒ ๋ถ„๋ฆฌํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ๋Š” ํ™”๋ฉด(View)๋งŒ ๋‹ด๋‹นํ•˜๋„๋ก ๋ณ€๊ฒฝํ•˜์˜€๊ณ , ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ API ํ˜ธ์ถœ์„ ๊ฐ๊ฐ ๋…๋ฆฝ์ ์ธ ๋ชจ๋“ˆ๋กœ ๋ถ„๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ์ฝ”๋“œ ๋ผ์ธ ๊ฐ์†Œ
    • 1534 → 358 Line
    • ์ด 1,176 Line ๊ฐ์†Œ(์•ฝ 77%)
  • ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‹ด๋‹นํ•˜๋˜ ์ฑ…์ž„์„ ์—ฌ๋Ÿฌ ๋ชจ๋“ˆ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ํ–ฅ์ƒ
  • ๊ธฐ๋Šฅ ์ถ”๊ฐ€ ์‹œ ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๋ฒ”์œ„๋ฅผ ์ตœ์†Œํ™”ํ•˜๋„๋ก ๊ตฌ์กฐ ๊ฐœ์„ 

๐ŸŽฑ AI Chat์˜ ์—ญํ• 

AI Chat์€ ๋‹จ์ˆœํ•œ ์ฑ„ํŒ… UI๊ฐ€ ์•„๋‹ˆ๋ผ ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์— ๋”ฐ๋ผ ๋‹ค์–‘ํ•œ AI ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํ•ต์‹ฌ ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค.

์ฃผ์š” ๊ธฐ๋Šฅ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • AI ์ฑ„๋„ ์ƒ์„ฑ
  • ์Œ์•… ํ๋ ˆ์ด์…˜
  • AI CM Song ์ƒ์„ฑ
  • ์‚ฌ์šฉ์ž์™€ AI ๊ฐ„ ๋ฉ”์‹œ์ง€ ๊ด€๋ฆฌ
  • AI ์‘๋‹ต ์ƒํƒœ ๋ฐ ์ง„ํ–‰ ๊ณผ์ • ๊ด€๋ฆฌ

์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ์ด ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ์— ์ง‘์ค‘๋˜์–ด ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ง€์†์ ์ธ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ ๊ณผ์ •์—์„œ ์ฝ”๋“œ ๋ณต์žก๋„๊ฐ€ ์ฆ๊ฐ€ํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.


๐Ÿชƒ ๊ธฐ์กด ์ด์Šˆ

1. View์™€ Business Logic์˜ ๊ฒฐํ•ฉ

๊ธฐ์กด์—๋Š” ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ

  • API ํ˜ธ์ถœ
  • ์‘๋‹ต ๋ฐ์ดํ„ฐ ๊ฐ€๊ณต
  • ์ƒํƒœ ๊ด€๋ฆฌ
  • ํ™”๋ฉด ๋ Œ๋”๋ง

๋ชจ๋“  ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๋กœ ์ธํ•ด ํ™”๋ฉด ์ˆ˜์ •๋งŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋„ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ํ•จ๊ป˜ ํ™•์ธํ•ด์•ผ ํ–ˆ์œผ๋ฉฐ, ์ž‘์€ ์ˆ˜์ •์—๋„ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.


2. Message ๊ตฌ์กฐ๊ฐ€ ์ผ๊ด€๋˜์ง€ ์•Š์Œ

๋ฉ”์‹œ์ง€ ํƒ€์ž…์ด ๊ทœ๊ฒฉํ™”๋˜์–ด ์žˆ์ง€ ์•Š์•„

  • Message๋งˆ๋‹ค ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ์‚ฌ์šฉ
  • ์กฐ๊ฑด๋ฌธ ์ฆ๊ฐ€
  • ์ƒˆ๋กœ์šด Message ํƒ€์ž… ์ถ”๊ฐ€ ์‹œ ๊ธฐ์กด ์ฝ”๋“œ ์ˆ˜์ • ํ•„์š”

๋“ฑ์˜ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ฉ”์‹œ์ง€๊ฐ€ ๋งŽ์•„์งˆ์ˆ˜๋ก ์ฝ”๋“œ์˜ ๋ณต์žก๋„๊ฐ€ ๋น ๋ฅด๊ฒŒ ์ฆ๊ฐ€ํ•˜๋Š” ๊ตฌ์กฐ์˜€์Šต๋‹ˆ๋‹ค.


3. ๋ฌธ์ž์—ด ์ƒ์ˆ˜ ์‚ฌ์šฉ

๋ฉ”์‹œ์ง€ ํƒ€์ž…๊ณผ ์ด๋ฒคํŠธ ์ด๋ฆ„ ๋“ฑ์ด ๋ฌธ์ž์—ด(String Literal)๋กœ ๊ด€๋ฆฌ๋˜๊ณ  ์žˆ์–ด

"TEXT"
"LOADING"
"SONG"

์˜คํƒ€ ํ•˜๋‚˜๋งŒ ๋ฐœ์ƒํ•ด๋„ ๋Ÿฐํƒ€์ž„์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์—ˆ์œผ๋ฉฐ, IDE์˜ ์ž๋™์™„์„ฑ์ด๋‚˜ ํƒ€์ž… ๊ฒ€์ฆ๋„ ํ™œ์šฉํ•˜๊ธฐ ์–ด๋ ค์› ์Šต๋‹ˆ๋‹ค.


๐Ÿ›  ๊ฐœ์„  ์‚ฌํ•ญ

1. ์—ญํ• ๋ณ„ ๋””๋ ‰ํ† ๋ฆฌ ๋ถ„๋ฆฌ

๊ธฐ์กด์—๋Š” ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋Œ€๋ถ€๋ถ„์˜ ์—ญํ• ์„ ๋‹ด๋‹นํ–ˆ์ง€๋งŒ, ๋ฆฌํŒฉํ† ๋ง ์ดํ›„์—๋Š” ๊ฐ ์ฑ…์ž„์„ ๋…๋ฆฝ์ ์ธ ๋ชจ๋“ˆ๋กœ ๋ถ„๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

src
โ”œโ”€โ”€ components
โ”‚   โ””โ”€โ”€ AiChat.vue          // View
โ”œโ”€โ”€ composables
โ”‚   โ””โ”€โ”€ useAiChat.js        // Business Logic
โ”œโ”€โ”€ service/api
โ”‚   โ””โ”€โ”€ aiChatApi.js        // API
โ””โ”€โ”€ shared
    โ”œโ”€โ”€ adapter
    โ”‚   โ””โ”€โ”€ ai-chat.js      // ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜
    โ””โ”€โ”€ factory
        โ””โ”€โ”€ ai-chat.js      // Message ์ƒ์„ฑ

์ด๋ฅผ ํ†ตํ•ด View๋Š” ํ™”๋ฉด ๋ Œ๋”๋ง๋งŒ ๋‹ด๋‹นํ•˜๊ณ , ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ API ํ˜ธ์ถœ์€ ๋…๋ฆฝ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.


2. Business Logic ๋ถ„๋ฆฌ

๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ useAiChat์œผ๋กœ ์ด๋™ํ•˜์—ฌ

  • ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ ํ–ฅ์ƒ
  • View ์ฝ”๋“œ ๋‹จ์ˆœํ™”
  • ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋กœ์ง ๊ตฌ์„ฑ

์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.


3. API ๊ณ„์ธต ๋ถ„๋ฆฌ

API ํ˜ธ์ถœ์„ ๋ณ„๋„์˜ Service Layer๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ

  • API ๋ณ€๊ฒฝ ์‹œ ์ˆ˜์ • ๋ฒ”์œ„ ์ตœ์†Œํ™”
  • Mock API ์ ์šฉ ์šฉ์ด
  • ์œ ์ง€๋ณด์ˆ˜์„ฑ ํ–ฅ์ƒ

ํšจ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.


4. Adapter & Factory ํŒจํ„ด ์ ์šฉ

๋ฉ”์‹œ์ง€ ์ƒ์„ฑ๊ณผ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜์„ ๊ฐ๊ฐ Factory์™€ Adapter๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ

  • Message ์ƒ์„ฑ ๋กœ์ง ์ผ์›ํ™”
  • ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ๋ณ€๊ฒฝ์— ๋Œ€ํ•œ ๋Œ€์‘๋ ฅ ํ–ฅ์ƒ
  • ์ƒˆ๋กœ์šด Message ํƒ€์ž… ์ถ”๊ฐ€ ์‹œ ์˜ํ–ฅ ๋ฒ”์œ„ ์ตœ์†Œํ™”

ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.


5.Strategy Pattern ์ ์šฉ

AI Channel, ์‹œ๊ฐ„๋ณ„ ํ๋ ˆ์ด์…˜, AI CM Song์€ ๋™์ผํ•œ Chat UI๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋ฉ”์‹œ์ง€๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ „์†กํ•˜๋Š” ๋ฐฉ์‹์ด ์„œ๋กœ ๋‹ฌ๋ž์Šต๋‹ˆ๋‹ค.

๊ธฐ์กด์—๋Š” ์„œ๋น„์Šค๋ณ„๋กœ if/else๋ฅผ ํ†ตํ•ด ์ „์†ก ๋กœ์ง์„ ๋ถ„๊ธฐํ–ˆ์ง€๋งŒ, AI ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋ ์ˆ˜๋ก ์กฐ๊ฑด๋ฌธ์ด ์ฆ๊ฐ€ํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋ฉ”์‹œ์ง€ ํƒ€์ž…๋ณ„ Handler๋ฅผ ๋งคํ•‘ํ•˜๋Š” ์ „๋žต(Strategy) ๋ฐฉ์‹์„ ์ ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

constsendHandlerMap= {
  [AI_CHAT_TYPES.AI_CHANNEL]:sendDefaultMessage,
  [AI_CHAT_TYPES.TIME_CURATION]:sendDefaultMessage,
  [AI_CHAT_TYPES.AI_CM_SONG]:sendCmSongMessage
};

sendHandlerMap[type]?.();

์ด ๊ตฌ์กฐ๋ฅผ ํ†ตํ•ด

  • ์กฐ๊ฑด๋ฌธ(if, switch) ์ œ๊ฑฐ
  • ์ „์†ก ๋กœ์ง์„ Handler ๋‹จ์œ„๋กœ ๋ถ„๋ฆฌ
  • ์ƒˆ๋กœ์šด AI ๊ธฐ๋Šฅ์€ Handler๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด ๋˜๋ฏ€๋กœ ๊ธฐ์กด ํ˜ธ์ถœ๋ถ€ ์ˆ˜์ • ๋ถˆํ•„์š”
  • ์œ ์ง€๋ณด์ˆ˜์„ฑ๊ณผ ํ™•์žฅ์„ฑ ํ–ฅ์ƒ

์ด๋ผ๋Š” ํšจ๊ณผ๋ฅผ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค.


๐ŸŽฏ ๊ฐœ์„  ํšจ๊ณผ

  • ์ฝ”๋“œ ๋ผ์ธ 77% ๊ฐ์†Œ (1534 → 358)
  • View / Business Logic / API์˜ ์ฑ…์ž„ ๋ถ„๋ฆฌ
  • ๋ฉ”์‹œ์ง€ ์ƒ์„ฑ ๋ฐฉ์‹ ํ‘œ์ค€ํ™”
  • ์œ ์ง€๋ณด์ˆ˜์„ฑ๊ณผ ๊ฐ€๋…์„ฑ ํ–ฅ์ƒ
  • ๊ธฐ๋Šฅ ์ถ”๊ฐ€ ์‹œ ๋ณ€๊ฒฝ ๋ฒ”์œ„ ์ตœ์†Œํ™”
  • ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ตฌ์กฐ๋กœ ๊ฐœ์„ 
  • ํ™•์žฅ์„ฑ๊ณผ ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ ํ™•๋ณด
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€