Projects/Personal project - 게시판 만들기

[게시판 프로젝트] 테이블 설계 및 엔티티 관계매핑에 대한 회고

마손리 2023. 8. 15. 05:52

이번 포스트는 제 개인 프로젝트인 게시판 만들기를 모든 코딩 작업을 마치고 난 후 회고 목적으로 작성하는 포스트입니다.

 

사실 해당 프로젝트를 완료했을 때, 기능 하나하나에 공들인 만큼 모든 기능들이 순조롭게 작동되어 스스로가 너무 뿌듯했다.

 

그러나 두달이 지난 현재, 다시 코드를 살펴보니... 엔티티 하나만 살펴봤는데도 답답함이 느껴진다.

 

@Entity
@NoArgsConstructor
@Getter
@Setter
public class Member extends Auditable {
    public Member(Integer memberId) {
        this.memberId = Long.valueOf(memberId);
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long memberId;
    @Column(nullable = false,unique = true)
    private String email;
    @Column(nullable = false, length = 50)
    private String name;
    @Column(length = 100) 
    private String password;
    @Column(nullable = false)
    private boolean socialLogin;

    @Enumerated(value = EnumType.STRING)
    @Column(length = 20, nullable = false)
    private MemberStatus memberStatus = MemberStatus.MEMBER_ACTIVE;

    @ElementCollection(fetch = FetchType.EAGER)
    private List<String> roles = new ArrayList<>();
    @OneToOne(mappedBy = "member", cascade = {CascadeType.REMOVE, CascadeType.PERSIST})
    private EmailVerification emailVerification;
    @OneToMany(mappedBy = "member", cascade = CascadeType.REMOVE)
    private List<Posts> posts = new ArrayList<>();
    @OneToMany(mappedBy = "member", cascade = CascadeType.REMOVE)
    private List<Likes> likes = new LinkedList<>();
    @OneToMany(mappedBy = "posts", cascade = CascadeType.REMOVE)
    private List<Comment> comments = new LinkedList<>();

    public void setEmailVerification(EmailVerification emailVerification){
        this.emailVerification = emailVerification;
        if(emailVerification.getMember()!=this) emailVerification.setMember(this);
    }
    public void setComments(Comment comment){
        this.comments.add(comment);
        if(comment.getMember()!=this) comment.setMember(this);
    }

    public void setLikes(Likes likes){
        this.likes.add(likes);
        if(likes.getMember()!=this) likes.setMember(this);
    }

    public void setPosts(Posts posts){
        this.posts.add(posts);
        if(posts.getMember() != this) posts.setMember(this);
    }

    public enum MemberStatus{
        MEMBER_ACTIVE("활동중"),
        MEMBER_SLEEP("휴면 계정"),
        MEMBER_QUIT("탈퇴 계정");
        @Getter
        private String status;

        MemberStatus(String status) {
            this.status = status;
        }
    }

    public Map<String,Object> getAttributes(){
        Map<String,Object> map = new HashMap<>();
        map.put("memberId", this.getMemberId());
        map.put("email", this.getEmail());
        map.put("name", this.getName());
        map.put("password", this.getPassword());
        map.put("socialLogin", this.isSocialLogin());
        map.put("memberStatus", this.getMemberStatus());
        map.put("roles", this.getRoles());
        return map;
    }
}

 

실제 작성된 Member 엔티티이다. 

 

다른 필드들은 필요한 부분이라 생각하고 넘어가겠지만,
왜 이렇게 연관 관계 매핑을 모두 양방향으로 설정 했을까?

그리고 그에 따라 작성한 Setter 메서드들... 저거... 어쩌죠....????

(사실 처음 프로젝트를 시작할 때만 해도 단방향 매핑이 가능한지 조차 몰랐는데 지금 보니까 어휴.... )

 

그래도 차근차근 나아가기 위해 @ElementCollection과 Embedded Type에 대해 공부하고 관계매핑 최적화를 해주려는데 더 큰 문제가 발생했다.

 

연관된 데이터에 접근하는 로직이 엔티티 간에 분산되어 있어서 하나의 엔티티를 수정하면 다른 엔티티와 그에 관련된 비즈니스로직도 모두 수정해야 하는 상황이 벌어젔다...

 

결국 코드를 수정하는 것을 미루고 ERD만이라도 작성해 보기로 했다.

 

 

 

기존의 ERD

위와 같이 기존의 ERD는 모든 관계가 양방향으로 설계되었다. 또한 OneToMany 관계에 해당하는 모든 Setter 메서드가 각 엔티티에 별도로 구현되어 코드의 가독성이 현저히 떨어지고 비즈니스로직을 작성할 때 개발자의 실수를 유발할 가능성이 높아 보인다.

이러한 문제점들로 인해 기존의 ERD를 수정할 필요가 보인다.

 

 

 

수정된 ERD

새로 변경된 ERD를 살펴보면 기존의 ERD와 비교했을때 엔티티의 필드수가 줄어들었다. 기존의 모든 양방향 관계를 ManyToOne 단방향 관계로 변경해 주었다.

 

또한 Member의 "email"과 "emailVerification" 필드를 Embedded type을 이용하여 하나의 "Email" 객체로 묶어 주었으며 "Photo" 엔티티를 ElementCollection으로 변경해 주었다.

이로 인해 실제 작성된 엔티티는 더 효율적으로 개선되었을 것으로 예상된다.