[개발일지] 취미 커뮤니티 - 크루 가입 및 탈퇴 기능 중 객체의 동등성 비교

zwon·2023년 10월 23일
0

개발일지

목록 보기
19/23

크루 가입 탈퇴 기능을 구현하다가 객체의 비교에 있어서 정리하고자한다.

Crew

// 크루에 가입이 가능한지
  public boolean isJoinable(User user) { // (1)
    return this.isPublished() && this.isRecruiting() && !this.users.contains(user);
  }
  // 크루 멤버인지
  public boolean isMember(User user) { // (2)
    if (this.user.equals(user)){ // 크루장인 경우
      return true;
    }
    return this.users.contains(user); // 크루원인 경우
  }
  • 크루 엔티티에 크루 가입 가능 여부와 크루 멤버인지에 대해서 작성했다.

CrewViewController

// 크루 참가 신청
  @GetMapping("/crew/{id}/join")
  public String joinCrew(HttpSession session, @PathVariable Long id){
    User loginUser = (User) session.getAttribute("loginUser");
    crewService.addUser(id, loginUser);
    return "redirect:/crews/"+id;
  }
  // 크루 탈퇴
  @GetMapping("/crew/{id}/leave")
  public String leaveCrew(HttpSession session, @PathVariable Long id){
    User loginUser = (User) session.getAttribute("loginUser");
    crewService.leaveCrew(id, loginUser);
    return "redirect:/crews/"+id;
  }
  • 컨트롤러는 위와 같이 작성했다.

CrewService

 // 크루 참가
  public void addUser(Long id, User user){
    Crew crew = crewRepository.findById(id).orElseThrow(IllegalArgumentException::new);
    log.info("addUser before : isMember() = {}",crew.isMember(user));
    if (crew.isJoinable(user)){
      crew.addUser(user);
    }
    log.info("addUser after : isMember() = {}",crew.isMember(user));

  }
  public void leaveCrew(Long id, User user){
    Crew crew = crewRepository.findById(id).orElseThrow(IllegalArgumentException::new);
    log.info("leaveCrew before : isMember() = {}",crew.isMember(user)); // 왜 여기서 false지?
    if (crew.isMember(user)) {
      crew.removeUser(user);
    }
    log.info("leaveCrew after : isMember() = {}",crew.isMember(user));
  }
  • crewService는 위와 같이 작성했는데 자꾸 가입은 되도 탈퇴가 되지 않았다.
  • 문제는 User 객체의 동등성 문제였다.
  • User 클래스에서 equals 및 hashCode 메서드를 적절하게 재정의하지 않아서 발생한 문제였고 User 엔티티에 다음과 같이 equals 및 hashCode 메서드 재정의해주었다.

User

@Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    User user = (User) o;
    return Objects.equals(getId(), user.getId()) && Objects.equals(getName(), user.getName()) && Objects.equals(getNickname(), user.getNickname()) && Objects.equals(getPassword(), user.getPassword()) && Objects.equals(getEmail(), user.getEmail());
  }

  @Override
  public int hashCode() {
    return Objects.hash(getId(), getName(), getNickname(), getPassword(), getEmail());
  }
  • equals() 메서드를 재정의하지 않으면 Java는 기본적으로 두 객체의 동일성(즉, 두 객체가 정확히 같은 메모리 위치를 참조하는 경우)을 확인한다.
  • 그러나 두 객체가 동일한 값을 나타내고 서로 다른 메모리 위치를 참조할 때, equals()를 사용하여 이러한 객체를 비교할 수 없다.
  • 그래서 equals() 메서드를 재정의하여 객체의 논리적 동등성을 확인할 수 있게 만들어야한다.
  • 뿐만 아니라, 동일한 객체를 검색하려면 동일한 해시 코드를 가져야하기때문에 hashCode() 메서드도 equals() 메서드와 일관성을 유지를 위해 재정의를 해주어야한다.
  • 직접 재정의 하는건 실수할 가능성이 있으니 IDE에서 제공해주는 기능을 사용하자.
  • 인텔리제이에서는 다음과 같이 equals() and hashcode()를 재정의해주는 기능이 있다.
profile
Backend 관련 지식을 정리하는 Back과사전

0개의 댓글