Skip to main content

๐Ÿค 25๋…„ 1๋ถ„๊ธฐ ํšŒ๊ณ 

31 min read
Ju young Lee
A contribution-driven developer

์„œ๋ก โ€‹

25๋…„ 1๋ถ„๊ธฐ๊ฐ€ ๋น ๋ฅด๊ฒŒ ํ˜๋Ÿฌ๊ฐ”์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ์ง„ํ–‰ํ•˜๊ณ  ์žˆ๋Š” ํ”„๋กœ์ ํŠธ์ธ ๋น„์ ผ ์‹œ์Šคํ…œ๊ณผ ๊ด€๋ จํ•ด ๊ธฐํš๋ถ€ํ„ฐ ๊ฐœ๋ฐœ ๋ฐ ์šด์˜์„ ํ•˜๋ฉฐ 1๋ถ„๊ธฐ๋ฅผ ๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค. 1๋ถ„๊ธฐ๋ฅผ ๋Œ์•„๋ณด๋ฉฐ 2๋ถ„๊ธฐ์˜ ๋‚˜์•„๊ฐˆ ๋ฐฉํ–ฅ์„ ์„ค๊ณ„ํ•˜๊ณ  ์•ก์…˜ํฌ์ธํŠธ๋ฅผ ๊ธฐ๋กํ•ด๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๋ณธ๋ก โ€‹

ํ•ญํ•ด ํ”„๋ก ํŠธ์—”๋“œ 4๊ธฐ ์ˆ˜๋ฃŒํ–ˆ์Šต๋‹ˆ๋‹ค!โ€‹

1๋ถ„๊ธฐ๋ฅผ ๋Œ์•„๋ณด๋ฉด ๊ฐ€์žฅ ๋จผ์ € ๋– ์˜ค๋ฅด๋Š” ๊ฒƒ์€ ์•„๋ฌด๋ž˜๋„ ํ•ญํ•ด์ž…๋‹ˆ๋‹ค. 24๋…„ ์—ฐ๋ง ํ‰๊ฐ€๋ฅผ ํ†ตํ•ด ๊ธฐ๋ณธ๊ธฐ๋ฅผ ๋‹ค์ง€๋Š” ์‹œ๊ฐ„์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐ์ด ๋“ค์–ด ํ•ฉ๋ฅ˜ํ•˜๊ฒŒ ๋๊ณ  ์ด๋ฅผ ํ†ตํ•ด ๋ฆฌ์•กํŠธ์˜ ๋™์ž‘ ์›๋ฆฌ์™€ ํด๋ฆฐ ์ฝ”๋“œ ๋ฐ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์— ๋Œ€ํ•œ ํ•™์Šต์„ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๊ฐœ์ธ ๋ธ”๋กœ๊ทธ๋ฅผ ํ†ตํ•ดย ํ™•์ธํ•ด ๋ณด์‹คย ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ณผ์ œ๋Š”ย ์™œ ์ด๋ ‡๊ฒŒย ์–ด๋ ต๋˜์ง€์š”โ€ฆ ใ… ใ…  ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์‹ค๋ฌด์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ์ˆ ๋“ค์„ ์ตํž ์ˆ˜ ์žˆ๋Š” ์œ ์ตํ•œ ์‹œ๊ฐ„์ด์—ˆ์Šต๋‹ˆ๋‹ค.

24๋…„ 12์›”, ํ…Œ๋”๊ฐ€์ด,์‹ ์‚ฌ์—… ์ž ์ • ์ค‘๋‹จ ๊ฒฐ์ •โ€‹

๋น„๋ก ์ž‘๋…„์— ๊ฒฝํ—˜ํ•œ ๊ฒƒ์ด์ง€๋งŒ,,, 24๋…„ 6์›”์— ์ž…์‚ฌํ•ด์„œ 12์›”๊นŒ์ง€ ํ•ด์™ธ ๊ฑฐ๋ž˜์†Œ ์ค‘๊ฐœ ํ”Œ๋žซํผ ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

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

ํ”„๋ก ํŠธ์—”๋“œ ๊ธฐ์ˆ  ์Šคํƒ์€ Next.js, tailwindCss, zustand, tanstack-query, storybook ๋“ฑ์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๋‹น์‹œ์— ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์™€ Next.js์˜ SSR์— ๋Œ€ํ•œ ์ดํ•ด๋„ ๋ถ€์กฑํ–ˆ์„ ๋•Œ์˜€๊ธฐ์— ๋งŒ๋“ค๋ฉด์„œ ์ด๊ฒŒ ๋งž๋Š”์ง€, ๊ณ ์ƒํ–ˆ๋˜ ๊ธฐ์–ต์ด ๋‚ฉ๋‹ˆ๋‹ค. ๋ฆฌ์•กํŠธ ์ฟผ๋ฆฌ์™€ ์–ด๋–ป๊ฒŒ ๋ณ‘ํ–‰ํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์ธ์ง€, ์ธ์ฆ๊ณผ ์ธ๊ฐ€๋Š” ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ•˜๋Š”์ง€ ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. Next.js์˜ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ํ™œ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„์—์„œ ์ฟ ํ‚ค๋ฅผ ๊ฐ€์ง€๊ณ  ์™”์„ ๋•Œ์™€ ํด๋ผ์ด์–ธํŠธ์—์„œ ์ฟ ํ‚ค๋ฅผ ๊ฐ€์ง€๊ณ  ์™”์„ ๋•Œ, ๊ฐ’์ด ๋‹ฌ๋ผ ๊ณ ์ƒ์„ ํ–ˆ๋˜ ๊ธฐ์–ต์ด ๋‚ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‹ค ๊ฒฐ๊ตญโ€ฆ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋ฅผ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ์ผ์ •์„ ๋งž์ท„์Šต๋‹ˆ๋‹ค. Next.js๋ฅผ ์ •ํ™•ํžˆ ์•Œ์ง€ ๋ชปํ•˜๊ณ  ํ”„๋กœ์ ํŠธ๋ฅผ ๋ฐ”๋กœ ์‹œ์ž‘ํ–ˆ๋˜๊ฒŒ ๋ถˆ์ฐฐ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๊ธฐ๋ณธ์ ์ธ ๊ฐœ๋…๋“ค๊ณผ ์‚ฌ์šฉ๋ฐฉ๋ฒ•์„ ์ตํžˆ๊ณ  ์‹ค๋ฌด์— ์ ์šฉํ•ด์•ผ ํ•จ์„ ๊ฒฝํ—˜ํ–ˆ์Šต๋‹ˆ๋‹ค. MVP๋ฅผ ์‹œ์žฅ์— ์ถœ์‹œํ•˜์˜€์ง€๋งŒ ๋ฐ˜์‘์ด ์ฐจ๊ฐ€์› ์Šต๋‹ˆ๋‹ค. GA์™€ hotjar์„ ํ™œ์šฉํ•ด์„œ ์œ ์ž… ์ถœ์ฒ˜์™€ ์ดํƒˆ๋ฅ ๋“ฑ์„ ์‚ดํŽด๋ณด๋ฉด์„œ ๊ฐœ์„ ์ ์„ ์ œ์•ˆํ•˜๊ณ  ์•Œ๋ฆผํ•จ ๊ธฐ๋Šฅ๊ณผ ์ฟ ํฐ ๊ธฐ๋Šฅ์„ ๋„์ž…ํ–ˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๊ณ ๊ฐ ์ž์ฒด๊ฐ€ ์œ ์ž…์ด ์•ˆ๋ผ, ์šฐ๋ฆฌ๊ฐ€ ์ž˜ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์— ์ง‘์ค‘ํ•˜๊ธฐ๋กœ ํ•˜๋ฉฐ ํ•ด๋‹น ํ”Œ๋žซํผ ์‚ฌ์—…์„ ์ž ์ • ์ค‘๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.

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

๊ฐœ๋ฐœ์ž๊ฐ€ ๊ธฐํš์— ๋” ์ ๊ทน์ ์œผ๋กœ ์ฐธ์—ฌ ํ•ด์•ผํ•œ๋‹ค. (์žˆ๋Š” ๋ฆฌ์†Œ์Šค ์•ˆ์—์„œ ์ตœ๋Œ€ํ•œ ์‹œ๋„๊ฐ€ ํ•„์š”ํ•˜๋‹ค.)

์ง€๋‚œ 8๊ฐœ์›”๊ฐ„ ์ง€์†์ ์ธ ํŽ˜์ธ ํฌ์ธํŠธ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

โ€œ์šฐ๋ฆฌ๋Š” ๊ธฐํš์ž๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์„๊นŒ?โ€

โ€œ๊ธฐํš์ž๊ฐ€ ์˜ค๋ฉด ์ด ๋ชจ๋“  ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜๋Š” ๊ฒŒ ์•„๋‹๊นŒ?โ€

โ€œ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ๋งŒ๋“œ๋Š”๋ฐ ๊ธฐํš์ด๋ผ๋Š” โ€˜๋จธ๋ฆฌโ€™๊ฐ€ ์—†์œผ๋ฉด ์•ˆ ๋˜๋Š” ๊ฒŒ ์•„๋‹๊นŒ?โ€

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

ํ•˜์ง€๋งŒ โ€œ์ œ ์ƒ๊ฐ์ด ํ‹€๋ ธ์Œ์„ ์•Œ๊ฒŒ ๋์Šต๋‹ˆ๋‹ค.โ€ "์—์ž์ผ ์—์ž์ผ"์„ ์™ธ์ณค๋˜ ์ œ๊ฐ€ ์ •์ž‘ ์›ํ–ˆ๋˜ ๊ฒƒ์€ ์›Œํ„ฐํด ๋ฐฉ์‹์˜ ์ผํ•˜๋Š” ๋ฐฉ์‹์ด์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋์Šต๋‹ˆ๋‹ค.

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

์šฐ๋ฆฌ๋Š” ์ˆ˜๋™์ ์œผ๋กœ ์ง€์‹œ๋ฐ›๋Š” ์กฐ์ง์ธ๊ฐ€? ์•„๋‹ˆ๋ฉด ๋Šฅ๋™์ ์œผ๋กœ ์›€์ง์ด๋Š” ์กฐ์ง์ธ๊ฐ€?

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

[์ฐธ๊ณ  ๋…ธ์…˜ ๊ณต์œ  ํŽ˜์ด์ง€]

์–ด๋–ป๊ฒŒ ๊ฐœ๋ฐœ์„ ์ฆ๊ธธ ์ˆ˜ ์žˆ์„๊นŒ?โ€‹

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

๋Œ€์‹œ๋ณด๋“œ๋ฅผ ๋งŒ๋“ค๊ณ  ์žˆ๋Š” ์ง€๊ธˆ,,, ์ด๋Ÿฐ ์š”๊ตฌ์‚ฌํ•ญ์„ ๋ฐ›๊ณค ํ•ฉ๋‹ˆ๋‹ค.

โ€œ์ด๋Ÿฐ ๊ธฐ๋Šฅ์€ ์ด๋ ‡๊ฒŒ ์ˆ˜์ •ํ•ด ์ฃผ์„ธ์š”.โ€

โ€œ์ด๋Ÿฐ ๊ธฐ๋Šฅ์— ์ด ๊ธฐ๋Šฅ์— ๋ถ™์—ฌ์ฃผ์‹ค ์ˆ˜ ์žˆ์œผ์„ธ์š”?โ€

๊ณ ๊ฐ์˜ ๊ณ„์ขŒ์˜ ํฌ์ง€์…˜๊ณผ ์˜ค๋”๋ฅผ ํ•œ ๋ˆˆ์— ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ์ข‹๊ฒ ์–ด์š”. ์Œ...

๊ทธ๋ž˜ํ”„ ํ•„ํ„ฐ๋ง ๋ฒ„ํŠผ ํด๋ฆญํ•˜๋ฉด 1์ดˆ ์žˆ๋‹ค๊ฐ€ ์›€์ง์ด๋Š”๋ฐ ์ด๊ฑฐ ์™œ ์ด๋Ÿฌ์ฃ ?

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

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

๊ทธ๋Ÿผ ์–ด๋–ป๊ฒŒ ํ•  ๊ฒƒ์ธ๊ฐ€??

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

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

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

// ์‚ฌ์ด๋“œ ๋„ค๋น„๊ฒŒ์ด์…˜ ์˜์—ญ ( ์‚ฌ์šฉ์ž ๋กœ๊ทธ์ธ ์—ฌ๋ถ€์— ๋”ฐ๋ฅธ UI ๋ Œ๋”๋ง ๋ฐ ์ƒํ˜ธ ์ž‘์šฉ)

// ์‚ฌ์šฉ์ž ๋กœ๊ทธ์ธ ๋ฐ ํšŒ์›๊ฐ€์ž… ๊ธฐ๋Šฅ ํ…Œ์ŠคํŠธ
import { mockSessionStore } from "@/__mock__/mockZustandStore";
import { render, renderHook, screen } from "@testing-library/react";
import { useState } from "react";
import { MemoryRouter } from "react-router-dom";

import { Sidebar } from "@/pages/home";

import { VIEW } from "@/shared/lib";

vi.mock("../pages/home/ui/sidebar/AccountsSubNav.tsx", () => ({
default: () => <div data-testid="mock-heavy-child">Mocked HeavyChild</div>,
}));

describe("์‚ฌ์ด๋“œ๋ฐ” UI ํ…Œ์ŠคํŠธ", () => {
it("์–ด๋“œ๋ฏผ์ผ ๊ฒฝ์šฐ ์‚ฌ์ด๋“œ ๋ฐ” UI๊ฐ€ ๊ถŒํ•œ์— ๋งž๋Š” ์š”์†Œ๋“ค์ด ์กด์žฌํ•˜๋‚˜์š”?", async () => {
mockSessionStore({
access_token: "admin",
refresh_token: "admin",
access_token_duration: 3600,
role: "administrator",
token_type: "Bearer",
});
const { result } = renderHook(() => useState(false));

render(
<MemoryRouter>
<Sidebar
sidebarOpen={result.current[0]}
setSidebarOpen={result.current[1]}
/>
</MemoryRouter>,
);
// TODO : ์ด๊ฒŒ ์ตœ์„ ์„ ์•„๋‹ˆ๊ฒ ์ง€๋งŒ ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์žˆ์„๊นŒ?
expect(screen.getByText(VIEW.HOME)).toBeInTheDocument();
expect(screen.getByText(VIEW.PNL_TRANKING)).toBeInTheDocument();
expect(screen.getByText(VIEW.ORGANIZATIONS)).toBeInTheDocument();
expect(screen.getByText(VIEW.ACCOUNTS)).toBeInTheDocument();
expect(screen.getByText(VIEW.USERS)).toBeInTheDocument();
expect(screen.getByText(VIEW.TRANSFER_RECORDS)).toBeInTheDocument();
expect(screen.getByText(VIEW.RISK_MANAGEMENT)).toBeInTheDocument();
expect(screen.getByText(VIEW.DASHBOARDS)).toBeInTheDocument();
});

it("์Šคํƒœํ”„์ผ ๊ฒฝ์šฐ ์‚ฌ์ด๋“œ ๋ฐ” UI๊ฐ€ ๊ถŒํ•œ์— ๋งž๋Š” ์š”์†Œ๋“ค์ด ์กด์žฌํ•˜๋‚˜์š”?", () => {
mockSessionStore({
access_token: "admin",
refresh_token: "admin",
access_token_duration: 3600,
role: "staff",
token_type: "Bearer",
});
const { result } = renderHook(() => useState(false));

render(
<MemoryRouter>
<Sidebar
sidebarOpen={result.current[0]}
setSidebarOpen={result.current[1]}
/>
</MemoryRouter>,
);
expect(screen.getByText(VIEW.HOME)).toBeInTheDocument();
expect(screen.getByText(VIEW.PNL_TRANKING)).toBeInTheDocument();
expect(screen.getByText(VIEW.ORGANIZATIONS)).toBeInTheDocument();
expect(screen.getByText(VIEW.ACCOUNTS)).toBeInTheDocument();
expect(screen.getByText(VIEW.USERS)).toBeInTheDocument();
expect(screen.getByText(VIEW.TRANSFER_RECORDS)).toBeInTheDocument();
expect(screen.getByText(VIEW.RISK_MANAGEMENT)).toBeInTheDocument();
expect(screen.getByText(VIEW.DASHBOARDS)).toBeInTheDocument();
});

it("์œ ์ €์ผ ๊ฒฝ์šฐ ์‚ฌ์ด๋“œ ๋ฐ” UI๊ฐ€ ๊ถŒํ•œ์— ๋งž๋Š” ์š”์†Œ๋“ค์ด ์กด์žฌํ•˜๋‚˜์š”?", () => {
mockSessionStore({
access_token: "admin",
refresh_token: "admin",
access_token_duration: 3600,
role: "user",
token_type: "Bearer",
});

const { result } = renderHook(() => useState(false));

render(
<MemoryRouter>
<Sidebar
sidebarOpen={result.current[0]}
setSidebarOpen={result.current[1]}
/>
</MemoryRouter>,
);
expect(screen.getByText(VIEW.HOME)).toBeInTheDocument();
expect(screen.getByText(VIEW.DASHBOARDS)).toBeInTheDocument();
});
});

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

FSD (Feature-Sliced Design)๋ฅผ ์ ์šฉํ•ด๋ณด๊ณ  ์žˆ์–ด์š”โ€‹

1์›”์— ํ•ญํ•ด๋ฅผ ํ†ตํ•ด FSD๋ฅผ ์•Œ๊ฒŒ ๋๊ณ  2์›”๋ถ€ํ„ฐ ์ฐจ์ธฐ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•ด๋ณด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋ธ”๋กœ๊ทธ๋ฅผ ์ฐธ๊ณ ํ•˜์‹œ๋ฉด ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์•„์š”. FSD ์ ์šฉ๊ธฐ 1ํŽธ ๊ณ„์† ์ง„ํ–‰ํ•˜๊ณ  ์žˆ๊ณ  ํ˜„์žฌ๋Š” 2ํŽธ ๋ธ”๋กœ๊ทธ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•ด ํ•™์Šตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

map ๋งค์†Œ๋“œ๋Š” Array.prototype์—๋งŒ ์žˆ์ง€ ์•Š๋‹ค. (ํฌ๋กœ์Šค ๋ธŒ๋ผ์šฐ์ง• ์ด์Šˆ)โ€‹

์–ด๋А ๋‚ , ์‚ฌ๋‚ด ๋ฉ”์‹ ์ €์— ๋™๋ฃŒ์˜ ํƒœ๊ทธ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

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

์—๋Ÿฌ๋ฅผ ๋””๋ฒ„๊น…ํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋ฐ”์ผ ์—๋Ÿฌ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ๋””๋ฒ„๊ฑฐ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ตฌ๊ธ€์— ๊ฒ€์ƒ‰ํ•ด ๋ณด๋‹ˆ ๋ชจ๋ฐ”์ผ ๋””๋ฒ„๊ฑฐ (chrome://inspect/#devices)๊ฐ€ ์กด์žฌํ–ˆ๊ณ  ํ•ด๋‹น ๋ชจ๋ฐ”์ผ ๋””๋ฒ„๊ฑฐ๋ฅผ ํ™œ์šฉํ•˜์—ฌ console.log()๋ฅผ ํ™•์ธํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ํ™•์ธํ•ด ๋ณด๋‹ˆ ํ…Œ์ด๋ธ” ํ—ค๋” ์ฝ”๋“œ์— ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋์Šต๋‹ˆ๋‹ค. ํ—ค๋”๋ฅผ ํ•„ํ„ฐ๋งํ•˜๋Š” ๋กœ์ง์ด ๋ฌธ์ œ์˜€์ฃ . ์šฐ์„  ํ•„ํ„ฐ๋ง ๊ธฐ๋Šฅ์„ ์ œ์™ธํ•˜๊ณ  hotfix๋ฅผ ๋งŒ๋“ค์–ด ๋ฐฐํฌ๋ฅผ ์ง„ํ–‰ํ•˜๊ณ  main์™€ develop์— ๊ฐ๊ฐ merge๋ฅผ ์ง„ํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์šฐ์„  Filter ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ๊ฑฐํ•˜๋‹ˆ ์ •์ƒ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ์œผ๋‹ˆ ๋ฒ”์œ„๊ฐ€ ์ข์•„์กŒ์Šต๋‹ˆ๋‹ค.

const PnlTable = () => {
return (
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id} className="text-center font-bold">
<div className="flex w-full items-center justify-center gap-2">
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext(),
)}

{header.column.getCanFilter() ? (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<button className="flex items-center">
<ChevronDown />
</button>
</DropdownMenuTrigger>
{/* HERE : ๋ชจ๋ฐ”์ผ์—์„  ์—๋Ÿฌ๊ฐ€ ๋œจ๋Š”๋ฐ ๋ฐ์Šคํฌํƒ‘์—์„œ๋Š” ์ •์ƒ ์ž‘๋™ํ•จ... */}
<DropdownMenuContent align="end">
<Suspense fallback={"error in Filter Component"}>
{/* HERE : ์•„๋ž˜์˜ Filter ์ปดํฌ๋„ŒํŠธ ์ œ๊ฑฐํ•˜์—ฌ ์šฐ์„  ๋ฌธ์ œ ํ•ด๊ฒฐ */}
<Filter column={header.column} />
</Suspense>
</DropdownMenuContent>
</DropdownMenu>
) : null}
</div>
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody>...</TableBody>
</Table>
);
};

์šฐ์„  Filter ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ฃผ์„ ์ฒ˜๋ฆฌํ•˜์—ฌ ์ž„์‹œ๋กœ ํ•ด๊ฒฐํ•œ ํ›„ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๋‹ˆ

// HERE!
function Filter({ column }: { column: Column<any, unknown> }) {
return (
<>
{Array.from(
column
.getFacetedUniqueValues()
.keys()
.map((option) => {
return <>123</>;
}),
)}
</>
);
}

map ๋ฉ”์„œ๋“œ๊ฐ€ ์ด์ƒํ•จ์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์œ„์˜ ์ฝ”๋“œ๋Š” ๊ณต์‹ ๋ฌธ์„œ์˜ ์ฝ”๋“œ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ๊ตฌํ˜„ํ•œ ๊ฒƒ์ธ๋ฐ,,, ํ•ด๋‹น ํƒ€์ž…์„ ๋ณด๋‹ˆ,

column.getFacetedUniqueValues(); // Type: Map<any, number>

Map ์ž๋ฃŒ๊ตฌ์กฐ์—๋„ keys ๋ฉ”์†Œ๋“œ๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. MDN ๊ณต์‹๋ฌธ์„œ๋ฅผ ํ†ตํ•ด ํ™•์ธํ•ด๋ณด๋‹ˆ keys ๋งค์†Œ๋“œ๋Š” ์ƒˆ๋กœ์šด map interator ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ดํ„ฐ๋ ˆ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค!

๊ทธ๋Ÿผ iterator์—๋„ map ๋ฉ”์†Œ๋“œ๊ฐ€ ์žˆ์—ˆ๋˜ ๊ฒƒ์ธ๊ฐ€?

๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. map ๋ฉ”์†Œ๋“œ๋Š” ๋™์ผํ•ด๋ณด์ด์ง€๋งŒ, ๋‘๊ฐ€์ง€๋กœ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. Array ํด๋ž˜์Šค์˜ ์ƒ์† map
  2. Iterator์˜ map

Iterator ๊ฐ์ฒด์˜ ๋ฉ”์†Œ๋“œ์ธ map์€ Limited availability yet์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌํŒŒ๋ฆฌ์—์„  ์•„์ง ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋ชจ๋ฐ”์ผ ๋ฒ„์ „์—์„œ ํ•ด๋‹น ๊ธฐ๋Šฅ์ด ์žˆ๋Š” ํŽ˜์ด์ง€์—์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋์Šต๋‹ˆ๋‹ค.

๊ธฐ์กด์—๋Š” ๋ชจ๋“  ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ๋‚˜์˜จ ๊ฒฐ๊ณผ๋ฅผ ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ํ–ˆ์—ˆ๋‹ค๋ฉด, map์„ Array ํ”„๋กœํ† ํƒ€์ž…์˜ map์„ ์‚ฌ์šฉํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜์—ฌ ์˜ค๋ฅ˜๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ฆฌํ”„๋ ˆ์‹œ ๋„์ž…์— ๋”ฐ๋ฅธ API ์ค‘๋ณต ํ˜ธ์ถœ ๋ฌธ์ œโ€‹

ํ˜„์žฌ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” react-router-dom์˜ loader ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ๊ถŒํ•œ ์ฒ˜๋ฆฌ์™€ prefetch ํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์˜ค๋Š” ๋กœ์ง์„ ์ถ”๊ฐ€ํ•˜์—ฌ ํ•œ ๊ณณ์—์„œ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

export const router: ReturnType<typeof createBrowserRouter> = createBrowserRouter([
{
//public route
path: publicPathKeys.root,
element: <DefaultLayout />,
//HERE!
loader: DefaultLayoutLoader.AuthLayoutPage,
errorElement:<ErrorPage>,
children:{
...
}},

{
// private route
path: privatePathKeys.root,
element: <AuthLayout />,
//HERE!
loader: AuthLayoutLoader.AuthLayoutPage,
errorElement:<ErrorPage>,
children:{
...
},
}
])

loader ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•œ ์ด์œ ๋Š” Cumulative Layout Shift๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•จ์ด์—ˆ์Šต๋‹ˆ๋‹ค. react-router-dom ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ›์•„์™€ ์ง„ ๊ฒฝ์šฐ ํ•ด๋‹น ํŽ˜์ด์ง€๋ฅผ ๋ Œ๋”๋ง ํ•˜๋Š” ๋กœ์ง์„ ์‹คํ–‰์‹œํ‚ค๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์†Œ ๋А๋ฆฌ๊ฒŒ ๋ณด์ด๋”๋ผ๊ณ  ์‚ฌ์šฉ์ž๋Š” ๋ฐ์ดํ„ฐ์™€ UI๊ฐ€ ๊ฒฐํ•ฉ๋œ ์ƒํƒœ๋กœ ๋ณผ ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

ํ˜„์žฌ ํ”„๋กœ์ ํŠธ์—์„  axios๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ axios์˜ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜์ธ ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ๊ฐ€๋กœ์ฑ„๋Š” ๋ฐฉ์‹์œผ๋กœ 401 ์—๋Ÿฌ๊ฐ€ ์žˆ์„ ๋•Œ, ์•ก์„ธ์Šค ํ† ํฐ์„ ์žฌ๋ฐœ๊ธ‰ํ•˜๋Š” ๊ณผ์ •์„ ํ†ตํ•ด ์ž๋™ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋กœ๊ทธ์ธ์„ ํ•˜๋ฉด ์Šฌ๋ž™์œผ๋กœ ์•Œ๋ฆผ์ด ์˜ค๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค. ์•ก์„ธ์Šค ํ† ํฐ์ด ๋งŒ๋ฃŒ๋œ ์ดํ›„ ์ž๋™ ๋กœ๊ทธ์ธ์ด ๋˜์–ด๋„ ์Šฌ๋ž™์œผ๋กœ ์•Œ๋ฆผ์ด ์˜ต๋‹ˆ๋‹ค. ๋ฌธ์ œ๋Š” ์•ก์„ธ์Šค ํ† ํฐ ๊ฐฑ์‹ ์„ ํ•˜๋ฉด 3๋ฒˆ์˜ ์•Œ๋ฆผ์ด ๊ฐ€๋Š” ๊ฒƒ์ธ๋ฐ ์šฐ์„  ์™œ ๊ทธ๋Ÿฐ์ง€ ํŒŒ์•…ํ•ด ๋ณด๋‹ˆ ๋ฉ”์ธ ํŽ˜์ด์ง€์„œ 3๊ฐœ์˜ API๋ฅผ ํ˜ธ์ถœํ–ˆ์Šต๋‹ˆ๋‹ค.

ํŽ˜์ด์ง€ ์ง„์ž… ๋•Œ ์ธ์ฆ ๊ฒ€์ฆ๊ณผ prefetch ํ•˜๋„๋ก ํ•ด์„œ ํŽ˜์ด์ง€๊ฐ€ ๋ณด์ผ ๋•Œ CLS๋ฅผ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์„ ๋„์ž…ํ•˜๊ณ  ์ƒˆ๋กœ์šด ์•ก์„ธ์Šค ํ† ํฐ์„ ๋ฐœ๊ธ‰๋ฐ›์„ ๋•Œ ์Šฌ๋ž™์œผ๋กœ 3๋ฒˆ ๋กœ๊ทธ์ธ ์š”์ฒญ์ด ๋ณด๋‚ด์ง€๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋์–ด ๊ทธ๋ž˜์„œ ์ด ๋ถ€๋ถ„์ด ์›๋ž˜ prefetchQuery์˜€๋Š”๋ฐ fetchQuery๋กœ ๋ฐ”๊ฟ”์„œ ์—๋Ÿฌ๋ฅผ ๋ฆฌํ„ดํ•˜๋„๋ก ํ•ด์„œ ์ด๋•Œ interceptor๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ํ•ด์„œ 1๋ฒˆ๋งŒ ๊ฐ€๊ฒŒ ํ–ˆ๋Š”๋ฐ ์ด ๋ฐฉ๋ฒ•๋„ ๊ดœ์ฐฎ์€ ๋ฐฉ๋ฒ• ๊ฐ™์€๋ฐ ์ •๋‹ต์ด ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. 4์›”์— ์ œ๋Œ€๋กœ ํ•ด๊ฒฐํ•˜๊ณ  ๋„˜์–ด๊ฐ€๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

Git ์„ธ์…˜์„ ๋งŒ๋“ค๊ณ  ๊ณต์œ ํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.โ€‹

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

๋ณด์•ˆ์— ๊ฒฝ๊ฐ์‹ฌ์„ ๊ฐ€์ง€์ž. ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์˜ ์ทจ์•ฝ์„ฑ์— ๋Œ€ํ•ดโ€‹

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

2๋…„๋งŒ์— ์žฌ๋…๋ฆฝ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.โ€‹

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

๊ตํšŒ ๋“œ๋Ÿผ ๋ฐ˜์ฃผ ๋‹ค์‹œ ์‹œ์ž‘โ€‹

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

์šด๋™ ์ˆ˜ํ–‰ ๋Šฅ๋ ฅ ํ–ฅ์ƒ, ํ„ฑ๊ฑธ์ด 2๊ฐœ โ†’ 8๊ฐœโ€‹

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

์ดํ˜•์˜ ํƒ€์ž„ ํŠธ๋ ˆ์ปค ์‚ฌ์šฉ ํ›„๊ธฐโ€‹

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

2์›” 3์›”, ํƒ€์ž„ ํŠธ๋ž˜์ปค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๋А๋‚€ ์ ์€ ์‹œ๊ฐ„์„ ๊ธฐ๋กํ•˜๋ฉด์„œ ๋‚ญ๋น„ํ•œ ์‹œ๊ฐ„์ด ์–ผ๋งˆ๋‚˜ ๋งŽ์€์ง€์— ๋Œ€ํ•œ ๊ฐ๊ฐ์ด ์ƒ๊ธด๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ์œ ์พŒํ•œ ์ผ์€ ์•„๋‹ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋งค์ผ ๋‚˜์˜ ์‹คํŒจ๋ฅผ ๋งˆ์ฃผํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋กœ ์ธํ•ด 1๋ถ„๊ธฐ์— ๋‚ด๊ฐ€ ์–ผ๋งˆ๋‚˜ ์‹œ๊ฐ„์„ ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ–ˆ๋Š”์ง€๋ฅผ ์•Œ๊ฒŒ ๋๊ณ  ํšŒ๊ณ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‚ญ๋น„ํ•œ ์‹œ๊ฐ„๋„ ์žˆ์—ˆ์ง€๋งŒ ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์ง€์ผœ๋‚ธ ์‹œ๊ฐ„๋„ ๋งŽ์•˜๋˜ 1๋ถ„๊ธฐ์ž…๋‹ˆ๋‹ค.

์•„์ง ํ•ด๋‹น ์บ˜๋ฆฐ๋”๋ฅผ ์ž˜ ์‚ฌ์šฉํ•˜๋Š”์ง„ ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ ๋ถ„๋ช… 2๋ถ„๊ธฐ์—๋Š” 1๋ถ„๊ธฐ๋ณด๋‹ค ์‹œ๊ฐ„์„ ์ž˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์–ด๋–ค ์ผ์ด ์—†๋‹ค๋ฉด์š”โ€ฆ ์ธ์ƒ์€ ๋ณ€์ˆ˜์˜ ์—ฐ์†!

๊ฒฐ๋ก โ€‹

4์›” ์•ก์…˜ ํฌ์ธํŠธ

  • ์‹ค๋ฌด์—์„œ ๋งŒ๋‚œ ๋ฌธ์ œ ๊ทผ๋ณธ์ ์œผ๋กœ 2๊ฐœ ์ด์ƒ ํ•ด๊ฒฐ
  • Git ๋ฌธ์„œ ์ •๋ฆฌํ•˜๊ณ  Merge์™€ rebase ์„ธ์…˜ ์ •๋ฆฌ ๋ฐ ๊ณต์œ 
  • ๋ฐฑ์—”๋“œ CI/CD ํ™œ์šฉํ•˜์—ฌ ECS์— ์ปจํ…Œ์ด๋„ˆ ์ž๋™ ๋ฐฐํฌ ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ•
  • FSD์˜ Public API ๋ฐฉ์‹์™€ ๋ฒˆ๋“ค๋Ÿฌ ์—ฐ๊ด€์ง€์–ด ์ธ์‚ฌ์ดํŠธ ์ •๋ฆฌ
  • HTTP ์ „์†ก ๊ณ„์ธต์— ๋Œ€ํ•ด ์ •ํ™•ํžˆ ์ •๋ฆฌ
  • ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋ณด์•ˆ ๋ฌธ์„œํ™”ํ•˜๊ธฐ (XSS ๋ฐ CSRF ๊ณต๊ฒฉ)
  • FSD ์ ์šฉ๊ธฐ ํฌ์ŠคํŠธ 2ํŽธ ์ž‘์„ฑํ•˜๊ธฐ
  • ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ๋Œ€ํ•ด ํ•™์Šต ์‹œ์ž‘ํ•˜๊ธฐ
  • ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ๋Œ€ํ•ด ํ•™์Šต ์‹œ์ž‘ํ•˜๊ธฐ

4์›”์€ 1๋ถ„๊ธฐ๋ฅผ ๋›ฐ์–ด๋„˜์–ด ๋” ์น˜์—ดํ•˜๊ฒŒ ํ•™์Šตํ•˜๊ณ  ์ ์šฉํ•˜๋Š” ์‹œ๊ฐ„์„ ๊ฐ€์ง€๋ฉฐ ์‚ฌ๋‚ด์— ๋” ๋งŽ์€ ๊ธฐ์—ฌ์™€ ์„ฑ์žฅ์„ ๊ธฐ๋Œ€ํ•ด๋ด…๋‹ˆ๋‹ค.