본문 바로가기

회고록(TIL&WIL)

TIL 2022.08.12 카카오톡 로그인

카카오톡 로그인을 사용하기 위해선 kakao development 페이지에서 기본 셋팅은 필수

애플리케이션 생성


플랫폼 Web으로 도메인 지정


response 받을 데이터들 동의 후에 받아올 수 있음


카카오 로그인 활성화 ON, Redirect URI 지정


HTML

...
<body>
    <section class="background-login">
        <div class="container-login">
            <div class="wrap-login">
                <div class="box-title-login">
                    <h1>SIDE PRO</h1>
                </div>
                <div class="wrap-input-login">
                    <li><input id="input-id-login" type="text" size=40 placeholder="이메일 주소를 입력하세요" title="아이디"></li>
                    <li><input id="input-password-login" type="password" size=40 maxlength="16"
                            placeholder="비밀번호를 입력하세요" onkeyup="login_enterkey()" title="비밀번호">
                    </li>
                    <li class="btn-login-login">
                        <div class="box-btn-login-login">
                            <button type="submit" onclick="login()" class="btn-login">
                                로그인
                            </button>
                            <button type="submit" onclick='kakao_login()' class="btn-kakao-login">
                                카카오 로그인
                            </button>
                            <button type="submit" onclick='alert("준비중입니다.")' class="btn-google-login">
                                구글 로그인
                            </button>
                        </div>
                    </li>
                    <li>
                        <span class="text-join">아직 아이디가 없으신가요?</span>
                        <button class="btn-join-login" onclick="window.location.href='join.html'">
                            <span>회원가입</span>
                        </button>
                    </li>
                </div>
            </div>
        </div>
    </section>
    <!-- Javascript Import -->
    <script src="/static/js/_base.js"></script>
    <script src="https://developers.kakao.com/sdk/js/kakao.js"></script>
    <script src="/static/js/user.js"></script>

</body>
...

자바스크립트

async function login_token(loginData, is_social){

    const response = await fetch(`${backend_base_url}/user/api/token/`, {
        headers: {
            Accept: "application/json",
            'Content-type': "application/json"
        },
        method: "POST",
        body: JSON.stringify(loginData)
    })

    response_json = await response.json()
    
    if (response.status == 200) {
        // 로컬스토리지에 jwt access 토큰과 refresh 토큰 저장
        localStorage.setItem("access", response_json.access)
        localStorage.setItem("refresh", response_json.refresh)

        // 파싱하는 부분 복사해서 사용하기! 
        const base64Url = response_json.access.split('.')[1];
        const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
        const jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) {
            return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
        }).join(''));

        localStorage.setItem("payload", jsonPayload);
        // window.location.href(`${frontend_base_url}/`);
        payload = JSON.parse(localStorage.getItem("payload"))
        user_id = payload["user_id"]
        const response = await fetch(`${backend_base_url}/user/profile`,{
            headers:{
            Accept: "application/json",
            'content-type': "application/json",
            "Authorization": "Bearer " + localStorage.getItem("access")
            },
            method: 'GET'
        })
        response_json = await response.json()

        if (response_json['userprofile'] == null) {
            window.location.assign(`${frontend_base_url}/templates/userprofile.html`);
        } else {
            window.location.assign(`${frontend_base_url}/templates/main.html`);
        }
    } else {
        if(is_social == true & response.status==401){
            alert('이미 가입된 이메일 입니다! 일반로그인으로 로그인 해주세요!', response.status)
        } else {
            alert('아이디 혹은 비밀번호를 확인해주세요!', response.status)
        }
    }
}


function kakao_join(){
    const username = document.querySelector("#input-username-join").value
    const data = JSON.parse(localStorage.getItem("kakao"));
    const join_data = {
        email: data['email'],
        password: data['email'],
        username: username,
        is_social: 1,
    }
    // 닉네임 중복체크
    fetch(`${backend_base_url}/user/dup_name/`,{
        headers: {
            Accept: "application/json",
            'Content-type': "application/json"
        },
        method: "POST",
        body: JSON.stringify(join_data)
    }).then(response => {
        return response.json()
    }).then(json => {
        if(json['result'] == 'false') {
            // 회원가입
            fetch(`${backend_base_url}/user/join/`,{
                headers: {
                    Accept: "application/json",
                    'Content-type': "application/json"
                },
                method: "POST",
                body: JSON.stringify(join_data)
            }).then(response => {
                localStorage.removeItem("kakao")
                is_social = true
                login_token(join_data, is_social)
            })
        } else {
            alert("중복된 닉네임입니다!")
            document.getElementById("input-username-join").focus()
        }
    })
    
}

// 카카오 api 를 쓰기위해 초기화
window.Kakao.init('8e2d299c275ad124f7fd5489f9dc723a');

function kakao_login(){
    console.log(Kakao.isInitialized());
    
    window.Kakao.Auth.login({
        scope: 'account_email',
        success: function(authObj) {
            console.log(authObj)
            window.Kakao.API.request({
                url: '/v2/user/me',
                success: function(resp){
                    var kakao_email = resp['kakao_account']['email']
                    var data = {
                        email : kakao_email,
                        password : kakao_email,
                        is_social: true,
                    }
                    // 이미 가입한 이메일인지 체크
                    fetch(`${backend_base_url}/user/dup/`, {
                        headers: {
                            Accept: "application/json",
                            'Content-type': "application/json"
                        },
                        method: "POST",
                        body: JSON.stringify(data)
                    }).then(response => {
                        return response.json()
                    }).then(json => {
                        // 가입 안한 경우 > 회원가입 > 로그인
                        if(json["result"] == 'false'){
                            const data = {
                                email : kakao_email,
                                is_social: true,
                            }
                            localStorage.setItem("kakao", JSON.stringify(data));
                            window.location.assign(`${frontend_base_url}/templates/kakao_join.html`);
                        // 이미 가입한 경우 > 로그인
                        } else {
                            const loginData = {
                                email : kakao_email,
                                password : kakao_email,
                            }
                            is_social = true
                            login_token(loginData, is_social)
                        }
                    })
                    
                }
            })
        }
    })

}

기존의 User 모델에서 is_social (Boolean) 필드를 추가하였고

이메일(아이디) 중복체크를 위해서 UserDupView(APIView) 클래스를 정의해서 post 메서드를 통해 request 줄 경우 중복 여부를 Boolean 값으로 리턴해주도록 구현, 회원가입의 경우는 기존의 join 에 사용되던 함수 같이 사용하도록 구현함