diff --git a/keyword/chapter10/keyword.md b/keyword/chapter10/keyword.md new file mode 100644 index 00000000..69a6e81a --- /dev/null +++ b/keyword/chapter10/keyword.md @@ -0,0 +1,1248 @@ +# ๐Ÿ“ย ํ•™์Šต ๋ชฉํ‘œ + +--- + +**1) Referential Equality(์ฐธ์กฐ ๋™์ผ์„ฑ)์˜ ์›๋ฆฌ ์ดํ•ด ๋ฐ ์ ์šฉ** + +- ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๊ฐ’(Primitive) ํƒ€์ž…๊ณผ ์ฐธ์กฐ(Object) ํƒ€์ž…์˜ ์ฐจ์ด๋ฅผ ๋ฉ”๋ชจ๋ฆฌ ๊ด€์ ์—์„œ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค. +- `==`, `===`, `Object.is`์˜ ๋น„๊ต ๋ฐฉ์‹ ์ฐจ์ด๋ฅผ ์ดํ•ดํ•˜๊ณ , ์ƒํ™ฉ์— ๋งž๊ฒŒ ๊ตฌ๋ณ„ํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. +- React์˜ ๋ถˆ๋ณ€์„ฑ(Immutability)๊ณผ ์ฐธ์กฐ ๋™์ผ์„ฑ์ด ๋ Œ๋”๋ง ์ตœ์ ํ™”์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ์„ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค. + +**2) React ์„ฑ๋Šฅ ์ตœ์ ํ™”(Optimization) Hooks ๋งˆ์Šคํ„ฐ** + +- `useCallback`, `useMemo`, `React.memo`์˜ ๊ฐœ๋…๊ณผ ์ฐจ์ด์ ์„ ๋ช…ํ™•ํžˆ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค. +- ๋ฉ”๋ชจ์ด์ œ์ด์…˜(Memoization)์ด ๋ฌด์—‡์ธ์ง€ ์ดํ•ดํ•˜๊ณ , ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. +- ์˜์กด์„ฑ ๋ฐฐ์—ด(Dependency Array)๊ณผ ์ฐธ์กฐ ๋™์ผ์„ฑ์˜ ๊ด€๊ณ„๋ฅผ ํŒŒ์•…ํ•˜์—ฌ `stale closure` ๋ฌธ์ œ๋ฅผ ์˜ˆ๋ฐฉํ•  ์ˆ˜ ์žˆ๋‹ค. +- ๋ฌด์กฐ๊ฑด์ ์ธ ์ตœ์ ํ™”๊ฐ€ ์•„๋‹Œ, ์„ฑ๋Šฅ์ƒ ์ด์ ์ด ์žˆ๋Š” ๊ฒฝ์šฐ๋ฅผ ํŒ๋‹จํ•˜์—ฌ ์ ์ ˆํ•œ Hook์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋‹ค. + +**3) Vercel์„ ํ™œ์šฉํ•œ ์‹ค์ „ ๋ฐฐํฌ ๋ฐ ์„œ๋ฒ„ ํ™˜๊ฒฝ ์ดํ•ด** + +- ๋ฐฐํฌ(Deployment)์˜ ํ•ต์‹ฌ ๊ฐœ๋…(Build, Hosting)๊ณผ ๋กœ์ปฌ(Local) ํ™˜๊ฒฝ๊ณผ์˜ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค. +- Vercel๊ณผ GitHub๋ฅผ ์—ฐ๋™ํ•˜์—ฌ ์ฝ”๋“œ ํ‘ธ์‹œ ์‹œ ์ž๋™์œผ๋กœ ๋ฐฐํฌ๋˜๋Š” ํ๋ฆ„์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋‹ค. +- SPA(Single Page Application) ๋ฐฐํฌ ์‹œ ๋ฐœ์ƒํ•˜๋Š” ๋ผ์šฐํŒ… ๋ฌธ์ œ(404 ์—๋Ÿฌ)๋ฅผ `vercel.json`์œผ๋กœ ํ•ด๊ฒฐํ•˜๊ณ , ํ™˜๊ฒฝ๋ณ€์ˆ˜(Environment Variables)๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. + +**4) CI/CD ๊ฐœ๋… ์ดํ•ด์™€ ๋ชจ๋˜ ์›น ๊ฐœ๋ฐœ ํ”„๋กœ์„ธ์Šค ์ •๋ฆฝ** + +- CI(์ง€์†์  ํ†ตํ•ฉ)์™€ CD(์ง€์†์  ๋ฐฐํฌ)์˜ ์ •์˜์™€ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ (์ƒ์‚ฐ์„ฑ, ์•ˆ์ •์„ฑ)๋ฅผ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค. +- ์ž๋™ํ™”๋œ ๋ฐฐํฌ ์‹œ์Šคํ…œ์ด ๊ฐœ๋ฐœ์ž์˜ ์‹ค์ˆ˜(Human Error)๋ฅผ ์ค„์—ฌ์ฃผ๋Š” ์›๋ฆฌ๋ฅผ ์ดํ•ดํ•œ๋‹ค. +- ์ปค์Šคํ…€ ๋„๋ฉ”์ธ ์—ฐ๊ฒฐ ๊ณผ์ •์„ ํ†ตํ•ด ์‹ค์ œ ์‚ฌ์šฉ์ž๊ฐ€ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ์„œ๋น„์Šค๋ฅผ ์™„์„ฑํ•˜๋Š” ๊ฒฝํ—˜์„ ๊ฐ–๋Š”๋‹ค. + +# โš ๏ธย ์Šคํ„ฐ๋”” ์ง„ํ–‰ ๋ฐฉ๋ฒ• + +--- + +1. **์›Œํฌ๋ถ ์™„๋ฃŒ ํ›„ ์Šคํ„ฐ๋”” ์ฐธ์—ฌ** + - ์Šคํ„ฐ๋”” ์ „, ์›Œํฌ๋ถ ๋‚ด์šฉ์„ **๋ชจ๋‘ ์ž‘์„ฑ**ํ•˜๊ณ  ์ดํ•ด๋˜์ง€ ์•Š์€ ๋ถ€๋ถ„์„ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค. +2. **์Šคํ„ฐ๋”” ๋ฏธ์…˜ ์ˆ˜ํ–‰** + - ์›Œํฌ๋ถ ์™„๋ฃŒ ํ›„ ๋ฏธ์…˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. + - ์ง„ํ–‰ ๋‚ด์šฉ๊ณผ ๋ฌธ์ œ์ ์„ ์Šคํ„ฐ๋”” ์‹œ๊ฐ„์— ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค. + - **์ฝ”๋“œ ๋ฆฌ๋ทฐ**๋Š” GitHub PR์—์„œ ์ƒ์‹œ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. +3. **์Šคํ„ฐ๋”” ์‹œ๊ฐ„ ๊ตฌ์„ฑ** + 1. ๊ฐ์ž ์ง„ํ–‰ํ•œ ๋ฏธ์…˜ ์ค‘ **ํ•ด๊ฒฐํ•˜์ง€ ๋ชปํ•œ ์ด์Šˆ ๊ณต์œ ** + 2. ํ•ด๋‹น ๋ฌธ์ œ๋ฅผ **์Šคํ„ฐ๋””์›๊ณผ ํ•จ๊ป˜ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• ๊ณต์œ **, ํ•„์š” ์‹œ ๊ฐ™์ด ํ•ด๊ฒฐ + 3. ๋ฏธ์…˜ ํ›„ **ํ”ผ๋“œ๋ฐฑ ๊ณต์œ  ๋ฐ ๊ฐœ์„ ** +4. **์ฃผ์ฐจ๋ณ„ ๋ฏธ์…˜ ์ œ์ถœ** + - ๋งค์ฃผ **์›Œํฌ๋ถ๊ณผ ๋ฏธ์…˜์„ ์ œ์ถœ**ํ•ฉ๋‹ˆ๋‹ค. (๋””์ž์ธ์€ ๊ฐœ์ธ ๋ณด์™„ ๊ฐ€๋Šฅ) + - ์›Œํฌ๋ถ ์™„๋ฃŒ ํ›„ [**์›Œํฌ๋ถ ํ”ผ๋“œ๋ฐฑ ํผ ์ œ์ถœ**](https://forms.gle/aXPWVZpDSfYTAiCd6?utm_source=chatgpt.com) + - ํŠน์ • ์ฃผ์ œ์— ๋งŽ์€ ํ”ผ๋“œ๋ฐฑ ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๊ฒฝ์šฐ, ํ”ผ๋“œ๋ฐฑ ์ดํ›„ ํ•ด๋‹น ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ **์ถ”๊ฐ€ ๊ฐ•์˜ ์˜์ƒ** ์ œ๊ณต ์˜ˆ์ • ([์œ ํŠœ๋ธŒ ๊ตฌ๋…](https://www.youtube.com/@yongcoding?utm_source=chatgpt.com)) + - **๐Ÿ ย ์ฝ”๋“œ ๋ฆฌ๋ทฐ ์ œ์ถœ ๊ธฐ์ค€** + - ๋ณธ์ธ์ด ๋ฆฌ๋ทฐํ•œ ์ฝ”๋“œ **์ตœ์†Œ 1๊ฐœ** + - ๋ณธ์ธ์ด ๋ฐ›์€ ๋ฆฌ๋ทฐ๋ฅผ ์ฝ”๋“œ์— **์‹ค์ œ ๋ฐ˜์˜ํ•œ ๊ฒƒ ์ตœ์†Œ 1๊ฐœ** +5. **์Šคํ„ฐ๋”” ์ธ์ฆ์ƒท** + - ๋งค์ฃผ ๋Œ€ํ‘œ ์‚ฌ์ง„ **1์žฅ** ๋‚จ๊ธฐ๊ธฐ + - ์ด๋ฏธ์ง€ ์ž„๋ฒ ๋“œ ๋˜๋Š” ๋ณต์‚ฌยท๋ถ™์—ฌ๋„ฃ๊ธฐ ๊ฐ€๋Šฅ + +# ๐Ÿ“ธย ์ž ๊น ! ์Šคํ„ฐ๋”” ์ธ์ฆ์ƒท์€ ์ฐ์œผ์…จ๋‚˜์š”?๐Ÿ“ธ + +--- + +* ์Šคํ„ฐ๋””๋ฆฌ๋”๊ป˜์„œ ๋Œ€ํ‘œ๋กœ ๋งค ์ฃผ์ฐจ๋งˆ๋‹ค ํ•œ ์žฅ ๋‚จ๊ฒจ์ฃผ์‹œ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค!๐Ÿ™†๐Ÿ’— + (์‚ฌ์ง„์„ ์ €์žฅํ•ด์„œ ์ด๋ฏธ์ง€ ์ž„๋ฒ ๋“œ๋ฅผ ํ•˜์…”๋„ ์ข‹๊ณ , ๋ณต์‚ฌ+๋ถ™์—ฌ๋„ฃ๊ธฐํ•ด์„œ ๋„ฃ์–ด์ฃผ์…”๋„ ์ข‹์Šต๋‹ˆ๋‹ค!) + +[]() + +# ๐ŸŽฏย ํ•ต์‹ฌ ํ‚ค์›Œ๋“œ + +--- + + + +- **`Referential Equality` (์ฐธ์กฐ ๋™์ผ์„ฑ)** ๐Ÿ  + - **`Referential Equality`๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?** + + # **`Referential Equality`๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?** + + ๊ฐ„๋‹จํžˆ ๋งํ•˜๋ฉด, + + > **์ฐธ์กฐ ๋™์ผ์„ฑ**์€ โ€œ๋‘ ๋ณ€์ˆ˜๊ฐ€ **์™„์ „ํžˆ ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋Š”๊ฐ€**?โ€๋ฅผ ๋ณด๋Š” ๊ฐœ๋…์ด์—์š”. + > + - โ€œ๊ฐ™์€ ๊ฐ’์ด๋ƒ?โ€๊ฐ€ ์•„๋‹ˆ๋ผ โ€œ๊ฐ™์€ **๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ(๊ฐ™์€ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค)**๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋ƒ?โ€๋ฅผ ๋ฌป๋Š” ๊ฑฐ์—์š”. + + ๊ทธ๋ž˜์„œ **โ€œ๋‘ ๊ฐ์ฒด๊ฐ€ ์ง„์งœ๋กœ ๊ฐ™์€ ๋…€์„์ด๋ƒ?โ€** ๋ฅผ ํ™•์ธํ•  ๋•Œ ์“ฐ๋Š” ๊ธฐ์ค€์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ์–ด์š”. + + --- + + ## 1. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๊ฐ’ vs ์ฐธ์กฐ์—์š” + + --- + + ### 1-1. ๊ฐ’(primitive) ํƒ€์ž… + + - `number`, `string`, `boolean`, `null`, `undefined`, `bigint`, `symbol` + - ๋ณ€์ˆ˜ ์•ˆ์— **๊ฐ’ ์ž์ฒด๊ฐ€ ๋“ค์–ด์žˆ๋Š” ๊ฒฝ์šฐ**์—์š”. + + ```jsx + let a = 10; + let b = 10; + + console.log(a === b); // true (๊ฐ’ ๋น„๊ต) + ``` + + --- + + ### 1-2. ์ฐธ์กฐ(object) ํƒ€์ž… + + - `object`, `array`, `function`, `Date`, `Map` ๋“ฑ + - ๋ณ€์ˆ˜ ์•ˆ์—๋Š” โ€œ๊ฐ์ฒด๊ฐ€ ์ €์žฅ๋œ ๋ฉ”๋ชจ๋ฆฌ ์œ„์น˜(์ฐธ์กฐ)โ€๊ฐ€ ๋“ค์–ด์žˆ์–ด์š”. + + ```jsx + const obj1 = { x: 1 }; + const obj2 = { x: 1 }; + const obj3 = obj1; + + console.log(obj1 === obj2); // false (์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด(์ฃผ์†Œ๊ฐ’)์—์š”) + console.log(obj1 === obj3); // true (๊ฐ™์€ ๊ฐ์ฒด(์ฃผ์†Œ๊ฐ’)๋ฅผ ๊ฐ€๋ฆฌ์ผœ์š”) + ``` + + - `obj1`๊ณผ `obj2`๋Š” ๋ชจ์–‘์€ ๊ฐ™์ง€๋งŒ **์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด**์—์š”. + - `obj1`๊ณผ `obj3`๋Š” **์ •ํ™•ํžˆ ๊ฐ™์€ ๊ฐ์ฒด**๋ฅผ ๊ณต์œ ํ•ด์š”. + + โ†’ ์ด ๋‘˜์ด โ€œ์ฐธ์กฐ ๋™์ผโ€ํ•˜๋‹ค๊ณ  ๋งํ•˜๋Š” ๊ฑฐ์˜ˆ์š”. + + + --- + + ## 2. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ==, ===, Object.is ์—์š” + + --- + + ### 2-1. `==` (๋А์Šจํ•œ ๋™๋“ฑ) + + - ํƒ€์ž…์„ **์•”๋ฌต์ ์œผ๋กœ ๋ณ€ํ™˜**ํ•˜๋ฉด์„œ ๋น„๊ตํ•ด์š”. + - ์˜ˆ์ธกํ•˜๊ธฐ ์–ด๋ ค์šด ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„์„œ, **์‹ค๋ฌด์—์„œ๋Š” ๊ฑฐ์˜ ์•ˆ ์“ฐ๋Š” ๊ฒŒ ์ข‹์•„์š”.** + + ```jsx + 0 == false; // true + "" == false; // true + null == undefined; // true + ``` + + --- + + ### 2-2 `===` (์—„๊ฒฉํ•œ ๋™๋“ฑ) + + - ํƒ€์ž… ๋ณ€ํ™˜ ์—†์ด **๊ทธ๋Œ€๋กœ ๋น„๊ต**ํ•ด์š”. + - primitive์—์„œ๋Š” โ€œ๊ฐ’ ๋™์ผ์„ฑโ€ + - ๊ฐ์ฒด/๋ฐฐ์—ด/ํ•จ์ˆ˜์—์„œ๋Š” โ€œ์ฐธ์กฐ ๋™์ผ์„ฑโ€์„ ๋น„๊ตํ•ด์š”. + + ```jsx + // primitive + 1 === 1; // true + "hi" === "hi"; // true + + // object + const a = { x: 1 }; + const b = { x: 1 }; + const c = a; + + a === b; // false (์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด) + a === c; // true (์ฐธ์กฐ ๋™์ผ์„ฑ) + ``` + + --- + + ### 2-3. `Object.is` + + - ๊ธฐ๋ณธ์ ์œผ๋กœ `===`์™€ ๋น„์Šทํ•˜์ง€๋งŒ, + - `NaN` ๋น„๊ต, `+0` vs `-0` ๊ฐ™์€ ํŠน์ˆ˜ ์ผ€์ด์Šค์—์„œ๋งŒ ์กฐ๊ธˆ ๋‹ฌ๋ผ์š”. + + ```jsx + NaN === NaN; // false + Object.is(NaN, NaN); // true + + +0 === -0; // true + Object.is(+0, -0); // false + ``` + + - **๊ฐ์ฒด์— ๋Œ€ํ•ด์„œ๋Š” `===`์™€ ๋˜‘๊ฐ™์ด ์ฐธ์กฐ ๋™์ผ์„ฑ**์„ ๋น„๊ตํ•ด์š”. + + ```jsx + const obj1 = {}; + const obj2 = obj1; + + Object.is(obj1, obj2); // true (๊ฐ™์€ ์ฐธ์กฐ์—์š”) + ``` + + --- + + ## 3. ๊ฐ์ฒด/๋ฐฐ์—ด/ํ•จ์ˆ˜์—์„œ ์ฐธ์กฐ ๋™์ผ์„ฑ ์˜ˆ์ œ + + --- + + ### 3-1. ๊ฐ์ฒด + + ```jsx + const user1 = { name: "kim" }; + const user2 = { name: "kim" }; + const user3 = user1; + + console.log(user1 === user2); // false + console.log(user1 === user3); // true + ``` + + - `user1`๊ณผ `user2`๋Š” **๊ฐ’์€ ๊ฐ™์•„ ๋ณด์—ฌ๋„** ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด์—์š”. + - `user1`๊ณผ `user3`๋Š” ๊ฐ™์€ ์ฐธ์กฐ๋ฅผ ๊ณต์œ ํ•˜๋‹ˆ๊นŒ ์ฐธ์กฐ ๋™์ผ์ด์—์š”. + + --- + + ### 3-2. ๋ฐฐ์—ด + + ```jsx + const arr1 = [1, 2, 3]; + const arr2 = [1, 2, 3]; + const arr3 = arr1; + + console.log(arr1 === arr2); // false + console.log(arr1 === arr3); // true + ``` + + โ€œ๋ฐฐ์—ด ๋‚ด์šฉ์ด ๊ฐ™์€์ง€โ€๋ฅผ ๋ณด๋ ค๋ฉด **์ง์ ‘ ๋น„๊ต ๋กœ์ง**์ด ํ•„์š”ํ•ด์š”. + + ```jsx + const isArrayEqual = (a, b) => + a.length === b.length && a.every((v, i) => v === b[i]); + + console.log(isArrayEqual(arr1, arr2)); // true (๊ฐ’ ๋™์ผ์„ฑ) + ``` + + --- + + ### 3-3. ํ•จ์ˆ˜ + + ```jsx + function foo() {} + + const bar = function () {}; + + const baz = foo; + + console.log(foo === bar); // false (๋‹ค๋ฅธ ํ•จ์ˆ˜ ๊ฐ์ฒด) + console.log(foo === baz); // true (๊ฐ™์€ ํ•จ์ˆ˜ ๊ฐ์ฒด) + ``` + + - ํ•จ์ˆ˜๋„ ๊ฒฐ๊ตญ **๊ฐ์ฒด**๋ผ์„œ, ์ฐธ์กฐ ๋‹จ์œ„๋กœ ๋น„๊ต๋ผ์š”. + + --- + + ## 4. ์ฐธ์กฐ ๋™์ผ์„ฑ์ด ์ค‘์š”ํ•œ ์ด์œ  + + --- + + ### 4-1. ๊ฐ€๋ณ€ ๊ฐ์ฒด ๊ณต์œ ๋กœ ์ธํ•œ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ + + ```jsx + const state = { count: 0 }; + + function increment(s) { + s.count += 1; + return s; + } + + const a = state; + const b = increment(state); + + console.log(a === b); // true (๊ฐ™์€ ๊ฐ์ฒด) + console.log(state.count); // 1 + console.log(a.count); // 1 + console.log(b.count); // 1 + ``` + + - `state`, `a`, `b` ์„ธ ๋ณ€์ˆ˜๊ฐ€ **๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๊ณต์œ **ํ•˜๊ณ  ์žˆ์–ด์š”. + - ์–ด๋А ํ•œ ๊ณณ์—์„œ `count`๋ฅผ ๋ฐ”๊พธ๋ฉด **์ „๋ถ€ ๋™์‹œ์— ๋ฐ”๋€Œ๋Š” ํšจ๊ณผ**๊ฐ€ ๋‚˜์š”. + - โ€œ์—ฌ๊ธฐ๋งŒ ๋ฐ”๊พผ ์ค„ ์•Œ์•˜๋Š”๋ฐ, ์ €๊ธฐ๋„ ๊ฐ™์ด ๋ฐ”๋€Œ์—ˆ๋‹คโ€๋Š” ๋ฒ„๊ทธ๊ฐ€ ๋‚˜๊ธฐ ์‰ฌ์šด ํŒจํ„ด์ด์—์š”. + + --- + + ### 4-2. ๋ถˆ๋ณ€ ๊ฐ์ฒด(immutable) + ์ฐธ์กฐ ๋™์ผ์„ฑ + + ```jsx + const state = { count: 0 }; + + function incrementImmutable(s) { + return { ...s, count: s.count + 1 }; + } + + const a = state; + const b = incrementImmutable(state); + + console.log(a === b); // false (์ƒˆ ๊ฐ์ฒด) + console.log(a.count); // 0 + console.log(b.count); // 1 + ``` + + - **์›๋ณธ์€ ๊ทธ๋Œ€๋กœ ๋‘๊ณ , ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋ฐ˜ํ™˜**ํ•ด์š”. + - ์ด ํŒจํ„ด์„ ์“ฐ๋ฉด + - ๊ณผ๊ฑฐ ์ƒํƒœ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณด๊ด€ํ•  ์ˆ˜ ์žˆ๊ณ  + - โ€œ์ฐธ์กฐ๊ฐ€ ๋ฐ”๋€Œ์—ˆ๋Š”์ง€โ€๋งŒ ๋ด๋„ ๋ณ€๊ฒฝ ์—ฌ๋ถ€๋ฅผ ์–ด๋А ์ •๋„ ์•Œ ์ˆ˜ ์žˆ์–ด์š”. + + ๋ฆฌ์•กํŠธ์—์„œ + + - `useMemo`, `useCallback` + - `React.memo`, `shouldComponentUpdate` + - ๋ฆฌ๋•์Šค์˜ ์ƒํƒœ ๋น„๊ต + + ๊ฐ™์€ ๊ณณ์—์„œ **โ€œ์ฐธ์กฐ๊ฐ€ ๋ฐ”๋€Œ์—ˆ๋ƒ?โ€๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ฆฌ๋ Œ๋”๋ง/๊ณ„์‚ฐ ์ตœ์ ํ™”๋ฅผ ํ•˜๋Š” ์ด์œ **๊ฐ€ ์—ฌ๊ธฐ์— ์žˆ์–ด์š”. + + --- + + ## 5. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์ž์ฃผ ํ•˜๋Š” ์‹ค์ˆ˜๋“ค + + --- + + ### 5-1. โ€œ๊ฐ์ฒด ๋‚ด์šฉ์ด ๊ฐ™์€๋ฐ ์™œ false์ฃ ?โ€ + + ```jsx + const a = { x: 1 }; + const b = { x: 1 }; + + console.log(a === b); // false + ``` + + - ์ด ๋น„๊ต๋Š” **โ€œ๊ฐ™์€ ๊ฐ์ฒด๋ƒ?โ€** ๋ฅผ ๋ฌป๋Š” ๊ฑฐ์˜ˆ์š”. + - โ€œ๋‚ด์šฉ์ด ๊ฐ™๋ƒ?โ€๋ฅผ ๋ณด๋ ค๋ฉด ๋ณ„๋„์˜ **deepEqual** ๋กœ์ง์ด๋‚˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์จ์•ผ ํ•ด์š”. + + --- + + ### 5-2. ๋ฐฐ์—ด๋„ ๋งˆ์ฐฌ๊ฐ€์ง€ + + ```jsx + [1, 2, 3] === [1, 2, 3]; // ํ•ญ์ƒ false + ``` + + ๋งค๋ฒˆ ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์ง€๋Š” ๋ฐฐ์—ด์€ **๋‹ค ๋‹ค๋ฅธ ๊ฐ์ฒด**๋ผ์„œ, ์ฐธ์กฐ ๋™์ผ์„ฑ์ด ๊นจ์ ธ์š”. + + --- + + ### 5-3. ์ƒํƒœ๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•˜๋ฉด์„œ, ์ฐธ์กฐ ๋น„๊ต๋กœ ๋ณ€๊ฒฝ ์—ฌ๋ถ€๋ฅผ ๋ณด๋ ค๋Š” ๊ฒฝ์šฐ + + ```jsx + const state = { x: 1 }; + + function mutate(s) { + s.x = 2; + } + + mutate(state); + + console.log(state === state); // ํ•ญ์ƒ true์ฃ โ€ฆ + ``` + + - โ€œ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ์ˆ˜์ •โ€ํ–ˆ๋Š”๋ฐ, ์ฐธ์กฐ๋Š” ๊ทธ๋Œ€๋กœ๋‹ˆ๊นŒ ์ฐธ์กฐ ๋™์ผ์„ฑ์œผ๋กœ๋Š” ๋ณ€๊ฒฝ ์—ฌ๋ถ€๋ฅผ ์•Œ ์ˆ˜ ์—†์–ด์š”. + - ์ฐธ์กฐ ๋น„๊ต๋กœ ๋ณ€๊ฒฝ ์—ฌ๋ถ€๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด **๋ถˆ๋ณ€ ํŒจํ„ด(์ƒˆ ๊ฐ์ฒด ์ƒ์„ฑ)**์„ ์จ์•ผ ํ•ด์š”. + + - **๋ฆฌ์•กํŠธ ๋ Œ๋”๋ง ์ตœ์ ํ™”**์™€ **`Referential Equality`**๋Š” ์–ด๋–ค ๊ด€๊ณ„๊ฐ€ ์žˆ์„๊นŒ์š”? ๐Ÿ  + + ๋ฆฌ์•กํŠธ๋Š” ๊ฐ์ฒด์˜ **๋‚ด์šฉ์„ ๋น„๊ตํ•˜์ง€ ์•Š๊ณ  ์ฐธ์กฐ ๋™์ผ์„ฑ(`===`)** ์œผ๋กœ props์™€ state์˜ ๋ณ€๊ฒฝ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จ. + + ๋”ฐ๋ผ์„œ ๊ฐ์ฒดยท๋ฐฐ์—ดยทํ•จ์ˆ˜๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜๋ฉด ๊ฐ’์ด ๊ฐ™์•„๋„ ์ฐธ์กฐ๊ฐ€ ๋‹ฌ๋ผ์ ธ ๋ฆฌ๋ Œ๋”๋ง์ด ๋ฐœ์ƒ! + + `React.memo`, `useMemo`, `useCallback`์€ ์ด๋Ÿฌํ•œ **๋ถˆํ•„์š”ํ•œ ์ฐธ์กฐ ๋ณ€๊ฒฝ์„ ๋ง‰์•„,** ๋ฆฌ๋ Œ๋”๋ง๊ณผ ์žฌ๊ณ„์‚ฐ์„ ์ตœ์ ํ™”ํ•˜๊ธฐ ์œ„ํ•œ ๋„๊ตฌ. + + ์ด๋ฅผ ์ œ๋Œ€๋กœ ํ™œ์šฉํ•˜๋ ค๋ฉด ์ƒํƒœ๋ฅผ **๋ถˆ๋ณ€ ๊ฐ์ฒด๋กœ ๊ด€๋ฆฌ**ํ•ด ์ฐธ์กฐ ๋ณ€๊ฒฝ์ด ์˜๋ฏธ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ๋ฐœ์ƒํ•˜๋„๋ก ํ•ด์•ผ ํ•จ. + +- **`useCallabck`๊ณผ `memo`** ๐Ÿ  + + ### ๐ŸŽฅ ์‹ค์Šต 1. ๊ฐ•์˜ ์˜์ƒ + + https://www.youtube.com/watch?v=Z3uNjFqYSF8&t=904s + + + + - **`useCallabck`** ์— ๋Œ€ํ•˜์—ฌ ์ •๋ฆฌํ•ด์ฃผ์„ธ์š”! ๐Ÿ  + + # **`useCallabck`** ์— ๋Œ€ํ•˜์—ฌ ์ •๋ฆฌํ•ด์ฃผ์„ธ์š”! ๐Ÿ  + + --- + + - **`useCallabck`** ์ด ๋ฌด์—‡์ธ์ง€? ๐Ÿ  + + # **`useCallabck`** ์ด ๋ฌด์—‡์ธ์ง€? + + --- + + - ํ•จ์ˆ˜(์ฝœ๋ฐฑ)๋ฅผ โ€œ๋ฉ”๋ชจ์ด์ œ์ด์…˜โ€ ํ•œ๋‹ค๋Š” ๊ฒŒ ๋ฌด์Šจ ๋œป์ธ์ง€? + - ํ•จ์ˆ˜์˜ **์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ**, + + **ํ•จ์ˆ˜ ๊ฐ์ฒด ์ž์ฒด(์ฐธ์กฐ)๋ฅผ ์ €์žฅ**ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. + + - dependencies๊ฐ€ ๊ฐ™์œผ๋ฉด โ†’ **์ด์ „ ํ•จ์ˆ˜ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜** + - dependencies๊ฐ€ ๋ฐ”๋€Œ๋ฉด โ†’ **์ƒˆ ํ•จ์ˆ˜ ์ƒ์„ฑ** + - ์–ธ์ œ ์ƒˆ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๊ณ , ์–ธ์ œ ๊ธฐ์กด ํ•จ์ˆ˜๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š”์ง€? + - ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‹ค์‹œ ๋ Œ๋”๋ง๋˜์–ด๋„ **์˜์กด์„ฑ์ด ๋ณ€ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ฐ™์€ ํ•จ์ˆ˜ ์ฐธ์กฐ๋ฅผ ์žฌ์‚ฌ์šฉ**ํ•œ๋‹ค. + - ์ฆ‰, ๋งค ๋ Œ๋”๋งˆ๋‹ค ์ƒˆ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๊ณ  **๊ธฐ์กด ํ•จ์ˆ˜๋ฅผ ์œ ์ง€**ํ•ด์ค€๋‹ค. + - ์˜์กด์„ฑ์ด ๋ณ€ํ•  ๋•Œ๋งŒ ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑ. + - ์™œ **`useCallabck`**์„ ์‚ฌ์šฉํ•˜๋Š”์ง€? ๐Ÿ  + + # ์™œ **`useCallabck`**์„ ์‚ฌ์šฉํ•˜๋Š”์ง€? + + --- + + - **๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง ๋ฐฉ์ง€**์™€ ์–ด๋–ค ๊ด€๋ จ์ด ์žˆ๋Š”์ง€ + - React๋Š” props๋ฅผ `===`๋กœ ๋น„๊ตํ•œ๋‹ค. + - ๋งค ๋ Œ๋”๋งˆ๋‹ค ์ƒˆ ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑ๋˜๋ฉด ์ฐธ์กฐ๊ฐ€ ๋‹ฌ๋ผ์ ธ + + `React.memo`๋กœ ๊ฐ์‹ผ ์ž์‹๋„ ๋‹ค์‹œ ๋ Œ๋”๋ง๋œ๋‹ค. + + - `useCallback`์€ **ํ•จ์ˆ˜ ์ฐธ์กฐ๋ฅผ ๊ณ ์ •**ํ•ด ์ด๋ฅผ ๋ง‰์•„์ค€๋‹ค. + - ์„ฑ๋Šฅ ์ตœ์ ํ™” ๊ด€์ ์—์„œ ์–ป๋Š” ์ด๋“ vs ๋‚จ์šฉํ–ˆ์„ ๋•Œ์˜ ์˜ค๋ฒ„ํ—ค๋“œ + - `useCallback`์€ ํ•จ์ˆ˜ ์ฐธ์กฐ๋ฅผ ์œ ์ง€ํ•ด **๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง๊ณผ ์žฌ๊ณ„์‚ฐ์„ ์ค„์ด๋Š” ์ด์ **์ด ์žˆ๋‹ค. + - ํŠนํžˆ `React.memo`๋กœ ๊ฐ์‹ผ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์— ์ฝœ๋ฐฑ์„ ์ „๋‹ฌํ•  ๋•Œ ํšจ๊ณผ์ ์ด๋‹ค. + - ํ•˜์ง€๋งŒ ๋ชจ๋“  ํ•จ์ˆ˜์— ์‚ฌ์šฉํ•˜๋ฉด **์˜์กด์„ฑ ๋น„๊ต ๋น„์šฉ๊ณผ ์ฝ”๋“œ ๋ณต์žก๋„**๊ฐ€ ์ฆ๊ฐ€ํ•œ๋‹ค. + - ๋”ฐ๋ผ์„œ ์‹ค์ œ ์„ฑ๋Šฅ ์ด๋“์ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ **์„ ๋ณ„์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”**ํ•˜๋‹ค. + - **`useCallabck`** ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ• ๐Ÿ  + + # **`useCallabck`** ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ• + + --- + + - **`useCallabck`**์€ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋‚˜์š”? (์ฝ”๋“œ) + + ```tsx + import { useCallback } from "react"; + + const handleClick = useCallback(() => { + console.log("click"); + }, []); + ``` + + - `deps` ๋ฐฐ์—ด์— ๋ฌด์—‡์„ ๋„ฃ์–ด์•ผ ํ•˜๋Š”์ง€ ๊ทœ์น™ + - ์ฝœ๋ฐฑ ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•˜๋Š” **state, props, ๋ณ€์ˆ˜๋Š” ๋ชจ๋‘ deps์— ํฌํ•จ**ํ•ด์•ผ ํ•œ๋‹ค. + - deps๋Š” **ํ•ญ์ƒ ๊ณ ์ •๋œ ๊ธธ์ด์˜ ๋ฐฐ์—ด**์ด์–ด์•ผ ํ•œ๋‹ค. + - React๋Š” deps๋ฅผ `Object.is`๋กœ ๋น„๊ตํ•œ๋‹ค. + - ์˜์กด์„ฑ ๋ณ€๊ฒฝ ์‹œ ์ฝœ๋ฐฑ์ด ์–ด๋–ป๊ฒŒ ๋‹ค์‹œ ๋งŒ๋“ค์–ด์ง€๋Š”์ง€ + - `useCallback`์€ ๋ Œ๋”๋ง ์‹œ๋งˆ๋‹ค **์˜์กด์„ฑ ๋ฐฐ์—ด(deps)์„ ์ด์ „ ๊ฐ’๊ณผ ๋น„๊ต**ํ•œ๋‹ค. + - React๋Š” ๊ฐ ์˜์กด์„ฑ์„ `Object.is`๋กœ ๋น„๊ตํ•ด ๋ณ€๊ฒฝ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•œ๋‹ค. + - deps ์ค‘ ํ•˜๋‚˜๋ผ๋„ ๋ณ€๊ฒฝ๋˜๋ฉด **๊ธฐ์กด ์ฝœ๋ฐฑ์„ ๋ฒ„๋ฆฌ๊ณ  ์ƒˆ ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑ**ํ•œ๋‹ค. + - ๋ชจ๋“  ์˜์กด์„ฑ์ด ๋™์ผํ•˜๋ฉด **์ด์ „ ๋ Œ๋”์—์„œ ์ƒ์„ฑ๋œ ์ฝœ๋ฐฑ์„ ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉ**ํ•œ๋‹ค. + - **`useCallabck`**์—์„œ ์ค‘์š”ํ•œ ๊ฐœ๋… ๐Ÿ  + + # **`useCallabck`**์—์„œ ์ค‘์š”ํ•œ ๊ฐœ๋… + + --- + + - **์ฐธ์กฐ ๋™์ผ์„ฑ(reference equality)** ์ด ์™œ ์ค‘์š”ํ•œ์ง€ (=== ๋น„๊ต) + - React๋Š” ๊ฐ์ฒดยท๋ฐฐ์—ดยทํ•จ์ˆ˜์˜ ๋ณ€๊ฒฝ ์—ฌ๋ถ€๋ฅผ **๊ฐ’์ด ์•„๋‹ˆ๋ผ ์ฐธ์กฐ ๋™์ผ์„ฑ(`===`)** ์œผ๋กœ ํŒ๋‹จํ•œ๋‹ค. + - ์ฐธ์กฐ๊ฐ€ ๊ฐ™์œผ๋ฉด โ€œ๋ณ€๊ฒฝ ์—†์Œโ€, ์ฐธ์กฐ๊ฐ€ ๋‹ค๋ฅด๋ฉด โ€œ๋ณ€๊ฒฝ ์žˆ์Œโ€์œผ๋กœ ์ธ์‹ํ•œ๋‹ค. + - ๋”ฐ๋ผ์„œ ๊ฐ’์ด ๊ฐ™์•„๋„ ์ƒˆ ๊ฐ์ฒด๋‚˜ ์ƒˆ ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑ๋˜๋ฉด **๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง**์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. + - `useCallback`, `useMemo`, `React.memo`๋Š” **์ฐธ์กฐ๋ฅผ ์œ ์ง€ํ•ด ์„ฑ๋Šฅ ์ตœ์ ํ™”**๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•œ๋‹ค. + - ํด๋กœ์ €์™€ ์ƒํƒœ: ์ฝœ๋ฐฑ ์•ˆ์—์„œ state, props๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ฃผ์˜ํ•  ์  + - ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” **์ƒ์„ฑ ์‹œ์ ์˜ state์™€ props๋ฅผ ํด๋กœ์ €๋กœ ์บก์ฒ˜**ํ•œ๋‹ค. + - ๋”ฐ๋ผ์„œ `useCallback`์˜ deps์— state๋‚˜ props๋ฅผ ๋ˆ„๋ฝํ•˜๋ฉด **์ตœ์‹  ๊ฐ’์ด ๋ฐ˜์˜๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค**. + - ์ฝœ๋ฐฑ ๋‚ด๋ถ€์—์„œ state๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์—…๋ฐ์ดํŠธํ•  ๊ฒฝ์šฐ, **ํ•จ์ˆ˜ํ˜• ์—…๋ฐ์ดํŠธ(`prev => โ€ฆ`)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ „**ํ•˜๋‹ค. + - ํ•ญ์ƒ ์ฝœ๋ฐฑ์—์„œ ์ฐธ์กฐํ•˜๋Š” ๊ฐ’์ด **์˜์กด์„ฑ ๋ฐฐ์—ด์— ์ •ํ™•ํžˆ ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€** ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค. + - **stale closure(๋‚ก์€ ๊ฐ’ ์บก์ฒ˜)** ๋ฌธ์ œ๋Š” ์–ธ์ œ ์ƒ๊ธฐ๋Š”์ง€, ์–ด๋–ป๊ฒŒ ํ”ผํ•˜๋Š”์ง€ + - `useCallback`์œผ๋กœ ๋งŒ๋“  ํ•จ์ˆ˜๊ฐ€ **์ƒ์„ฑ ๋‹น์‹œ์˜ state/props ๊ฐ’์„ ํด๋กœ์ €๋กœ ๊ธฐ์–ต**ํ•  ๋•Œ ๋ฐœ์ƒํ•œ๋‹ค. + - deps ๋ฐฐ์—ด์— ํ•„์š”ํ•œ state๋‚˜ props๋ฅผ ๋น ๋œจ๋ฆฌ๋ฉด, **์ตœ์‹  ๊ฐ’์ด ์•„๋‹Œ ๊ณผ๊ฑฐ ๊ฐ’**์„ ๊ณ„์† ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค. + - ์ด๋ฅผ ํ”ผํ•˜๋ ค๋ฉด **์ฝœ๋ฐฑ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ๊ฐ’๋“ค์„ deps์— ์ •ํ™•ํžˆ ํฌํ•จ**ํ•ด์•ผ ํ•œ๋‹ค. + - ์ƒํƒœ ์—…๋ฐ์ดํŠธ๊ฐ€ ๋ชฉ์ ์ด๋ผ๋ฉด `setState(prev => โ€ฆ)` ๊ฐ™์€ **ํ•จ์ˆ˜ํ˜• ์—…๋ฐ์ดํŠธ**๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด stale closure๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค. + - **`useCallabck`**์„ ์‚ฌ์šฉํ•œ ์ฝœ๋ฐฑ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ์˜ˆ์‹œ ๐Ÿ  + + # **`useCallabck`**์„ ์‚ฌ์šฉํ•œ ์ฝœ๋ฐฑ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ์˜ˆ์‹œ + + --- + + - ๋ถ€๋ชจ์—์„œ ์ž์‹์œผ๋กœ ์ฝœ๋ฐฑ์„ ๋‚ด๋ ค์ค„ ๋•Œ, `onClick`, `onChange` ๊ฐ™์€ ํ•ธ๋“ค๋Ÿฌ๋ฅผ **`useCallabck`** ์—†์ด ๋„˜๊ฒผ์„ ๋•Œ์™€ **`useCallabck`**์œผ๋กœ ๊ฐ์‹ธ์„œ ๋„˜๊ฒผ์„ ๋•Œ ์ฐจ์ด + + ### โŒ `useCallback` ์—†์ด ์ฝœ๋ฐฑ ์ „๋‹ฌ + + ```tsx + functionParent() { + consthandleClick = () => { + console.log("click"); + }; + + return; + } + ``` + + - ๋ Œ๋”๋ง๋งˆ๋‹ค **์ƒˆ ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑ** + - `Child`๊ฐ€ `memo`๋กœ ๊ฐ์‹ธ์ ธ ์žˆ์–ด๋„ **ํ•ญ์ƒ ๋ฆฌ๋ Œ๋”๋ง๋จ** + + --- + + ### โœ… `useCallback`์œผ๋กœ ๊ฐ์‹ผ ๊ฒฝ์šฐ + + ```tsx + functionParent() { + const handleClick =useCallback(() => { + console.log("click"); + }, []); + + return; + } + ``` + + - ํ•จ์ˆ˜ ์ฐธ์กฐ๊ฐ€ ์œ ์ง€๋จ + - `Child`๋Š” props๊ฐ€ ๊ฐ™๋‹ค๊ณ  ํŒ๋‹จํ•ด **๋ฆฌ๋ Œ๋”๋ง์„ ๊ฑด๋„ˆ๋œ€** + + --- + + ### ์ •๋ฆฌ ํ•œ ์ค„ โœ๏ธ + + > useCallback์€ ๋ถ€๋ชจ ๋ Œ๋”๋ง ์‹œ์—๋„ ์ฝœ๋ฐฑ ์ฐธ์กฐ๋ฅผ ์œ ์ง€ํ•ด + ์ž์‹ ์ปดํฌ๋„ŒํŠธ์˜ ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ง‰๋Š”๋‹ค. + > + + - ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ / ๋น„๋™๊ธฐ ๋กœ์ง์—์„œ **`useCallabck`** ์˜ˆ์‹œ ๐Ÿ  + + # ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ / ๋น„๋™๊ธฐ ๋กœ์ง์—์„œ **`useCallabck`** ์˜ˆ์‹œ + + --- + + - ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ API ํ˜ธ์ถœํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ๋ฅผ `useCallback`์œผ๋กœ ๊ฐ์‹ธ๋Š” ํŒจํ„ด + + ### ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ API ํ˜ธ์ถœ ํ•ธ๋“ค๋Ÿฌ + + ```tsx + const handleClick =useCallback(async () => { + awaitfetch("/api/data"); + }, []); + + ``` + + - ํด๋ฆญ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ํ•ด **๋ถˆํ•„์š”ํ•œ ํ•จ์ˆ˜ ์žฌ์ƒ์„ฑ**์„ ๋ง‰๋Š”๋‹ค. + - `memo`๋œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌํ•  ๋•Œ ํšจ๊ณผ์ ์ด๋‹ค. + - `useEffect` ์•ˆ์—์„œ ์˜์กด์„ฑ์œผ๋กœ ์ฝœ๋ฐฑ์„ ๋„ฃ์„ ๋•Œ ํŒจํ„ด + + ### `useEffect` ์˜์กด์„ฑ์œผ๋กœ ์ฝœ๋ฐฑ์„ ๋„ฃ๋Š” ํŒจํ„ด + + ```tsx + const fetchData =useCallback(() => { + fetch(`/api/${id}`); + }, [id]); + + useEffect(() => { + fetchData(); + }, [fetchData]); + + ``` + + - ์ฝœ๋ฐฑ์„ `useCallback`์œผ๋กœ ๊ฐ์‹ธ๋ฉด **Effect๊ฐ€ ํ•„์š”ํ•  ๋•Œ๋งŒ ์‹คํ–‰**๋œ๋‹ค. + - ๋งค ๋ Œ๋”๋งˆ๋‹ค Effect๊ฐ€ ๋‹ค์‹œ ์‹คํ–‰๋˜๋Š” ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•œ๋‹ค. + - ํผ ์ œ์ถœ ํ•ธ๋“ค๋Ÿฌ, ๋””๋ฐ”์šด์Šค/์Šค๋กœํ‹€ ํ•จ์ˆ˜์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ๋•Œ + + ### ํผ ์ œ์ถœ / ๋””๋ฐ”์šด์Šคยท์Šค๋กœํ‹€๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ + + ```tsx + const handleSubmit =useCallback(() => { + submitForm(form); + }, [form]); + + ``` + + - ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์˜ **์ฐธ์กฐ๋ฅผ ์•ˆ์ •์ ์œผ๋กœ ์œ ์ง€**ํ•  ์ˆ˜ ์žˆ๋‹ค. + - ๋””๋ฐ”์šด์Šคยท์Šค๋กœํ‹€ ํ•จ์ˆ˜์™€ ๊ฒฐํ•ฉ ์‹œ, **ํƒ€์ด๋จธ๊ฐ€ ๋งค๋ฒˆ ์ดˆ๊ธฐํ™”๋˜๋Š” ๋ฌธ์ œ**๋ฅผ ๋ง‰์•„์ค€๋‹ค. + + - **`memo`**์— ๋Œ€ํ•˜์—ฌ ์ •๋ฆฌํ•ด์ฃผ์„ธ์š”!๐Ÿ  + + # **`memo`**์— ๋Œ€ํ•˜์—ฌ ์ •๋ฆฌํ•ด์ฃผ์„ธ์š”!๐Ÿ  + + --- + + - **`memo`**๊ฐ€ ๋ฌด์—‡์ธ์ง€? ๐Ÿ  + + # **`memo`**๊ฐ€ ๋ฌด์—‡์ธ์ง€? + + --- + + - `memo`๋Š” **props๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์œผ๋ฉด ์ปดํฌ๋„ŒํŠธ ๋ฆฌ๋ Œ๋”๋ง์„ ๊ฑด๋„ˆ๋›ฐ๋Š”** ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ(HOC)์ด๋‹ค. + - ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋˜์–ด๋„, **props๊ฐ€ ์ด์ „๊ณผ ๊ฐ™์œผ๋ฉด ์ž์‹์€ ๋ฆฌ๋ Œ๋”๋ง๋˜์ง€ ์•Š๋Š”๋‹ค**. + - ๊ธฐ๋ณธ์ ์œผ๋กœ React๋Š” props๋ฅผ `Object.is`(์–•์€ ๋น„๊ต)๋กœ ๋น„๊ตํ•œ๋‹ค. + - ๋‹จ, `memo`๋Š” **์„ฑ๋Šฅ ์ตœ์ ํ™” ๋„๊ตฌ์ด์ง€ ๋ Œ๋”๋ง ๋ณด์žฅ์„ ์˜๋ฏธํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค**. + + - ์™œ **`memo`**๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€? ๐Ÿ  + + # ์™œ **`memo`**๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€? + + --- + + - ๋ Œ๋”๋ง ๋น„์šฉ์ด ํฐ ์ปดํฌ๋„ŒํŠธ์˜ **๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€**ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค. + - ๋ถ€๋ชจ ์ƒํƒœ ๋ณ€๊ฒฝ์ด ์žฆ์ง€๋งŒ, ์ž์‹ props๋Š” ๊ฑฐ์˜ ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์— ํšจ๊ณผ์ ์ด๋‹ค. + - `useCallback`, `useMemo`์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด **์ฐธ์กฐ ๋™์ผ์„ฑ ์œ ์ง€๋กœ ์ตœ์ ํ™” ํšจ๊ณผ๊ฐ€ ์ปค์ง„๋‹ค**. + - ๊ฒฐ๊ณผ์ ์œผ๋กœ **UI ๋ฐ˜์‘์„ฑ๊ณผ ์„ฑ๋Šฅ์„ ๊ฐœ์„ **ํ•  ์ˆ˜ ์žˆ๋‹ค. + - **`memo`** ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ• ๐Ÿ  + + # **`memo`** ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ• + + --- + + ```tsx + import { memo }from"react"; + + constChild =memo(functionChild({ value }) { + return
{value}
; + }); + ``` + + - `memo(Component)` ํ˜•ํƒœ๋กœ ๊ฐ์‹ธ์„œ ์‚ฌ์šฉํ•œ๋‹ค. + - props๊ฐ€ ์ด์ „๊ณผ ๋™์ผํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ ๋ Œ๋”๋ง์„ ๊ฑด๋„ˆ๋›ด๋‹ค. + - ํ•„์š”ํ•˜๋ฉด ๋‘ ๋ฒˆ์งธ ์ธ์ž๋กœ **์ปค์Šคํ…€ ๋น„๊ต ํ•จ์ˆ˜**๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. + - **`memo`**๋ฅผ ์–ธ์ œ ์“ฐ๋ฉด ์ข‹์€์ง€ / ์•ˆ ์ข‹์€์ง€ ๐Ÿ  + + # **`memo`**๋ฅผ ์–ธ์ œ ์“ฐ๋ฉด ์ข‹์€์ง€ / ์•ˆ ์ข‹์€์ง€ + + --- + + ### โœ… ์“ฐ๊ธฐ ์ข‹์€ ๊ฒฝ์šฐ + + - ๋ Œ๋”๋ง ๋น„์šฉ์ด ํฌ๊ณ  props ๋ณ€๊ฒฝ์ด ๋“œ๋ฌธ ์ปดํฌ๋„ŒํŠธ + - ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ, ์ฐจํŠธ, ๋ณต์žกํ•œ UI ์ปดํฌ๋„ŒํŠธ + - props๋กœ ๊ฐ์ฒดยทํ•จ์ˆ˜ ์ „๋‹ฌ ์‹œ `useCallback`/`useMemo`์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ + + ### โŒ ์•ˆ ์ข‹์€ ๊ฒฝ์šฐ + + - ๋ Œ๋”๋ง ๋น„์šฉ์ด ๋งค์šฐ ์ž‘์€ ์ปดํฌ๋„ŒํŠธ + - props๊ฐ€ ์ž์ฃผ ๋ฐ”๋€Œ๋Š” ์ปดํฌ๋„ŒํŠธ + - ๋ฌด๋ถ„๋ณ„ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด **๋น„๊ต ๋น„์šฉ๊ณผ ์ฝ”๋“œ ๋ณต์žก๋„๋งŒ ์ฆ๊ฐ€** + + ### ํ•œ ์ค„ ์š”์•ฝ โœ๏ธ + + > memo๋Š” props์˜ ์ฐธ์กฐ ๋™์ผ์„ฑ์„ ๊ธฐ์ค€์œผ๋กœ + ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ์ค„์ด๊ธฐ ์œ„ํ•œ ์ปดํฌ๋„ŒํŠธ ์ตœ์ ํ™” ๋„๊ตฌ๋‹ค. + > + + --- + + ### ๐Ÿ ย ์‹ค์Šต 1. ์ œ์ถœ + + - ๊นƒํ—ˆ๋ธŒ ์ฃผ์†Œ ๐Ÿ  + - ์‹คํ–‰ ์˜์ƒ ๐Ÿ  + +- **`useMemo`** ๐Ÿ  + + # **`useMemo`** ๐Ÿ  + + --- + + ### ๐ŸŽฅ ์‹ค์Šต 2. ๊ฐ•์˜ ์˜์ƒ + + https://youtu.be/GdnfH_WH8pg?si=lILRTKG4hFOjqrYH + + + + - **`useMemo`** ์— ๋Œ€ํ•˜์—ฌ ์ •๋ฆฌํ•ด์ฃผ์„ธ์š”! ๐Ÿ  + + # **`useMemo`** ์— ๋Œ€ํ•˜์—ฌ ์ •๋ฆฌํ•ด์ฃผ์„ธ์š”! ๐Ÿ  + + --- + + - **`useMemo`**๊ฐ€ ๋ฌด์—‡์ธ์ง€? ๐Ÿ  + + # **`useMemo`**๊ฐ€ ๋ฌด์—‡์ธ์ง€? ๐Ÿ  + + --- + + - ์™œ **`useMemo`**๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€? ๐Ÿ  + + # ์™œ **`useMemo`**๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€? ๐Ÿ  + + --- + + - **`useMemo`** ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ• ๐Ÿ  + + # **`useMemo`** ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ• ๐Ÿ  + + --- + + - **`useMemo`**์—์„œ ์ค‘์š”ํ•œ ๊ฐœ๋… ๐Ÿ  + + # **`useMemo`**์—์„œ ์ค‘์š”ํ•œ ๊ฐœ๋… ๐Ÿ  + + --- + + - **`useMemo`** ์‹ค์ „ ์˜ˆ์‹œ ๐Ÿ  + + # **`useMemo`** ์‹ค์ „ ์˜ˆ์‹œ ๐Ÿ  + + --- + + + + --- + + ### ๐Ÿ ย ์‹ค์Šต 2. ์ œ์ถœ + + - ๊นƒํ—ˆ๋ธŒ ์ฃผ์†Œ ๐Ÿ  + - ์‹คํ–‰ ์˜์ƒ ๐Ÿ  +- **Vercel**์„ ํ™œ์šฉํ•œ **`๋ฐฐํฌ`**์™€ CI/CD ๐Ÿ  + + # Vercel์„ ํ™œ์šฉํ•œ **`๋ฐฐํฌ`**์™€ CI/CD ๐Ÿ  + + --- + + + + [Vercel Documentation](https://vercel.com/docs) + + [GitHub Actions documentation - GitHub Docs](https://docs.github.com/en/actions) + + - **`๋ฐฐํฌ`**๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”? + + # **`๋ฐฐํฌ`**๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”? + + --- + + **`๋ฐฐํฌ`(Deployment)**๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋งŒ๋“  ์ฝ”๋“œ๋ฅผ ์‹ค์ œ ์‚ฌ์šฉ์ž๋“ค์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ธํ„ฐ๋„ท ์ƒ์— ๊ณต๊ฐœํ•˜๋Š” ๊ณผ์ •์ด์—์š”. ๋‚ด ์ปดํ“จํ„ฐ(Localhost)์—์„œ๋งŒ ๋Œ์•„๊ฐ€๋˜ ์›น์‚ฌ์ดํŠธ๋ฅผ, ๋ˆ„๊ตฌ๋‚˜ URL์„ ํ†ตํ•ด ์ ‘์†ํ•  ์ˆ˜ ์žˆ๋Š” (Server)๋กœ ์˜ฎ๊ธฐ๋Š” ์ž‘์—…์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ์ข‹์•„์š”. + + --- + + **ํŠน์ง• ์ •๋ฆฌ:** + + - **๋นŒ๋“œ(Build):** ์šฐ๋ฆฌ๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ(React, TypeScript ๋“ฑ)๋ฅผ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ํŒŒ์ผ(HTML, CSS, JS)๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •์ด ํ•„์š”ํ•ด์š”. + - **ํ˜ธ์ŠคํŒ…(Hosting):** ๋ณ€ํ™˜๋œ ํŒŒ์ผ๋“ค์„ 24์‹œ๊ฐ„ ์ผœ์ ธ ์žˆ๋Š” ์ปดํ“จํ„ฐ(์„œ๋ฒ„)์— ์ €์žฅํ•ด ๋‘๊ณ , ์š”์ฒญ์ด ์˜ค๋ฉด ๋ณด์—ฌ์ค˜์š”. + - **์ ‘๊ทผ์„ฑ:** ๋ฐฐํฌ๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ๊ณ ์œ ํ•œ ๋„๋ฉ”์ธ ์ฃผ์†Œ(์˜ˆ: `www.yolog.co.kr`)๊ฐ€ ์ƒ๊ฒจ์„œ ์–ด๋””์„œ๋“  ์ ‘์†ํ•  ์ˆ˜ ์žˆ์–ด์š”. + + --- + + **๋‹จ์ ๋„ ์žˆ์–ด์š”:** + + - ๊ณผ๊ฑฐ์—๋Š” ์ง์ ‘ ์„œ๋ฒ„ ์ปดํ“จํ„ฐ๋ฅผ ์‚ฌ๊ณ , ๋ฆฌ๋ˆ…์Šค๋ฅผ ์„ค์น˜ํ•˜๊ณ , ๋ณต์žกํ•œ ๋„คํŠธ์›Œํฌ ์„ค์ •์„ ํ•ด์•ผ ํ–ˆ์–ด์š”. + - ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ๋งˆ๋‹ค ์ˆ˜๋™์œผ๋กœ ํŒŒ์ผ์„ ์„œ๋ฒ„์— ์—…๋กœ๋“œํ•ด์•ผ ํ•ด์„œ ๋ฒˆ๊ฑฐ๋กญ๊ณ  ์‹ค์ˆ˜๊ฐ€ ์žฆ์•˜์–ด์š”. + - **Vercel**์€ ๋ฌด์—‡์ธ๊ฐ€์š”? + + # **Vercel**์€ ๋ฌด์—‡์ธ๊ฐ€์š”? + + --- + + **Vercel**์€ ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ณต์žกํ•œ ์„œ๋ฒ„ ์„ค์ • ์—†์ด ์•„์ฃผ ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ์›น์‚ฌ์ดํŠธ๋ฅผ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ํ”Œ๋žซํผ์ด์—์š”. + React์˜ ํ”„๋ ˆ์ž„์›Œํฌ์ธ **Next.js**๋ฅผ ๋งŒ๋“  ํŒ€์—์„œ ๊ฐœ๋ฐœํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋ฆฌ์•กํŠธ ๊ธฐ๋ฐ˜ ํ”„๋กœ์ ํŠธ์™€ ์ฐฐ๋–ก๊ถํ•ฉ์ธ ๋„๊ตฌ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ์ข‹์•„์š”. + + --- + + **ํŠน์ง•:** + + - **GitHub ์—ฐ๋™:** GitHub ์ €์žฅ์†Œ์— ์ฝ”๋“œ๋ฅผ ์˜ฌ๋ฆฌ๊ธฐ๋งŒ ํ•˜๋ฉด(Push), Vercel์ด ์•Œ์•„์„œ ๊ฐ์ง€ํ•˜๊ณ  ๋ฐฐํฌ๋ฅผ ์‹œ์ž‘ํ•ด์š”. + - **์ž๋™ ์„ค์ •:** ๋ณต์žกํ•œ ์„œ๋ฒ„ ์„ธํŒ… ์—†์ด๋„ HTTPS(๋ณด์•ˆ ์—ฐ๊ฒฐ), ๋„๋ฉ”์ธ ์„ค์ • ๋“ฑ์„ ์ž๋™์œผ๋กœ ํ•ด์ค˜์š”. + - **๋ฏธ๋ฆฌ๋ณด๊ธฐ(Preview):** ์‹ค์ œ ์„œ๋น„์Šค์— ๋ฐ˜์˜ํ•˜๊ธฐ ์ „์—, ํ…Œ์ŠคํŠธ ์ฃผ์†Œ๋ฅผ ์ƒ์„ฑํ•ด ์ค˜์„œ ํŒ€์›๋“ค๊ณผ ๋ฏธ๋ฆฌ ํ™•์ธํ•ด ๋ณผ ์ˆ˜ ์žˆ์–ด์š”. + - **๋น ๋ฅธ ์†๋„:** ์ „ ์„ธ๊ณ„ ๊ณณ๊ณณ์— ์„œ๋ฒ„(CDN)๊ฐ€ ์žˆ์–ด์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์–ด๋””์— ์žˆ๋“  ๋น ๋ฅด๊ฒŒ ์‚ฌ์ดํŠธ๋ฅผ ๋ณด์—ฌ์ค˜์š”. + + - **CI / CD**๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”? + + # **CI / CD**๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”? + + --- + + **CI/CD**๋Š” ๊ฐœ๋ฐœ๋ถ€ํ„ฐ ๋ฐฐํฌ๊นŒ์ง€์˜ ๊ณผ์ •์„ "์ž๋™ํ™”"ํ•˜์—ฌ, ๋” ์ž์ฃผ, ๋” ์•ˆ์ „ํ•˜๊ฒŒ ์ฝ”๋“œ๋ฅผ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๋ฐฉ๋ฒ•๋ก ์ด์ž ๋„๊ตฌ ๋ชจ์Œ์ด์—์š”. + ๊ฐœ๋ฐœ์ž๊ฐ€ ์ผ์ผ์ด ์ˆ˜๋™์œผ๋กœ ํ•˜๋˜ ์ผ๋“ค์„ "๋กœ๋ด‡(์Šคํฌ๋ฆฝํŠธ)"์—๊ฒŒ ๋งก๊ฒจ์„œ ์‹ค์ˆ˜๋ฅผ ์ค„์ด๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ์ด์—์š”. + + --- + + ### **1. CI (Continuous Integration - ์ง€์†์  ํ†ตํ•ฉ)** + + - **๋ฌด์—‡์ธ๊ฐ€์š”?** ์—ฌ๋Ÿฌ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ฅผ **์ž์ฃผ, ์ •๊ธฐ์ ์œผ๋กœ ํ•ฉ์น˜๋Š”(Merge)** ๊ณผ์ •์ด์—์š”. + - **ํ•˜๋Š” ์ผ:** ์ฝ”๋“œ๊ฐ€ ํ•ฉ์ณ์งˆ ๋•Œ๋งˆ๋‹ค ์ž๋™์œผ๋กœ **ํ…Œ์ŠคํŠธ**๋ฅผ ์‹คํ–‰ํ•˜๊ณ , ๋นŒ๋“œ๊ฐ€ ์ž˜ ๋˜๋Š”์ง€ ํ™•์ธํ•ด์š”. + - **์™œ ํ•˜๋‚˜์š”?** ๋ฒ„๊ทธ๋ฅผ ๋ฏธ๋ฆฌ ๋ฐœ๊ฒฌํ•ด์„œ, ์ž˜๋ชป๋œ ์ฝ”๋“œ๊ฐ€ ํ•ฉ์ณ์ง€๋Š” ๊ฒƒ์„ ๋ง‰๊ธฐ ์œ„ํ•ด์„œ์˜ˆ์š”. "๋ฌธ์ง€๊ธฐ" ์—ญํ• ์„ ํ•œ๋‹ค๊ณ  ๋ณด๋ฉด ๋ผ์š”. + + --- + + ### **2. CD (Continuous Deployment/Delivery - ์ง€์†์  ๋ฐฐํฌ/์ œ๊ณต)** + + - **๋ฌด์—‡์ธ๊ฐ€์š”?** CI๋ฅผ ํ†ต๊ณผํ•œ ์ฝ”๋“œ๋ฅผ ์ž๋™์œผ๋กœ **์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฐฐํฌ**ํ•˜๋Š” ๊ณผ์ •์ด์—์š”. + - **ํ•˜๋Š” ์ผ:** ํ…Œ์ŠคํŠธ๊ฐ€ ๋๋‚œ ์ฝ”๋“œ๋ฅผ ์„œ๋ฒ„๋กœ ์ „์†กํ•˜๊ณ , ์‹ค์ œ ์›น์‚ฌ์ดํŠธ๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์š”. + - **์™œ ํ•˜๋‚˜์š”?** ๊ฐœ๋ฐœ์ž๊ฐ€ ์ˆ˜๋™์œผ๋กœ ์—…๋กœ๋“œํ•  ํ•„์š” ์—†์ด, ์ฝ”๋“œ๋งŒ ์ž‘์„ฑํ•˜๋ฉด ๊ณ ๊ฐ์—๊ฒŒ ๊ธฐ๋Šฅ์ด ์ฆ‰์‹œ ์ „๋‹ฌ๋˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ์˜ˆ์š”. + + - **`๋ฐฐํฌ`** vs **Vercel** vs **CI/CD** ํ•œ๋ˆˆ์— ๋น„๊ต + + # ๋ฐฐํฌ vs Vercel vs CI/CD ํ•œ๋ˆˆ์— ๋น„๊ต + + --- + + | **ํ•ญ๋ชฉ** | **๋ฐฐํฌ (Deployment)** | **Vercel** | **CI / CD** | + | --- | --- | --- | --- | + | **ํ•ต์‹ฌ ๊ฐœ๋…** | ์„œ๋น„์Šค ๊ณต๊ฐœ | ๋ฐฐํฌ ๋„๊ตฌ (ํ”Œ๋žซํผ) | ์ž๋™ํ™” ํ”„๋กœ์„ธ์Šค | + | **์—ญํ• ** | ๋‚ด ์ปดํ“จํ„ฐ -> ์„ธ์ƒ ๋ฐ–์œผ๋กœ | ๋ฐฐํฌ๋ฅผ ์‰ฝ๊ฒŒ ํ•ด์ฃผ๋Š” ์กฐ๋ ฅ์ž | ๊ฐœ๋ฐœ~๋ฐฐํฌ ๊ณผ์ •์„ ์—ฐ๊ฒฐํ•˜๋Š” ํŒŒ์ดํ”„๋ผ์ธ | + | **๋น„์œ ** | ๊ฐ€๊ฒŒ ์˜คํ”ˆ | ์ธํ…Œ๋ฆฌ์–ด/์„ค๋น„ ๋‹ค ๋œ ๋งค์žฅ ์ž„๋Œ€ | ๋กœ๋ด‡์ด ์ฒญ์†Œ/์š”๋ฆฌ/์„œ๋น™๊นŒ์ง€ ์ž๋™ํ™” | + | **๋‚œ์ด๋„** | (๊ณผ๊ฑฐ) ๋งค์šฐ ๋†’์Œ | ๋งค์šฐ ๋‚ฎ์Œ (ํด๋ฆญ ๋ช‡ ๋ฒˆ) | ์„ค์ •์— ๋”ฐ๋ผ ๋‹ค๋ฆ„ (GitHub Actions ๋“ฑ) | + | **์ฃผ์š” ์ž‘์—…** | ํŒŒ์ผ ์—…๋กœ๋“œ, ์„œ๋ฒ„ ์‹คํ–‰ | GitHub ๋ ˆํฌ์ง€ํ† ๋ฆฌ ์—ฐ๊ฒฐ | ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ, ์›Œํฌํ”Œ๋กœ์šฐ(.yml) ์„ค์ • | + - **Vercel๊ณผ CI/CD**๊ฐ€ ๊ถŒ์žฅ๋˜๋Š” ์ด์œ  + + # **Vercel๊ณผ CI/CD**๊ฐ€ ๊ถŒ์žฅ๋˜๋Š” ์ด์œ  + + --- + + ํ˜„๋Œ€ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ ํ•ต์‹ฌ์€ **"์ƒ์‚ฐ์„ฑ"**๊ณผ **"์•ˆ์ •์„ฑ"**์ด์—์š”: + + > "๊ฐœ๋ฐœ์ž๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง(๊ธฐ๋Šฅ ๊ตฌํ˜„)์—๋งŒ ์ง‘์ค‘ํ•˜์„ธ์š”. ๋ฐฐํฌ์™€ ์šด์˜์€ ๋„๊ตฌ๊ฐ€ ํ•ด๊ฒฐํ•ด ๋“œ๋ฆฝ๋‹ˆ๋‹ค." + > + + ์ฆ‰, **Vercel**์„ ์‚ฌ์šฉํ•˜๋ฉด ์ธํ”„๋ผ ๊ตฌ์ถ• ์‹œ๊ฐ„์„ ์•„๋‚„ ์ˆ˜ ์žˆ๊ณ , **CI/CD**๋ฅผ ๊ตฌ์ถ•ํ•˜๋ฉด ์‚ฌ๋žŒ์ด ํ•  ์ˆ˜ ์žˆ๋Š” ์‹ค์ˆ˜๋ฅผ ์ปดํ“จํ„ฐ๊ฐ€ ๋Œ€์‹  ๊ฒ€์ฆํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ํ›จ์”ฌ ์•ˆ์ •์ ์ธ ์„œ๋น„์Šค ์šด์˜์ด ๊ฐ€๋Šฅํ•ด์š”. + + --- + + ### **โœ” ์–ธ์ œ ์ด ๋„๊ตฌ๋“ค์„ ์‚ฌ์šฉํ• ๊นŒ์š”?** + + --- + + ๐Ÿ‘‰ **์ด๋Ÿฐ ๊ฒฝ์šฐ๋ผ๋ฉด ๊ฐ•๋ ฅ ์ถ”์ฒœํ•ด์š”** + + - โœ” ๋‚ด๊ฐ€ ๋งŒ๋“  ํ”„๋กœ์ ํŠธ๋ฅผ ํฌํŠธํด๋ฆฌ์˜ค๋กœ ์ œ์ถœํ•ด์„œ ๋งํฌ๋กœ ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ์„ ๋•Œ (**Vercel**) + - โœ” ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ๋งˆ๋‹ค ์ผ์ผ์ด ๋‹ค์‹œ ๋นŒ๋“œํ•˜๊ณ  ์—…๋กœ๋“œํ•˜๊ธฐ ๊ท€์ฐฎ์„ ๋•Œ (**CI/CD**) + - โœ” ํŒ€ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉฐ, ํŒ€์›์˜ ์ฝ”๋“œ๊ฐ€ ์—๋Ÿฌ ์—†์ด ์ž˜ ํ•ฉ์ณ์ง€๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์‹ถ์„ ๋•Œ + - โœ” ์‹ค๋ฌด์—์„œ์ฒ˜๋Ÿผ ์ฒด๊ณ„์ ์ธ ๊ฐœ๋ฐœ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฒฝํ—˜ํ•ด๋ณด๊ณ  ์‹ถ์„ ๋•Œ + + --- + + ๐Ÿ‘‰ **์ด๋Ÿฐ ๊ฒฝ์šฐ ๊ณผํ•  ์ˆ˜๋„ ์žˆ์–ด์š”** + + - โœ” ์ธํ„ฐ๋„ท ์—ฐ๊ฒฐ ์—†์ด ๋กœ์ปฌ์—์„œ๋งŒ ๋™์ž‘ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค ๋•Œ + - โœ” ๋ฐฐํฌํ•  ํ•„์š” ์—†์ด ์ฝ”๋“œ ๋กœ์ง๋งŒ ๊ณต๋ถ€ํ•˜๋Š” ๋‹จ๊ณ„์ผ ๋•Œ + - **์ถ”๊ฐ€๋กœ ๋ณธ์ธ์ด ํ•™์Šตํ•œ ๋‚ด์šฉ์— ๋Œ€ํ•ด์„œ ์ •๋ฆฌํ•ด์ฃผ์„ธ์š”** ๐Ÿ  + + # **์ถ”๊ฐ€๋กœ ๋ณธ์ธ์ด ํ•™์Šตํ•œ ๋‚ด์šฉ์— ๋Œ€ํ•ด์„œ ์ •๋ฆฌํ•ด์ฃผ์„ธ์š”** ๐Ÿ  + + --- + + - **Preview ๋ฐฐํฌ์˜ ์ค‘์š”์„ฑ**: Vercel์€ PR๋งˆ๋‹ค Preview URL์„ ์ž๋™ ์ƒ์„ฑํ•ด, ์‹ค์ œ ๋ฐฐํฌ ์ „ ๊ธฐ๋ŠฅยทUI๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋‹ค. + - **ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๊ด€๋ฆฌ**: API Key ๊ฐ™์€ ๋ฏผ๊ฐํ•œ ๊ฐ’์€ ์ฝ”๋“œ์— ์ง์ ‘ ๋„ฃ์ง€ ์•Š๊ณ , Vercel์˜ Environment Variables๋กœ ๊ด€๋ฆฌํ•ด์•ผ ํ•œ๋‹ค. + - **Rollback์˜ ํ•„์š”์„ฑ**: ๋ฐฐํฌ ํ›„ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋ฉด ์ด์ „ ๋ฒ„์ „์œผ๋กœ ์ฆ‰์‹œ ๋˜๋Œ๋ฆด ์ˆ˜ ์žˆ์–ด ์„œ๋น„์Šค ์•ˆ์ •์„ฑ์ด ๋†’์•„์ง„๋‹ค. + - **์ž๋™ํ™”์˜ ์‹ ๋ขฐ์„ฑ**: CI ๋‹จ๊ณ„์—์„œ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•˜๋ฉด ๋ฐฐํฌ ์ž์ฒด๊ฐ€ ์ฐจ๋‹จ๋˜์–ด, ์˜ค๋ฅ˜ ์ฝ”๋“œ๊ฐ€ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋…ธ์ถœ๋˜๋Š” ๊ฒƒ์„ ๋ง‰๋Š”๋‹ค. + - **ํ˜‘์—… ํšจ์œจ ํ–ฅ์ƒ**: GitHub Actions + Vercel์„ ์‚ฌ์šฉํ•˜๋ฉด ํŒ€์› ๊ฐ„ โ€œ๋‚ด ๋กœ์ปฌ์—์„œ๋Š” ๋์–ดโ€ ๋ฌธ์ œ๋ฅผ ํฌ๊ฒŒ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค. + - **์‹ค๋ฌด์™€์˜ ์—ฐ๊ฒฐ์„ฑ**: ๋Œ€๋ถ€๋ถ„์˜ ์‹ค๋ฌด ํ”„๋ก ํŠธ์—”๋“œ ํ”„๋กœ์ ํŠธ๋Š” CI/CD ๊ธฐ๋ฐ˜ ๋ฐฐํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ, ํ•™์Šต ์ž์ฒด๊ฐ€ ์‹ค๋ฌด ๊ฒฝํ—˜์ด ๋œ๋‹ค. + - **๋ฐฐํฌ๋Š” ๊ฐœ๋ฐœ์˜ ๋์ด ์•„๋‹ˆ๋ผ ์‹œ์ž‘**: ๋ฐฐํฌ ์ดํ›„ ๋กœ๊ทธ, ์„ฑ๋Šฅ, ์‚ฌ์šฉ์ž ๋ฐ˜์‘์„ ๋ณด๋ฉฐ ์ง€์†์ ์œผ๋กœ ๊ฐœ์„ ํ•˜๋Š” ๊ณผ์ •์ด ์ค‘์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์ดํ•ดํ–ˆ๋‹ค. + +# ๐Ÿ ย ๋ฏธ์…˜ 1 - ์˜ํ™” ์‚ฌ์ดํŠธ ๋ Œ๋”๋ง ์ตœ์ ํ™” + +--- + + + +### ๐ŸŽฅ ๋ฏธ์…˜ 1. ๊ฐ•์˜ ์˜์ƒ + +https://www.youtube.com/watch?v=Zr0OP21zF4c&t=3611s + +## ๐ŸŽฌ 1. ์˜ํ™” ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ + +### ๐ŸชŸ ๋ ˆ์ด์•„์›ƒ + +- [ ] ํŽ˜์ด์ง€ ์ƒ๋‹จ์— **์˜ํ™” ๊ฒ€์ƒ‰ ์˜์—ญ ๋ ˆ์ด์•„์›ƒ**์„ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”. +- [ ] ๊ฒ€์ƒ‰ ํผ์„ `form` ํƒœ๊ทธ๋กœ ๊ฐ์‹ธ์ฃผ์„ธ์š”. (์—”ํ„ฐ ์ž…๋ ฅ ์‹œ์—๋„ ๊ฒ€์ƒ‰๋˜๋„๋ก) + +### ๐ŸŽฌ ์˜ํ™” ์ œ๋ชฉ ์ž…๋ ฅ + +- [ ] โ€œ์˜ํ™” ์ œ๋ชฉโ€์„ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋Š” `input`(text)๋ฅผ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”. +- [ ] `placeholder`๋ฅผ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”. **์˜ˆ) ์˜ํ™” ์ œ๋ชฉ์„ ์ž…๋ ฅํ•˜์„ธ์š”** +- [ ] ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๊ฐ’์„ ์ƒํƒœ(state)๋กœ ๊ด€๋ฆฌํ•ด์ฃผ์„ธ์š”. + + ![Screenshot 2025-05-05 at 2.26.21โ€ฏAM.png](attachment:c256d019-be44-41a1-a617-5772ee3a388d:Screenshot_2025-05-05_at_2.26.21_AM.png) + + +### ๐Ÿ”ž ์„ฑ์ธ ์ฝ˜ํ…์ธ  ํ‘œ์‹œ ์—ฌ๋ถ€ (์ฒดํฌ๋ฐ•์Šค) + +- [ ] โ€œ์„ฑ์ธ ์ฝ˜ํ…์ธ  ํฌํ•จโ€ ์—ฌ๋ถ€๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” `checkbox`๋ฅผ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”. +- [ ] ์ฒดํฌ ์—ฌ๋ถ€๋ฅผ ์ƒํƒœ๋กœ ๊ด€๋ฆฌํ•ด์ฃผ์„ธ์š”. (true/false) +- [ ] ์‹ค์ œ API ํ˜ธ์ถœ ์‹œ, ์ด ๊ฐ’์— ๋”ฐ๋ผ **์„ฑ์ธ ์ฝ˜ํ…์ธ  ํฌํ•จ ์—ฌ๋ถ€๊ฐ€ ๋ฐ˜์˜๋˜๋„๋ก** ํ•ด์ฃผ์„ธ์š”. (์˜ˆ: TMDB์˜ `include_adult` ํŒŒ๋ผ๋ฏธํ„ฐ ํ™œ์šฉ ๋“ฑ) + +### ๐ŸŒ ์–ธ์–ด ์„ ํƒ (ํ•œ๊ตญ์–ด / ์˜์–ด / ์ผ๋ณธ์–ด) + +- [ ] ์–ธ์–ด๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” `select` ๋ฐ•์Šค๋ฅผ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”. +- [ ] ์˜ต์…˜์€ ์•„๋ž˜ 3๊ฐ€์ง€ ์ค‘์—์„œ ์„ ํƒ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด์ฃผ์„ธ์š”. + - [ ] ํ•œ๊ตญ์–ด (ko-KR) + - [ ] ์˜์–ด (en-US) + - [ ] ์ผ๋ณธ์–ด (ja-JP) + - [ ] ์‹ค์ œ API ํ˜ธ์ถœ ์‹œ, ์„ ํƒํ•œ ์–ธ์–ด ์ฝ”๋“œ๊ฐ€ ์ ์šฉ๋˜๋„๋ก ํ•ด์ฃผ์„ธ์š”. +- [ ] ์„ ํƒ๋œ ์–ธ์–ด ๊ฐ’์„ ์ƒํƒœ๋กœ ๊ด€๋ฆฌํ•ด์ฃผ์„ธ์š”. + + ![Screenshot 2025-05-05 at 2.26.40โ€ฏAM.png](attachment:55e6e542-bb58-4e3e-91d9-324147e1e133:Screenshot_2025-05-05_at_2.26.40_AM.png) + + +--- + +## ๐ŸชŸ 2. ์˜ํ™” ์ƒ์„ธ ์ •๋ณด ๋ชจ๋‹ฌ ๊ตฌํ˜„ + +### ๐ŸŽจ ๋ชจ๋‹ฌ ๋””์ž์ธ ์š”๊ตฌ์‚ฌํ•ญ + +- [ ] ์˜ํ™” ์นด๋“œ๋ฅผ ํด๋ฆญํ•˜๋ฉด **์„ ํƒ๋œ ์˜ํ™”์˜ ์ •๋ณด**๋ฅผ ๋ชจ๋‹ฌ ํ˜•ํƒœ๋กœ ๋ณด์—ฌ์ฃผ์„ธ์š”. +- [ ] ์ œ๊ณต๋œ **์ด๋ฏธ์ง€/์˜์ƒ๊ณผ ์ตœ๋Œ€ํ•œ ์œ ์‚ฌํ•œ ๋ ˆ์ด์•„์›ƒ**์œผ๋กœ ๋ชจ๋‹ฌ์„ ๋””์ž์ธํ•ด์ฃผ์„ธ์š”. + - [ ] ํฌ์Šคํ„ฐ, ์ œ๋ชฉ, ํ‰์ , ๊ฐœ๋ด‰์ผ, ์ค„๊ฑฐ๋ฆฌ ๋“ฑ์ด ๋ณด๊ธฐ ์ข‹๊ฒŒ ๋ฐฐ์น˜ํ•ด์ฃผ์„ธ์š”. + - [ ] ์ค‘์•™์— ์นด๋“œ ํ˜•ํƒœ์˜ ๋ชจ๋‹ฌ ๋ฐ•์Šค๊ฐ€ ๋‚˜ํƒ€๋‚˜๊ฒŒ ํ•ด์ฃผ์„ธ์š”. + + [Screen Recording 2025-05-05 at 2.27.20โ€ฏAM.mov](attachment:f75fbe0c-fb14-437c-9c45-199a7e905ed8:Screen_Recording_2025-05-05_at_2.27.20_AM.mov) + +- [ ] ๋ชจ๋‹ฌ ์ƒ๋‹จ์— **ํฌ์Šคํ„ฐ ์ด๋ฏธ์ง€**๋ฅผ ๋ณด์—ฌ์ฃผ์„ธ์š”. +- [ ] ๋ชจ๋‹ฌ์— ์ตœ์†Œ ์•„๋ž˜ ์ด๋ฏธ์ง€์˜ ์ •๋ณด๋“ค์„ ํ‘œ์‹œํ•ด์ฃผ์„ธ์š”. + + ![Screenshot 2025-05-05 at 2.26.50โ€ฏAM.png](attachment:59b72244-f758-470d-b411-488c3a8c2353:Screenshot_2025-05-05_at_2.26.50_AM.png) + +- [ ] ๋ชจ๋‹ฌ ์•ˆ์— **โ€œIMDb์—์„œ ๊ฒ€์ƒ‰ํ•˜๊ธฐโ€ ๋ฒ„ํŠผ**์„ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”. + - [ ] ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ, ์ƒˆ ํƒญ์—์„œ IMDb ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ ์—ด๋ฆฌ๋„๋ก ํ•ด์ฃผ์„ธ์š”. + - [ ] ์˜ˆ: `https://www.imdb.com/find?q=${์˜ํ™”์ œ๋ชฉ}` ํ˜•์‹์œผ๋กœ URL ๊ตฌ์„ฑ +- [ ] ๋ชจ๋‹ฌ ๋‚ด๋ถ€์— โ€œ๋‹ซ๊ธฐโ€ ๋ฒ„ํŠผ์„ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”. + - [ ] ๋‹ซ๊ธฐ ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ๋ชจ๋‹ฌ์ด ๋‹ซํžˆ๊ฒŒ ํ•ด์ฃผ์„ธ์š”. + +--- + +## โš™๏ธ ์„ฑ๋Šฅ ์ตœ์ ํ™” (React.memo, useCallback, useMemo) + +- [ ] ๋ธŒ๋ผ์šฐ์ €์— **React DevTools**๋ฅผ ์„ค์น˜ํ•œ๋‹ค. + + [React Developer Tools - Chrome Web Store](https://chromewebstore.google.com/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?pli=1) + +- [ ] React DevTools์˜ **Profiler ํƒญ**์„ ์—ด์–ด์ฃผ์„ธ์š”. +- [ ] ์˜ํ™” ๊ฒ€์ƒ‰ ๋ฐ ํ•„ํ„ฐ๋ง์„ ํ•œ ๋ฒˆ ์ˆ˜ํ–‰ํ•ด ๋ณด๊ณ , ์–ด๋–ค ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋˜๋Š”์ง€ ํ™•์ธํ•ด์ฃผ์„ธ์š”. + + [Screen Recording 2025-05-05 at 2.28.37โ€ฏAM.mov](attachment:75ffd2ba-abb4-482c-b42f-3801c50db5ba:Screen_Recording_2025-05-05_at_2.28.37_AM.mov) + + - [ ] ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์ƒ์œ„ ์ „์ฒด๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง ๋œ๋‹ค๋ฉด, ์›์ธ์„ ์ฐพ์•„ `memo`, `useCallback`, `useMemo`๋ฅผ ์กฐ์ •ํ•ด์ฃผ์„ธ์š”. +- [ ] ์ตœ์ ํ™” ์ „ / ํ›„์˜ ์ฐจ์ด๋ฅผ ์บก์ฒ˜ํ•ด์„œ ๊ธฐ๋กํ•˜๊ฑฐ๋‚˜, ๊ฐ„๋‹จํžˆ ์ •๋ฆฌํ•ด ์ฃผ์„ธ์š”. + - **์ ์šฉํ•œ ์ตœ์ ํ™” ์ •๋ฆฌํ•ด ๋ณด๊ธฐ** +- [ ] ๊ทธ๋™์•ˆ ์—ฌ๋Ÿฌ๋ถ„์ด ์ œ์ž‘ํ•˜์‹  **LP ์‚ฌ์ดํŠธ**๋„ ์ตœ์ ํ™”๋ฅผ 3๊ฐœ ์ด์ƒ ํ•ด๋ณด์‹œ๊ณ  ์•„๋ž˜์— ๋‚จ๊ฒจ์ฃผ์„ธ์š”. + - **LP ํŽ˜์ด์ง€ ์„ฑ๋Šฅ ๊ฐœ์„  ํฌ์ธํŠธ ์ •๋ฆฌ** + +### ๐Ÿ ย ๋ฏธ์…˜ 1. ์ œ์ถœ + +- ๊นƒํ—ˆ๋ธŒ ์ฃผ์†Œ ๐Ÿ  +- ์‹คํ–‰ ์˜์ƒ ๐Ÿ  + +--- + +# ๐Ÿ ย ๋ฏธ์…˜ 2. Vercel์„ ํ™œ์šฉํ•œ ์˜ํ™” ์‚ฌ์ดํŠธ ๋ฐฐํฌ ๋ฐ ๋„๋ฉ”์ธ ์—ฐ๊ฒฐ + +--- + + + +### ๐ŸŽฅ ๋ฏธ์…˜ 2. ๊ฐ•์˜ ์˜์ƒ + +https://youtu.be/GX9QbJiiQyQ?si=hVBHTZqgySzoyy82 + +### ๐Ÿ“š ๋ฏธ์…˜ 2. ๋ธ”๋กœ๊ทธ ์ž๋ฃŒ + +[๊ฐœ๋ฐœ์ž ๋งคํŠœ | ์šฐ๋ฆฌ๋Š” Vercel๋กœ ๊ฐ„๋‹ค! ํ”„๋ก ํŠธ์—”๋“œ ๋ฐฐํฌ ๊ฐ€์ด๋“œ](https://www.yolog.co.kr/post/vercel-deployment) + +### Vercel ๋ฐฐํฌ ์ฒดํฌ๋ฆฌ์ŠคํŠธ + +--- + +**1. ์ค€๋น„ ๋‹จ๊ณ„ (GitHub & CLI)** + +๋‚ด ์ฝ”๋“œ๋ฅผ ๋ฐฐํฌํ•  ์ค€๋น„๋ฅผ ํ•˜๋Š” ๋‹จ๊ณ„์˜ˆ์š”. + +- [ ] **GitHub ๋ ˆํฌ์ง€ํ† ๋ฆฌ ์ƒ์„ฑ ๋ฐ ์ฝ”๋“œ ์—…๋กœ๋“œ (Push)** + - `git init` โ†’ `git add .` โ†’ `git commit` โ†’ `git push` + - โš ๏ธ **์ฃผ์˜:** API ํ‚ค๊ฐ€ ๋“ค์–ด์žˆ๋Š” `.env` ํŒŒ์ผ์€ ์ ˆ๋Œ€ ์˜ฌ๋ฆฌ๋ฉด ์•ˆ ๋ผ์š”! (`.gitignore` ํ™•์ธ) +- [ ] **Vercel CLI ์„ค์น˜** + - ํ„ฐ๋ฏธ๋„์— `npm install -g vercel` ์ž…๋ ฅ +- [ ] **Vercel ๋กœ๊ทธ์ธ** + - ํ„ฐ๋ฏธ๋„์— `vercel login` ์ž…๋ ฅ ํ›„ GitHub ๊ณ„์ • ๋“ฑ์œผ๋กœ ๋กœ๊ทธ์ธ ์™„๋ฃŒํ•˜๊ธฐ + +**2. ํ”„๋กœ์ ํŠธ ์—ฐ๊ฒฐ ๋ฐ ์ฒซ ๋ฐฐํฌ (Preview)** + +Vercel๊ณผ ๋‚ด ํ”„๋กœ์ ํŠธ๋ฅผ ์—ฐ๊ฒฐํ•˜๊ณ  ๋ฏธ๋ฆฌ๋ณด๊ธฐ(Preview)๋ฅผ ๋„์šฐ๋Š” ๋‹จ๊ณ„์˜ˆ์š”. + +- [ ] **Vercel ์—ฐ๋™ ์‹œ์ž‘** + - ํ”„๋กœ์ ํŠธ ๊ฒฝ๋กœ์—์„œ `vercel` ๋ช…๋ น์–ด ์ž…๋ ฅ +- [ ] **์ดˆ๊ธฐ ์„ค์ • ์งˆ๋ฌธ ๋‹ต๋ณ€ํ•˜๊ธฐ** +- [ ] **Preview ๋ฐฐํฌ ํ™•์ธ** + - ํ„ฐ๋ฏธ๋„์— ๋œฌ `Preview` URL๋กœ ์ ‘์†ํ•ด์„œ ์‚ฌ์ดํŠธ๊ฐ€ ๋‚˜์˜ค๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ + +**3. ์‹ค์„œ๋น„์Šค ๋ฐฐํฌ (Production)** + +์ด์ œ ์ง„์งœ ์‚ฌ์šฉ์ž๊ฐ€ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ฃผ์†Œ๋กœ ๋ฐฐํฌํ•˜๋Š” ๋‹จ๊ณ„์˜ˆ์š”. + +- [ ] **Production ๋ฐฐํฌ ๋ช…๋ น์–ด ์‹คํ–‰** + - ํ„ฐ๋ฏธ๋„์— `vercel --prod` ์ž…๋ ฅ +- [ ] **Production URL ํ™•์ธ** + - `Production` ์˜†์— ๋œฌ URL๋กœ ์ ‘์†ํ•ด์„œ ํ™•์ธํ•˜๊ธฐ + +**4. ํ•„์ˆ˜ ์„ค์ • ๋ฐ ์—๋Ÿฌ ํ•ด๊ฒฐ** + +๋ธ”๋กœ๊ทธ์—์„œ ๊ฐ•์กฐํ•œ **"์ƒˆ๋กœ๊ณ ์นจ ์‹œ 404 ์—๋Ÿฌ"**์™€ **"ํ™˜๊ฒฝ๋ณ€์ˆ˜"** ํ•ด๊ฒฐ ๋‹จ๊ณ„์—์š”. + +- [ ] **`react-router-dom`**์„ ํ™œ์šฉํ•˜์—ฌ ์˜ํ™” ์ƒ์„ธํŽ˜์ด์ง€ ๋ผ์šฐํŒ…๋งŒ ํ•ด์ฃผ์„ธ์š” + - [ ] ์ œ๋Œ€๋กœ **`/movies/:movieId`** ํŽ˜์ด์ง€ ์ด๋™์ด ๋˜๋Š”์ง€ ํ™•์ธํ•ด์ฃผ์„ธ์š”. (์‹ค์ œ๋กœ ๋””์ž์ธ์„ ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.) +- [ ] **ํ™˜๊ฒฝ๋ณ€์ˆ˜(Environment Variables) ๋“ฑ๋ก** + - Vercel ๋Œ€์‹œ๋ณด๋“œ โ†’ Settings โ†’ Environment Variables ํƒญ ์ด๋™ + - `.env` ํŒŒ์ผ์— ์žˆ๋˜ ๋‚ด์šฉ(API URL ๋“ฑ)์„ ๋˜‘๊ฐ™์ด ์ž…๋ ฅํ•˜๊ณ  Save + - **ํ•„์ˆ˜:** ์ €์žฅ ํ›„ ๋ฐ˜๋“œ์‹œ **์žฌ๋ฐฐํฌ(`vercel --prod`)** ํ•ด์•ผ ์ ์šฉ๋จ! +- [ ] **SPA ์ƒˆ๋กœ๊ณ ์นจ 404 ์—๋Ÿฌ ๋ฐฉ์ง€ (`vercel.json`)** + - React, Vue ๋“ฑ SPA ํ”„๋กœ์ ํŠธ๋ผ๋ฉด ํ•„์ˆ˜! + - ํ”„๋กœ์ ํŠธ ์ตœ์ƒ๋‹จ์— `vercel.json` ํŒŒ์ผ ๋งŒ๋“ค๊ธฐ + - ๋ธ”๋กœ๊ทธ์— ๋‚˜์˜จ `rewrites` ์ฝ”๋“œ(๋ชจ๋“  ๊ฒฝ๋กœ๋ฅผ index.html๋กœ ๋ณด๋‚ด๋Š” ์„ค์ •) ๋ณต์‚ฌยท๋ถ™์—ฌ๋„ฃ๊ธฐ + +**5. ๋„๋ฉ”์ธ ์—ฐ๊ฒฐ (์„ ํƒ ์‚ฌํ•ญ)** + +๋‚˜๋งŒ์˜ ์˜ˆ์œ ์ฃผ์†Œ(`yolog.co.kr` ๋“ฑ)๋ฅผ ๊ฐ–๊ณ  ์‹ถ๋‹ค๋ฉด ์ง„ํ–‰ํ•˜์„ธ์š”. + +- [ ] **๋„๋ฉ”์ธ ์ถ”๊ฐ€** + - Vercel ๋Œ€์‹œ๋ณด๋“œ โ†’ Domains ํƒญ โ†’ ๊ตฌ์ž…ํ•œ ๋„๋ฉ”์ธ ์ž…๋ ฅ ํ›„ Add +- [ ] **DNS ๋ ˆ์ฝ”๋“œ ์„ค์ •** + - ๋„๋ฉ”์ธ ๊ตฌ์ž…์ฒ˜(๊ฐ€๋น„์•„ ๋“ฑ) ์„ค์ • ํŽ˜์ด์ง€ ์ด๋™ + - **A Record** (IP ์ฃผ์†Œ) ๋˜๋Š” **CNAME Record** (vercel.app ์ฃผ์†Œ) ์ž…๋ ฅ +- [ ] **์—ฐ๊ฒฐ ํ™•์ธ** + - 'Configured Correctly' ์ดˆ๋ก๋ถˆ์ด ๋“ค์–ด์˜ค๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ + +### ๐Ÿ ย ๋ฏธ์…˜ 2. ์ œ์ถœ + +- ๊นƒํ—ˆ๋ธŒ ์ฃผ์†Œ ๐Ÿ  +- ๋ฐฐํฌ ์‚ฌ์ดํŠธ ๋งํฌ ๐Ÿ  + +# ๐Ÿ ย ์›Œํฌ๋ถ ํ”ผ๋“œ๋ฐฑ (์™„๋ฃŒ) + +--- + + + +[](https://forms.gle/PCLJq6NUn1qBd1Ha8) + +# ๐Ÿ ย ์ฝ”๋“œ ๋ฆฌ๋ทฐ + +--- + + + +- ๋‚ด๊ฐ€ ๋ฆฌ๋ทฐํ•œ ๋‚ด์šฉ์„ ์บก์ฒ˜ํ•ด ์—…๋กœ๋“œ + + **์˜ˆ์‹œ** + + ![แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2025-09-05 แ„‹แ…ฉแ„’แ…ฎ 12.46.40.png](attachment:39549968-68c3-4416-b41f-423fd1f7fd79:แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ_2025-09-05_แ„‹แ…ฉแ„’แ…ฎ_12.46.40.png) + +- ๋ฐ›์€ ๋ฆฌ๋ทฐ๋ฅผ ๋ฐ˜์˜ํ•˜์—ฌ ๊ฐœ์„ ํ•œ ์ฝ”๋“œ์™€ ์บก์ฒ˜ ์—…๋กœ๋“œ + + **์˜ˆ์‹œ** + + ![แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2025-09-05 แ„‹แ…ฉแ„’แ…ฎ 12.47.34.png](attachment:01011e3f-c9fd-4041-bdd5-4da72a805955:แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ_2025-09-05_แ„‹แ…ฉแ„’แ…ฎ_12.47.34.png) + + +# ๐Ÿฅ•ย Vercel์€ ์–ด๋–ป๊ฒŒ ๋ฌด๋ฃŒ๋กœ ๋ฐฐํฌ๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ• ๊นŒ? + +--- + + + +[Vercel์€ ์–ด๋–ป๊ฒŒ ๋ฌด๋ฃŒ๋กœ ๋ฐฐํฌ๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ• ๊นŒ?](https://www.notion.so/Vercel-2b8b57f4596b81618336d5d8976bfb63?pvs=21) + +# ๐Ÿ ย ํ•™์Šต ํšŒ๊ณ  + +--- + + + +- ๐Ÿ“ขย ํ•™์Šต ํšŒ๊ณ  (์˜ˆ์‹œ, ์„œ์‹๋งŒ ๋ณต์‚ฌํ•˜์‹œ๊ณ  ์ง€์›Œ์ฃผ์„ธ์š”.) + - **ํ”„๋ก ํŠธ์—”๋“œ ๋ฐฐํฌ, Vercel ํ™œ์šฉ** + - **์ดํ•ดํ•œ ์ **: Vercel์€ ํ”„๋ก ํŠธ์—”๋“œ ํ”„๋กœ์ ํŠธ๋ฅผ **๋น ๋ฅด๊ณ  ๊ฐ„ํŽธํ•˜๊ฒŒ ๋ฐฐํฌ**ํ•  ์ˆ˜ ์žˆ๋Š” ํ”Œ๋žซํผ์ž…๋‹ˆ๋‹ค. + + GitHub ์—ฐ๋™, ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค์ •, ์ปค์Šคํ…€ ๋„๋ฉ”์ธ ์—ฐ๊ฒฐ ๋“ฑ ๋ฐฐํฌ ๊ณผ์ • ๋Œ€๋ถ€๋ถ„์ด GUI์™€ CLI๋กœ ์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌ๋˜๋ฉฐ, SPA ํ™˜๊ฒฝ์—์„œ๋„ ๋ผ์šฐํŒ… ๋ฌธ์ œ๋ฅผ `vercel.json` ์„ค์ •์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + - ์˜ˆ์‹œ: + + ```bash + # CLI๋กœ ๋ฐฐํฌ + vercel # Preview ๋ฐฐํฌ + vercel --prod # Production ๋ฐฐํฌ + ``` + + ```json + // SPA ๋ผ์šฐํŒ… ๋ฌธ์ œ ํ•ด๊ฒฐ + { + "routes": [ + { "src": "/[^.]+", "dest": "/index.html", "status": 200 } + ] + } + ``` + + - **์–ด๋ ค์šด ์  (๊ฐœ์„  ๋ฐฉ๋ฒ•)**: SPA ๊ธฐ๋ฐ˜ ํ”„๋กœ์ ํŠธ๋Š” ์ƒˆ๋กœ๊ณ ์นจ ์‹œ 404 ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๊ด€๋ฆฌ, ์ปค์Šคํ…€ ๋„๋ฉ”์ธ ์—ฐ๊ฒฐ ๊ณผ์ •์ด ์ฒ˜์Œ์—๋Š” ํ—ท๊ฐˆ๋ ธ์Šต๋‹ˆ๋‹ค. + - ๊ฐœ์„  ๋ฐฉ๋ฒ•: `vercel.json` ์„ค์ •์œผ๋กœ SPA ๋ผ์šฐํŒ… ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ , Vercel Dashboard์—์„œ ํ™˜๊ฒฝ๋ณ€์ˆ˜์™€ DNS ์„ค์ •์„ ์ง์ ‘ ํ™•์ธํ•˜๋ฉด์„œ ๋ฐ˜๋ณต์ ์œผ๋กœ ๋ฐฐํฌ ์‹ค์Šต์„ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. + - ์˜ˆ์‹œ: + + ```tsx + // ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์‚ฌ์šฉ + const api = axios.create({ + baseURL: import.meta.env.VITE_API_URL, + headers: { 'Content-Type': 'application/json' }, + }); + + ``` + + - **ํšŒ๊ณ **: ์‹ค์ œ ๋ฐฐํฌ ๊ณผ์ •์„ ๊ฒฝํ—˜ํ•ด๋ณด๋‹ˆ, ๋กœ์ปฌ ํ™˜๊ฒฝ๊ณผ ๋‹ค๋ฅธ ์‹ค์ œ ์„œ๋น„์Šค ํ™˜๊ฒฝ์—์„œ์˜ ํ…Œ์ŠคํŠธ ํ•„์š”์„ฑ์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. + + ์•ž์œผ๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•  ๋•Œ, GitHub ์—ฐ๋™๊ณผ Vercel ๋ฐฐํฌ๋ฅผ ํ™œ์šฉํ•ด **์ฆ‰์‹œ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅํ•œ ํ™˜๊ฒฝ**์„ ๋งŒ๋“ค๊ณ , SPA ๋ผ์šฐํŒ… ๋ฌธ์ œ์™€ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์‹ ๊ฒฝ ์จ์„œ ์•ˆ์ •์ ์œผ๋กœ ์„œ๋น„์Šค๋ฅผ ์šด์˜ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. + + + --- + + ### ์ฐธ๊ณ  ์ž๋ฃŒ + + [๊ฐœ๋ฐœ์ž ๋งคํŠœ | ์šฐ๋ฆฌ๋Š” Vercel๋กœ ๊ฐ„๋‹ค! ํ”„๋ก ํŠธ์—”๋“œ ๋ฐฐํฌ ๊ฐ€์ด๋“œ](https://www.yolog.co.kr/post/vercel-deployment) + + +# ๐Ÿค”ย ์ฐธ๊ณ  ์ž๋ฃŒ + +--- + +[useCallback โ€“ React](https://ko.react.dev/reference/react/useCallback) + +[useMemo โ€“ React](https://ko.react.dev/reference/react/useMemo) + +[memo โ€“ React](https://ko.react.dev/reference/react/memo) + +[๊ฐœ๋ฐœ์ž ๋งคํŠœ | ์šฐ๋ฆฌ๋Š” Vercel๋กœ ๊ฐ„๋‹ค! ํ”„๋ก ํŠธ์—”๋“œ ๋ฐฐํฌ ๊ฐ€์ด๋“œ](https://www.yolog.co.kr/post/vercel-deployment) + +[Vercel Documentation](https://vercel.com/docs) + +[GitHub Actions documentation - GitHub Docs](https://docs.github.com/en/actions) + +# ๐Ÿ›ก๏ธย ์ €์ž‘๊ถŒ + +--- + +**ยฉ 2025 [Kim Yongmin (Matthew)](https://www.youtube.com/@yongcoding). All rights reserved.** \ No newline at end of file