BootCamp

[Error] 일정 관리 트러블슈팅 1 - URI 설계 (User)

limitation01 2025. 11. 15. 06:24

문제 상황 

처음에 User URI 설계를 다음과 같이 진행했다.

PATCH /users/{userId}
POST /users/{userId}/delete

이때 서비스 단에서는

User user = globalValidator.findOrException(userRepository, userId);
globalValidator.matchPassword(user, request.getPassword());
globalValidator.forbiddenErrorHandler(user, sessionUserId);
  • forbiddenErrorHandeler 메소드로 URL로 전달된 userId, 세션에 저장된 로그인 유저의 userId가 일치하는지 매번 검증

하지만 여기서 문제가 발생했는데

문제 분석

1.URL 조작 위험

  • 클라이언트가 /users/2 → /users/3 으로 바꾸면 다른 사람의 리소스에 접근 시도가 가능해짐.
  • 물론 서버에서 세션 검증(forbiddenErrorHandler)으로 막고 있었지만, 테스트시  직접 바꾸면 여전히 접근 가능 

2. UI적으로 생각하면 모순됨

  • 현재는 특정 ID의 리소스에 접근한다는 의미인데 이상하게 느껴짐
  • 이미 쿠키에 세션아이디가 존재
  • 로그인 세션이 존재한다면 현재 로그인한 유저가  유일한 리소스 대상
  • 인증된 사용자에게 userId는 불필요한 데이터

3. 중복 검증 로직의 복잡성

  • 서비스단마다 forbiddenErrorHandler(user, sessionUserId) 검증이 반복
  • 결국 모든 메서드에 같은 검증이 들어가서 코드 중복 + 가독성 저하 발생

해결 - /me URI 수정

URI를 다음과 같이 수정했다

PATCH /users/me
DELETE /users/me
GET   /users/me

개선된 점

  1. URL 조작 가능했는데 세션 기반으로 조작할수 없게 되었다 
  2. 특정 ID 리소스에 접근한다 에서 로그인 유저 자신의 리소스 접근으로 의미가 명확해졌다
  3. 매번 ID 비교 검증이 필요했는데 세션에서 바로 가져옴

배운점

처음에는 단순히 REST 규칙대로 , 아니 그전 일정 CRUD처럼 리소스의 id를 명시해야한다고 생각했다. 하지만 다른 도메인과 다르게 인증된 사용자 시스템에서는 URL에 userId가 들어가는게 말이 안된다고 생각했다. 어떤 웹서비스 마이페이지를 생각해도 userId는 없다. 그래서 /user/me로 표현하는게 더 명확했다.

이번 트러블슈팅으로 인증 기반 시스템에서는 세션이 이미 사용자 식별자를 포함하므로, /users/me처럼 명시적인 ID를 제거하는 편이 보안과 표현도 더 낫다는 것을 깨달았다