효율적인 엔티티 관계 설정

양성준·2025년 3월 20일

스프링

목록 보기
17/49

연관 관계

1. User가 UserStatus를 갖는게 아니라, 왜 UserStatus가 UserId를 갖는가?

  • UserStatus가 User 엔티티 내부 필드가 아니라, 별도 테이블에서 userId를 참조하는 방식
  • UserStatus는 User 없이 존재할 수 없지만, 별도 테이블로 관리됨

why?

  • 이렇게 하면 유저의 상태 변경이 빈번해도 User 엔티티에 직접 영향을 주지 않고 변경 가능하다는 장점이 있다.
  • UserStatus가 User 엔티티 내부에 있으면, User 엔티티가 너무 커지고 불필요한 데이터 변경이 많아짐
  • 유저 정보를 조회할 때 불필요한 status 정보까지 항상 함께 불러올 필요 없음
  • userId로 빠르게 상태를 조회할 수 있음 → 유저가 많아도 성능 최적화 가능

=> UserStatus는 특정 User가 있어야만 의미를 가질 수 있는 엔티티이기 때문에, UserStatus에서 User를 직접 참조하는 것이 더 적절한 설계.

2. User와 Channel이 ReadStatus를 갖는게 아니라, 왜 ReadStatus가 UserId, ChannelId를 갖는가?

  • ReadStatus가 User나 Channel에 List< ReadStatus>로 직접 포함되는 게 아니라, userId와 channelId를 갖고 엔티티로 존재
  • userId와 channelId없이 존재할 수 없다.
  • 특정 유저가 특정 채널을 마지막으로 읽은 위치(시간 등)를 저장하는 역할

why?

  • User 엔티티나 Channel 엔티티가 길게 리스트를 가질 필요가 없음, 엔티티를 불러올 때 마다 방대한 List를 불러와야함
  • ReadStatus는 User + Channel 간의 다대다(N:M) 관계를 효율적으로 관리
  • userId + channelId를 PK 또는 유니크 키로 설정하여 빠르게 조회 가능
  • User나 Channel 엔티티에서 List로 가지고 있다면, 엔티티를 불러와서 List 뜯고.. 엄청 불편하지만,
    이 방식으로 하면 userId + channelId로 간단하게 ReadStatus 조회 가능

=> ReadStatus는 특정 User와 특정 Channel이 있어야만 의미를 가질 수 있는 엔티티이기 때문에, ReadStatus에서 User와 Channel을 직접 참조하는 것이 더 적절한 설계.

3. BinaryContent에서 UserId와 MessageId를 갖는게 아니라, 왜 User와 Message에서 갖는가?

  • BinaryContent를 User, Message, Channel 등의 여러 엔티티에서 참조 가능
  • 특정 엔티티 없이 단독으로 존재 가능

why?

  • BinaryContent가 여러 곳에서 사용될 수 있기 때문
  • 하나의 BinaryContent가 특정 User(프로필 사진), Message(첨부파일), Channel(채널 아이콘) 등에서 사용될 수 있음
  • 만약 BinaryContent가 User, Message를 다 포함하고 있었다면?
    • 특정 경우(예: 프로필 사진)에서는 Message가 비어 있어야 하고,
    • 특정 경우(예: 메시지 첨부파일)에서는 User가 비어 있어야 함
  • 이런 상황이 많아지면 BinaryContent가 점점 복잡해지고 불필요한 필드가 많아짐
  • 유지 보수 측면에서도, 갑자기 BinaryContent를 쓰는 엔티티가 생기면, 그걸 또 BinaryContent에 추가해줘야함
    -> 이 방식으로 하면 엔티티에서 BinaryContent Id만 가지는 식으로 간단하게 추가 가능!

=> BinaryContent는 공용 엔티티기 때문에, 특정 엔티티에 대한 정보가 없어도 존재할 수 있기 때문

4. 왜 BinaryContent는 독립적인가?

1. 특정 엔티티 없이도 저장될 수 있음

  • 파일 업로드 API를 호출하면, 메시지를 보내지 않아도 BinaryContent 엔티티는 먼저 DB에 저장됨
  • 즉, Message나 User 없이도 BinaryContent는 먼저 생성될 수 있음
  • 메시지를 안 보냈다면, 메타데이터만 저장된 채로 남아 있을 수도 있음 (이 경우 일정 시간이 지나면 삭제)
  • BinaryContent는 누군가 참조하지 않아도 저장 자체는 가능함! (사용되지 않는다면 이후 정리될 뿐)

2. 여러 엔티티에서 참조 가능 → 다중 사용 가능

  • User, Message, Channel 등 다양한 엔티티가 BinaryContent를 사용할 수 있음
  • 만약 특정 User의 프로필 이미지로 사용될 수도 있고,
    같은 파일이 Message의 첨부파일로도 활용될 수도 있음 (이론적으로는 가능)
  • 즉, BinaryContent는 특정 엔티티(User, Message 등) 하나에 종속되지 않음!

3. 만약 BinaryContent가 특정 엔티티(User, Message 등)에 종속적이었다면?

  • Message가 삭제되면 첨부파일도 함께 사라져야 할까?
  • 하지만 같은 파일이 여러 메시지에서 참조될 수도 있음!
  • 그러면 다른 메시지에서도 사용되는 파일이 지워지는 문제가 생김

=> 이러한 이유들 때문에, BinaryContent를 독립적인 엔티티 객체로 설계해야한다.

  • 특정 엔티티(User, Message 등)에 종속되지 않으면서 필요한 곳에서 참조하도록 설계
  • 파일이 여러 엔티티에서 사용될 가능성을 고려해서 독립적인 구조로 둠

결론: 언제 별도 엔티티로 분리해야 할까?

  • 여러 엔티티가 있어야 존재할 수 있다면? → ReadStatus처럼 따로 분리 (관계 엔티티)
  • 여러 엔티티에서 사용되지만, 단독으로도 존재할 수 있다면? → BinaryContent처럼 참조하는 방식이 좋음
profile
백엔드 개발자

0개의 댓글