이전 JPA 2번 게시물에서는 N:1 (Board : Member) 에 대한 예제에 관해서 Entity 구조에 대해서만 다루었다.
이번 게시물에서는 Board / Member 테이블 사이에 있어서 Like 테이블을 추가하여 좋아요기능을 추가해보려고 한다.
어떤 사용자가 특정 게시물에 좋아요를 누르게 되면 Like 테이블에 어떤 사용자가 어떤 게시물에 좋아요를 눌렀는지 데이터가 추가된다.
그리고 그 테이블을 기반으로
1. 특정 사용자가 어떤 게시물들에 좋아요를 눌렀는지에 대해서 조회할 수 있도록하고
2. 특정 게시물이 어떤 사용자들로 부터 좋아요를 받았는지를 조회할 수 있도록 한다.
구조는 다음과 같다.
기존에 Board - Member에 대해서만 다루고 있었다면 지금은 중계테이블 처럼
Board - Like - Member 구조가 되었다.
ex) 1번 사용자가 1번 2번 3번 게시물에 좋아요를 누르면 Like 테이블에 1-1,1-2,1-3 과 같이 데이터가 등록되고,
1번사용자가 어떤 게시물에 대해서 좋아요를 눌렀는지는 Like 테이블에서 1번 사용자에 대한 여러 개의 게시물을 조회하면 된다.
ex) 1번 게시물에 1번 2번 3번 사용자가 좋아요를 눌렀다면 Like 테이블에 1-1, 2-1, 3-1 과 같이 데이터가 등록되고,
1번 게시물에 어떤 사용자들이 좋아요를 눌렀는지는 Like 테이블에서 1번 게시물에 대한 여러 개의 사용자를 조회하면 된다.
일단 구조를 다루는 테이블 생성에 대한 Entity에 대해서 알아보자
[MemberEntity]

@Entity 어노테이션을 통해서 해당 클래스가 영속성 컨텍스트를 다루는 Entity 클래스임을 명시하고,
@Table 어노테이션을 통해서 생성될 테이블 이름을 지정한다.
그리고 작업에 필요한 필드값을 참조하고 브라우저 요청으로부터 데이터를 받아올때 JSON 파싱을 위한
@Getter 어노테이션을 사용하였다.
필드는 no, userId, userPwd, userNick, delYn, createAt, updateAt이 있고 해당 게시물에서 가장 중요한 likeEntityList라는 필드가 존재한다. 해당 Table에 기본키 설정으로 no에는 @Id 어노테이션과 @GeneratedValue 어노테이션을 통해서 Seq가 1씩 오르도록 설정하였다.
그리고 likeEntityList에는 @OneToMany 어노테이션이 적혀있는데 여기서는 각 MemberEntity에 대해서 해당 사용자가
어떤 게시물에 대해서 좋아요를 눌렀는지에 대한 좋아요리스트를 받아오는 필드이다.
mappedBy 옵션을 채우는 것은 필수적인데, LikeEntity 클래스 내에서 어떤 필드와 연관지어서 OneToMany 관계를 이루는지 설정해주어야한다. (이때 필드명을 정확히 동일하게 적어주어야함)
추가적으로 orphanRemoval과 cascade 옵션이 있는데 고아Entity가 생긴경우 자동삭제와 같은 기능을 도와준다.

MemberEntity 기본 생성자에 Entity 객체가 생성될때 기본적으로 설정되어야 할 속성에 대해서 설정해주고 있다. delYn는 소프트 딜리트 필드로 생성시 기본적으로 N이어야 하고, 생성일자가 적혀있을 createdAt 에는 LocalDateTime 클래스의 now() 메서드를 통해서 값을 채워준다.
그리고 from 메서드는 dto로 받아온 객체를 영속성 컨텍스트로 다루기 위한 Entity 객체로의 형변환 해주기 위한 메서드이다.
[BoardEntity]

MemberEntity에서 설명한 어노테이션은 제외하고 중요한 어노테이션에 대해서만 보도록 하자.
일단 BoardEntity에 writer 필드가 존재한다. 해당 필드에 어노테이션으로 @ManyToOne과 JoinColumn이 달려있다.
게시물 마다 작성자가 존재하므로 테이블간의 JOIN 설정을 필요로 하고
Board를 기점으로 MemberEntity는 N:1 구조이므로 @ManyToOne 어노테이션을 사용한다. 그리고 JoinColumn 어노테이션을 통해서 해당 필드가 테이블 생성시에 어떤 필드명을 가지도록 할껀지 설정한다. 조인 설정 시에는 MemberEntity의 기본키 값이 writer 필드에 받아와지므로, writerNo이라는 이름으로 필드명을 설정하였다.
fetch 옵션의 경우 LAZY 타입과 EAGER 타입을 설정할 수 있는데 지연로딩 방식과 즉시로딩 방식을 설정한 것이다.
해당 내용에 대해서는 넘어가고 다른 게시물에서 다루도록 하겠다.
그리고 아래에 추가로 @OneToMany 어노테이션의 likeEntityList가 존재한다.
게시물을 기준으로 해당 게시물에 어떤 사용자들이 좋아요를 눌렀는지를 담기위한 필드로 mappedBy 옵션에는 LikeEntity에서 필드명으로 가지고있는 boardEntity와 연관되어있으므로 boardEntity로 설정하였다.

MemberEntity와 동일하게 delYn과 createdAt 기본값 설정 및 dto로 받아온 게시물 정보에 대해서 영속성 컨텍스트로 다루기 위한 Entity 객체로의 형변환을 위한 from 메서드가 정의되어있다.
[LikeEntity]

@Table 어노테이션에 대해서 이미 다루었지만 옵션에 추가된 내용이 있다.
uniqueConstraints 두가지 이상의 필드묶음에 대해서 유니크 제약조건을 달아주는 것으로, ColumnNames 옵션으로
중괄호 안에 연관하여 유니크 제약조건을 달아주고 싶은 필드에 대해서 나열하면 된다.
Like 테이블에서는 어떤 사용자가 어떤 게시물에 좋아요를 눌렀는지에 대해서 데이터가 쌓이는 구조인데,
한 사용자가 동일한 게시물에 좋아요를 2번 누를 수 없기 때문에 1-1, 1-1과같은 데이터가 중복으로 있어서는 안된다.
그래서 UniqueConstraint 옵션을 통해서 memberNo와 boardNo 를 설정하여 위와 같은 중복이 없도록 제약조건을 설정하였다.
그리고 테이블에 1-1 1-2, 2-1 2-2 2-3, 3-1 .. 이런식으로 데이터가 쌓이는데
LikeEntity를 기준으로 MemberEntity와 BoardEntity는 N:1 관계이므로 @ManyToOne 어노테이션이 설정이 각각 되어있고
@JoinColumn을 통해서 테이블에 어떤 필드명으로 적힐지에 대해서 name 옵션이 설정되어 있다.
memberEntity와 boardEntity에 기본키인 번호가 데이터로 참조되므로 memberNo와 boardNo로 설정하였다.
아래는 from 메서드로 특정 사용자, 특정 게시물에 대한 Entity를 파라미터로 LikeEntity를 생성해서 반환하는 메서드가 정의되어있다.
'JPA' 카테고리의 다른 글
| [JPA] React 브라우저 서버 / Spring boot 서버 연동 시, 쿠키 / Session 설정 (3) (3) | 2025.08.26 |
|---|---|
| [JPA] 1 : N 구조의 외래키 설정 및 Entity 구조 알아보기 (2) (0) | 2025.08.21 |
| [JPA] JPA란 ? (1) (0) | 2025.08.20 |