솔직히 말하면 나는 구글이 제일 Oauth의 문서가 어렵다고 생각했는데, 그 상상을 뛰어넘는게 바로 네이버 Oauth임을 밝히고싶다.
아니, 정확히 말하면 문서 자체는 어려운건 아니다 (한국어고)
근데 가장 큰 문제는, 정식 문서에 있는 내용이 구식 버전이라는 점이다 (현재 2.0.2, 문서는 1.0.3) 이로 인해 공식문서의 내용을 사용하기 좀 꺼려지는 부분이 있다.
추가적으로 몹시 고통스러웠던 것은, sdk 안에 구현되어 있는 메서드들이 실제로 작동을 안하는 것들이 있다는 점이었다.
logout메소드는 실제로 작동하지 않는다.
거기에 첩첩산중으로 네이버는 별도의 로그아웃 API를 보안상 제공하지 않기 때문에 계정연동을 해제할 수가 없다.
보안상 어쩔 수 없다고는 하는데, 사실 방법이라고 해볼만한 요소는 2가지가 있었다.
토큰을 이용한 연동해제 = 만약 REST로 실행했으면 이 방법을 택하겠는데, 네이버는 자신들이 제공하는 팝업 oauth창이 아니고서야 cors 규칙으로 충돌이 난다. (분명 설정상에 주소가 등록되어 있음에도 이런다)
"https://nid.naver.com/nidlogin.logout" 을 window.open을 통해 열어서 로그인 상태를 해제하는 방법. 하지만 이 방법은 해제 후 불필요한 네이버 팝업창으로 리다이렉트되기 때문에 몹시 지저분하다. 하지만 별 방법이 없다. 이렇게 해서 window.close를 활용하면 깜빡거림과 함께 연동이 끊어지기는 한다.
현재, 과거 프로젝트는 신규 창에서 Oauth를 실행하도록 만들어봤으니 이번엔 팝업창을 이용한 로그인을 해보려고 시도하고 있었는데, 간단히 구현이 될것이라고 에상했던 처음 생각과는 다르게 오히려 REST API를 통한 새창을 이용한 로그인이 훨씬 더 쉽지 않았을까 하는 회고를 해본다
마지막으로, 네이버는 특이하게 javascript를 통한 oauth 시스템이 처음 초기화를 시작하면 미리 설정한 id 어트리뷰트를 가진 요소에 자신들의 버튼을 반영하는 형식으로 되어 있어서 커스텀을 하기 위해선 별도의 useRef를 이용한 참조 형태를 취해야 한다.
이런 후, 작업하는 것은 그렇게 어려운 것은 아닌데 귀찮다. 그냥 필요한 작업만 하고 싶었다.
마지막으로, 네이버가 제공하는 버튼은 항상 팝업을 screenX=0 screenY=0인 지점에서 튀어나오도록 되어있는데, 이것을 바꾸려면 네이버 oauth 버튼 내부 로직에 있는 popup 메서드의 몸체를 건들여야 했다. (즉 그건 무리다)
네이버 oauth만큼은 구글링으로도 너무 한계가 존재해서, 이것저것 다 건들여보며 데이터값을 확인 후 처리해보았다.
거두절미하고 코드만 보자면
<button
onClick={() => {
window.open(
"https://nid.naver.com/oauth2.0/authorize?response_type=token&client_id=VYxWDMtdyXyOms1pHNDe&state=17f11f50-4ac6-4334-9fdf-ac2b8589323e&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fnaver&version=js-2.0.1",
"_blank",
"height=400,width=377,top=100,left=200,scrollbars=yes,resizable=yes"
);
}}
>
네이버 계정으로 계속하기
</button>
버튼은 네이버가 강제로 id를 통해 요소를 찾아 디자인을 덮어씌우는 행위를 막기 위해, 일반 버튼 위에 버튼을 누른 후 가게되는 링크 주소를 새창 형식으로 열도록 만들었다.
3번째 인자로는 팝업창의 옵션을 줄 수 있는데, 여기서는 높이 400px, 넓이 377px, 그리고 top과 left를 고정 px로 주긴했는데 저 부분은 현재 screen의 좌표 값을 읽어와서 중앙정렬하도록 바꾸면 된다.
네이버는 저 상태에서 인증을 동의하는 순간, [팝업창] 의 위치에서 리다이렉트를 해버린다.
그리고 그 팝업창의 url에다가 accessToken을 담아서 주는데, 문제는 이 창이 아니라 부모한테 로그인 관련한 데이터가 가야한다
그래서 이것저것 찾아보니 알게 된 윈도우 프로퍼티가 있는데 그것은 바로
window.opener
였다. 이 프로퍼티 값은 놀랍게도, 팝업창의 입장에서 누가 나를 띄워줬는지에 대한 그 윈도우 객체의 정보를 담고 있다.
따라서, 팝업창의 라우팅에서 useEffect를 통해 자신의 opener, 즉 부모 윈도우 객체에다가 자신이 가지고 있는 값을 넘겨주면 그것은 그대로 부모한테 전달된다
아래는 팝업창이 아닌 부모, "localhost:3000" 의 윈도우 객체를 찍어본 결과이다.
이를 통해 원하는 형태로 네이버 로그인을 구현하는 것을 성공하였....
지만 로그아웃은 아직도 만족스럽지 못하다.