프론트엔드

카카오 싱크와 퍼머 링크 도입기

자몽0 2024. 5. 5. 14:47

필자의 회사에서 카카오 싱크와 퍼머링크를 도입하면서 겪었던 시행착오와 이를 어떻게 개선했는지 적어보자 한다.

 

이 글을 읽으면, 필자가 카카오 싱크를 어떻게 도입하게 되었으며,

유저 플로우를 어떻게 개선해 나갔는지 확인할 수 있을 것이라고 생각한다.

 

카카오 싱크란,

간편가입으로 내 회원을 쉽고 빠르게 모으고,
카카오톡에서의 정교한 타겟 마케팅 도구까지 제공하는 카카오의 새로운 비즈니스 솔루션이다.

 

필자의 회사에서 '카카오 싱크'를 도입하기로 결정한 이유도 바로 '자동 로그인'과 '간편가입' 기능을 활용하기 위함이였다.

카카오 싱크를 사용한 메인 동작 플로우는 다음과 같다.

카카오 싱크 설계하기

카카오 싱크를 사용해 로그인을 진행하고, 사용자 정보를 받아오기 위해서는 서버와 클라이언트에서 특정 처리가 필요하다.

참고: https://developers.kakao.com/docs/latest/ko/kakaologin/common

  1. 대략적인 흐름은 아래와 같다.
  2. 웹에서 카카오 로그인 SDK를 호출한다.
  3. 카카오는 카카오 서버를 통한 인증 과정을 거쳐 정해진 주소로 인가 코드와 함께 redirect 해준다.
    (redirect에는 웹 주소를 넣어도 되고, 서버 주소를 넣어도 된다. 토큰을 발급받아 사용자 정보를 가져오는 행동을 어디서 진행할건지에 따라 결정하면 된다.)
  4. 서버에서 인가 코드를 기반으로 토근을 발급받고, 원하는 정보를 카카오에서 받아온다.
  5. 카카오에서 받아온 정보를 기반으로 서버에서 원하는 처리를 진행하고, 웹에 redirect로 필요한 정보를 전달해준다.

카카오 싱크 (웹)

카카오 싱크를 연동하며 웹에서 고민해야 할 점은 다음과 같다.

확장성 있는 구조 가져가기

서버에서 웹에 redirect 해주는 주소는 고정되있다 가정할 때, 아래 조건을 충족시키기 위해서는 어떻게 해야할까?

A 랜딩 페이지에서 카카오 싱크 플로우를 완료하면 A 결과 페이지로 가야한다.
B 랜딩 페이지에서 카카오 싱크 플로우를 완료하면 B 결과 페이지로 가야한다.

카카오 공식 문서를 보면, 카카오 로그인을 진행할 때, request에 state라는 값이 존재한다.

state: 카카오 로그인 과정 중 동일한 값을 유지하는 임의의 문자열(정해진 형식 없음)

 

state에 JSON.stringify 형식으로 데이터를 전달해주고, 서버가 웹에서 전달한 state값을 카카오 로그인이 완료되는 시점에 전달해주면, 확장성있게 원하는 값을 웹에서 사용할 수 있다.

 

예를 들어, A랜딩 페이지에서 카카오 싱크를 진행하면 A결과 페이지로 가야함., A페이지에 접근한 유저 타입을 알아야함. 과 같은 요구 조건들이 있다면, 아래와 같이 state에 event_redirect_uri, user_type 을 전달해주면 된다.

Kakao.Auth.authorize({
    kakaoSinkRedirectUri, 
    {
          state: JSON.stringify({
          event_redirect_uri: this.eventRedirectUri,
          user_type: this.userType
        })
    }
});

검색 엔진 노출 방지

웹 개발을 하면서 의외로 놓치기 쉬운 부분이다.
카카오 싱크가 완료되었을 때, 서버 -> 웹으로 redirect되는 페이지는 query에 사용자 정보가 포함되어 있다.


이 정보는 검색엔진에 노출되서는 안되는 정보이므로, robots에 명시적으로 해당 페이지는 Disallow 처리를 해주어야 한다.

퍼머 링크 도입 (iOS: 카카오 로그인 시 ‘사용 중이던 서비스로 이동하여 로그인을 완료해 주세요.’라고 뜨는 현상 개선)

카카오 싱크를 통해 사용자 인증 절차를 매우 간소화 시키는 변화를 일으켜 냈지만, 그럼에도 한 가지 아쉬운 부분이 남아있었다.

 

우선, 모바일 환경에서 카카오 싱크는 아래 과정을 통해 진행된다.

  1. 브라우저(chrome, safari)에서 이벤트를 참여.
  2. 카카오 싱크를 진행하기 위해 카카오 앱이 열림.
  3. 카카오 싱크가 완료되면 카카오 앱이 닫히며 브라우저가 열림.

하지만 iOS의 경우 OS 보안 정책에 따라,

카카오톡이 실행된 상태인데 iOS 플랫폼에서 앱에서 특정 브라우저로 돌아가는 것은 불가능하기 때문에,

사용자에게 직접 돌아가도록 안내하는 창이 강제로 뜨게된다.

 

이 현상을 개선하기 위해 찾은 방법은 카카오 퍼머링크였다.

(카카오 퍼머링크는 따로 공식적인 발급 채널은 없고, 데브톡을 통해 발급 요청하면 된다.)

 

카카오 퍼머링크의 개념은 다음과 같다.

어떤 앱으로 QR코드를 스캔하더라도,
카카오톡 클라이언트를 실행하고,
카카오톡 인웹뷰를 실행해, 여러분의 서비스 URL로 리다이렉트 해주는 역할을 합니다.

 

여기서 주의깊게 봐야할 부분은 '카카오 인앱뷰를 실행해 여러분의 서비스 URL로 리다이렉트 해주는 역할은 합니다.' 라는 부분이다.

iOS 플랫폼에서 앱에서 특정 브라우저로 이동하는 것이 막혀있다면, 앱에서 앱의 웹뷰가 열리면 보안 정책에 위배되지 않는다.

 

이제 카카오 퍼머링크가 추가된 카카오 싱크 플로우는 다음과 같다.

 

 

이러한 점을 이용해 카카오 싱크 플로우에 퍼머 링크를 추가했고,

사용자가 카카오 싱크 플로우를 진행하는 과정에서 더 이상 안내 창이 뜨지 않도록 개선하였다.

 

카카오 퍼머링크 개선

퍼머 링크 도입 이후 모든게 끝난 줄 알았지만, 퍼머 링크 도입으로 인해 발생한 사이드 이펙트가 있었다. 

카카오 인앱 뷰에서 열린 이벤트 결과 페이지에서 뒤로가기를 하면, 다시 카카오 싱크가 실행되는 부분이였다.

 

다시 한 번 퍼머 링크의 개념을 들여다보자.

카카오톡 인웹뷰를 실행해, 여러분의 서비스 URL로 리다이렉트 해주는 역할을 합니다.

 

문서에서는 서비스 URL로 리다이렉트 해주는다는 건 리다이렉트할 서비스 URL이란 '카카오싱크 간편가입 화면을 호출하는 서비스의 URL을 의미합니다. 라고 되어있다.

 

즉, 아래 플로우와 같이 카카오 싱크를 완료하고 뜬 결과 페이지에서 뒤로가기를 하면,

카카오 싱크 호출 페이지로 가게 되고, 다시 카카오 싱크가 실행되서 이벤트 결과페이지가 보여진다.

 

이런 어색한 결과는 사용자가 뒤로가기를 여러번 연타하거나, 인앱 뷰 닫기(X 버튼)를 통해 명시적으로 페이지를 탈출해 주어야만 해결할 수 있었다.

이러한 현상을 개선하기 위해, 고민 끝에 HTTP 302 응답 특성을 활용하기로 하였다.

 

HTTP 302는 이전 페이지에 대해 기록하지 않는다는 특징이 있다.

(참고: Why do browsers not keep status 302 pages in back-button history?)

 

이를 활용해, '카카오 싱크 호출'을 서버 또는 SSR 에서 구현한다면,

이벤트 결과 페이지를 보기 전까지 302 redirect를 시킨다면 뒤로가기는 존재하지 않을 것 이라는 추측을 했다.

  1. [302 redirect]: 카카오 싱크 호출
  2. [302 redirect]: 카카오에서 서버로 redirect
  3. [302 redirect]: 서버에서 웹으로 redirect
  4. [200]: 이벤트 결과 페이지

필자의 회사에서는 이벤트 페이지들을 SSR 환경에서 동작시키고 있었기 때문에,

카카오 싱크를 호출하는 path는 서버 환경에서 동작하도록 개발했다. (server.ts에서 해당 path일 때, 카카오 로그인 REST API 호출)

 

이러한 해결 과정을 통해,

사용자가 카카오 싱크 과정을 거쳐, 카카오 인앱 뷰에서 이벤트 결과 페이지가 떴을 때, 뒤로가기를 통해서 자연스럽게 이벤트 페이지가 닫히도록 구현하였다.

 

지금까지 카카오 싱크와 카카오 퍼머링크를 도입하면서 겪었던 이슈들과 이를 어떻게 해결했는지 간단하게 서술해 보았다.

사용자의 입장에서 프로덕트를 바라보고, 개선하다 보니 기존 예상보다 더 좋은 결과물이 나올 수 있었던 것 같다.