본문 바로가기

프로그래밍/Node & Express

Node.js - 카카오 로그인 구현하기

 

 

 

1. 먼저 해야할 것

https://developers.kakao.com/

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

이 곳에 들어가서, 애플리케이션 등록을 먼저 해줘야한다.

 

흰 원이 보이지? 내 애플리케이션 클릭!

내 애플리케이션에 들어가면 아래와 같은 화면이 보일것이다.

 

ThePaisleyShop 은 내가 미리 만들어 놓은 애플리케이션이다.

여기서, 애플리케이션 추가하기를 누르면 앱 아이콘 / 앱 이름 / 사업자 명 세 개의 입력란이 나오는데,

앱이름은 현재 만드는 앱 이름, 사업자명은 본인 이름을 적어주면 되겠다. 만들고나서 클릭하게되면

 

이런 창이 뜰텐데, 여기서 REST API 키를 따로 저장해둔다!

 

그 다음 왼쪽을 보면 카카오 로그인이라는 탭이 보일텐데, 클릭하고 활성화를 시켜준다.

Redirect URI 가 보일것이다. 아마 처음 만드는 사람은 비어져있을텐데, 설정해준다.

이 게시물과 똑같이 설정할 필요는 없다. 그리고 이것 또한 중요하니, REST API키와 마찬가지로 메모장 같은데에 우선 복붙 해놓으면 된다.

 

그 다음 카카오 로그인 - 동의 항목에 들어가면 동의항목들이 쭉~ 나열되어있는데, 닉네임, 프로필 사진을 체크한다.

 

그리고 왼쪽에 보면 카카오 로그인 - 보안 탭에 들어가면 Client Secret 코드를 발급받을 수 있는데, 이것을 발급받고 메모장에 복붙해놓는다.

 

*아래 활성화 상태에서 활성화도 시켜주자*

 

REST_API 키 / CLIENT_SECRET 키 / REDIRECT_URI 이 세가지로 이제 카카오톡 로그인을 구현해볼것인데,

 

카카오톡 개발자 문서에 나와있듯이 첫번째 과정은 인가 코드 받기이다.

 

 

https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

여기 들어가서 문서를 내리다보면 

 

Request

URL

GET /oauth/authorize?client_id={REST_API_KEY}&redirect_uri={REDIRECT_URI}&response_type=code HTTP/1.1
Host: kauth.kakao.com

요로코롬 되있고, 아래에는 자세한 설명이 되어있다.

 

이제 이걸 이용해서 요청을 보내야한다.

 

a(href="https://kauth.kakao.com/oauth/authorize?client_id={REST_API_KEY}&redirect_uri={REDIRECT_URI}&response_type=code") 카카오 로그인

 

(나는 pug 템플릿엔진을 사용중이다.)

 

처음엔, 현재 코딩하고있는 login form이 있는곳에 a태그를 이용하여 위처럼 링크를 만들어서 접근해야하는데,

{REST_API_KEY} 와 {REDIRECT_URI} 가 REST_API_KEY 에는 아까 복사했던 REST API 키 값을 넣어주고, REDIRECT_URI 도 마찬가지로 아까 복사했던걸 넣어주면된다. {} < 이거 지워줘야한다.

 

근데 저렇게 하면, 링크가 너무 길고 활용하기 불편하다. 그래서 정리가 필요하다. 

router와 controller를 이용해서 정리를 할건데, 아래와 같이 각자 님들이 만든 라우터를 참고해서 링크를 만든다.

a(href="/users/kakao/start") 카카오 로그인

 

// 라우터.js
import { startKakaoLogin } from "../controllers/userController";

userRouter.route("/kakao/start").get(startKakaoLogin);
userRouter.route("/kakao/finish").get(finishKakaoLogin);


// 전체 코드 아닙니다.

이렇게 라우터를 만들고, get에 반응하는 컨트롤러를 만들어서 정리를 해준다.

 

// 컨트롤러.js

export const startKakaoLogin = (req, res) => {
  const baseUrl = "https://kauth.kakao.com/oauth/authorize";
  const config = {
    client_id: "e0ec674a876978f7083ca57afdab7cb8",
    redirect_uri: "http://localhost:4002/users/kakao/finish",
    response_type: "code",
  };
  const params = new URLSearchParams(config).toString();

  const finalUrl = `${baseUrl}?${params}`;
  console.log(finalUrl);
  return res.redirect(finalUrl);
};

이렇게 정리를 해주었다.

* URLSearchParams 메서드는 객체에 나눠져있는 문자열을 URL처럼 뭉쳐준다. 오브젝트로 반환되기때문에 toString() 메서드를 이용해서 문자열로 바꿔준것 *

 

* 주의 사항 : config 객체에서 키값의 이름에 주의하자. 키 값 이름은 꼭 client_id, redirect_uri, response_type 이렇게 카카오 API에 있는 그대로 써주어야한다. 난 여기서 실수해서 꽤 많은 시간을 날려먹었다.. *

 

이렇게 정리하고? 아까 만들어준 링크를 누르면?

 

오! 떴다!

 

 

짠!

 

이제 여기서 전체동의 -> 동의하고 계속하기를 누르면

 

당연히 안되지~

/users/kakao/finish 라는 URL로 GET요청을 보내고있는것을 관찰할 수 있다.

이 URL은? 낯이 익다. 아까 우리가 카카오 개발자 홈페이지에서 설정한 그 URl이다.

여기서 URL 뒤쪽에보면 code가 붙어있는것도 확인할 수 있다.

이제 인가 코드 받기 과정은 끝났고,

 

다음으로 토큰 받기 과정이다.

토큰까지 받는 과정을 제대로 완수해야 카카오 로그인을 정상적으로 마칠 수 있다.

 

*nodejs에서는 fetch()함수를 기본적으로 제공하고 있지 않기 때문에, 모듈을 설치해줘야한다.*

*npm i node-fecth 로 설치*

export const finishKakaoLogin = async (req, res) => {
  const baseUrl = "https://kauth.kakao.com/oauth/token";
  const config = {
    client_id: process.env.KAKAO_CLIENT,
    client_secret: process.env.KAKAO_SECRET,
    grant_type: "authorization_code",
    redirect_uri: "http://localhost:4002/users/kakao/finish",
    code: req.query.code,
  };
  const params = new URLSearchParams(config).toString();
  const finalUrl = `${baseUrl}?${params}`;
  const kakaoTokenRequest = await fetch(finalUrl, {
    method: "POST",
    headers: {
      "Content-type": "application/json", // 이 부분을 명시하지않으면 text로 응답을 받게됨
    },
  });
  const json = await kakaoTokenRequest.json();
  console.log(json);
  res.send(JSON.stringify(json)); // 프론트엔드에서 확인하려고
};

위와 마찬가지로 비슷한 로직의 코드이다.

startKakaoLogin 함수에서 finalUrl로 요청을하면

/users/kakao/finish 로 시작하는 URL로 돌아왔었다.

userRouter.route("/kakao/finish").get(finishKakaoLogin);

아까 만들어준 라우터가 이를 감지하고 finishKakaoLogin 함수를 실행 시킨것..

이제 fetch를 이용해서 공식문서에 나온대로 POST 요청을 보내고(카카오 로그인을 누르고 쭉 진행), 성공적으로 잘 되면

콘솔 + 웹상에 아래처럼 출력될것이다.

{
  access_token: 'jvJP24FtckJgjtF0XJZ0PI98ZcBi32qlqq9dogo9cxcAAAF7MaSk0Q',
  token_type: 'bearer',
  refresh_token: 'Szpw4tSQgfAhU8Z-FmpC7dGv_2sZGAPCuAExYgo9cxcAAAF7MaSk0A',
  expires_in: 21599,
  scope: 'profile_image profile_nickname',
  refresh_token_expires_in: 5183999
}

이제 토큰을 성공적으로 받았다.

 

다음 단계는 엑세스 토큰을 이용하여 사용자 정보를 가져오는 단계이다.

 

export const finishKakaoLogin = async (req, res) => {
  const baseUrl = "https://kauth.kakao.com/oauth/token";
  const config = {
    client_id: process.env.KAKAO_CLIENT,
    client_secret: process.env.KAKAO_SECRET,
    grant_type: "authorization_code",
    redirect_uri: "http://localhost:4002/users/kakao/finish",
    code: req.query.code,
  };
  const params = new URLSearchParams(config).toString();
  const finalUrl = `${baseUrl}?${params}`;
  const kakaoTokenRequest = await (
    await fetch(finalUrl, {
      method: "POST",
      headers: {
        "Content-type": "application/json", // 이 부분을 명시하지않으면 text로 응답을 받게됨
      },
    })
  ).json();
  if ("access_token" in kakaoTokenRequest) {
    // 엑세스 토큰이 있는 경우 API에 접근
    const { access_token } = kakaoTokenRequest;
    const userRequest = await (
      await fetch("https://kapi.kakao.com/v2/user/me", {
        headers: {
          Authorization: `Bearer ${access_token}`,
          "Content-type": "application/json",
        },
      })
    ).json();
    console.log(userRequest);
  } else {
    // 엑세스 토큰이 없으면 로그인페이지로 리다이렉트
    return res.redirect("/login");
  }
};

이렇게 엑세스 토큰을 가지고 카카오가 제공하는 url에 fecth로 요청하고, 리턴받은 값을 출력하면 다음과 같이 출력된다!

{
  id: 1845121196,
  connected_at: '2021-08-10T19:48:15Z',
  properties: {
    nickname: '종재',
    profile_image: 'http://k.kakaocdn.net/dn/dwvDUL/btq5apOKqyF/AkhYvQZukyenem9wAOaT6K/img_640x640.jpg',
    thumbnail_image: 'http://k.kakaocdn.net/dn/dwvDUL/btq5apOKqyF/AkhYvQZukyenem9wAOaT6K/img_110x110.jpg'
  },
  kakao_account: {
    profile_nickname_needs_agreement: false,
    profile_image_needs_agreement: false,
    profile: {
      nickname: '종재',
      thumbnail_image_url: 'http://k.kakaocdn.net/dn/dwvDUL/btq5apOKqyF/AkhYvQZukyenem9wAOaT6K/img_110x110.jpg',
      profile_image_url: 'http://k.kakaocdn.net/dn/dwvDUL/btq5apOKqyF/AkhYvQZukyenem9wAOaT6K/img_640x640.jpg',
      is_default_image: false
    }
  }
}

성공적으로 로그인 한 유저의 데이터를 가져온 것을 볼 수 있다.

이제 이 정보를 사용하기만 하면 된다!

 

 


구현하는 방법을 아는 상태로 글을 올린게 아닌, 나도 처음으로 구현하면서 포스팅을해서 다른 사람이 보기엔 좀 뒤죽박죽처럼 느낄것같다.

 

노마드 아카데미의 유튜브 클론강의를 들으면서 github 로그인은 구현해본적 있는데, 이번에 혼자 프로젝트를 할땐 카카오 로그인을 구현해보고 싶었고, 나중에도 참고하기위해 포스팅을 했다.

 

이번 포스팅도 노마드 아카데미의 유튜브 클론 영상의 영향을 아주 많이 받았다!

 

처음 카카오 공식문서만 보고 해보려고했을땐 어떻게 손을 대야할지 모르겠었는데, 고마워요 니콜라스..

 

하여튼 오늘 구현하면서 fetch 나 json의 대한 지식이 얕기때문에 완벽하게 이해는 못했지만, 깃허브 로그인 구현과 상당히 유사하게 구현된다는걸 알았다! 

 

fetch / json 에 대해 더 공부하고, fetch() 안에서의 headers 는 어떤 역할을 하는지도 공부해야겠다.

 

오늘 공부한 걸 정리한 글이지만 카카오 로그인을 구현하려고 구글링하시는 방문자님들에게 도움이 됐으면 좋겠다~

 

 

** 아, 그리고 email을 필수동의해야 사용자의 email 정보를 얻어올수있는데, 사업자가 아닌경우, 데브톡에 들어가서 게시글을 써서 요청해야한다! **

 

 

(조만간 참고할 것)

https://developer.mozilla.org/ko/docs/Web/HTTP/Headers

https://ko.javascript.info/fetch

'프로그래밍 > Node & Express' 카테고리의 다른 글

Express - 정규식  (0) 2021.08.07
Express.js - URL Parameter  (0) 2021.08.07
window에서 Express 설치하기  (0) 2021.02.16
window 에서 node.js 설치하기  (0) 2021.02.16