โœ๐Ÿป [Code Camp_TIL] 11์ผ์ฐจ: ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง, ์ฝ”๋“œ๋ฆฐํ„ฐ์™€ ์ฝ”๋“œ ํฌ๋ฉงํ„ฐ(eslint & prettier)

code_Jยท2023๋…„ 4์›” 3์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
16/41
post-thumbnail

์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง


๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๊ฑฐ๋‚˜ ๋ฉ”๋‰ด๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ, ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š”๋ฐ ์ž˜ ์ž‘๋™๋˜์ง€ ์•Š์„ ๋•Œ๊ฐ€ ์žˆ์—ˆ๋‹ค. ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง์„ ์•Œ๊ฒŒ ๋˜๋ฉด ์™œ ์ž‘๋™์ด ์ž˜ ๋˜์ง€ ์•Š์•˜๋Š”์ง€ ๋ช…ํ™•ํ•˜๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค.

ํด๋ฆญํ–ˆ์„ ๋•Œ, "00๋‹˜์ด ์ž‘์„ฑํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค." ๋ผ๋Š” ๋ฌธ๊ตฌ๊ฐ€ ๋œจ๊ฒŒ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, onClick์„ ์–ด๋””์— ๋‘์–ด์•ผ ํ• ๊นŒ? ๊ณต๋ฐฑ์ด๋‚˜ div box ์˜์—ญ์„ ํด๋ฆญํ•˜๋ฉด ์•Œ๋ฆผ์ฐฝ์€ ๋œจ์ง€๋งŒ, ์•Œ๋ฆผ ๋ฌธ๊ตฌ๊ฐ€ ์ œ๋Œ€๋กœ ๋œจ์ง€ ์•Š๋Š”๋‹ค. ์–ด๋””๋ฅผ ํด๋ฆญํ•˜๋“  ์ œ๋Œ€๋กœ ์•Œ๋ฆผ์ด ๋œจ๋„๋ก ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ?


์ž์‹ div์— onclick ์†์„ฑ์„ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด, ๋ถ€๋ชจ div์— ์žˆ๋˜ onclick ์†์„ฑ๋„ ํ•จ๊ป˜ ์‹คํ–‰๋œ๋‹ค. ์ฆ‰ ์ž์‹ div์˜ click event๊ฐ€ ๋ถ€๋ชจ div๋กœ ์ „ํŒŒ๋œ๋‹ค. ์ด๋ฅผ propagation์ด๋ผ ํ•œ๋‹ค. ๊ทธ๋ฆผ์„ ๋ณด๋ฉด์„œ ์ดํ•ดํ•˜๋ฉด ์‰ฝ๋‹ค.

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


<form onclick="alert(form)">
	<div onclick="alert(div)">
		<p onclick="alert(p)">P</p>
	</div>
</form>

์˜ˆ๋ฅผ ๋“ค์–ด, ์œ„์™€ ๊ฐ™์€ ๊ตฌ์กฐ์—์„œ p ํƒœ๊ทธ๋ฅผ ํด๋ฆญํ•˜๋ฉด p -> div -> form ์˜ ์ˆœ์„œ๋กœ 3๊ฐœ์˜ ๊ฒฝ๊ณ ์ฐฝ์ด ๋‚˜ํƒ€๋‚˜๊ฒŒ ๋œ๋‹ค.


์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง ์ค‘๋‹จ


const onClick = (event: MouseEvent<HTMLDivElement>) => {
    if (event.target instanceof Element)
      alert(event.target.id + "๋‹˜์ด ์ž‘์„ฑํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.");
  };
  return (
    <div>
      {data?.fetchBoards?.map((el) => (
        <div onClick={onClick} id={el.writer ?? ""}>
          <span>{el.number}</span>
          <span>{el.title}</span>
          <span>{el.writer}</span>
        </div>
      ))}
    </div>
  );

์œ„ ์˜ˆ์‹œ์—์„œ๋Š” onClick ํ•จ์ˆ˜๊ฐ€ ์ œ๋ชฉ์ด๋‚˜ ๋‚ด์šฉ์— ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ „์ฒด๋ฅผ ๊ฐ์‹ธ์ฃผ๋Š” ๋ฐ•์Šค์— ์žˆ์–ด์„œ ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง์ด ๋ฐœ์ƒํ•œ๋‹ค. number, title ๋“ฑ์˜ span ํƒœ๊ทธ๊ฐ€ ์žˆ๋Š” ์˜์—ญ์„ ํด๋ฆญํ•˜๋ฉด id๋ฅผ ๋ฐ›์•„์˜ค์ง€ ๋ชปํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด, ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?


id๋ฅผ ๋ถ€๋ชจ div์— ์ฃผ๊ณ , event.target์ด ์•„๋‹Œ event.currentTarget์„ ์ ์šฉํ•ด์ฃผ๋ฉด ๋œ๋‹ค. event.target์€ ์šฐ๋ฆฌ๊ฐ€ ํด๋ฆญํ•œ ํƒœ๊ทธ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ , ๊ทธ ํƒœ๊ทธ์˜ id๋ฅผ ๊ฐ€์ ธ์˜ค์ง€๋งŒ, event.currentTarget์€ ํ˜„์žฌ ์ž‘๋™ํ•˜๊ณ  ์žˆ๋Š” ํƒ€๊ฒŸ์œผ๋กœ event.target์œผ๋กœ ์ธํ•ด ์ž‘๋™๋˜๋Š” ํƒœ๊ทธ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ๋œ๋‹ค. ๋ฒ„๋ธ”๋ง์„ ํ†ตํ•ด ๋ฐ”์ธ๋”ฉ๋˜์–ด ์žˆ๋Š” ํƒœ๊ทธ๊ฐ€ ์ž‘๋™ํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋Ÿฌํ•œ ๊ณผ์ •์„ ์œ„์ž„(delegation)์ด๋ผ๊ณ  ํ•œ๋‹ค.


๋˜ ๋‹ค๋ฅธ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์œผ๋กœ๋Š”, event.stopPropagation()์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์žˆ๋‹ค.

export default function StaticRoutingPage() {
  const { data } = useQuery(FETCH_BOARDS);

  const qqq1 = (event) => {
    alert("1๋ฒˆ ํด๋ฆญ");
  };

  const qqq4 = (event) => {
    event.stopPropagation();
    // 1๋ฒˆ์œผ๋กœ ์ „ํŒŒ๋˜์ง€ ์•Š๋„๋ก ์„ค์ •
    alert("4๋ฒˆ ํด๋ฆญ");
  };

  return (
    <div>
      {data?.fetchBoards.map((el: any) => (
        <div id={el.writer} onClick={qqq1}>
          <Checkbox />
          <span style={{ margin: "10px" }} onClick={qqq4}>
            {el.number}
          </span>
          <span style={{ margin: "10px" }}>{el.title}</span>
          <span style={{ margin: "10px" }}>{el.writer}</span>
        </div>
      ))}
    </div>
  );
}

์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง์˜ ๋ฐ˜๋Œ€๋˜๋Š” ๊ฐœ๋…์œผ๋กœ ์ด๋ฒคํŠธ ์บก์ฒ˜๋ง์ด ์žˆ์ง€๋งŒ, ๋””ํดํŠธ ๊ฐ’์€ ๋ฒ„๋ธ”๋ง์ด๊ธฐ ๋•Œ๋ฌธ์— ์บก์ฒ˜๋ง์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋”ฐ๋กœ ์„ค์ •์„ ํ•ด์ค˜์•ผ ํ•œ๋‹ค.



์ฝ”๋“œ์˜ ๊ทœ์น™ ์ •ํ•˜๊ธฐ

๊ฐœ๋ฐœ์ž๋“ค์€ ํŒ€ ๋‹จ์œ„๋กœ ํ˜‘์—…์„ ๋งŽ์ด ํ•˜๋Š”๋ฐ, ๊ทธ ๊ณผ์ •์—์„œ ์ผ์„ ์กฐ๊ธˆ ๋” ์ˆ˜์›”ํ•˜๊ฒŒ ์ง„ํ–‰ํ•˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด ์ฝ”๋“œ์— ๊ทœ์น™์„ ์ •ํ•ด ํ†ต์ผ์„ฑ์„ ๊ฐ–์ถ”๋„๋ก ํ•œ๋‹ค.


์ฝ”๋“œ ๋ฆฐํ„ฐ์™€ ์ฝ”๋“œ ํฌ๋ฉงํ„ฐ

์ฝ”๋“œ๋ฆฐํ„ฐ: ๋ฌธ๋ฒ• ์ƒ ์—๋Ÿฌ๋Š” ์•„๋‹ˆ์ง€๋งŒ, ์—๋Ÿฌ๋กœ ์•ฝ์†ํ•˜์ž๊ณ  ๊ทœ์น™์„ ์ •ํ•˜๋Š” ๊ฒƒ
์ฝ”๋“œ ํฌ๋ฉ”ํ„ฐ: ์ฝ”๋“œ๋ฅผ ๋ณด๊ธฐ ์ข‹๊ฒŒ ๋งŒ๋“ค์–ด์ฃผ๋Š” ๊ฒƒ

์ฝ”๋“œ๋ฆฐํ„ฐ์˜ ๋Œ€ํ‘œ์ ์ธ ๊ฒƒ์ด eslint, ์ฝ”๋“œ ํฌ๋ฉงํ„ฐ์˜ ๋Œ€ํ‘œ์ ์ธ ๊ฒƒ์ด prettier๋‹ค.

eslint์™€ prettier๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” vs code์— ์„ค์น˜๋ฅผ ํ•ด์ค˜์•ผ ํ•œ๋‹ค. eslint๋Š” ESLinst Extention์„, prettier๋Š” Prettier Extention์„ ์„ค์น˜ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.



์˜ค๋Š˜์€ ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง๊ณผ ์›ํ™œํ•œ ํ˜‘์—…์„ ์œ„ํ•œ ์ฝ”๋“œ๋ฆฐํ„ฐ ๋ฐ ์ฝ”๋“œ ํฌ๋ฉงํ„ฐ๋ฅผ ๋ฐฐ์› ๋‹ค.

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

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

๊ทธ๋ฆฌ๊ณ  eslint์™€ prettier extention์„ ์„ค์น˜ํ•ด์„œ ์‚ฌ์šฉ์„ ํ•ด๋ดค๋Š”๋ฐ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์ฒ˜๋Ÿผ ๊ผผ๊ผผํ•˜๊ฒŒ ๊ทœ์น™์„ ์ •ํ•ด๋†“์•˜๊ณ , ์–ด๊ฒผ์„ ์‹œ์— ๋นจ๊ฐ„ ์ค„๋กœ ์—๋Ÿฌ๋ฅผ ๋„์›Œ์ค€๋‹ค.

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



profile
Web FE ๊ฐœ๋ฐœ์ž ์ทจ์ค€์ƒ

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