equals() 미구현으로 발생한 JPA Entity 비교 오류

coldrice99·2025년 3월 30일
0
post-thumbnail

클럽 가입 신청을 관리자가 승인하는 기능을 만들던 중, 관리자가 본인의 클럽에 대해 승인하려 했는데, "유효하지 않은 클럽 관리자입니다" 라는 오류가 발생했다. 분명히 로그인한 사용자는 해당 클럽의 관리자였는데도 말이다.


✅ 문제 코드

아래는 클럽 관리자인지 검증하는 로직이다:

if (!club.getManager().equals(manager)) {
    throw new GlobalException(ExceptionCode.UNAUTHORIZED_MANAGER);
}

로그를 찍어보면 다음과 같았다:

System.out.println("club.getManager() = " + club.getManager().getId());
System.out.println("requesting manager = " + manager.getId());

📋 출력 결과:

club.getManager() = 2
requesting manager = 2

두 ID는 분명히 같지만, equals는 false를 반환하여 예외가 발생하고 있었다.


🔍 원인 분석

JPA에서 equals()를 오버라이드하지 않으면, 기본적으로 Object.equals()가 사용된다. 이는 객체의 참조(주소)가 같은지를 비교하기 때문에, 같은 ID를 가진 Member라도 다른 영속성 컨텍스트에서 가져온 객체는 다르다고 판단한다.

즉, 다음과 같은 상황이 되는 것이다:

Member managerFromClub = club.getManager(); // 영속성 컨텍스트 A
Member currentUser = userDetails.getMember(); // 영속성 컨텍스트 B

managerFromClub.equals(currentUser); // false → 예외 발생

✅ 해결 방법

Member 엔티티에 equals()hashCode()를 오버라이드하여 ID 기준으로 논리적 동일성을 판단하도록 수정했다:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Member member = (Member) o;
    return id != null && id.equals(member.id);
}

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

🔎 이렇게 하면 ID만 같아도 equals()가 true로 판단되어 로직이 제대로 작동한다. 위 코드는 JPA에서 권장하는 패턴이며, Hibernate 공식 문서에서도 소개된 방식이다.


📌 결론

  • 인증/인가 관련 로직에서 equals로 객체 비교하는 경우 주의해야 한다.
profile
서두르지 않으나 쉬지 않고

0개의 댓글