Today Sangmin Learned
article thumbnail
728x90

종합설계를 하면서 배우는 게 참 많다. 의무성이 생기니까 어떻게든 내가 맡은 부분을 책임감있게 끝내야 한다는 마음가짐을 갖고 하게 된다. 근데 또 하나하나 나중에 서비스를 만들 때도 꼭 필요한 것들만 한지라, 다행히 좋은 부분을 잘 맡았다는 생각이 들었다.

 

이 부분은, 서버에 토큰을 넘겨주는 방식은 아니고, 클라이언트 단에서 로그인 및 로그아웃을 해결하기 위한 방법이다. 서버와 합쳤을 때 토큰을 넘겨주는 부분은 따로 포스팅을 할 예정이다.

 

이번에는 카카오 로그인과, 로그인 여부에 따라 라우팅할 수 있는 페이지와 그렇지 않은 페이지를 구분하는 것을 구현했다.

Kakao Developers에 들어가서 로그인을 한 뒤, 내 애플리케이션에 들어가서 애플리케이션 추가하기를 누른다.

그럼 이러한 페이지가 보일 것인데, 각자 임의로 작성하자. 이렇게 한 후 저장을 마치면 목록이 추가가 될 것이고, 누르면 바로 아래 사진과 같은 앱 키가 나올 것이다.

이 키들을 사용하기 전에, 우선 플랫폼 등록부터 해야한다. 좌측 앱 설정 > 플랫폼을 들어가면, Android, iOS, Web의 플랫폼을 등록할 수 있다. 나는 React 환경에서 개발하므로 localhost:3000으로 플랫폼 등록을 했다.

react-app 프로젝트를 만들고, public 내 index.html의 헤더에

    <!-- OAuth: Kakao -->
    <script src="https://developers.kakao.com/sdk/js/kakao.min.js"></script>
    <script>
      Kakao.init('YOUR_JAVASCRIPT_KEY');
    </script>

자바스크립트 키를 포함한 해당 코드를 넣어준다. 이제 준비는 완료되었고, KakaoLogin이라는 컴포넌트를 만든다. 로그인과 로그아웃이 위치해야 할 곳이 다르기 때문에, 로그인과 로그아웃에 대해 각각 컴포넌트를 만들어줬다.

 

import React, { Component } from 'react';
import Styled from 'styled-components';
import { withRouter } from 'react-router-dom';
import KakaoLoginImg from '../assets/kakao.png';

const ButtonWrap = Styled.div`
  background-image: url(${KakaoLoginImg});
  background-repeat: no-repeat;
  margin: 38px auto;
  color: transparent;
  width: 183px;
  height: 45px;
`;

const { Kakao } = window;

class KakaoLogin extends Component {
  state = {
    isLogin: false,
  };
  loginWithKakao = () => {
    try {
      return new Promise((resolve, reject) => {
        if (!Kakao) {
          reject('인스턴스 없음');
        }
        Kakao.Auth.login({
          success: res => {
            localStorage.setItem('token', res.token);
            this.setState({
              isLogin: true,
            });
            this.props.history.push('/signup');
          },
          fail: err => {
            console.error(err);
          },
        });
      });
    } catch (err) {
      console.error(err);
    }
  };
  componentDidMount() {
    if (Kakao.Auth.getAccessToken()) {
      this.setState({
        isLogin: true,
      });
    }
  }
  render() {
    const { isLogin } = this.state;
    const loginView = <ButtonWrap onClick={this.loginWithKakao}></ButtonWrap>;

    return <div className="App">{loginView}</div>;
  }
}

export default withRouter(KakaoLogin);

우선 카카오 인스턴스의 존재여부에 따라 resolve와 reject를 나눴고, Kakao.Auth.login을 통해 로그인을 시도하며, 성공할 경우 localStorage에 카카오 서버로부터 받은 토큰 값(value)을 'token'이라는 키(key) 값에 저장한다. 그리고, 기본적으로 false 처리가 되어있는 isLogin의 상태를 true로 업데이트해준다.

(근데 이게 가능하려면, 아래 componentDidMount 하에서 Kakao.Auth.getAccessToken이 가능해야한다. 이는 카카오 로그인에서 제공하는 MDN에 따른 명령어로, 토큰 접근 여부를 판단하는 것으로 보인다)

이후에 /signup (회원가입 페이지)로 history.push를 통해 이동시켜준다. 

 

위 코드를 이해했다면 로그아웃 코드를 이해하는 건 어렵지 않다.

import React, { Component } from 'react';
import Styled from 'styled-components';
import { withRouter } from 'react-router-dom';

const ButtonWrap = Styled.div`
  border: 2px solid black;
  position: relative;
  margin: 38px auto;
  width: 183px;
  height: 45px;
  h2 {
      color: black;
      font-size: 20px;
      text-align: center;
  }
`;

const { Kakao } = window;

class KakaoLogout extends Component {
  state = {
    isLogin: true,
  };
  logoutWithKakao = () => {
    if (Kakao.Auth.getAccessToken()) {
      console.log(
        '카카오 인증 액세스 토큰이 존재합니다.',
        Kakao.Auth.getAccessToken(),
      );
      Kakao.Auth.logout(() => {
        console.log('로그아웃 되었습니다.', Kakao.Auth.getAccessToken());
        this.setState({
          isLogin: false,
        });
        localStorage.clear();
        this.props.history.push('/');
      });
    }
  };
  componentDidMount() {
    if (Kakao.Auth.getAccessToken()) {
      this.setState({
        isLogin: false,
      });
    }
  }

  render() {
    const { isLogin } = this.state;
    const logoutView = (
      <ButtonWrap onClick={this.logoutWithKakao}>
        <h2>로그아웃</h2>
      </ButtonWrap>
    );

    return <div className="App">{logoutView}</div>;
  }
}

export default withRouter(KakaoLogout);

로그아웃을 하려면 (물론 로그인도 그렇지만) 우선 토큰에 접근이 가능한 상태여야 한다. 로그아웃은 우선 로그인이 되어있다는 전제가 깔려 있어야 하므로, isLogin state가 기본적으로 true인 상태에서 진행된다.

로그아웃은 isLogin 상태를 false로 바꿔 주고, localStorage를 비워주는 방식으로 진행된다. localStorage에 setItem으로 토큰이 들어간 상황이라면, 따로 비워주지 않으면 항상 들어가있는 상태가 된다. 이것을 몰랐어서 라우터 제한 접근이 제대로 되고 있지 않은 상태가 지속되었다. 동아리원의 도움을 받아서 해결했다. ㅋㅋ

이제 다 끝났다. 내가 하고있는 프로젝트에서 메인페이지는 로그인을 한 상태에서만 들어갈 수 있으므로 '/'(랜딩 페이지)로 푸시해줬다.

이외에 styled-components는 각자 임의로 하면 된다.

 

나는 카카오 로그인의 경우 카카오 로그인 리소스 에서 가져다 썼다. 근데 정말 아쉬운 점은, svg파일이 제공되지 않고 이미지파일만 제공된다는 점이다. 이미지는 필연적으로 깨지게 마련인데, 이점이 너무 아쉬웠다.

어쨌든.. 카카오 로그인과 로그아웃은 이러한 방식으로 구현할 수 있겠다.

로그아웃을 했을 때 이렇게 잘 출력되고 있다.

profile

Today Sangmin Learned

@steadily-worked

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!