개발/프로젝트

[세션 / 토큰 로그인 프로젝트] 고도화(2) 멱등성에 대한 생각, 미들웨어 구현 결과

prpn97 2023. 7. 29. 22:22

이전에서 멱등성에 대해 공부하며 스스로 정의를 내린 것은, 무조건 post라서 멱등하지 않고 get이라서 멱등하다고 정의하기엔 어렵다는 것이다. 

 

미들웨어를 구현한 결과를 비교하며 자세히 생각해보자. 

1. 토큰 로그인

Request data saved to DB는 말그대로 db에 저장되는 요청 데이터의 값인데, 모든 요청에 대해 로직이 실행되기 전에 가장 먼저 거쳐가게 된다. 보는 바와 같이 post메서드로 토큰 로그인을 시도, sh5080을 입력하였고(비밀번호는 보이지 않게 함) 쿠키에는 값이 없고 키에는 값이 들어있다. 

 

로그인을 시도하면서 먼저 요청한 내용과 key값을 넣어서 보내주고, 로직이 작동한 이후의 데이터를 비교한다. 사실상 메서드, url, body는 달라질 일이 없고, 쿠키와 키를 살펴보면, 처음엔 쿠키에 값이 없었다. (request data와 이전 요청은 같은 값)

그리고 현재 요청에는 쿠키에 tokenID 값이 들어왔다. 토큰로그인을 하면서 토큰을 쿠키에 넣어서 보냈기 때문에 로그인을 하면서 쿠키에 값이 들어간 것이다. 

 

멱등성이 깨졌다는 근거는 tokenID가 생겼기 때문에 이전과 달라진 결과를 낳기 때문이다. 그래서 로그인을 post로 사용하는 것이다. 물론 로그인하는데 id, password로만 조회하는 식으로 검증한다면 의도상 get메서드로 보내주는게 맞겠지만 새롭게 cookie값을 생성하게 되기 때문에 post를 쓰는 것이다. 그리고 값이 생성됨으로 이전과 다르기 때문에 멱등성이 깨진 것이다. 

 

여기서 key는 req.sessionID로 express-session을 이용한 임의의 키값인데, 모든 요청마다 sessionID는 달라지기 때문에 다른 값이 생기고, iKey로 쿠키로 보내줄 예정이다. 이제 로그인한 이후 다음 요청을 보냈을 때 어떻게 변하는지 살펴보자.

2. 토큰 검증

get으로 토큰을 체크하는 api에서 멱등성을 만족한다고 한다. cookie값을 살펴보면 iKey와 tokenID로 나뉜다. 위의 스크린샷에는 아무것도 없었는데, 이 둘이 들어오는 것은 토큰로그인할 때 생긴 값이 확인되는 것이다. 그리고 req.sessionID를 똑같이 사용하는데도 iKey와 key의 값이 다르다. 앞서 설명했듯, 계속 바뀌는 값이기 때문에 이전 key와 현재의 key가 다른 것이다. 

그리고 jwt를 통해 tokenID 값을 검증하는 과정에서는 변동사항이 생기지 않는다. 실제로 비교하여 변동사항이 없기 때문에 멱등성을 만족한다고 확인되고 있다. 

 

느낀점

  멱등성의 여부가 좋고 나쁘고를 결정하지 않는다. 필요한 대로 post를 post답게, get을 get답게 목적대로 메서드를 적용하여 사용하는게 중요하다는 생각이 들었다. 

 

  멱등성에 대해 공부하면서 가장 많이 본 예시는 결제 였다. 사용자가 결제 시도 후 오류가 났을 때 에러화면이 확인되어 다시 결제를 했는데 중복결제가 되는 예시였다. 과정을 생각하면, 결제는 되었는데 결제로직이 지나간 후 네트워크나 여러 사유로 오류가 나는 경우 그런 상황이 생길 수는 있겠지만, 결제가 되었다는 것은 이전과 다른 즉, 멱등하지 않은 상황이다.

 

  당연스레 결제를 하면 변동사항이 생기기 때문에 멱등하지 않은 것이지만, 결제를 멱등하지 않게 api를 구현하면 방금 말한 상황이 나오겠지만 멱등하게 결제를 구현하면 어떻게 될까? 결국 멱등성은 연산을 여러 번 하더라도 결과가 달라지지 않는 성질을 뜻하고, API 요청에서 멱등성을 보장하면 같은 요청이 여러 번 일어나도 항상 첫 번째 요청과 같은 결과가 돌아온다.

 

  즉, 같은 요청을 여러번 보내도 여러번 처리되지 않는 것이다. 단순하게 1이라는 값에 1을 post한다고 하면 2가 되겠고, 1이라는 값에 1을 put한다면 1이 되겠다. 만약 내가 구현한 멱등성을 검사하는 과정을 적용해본다면, 이전에 같은 멱등키로 들어온 요청이 있었다면, 서버에서 실제 요청을 실행하지 않고 저장되어 있던 응답 데이터를 돌려주는 것이다. 

  그렇게 한다면 결제가 처리되는 시점의 key값과 동일한 값이 있으면 추가로 더 결제가 되지 않고 이미 결제가 되었다고 보내줄 수 있겠다.

 

결론적으로는 default하게 원 의도대로 멱등한, 멱등하지 않은 메서드대로 구현하면서도, 값이 바뀌는 멱등하지 않은 메서드에 대해서는 특별히 더 주의하며 에러처리 등 필요시에는 멱등하게 구현하는 시야가 필요할 것 같다. 

728x90