๐Ÿ“– TIL - API ๊ด€๋ จ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ… & ํ•™์Šต ์ •๋ฆฌ

์Š˜ยท2025๋…„ 2์›” 20์ผ

๐Ÿ“– TIL

๋ชฉ๋ก ๋ณด๊ธฐ
61/89

1๏ธโƒฃ URL ์ปจ๋ฒค์…˜ & API ๊ธฐ๋ณธ ์„ค์ •

๋ผ์šฐํ„ฐ์— testPage๋‚˜ testResultPage๋ฅผ ์–ด๋–ป๊ฒŒ ์ค˜์•ผํ• ๊นŒ ์ฐพ์•„๋ณด๊ฒŒ ๋˜์—ˆ๋‹ค.
์œ„์ฒ˜๋Ÿผ ์นด๋ฉœ์ผ€์ด์Šค๋กœ ์ž‘์„ฑํ•ด์•ผํ•˜๋Š”๊ฑด๊ฐ€? ์•„๋‹ˆ๋ฉด ์ผ€๋ฐฅ์ผ€์ด์Šค? ์•„๋‹ˆ๋ฉด ์†Œ๋ฌธ์ž๋กœ ์ญ‰?

URL ๋„ค์ด๋ฐ ๊ทœ์น™

  • ์†Œ๋ฌธ์ž + ํ•˜์ดํ”ˆ(-) ์‚ฌ์šฉ ๊ถŒ์žฅ
  • camelCase๋‚˜ PascalCase๋Š” ํ”ผํ•˜๊ธฐ
// โŒ ํ”ผํ•ด์•ผ ํ•  URL
/userProfile
/UserDetails

// โœ… ๊ถŒ์žฅํ•˜๋Š” URL
/user-profile
/user-details

์ผ€๋ฐฅ์ผ€์ด์Šค๋กœ ๊ฒฐ์ •!

axios ๊ธฐ๋ณธ ์„ค์ • ์ตœ์ ํ™”

axios๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Auth์™€ json server๊ด€๋ จ baseUrl์„ ์„ค์ •ํ•˜์˜€๋‹ค.

// ๊ธฐ๋ณธ URL ์„ค์ •
const api = axios.create({
  baseURL: "https://api.example.com"
});

// ๊ฐ™์€ ๊ฒฝ๋กœ์ผ ๋•Œ๋Š” ๋นˆ ๋ฌธ์ž์—ด๋กœ ์ฒ˜๋ฆฌ
export const getTestResults = async () => {
  const response = await api.get("");  // baseURL๋งŒ ์‚ฌ์šฉ
  return response.data;
};

2๏ธโƒฃ ๋กœ๊ทธ์ธ ๋กœ์ง ๋ฆฌํŒฉํ† ๋ง

๋กœ๊ทธ์ธ ๋กœ์ง์„ ์ž‘์„ฑํ•˜๋‹ค๊ฐ€ ๋ฌธ์ œ๋ฅผ ๋ฐœ๊ฒฌํ–ˆ๋‹ค. ๊ธฐ๋Šฅ์ ์ธ ๋ฌธ์ œ๋ผ๊ธฐ ๋ณด๋‹จ ๋ณด์•ˆ์ ์œผ๋กœ password๋ฅผ ๊ฐ™์ด ๋˜์ ธ์ฃผ๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒ..

AS-IS: ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ์ฝ”๋“œ

const handleLogin = async (formData) => {
  try {
    if(formData){
      const data = await login(formData)
      setToken(data.accessToken);
      if(data.success){
        navigate('/')
        setUser(formData)  // ๐Ÿ˜ฑ ๋น„๋ฐ€๋ฒˆํ˜ธ ํฌํ•จ๋œ formData ์ €์žฅ
      }
    }
  } catch (error) {
    console.error(error);
  }
};

TO-BE: ๊ฐœ์„ ๋œ ์ฝ”๋“œ

const handleLogin = async (formData) => {
  try {
    if (formData) {
      const data = await login(formData);
      
      if (data.success) {
        setToken(data.accessToken);
        setUser({  // ํ•„์š”ํ•œ ์ •๋ณด๋งŒ ์„ ํƒ์ ์œผ๋กœ ์ €์žฅ
          userId: data.userId,
          nickname: data.nickname,
          avatar: data.avatar
        });
        navigate('/');
      }
    }
  } catch (error) {
    console.error(error);
    alert(`๋กœ๊ทธ์ธ ์‹คํŒจ: ${error?.response?.data?.message || '์•Œ ์ˆ˜ ์—†๋Š” ์˜ค๋ฅ˜'}`);
  }
};

3๏ธโƒฃ Zustand ์ƒํƒœ๊ด€๋ฆฌ ๋ฌธ์ œ ํ•ด๊ฒฐ

๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€๋ฅผ ์„ค์ •ํ•˜๋‹ค๊ฐ€.. token์ด set์œผ๋กœ ์„ค์ •๋˜์ง€ ๋ชปํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€๋‹ค.
์ฝ”๋“œ๋ฅผ ๋œฏ์–ด๋ณด๋‹ˆ ๋‚ด๊ฐ€ token์„ ํ•จ์ˆ˜๋กœ์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ์—ˆ๋‹ค.. localStorage๋ฅผ getItem์œผ๋กœ ๋ฐ›์œผ๋ฉด ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ ์ƒ๊ฐํ–ˆ๋Š”๋ฐ.. set์„ ์‚ฌ์šฉํ•˜๋Š”๊ฒƒ์„ ๊ณ ๋ คํ•œ๋‹ค๋ฉด ํ•จ์ˆ˜๋กœ์„œ ์‚ฌ์šฉํ•˜๋Š”๊ฒƒ์€ ์ง€์–‘ํ•ด์•ผํ–ˆ๋‹ค.

๋ฌธ์ œ ์ƒํ™ฉ

// โŒ ์ž˜๋ชป๋œ ๋ฐฉ์‹
token: () => {
  try {
    const item = window.localStorage.getItem("token")
    return item ? JSON.parse(item) : null
  } catch (error) {
    console.error(error);
    return null;
  }
},

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

// โœ… ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ์‹
const useAuthStore = create((set) => ({
  token: null,
  
  setToken: (token) => {
    try {
      window.localStorage.setItem("token", JSON.stringify(token));
      set({ token });
    } catch (error) {
      console.error(error);
    }
  }
}));

// ์ปดํฌ๋„ŒํŠธ์—์„œ ์ดˆ๊ธฐํ™”
useEffect(() => {
  const storedToken = window.localStorage.getItem("token");
  if(storedToken) {
    setToken(JSON.parse(storedToken));
  }
}, []);

๐Ÿ’ก ํ•ต์‹ฌ ๋ฐฐ์šด ์ 

  1. URL ๋„ค์ด๋ฐ์€ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ์œ ์ง€ํ•˜๊ธฐ
  2. ๋ฏผ๊ฐํ•œ ์ •๋ณด(๋น„๋ฐ€๋ฒˆํ˜ธ ๋“ฑ)๋Š” ์ƒํƒœ์— ์ €์žฅํ•˜์ง€ ์•Š๊ธฐ
  3. Zustand์—์„œ ์ƒํƒœ๋Š” ํ•จ์ˆ˜๊ฐ€ ์•„๋‹Œ ๊ฐ’์œผ๋กœ ์ €์žฅํ•˜๊ธฐ
  4. localStorage ๋™๊ธฐํ™”๋Š” useEffect ํ™œ์šฉํ•˜๊ธฐ
profile
์ฃผ๋‹ˆ์–ด ํ”„๋ก ํŠธ์—”๋“œ ์„ฑ์žฅ๊ธฐ ๊ธฐ๋ก๊ธฐ๋ก

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