M
MLOG
2025๋…„ 8์›” 18์ผํ•œ๊ตญ์–ด

์œ ์ง€๋ณด์ˆ˜์™€ ํ™•์žฅ์ด ์šฉ์ดํ•œ ํ”„๋ก ํŠธ์—”๋“œ ์•ฑ์„ ์œ„ํ•œ ํ—ฅ์‚ฌ๊ณ ๋‚  ๋ฐ ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜๋ฅผ ํƒ์ƒ‰ํ•˜์„ธ์š”. ์›์น™, ์ด์ , ์‹ค์ œ ๊ตฌํ˜„ ์ „๋žต์„ ์•Œ์•„๋ด…๋‹ˆ๋‹ค.

ํ”„๋ก ํŠธ์—”๋“œ ์•„ํ‚คํ…์ฒ˜: ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•œ ํ—ฅ์‚ฌ๊ณ ๋‚  ๋ฐ ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜

ํ”„๋ก ํŠธ์—”๋“œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ณต์žกํ•ด์ง์— ๋”ฐ๋ผ, ์ž˜ ์ •์˜๋œ ์•„ํ‚คํ…์ฒ˜๋Š” ์œ ์ง€๋ณด์ˆ˜์„ฑ, ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ, ํ™•์žฅ์„ฑ์„ ์œ„ํ•ด ๋งค์šฐ ์ค‘์š”ํ•ด์กŒ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋‘ ๊ฐ€์ง€ ์ธ๊ธฐ ์žˆ๋Š” ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด์€ ํ—ฅ์‚ฌ๊ณ ๋‚  ์•„ํ‚คํ…์ฒ˜(ํฌํŠธ์™€ ์–ด๋Œ‘ํ„ฐ๋ผ๊ณ ๋„ ํ•จ)์™€ ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜์ž…๋‹ˆ๋‹ค. ๋ฐฑ์—”๋“œ ์„ธ๊ณ„์—์„œ ์‹œ์ž‘๋˜์—ˆ์ง€๋งŒ, ์ด๋Ÿฌํ•œ ์›์น™๋“ค์€ ๊ฒฌ๊ณ ํ•˜๊ณ  ์ ์‘์„ฑ ๋†’์€ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์— ํšจ๊ณผ์ ์œผ๋กœ ์ ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ”„๋ก ํŠธ์—”๋“œ ์•„ํ‚คํ…์ฒ˜๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

ํ”„๋ก ํŠธ์—”๋“œ ์•„ํ‚คํ…์ฒ˜๋Š” ํ”„๋ก ํŠธ์—”๋“œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‚ด์˜ ๋‹ค์–‘ํ•œ ๊ตฌ์„ฑ ์š”์†Œ์˜ ๊ตฌ์กฐ, ์กฐ์ง ๋ฐ ์ƒํ˜ธ ์ž‘์šฉ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์–ด๋–ป๊ฒŒ ๊ตฌ์ถ•, ์œ ์ง€๋ณด์ˆ˜, ํ™•์žฅ๋˜๋Š”์ง€์— ๋Œ€ํ•œ ์ฒญ์‚ฌ์ง„์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ข‹์€ ํ”„๋ก ํŠธ์—”๋“œ ์•„ํ‚คํ…์ฒ˜๋Š” ๋‹ค์Œ์„ ์ด‰์ง„ํ•ฉ๋‹ˆ๋‹ค:

  • ์œ ์ง€๋ณด์ˆ˜์„ฑ: ์ฝ”๋“œ๋ฅผ ๋” ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ณ , ์ˆ˜์ •ํ•˜๊ณ , ๋””๋ฒ„๊น…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ: ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์™€ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ์„ ์šฉ์ดํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
  • ํ™•์žฅ์„ฑ: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ฆ๊ฐ€ํ•˜๋Š” ๋ณต์žก์„ฑ๊ณผ ์‚ฌ์šฉ์ž ๋ถ€ํ•˜๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
  • ์žฌ์‚ฌ์šฉ์„ฑ: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์—ฌ๋Ÿฌ ๋ถ€๋ถ„์—์„œ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ ์ด‰์ง„ํ•ฉ๋‹ˆ๋‹ค.
  • ์œ ์—ฐ์„ฑ: ๋ณ€ํ™”ํ•˜๋Š” ์š”๊ตฌ์‚ฌํ•ญ๊ณผ ์ƒˆ๋กœ์šด ๊ธฐ์ˆ ์— ์ ์‘ํ•ฉ๋‹ˆ๋‹ค.

๋ช…ํ™•ํ•œ ์•„ํ‚คํ…์ฒ˜๊ฐ€ ์—†์œผ๋ฉด ํ”„๋ก ํŠธ์—”๋“œ ํ”„๋กœ์ ํŠธ๋Š” ๋น ๋ฅด๊ฒŒ ๋ชจ๋†€๋ฆฌ์‹ ๊ตฌ์กฐ๊ฐ€ ๋˜์–ด ๊ด€๋ฆฌ๊ฐ€ ์–ด๋ ค์›Œ์ง€๊ณ , ๊ฐœ๋ฐœ ๋น„์šฉ ์ฆ๊ฐ€์™€ ๋ฏผ์ฒฉ์„ฑ ๊ฐ์†Œ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ—ฅ์‚ฌ๊ณ ๋‚  ์•„ํ‚คํ…์ฒ˜ ์†Œ๊ฐœ

Alistair Cockburn์ด ์ œ์•ˆํ•œ ํ—ฅ์‚ฌ๊ณ ๋‚  ์•„ํ‚คํ…์ฒ˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, UI ํ”„๋ ˆ์ž„์›Œํฌ, ์„œ๋“œํŒŒํ‹ฐ API์™€ ๊ฐ™์€ ์™ธ๋ถ€ ์ข…์†์„ฑ์œผ๋กœ๋ถ€ํ„ฐ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํฌํŠธ์™€ ์–ด๋Œ‘ํ„ฐ๋ผ๋Š” ๊ฐœ๋…์„ ํ†ตํ•ด ๋‹ฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

ํ—ฅ์‚ฌ๊ณ ๋‚  ์•„ํ‚คํ…์ฒ˜์˜ ํ•ต์‹ฌ ๊ฐœ๋…:

  • ์ฝ”์–ด (๋„๋ฉ”์ธ): ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ์œ ์Šค ์ผ€์ด์Šค๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ์™ธ๋ถ€ ํ”„๋ ˆ์ž„์›Œํฌ๋‚˜ ๊ธฐ์ˆ ๋กœ๋ถ€ํ„ฐ ๋…๋ฆฝ์ ์ž…๋‹ˆ๋‹ค.
  • ํฌํŠธ: ์ฝ”์–ด๊ฐ€ ์™ธ๋ถ€ ์„ธ๊ณ„์™€ ์–ด๋–ป๊ฒŒ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š”์ง€๋ฅผ ์ •์˜ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ž…๋‹ˆ๋‹ค. ์ฝ”์–ด์˜ ์ž…๋ ฅ ๋ฐ ์ถœ๋ ฅ ๊ฒฝ๊ณ„๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • ์–ด๋Œ‘ํ„ฐ: ์ฝ”์–ด๋ฅผ ํŠน์ • ์™ธ๋ถ€ ์‹œ์Šคํ…œ์— ์—ฐ๊ฒฐํ•˜๋Š” ํฌํŠธ์˜ ๊ตฌํ˜„์ฒด์ž…๋‹ˆ๋‹ค. ๋‘ ๊ฐ€์ง€ ์œ ํ˜•์˜ ์–ด๋Œ‘ํ„ฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค:
    • ์ฃผ๋„ ์–ด๋Œ‘ํ„ฐ (Primary Adapters): ์ฝ”์–ด์™€์˜ ์ƒํ˜ธ ์ž‘์šฉ์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ์‹œ๋กœ๋Š” UI ์ปดํฌ๋„ŒํŠธ, ๋ช…๋ น์ค„ ์ธํ„ฐํŽ˜์ด์Šค ๋˜๋Š” ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.
    • ํ”ผ์ฃผ๋„ ์–ด๋Œ‘ํ„ฐ (Secondary Adapters): ์ฝ”์–ด์— ์˜ํ•ด ํ˜ธ์ถœ๋˜์–ด ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ ์ƒํ˜ธ ์ž‘์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ์‹œ๋กœ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, API ๋˜๋Š” ํŒŒ์ผ ์‹œ์Šคํ…œ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ฝ”์–ด๋Š” ํŠน์ • ์–ด๋Œ‘ํ„ฐ์— ๋Œ€ํ•ด ์•„๋ฌด๊ฒƒ๋„ ์•Œ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ์˜ค์ง ํฌํŠธ๋ฅผ ํ†ตํ•ด์„œ๋งŒ ์–ด๋Œ‘ํ„ฐ์™€ ์ƒํ˜ธ ์ž‘์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋””์ปคํ”Œ๋ง์„ ํ†ตํ•ด ์ฝ”์–ด ๋กœ์ง์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ์–ด๋Œ‘ํ„ฐ๋ฅผ ์‰ฝ๊ฒŒ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ฃผ๋„ ์–ด๋Œ‘ํ„ฐ๋ฅผ ๊ต์ฒดํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ํ•œ UI ํ”„๋ ˆ์ž„์›Œํฌ(์˜ˆ: React)์—์„œ ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ(์˜ˆ: Vue.js)๋กœ ์ „ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ—ฅ์‚ฌ๊ณ ๋‚  ์•„ํ‚คํ…์ฒ˜์˜ ์ด์ :

  • ํ–ฅ์ƒ๋œ ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ: ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์™ธ๋ถ€ ์ข…์†์„ฑ์— ์˜์กดํ•˜์ง€ ์•Š๊ณ  ๊ฒฉ๋ฆฌํ•˜์—ฌ ์‰ฝ๊ฒŒ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ์˜ ์–ด๋Œ‘ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์™ธ๋ถ€ ์‹œ์Šคํ…œ์˜ ๋™์ž‘์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ฆ๊ฐ€๋œ ์œ ์ง€๋ณด์ˆ˜์„ฑ: ์™ธ๋ถ€ ์‹œ์Šคํ…œ์˜ ๋ณ€๊ฒฝ์ด ์ฝ”์–ด ๋กœ์ง์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ์„ ์ตœ์†Œํ™”ํ•ฉ๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ณ  ๋ฐœ์ „์‹œํ‚ค๊ธฐ ๋” ์‰ฌ์›Œ์ง‘๋‹ˆ๋‹ค.
  • ๋” ํฐ ์œ ์—ฐ์„ฑ: ์–ด๋Œ‘ํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๊ต์ฒดํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ƒˆ๋กœ์šด ๊ธฐ์ˆ ๊ณผ ์š”๊ตฌ์‚ฌํ•ญ์— ์‰ฝ๊ฒŒ ์ ์‘์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํ–ฅ์ƒ๋œ ์žฌ์‚ฌ์šฉ์„ฑ: ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋‹ค๋ฅธ ์–ด๋Œ‘ํ„ฐ์— ์—ฐ๊ฒฐํ•˜์—ฌ ๋‹ค์–‘ํ•œ ์ปจํ…์ŠคํŠธ์—์„œ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜ ์†Œ๊ฐœ

Robert C. Martin (Uncle Bob)์— ์˜ํ•ด ๋Œ€์ค‘ํ™”๋œ ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜๋Š” ๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ์™€ ๋””์ปคํ”Œ๋ง์„ ๊ฐ•์กฐํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด์ž…๋‹ˆ๋‹ค. ์ด๋Š” ํ”„๋ ˆ์ž„์›Œํฌ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, UI ๋ฐ ๋ชจ๋“  ์™ธ๋ถ€ ์š”์†Œ๋กœ๋ถ€ํ„ฐ ๋…๋ฆฝ์ ์ธ ์‹œ์Šคํ…œ์„ ๋งŒ๋“œ๋Š” ๋ฐ ์ค‘์ ์„ ๋‘ก๋‹ˆ๋‹ค.

ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜์˜ ํ•ต์‹ฌ ๊ฐœ๋…:

ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋™์‹ฌ์› ๊ณ„์ธต์œผ๋กœ ๊ตฌ์„ฑํ•˜๋ฉฐ, ๊ฐ€์žฅ ์ถ”์ƒ์ ์ด๊ณ  ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ๋Š” ์ค‘์•™์—, ๊ฐ€์žฅ ๊ตฌ์ฒด์ ์ด๊ณ  ๊ธฐ์ˆ ์— ํŠนํ™”๋œ ์ฝ”๋“œ๋Š” ์™ธ๋ถ€ ๊ณ„์ธต์— ์œ„์น˜ํ•ฉ๋‹ˆ๋‹ค.

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

ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜์˜ ์˜์กด์„ฑ ๊ทœ์น™์€ ์™ธ๋ถ€ ๊ณ„์ธต์ด ๋‚ด๋ถ€ ๊ณ„์ธต์— ์˜์กดํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ๋‚ด๋ถ€ ๊ณ„์ธต์€ ์™ธ๋ถ€ ๊ณ„์ธต์— ์˜์กดํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ๋ช…์‹œํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ์™ธ๋ถ€ ํ”„๋ ˆ์ž„์›Œํฌ๋‚˜ ๊ธฐ์ˆ ๋กœ๋ถ€ํ„ฐ ๋…๋ฆฝ์ ์ž„์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜์˜ ์ด์ :

  • ํ”„๋ ˆ์ž„์›Œํฌ๋กœ๋ถ€ํ„ฐ ๋…๋ฆฝ์ : ์•„ํ‚คํ…์ฒ˜๋Š” ๊ธฐ๋Šฅ์ด ํ’๋ถ€ํ•œ ์†Œํ”„ํŠธ์›จ์–ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์กด์žฌ์— ์˜์กดํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋„๊ตฌ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์‹œ์Šคํ…œ์„ ํ”„๋ ˆ์ž„์›Œํฌ์˜ ์ œํ•œ๋œ ์ œ์•ฝ์— ์–ต์ง€๋กœ ๋งž์ถœ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
  • ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ: ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™์€ UI, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, ์›น ์„œ๋ฒ„ ๋˜๋Š” ๋‹ค๋ฅธ ์™ธ๋ถ€ ์š”์†Œ ์—†์ด ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • UI๋กœ๋ถ€ํ„ฐ ๋…๋ฆฝ์ : UI๋Š” ์‹œ์Šคํ…œ์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ ๋„ ์‰ฝ๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์›น UI๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ์ฝ˜์†” UI๋กœ ๋Œ€์ฒด๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋กœ๋ถ€ํ„ฐ ๋…๋ฆฝ์ : Oracle์ด๋‚˜ SQL Server๋ฅผ Mongo, BigTable, CouchDB ๋˜๋Š” ๋‹ค๋ฅธ ๊ฒƒ์œผ๋กœ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์–ฝ๋งค์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ๋ชจ๋“  ์™ธ๋ถ€ ์š”์†Œ๋กœ๋ถ€ํ„ฐ ๋…๋ฆฝ์ : ์‹ค์ œ๋กœ ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™์€ ์™ธ๋ถ€ ์„ธ๊ณ„์— ๋Œ€ํ•ด *์•„๋ฌด๊ฒƒ๋„* ์•Œ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์— ํ—ฅ์‚ฌ๊ณ ๋‚  ๋ฐ ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜ ์ ์šฉํ•˜๊ธฐ

ํ—ฅ์‚ฌ๊ณ ๋‚  ์•„ํ‚คํ…์ฒ˜์™€ ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜๋Š” ์ข…์ข… ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ๊ณผ ์—ฐ๊ด€๋˜์ง€๋งŒ, ๊ทธ ์›์น™๋“ค์€ ํ”„๋ก ํŠธ์—”๋“œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์•„ํ‚คํ…์ฒ˜์™€ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด ํšจ๊ณผ์ ์œผ๋กœ ์ ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

1. ์ฝ”์–ด(๋„๋ฉ”์ธ) ์‹๋ณ„ํ•˜๊ธฐ

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

์˜ˆ์‹œ: ์ž‘์—… ๊ด€๋ฆฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ฝ”์–ด ๋„๋ฉ”์ธ์€ ๋‹ค์Œ์œผ๋กœ ๊ตฌ์„ฑ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • ์—”ํ‹ฐํ‹ฐ: Task(์ž‘์—…), Project(ํ”„๋กœ์ ํŠธ), User(์‚ฌ์šฉ์ž)
  • ์œ ์Šค ์ผ€์ด์Šค: CreateTask(์ž‘์—… ์ƒ์„ฑ), UpdateTask(์ž‘์—… ์ˆ˜์ •), AssignTask(์ž‘์—… ํ• ๋‹น), CompleteTask(์ž‘์—… ์™„๋ฃŒ), ListTasks(์ž‘์—… ๋ชฉ๋ก ์กฐํšŒ)
  • ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™: ์ž‘์—…์€ ์ œ๋ชฉ์ด ์žˆ์–ด์•ผ ํ•˜๋ฉฐ, ํ”„๋กœ์ ํŠธ์˜ ๋ฉค๋ฒ„๊ฐ€ ์•„๋‹Œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ž‘์—…์„ ํ• ๋‹นํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

2. ํฌํŠธ์™€ ์–ด๋Œ‘ํ„ฐ(ํ—ฅ์‚ฌ๊ณ ๋‚  ์•„ํ‚คํ…์ฒ˜) ๋˜๋Š” ๊ณ„์ธต(ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜) ์ •์˜ํ•˜๊ธฐ

๋‹ค์Œ์œผ๋กœ, ์ฝ”์–ด๋ฅผ ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ ๋ถ„๋ฆฌํ•˜๋Š” ํฌํŠธ์™€ ์–ด๋Œ‘ํ„ฐ(ํ—ฅ์‚ฌ๊ณ ๋‚  ์•„ํ‚คํ…์ฒ˜) ๋˜๋Š” ๊ณ„์ธต(ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜)์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ํ”„๋ก ํŠธ์—”๋“œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒƒ๋“ค์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • UI ์ปดํฌ๋„ŒํŠธ (์ฃผ๋„ ์–ด๋Œ‘ํ„ฐ/ํ”„๋ ˆ์ž„์›Œํฌ ๋ฐ ๋“œ๋ผ์ด๋ฒ„): ์‚ฌ์šฉ์ž์™€ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š” React, Vue.js, Angular ์ปดํฌ๋„ŒํŠธ.
  • API ํด๋ผ์ด์–ธํŠธ (ํ”ผ์ฃผ๋„ ์–ด๋Œ‘ํ„ฐ/์ธํ„ฐํŽ˜์ด์Šค ์–ด๋Œ‘ํ„ฐ): ๋ฐฑ์—”๋“œ API์— ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ์„œ๋น„์Šค.
  • ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ (ํ”ผ์ฃผ๋„ ์–ด๋Œ‘ํ„ฐ/์ธํ„ฐํŽ˜์ด์Šค ์–ด๋Œ‘ํ„ฐ): ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€, IndexedDB ๋˜๋Š” ๊ธฐํƒ€ ๋ฐ์ดํ„ฐ ์ €์žฅ ๋ฉ”์ปค๋‹ˆ์ฆ˜.
  • ์ƒํƒœ ๊ด€๋ฆฌ (์ธํ„ฐํŽ˜์ด์Šค ์–ด๋Œ‘ํ„ฐ): Redux, Vuex ๋˜๋Š” ๊ธฐํƒ€ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ.

ํ—ฅ์‚ฌ๊ณ ๋‚  ์•„ํ‚คํ…์ฒ˜ ์‚ฌ์šฉ ์˜ˆ์‹œ:

  • ์ฝ”์–ด: ์ž‘์—… ๊ด€๋ฆฌ ๋กœ์ง (์—”ํ‹ฐํ‹ฐ, ์œ ์Šค ์ผ€์ด์Šค, ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™).
  • ํฌํŠธ: TaskService (์ž‘์—… ์ƒ์„ฑ, ์ˆ˜์ •, ์กฐํšŒ๋ฅผ ์œ„ํ•œ ๋ฉ”์„œ๋“œ ์ •์˜).
  • ์ฃผ๋„ ์–ด๋Œ‘ํ„ฐ: TaskService๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฝ”์–ด์™€ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š” React ์ปดํฌ๋„ŒํŠธ.
  • ํ”ผ์ฃผ๋„ ์–ด๋Œ‘ํ„ฐ: TaskService๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ๋ฐฑ์—”๋“œ API์— ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” API ํด๋ผ์ด์–ธํŠธ.

ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜ ์‚ฌ์šฉ ์˜ˆ์‹œ:

  • ์—”ํ‹ฐํ‹ฐ: Task, Project, User (์ˆœ์ˆ˜ JavaScript ๊ฐ์ฒด).
  • ์œ ์Šค ์ผ€์ด์Šค: CreateTaskUseCase, UpdateTaskUseCase (์—”ํ‹ฐํ‹ฐ ์กฐ์œจ).
  • ์ธํ„ฐํŽ˜์ด์Šค ์–ด๋Œ‘ํ„ฐ:
    • ์ปจํŠธ๋กค๋Ÿฌ: UI๋กœ๋ถ€ํ„ฐ์˜ ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ์ฒ˜๋ฆฌ.
    • ํ”„๋ ˆ์  ํ„ฐ: UI์— ํ‘œ์‹œํ•  ๋ฐ์ดํ„ฐ๋ฅผ ํฌ๋งท.
    • ๊ฒŒ์ดํŠธ์›จ์ด: API ํด๋ผ์ด์–ธํŠธ์™€ ์ƒํ˜ธ ์ž‘์šฉ.
  • ํ”„๋ ˆ์ž„์›Œํฌ ๋ฐ ๋“œ๋ผ์ด๋ฒ„: React ์ปดํฌ๋„ŒํŠธ, API ํด๋ผ์ด์–ธํŠธ (axios, fetch).

3. ์–ด๋Œ‘ํ„ฐ(ํ—ฅ์‚ฌ๊ณ ๋‚  ์•„ํ‚คํ…์ฒ˜) ๋˜๋Š” ๊ณ„์ธต(ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜) ๊ตฌํ˜„ํ•˜๊ธฐ

์ด์ œ ์ฝ”์–ด๋ฅผ ์™ธ๋ถ€ ์‹œ์Šคํ…œ์— ์—ฐ๊ฒฐํ•˜๋Š” ์–ด๋Œ‘ํ„ฐ๋‚˜ ๊ณ„์ธต์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ์–ด๋Œ‘ํ„ฐ๋‚˜ ๊ณ„์ธต์ด ์ฝ”์–ด๋กœ๋ถ€ํ„ฐ ๋…๋ฆฝ์ ์ธ์ง€, ๊ทธ๋ฆฌ๊ณ  ์ฝ”์–ด๊ฐ€ ์˜ค์ง ํฌํŠธ๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด์„œ๋งŒ ์ด๋“ค๊ณผ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. ์ด๋ฅผ ํ†ตํ•ด ์ฝ”์–ด ๋กœ์ง์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ์–ด๋Œ‘ํ„ฐ๋‚˜ ๊ณ„์ธต์„ ์‰ฝ๊ฒŒ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ (ํ—ฅ์‚ฌ๊ณ ๋‚  ์•„ํ‚คํ…์ฒ˜):


// TaskService ํฌํŠธ
interface TaskService {
  createTask(taskData: TaskData): Promise;
  updateTask(taskId: string, taskData: TaskData): Promise;
  getTask(taskId: string): Promise;
}

// API ํด๋ผ์ด์–ธํŠธ ์–ด๋Œ‘ํ„ฐ
class ApiTaskService implements TaskService {
  async createTask(taskData: TaskData): Promise {
    // ํƒœ์Šคํฌ ์ƒ์„ฑ์„ ์œ„ํ•œ API ์š”์ฒญ
  }

  async updateTask(taskId: string, taskData: TaskData): Promise {
    // ํƒœ์Šคํฌ ์ˆ˜์ •์„ ์œ„ํ•œ API ์š”์ฒญ
  }

  async getTask(taskId: string): Promise {
    // ํƒœ์Šคํฌ ์กฐํšŒ๋ฅผ ์œ„ํ•œ API ์š”์ฒญ
  }
}

// React ์ปดํฌ๋„ŒํŠธ ์–ด๋Œ‘ํ„ฐ
function TaskList() {
  const taskService: TaskService = new ApiTaskService();

  const handleCreateTask = async (taskData: TaskData) => {
    await taskService.createTask(taskData);
    // ํƒœ์Šคํฌ ๋ชฉ๋ก ์—…๋ฐ์ดํŠธ
  };

  // ...
}

์˜ˆ์‹œ (ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜):


// ์—”ํ‹ฐํ‹ฐ
class Task {
  constructor(public id: string, public title: string, public description: string) {}
}

// ์œ ์Šค ์ผ€์ด์Šค
class CreateTaskUseCase {
  constructor(private taskGateway: TaskGateway) {}

  async execute(title: string, description: string): Promise {
    const task = new Task(generateId(), title, description);
    await this.taskGateway.create(task);
    return task;
  }
}

// ์ธํ„ฐํŽ˜์ด์Šค ์–ด๋Œ‘ํ„ฐ - ๊ฒŒ์ดํŠธ์›จ์ด
interface TaskGateway {
  create(task: Task): Promise;
}

class ApiTaskGateway implements TaskGateway {
  async create(task: Task): Promise {
    // ํƒœ์Šคํฌ ์ƒ์„ฑ์„ ์œ„ํ•œ API ์š”์ฒญ
  }
}

// ์ธํ„ฐํŽ˜์ด์Šค ์–ด๋Œ‘ํ„ฐ - ์ปจํŠธ๋กค๋Ÿฌ
class TaskController {
  constructor(private createTaskUseCase: CreateTaskUseCase) {}

  async createTask(req: Request, res: Response) {
    const { title, description } = req.body;
    const task = await this.createTaskUseCase.execute(title, description);
    res.json(task);
  }
}

// ํ”„๋ ˆ์ž„์›Œํฌ ๋ฐ ๋“œ๋ผ์ด๋ฒ„ - React ์ปดํฌ๋„ŒํŠธ
function TaskForm() {
  const [title, setTitle] = useState('');
  const [description, setDescription] = useState('');
  const apiTaskGateway = new ApiTaskGateway();
  const createTaskUseCase = new CreateTaskUseCase(apiTaskGateway);
  const taskController = new TaskController(createTaskUseCase);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    await taskController.createTask({ body: { title, description } } as Request, { json: (data: any) => console.log(data) } as Response);
  };

  return (
    
setTitle(e.target.value)} />