공식 문서를 꼼꼼히 읽지 못하여 실수..
- 카카오 로그인을 구현하는 방법 중 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)를 붙여주어 기존 웹에서의 닉네임과 구분해주었다.