카카오 소셜 로그인 구현

JH.P·2022년 6월 22일
0

공식 문서를 꼼꼼히 읽지 못하여 실수..

  • 카카오 로그인을 구현하는 방법 중 REST API를 이용한 방법을 읽고 적용을 시도하였다.
  • 프론트엔드에서 로그인 한 후, 카카오 로그인 전용 라우팅으로 이동 시켜 인가코드를 받았다.
  • 이 인가코드를 이용하여 카카오 서버로부터 토큰을 발급받았다.
  • 이 토큰을 이용하여 현재 사용자의 카카오에 등록된 정보를 받고자 하였다.
  • 프론트엔드에서 토큰을 담아 카카오 서버로 get 요청을 보냈지만, CORS 에러가 발생하였다.
  • 구글링해보니, 프론트엔드에서는 토큰을 이용하여 사용자 정보를 받아올 수 없고, 백엔드에서만 가능하다고 한다.
  • 현재 진행중인 프로젝트의 백엔드는 REST API가 아닌 graphql로 진행중이다.
  • 앞으론 공식문서를 "꼼꼼히" 읽고 진행하자. 급하게 진행하지 말자..

자바스크립트 sdk를 이용한 로그인 구현

  • 카카오 개발자 플랫폼에서 내 앱을 생성하고, JS 키를 부여 받았다.
    • 이미 카카오 지도 api를 이용할 때 발급받았었다.
  • 발급받은 JS키를 이용하여 컴포넌트 내에서 생성한 카카오 앱이 잘 초기화되는지 확인해본다. 콘솔 창에 true가 반환되면 성공이다.
window.Kakao.init(process.env.REACT_APP_KAKAO);
console.log(Kakao.isInitialized());
  • 프론트엔드 내 로그인 스크린 컴포넌트에서, 카카오 로그인 버튼 클릭 시 아래와 같이 정보를 입력한 후, 사용자 정보를 받아오는 함수를 작성하였다.
  const handleKakaoLogin = () => {
    window.Kakao.Auth.login({
      success: function (response) {
        window.Kakao.API.request({
          url: '/v2/user/me',
          success: function (response) {
            kakaoLogin({
              variables: {
                username: response.properties.nickname,
                email: response.kakao_account.email,
                avatar: response.properties.profile_image,
              },
              onCompleted: (data) => {
                const {
                  kakaoLogin: { ok, token, error },
                } = data;
                if (token) {
                  logUserIn(token);
                }
              },
            });
          },
          fail: function (error) {},
        });
      },
      fail: function (error) {
        console.log(error);
      },
    });
  };
  • 위 코드의 실행 내용은, 사용자가 카카오 로그인을 요청하면, 동의 화면과 함께 이메일과 비밀번호 입력창이 출력된다. 해당 과정을 거치게 되면 사용자 정보를 받아오게 되고, 즉시 백엔드로 전송된다.(kakaoLogin Mutation을 통해 전송)
  • 백엔드에선 해당 내용을 확인 후 서버 자체 토큰을 발행한다.
  • 발행한 토큰이 성공적으로 돌아오면, 해당 카카오 아이디로 웹 이용이 가능해진다.
  • 아래는 백엔드의 카카오 로그인 resolver 내용이다.
export default {
  Mutation: {
    kakaoLogin: async (_, { username, avatar, email }) => {
      // DB에 해당 유저의 정보가 존재하는지 찾는다.
      const findUser = await client.user.findFirst({
        where: {
          AND: [
            {
              username: `${username}(kakao)`,
            },
            {
              email: `${email}(kakao)`,
            },
          ],
        },
      });
      // 만약 존재하지 않으면 DB에 이름, 닉네임, 아바타, 이메일을 저장 한 후에 토큰 발행해준다.
      if (!findUser) {
        const uglyPassword = await bcrypt.hash(username, 10);
        const createUser = await client.user.create({
          data: {
            name: username,
            username: `${username}(kakao)`,
            email: `${email}(kakao)`,
            avatar,
            password: uglyPassword,
            isKaKao: true,
          },
        });
        const token = await jwt.sign(
          { id: createUser.id },
          process.env.SECRET_KEY
        );
        return {
          ok: true,
          token,
          name: user.username,
        };
      }
      const token = await jwt.sign({ id: findUser.id }, process.env.SECRET_KEY);
      return {
        ok: true,
        token,
      };
    },
  },
};
  • 카카오의 닉네임과 기존에 존재하던 웹 자체에서의 닉네임이 서로 겹칠 수 있기 때문에 닉네임 뒤에 (kakao)를 붙여주어 기존 웹에서의 닉네임과 구분해주었다.
profile
꾸준한 기록

0개의 댓글