Spring/괴발개발

[괴발개발] TODO 웹 개발 노트 - 엔티티 설계

오잎 클로버 2022. 2. 17. 09:15
728x90

TODO 웹 개발에는 기본적으로 갖추어야하는 조건에는 회원가입과 글 작성이 있습니다.

회원가입은 기본적으로 회원 엔티티가 필요할 것이고,

TODO 게시글도 따로 저장을 해야하기에 엔티티가 필요합니다.

 

그리고 TODO 게시글의 수정 및 삭제는 작성자만이 할 수 있어야고, 동시에 회원이 총 몇개의 글을 작성했는 지 역시

알게 하고 싶었기에 양방향 연관관계로 매핑하였습니다.

ERDCloud를 사용했습니다. (한 번도 써본 적이 없어서 잘못 표현했을 수도 있습니다;;)

회원과 TODO 게시글의 관계는 일대다이고, TODO 게시글과 회원의 관계는 다대일입니다.

 

Member.java
@Getter @Setter
@NoArgsConstructor @AllArgsConstructor
@Builder
@Entity
public class Member {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private String email;

    @Column(nullable = false, unique = true)
    private String username;

    @Column(nullable = false)
    private String password;

    @OneToMany(mappedBy = "member")
    private List<Post> posts;

    public void addPost(Post post) {
        posts.add(post);
    }

    public void removePost(Post post) {
        posts.remove(post);
    }

}

일대다 관계는 여러 객체와 연관관계를 맺을 수 있기에 컬랙션을 사용해야합니다.

 

Post.java
@Getter @Setter
@NoArgsConstructor @AllArgsConstructor
@Builder
@Entity
public class Post {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, length = 100)
    private String title;

    @Column(nullable = false, length = 10000)
    private String content;

    private String comment;

    private boolean checked;

    private LocalDateTime checkedDate;

    @ManyToOne
    @JoinColumn
    private Member member;

    @CreatedDate
    @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
    private LocalDateTime createdDate;

    @LastModifiedDate
    @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
    private LocalDateTime modifiedDate;
    
}

 

위의 코드를 확인해보시면 아시듯이 @OneToMany만 있어도 될 것 같은 데, mappedBy 속성까지 해두었습니다.

실질적으로는 객체에는 양방향 연관관계라는 것이 없습니다.

서로 다른 단방향 연관관계로 잘 묶어서 양방향인 것처럼 보이도록 하는 것이 전부입니다.

단, 데이터베이스 내에서는 외래키를 사용하여 양방향 연관관계를 맺습니다. 이를 주의하셔야합니다.

 

Entity를 단반향으로 매핑하면 참조를 하나만 사용하기 때문에 @JoinColumn에 위치한 member를 참조로 외래키를 관리하면 됩니다. 그러나 Entity를 양방향으로 매핑하면 두 곳에서 서로를 참조하게 되게 때문에 객체의 연관관계를 

관리하는 포인트는 2곳으로 늘어나게 됩니다.

 

 

그리고 양방향 연관관계를 맺게 되면 헷갈리는 부분이 하나 더 생겨납니다.

Entity를 양방향 연관관계로 설정하게 되면 객체의 참조는 2개로 늘어납니다. 하지만 외래키는 하나입니다.

이 문제를 JPA에서는 해결하고자 두 객체 연관관계 중 하나를 정해서 테이블의 외래키로 관리해야하는 데,

이것을 연관관계의 주인이라고 합니다.

 

위 Entity 같은 경우에는 Post가 주인이되어야합니다. 그래야 본인 테이블에 있는 외래키를 관리할 수 있습니다.

만약 Member에 있는 posts가 주인이 되버린다면, 물리적으로 다른 테이블의 외래키를 관리해야합니다.

따라서 posts에는 mappedBy = "member" 속성을 추가하여 주인이 아님을 설정해야합니다.

(물론 엔티티(혹은 테이블)를 하나 더 생성하여 관리해주는 방법도 있지만, mappedBy를 사용하여 관리해주는 편이

나을 것 같기에 그리 하였습니다.)

 

 

이로써 엔티티 설계 및 설명을 하였습니다.

다음 포스팅을 미리 예고하겠습니다.

다음 포스팅은 PasswordEncoder를 사용한 간단한 암호화에 대해서 포스팅하도록 하겠습니다.

(PasswordEncoder를 사용하여 비밀번호를 암호화하기 위함)

 

 

이상입니다.