ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 항해99 47일차 : 회원가입/로그인으로 연습한 axios 사용법
    항해99_WIL 이따금씩 TIL 2021. 4. 17. 08:10

    이번주의 개인 목표의 하나는 프론트엔드 개발자로서 axios를 이용한 클라이언트-서버 통신 코드를 짜는 것에 숙달 되는 것이었다. 클론코딩주에는 뷰를 만드는 등의 다른 부분을 많이하고 axios 코드를 짜는 것은 일부만 해서 axios 사용법을 완전히 알지 못했기 때문이다. 파이어베이스 같은 서버리스 서비스를 이용하는 것이 아니라 정말 진지하게 서버와 데이터 통신을 하려면 axios 사용법은 꼭 숙달해야 한다(물론 fetch도 있지만 대세 같은 axios를 먼저 정복하고 싶었다).

     

    내가 맡은 로그인/회원가입을 하면서 짜는 리덕스 모듈 파일(이름은 user.js)에는 서버와 통신하는 미들웨어함수가 있고 여기에 axios 코드를 넣어서 서버와 통신을 한다. 아쉽게도 지난주 클론코딩을 하면서는 서버의 문제로 회원가입/로그인을 리액트 심화주에 배운대로 파이어베이스로 구현했기 때문에, 지난주 코드를 참고할 수는 없었다. 대신 다른 데이터 통신을 하는 부분은 axios로 능력자님이 짜뒀기 때문에  그 부분을 참고해서 코드를 짰다.

     

    어떻게 짰는지 예시를 보자. 아래는 user.js 모듈 파일의 회원가입 코드다.

    // 회원가입 요청(request, 클라이언트 -> 서버) 미들웨어
    const signupAPI = (email, password, username, city, street) => {
      return function (dispatch, getState, {history}) {
        // if(!profile_url){
        //   profile_url = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRBjZn8mOw7F4rtWWKbEIIHOr_w_GAeHiXPgA&usqp=CAU"
        // }
        console.log(email, password, username, city, street);
        
        const API = "http://seungwook.shop/signups";
        // const API = "http://52.78.12.253/signups";
        console.log(API);
    
        axios.post(API,
          // 클라이언트에서 서버로 request(요청)하며 보내주는 데이터
          // 회원가입창에서 클라이언트가 입력하는 데이터
          {
            email: email,           
            password: password,  // 숫자, 영어 대문자, 소문자, 특수기호, 8-20자  1234567#Aaa
            username: username,  // id개념, 한글이 아니라 영어로 보내기, 영어+숫자, 4-12글자 
            city: city,           
            street: street,
          },
          {
            headers: {
              'Content-Type': 'application/json',
              // 'Accept': 'application/json',
            },
          })
          // 그러면 서버에서 클라이언트로 response(응답)으로 
          // {ok: true} 아니면 {ok: false}가 온다.
          // .then((response) => {
          //   console.log(response); // response.data로 해야?
          // })
          .then((result) => {
            console.log(result);
            console.log("singupDB!");
            window.alert('회원가입이 되었습니다! 로그인 해주세요.');
            history.replace('/login');
          })
          .catch((error) => {
            window.alert('회원가입이 정상적으로 되지 않았습니다.');
            console.log(error);
          })
        };
      };

     

     

    axios를 이용해서 POST 요청을 하면서 서버의 회원가입 API와 회원가입창에서 입력한 데이터를 서버로 보내줬다. 그래서 정상적으로 되면 회원가입이 되었다는 안내창이 뜨고, 로그인 페이지로 이동해준다. 간단하다.

     

    다음은 로그인 코드다.

    // 로그인 요청(request, 클라이언트 -> 서버) 미들웨어
    const loginAPI = (username, password) => {
      return function (dispatch, getState, {history}) {
    
        console.log(username, password);
        // const API = 'http://52.78.12.253/login';
        const API = "http://seungwook.shop/login";
        axios.post(API, {
          // 클라이언트에서 서버로 request(요청)하며 보내주는 데이터
          // 로그인창에서 클라이언트가 입력하는 데이터
          "username": username,
          "password": password,
        },
        {
          headers : {
            "Content-Type": "application/json;charset=UTF-8",
            // 'Content-Type' : 'application/json', //클라이언트가 서버한테 요청하는(원하는) 타입
            'Accept' : 'application/json', //현재 서버한테 보내는 데이터 타입
            'Access-Control-Allow-Origin' : '*',
          },
        })
          // 그러면 서버에서 클라이언트로 response(응답)으로 
          // header에선 token(JWT)이 오고,
          // body에선 id, name이 온다.
        .then((response) => {
          console.log(response)
          console.log(response.data); // body 데이터
          console.log(response.headers.authorization);  // undefined getItem
          console.log('로그인 되었습니다!');
          localStorage.setItem('Authorization', response.headers.authorization);
          localStorage.setItem('uid', response.data.id);
          localStorage.setItem('username', response.data.name);
          localStorage.setItem('email', response.data.email);
            // setUser를 발동시켜서
            // 리덕스의 is_login 값을 true로 변경한다.
            let user={
              uid: response.data.id,   
              username: response.data.name,
              email: response.data.email,
            }
            dispatch(setUser(user))
            window.alert('로그인 되었습니다!');
            history.replace('/');
          }).catch((error) => {
            console.log(error);
            window.alert('로그인 실패!')
          });  
        };
      }

    다음은 로그인 코드다. 회원가입과 거의 비슷하지만, 이 경우에는 서버로부터 토큰(우리는 세션/쿠키 방식의 로그인이 아니라 토큰 방식으로 로그인을 했다.)을 받고 이메일과 로그인한 user의 id와 email을 받았다. 왜 id와 email도 함께 받냐면, id는 상품게시물이 로그인한 사용자가 작성했는지 판별하기위해서, email은 상품 상세 페이지에서 채팅을 할 때 채팅참여자의 '이름'으로 쓰기 위해서이다.

     

    사실 이렇게 하고 나서 보니 쉬워 보이지만, 과정은 쉽지 않았다. fetch를 쓸지 axios를 쓸지 고민하다가 axios를 잘 몰라서 fetch를 썼다가 코드가 꼬여서 잘 되지 않아서 axios로 돌아왔다. 능력자님들의 git을 참고해서 axios 코드를 썼지만 잘 되지 않거나 뭘 넣고 뭘 빼야할지 감이 잡히지 않았다. 그래도 해결하려고 친분이 많이 없는 분이지만 능력자분에게 요청을 구해서 실마리를 찾기도 했다. 그렇게 어찌저찌해서 짠 코드가 될거라고 믿고 백엔드에서 로그인/회원가입하는 분과 맞춰봤지만 역시 잘 되지 않아서 여러번 삽질을 거듭했다. 그러면서 수정을 거듭하다가, 결국에는 깔끔하게 해결! axios는 아니지만 로그아웃에서 로그인할 때 localstorage에 저장해 둔 토큰,  id, username, email 이 깔끔하게 삭제되었을땐 너무 기뻐서 춤이라도 추고 싶을 정도로 환의에 가득 찼다. 이런게 성취감인갑다 싶었다ㅋㅋㅋㅋㅋ 

     

    다만 하나 짚어 볼 것은 토큰이랑 다른 데이터들을 localstorage에 저장하는 것이 맞나 하는 것이다. 보안 상 취약점이 있다는데, 다른 분들의 코드를 참고하기도 하고 다음번 실전프로젝트에서 만날 분들과 이야기해서 어디에 저장해둘지 알아볼 생각이다.  

    댓글

금손이 프론트엔드 개발자가 되고자 오늘도 존버중