카카오 소셜 로그인 api를 활용하여 회원가입/로그인 기능 구현해보기

정재헌·2023년 1월 2일
0

카카오 소셜 로그인 api

웹 서비스를 이용하다보면 SNS 계정 기능을 활용하여 로그인을 할 수 있는 경우가 많다. 3초 간단 가입!, 간편 가입으로 유저의 회원가입 및 로그인 flow를 간소화시켜 빠르게 우리 서비스의 유저로 만들 수 있다는 면에서 상당히 필요한 기능이다.

그 중에서도 카카오 소셜 로그인을 사용한 이유는 기능 사용에 대한 진입 장벽이 상대적으로 낮으며, 대한민국 사람이라면 누구나 사용하고 있기에 유저 접근성 면에서도 좋다고 생각했기 때문이다.

카카오 로그인은 OAuth 2.0 기반의 소셜 로그인 서비스로, 사용자가 카카오톡 또는 카카오계정으로 손쉽게 서비스에 로그인할 수 있다. 서비스는 서비스 ID 및 비밀번호를 입력받고 검증하는 과정을 직접 구현하지 않고도 사용자에 대한 인증 및 인가를 간편하고 안전하게 처리할 수 있다.


<출처 : Kakao Developers 문서>

실습 준비

실습 환경

  • JavaScript
  • Node.js
  • express.js
  • MySQL 8.0
  • typeORM
  • Kakao social login REST API

백엔드에서 카카오 소셜 로그인은 인가 코드를 받는 것부터 시작할 수도 있고, kakao access token을 받는 것부터 시작할 수도 있다. 기능 구현에 있어서 이 부분이 가장 고민이었는데, 보안과 안정성 면에서 백엔드에서 인가 코드를 받는 것이 더 보안에 있어 안정적이라는 생각이 들었다.

그래서 인가 코드를 받아 카카오 인증 서버에 kakao access token 발급을 요청하고 받아서, 다시 카카오 resource api 서버에 유저 정보를 요청하는 flow로 코드를 구현해보았다.

<카카오 소셜 로그인 flow>

  • 프론트엔드로 부터 인가 코드를 전달 받는다.
  • 전달 받은 인가 코드를 가지고, 카카오 인증 서버에 토큰 발급 요청을 보낸다.
  • 전달 받는 카카오 토큰을 가지고 카카오 리소스 서버에 유저 정보 요청을 보낸다.
  • 전달 받은 유저 정보를 가지고 회원가입 중복 여부를 거친다.
  • 중복이라면, jwt 토큰을 발급하여 프론트엔드에 전달하고, 중복이 아니라면 새로운 유저로 가입을 시킨 후, jwt 토큰을 발급하여 프론트 엔드에 전달한다.

카카오 인증 서버 및 리소스 서버에 요청 보내기

const getAccessTokenByKakao = async(code) => {
    const result = await axios({
        method: 'post',
        url: 'https://kauth.kakao.com/oauth/token',
        params: {
            "grant_type": 'authorization_code',
            "client_id": process.env.RESTAPI_KEY,
            "redirect_url": process.env.REDIRCT_URL,
            "code": code
        }
    })
    return result.data.access_token
}
	const getUserInfoByKakao = async(getAccessTokenByKakao) => {
    const result = await axios({
        method: 'get',
        url: 'https://kapi.kakao.com/v1/oidc/userinfo',
        headers: {
            "Content-Type": "application/x-www-form-urlencoded;charset=utf-8",
            Authorization: `Bearer ${getAccessTokenByKakao}`
        }
    })
    return result.data
}

중복 여부를 판단하여 회원 가입 및 jwt 토큰 발급 처리하기

const kakaoSignIn = async(code) => {

    const kakaoAccessToken = await getAccessTokenByKakao(code)
    const kakaoUserInfo = await getUserInfoByKakao(kakaoAccessToken)

    const socialId = kakaoUserInfo.sub
    const userInfo = await userDao.getUserBySocialId(socialId)
    
    if(!userInfo){
                
        const newUser = await userDao.createUser(kakaoUserInfo)
        const payLoad = {userId: newUser.insertId}
        const accessToken = jwt.sign(
            payLoad,
            process.env.JWT_SECRET,
            { algorithm: process.env.ALGORITHM, expiresIn: process.env.JWT_EXPIRES_IN}
        )
        return accessToken   
    }

        const payLoad = { userId: userInfo.id }
        const accessToken = jwt.sign(
            payLoad,
            process.env.JWT_SECRET,
            { algorithm: process.env.ALGORITHM, expiresIn: process.env.JWT_EXPIRES_IN } 
        )
        return accessToken
    }

마치며

개발자로 성장해가며 다양한 오픈 소스 api를 할용하게 될 것이라 생각합니다. 오픈 소스 api를 사용하며 단순히 좋다고 하여 사용하기보다 우리 서비스에 있어 어떤 점이 좋고 어떤 점이 부족한지, 그리고 더 나아가 비용 및 보안의 관점 및 스케일 업, 스케일 아웃에 있어서도 함께 볼 수 있으면 좋을 것이라 생각합니다.

profile
백엔드 개발자

0개의 댓글