[데브코스] Spring Boot 인증·인가(Auth) (30강) - 댓글 수정/삭제에도 Authorization 헤더 인증 + 작성자 권한 체크(인가) 적용하기

zuno·2026년 1월 13일

이번 30강에서는 댓글 수정/삭제 요청에도 인증 정보(Authorization 헤더)를 전달하도록 맞추고, 그 인증된 사용자가 해당 댓글의 작성자인지(인가, 권한 체크)까지 검증하는 로직을 추가했다.

정리하면 흐름은 이거다.

  • 인증(Authentication): “너 누구냐?” → apiKey로 사용자(회원) 확인
  • 인가(Authorization): “너 이 댓글 수정/삭제할 권한 있냐?” → 댓글 작성자인지 확인

1) 변경 목표

✅ 댓글 삭제 / 댓글 수정에 공통으로 들어간 것

  1. @RequestHeader("Authorization") 로 헤더 값 받기
  2. "Bearer " 제거해서 apiKey만 추출
  3. memberService.findByApiKey(apiKey)로그인한 사용자(actor) 찾기
  4. actor.equals(postComment.getAuthor())작성자 일치 여부 확인
  5. 불일치하면 403 에러로 막기

2) 댓글 삭제 API에 권한 체크 추가

컨트롤러에서 댓글 삭제는 이런 형태로 바뀌었다.

  • Authorization 헤더를 필수로 받는다 (@NotBlank, @Size)
  • Bearer 토큰에서 apiKey 추출
  • apiKey로 actor(요청자) 조회
  • 댓글 작성자와 actor 비교해서 다르면 403

핵심 로직은 아래다.

@NotBlank
@Size(min = 30, max = 50)
@RequestHeader("Authorization")
String authorization

String apiKey = authorization.replace("Bearer ", "");
Member actor = memberService.findByApiKey(apiKey)
        .orElseThrow(() -> new ServiceException("401-1", "존재하지 않는 apiKey 입니다."));

PostComment postComment = post.findCommentById(id).get();

if (!actor.equals(postComment.getAuthor()))
    throw new ServiceException("403-1", "댓글 삭제 권한이 없습니다.");

3) 댓글 수정 API에도 동일하게 권한 체크 추가

댓글 수정도 삭제와 완전히 같은 패턴이다.

  • Authorization 헤더로 actor를 구하고
  • 댓글 작성자인지 비교해서 아니면 403

핵심 로직만 보면 아래처럼 동일하다.

String apiKey = authorization.replace("Bearer ", "");
Member actor = memberService.findByApiKey(apiKey)
        .orElseThrow(() -> new ServiceException("401-1", "존재하지 않는 apiKey 입니다."));

PostComment postComment = post.findCommentById(id).get();

if (!actor.equals(postComment.getAuthor()))
    throw new ServiceException("403-1", "댓글 수정 권한이 없습니다.");

4) 테스트 코드도 Authorization 헤더 기반으로 수정

기존에 쿼리 파라미터로 apiKey 넘기던 방식이 아니라,
이제 테스트에서도 아래처럼 헤더를 붙여서 요청하도록 바뀌었다.

  • delete 테스트
delete("/api/v1/posts/%d/comments/%d".formatted(postId, id))
    .header("Authorization", "Bearer " + actorApiKey)
  • put 테스트
put("/api/v1/posts/%d/comments/%d".formatted(postId, id))
    .header("Authorization", "Bearer " + actorApiKey)
    .contentType(MediaType.APPLICATION_JSON)
    .content(...)

5) (중요) 왜 actor.equals(comment.getAuthor()) 가 동작하나?

나도 처음엔 “DB에서 각각 조회한 객체인데 어떻게 같다고 판단하지?”가 의문이었는데,
이 프로젝트는 BaseEntity에서 equals/hashCode를 id 기반으로 오버라이드 해두었기 때문에 가능했다.

현재 BaseEntity는 아래 기준으로 equals()가 동작한다.

  • 같은 클래스인지 확인 (getClass() 비교)
  • id 값이 같으면 같은 엔티티로 판단
@Override
public boolean equals(Object o) {
    if (o == this) return true;
    if (o == null || getClass() != o.getClass()) return false;
    BaseEntity that = (BaseEntity) o;
    return id == that.id;
}

@Override
public int hashCode() {
    return Objects.hashCode(id);
}

즉,

  • actor의 id == comment.getAuthor().id
    이면 객체가 서로 다른 인스턴스여도 같은 회원으로 판단한다.

그래서 아래 권한 체크가 정상적으로 성립한다.

if (!actor.equals(postComment.getAuthor()))
    throw new ServiceException("403-1", "권한 없음");

6) 이번 강의 한 줄 요약

댓글 수정/삭제 요청도 Authorization 헤더로 인증하고, 작성자(id) 기반 equals로 “본인 댓글만 수정/삭제 가능” 인가 체크를 추가했다.

0개의 댓글