๐ŸŒ• ๋ณด๋ฆ„์นผ๋Ÿผ

๋‹จ์ˆœ ๊ธฐ๋ก๋ณด๋‹จ ์ข€ ๋” ์–‘์งˆ์˜, ์ •๋ฆฌ๋œ ๊ธ€์„ ์“ฐ๊ณ ์ž ์‹œ์ž‘ํ•˜๋Š” ๋ณด๋ฆ„์นผ๋Ÿผ
๋ถ€๋‹ด์—†์ด ๋งค ๋ณด๋ฆ„ ํ•˜๋‚˜์˜ ์ฃผ์ œ๋ฅผ ๊นŠ๊ฒŒ ๋“ค์—ฌ๋‹ค๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ธฐํšŒ๊ฐ€ ๋˜์—ˆ์œผ๋ฉด ์ข‹๊ฒ ๋‹ค.

๊ฐ€์ˆ˜ ์œค์ข…์‹ ๋‹˜์ด ์›”๊ฐ„ ์œค์ข…์‹ ์„ ํ†ตํ•ด ๊พธ์ค€ํžˆ ์Œ์•…์„ ๋‚ด์‹œ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์ด ๋ณด๋ฆ„์นผ๋Ÿผ์„ ์ ์–ด๋ณด์ž!

๋ณด๋ฆ„์นผ๋Ÿผ ๊ทœ์น™

  1. ๋งค์ผ์„ ๊ธฐ๋กํ•˜๋Š” ์„ฑ์žฅ์ผ์ง€๋ณด๋‹ค ์ข€๋” ๊นŠ์€ ๋‚ด์šฉ์˜ ๊ธ€์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์ž.
  2. ๋„ˆ๋ฌด ์š•์‹ฌ๋ถ€๋ฆฌ์ง€๋ง๊ณ  ํ•˜๋‚˜์˜ ์ฃผ์ œ(ํ‚ค์›Œ๋“œ)์— ์ง‘์ค‘ํ•œ๋‹ค.
  3. 2์ฃผ์— ํ•œ ๋ฒˆ ๋‹ค๋“ฌ์–ด์ง„ ์นผ๋Ÿผ ํ˜•ํƒœ์˜ ๊ธ€์„ ์ž‘์„ฑํ•œ๋‹ค.
  4. ๋งˆ๊ฐ์€ ๋งค์ฃผ ์ผ์š”์ผ์„ ๊ธฐ์ค€์œผ๋กœ ํ•œ๋‹ค.

๐Ÿ“ƒ ๊ธ€๋˜ 8๊ธฐ

๊ฐœ๋ฐœ์ž๋“ค์ด ๋ชจ์—ฌ ํ•จ๊ป˜ ๊ธ€์„ ์“ฐ๊ณ  ํ”ผ๋“œ๋ฐฑํ•˜๋Š” ์ปค๋ฎค๋‹ˆํ‹ฐ์ธ ๊ธ€๋˜(๊ธ€์“ฐ๋Š” ๋˜๋ผ์ด๊ฐ€ ์„ธ์ƒ์„ ๋ฐ”๊พผ๋‹ค.)์—์„œ
ํ™œ๋™ํ•˜๊ฒŒ ๋˜์–ด ๋ณด๋ฆ„์นผ๋Ÿผ์˜ ๊ทœ์น™์€ ๊ธ€๋˜์˜ ๊ทœ์น™์„ ๋”ฐ๋ฅด๊ธฐ๋กœ ํ•œ๋‹ค.

2์ฃผ๋งˆ๋‹ค ๊ธ€์„ ์ž‘์„ฑํ•˜๋Š” ๊ทœ์น™์€ ๋™์ผํ•˜๋ฉฐ, ๊ทธ ๋งˆ๊ฐ ๋‚ ์งœ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค. ๋งˆ๊ฐ ๋‚ ์งœ๋ฅผ ์ฒดํฌํ•˜๋ฉฐ ๋งค๋ฒˆ ๊ธ€ ์ž‘์„ฑ์— ๋Œ€ํ•ด ์ธ์ง€ํ•˜๋„๋ก ํ•˜์ž!

๐Ÿšˆ ๋“ค์–ด๊ฐ€๊ธฐ์— ์•ž์„œโ€ฆ

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

๐Ÿ— ํŒจํ„ด???

ํŒจํ„ด(pattern)์€ ํ”„๋ž‘์Šค์–ด ๋‚ฑ๋ง์ธ patron์—์„œ ๋‚˜์˜จ ๋ง๋กœ, ๋˜ํ’€์ด๋˜๋Š” ์‚ฌ๊ฑด์ด๋‚˜ ๋ฌผ์ฒด์˜ ํ˜•ํƒœ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ์ฆ‰, ๊ฐœ๋ฐœ์— ์žˆ์–ด์„œ์˜ ํŒจํ„ด์€ ์ฝ”๋“œ๋กœ ํ‘œํ˜„๋œ ์–ด๋–ค ๋˜ํ’€์ด๋˜๋Š” ํ˜•ํƒœ๋ฅผ ์˜๋ฏธํ•œ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ– ์†Œํ”„ํŠธ์›จ์–ด ์•„ํ‚คํ…์ฒ˜..?

๋จผ์ € ์œ„ํ‚คํ”ผ๋””์•„ ์ •์˜๋ฅผ ๋ณด์ž.

์†Œํ”„ํŠธ์›จ์–ด ๊ตฌ์กฐย ๋˜๋Š”ย ์†Œํ”„ํŠธ์›จ์–ด ์•„ํ‚คํ…์ฒ˜(software architecture)๋Š”ย ์†Œํ”„ํŠธ์›จ์–ด์˜ ๊ตฌ์„ฑ์š”์†Œ๋“ค ์‚ฌ์ด์—์„œ ์œ ๊ธฐ์  ๊ด€๊ณ„๋ฅผ ํ‘œํ˜„ํ•˜๊ณ  ์†Œํ”„ํŠธ์›จ์–ด์˜ ์„ค๊ณ„์™€ ์—…๊ทธ๋ ˆ์ด๋“œ๋ฅผ ํ†ต์ œํ•˜๋Š” ์ง€์นจ๊ณผ ์›์น™์ด๋‹ค.

์—„โ€ฆ ์ง์ ‘์ ์œผ๋กœ ์™€๋‹ฟ์ง€๋Š” ์•Š์ง€๋งŒ, ๋Œ€์ถฉ ๋ญ”๊ฐ€ ์•Œ ๊ฒƒ ๊ฐ™์€ ์„ค๋ช…์ด๋‹ค. ์†Œํ”„ํŠธ์›จ์–ด์˜ ๊ตฌ์กฐ๋ฅผ ํ‘œํ˜„ํ•˜๊ณ  ์ด๋ฅผ ์„ค๊ณ„ํ•˜๋Š” ์–ด๋–ค ์›์น™ ์ •๋„๋กœ ์ƒ๊ฐํ•ด๋ณผ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค. ์ข€๋” ์ƒ์ƒ๋ ฅ์„ ํ†ตํ•ด ๋ง๋ถ™์—ฌ๋ณด์ž๋ฉด ๋ญ”๊ฐ€ ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ๊ฐœ๋ฐœํ•˜๊ธฐ ์œ„ํ•œ ์งœ์—ฌ์ ธ ์žˆ๋Š” ํ‹€(?) ์ •๋„์˜ ๋Š๋‚Œ๋„ ๋‚œ๋‹ค.

๊ธฐ๋ณธ์ ์ธ ์›๋ฆฌ

๋ชจ๋“ˆํ™”

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

๐Ÿงโ€ฆ ์ •์˜๋ณด๋‹ค ๊ธฐ๋ณธ์ ์ธ ์›๋ฆฌ๊ฐ€ ๋” ํ—ท๊ฐˆ๋ฆฌ๋Š” ๊ธฐ๋ถ„์ด๋‹ค. ์ •์˜๋งŒ ๋ดค์„ ๋•Œ๋Š” ๋„ˆ๋ฌด ์ถ”์ƒ์ ์ด๋ผ ๊ตฌ์ฒด์ ์œผ๋กœ ์™€๋‹ฟ์ง€ ์•Š์•˜๋‹ค๋ฉด, ์›๋ฆฌ๋Š” ๊ฐ์ฒด์ง€ํ–ฅ์˜ ๊ธฐ๋ณธ์ ์ธ ๊ฐœ๋…์ด๋ผ ๋„ˆ๋ฌด ๋‹น์—ฐํ•œ ๋Š๋‚Œ์ด ๋“ ๋‹ค.

์™œ ์ค‘์š”ํ•œ๊ฐ€?

์™œ ์†Œํ”„ํŠธ์›จ์–ด ์•„ํ‚คํ…์ณ๋ฅผ ์ค‘์š”ํ•˜๊ฒŒ ์ƒ๊ฐํ•ด์•ผํ• ๊นŒ?

์•„๋ž˜ ๊ทธ๋ฆผ์€ ๋งˆํ‹ด ํŒŒ์šธ๋Ÿฌ - ์†Œํ”„ํŠธ์›จ์–ด ์•„ํ‚คํ…์ฒ˜์˜ ์ค‘์š”์„ฑ ์˜์ƒ์—์„œ ๋‚˜์˜ค๋Š” ์ž๋ฃŒ์ด๋‹ค.

์•„ํ‚คํ…์ฒ˜ ์œ ๋ฌด ์‹œ๊ฐ„ ๊ทธ๋ž˜ํ”„

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

์ข‹์€ ๋‚ด๋ถ€ ํ’ˆ์งˆ์„ ๊ฐ€์ง„ ์†Œํ”„ํŠธ์›จ์–ด๋Š” ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๋Š”๋ฐ ์ดˆ๊ธฐ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๋”๋ผ๋„ ์ถ”ํ›„์— ๋” ๋น ๋ฅด๊ฒŒ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ๋”ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์•„ํ‚คํ…์ฒ˜๊ฐ€ ์ ์šฉ๋˜๊ธฐ ์ „

์•„ํ‚คํ…์ฒ˜ ์ ์šฉ ์ „

  • ์•„ํ‚คํ…์ฒ˜๊ฐ€ ์ ์šฉ๋œ ํ›„

์•„ํ‚คํ…์ฒ˜ ์ ์šฉ ํ›„

์œ„์˜ ์‚ฌ์ง„์„ ๋ณด๋ฉด ์–ด๋–จ๊นŒ? ๋ˆ„๊ฐ€๋ด๋„ ํ›„์ž์˜ ์‚ฌ์ง„์ด ๋” ์ถ”ํ›„ ๋ฌผ๊ฑด์„ ๋”ํ•˜๊ฑฐ๋‚˜ ์ œ๊ฑฐํ•˜๋Š” ๊ฒŒ ์‰ฝ๊ณ  ํŽธํ•ด๋ณด์ธ๋‹ค.(๋ฌผ๋ก  ํ›„์ž์˜ ์‚ฌ์ง„๋„ ์ค‘์•™์˜ ํฌ์ŠคํŠธ์ž‡์— ๋Œ€ํ•œ ์˜์กด์„ฑ์ด ๋„ˆ๋ฌด ํฐ ๋ฌธ์ œ๊ฐ€ ์žˆ๊ธด ํ•˜๋‹ค.)

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

๐Ÿฆด ์–ด๋–ค ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด๋“ค์ด ์žˆ์„๊นŒ?

  1. Layered pattern
  2. Client-server pattern
  3. Master-slave pattern
  4. Pipe-filter pattern
  5. Broker pattern
  6. Peer-to-peer pattern
  7. Event-bus pattern
  8. Model-view-controller pattern
  9. Blackboard pattern
  10. Interpreter pattern

์Œโ€ฆ ์‚ฌ์‹ค ๋‚˜๋Š” ์œ„์˜ 10๊ฐœ ์ค‘ MVC๋งŒ ์•Œ๊ณ  ์žˆ์—ˆ๊ณ  ์ฐธ๊ณ ์ž๋ฃŒ์—์„œ ๋‚ด์šฉ์„ ์‚ดํŽด๋ณด๋‹ˆ Client-server pattern๋„ ์•Œ๊ณ ๋Š” ์žˆ์—ˆ์ง€๋งŒ, ์ด๊ฒŒ ์•„ํ‚คํ…์ณ ํŒจํ„ด ์ค‘ ํ•˜๋‚˜์ธ์ง€๋Š” ์ฒ˜์Œ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค. ์ด ์ค‘ MVC ํŒจํ„ด์ด ์ž์ฃผ ์‚ฌ์šฉ๋˜๊ณ (๋ฐฑ์—”๋“œ์—์„œ ์•„์ฃผ ์ค‘์š”ํ•œ ํŒจํ„ด) ์—ฌ๊ธฐ์„œ MVVM, Flux ํŒจํ„ด ๋“ฑ์ด ํŒŒ์ƒ๋˜์—ˆ๋‹ค๊ณ  ํ•ด๋„ ๋ฌด๋ฐฉํ•˜๊ธฐ์— MVC ํŒจํ„ด์— ๋Œ€ํ•ด์„œ ์ข€๋” ์•Œ์•„๋ณด๋ ค ํ•œ๋‹ค.

MVC(Model - View - Controller) ํŒจํ„ด

  • ๋ชจ๋ธ(Model) - ์†Œํ”„ํŠธ์–ด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.
  • ๋ทฐ(View) - ์‚ฌ์šฉ์ž๊ฐ€ ๋ณผ ์ˆ˜ ์žˆ๋Š” ํ™”๋ฉด์„ ๋‹ด๋‹นํ•œ๋‹ค.
  • ์ปจํŠธ๋กค๋Ÿฌ(Controller) - ๋ชจ๋ธ๊ณผ ๋ทฐ ์‚ฌ์ด์—์„œ ์ด ๋‘˜์„ ๊ด€๋ฆฌํ•˜์—ฌ ์˜์กด์„ฑ์„ ๋‚ฎ์ถ”๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

MVCํŒจํ„ด

์‚ฌ์‹ค ๋ถ€๋„๋Ÿฝ์ง€๋งŒ, ์•„ํ‚คํ…์ฒ˜์˜ ๊ฐœ๋…์ด ์ด๋ ‡๊ฒŒ ๊ฑฐ๋Œ€ํ•œ ๊ฒƒ์ธ์ค„ ๋ชจ๋ฅด๊ณ  ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ ๊ฐ ์ปดํฌ๋„ŒํŠธ๋ฅผ MVC ํŒจํ„ด์œผ๋กœ ๊ฐœ๋ฐœํ•ด๋ณด์•˜๋‹ค. ์ด ๋•Œ, Controller์˜ ์—ญํ• ์„ Component๋ผ๊ณ  ๋ถ€๋ฅด๊ธฐ๋กœ ํ•˜๊ณ  Component์—์„œ Model๊ณผ View๋ฅผ ์ด์šฉํ•˜์—ฌ ํ•˜๋‚˜์˜ ์ž‘์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ์„ค๊ณ„๋ฅผ ํ•ด๋ณด์•˜๋‹ค.

MVC ํŒจํ„ด์œผ๋กœ ์„ค๊ณ„ํ•ด๋ณธ ์ปดํฌ๋„ŒํŠธ(feat. TypeScript)

๋จผ์ € Model, View, Component(Controller)์— ๋Œ€ํ•œ interface์ด๋‹ค.

export interface Model {  
setState(state: State): void;  
get state(): State;  
}  
  
export interface View {  
render(state: State): void;  
get element(): HTMLElement;  
}  
  
// Component๋Š” ์ข€๋” ์œ ์—ฐํ•˜๊ฒŒ interface๋กœ๋งŒ ๊ด€๋ฆฌ  
export interface Component {  
// private _model: Model;  
// private _view: View;  
// setState๋ฅผ private ์ฒ˜๋ฆฌํ•จ์œผ๋กœ์จ ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํƒœ๋ฅผ ์ง์ ‘ ์กฐ์ž‘ํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋ง‰์Œ.  
// private setState(state: State): void;  
get element(): HTMLElement;  
attachTo(component: Component): void;  
get state(): State;  
}
  • Model์€ state๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  setState๋ฅผ ํ†ตํ•ด state๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.
  • View๋Š” state๋ฅผ ๋ฐ›์•„ ํ™”๋ฉด์„ ๊ทธ๋ฆฌ๋Š” render ํ•จ์ˆ˜ ๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น ํ™”๋ฉด์„ element๋กœ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” element getter๋ฅผ ๊ฐ–๊ณ  ์žˆ๋‹ค.
  • Component๋Š”Model๊ณผ View๋ฅผ ํ†ตํ•ด state ๊ด€๋ฆฌ์™€ ํ™”๋ฉด์„ ๊ทธ๋ ค์ฃผ๊ฒŒ ๋˜๋ฉฐ attachTo ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ปดํฌ๋„ŒํŠธ ๊ฐ„์˜ ์ƒํ•˜์œ„ ๊ด€๊ณ„๋ฅผ ํ˜•์„ฑํ•œ๋‹ค.(DOM Tree ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•จ)

๊ทธ๋ฆฌ๊ณ  ์ด์ œ ์œ„์˜ interface๋ฅผ ํ†ตํ•ด ์ข€๋” ๊ตฌ์ฒด์ ์ธ ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•ด๋ณด์•˜๋‹ค.

export abstract class AbstractModel implements Model {  
protected _state: State;  
protected constructor() {  
this._state = {};  
}  
  
setState(newState: State) {  
this._state = { ...this._state, ...newState };  
}  
  
get state() {  
return this._state;  
}  
}  

export abstract class AbstractView implements View {  
protected _templateElement: HTMLTemplateElement;  
protected _element: HTMLElement;  
protected constructor() {  
this._templateElement = document.createElement('template');  
this._element = this._templateElement.content  
.firstElementChild as HTMLElement;  
  
this.setTemplate();  
this.setElement();  
}  
  
protected setTemplate() {  
this._templateElement.innerHTML = ``;  
}  
  
protected setElement() {  
this._element = this._templateElement.content  
.firstElementChild as HTMLElement;  
}  
  
render(state: State) {  
this.element.innerHTML = ``;  
}  
  
get element() {  
return this._element;  
}  
  
setEvent(  
selector: string,  
eventName: keyof WindowEventMap,  
handler: EventListener,  
) {  
$(selector, this.element)!.addEventListener(eventName, handler);  
}  
}

๋จผ์ € Model์€ interface์™€ ํฐ ์ฐจ์ด๊ฐ€ ์—†๊ธฐ์— ์ƒ๋žตํ•˜๊ณ , View๋ฅผ ์‚ดํŽด๋ณด์ž. ์กฐ๊ธˆ ์ง€์ €๋ถ„ํ•˜์ง€๋งŒ ๊ฐ„๋‹จํ•˜๋‹ค. ๋จผ์ € template element๋ฅผ ๋งŒ๋“ค๊ณ  ์ด element์— innerHTML๋กœ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” element์˜ html ํ˜•ํƒœ๋ฅผ ์ „๋‹ฌํ•œ๋‹ค. ์ดํ›„ template element์˜ ์ฒซ๋ฒˆ์งธ ์ž์‹์„ ์„ ํƒํ•˜์—ฌ template ํƒœ๊ทธ๋ฅผ ์ œ์™ธํ•œ ๊ทธ ๋‚ด๋ถ€ template literal์— ํ•ด๋‹นํ•˜๋Š” element๋ฅผ ์–ป์–ด๋‚ธ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์— ์กด์žฌํ•˜๋Š” element๋“ค์— ์–ด๋–ค ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ๋ถ™์—ฌ์ฃผ๊ธฐ ์œ„ํ•œ setEvent ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์˜€๋‹ค.

Controller์˜ ์—ญํ• ์„ ํ•˜๊ฒŒ ๋  Component๋Š” Model๊ณผ View๋ฅผ ์˜์กด์„ฑ ์ฃผ์ž… ํ˜•ํƒœ๋กœ ๋ฐ›๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ ๊ฐ๊ฐ์˜ Component๋งˆ๋‹ค ๋ชจ๋“ˆ๋กœ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ–ˆ๊ธฐ์— ๋”ฐ๋กœ ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ๋‘์ง€ ์•Š์•˜๋‹ค.

์ด์ œ ์–ด๋Š ์ •๋„ ๋‚˜๋งŒ์˜ ์„ค๊ณ„๋Š” ์™„์„ฑ๋˜์—ˆ๊ณ  ์ด๋ฅผ ํ†ตํ•ด ์•„์ฃผ ๊ฐ„๋‹จํ•œ ์ปดํฌ๋„ŒํŠธ ์˜ˆ์‹œ๋ฅผ ํ•˜๋‚˜ ์‚ดํŽด๋ณด๋ ค ํ•œ๋‹ค.

  • HeaderModel
import { AbstractModel } from '@custom-types/abstracts.js';  
  
export class HeaderModel extends AbstractModel {  
constructor() {  
super();  
}  
}

Model์€ ๋„ˆ๋ฌด ๊ฐ„๋‹จํ•˜๋‹ค. ์œ„์˜ ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•˜์—ฌ header ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ฐ–๊ฒŒ ๋  ์ƒํƒœ๋งŒ์„ ๊ด€๋ฆฌํ•œ๋‹ค.

  • HeaderView
import { State } from '@custom-types/types';
import { AbstractView } from '@custom-types/abstracts.js';  
  
export class HeaderView extends AbstractView {  
constructor() {  
super();  
}  
  
protected setTemplate() {  
this._templateElement.innerHTML = `<header class="h-1/6 bg-green-100 border border-green-500 text-3xl text-gray-500 grid place-content-center">Header</header>`;  
}  
  
render(state: State) {  
return;  
}  
}

์œ„์™€ ๊ฐ™์ด ๋‚ด๊ฐ€ ์›ํ•˜๋Š” header์˜ ํ˜•ํƒœ๋ฅผ template literal๋กœ ์ „๋‹ฌํ•ด์ฃผ๊ณ  render์—์„œ๋Š” state๋ฅผ ๋ฐ›์•„ ์ „๋‹ฌ๋ฐ›์€ template literal์„ ์กฐ์ž‘ํ•˜๋Š” ์ž‘์—…์„ ํ•œ๋‹ค.(์ถ”ํ›„์— ์ด ๋ถ€๋ถ„์ด ๋‚ด๊ฐ€ ์›ํ•˜๋˜ ๋ฆฌ์•กํŠธ์Šค๋Ÿฌ์šด ์„ค๊ณ„๊ฐ€ ์•„๋‹ˆ๋ผ๋Š” ๊ฑธ ์•Œ๊ฒŒ ๋˜์–ด์„œ ๋Œ€๊ทœ๋ชจ๋กœ ๋ฆฌํŒฉํ† ๋ง์„ ํ•˜๊ฒŒ ๋œ๋‹คโ€ฆ๐Ÿฅบ ์ด๋• ๋ชฐ๋ž์ง€โ€ฆใ… )

์ฐธ๊ณ ๋กœ html ํƒœ๊ทธ์˜ class๋‚ด์— ์žˆ๋Š” ๊ฐ’๋“ค์€ tailwindCSS๋ฅผ ํ†ตํ•œ ์Šคํƒ€์ผ ํ‘œํ˜„๋ฒ•์ด๋‹ค. ์ด ๊ธ€์—์„œ๋Š” ์ž์„ธํžˆ ๋‹ค๋ฃจ์ง€ ์•Š๊ฒ ์ง€๋งŒ, ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์ฝ”๋“œ์˜ ์„ค๊ณ„์— ์ง‘์ค‘ํ•˜๊ณ  ์‹ถ์–ด์„œ ๋น„๊ต์  style์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์„ ๋œํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š”(?) tailwindCSS๋ฅผ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

์œ„์™€ ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ€์žฅ ๋ฐ”๊นฅ์˜ root id๋ฅผ ๊ฐ€์ง„ ํƒœ๊ทธ์— ๋ถ™์—ฌ์ค€๋‹ค.

import { HeaderComponent } from '@components/header/HeaderComponent.js';  
import { MainComponent } from '@components/main/MainComponent.js';  
import { FooterComponent } from '@components/footer/FooterComponent.js';  
  
export class App {  
constructor(appRoot: HTMLElement) {  
const header = new HeaderComponent();  
const main = new MainComponent();  
const footer = new FooterComponent();  
  
appRoot.appendChild(header.element); // ์ด ๋…€์„์ด ์œ„์—์„œ ๊ตฌํ˜„ํ•œ header ์ปดํฌ๋„ŒํŠธ
appRoot.appendChild(main.element);  
appRoot.appendChild(footer.element);  
}  
}

์—ฌ๊ธฐ์„œ๋Š” App ์ปดํฌ๋„ŒํŠธ๋Š” ๋‚ด๊ฐ€ ์„ค๊ณ„ํ•œ component๋ฅผ ์ ์šฉํ•˜์ง€ ์•Š์•˜๊ธฐ์— DOM api์ธ appendChild๋ฅผ ํ†ตํ•ด ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถ™์ด๊ฒŒ ๋œ๋‹ค.

์œ„์˜ ๊ฒฐ๊ณผ๋ฌผ์„ ์‚ดํŽด๋ณด์ž๋ฉด

Header ์ปดํฌ๋„ŒํŠธ

์ด๋Ÿฐ ์‹์˜ Header๊ฐ€ ์™„์„ฑ๋œ๋‹ค. ์ด์ œ ์—ฌ๊ธฐ์— ๋˜ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถ™์—ฌ์„œ ํ•˜๋‚˜์˜ ํฐ ํ”„๋กœ์ ํŠธ๋ฅผ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿš‰ ๊ธ€์„ ๋งˆ์น˜๋ฉฐโ€ฆ

์ฒ˜์Œ ์ด ๊ธ€์˜ ์ฃผ์ œ๋Š” ์•„ํ‚คํ…์ฒ˜ vs ๋””์ž์ธ ํŒจํ„ด์ด์—ˆ๋‹ค. ๋งค๋ฒˆ ์„ค๊ณ„์—†์ด ์ง„ํ–‰ํ–ˆ๋˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์ถ”ํ›„์— ๋ฆฌํŒฉํ† ๋งํ•˜๋Š” ๊ฒŒ ๋„ˆ๋ฌด ํž˜๋“ค์–ด์„œ ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„  ์„ค๊ณ„์— ์ •๋ง ๋งŽ์€ ์‹œ๊ฐ„์„ ๋“ค์˜€๋‹ค. ํ•˜์ง€๋งŒ ์ด๊ฒŒ ์›ฌ๊ฑธโ€ฆ ์•„ํ‚คํ…์ฒ˜์™€ ๋””์ž์ธ ํŒจํ„ด์˜ ๊ทผ๋ณต์ ์ธ ์ฐจ์ด๋„ ๋ชจ๋ฅด๊ณ  ๊ทธ์ € ์œ ๋ช…ํ•œ MVC ํŒจํ„ด์„ ์ ์šฉํ•ด์„œ ๋‚˜๋งŒ์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค๊ณ  ์žˆ์—ˆ๊ณ , MVC์™€ ์˜ต์ €๋ฒ„ ํŒจํ„ด์„ ๋™์ผํ•œ ์„ ์ƒ์˜ ๊ฐœ๋…์œผ๋กœ ์ƒ๊ฐํ•˜๊ณ  ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ–ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‹ค ์ „๊ณต์ƒ์ธ ๋™๋ฃŒ์™€์˜ ๋Œ€ํ™” ์ค‘ ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด(ex. MVC)๊ณผ ๋””์ž์ธ ํŒจํ„ด(ex. ์˜ต์ €๋ฒ„ ํŒจํ„ด)์˜ ์ฐจ์ด๋ฅผ ์•Œ๊ฒŒ ๋˜์—ˆ๊ณ  ๋ญฃ๋ชจ๋ฅด๊ณ  ์„ค๊ณ„ํ•œ ํ”„๋กœ์ ํŠธ์˜ ์ฝ”๋“œ๊ฐ€ ์กฐ๊ธˆ์€ ๋ถ€๋„๋Ÿฌ์›Œ์กŒ๋‹ค. ์ด๋Ÿฐ ์ด์œ ๋กœ ์ด ๋‘˜์˜ ์ฐจ์ด๋ฅผ ํ™•์‹คํžˆ ์•Œ๊ณ  ๋‚ด๊ฐ€ ์ ์šฉํ–ˆ๋˜ ๋ฐฉ๋ฒ•์ด ํ†ต์šฉ๋˜๋Š” ๋ฐฉ๋ฒ•(?)์€ ์•„๋‹ˆ์—ˆ์Œ์„ ๊ธฐ๋กํ•˜๊ธฐ ์œ„ํ•ด ์ด ์ฃผ์ œ๋ฅผ ์„ ์ •ํ•˜์˜€๋‹ค. ๋‹ค์Œ์—๋Š” ๋””์ž์ธ ํŒจํ„ด์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๊ณ  ๋””์ž์ธ ํŒจํ„ด ์ค‘ ์˜ต์ €๋ฒ„ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌ์„ฑํ•œ ๊ฒฝํ—˜์„ ์ ์–ด๋ณด๋ ค ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ๋’ค์—๋Š” ์ด ์ฐจ์ด๋ฅผ ์•Œ๊ณ ์„œ ์ƒˆ๋กญ๊ฒŒ ๋ฆฌํŒฉํ† ๋งํ•œ ์ฝ”๋“œ์— ๋Œ€ํ•ด์„œ๋„ ๋‹ค๋ค„๋ณผ ์˜ˆ์ •์ด๋‹ค.

์•„์ง ๋งŽ์ด ๋ถ€์กฑํ•œ ๊ฐœ๋ฐœ์ž์ž…๋‹ˆ๋‹ค. ๋‚ด์šฉ์— ๋Œ€ํ•œ ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋‹ค๋ฉด, ์–ธ์ œ๋“  ํŽธํ•˜๊ฒŒ ๋ง์”€ํ•ด์ฃผ์„ธ์š”! ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

๐ŸŽ ์ฐธ๊ณ