๐Ÿšค ์„ฑ์žฅ์ผ์ง€ 7.0

์ฑ… ํ–‰๋ณตํ•œ ์ด๊ธฐ์ฃผ์˜์ž(์›จ์ธ ๋‹ค์ด์–ด)์˜ ๋‚ด์šฉ์— ์ž๊ทน๋ฐ›์•„ ์‹œ์ž‘ํ•˜๋Š” ์†Œ๋ฐ•ํ•œ ์„ฑ์žฅ๊ธฐ๋ก

์‚ด์•„์žˆ๋Š” ๊ฝƒ๊ณผ ์ฃฝ์€ ๊ฝƒ์€ ์–ด๋–ป๊ฒŒ ๊ตฌ๋ณ„ํ•˜๋Š”๊ฐ€?
์„ฑ์žฅํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ด ์‚ด์•„ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.
์ƒ๋ช…์˜ ์œ ์ผํ•œ ์ฆ๊ฑฐ๋Š” ์„ฑ์žฅ์ด๋‹ค!

โš› (7.0)<์™„์ „ ๊ฐœํŽธ> ํŒŒ์ธ๋งŒ ํ•™์Šต๋ฒ•์„ ์•Œ๊ฒŒ ๋œ๋งŒํผ, ์„ฑ์žฅ์ผ์ง€๋Š” ์ •๋ง ๊ทธ ๋‚ ์˜ ํ‚ค์›Œ๋“œ ์ค‘์‹ฌ์œผ๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ •๋ฆฌํ•˜๋„๋ก ํ•œ๋‹ค.

โš›๏ธ ํ‚ค์›Œ๋“œ: ์ง๊ด€์ ์ด๊ณ  ์‰ฝ๊ณ  ๊ฐ„๋‹จํ•˜๊ฒŒ ์ž‘์„ฑ

๋ฌดํ•œ ์Šคํฌ๋กค

์ด์ œ๋Š” ๋งŽ์ด ์ต์ˆ™ํ•ด์ง„ UX๋กœ, ์œ ์ €๊ฐ€ ์Šคํฌ๋กค์„ ๋‚ด๋ฆด ๋•Œ๋งˆ๋‹ค ํŠน์ • ์œ„์น˜์—์„œ data๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ์‹์ด๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์œ ์ €๋Š” ๋” ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๊ณ , ์„œ๋ฒ„๋Š” ๋ถˆํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

์˜ˆ์ „์—๋Š” ์œ ์ €์˜ viewpoint์˜ ์œ„์น˜๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ํŠน์ • ์œ„์น˜์— ๋„๋‹ฌํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ์‹์ด์—ˆ๋‹ค๋ฉด, ์ด์ œ๋Š” Intersection Observer API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŠน์ • ์š”์†Œ๊ฐ€ viewport์— ๋“ค์–ด์˜ค๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•œ๋‹ค.

Intersection Observer API๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์š”์†Œ์˜ ์œ„์น˜๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๋ธŒ๋ผ์šฐ์ €์˜ viewport์™€ ์š”์†Œ์˜ ์œ„์น˜๋ฅผ ๋น„๊ตํ•˜์—ฌ ์š”์†Œ๊ฐ€ viewport์— ๋“ค์–ด์˜ค๋ฉด ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์–ด๋–ค ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค. ๋ฌดํ•œ ์Šคํฌ๋กค์„ ๊ตฌํ˜„ํ•  ๋•Œ๋Š”, ์ฝœ๋ฐฑ ํ•จ์ˆ˜์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

Error Boundary

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

๋ง ๊ทธ๋Œ€๋กœ ์ปดํฌ๋„ŒํŠธ ๊ณ„์ธต ๊ตฌ์กฐ์—์„œ ํŠน์ • ๊ฒฝ๊ณ„๋ฅผ ๋‘์–ด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๊ทธ ๋ฐ”๊นฅ์œผ๋กœ ์—๋Ÿฌ๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š๊ณ  ๋‚ด๋ถ€์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

ํ”ํžˆ ์šฐ๋ฆฌ๊ฐ€ ์–ด๋–ค ์›น ์‚ฌ์ดํŠธ์˜ ์ผ๋ถ€๋ถ„๋งŒ ์—๋Ÿฌ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๋Š” ๊ฒƒ์„ ๋ณธ ์ ์ด ์žˆ์„ ๊ฒƒ์ด๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ๊ฐ€ ๋ฐ”๋กœ Error Boundary๋ฅผ ์‚ฌ์šฉํ•œ ๊ฒฝ์šฐ์ด๋‹ค.

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
  // ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ
  static getDerivedStateFromError(error) {
    // ๋‹ค์Œ ๋ Œ๋”๋ง์—์„œ ํด๋ฐฑ UI๊ฐ€ ๋ณด์ด๋„๋ก ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธ
    return { hasError: true };
  }
  componentDidCatch(error, errorInfo) {
    // ์—๋Ÿฌ ๋ฆฌํฌํŒ… ์„œ๋น„์Šค์— ์—๋Ÿฌ๋ฅผ ๊ธฐ๋กํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
    logErrorToMyService(error, errorInfo);
  }
  render() {
    if (this.state.hasError) {
      // ํด๋ฐฑ UI๋ฅผ ์ปค์Šคํ…€ํ•˜์—ฌ ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ๋‹ค.
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}

React Router์˜ errorElement

React Router์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์œผ๋กœ, ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํŠน์ • ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. React์˜ Error Boundary์™€ ๋น„์Šทํ•ด๋ณด์ด์ง€๋งŒ Error Boundary๋Š” ํŠน์ • ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ ๊ตฌ๊ฐ„์—์„œ์˜ ์—๋Ÿฌ๋ฅผ ํ•ธ๋“ค๋งํ•˜์—ฌ UI๋กœ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๋‹ค๋ฉด React Router์˜ errorElement๋Š” ํŠน์ • ๊ฒฝ๋กœ(route path)์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋งŒ ํŠน์ • ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

๐Ÿ“ ํšŒ๊ณ 

๊ตฌํ˜„ํ•ด๋‘์—ˆ๋˜ ๋ฌดํ•œ ์Šคํฌ๋กค ๊ตฌํ˜„ ๋ถ€๋ถ„์„ ์ˆ˜์ •ํ•˜๊ณ  ์—๋Ÿฌ ๋ฐ”์šด๋”๋ฆฌ์— ๋Œ€ํ•ด์„œ ๊ณต๋ถ€ํ–ˆ๋‹ค. ์˜ค๋Š˜ ์ผ์ง€์—๋Š” ์—†๋Š” ๋‚ด์šฉ์ด์ง€๋งŒ, useQuery์™€ ๋น„์Šทํ•˜๊ฒŒ ๊ตฌํ˜„ํ•œ ์ปค์Šคํ…€ ํ›…์—์„œ isLoading์„ ํ†ตํ•ด Loading ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๊ฒŒ ํ•˜๋ ค๋Š”๋ฐ ์ž˜ ๋˜์ง€ ์•Š์•„์„œโ€ฆ ๋‚ด์ผ๋„ ์ด ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ ์ˆ˜์ •ํ•ด๋ณผ ์˜ˆ์ •์ด๋‹ค.

์ฐธ๊ณ