221122 은근히 까다로운 즐겨찾기(북마크) 기능

샨티(shanti)·2022년 11월 22일
0
post-thumbnail

하루를 마무리 하기 전, 오늘 있었던 일들을 잔잔히 되짚어봅니다.
성공과 실패의 모든 요소에서 '배울 점'을 찾아내어 기록하고,
더 성장하는 내일의 나를 위해 'action plan'을 세웁니다.

스프린트 5차.
오늘은 2~3일 동안 이해가 가지 않았던 JWT 관련 에러를 발견했다.
어쨌든 잘못된 부분은 수정했지만 너-무 늦게 발견한 탓에 오만 진이 다 빠져버린 것 같았다.
access token으로 여러가지 접근 권한들을 처리해주고 싶었는데 이게 밀려버리니 즐겨찾기 기능이나 다른 메뉴들에 부가 기능을 더하는 것이 너무 더뎌졌던 것 같다.

그리고 마음에 드는 장소를 즐겨찾기로 추가하는 로직도 생각했던 것보다 굉장히 까다로왔던 것 같다.
사실 토글에 가까운 기능이라고 생각했고, 그게 오래 걸리려나? 싶었는데 오늘 하루를 다 잡아먹었다.

위 두가지 경험을 통해 오늘 배운 점은 (1) 업무 투입시간을 실제와 근사하게 예상할 수 있는 능력은 다양한 경험이 뒷받침 되어야 한다는 점, (2) 정책이 정확히 정해지지 않은 상태에서 구현을 시작하면 JWT 오류와 비슷한 오류상황을 겪게 될 것이라는 점이다.

JWT 오류

서드파티 기능 구현의 연장선 내용이다.
네이버, 카카오 계정으로 로그인을 하면 각 소셜 로그인 주체측에서 access token, refresh token, email, nickname, userId(unique)를 반환해준다.
처음에는 '소셜로그인 응답내용 중에서 이메일을 변환해야겠다'고 생각했다. 실제로 상용 서비스들 중에서는 소셜 로그인을 실행할 때 아이디가 아닌 이메일 계정을 identifier로 사용하는 곳들이 있고 나 역시 현재까지는 소셜로그인&회원가입만 구현해놓은 상태였기 때문에 추후에 서비스에서 자체적으로 로그인, 회원가입을 구현하면 이메일을 identifier로 가져오면 되겠다고 생각했다.

근데 어제였나? 각 소셜로그인 응답값을 자세히 살펴보는데 간과한 점이 있었다.
바로 e-mail 값이 불안정하다는 점이었다.

물론 그럴 일은 거의 없겠으나, 사용자가 해당 소셜 로그인 측에 이메일 계정이 아닌 전화번호와 같은 값으로 회원가입을 했다면? 그렇다면 그 회원은 이메일 계정이 없고 나 역시 해당 회원의 이메일 계정을 자동으로 받아올 수 없다.
또한 사용자가 이메일 계정을 바꿔버리면 이 역시 문제가 될 수 있다. user 정보에 기존에 저장되어 있는 e-mail 정보와 불일치했을 때 어떻게 처리할지 대책을 마련하지 않았기 때문이다.

굉장히 안정적이라고 생각했던 이 이메일 값이 불안정하다는 결론이 나면서 약간 멘붕에 빠졌다. 그러다가 이메일보다 안정적인 값인 id(각 소셜로그인 주체들이 회원을 구분하기 위해 부여한 identifier)를 발견했고 이를 사용하기로 결정했다.

하지만 이게 또다른 재앙이 될 줄 몰랐다.
컨트롤러나 서비스단에서는 기존에 활용하던 email을 socialLoginId라는 요소로 모두 바꾸었는데, 하나를 누락한 것이다. 바로 JWTUtil...

아...
정말 이 재앙 때문에 근 이틀을 꼬-박 고생했다.
아-무리 액세스토큰을 JWT 디버거로 변환해도 멀쩡한 값이 나오지 않는 것이었다.
분명히 나는 socialLoginId를 access token으로 변환했는데 디버거 결과에는 곧죽어도 email이라는 글자부터 튀어나오는 것이었다.
이 때 눈치를 챘어야 했는데...

오늘은 정말 너-무 지치고 힘든 마음에 저녁을 먹고 바로 들어오지 못하고 성수 주변을 걸었다.
걸으면서 생각한 점. '대체 왜 email로 변환되는 것일까?'
15분 정도 돌면서 계속 생각하다가 문득 내가 초기에 access token을 만들기 위해 활용했던 것이 email이라는 사실이 떠올랐고 설마? 하는 마음으로 부랴부랴 도장에 올라와 JWTUtil 클래스를 들여다보는데... 하.
인터셉터 내용만 변경해놓고 정작 이 변환유틸은 그냥 두었던 것이다.

약간의 안도, 하지만 압도적인 속상함(ㅎㅎ)으로 위와 같이 고쳤더니 500 서버에러는 사라졌다.

여기가 원인인 줄 모르고 네이버/카카오에서 정보를 받아오는 클래스 안에서 System.out.println();만 얼마나 찍어댔는지...

정말 다시는 겪고 싶지 않은 일이고 다시는 하고싶지 않은 실수다.
이 요상한 실수 때문에 너무 의욕이 사라져서...ㅎㅎㅎㅎㅎㅎ 휴.

어쨌든 정말 정말. 다시는.... 이런 실수 하지 말자. 반드시 사전에 정책이 결정되어야 하고, 만약 변경이 된다고 하더라도 그 변경으로 인해 영향을 받는 곳들은 빠짐없이 살펴야 한다.


생각보다 까다로운 즐겨찾기(북마크) 기능

즐겨찾기 기능을 구현하는 데 역시 하루를 몽땅 써버렸다.
간혹 노아님이 생각보다 구현이 어려운 것들이 있는데, 예를들면 카카오톡처럼 실시간 채팅에서 읽지않음을 표시하는 숫자 1을 표시하는게 굉장히 어렵다고 하셨다.

오늘 즐겨찾기 기능을 구현하면서 그 말이 떠올랐던 것 같다.
생각보다 너무너무 까다롭고 힘들었던 것 같다. JWT 문제를 해결하긴 했지만 힘이 안나서 그런가...ㅋㅋ

구현하다 보니 굳이 필요하지 않은 곳에도 즐겨찾기 버튼이 너무 중복해서 들어가있는 것 같아 두군데 정도는 제외했고.

toggle에 따라 즐겨찾기 아이콘을 변하게 만들었다.
이 기능을 구현하기 위해 백엔드에선 새로운 값 객체(Bookmark)를 생성해주었는데 이게 값 객체인지 entity인지도 살짝 헷갈려서 오늘 낮시간엔 동료들과 한바탕 토론아닌 토론을 했던 것 같다 ㅎㅎ.
그래도 다들 좋은 조언을 줘서 값 객체인 Bookmark를 생성하고 이를 리스트로 만든 것을 User가 가질 수 있게 만들었다.


Bookmark에 userId가 들어가야 하나? 고민했다가 굳이 그러지 않아도 될 것 같아서 placeId 하나의 요소만 들고있도록 만들었다.
List 타입의 객체가 entity에 들어가기 위해선 @ElementCollection 이란 처음 사용해보는 어노테이션을 붙여줘야 했고 실제 h2 console에서 살펴보니 Users 테이블 안에 column으로 들어가는 것이 아니라 별도의 테이블로 생성되있는 것을 볼 수 있었다.

Bookmark가 가진 placeId로 어떻게 User 안에 있는 리스트 객체를 수정할 것이냐도 좀 헤매서 동료 도움을 받아 구글링도 해가면서 ㅎㅎㅎ 그렇게 꾸역 꾸역;; 구현했다.

이미 CSS를 좀 해놓은 상태라 얘네도 좀 적용했고... 결과물은 아래와 같다.

  • 로그인 상태에서 즐겨찾기 한 장소가 없을 때

  • 즐겨찾기 한 장소가 있을 때(해당 리스트를 클릭하면 장소 세부정보 페이지로 이동)

  • 상세페이지에서 해당 장소가 즐겨찾기로 저장되지 않은 곳일 때, 장소이름 옆 별 모양이 비어있음

  • 즐겨찾기로 저장된 곳일 때 장소 이름 옆 별 모양이 컬러. 해당 버튼을 클릭하면 즐겨찾기가 toggle됨

오늘도 구현하고 싶었던 모든 사항을 구현하지 못해 아쉬운 하루...
내일은 액세스토큰을 끝을 내야 할지 다른 기능을 해야 할지 좀 감이 안잡힌다. 약간 지치는 감이 있어서... refresh 할 겸 다른 것으로 할까 생각중.

멘탈이 전부다 멘탈이... 이번주는 기능 구현 완료를 목표로 삼았으니 자잘한 버그들 잡아가면서 기능 모두 구현하자!!

profile
가벼운 사진, 그렇지 못한 글

0개의 댓글