사이드 프로젝트를 진행하며 로그인 부분 구현을 맡게 되었다.
그런데 가끔 카카오나 네이버 간편 로그인시 회원가입 로직을 처리할때 컨트롤러에 동시 요청이 들어와서
유저의 회원가입 처리를 끝내기전에 또 회원가입을 요청하여 회원가입 여부 조건을 패스하여 동시에 2번 회원가입이 되는 현상이 발생하였다.
처음에는 해당 오류가 JWT 구현한 부분의 OncePerRequestFilter가 작동하지 않는다고 생각했다. 하지만 찾아보니 해당 현상은 동시성 제어 관련 문제였다.
/**
* US-7
* @param code
* @return
*/
@GetMapping("/kakao")
public ResponseEntity<TokenDto> loginByKakao(HttpServletRequest request, @RequestParam String code){
log.info("code {}", code);
TokenDto tokenDto = kaKaoUseCase.login(code);
return ResponseEntity.ok(tokenDto);
}
기존 코드는 컨트롤러에서 위와 같이 처리를 하고 있었다.
즉 악의적이거나 알수없는 현상으로 인해 해당 컨트롤러에 동시 요청을 하게 되면 회원가입 요청을 여러번 하게 되면서 동시에 회원가입을 진행하게 되는것이다.
이를 해결하기 위해서는 로그인 코드를 실행하는 부분에 동시성 제어를 해줘야 했다.
그러면서도 다른 유저의 작동에는 영향을 주지 않아야 했다.
Spring WebUtils.getSessionMutex를 사용하면 다른 유저에 영향을 주지 않으면서 해당 유저의 요청에 대해서만 동시성 제어를 하게 되는걸 알게 되었고 다음과 같이 수정하였다.
/**
* US-7
* @param code
* @return
*/
@GetMapping("/kakao")
public ResponseEntity<TokenDto> loginByKakao(HttpServletRequest request, @RequestParam String code){
log.info("code {}", code);
TokenDto tokenDto;
synchronized(WebUtils.getSessionMutex(request.getSession())){
tokenDto = kaKaoUseCase.login(code);
}
return ResponseEntity.ok(tokenDto);
}
아직 갈길이 먼것같다...