๐ŸŽ Gift MBTI - 4. ํ† ์ด ํ”„๋กœ์ ํŠธ ์—๋Ÿฌ ๋ชจ์Œzip

zamanยท2022๋…„ 10์›” 29์ผ
0

Toy Projects

๋ชฉ๋ก ๋ณด๊ธฐ
5/6
post-thumbnail

์‚ฌ์‹ค ๋” ๋งŽ์•˜๋Š”๋ฐ ๊ธฐ๋กํ•˜๋Š”๊ฑธ ๊นŒ๋จน์–ด์„œใ… 
์•„์‰ฝ์ง€๋งŒ ์ƒ๊ฐ๋‚˜๋Š”๊ฒƒ๋งŒ ์ ์–ด๋ดค๋‹ค

1. Do not use Array index in keys

๐Ÿค” ์—๋Ÿฌ๊ฐ€ ์ผ์–ด๋‚˜๋Š” ์ด์œ 

๊ทผ๋ณธ์ ์œผ๋กœ array์— key๋Š” ์™œ ์ง€์ •ํ•˜๋Š”๊ฑธ๊นŒ?

โžก๏ธ ๋ Œ๋”๋ง์„ ์ตœ์ ํ™”ํ•˜๊ธฐ ์œ„ํ•ด์„œ

Key๋Š” React๊ฐ€ ์–ด๋–ค ํ•ญ๋ชฉ์„ ๋ณ€๊ฒฝ, ์ถ”๊ฐ€ ๋˜๋Š” ์‚ญ์ œํ• ์ง€ ์‹๋ณ„ํ•˜๋Š” ๊ฒƒ์„ ๋•์Šต๋‹ˆ๋‹ค. key๋Š” ์—˜๋ฆฌ๋จผํŠธ์— ์•ˆ์ •์ ์ธ ๊ณ ์œ ์„ฑ์„ ๋ถ€์—ฌํ•˜๊ธฐ ์œ„ํ•ด ๋ฐฐ์—ด ๋‚ด๋ถ€์˜ ์—˜๋ฆฌ๋จผํŠธ์— ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฆฌ์•กํŠธ๋Š” ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ํ™•์ธํ•˜๊ณ  ์—…๋ฐ์ดํŠธ๊ฐ€ ํ•„์š”ํ•  ๋•Œ๋งŒ ๋ฆฌ๋ Œ๋”๋ง
key๊ฐ€ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ ๋ฐฐ์—ด์— ์ถ”๊ฐ€๋œ ์š”์†Œ ํ•œ๊ฐ€์ง€๋งŒ ๋ฆฌ๋ Œ๋”๋ง! ๋”ฐ๋ผ์„œ key๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋Ÿผ ์™œ Index๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋˜๋Š”๊ฑธ๊นŒ?

key๊ฐ€ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ ๋ฐฐ์—ด์— ์ถ”๊ฐ€๋œ ์š”์†Œ ํ•œ๊ฐ€์ง€๋งŒ ๋ฆฌ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ์—ˆ๋˜ ์ด์œ ๋Š” ๋ฆฌ์•กํŠธ๊ฐ€ ๊ธฐ์กด ๋ Œ๋”๋ง ํ–ˆ๋˜ ๋ฐฐ์—ด๊ณผ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์˜ ์š”์†Œ๋ฅผ ๋น„๊ตํ•˜๊ธฐ ๋•Œ๋ฌธ

์˜ˆ๋ฅผ ๋“ค์–ด ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฐฐ์—ด์ด

[
  {id:0, title: 'title1', content: 'content1' },
  {id:1, title: 'title2', content: 'content2' },
  {id:2, title: 'title3', content: 'content3' },
]

์ด๋ ‡๊ฒŒ ๋ฐ”๋€Œ์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž

[
  {id:0, title: 'title1', content: 'content1' },
  {id:1, title: '2222', content: 'twotwotwo' },
  {id:2, title: 'title3', content: 'content3' },
]

๋ฆฌ์•กํŠธ๋Š” 1๋ฒˆ ๋ฐฐ์—ด์˜ id: 0๊ณผ 2๋ฒˆ ๋ฐฐ์—ด์˜ id: 0์„,
๋ฆฌ์•กํŠธ๋Š” 1๋ฒˆ ๋ฐฐ์—ด์˜ id: 1๊ณผ 2๋ฒˆ ๋ฐฐ์—ด์˜ id: 1์„,
๋ฆฌ์•กํŠธ๋Š” 1๋ฒˆ ๋ฐฐ์—ด์˜ id: 2๊ณผ 2๋ฒˆ ๋ฐฐ์—ด์˜ id: 2๋ฅผ ๋น„๊ตํ•  ๊ฒƒ์ด๋‹ค.

2๋ฒˆ ๋ฐฐ์—ด๋งŒ title๊ณผ content๊ฐ€ ๋ฐ”๋€Œ์—ˆ์œผ๋ฏ€๋กœ ์ด๊ฒƒ๋งŒ ๋ฆฌ๋ Œ๋”๋งํ•ด์ฃผ๋ฉด ๋!

๊ทธ๋Ÿฐ๋ฐ index๋ฅผ key๋กœ ์‚ฌ์šฉํ•˜๋ฉด?

๊ฐ’์ด ๋ฐ”๋€Œ์ง€ ์•Š์•„๋„ ๋ฐฐ์—ด ์ดˆ์ค‘๋ฐ˜์— ์ถ”๊ฐ€ ์ˆ˜์ • ์‚ญ์ œ๊ฐ€ ์ผ์–ด๋‚˜๋ฉด key๊ฐ€ ๋ฐ”๋€Œ๊ธฐ ๋•Œ๋ฌธ์— ๋งค๋ฒˆ ๊ฐ’์ด ๋ฐ”๋€Œ์—ˆ๋‹ค๊ณ  ์ธ์‹ํ•˜๊ณ  ๋น„ํšจ์œจ์ ์ธ ๋ฆฌ๋ Œ๋”๋ง์„ ํ•˜๊ฒŒ ๋œ๋‹ค.

๋”ฐ๋ผ์„œ index๋ฅผ key๋กœ ์‚ฌ์šฉํ•˜๋Š”๊ฒƒ์„ ์ง€์–‘ํ•˜์ž!

๐Ÿ’ก ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

๊ทธ๋Ÿฐ๋ฐ ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์˜ ๊ฒฝ์šฐ ์ˆ˜์ •, ์ถ”๊ฐ€, ์‚ญ์ œ์™€ ๊ฐ™์€ ๋™์ž‘์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์•˜๋‹ค.
๊ทธ๋ƒฅ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์—ฌ์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด ๋๊ธฐ ๋•Œ๋ฌธ์— index๋ฅผ key๋กœ ์‚ฌ์šฉํ•ด๋„ ๊ดœ์ฐฎ๋‹ค๊ณ  ํŒ๋‹จ!

๊ทธ๋ž˜์„œ ๊ทธ๋ƒฅ eslint๋ฅผ ์ˆ˜์ •ํ–ˆ๋‹ค

    // key๊ฐ’์œผ๋กœ index๋ฅผ ์‚ฌ์šฉํ• ์ˆ˜ ์žˆ๋„๋ก
    "react/no-array-index-key": "off",


2. ํ…์ŠคํŠธ์—์„œ ์ค„๋ฐ”๊ฟˆํ•˜๋Š” ๋ฒ•

๐Ÿค” ์—๋Ÿฌ๊ฐ€ ์ผ์–ด๋‚˜๋Š” ์ด์œ 

๋ฐ์ดํ„ฐ๋ฅผ ๋กœ์ปฌ์— ์žˆ๋Š” result.json์—์„œ ๊ฐ€์ ธ๋‹ค ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ jsx์—์„œ ์ค„๋ฐ”๊ฟˆ ๋ฌธ์ž \n ์ด ๋™์ž‘ํ•˜์ง€ ์•Š์•˜๋‹ค.

     "desc": [
        "ํ•œ ๋‹ฌ ๋™์•ˆ ๊ณ ๋ฏผํ•ด์„œ ์‚ฐ ๊ฐ€๋ฐฉ์„ ์นœ๊ตฌ๋“คํ•œํ…Œ\n ์ž๋ž‘ํ–ˆ๋Š”๋ฐ ์นœ๊ตฌ๋“ค ๋ฐ˜์‘์ด ์˜ ์‹œํฐ๋‘ฅํ•˜๋„ค์š”. ๋ญ,\n ๋‚˜๋Š” ์ •๋ง ๋งˆ์Œ์— ๋“ค์–ด์„œ ์ƒ๊ด€์—†์–ด์š”.", 
       ...
      ],

๊ทธ๋ž˜์„œ <br/>์„ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ ๊ทธ๊ฒƒ๋„ ๊ทธ๋ƒฅ ํ•œ ๋‹ฌ ๋™์•ˆ ๊ณ ๋ฏผํ•ด์„œ ์‚ฐ ๊ฐ€๋ฐฉ์„ ์นœ๊ตฌ๋“คํ•œํ…Œ<br/> ์ž๋ž‘ํ–ˆ๋Š”๋ฐ ์นœ๊ตฌ๋“ค ๋ฐ˜์‘์ด ์˜ ์‹œํฐ๋‘ฅํ•˜๋„ค์š”. ์ด๋Ÿฐ์‹์œผ๋กœ ๊ทธ๋Œ€๋กœ ๋‚˜์™”๋‹ค.

๐Ÿ’ก ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ์ง„์งœ ๊ฐ„๋‹จํ–ˆ๋Š”๋ฐ ์ฐพ๋Š”๋ฐ ์งฑ์˜ค๋ž˜๊ฑธ๋ ธ๋‹ค.
๋ฐ”๋กœ css์—์„œ white-space:pre-wrap ์„ค์ •ํ•˜๊ธฐ!
๊ทธ๋Ÿผ ์ค„๋ฐ”๊ฟˆ ๋ฌธ์ž \n๋ฅผ ์ธ์‹ํ•˜๊ณ  ์ค„ ๋ฐ”๊ฟˆํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•ด์ค€๋‹ค.

CSS white-space ์†์„ฑ์€ ์š”์†Œ๊ฐ€ ๊ณต๋ฐฑ ๋ฌธ์ž๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฒ•์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.



3. ์Šคํƒ€์ผ props ์—๋Ÿฌ

๐Ÿค” ์—๋Ÿฌ๊ฐ€ ์ผ์–ด๋‚˜๋Š” ์ด์œ 

ํƒ€์ž… ์ง€์ •์„ ์•ˆํ•ด์คฌ๊ธฐ ๋•Œ๋ฌธ!

๐Ÿ’ก ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

CSS์—๋„ ํƒ€์ž… ์ง€์ •์„ ํ•ด์ฃผ๋ฉด ๋จ!



4. useMemo ์‚ฌ์šฉ

๐Ÿค” ์—๋Ÿฌ๊ฐ€ ์ผ์–ด๋‚˜๋Š” ์ด์œ 

์‚ฌ์‹ค ์—๋Ÿฌ๋Š” ์•„๋‹ˆ๊ณ  ์ฒ˜์Œ ์‚ฌ์šฉํ•ด๋ด์„œ ๊ทธ๋ƒฅ ๋ผ์›Œ๋’€๋‹ค.
์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ์—ฐ์‚ฐ๋œ ๊ฐ’์„ ์žฌ์‚ฌ์šฉํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ–ˆ๋‹ค.

๐Ÿ’ก ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

useMemo

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

Returns a memoized value.

์‚ฌ์šฉ ๋ฐฉ๋ฒ•
ํ”Œ์ ์—์„œ useMemo๋ฅผ ์‚ฌ์šฉํ•œ ๋ถ€๋ถ„๋งŒ ์ž˜๋ผ์™”๋‹ค!

const quiz = ({ data }: any) => {
  const [steps, setStep] = useState<number>(0);
  // data๋ผ๋Š” ๋ฐฐ์—ด์ด ์žˆ๊ณ  ์šฐ๋ฆฌ๋Š” ๊ทธ ๋ฐฐ์—ด์—์„œ ํ•ด๋‹น step์ธ ๋ฐ์ดํ„ฐ๋งŒ ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ์Œ 
  // ์˜ˆ๋ฅผ๋“ค์–ด step์ด 1์ด๋ฉด data ๋ฐฐ์—ด์˜ 1๋ฒˆ์งธ ์š”์†Œ๋งŒ ๋ณด์—ฌ์คŒ
  
  // memoization ํ•  ๊ฐ’ step
  const currentData = useMemo(() => data[steps], [steps]);
  
  ... ์ƒ๋žต

  const handleClickNextStep = (ans: AnswerProps) => {
  // step์ด 8๊นŒ์ง€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— 8์ด ์•„๋‹ˆ๋ฉด +1 ์„ ํ•ด์คŒ
    if (steps !== 8) {
      setStep((step) => step + 1);
      return;
    }
  };
  
  ... ์ƒ๋žต
  
  );
};


5. do not add stylesheets using next/head

๐Ÿค” ์—๋Ÿฌ๊ฐ€ ์ผ์–ด๋‚˜๋Š” ์ด์œ 

head์— ์Šคํƒ€์ผ ์‹œํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์—ˆ๋Š”๋ฐ ๋”ฐ๋กœ ๋งŒ๋“ค๊ธฐ ๊ท€์ฐฎ์•„์„œ ๊ทธ๋ƒฅ SEO๋ฅผ ์œ„ํ•ด ๋งŒ๋“ค์–ด๋‘” Headํƒœ๊ทธ ๋‚ด์— ์Šคํƒ€์ผ ์‹œํŠธ๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋”๋‹ˆ ์ด๋Ÿฐ ์›Œ๋‹๊ฐ€ ๋–ด๋‹ค.

We don't recommend this pattern because it will potentially break when used with Suspense and/or streaming. In these contexts, next/head tags aren't:
โžก๏ธ suspense ๋˜๋Š” ์ŠคํŠธ๋ฆฌ๋ฐ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ์‹œ ๊นจ์งˆ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ

  • guaranteed to be included in the initial SSR response, so loading could be delayed until client-side rendering, regressing performance.
    โžก๏ธ ์ฒซ SSR ์‘๋‹ต์— ํฌํ•จ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํด๋ผ์ด์–ธํŠธ ์ธก ๋ Œ๋”๋ง๊นŒ์ง€ ๋กœ๋“œ๊ฐ€ ์ง€์—ฐ๋˜ ์„ฑ๋Šฅ์ด ์ €ํ•˜๋  ์ˆ˜ ์žˆ์Œ
  • loaded in any particular order. The order that the app's Suspense boundaries resolve will determine the loading order of your stylesheets.
    โžก๏ธ ํŠน์ • ์ˆœ์„œ๋กœ ๋กœ๋“œ
    ์•ฑ์˜ Suspense ๋ฐ”์šด๋”๋ฆฌ๊ฐ€ ํ•ด๊ฒฐ๋˜๋Š” ์ˆœ์„œ๊ฐ€ ๋‹น์‹ ์˜ Stylesheets์˜ ๋กœ๋”ฉ ์ˆœ์„œ๋ฅผ ๊ฒฐ์ •ํ•จ

    ๋„ฅ์ŠคํŠธ ๊ณต์‹๋ฌธ์„œ ์ฐธ์กฐํ•˜๊ธฐ

โž• suspense?

Suspense lets components โ€œwaitโ€ for something before rendering.
โžก๏ธ suspense๋Š” ๋ Œ๋”๋ง ์ „ ์–ด๋–ค ๊ฒƒ์„ ์œ„ํ•ด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ธฐ๋‹ค๋ฆฌ๋„๋ก ํ•ด์ฃผ๋Š” ๊ฒƒ

์•„์ง ๋ Œ๋”๋ง์ด ์ค€๋น„๋˜์ง€ ์•Š์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์„๋•Œ ๋กœ๋”ฉ ํ™”๋ฉด์„ ๋ณด์—ฌ์ฃผ๊ณ  ๋กœ๋”ฉ์ด ์™„๋ฃŒ๋˜๋ฉด ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” React์— ๋‚ด์žฅ๋˜์–ด ์žˆ๋Š” ๊ธฐ๋Šฅ์ด๋ผ๊ณ  ํ•œ๋‹ค.

๐Ÿ’ก ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

์นœ์ ˆํ•˜๊ฒŒ ๊ณต๋ฌธ์— ํ•ด๊ฒฐ๋ฒ•๋„ ๋‚˜์™€์žˆ์Œ

Add the stylesheet in a custom Document component.

// pages/_document.js
import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html>
      <Head>
        <link rel="stylesheet" href="..." />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

๋” ์•Œ์•„๋ณด๊ธฐ โžก๏ธ app๊ณผ document์˜ ์ฐจ์ด์ 


6. document is not defined

๐Ÿค” ์—๋Ÿฌ๊ฐ€ ์ผ์–ด๋‚˜๋Š” ์ด์œ 

โžก๏ธ document๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์—์„œ๋งŒ ์ •์˜๋œ ์ „์—ญ ๋ณ€์ˆ˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

Next๋Š” ๋ฆฌ์•กํŠธ๋ฅผ SSR ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ์ฒซ ๋ Œ๋”๋ง์ด SSR ๋ฐฉ์‹์œผ๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.
๋ฐ˜๋ฉด document๋Š” CSR์ด ๋™์ž‘ํ•  ๋•Œ ์ฆ‰, view ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์›น ํŽ˜์ด์ง€๋ฅผ ๋™์ž‘ํ•˜๋Š” ์š”์†Œ๋“ค์ด ๋ชจ๋‘ ํด๋ผ์ด์–ธํŠธ์— ๋กœ๋“œ๋˜์—ˆ์„ ๋•Œ ์ •์˜๋œ๋‹ค.

๋”ฐ๋ผ์„œ SSR์ด ์‹คํ–‰๋  ๋•Œ document์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋˜ ๊ฒƒ์ด๋‹ค.
์ฐธ๊ณ ๋กœ window๋„ ๊ฐ™์€ ์ด์œ ๋กœ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•จ!

๐Ÿ’ก ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•!
window๋‚˜ document๊ฐ€ undefined๊ฐ€ ์•„๋‹ ๋•Œ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ๋งŒ๋“ค๋ฉด ๋œ๋‹ค!

  if (typeof window !== 'undefined') {
      // Client-side-only code
   		 ์‹คํ–‰ํ•  ์ฝ”๋“œ ์ž…๋ ฅ!
    }


์ด๋ฏธ์ง€ ๋ Œ๋”๋ง, ํฐํŠธ๋Š” SEO, ํผํฌ๋จผ์Šค ๊ฐœ์„ ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ใ„ฑใ„ฑใ„ฑ

profile
๊ฐœ๋ฐœ์ž๋กœ ์„ฑ์žฅํ•˜๊ธฐ ์œ„ํ•œ ์•„์นด์ด๋ธŒ ๐Ÿ˜Ž

0๊ฐœ์˜ ๋Œ“๊ธ€