[๐Ÿ”ซ][W-Guardian] GPT์™€ Trouble Shooting

Hazยท2024๋…„ 6์›” 7์ผ

Trouble Shooting

๋ชฉ๋ก ๋ณด๊ธฐ
3/4

์ตœ๊ทผ CURSOR๋ผ๋Š” ์ฝ”๋“œ ์—๋””ํ„ฐ๋ฅผ ํ™œ์šฉํ•˜๊ณ  ์žˆ๋Š”๋ฐ ์ฒ˜์Œ์—๋Š” 'VSCode๋ž‘ ํ”Œ๋Ÿฌ๊ทธ์ธ ์—ฐ๋™๋˜๋Š” ์ ๊ณผ UI๊ฐ€ ๋น„์Šทํ•ด์„œ ์ž˜ ์ ์‘ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฑธ ์ œ์™ธํ•˜๋ฉด ๋ณ„ ์ด์ ์ด ์—†์ง€ ์•Š๋‚˜?' ์ƒ๊ฐํ–ˆ๋Š”๋ฐ, ๊ทธ๋žฌ๋˜ ๋‚˜ ์ž์‹  ๋ฐ˜์„ฑ ์ค‘...

CURSOR code editor

CURSOR IDE
์ฝ”๋“œ ์—๋””ํ„ฐ ์ž์ฒด์— GPT์™€ ์ž์—ฐ์–ด๋กœ ๋Œ€ํ™”ํ•˜๋ฉด์„œ ๊ฐœ๋ฐœ์ด ๊ฐ€๋Šฅํ•˜๊ณ , ์ฝ”๋“œ ์—๋””ํŒ… ๊ณผ์ •์— ๋‹จ์ถ•ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ์ฝ”๋“œ ์ƒ์„ฑ์„ ์ถ”์ฒœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” AI ํƒ‘์žฌํ˜• IDE

์ด IDE๋กœ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ VSCode์—์„œ ์ฝ”ํŒŒ์ผ๋Ÿฟ์ด๋‚˜ ChatGPT ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์“ฐ๋˜ ์—ฌํƒ€ ๊ฐœ๋ฐœ์ž ๋™๋ฃŒ ๋ถ„๋“ค์˜ ํฌ์—ด์„ ์ฒด๊ฐํ–ˆ๋‹ค. ์ž์—ฐ์–ด๋กœ AI์™€ ๋Œ€ํ™”ํ•˜๋ฉด์„œ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” ์ด ํŽธ๋ฆฌํ•จ์€ ๋„์ €ํžˆ ๊ทธ ์ „์œผ๋กœ ๋Œ์•„๊ฐˆ ์ˆ˜ ์—†๋Š” ์–ด๋–ค ๊ฒƒ์ด์—ˆ๋‹ค.

๊ฒŒ๋‹ค๊ฐ€ ChatGPT 4.0 ๋ฒ„์ „์„ ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ€„๋ฆฌํ‹ฐ ๋†’์€ ์ฝ”๋“œ ์ง€์›์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด ํŠนํžˆ ๋งŒ์กฑ์Šค๋Ÿฌ์› ๋‹ค. ๋ฌผ๋ก  ๋ฌด๋ฃŒ ๋ฒ„์ „์€ ํ•˜๋ฃจ์— 50ํšŒ๋กœ ํ•œ๋„๊ฐ€ ์ •ํ•ด์ ธ ์žˆ๊ณ , ๋น„์šฉ์„ ์ง€๋ถˆํ•˜๋ฉด ๊ทธ๋ณด๋‹ค ํ›จ์”ฌ ๋งŽ์€ ํšŸ์ˆ˜๋กœ AI์˜ ์ฝ”๋“œ ์ง€์›์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋ฌด๋ฃŒ ๋ฒ„์ „์œผ๋กœ๋„ ์ด์ „์— ์ฝ”ํŒŒ์ผ๋Ÿฟ์ด๋‚˜ ์œ ๋ฃŒ ChatGPT ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•ด๋ณธ์ ์ด ์—†๋Š” ์œ ์ €๋ผ๋ฉด ์ถฉ๋ถ„ํžˆ ํ•„์ž์ฒ˜๋Ÿผ ๋งŒ์กฑํ•  ์ˆ˜ ์žˆ์œผ๋ฆฌ๋ผ ์ƒ๊ฐํ•œ๋‹ค.

โ€ป ๊ด‘๊ณ  ์•„๋‹˜. ๊ด‘๊ณ  ํ™˜์˜.

๐Ÿ”ซ TypeScript Trouble-Shooting

๋ณธ๊ฒฉ์ ์œผ๋กœ IDE์™€ ChatGPT์˜ ๋„์›€์„ ๋ฐ›์•„ ์–ด๋–ค ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ๋Š”์ง€ ๋ณด์ž.

1. ~.ts ํŒŒ์ผ์—์„œ error ํƒ€์ž…์„ ์–ด๋–ป๊ฒŒ ์„ค์ •ํ•˜๋ฉด ์ข‹์„๊นŒ?

const GetWeather = () => {
  const { loc, error: locationError } = useCurrentLocation(geolocationOptions);

  const {
    data: weatherData,
    isLoading,
    isError,
    error,
  } = useQuery(...);
               
};

๋ฌธ์ œ๋Š” Tanstack Query ํ›…์ธ useQuery()๋กœ ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น์„ ํ†ตํ•ด ๋ณ€์ˆ˜์— ๊ฐ’์„ ํ• ๋‹นํ•  ๋•Œ ๋ฐœ์ƒํ–ˆ๋‹ค. ErrorLens ํ”Œ๋Ÿฌ๊ทธ์ธ์œผ๋กœ ์ฝ”๋“œ ์˜†์— error ํƒ€์ž…์„ ์„ค์ •ํ•˜๋ผ๋Š” ํƒ€์ž… ๊ฒฝ๊ณ  ๋ฌธ๊ตฌ๊ฐ€ ๋ถ‰๊ฒŒ ๋‚˜ํƒ€๋‚ฌ๋‹ค.

ํฌ๊ฒŒ ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ๊ฑด ์•„๋‹ˆ์ง€๋งŒ, data์˜ ํƒ€์ž…๋„ ํ•จ๊ป˜ ๊ฒฝ๊ณ  ๋ฌธ๊ตฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•จ๊ป˜ ํ•ด๊ฒฐํ•ด์•ผ๊ฒ ๋Š”๋ฐ ๋‚˜์˜ ์Šค์Šน, ChatGPT์—๊ฒŒ ๋ฐฉ๋ฒ•์„ ์งˆ๋ฌธํ•ด๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค.

/** ~.ts ํŒŒ์ผ์—์„œ error ๊ฐ์ฒด๋Š” react-query์˜ useQuery ํ›…์—์„œ ๋ฐ˜ํ™˜๋˜๋Š” ๊ฐ’ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. 
์ด error ๊ฐ์ฒด๋Š” ์ฃผ๋กœ ๋„คํŠธ์›Œํฌ ์š”์ฒญ ์‹คํŒจ๋‚˜ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์ค‘ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 
TypeScript์—์„œ ์ด๋Ÿฌํ•œ error ๊ฐ์ฒด์˜ ํƒ€์ž…์„ ๋ช…์‹œ์ ์œผ๋กœ ์„ค์ •ํ•˜๋ ค๋ฉด, ๋จผ์ € ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” API ํ˜ธ์ถœ์˜ ์˜ˆ์™ธ ์œ ํ˜•์„ ํŒŒ์•…ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 
๋‹ค์Œ์€ error ๊ฐ์ฒด์— ๋Œ€ํ•œ ํƒ€์ž…์„ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค:
1. ์—๋Ÿฌ ํƒ€์ž… ์ •์˜: Error ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™•์žฅํ•˜์—ฌ ์ปค์Šคํ…€ ์—๋Ÿฌ ํƒ€์ž…์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, WeatherAPIError๋ผ๋Š” ํƒ€์ž…์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
**/

interface WeatherAPIError extends Error {
  response?: {
    status: number;
    data: any;
  };
}

/**
* 2. useQuery์˜ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜ ์„ค์ •: useQuery์˜ ์ œ๋„ค๋ฆญ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ error์˜ ํƒ€์ž…์„ WeatherAPIError๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
**/

const {
  data: weatherData,
  isLoading,
  isError,
  error,
} = useQuery<WeatherData, WeatherAPIError>(
  ...
);

์นœ์ ˆํ•˜๊ฒŒ ์ธํ„ฐํŽ˜์ด์Šค๋กœ error ๊ฐ์ฒด์— ์ ์šฉํ•  ํƒ€์ž…์„ ์ƒ์„ฑํ•ด์„œ ์–ด๋–ป๊ฒŒ ์ ์šฉํ•ด์•ผํ•  ์ง€ ์ˆ˜์ •๊นŒ์ง€ ํ•ด์ฃผ์…จ๋‹ค. ์ด ๋Œ€๋‹ต์„ ํ† ๋Œ€๋กœ data์— ๋Œ€์‘์‹œํ‚ฌ WeatherData ํƒ€์ž…๊นŒ์ง€ ์ƒ์„ฑํ•ด์„œ ์ œ๋„ค๋ฆญ์œผ๋กœ ์ ์šฉํ–ˆ๋”๋‹ˆ ํƒ€์ž… ์—๋Ÿฌ๋Š” ์‚ฌ๋ผ์กŒ๋‹ค.

2. data?.name์—์„œ name์ด ํƒ€์ž…์— ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„๊นŒ?

/**
* 1. ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ํƒ€์ž… ํ™•์ธ: ํ•จ์ˆ˜์—์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ์ฒด์˜ ํƒ€์ž…์„ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 
์ด ํ•จ์ˆ˜๊ฐ€ ์ •์˜๋œ ํŒŒ์ผ์„ ์—ด๊ณ , ๋ฐ˜ํ™˜ ํƒ€์ž…์ด ์–ด๋–ป๊ฒŒ ์ •์˜๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.

* 2. ํƒ€์ž… ์ •์˜ ์—…๋ฐ์ดํŠธ: ๋งŒ์•ฝ ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์— name ํ•„๋“œ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด, ํ•ด๋‹น ํƒ€์ž…์— name ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํ•จ์ˆ˜๊ฐ€ `WeatherData` ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด, `WeatherData` ์ธํ„ฐํŽ˜์ด์Šค์— name ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
**/

interface WeatherData {
  name: string; // ๋„์‹œ ์ด๋ฆ„
  // ๊ธฐํƒ€ ํ•„์š”ํ•œ ํ•„๋“œ๋“ค...
}

๊ทธ๋ฆฌ๊ณ  ์ถ”๊ฐ€์ ์œผ๋กœ API ํ˜ธ์ถœ ๋ฐ์ดํ„ฐ๊ฐ€ name ํ•„๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ด๋ณด๋ผ๋Š” ๊ฒƒ๊ณผ ์˜ต์…”๋„ ์ฒด์ด๋‹์œผ๋กœ ๋ฐ˜ํ™˜๋˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ undefined๊ฐ€ ์•„๋‹Œ์ง€ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ œ์•ˆํ–ˆ๋‹ค. ์ด ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€ ํ™•์ธ ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ๊ฐ€ name ํ•„๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ œ์™ธํ•˜๊ณ  ์œ„ 2๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ํ™•์ธํ–ˆ๋‹ค. ๊ฒฐ๊ตญ ํƒ€์ž…์— ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ํƒ€์ž…์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ํ•ด๊ฒฐํ–ˆ๋‹ค.

3. ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋งŒ๋“  weatherData ํƒ€์ž…์„ ์กฐ๊ฑด๋ถ€ ํƒ€์ž… ๋‚ด์—์„œ ํŠน์ • ํƒ€์ž…์„ ์ถ”๋ก ํ•˜๋Š” ๋ฌธ๋ฒ•์ธ infer๋ฅผ ํ™œ์šฉํ•  ์ˆ˜๋„ ์žˆ์„๊นŒ?

๊ณ ๋ฏผํ•˜๋‹ค๋ณด๋‹ˆ ์›Œ๋‚™ API ํ˜ธ์ถœ ๊ฒฐ๊ณผ๋กœ ๋‚˜์˜ฌ ํ•„๋“œ๊ฐ€ ๋งŽ์€๋ฐ ๋ชจ๋‘ ํƒ€์ž…์— ์ถ”๊ฐ€ํ•˜์—ฌ ์ ์šฉํ•˜๊ธฐ๋Š” ์–ด๋ ค์šธ ๊ฒƒ ๊ฐ™์•„ infer๋ฅผ ํ™œ์šฉํ•˜๋Š” ๊ณ ์˜ค๊ธ‰ ํƒ€์ž… ์ถ”๋ก ์„ ์ ์šฉํ•˜๊ณ  ์‹ถ์–ด์กŒ๋‹ค. ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ์ข‹์„์ง€ ๋ฌผ์–ด๋ดค๋‹ค.

TypeScript์—์„œ infer ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์กฐ๊ฑด๋ถ€ ํƒ€์ž… ๋‚ด์—์„œ ํŠน์ • ํƒ€์ž…์„ ์ถ”๋ก ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. infer๋Š” ์ฃผ๋กœ ์ œ๋„ค๋ฆญ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ํƒ€์ž…์„ ์กฐ๊ฑด๋ถ€ ํƒ€์ž… ๋‚ด์—์„œ ์ถ”๋ก ํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ™œ์šฉํ•˜๋ฉด, ๋ณต์žกํ•œ ํƒ€์ž… ๊ตฌ์กฐ์—์„œ ํŠน์ • ๋ถ€๋ถ„์˜ ํƒ€์ž…์„ ๋™์ ์œผ๋กœ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด, useQuery๋กœ๋ถ€ํ„ฐ ๋ฐ˜ํ™˜๋˜๋Š” ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์ถ”๋ก ํ•˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ํƒ€์ž…์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. useQuery๋Š” ๋ฐ์ดํ„ฐ1, ๋กœ๋”ฉ ์ƒํƒœ2, ์—๋Ÿฌ3 ๋“ฑ์„ ํฌํ•จํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ useQuery์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์—์„œ data ํ•„๋“œ์˜ ํƒ€์ž…๋งŒ ์ถ”์ถœํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด infer๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด์ž.

type QueryReturnType<T> = T extends { data: infer D } ? D : never;

// ์‚ฌ์šฉ ์˜ˆ
type WeatherDataType = QueryReturnType<ReturnType<typeof useQuery>>;
                                                  
/**
์—ฌ๊ธฐ์„œ `QueryReturnType`์€ ์ œ๋„ค๋ฆญ ํƒ€์ž… `T`๋ฅผ ๋ฐ›์•„, `T`๊ฐ€ `{ data: infer D }` ํ˜•ํƒœ๋ฅผ ๊ฐ€์งˆ ๊ฒฝ์šฐ `D`๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์„ ๊ฒฝ์šฐ `never`๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. 
์ด๋ ‡๊ฒŒ ์ •์˜ํ•˜๋ฉด, `useQuery`์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์—์„œ `data` ํ•„๋“œ์˜ ํƒ€์ž…์„ `WeatherDataType`์œผ๋กœ ์ถ”๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
**/

4. ํ˜„์žฌ ํŒŒ์ผ์—์„œ ์ถ”๊ฐ€๋กœ ์ˆ˜์ •ํ•  ๋ถ€๋ถ„์ด ์žˆ์„๊นŒ?

๋”์ด์ƒ ErrorLens ํ”Œ๋Ÿฌ๊ทธ์ธ์œผ๋กœ ์ˆ˜์ •ํ•  ๋ถ€๋ถ„์„ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒฝ๊ณ  ๋ฌธ๊ตฌ๊ฐ€ ๋‚˜ํƒ€๋‚˜์ง„ ์•Š์•˜์ง€๋งŒ, ChatGPT ์„ ์ƒ๋‹˜์€ ๋ญ”๊ฐ€ ๋ณด์ผ๊นŒ ์‹ถ์–ด ์งˆ๋ฌธ์„ ๋˜์ ธ๋ดค๋‹ค.

๊ทธ๋Ÿฌ์ž ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋Šฅ ๊ตฌํ˜„์€ ์ž˜ ๋˜์–ด์žˆ์ง€๋งŒ ๊ฐœ์„ ํ• ๋งŒํ•œ ๋ถ€๋ถ„๋“ค์„ ์•Œ๋ ค์คฌ๋‹ค.

/**
* 1. ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๊ฐœ์„ : ํ˜„์žฌ WeatherAPIError ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ์ง€๋งŒ, 
์‹ค์ œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ฃผ๋Š” ๋ถ€๋ถ„์—์„œ `error.message`๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. 
๋งŒ์•ฝ API ์—๋Ÿฌ ์‘๋‹ต์ด `error.response.data.message`์— ํฌํ•จ๋˜์–ด ์žˆ๋‹ค๋ฉด, ์ด๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ด ๋” ๋ช…ํ™•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
**/

if (isError)
	return <div>๋‚ ์”จ ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค: {error.response?.data.message || error.message}</div>;
                                       
/**
* 2. ํƒ€์ž… ์•ˆ์ •์„ฑ ๊ฐ•ํ™”: `useQuery`์—์„œ ์‚ฌ์šฉํ•˜๋Š” `queryKey`์˜ ํƒ€์ž…์„ ์ข€ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 
ํ˜„์žฌ๋Š” `queryKey`๋ฅผ ๋ฐฐ์—ด๋กœ ๋ถ„ํ•ดํ• ๋‹นํ•˜๊ณ  ์žˆ์ง€๋งŒ, ์ด ๋ฐฐ์—ด์˜ ๊ตฌ์กฐ์— ๋Œ€ํ•œ ๋ช…ํ™•ํ•œ ํƒ€์ž… ์ •์˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. 
์ด๋ฅผ ๊ฐœ์„ ํ•˜์—ฌ ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
**/
                                       
const fetchWeather = async ({
     queryKey,
   }: QueryFunctionContext<[string, { lat: number; lon: number }]>) => {
     const [key, { lat, lon }] = queryKey;
     const openWeather = new OpenWeatherMap({ apiKey: apiKey });
  
const response = await openWeather.getCurrentWeatherByGeoCoordinates(
       lat,
       lon
     );
     return response;
   };                                       
                                       

๋‘ ๊ฐ€์ง€ ๊ฐœ์„ ์•ˆ ์™ธ์—๋„ ๊ฐ€๋…์„ฑ ํ–ฅ์ƒ, ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์‚ฌ์šฉ ์‹œ ํ‚ค๊ฐ’์ด ์—†์„ ๋•Œ ์˜ˆ์™ธ์ฒ˜๋ฆฌ ๋“ฑ์— ๋Œ€ํ•ด์„œ ๊ฐœ์„ ์•ˆ์„ ์ œ์•ˆํ•ด์คฌ๋‹ค. ๋ฐ˜์˜์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•œ 1๋ฒˆ ์ด์™ธ์—๋Š” ์ถ”ํ›„ ์ˆ˜์ •ํ•˜๊ณ  ๋‚œ ์ดํ›„์—๋„ ํ•„์š”ํ•  ์ง€ ์ƒ๊ฐํ•ด ์ ์šฉํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

๐Ÿ”ซ React Trouble-Shooting

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

๋™์‹œ์— ์ œ๋Œ€๋กœ Tanstack Query๋ฅผ ํ™œ์šฉํ•˜์ง€ ๋ชปํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์ƒ๊ฐ์„ ์ง€์šธ ์ˆ˜ ์—†์—ˆ๋‹ค. ์ด๋Ÿด ๊ฑฐ๋ฉด ๊ตณ์ด ์บ์‹ฑ์ด ๋˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†์ง€ ์•Š์„๊นŒ?

๊ทธ๋ž˜์„œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค.

1. ~.ts ํŒŒ์ผ์—์„œ GetWeather ํ•จ์ˆ˜๊ฐ€ weatherData๋ฅผ ๋ฐ˜ํ™˜ํ•ด. ์ด๊ฑธ temperature.tsx ํŒŒ์ผ์—์„œ weatherData๋ฅผ ๋ฐ›์•„์„œ ํ™œ์šฉํ•˜๊ณ  ์‹ถ์€๋ฐ ์–ด๋–ป๊ฒŒ ๋ฐ›์„ ์ˆ˜ ์žˆ์„๊นŒ?

์ด ์งˆ๋ฌธ์— ๋Œ€ํ•œ ์‘๋‹ต์€ ์ด๋ฏธ ๊ตฌํ˜„ํ•ด๋‘” ๋ฐฉ์‹๊ณผ ์ผ์น˜ํ•˜๋Š” ํ˜•์‹์ด์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ™œ์šฉํ•  ์ˆ˜ ์—†์—ˆ๋‹ค. ์ œ์•ˆํ•ด์ค€ ์˜ˆ์‹œ ์ฝ”๋“œ๋งŒ ํ•œ ๋ฒˆ ๋ณด๊ณ  ๋„˜์–ด๊ฐ€์ž.

// GetWeather ํ•จ์ˆ˜ ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜
const GetWeather = () => {
  const weatherData = {
    main: {
      temp: 22,
      humidity: 60
    },
    wind: {
      speed: 5
    }
  };
  return weatherData;
};

export default GetWeather;


// temperature.tsx
const Temperature: React.FC = () => {
  const data = GetWeather();

  console.log(data);

  return (
    <CityTempCon>
      ๊ธฐ์˜จ: {data?.main?.temp}ยฐC, ์Šต๋„: {data?.main?.humidity}%
    </CityTempCon>
  );
};

export default Temperature;

2. weatherData๋ฅผ ๋ฐ›๋Š” ํŒŒ์ผ์ด ์—ฌ๋Ÿฌ ๊ฐœ์ผ ๊ฒฝ์šฐ์—๋Š” ๋งค๋ฒˆ GetWeather ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด react-query์— ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์•„์„œ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ๋Š”๋ฐ ์‘์ง‘๋„ ์ธก๋ฉด์—์„œ ๊ดœ์ฐฎ์„๊นŒ?

์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์—์„œ GetWeather() ํ•จ์ˆ˜๋ฅผ ๋ฐ˜๋ณต์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์€ ๋น„ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Š” ๋„คํŠธ์›Œํฌ ์š”์ฒญ์˜ ์ค‘๋ณต, ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ ์œ ์ง€ ๋ฌธ์ œ, ๋ฆฌ์†Œ์Šค ๋‚ญ๋น„ ๋“ฑ์„ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. React์—์„œ๋Š” ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‚˜ ๋ฐ์ดํ„ฐ ํŽ˜์นญ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ค‘์•™์—์„œ ๊ด€๋ฆฌํ•˜๊ณ , ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ์—๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.
react-query๋Š” ์„œ๋ฒ„ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ํ›Œ๋ฅญํ•œ ๋„๊ตฌ๋กœ, ๋ฐ์ดํ„ฐ ์บ์‹ฑ, ๋ฐฐ๊ฒฝ ๋™๊ธฐํ™”, ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ ์œ ์ง€ ๋“ฑ์„ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ด ์ค๋‹ˆ๋‹ค. GetWeather() ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๋ฅผ react-query๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ์ข‹์€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ๋ฒˆ๋งŒ ๊ฐ€์ ธ์˜ค๊ณ , ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์—์„œ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„์™€ ๊ฐ™์€ ์ด๋ก ์ ์ธ ์‘๋‹ต์„ ๋ฐ›๊ณ  GetWeather ํ•จ์ˆ˜๋ฅผ useQuery ํ›…์„ ์‚ฌ์šฉํ•ด์„œ ์ปค์Šคํ…€ํ›…์œผ๋กœ ๋งŒ๋“œ๋Š” ๋ฐฉ์‹์„ ์ œ์•ˆํ•ด์คฌ๋‹ค.

// src/hooks/useWeather.ts
import { useQuery } from 'react-query';
import GetWeather from '@/components/weather-data';

// GetWeather ํ•จ์ˆ˜๋ฅผ react-query์˜ useQuery ํ›…์„ ์‚ฌ์šฉํ•˜์—ฌ ํ˜ธ์ถœ
const useWeather = () => {
  return useQuery('weather', GetWeather);
};

export default useWeather;


// ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์—์„œ useWeather ํ›… ์‚ฌ์šฉ
import useWeather from '@/hooks/useWeather';

const Temperature: React.FC = () => {
  const { data, isLoading, error } = useWeather();

  if (isLoading) return <div>๋กœ๋”ฉ ์ค‘...</div>;
  if (error) return <div>์˜ค๋ฅ˜ ๋ฐœ์ƒ!</div>;

  return <div>๊ธฐ์˜จ: {data?.main?.temp}ยฐC</div>;
};

export default Temperature;

/** 
์ด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ์ค‘์•™์—์„œ ๊ด€๋ฆฌํ•˜๊ณ , 
ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ์—์„œ๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ 
์‘์ง‘๋„๊ฐ€ ๋†’์•„์ง€๊ณ , ์ฝ”๋“œ์˜ ์ค‘๋ณต์„ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
**/

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

๊ฒฐ๊ณผ์ ์œผ๋กœ ํ•œ ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋Š” ์ƒ๊ฐ์„ ๋ฒ„๋ฆฌ๋‹ˆ ์ˆœ์ฐจ์  ์‘์ง‘๋„๋ฅผ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

profile
๋‚˜๋„ ์žฌ๋ฐŒ๊ณ , ๋‚จ๋“ค๋„ ์žฌ๋ฐŒ๋Š” ์„œ๋น„์Šค ๋งŒ๋“ค์–ด๋ณด๊ณ  ์‹ถ๋‹ค๐Ÿ˜Ž

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