Post

원티드 프리온보딩 - 로그인 기능 구현하기 2 (실습)

원티드 프리온보딩 - 로그인 기능 구현하기 2강 실습

실습 코드

로그인 기능 연결하기 1

실습 코드

1. 1일차에서 구성한 화면에 제공된 로그인 API 붙이기

2. 로그인 API의 응답을 바로 사용해 유저 정보를 받아와 화면에 보여주기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// login api

import { BASE_URL } from "./const.js";
import axios from "axios";

/*********
 *  실습 2-1
 * */

export const loginWithToken = async (args) => {
  const loginRes = await axios.post(`${BASE_URL}/auth/login`, args);

  if (loginRes)
    return { result: "success", access_token: loginRes.data.access_token };

  return {
    result: "fail",
    access_token: null
  };
};

export const getCurrentUserInfoWithToken = async (token) => {
  const userInfoRes = await axios.get(`${BASE_URL}/profile`, {
    headers: { Authorization: `Bearer ${token}` }
  });
  if (userInfoRes) return userInfoRes.data;

  return null;
};

로그인 연결 및 화면에 출력하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import React, { useState } from "react";
import {
  getCurrentUserInfoWithToken,
  loginWithToken
} from "../../api/login.js";

const JWTLogin = () => {
  const [userInfo, setUserInfo] = useState(null);

  const loginSubmitHandler = async (event) => {
    event.preventDefault();

    const formData = new FormData(event.currentTarget);

    const loginPayload = {
      username: formData.get("username"),
      password: formData.get("password")
    };

    const loginResponse = await loginWithToken(loginPayload);
    if (loginResponse.result === "fail") return;

    // token 넘기기
    const userInfo = await getCurrentUserInfoWithToken(
      loginResponse.access_token
    );
    if (!userInfo) return;

    setUserInfo(userInfo);
  };

  return (
    <div>
      <h1>Login with JWT - in memory</h1>
      <form onSubmit={loginSubmitHandler}>
        <label>
          Username:
          <input type="text" name="username" />
        </label>
        <label>
          Password:
          <input type="password" name="password" />
        </label>
        <button type="submit" value="Submit">
          submit
        </button>
      </form>
      <div>
        <h2>User info</h2>
        {JSON.stringify(userInfo)}
      </div>
    </div>
  );
};

export default JWTLogin;

로그인 기능 연결하기 2

실습 코드

1. 실습1에서 만든 로그인 로직에서 토큰을 반환하지 않고 로컬스토리지에 저장

2. 로컬스토리지에 저장된 토큰을 가져와 유저 정보 조회

3. 로그인 페이지가 아닌 다른 페이지에서 로컬 스토리지의 값을 이용해 로그인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// login api

/*********
 *  실습 2-2
 * */

export const login = async (args) => {
  const loginRes = await axios.post(`${BASE_URL}/auth/login`, args);

  // token을 로컬스토리지에 저장
  if (loginRes) {
    saveAccessTokenToLocalStorage(loginRes.data.access_token);
    return "success";
  }

  return "fail";
};

export const getCurrentUserInfo = async () => {
  // 로컬스토리지에 저장된 token 가져와서 로그인하기
  const token = getAccessTokenFromLocalStorage();

  const userInfoResponse = await axios.get(`${BASE_URL}/profile`, {
    headers: {
      Authorization: `Bearer ${token}`
    }
  });

  if (userInfoResponse) return userInfoResponse.data;

  return null;
};

다른 페이지에서 로그인하기

isDataFetched로 첫 렌더될 때만 getUserInfo 함수 실행되도록 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import React, { useCallback, useEffect, useRef, useState } from "react";
import { getCurrentUserInfo, login } from "../../api/login.js";

const AutoLogin = () => {
  const [userInfo, setUserInfo] = useState(null);
  const isDataFetched = useRef(false);

  const getUserInfo = useCallback(async () => {
    const userInfoResult = await getCurrentUserInfo();

    if (!userInfoResult) return;

    setUserInfo(userInfoResult);

    isDataFetched.current = true;
  }, []);

  useEffect(() => {
    if (isDataFetched.current) return;
    getUserInfo();
  }, []);

  return (
    <div>
      <h1>Another page</h1>
      <div>
        <h2>User info</h2>
        {JSON.stringify(userInfo)}
      </div>
    </div>
  );
};

export default AutoLogin;
This post is licensed under CC BY 4.0 by the author.