댓글 구조
ManyToOne
ManyToMany..
게시글의 id -> pk (primary key)
댓글에서 게시글의 id와 연결한 값 -> fk (foregin key)..
DB
DB에 질문글을 의미하는 article 데이터를 등록한 후, 각 질문의 id를 foregin key로 하는 댓글을 등록한다.
![]() |
![]() |
Entity
getter는 지양하는 게 좋지만 일단 편의상 @Getter 어노테이션을 사용했다.
각 게시글을 의미하는 Comment 엔티티를 생성하자.
질문 글 Article 엔티티에 대하여 ManyToOne 연결을 하고 article_id를 FK로 설정한다.
@JoinColumn
@JoinColumn 어노테이션은 연결될 외래키(FK)에 대한 정보를 지정한다. 여기서 name 속성은 외래키의 이름을 지정하는 것으로 article_id로 설정되었는데, 이는 Comment 엔티티가 Article 엔티티와 관계를 맺을 때 Article 엔티티의 id 필드를 참조하는 외래키로 사용된다.
DTO
해당 코드는 CommentDto 클래스를 정의하고 Comment Entity를 기반으로 CommentDto 객체를 생성하는 메서드를 구현한 것이다.
CommentDto 클래스는 id, articleId, nickname, body 필드를 갖는데, 이는 Comment Entity의 필드와 비슷하지만 CommentDto는 API 응답에 필요한 필드만을 포함하고 있다.
해당 메서드는 static으로 선언되어 있어 후에 CommentDto.createCommentDto(comment)와 같은 형식으로 객체를 생성하지 않고 호출할 수 있다.
왜 굳이 Dto와 Entity를 분리할까?
현재 실습에서는 아니지만 Entity는 비즈니스 로직을 가지고 있을 수 있기 때문에 API 응답과 요청에서 Entity를 그대로 사용하면 비즈니스 로직이 노출될 수 있다. 반면에 D
to는 API 응답에 필요한 필드만 포함하고, 전송할 수 있다. 따라서 보안성과 유연성을 높일 수 있고 보내는 데이터를 최소화할 수 있기 때문에 서로를 분리하여 사용한다.
Repository
해당 코드는 CommentRepository 인터페이스를 정의하고 JpaRepository를 상속받아 Comment Entity에 대한 데이터 액세스를 위한 메서드를 구현한 것이다.
findByArticleId 메서드는 articledId 값을 기준으로 해당 게시글의 모든 댓글을 조회하는 기능을 가진다. @Query 어노테이션을 사용하여 SQL 쿼리문을 직접 작성하여 DB에 접근한다.
여기서 쿼리문을 직접 사용하고 있는데 내가 소싯적 보안 공부를 할 때 배운 SQL 인젝션 공격을 당할 위험이 있기 때문에 지양하자.
CrudRepository vs JpaRepository
둘 다 Spring Data JPA에서 제공하는 인터페이스로, 모두 일반적인 CRUD(Create, Read, Update, Delete) 작업을 수행하기 위한 메서드를 제공한다.
차이점
- 기본적으로 제공하는 메서드 수
- CrudRepository는 기본적으로 CRUD 메서드 4개를 제공한다. (save(), findById(), findAll(), deleteById())
- JpaRepository는 CrudRepository가 제공하는 4개의 메서드 외에도 추가적으로 flush(), getOne(), saveAndFlush()와 같은 메서드를 제공한다.
- Persistence Context 관리 방식
- CrudRepository는 각각의 메서드가 실행될 때마다 새로운 Persistence Context를 생성한다. 이는 각각의 메서드 호출이 별개의 트랜잭션으로 처리되는 경우 유용합니다.
- JpaRepository는 모든 메서드가 하나의 Persistence Context 내에서 실행된다. 이는 여러 메서드 호출이 하나의 트랜잭션 내에서 실행되는 경우 유용하다.
Persistence Context
Persistence Context는 영속성 컨텍스트라고도 불리며 JPA에서 엔티티들의 상태를 보관하고 있는 공간을 의미한다. 이 공간은 JPA가 관리하는 엔티티들의 생명주기를 관리한다.
영속성 컨텍스트는 JPA가 엔티티를 조회할 때 생성되고, 엔티티의 상태 변화를 감지해 Transaction이 커밋될 때 해당 엔티티의 상태를 DB에 동기화한다.
즉, JPA에서 엔티티의 변경사항은 먼저 영속성 컨테스트에 저장된 후, Transaction이 커밋되는 시점에 DB에 반영된다.
또한 동등성(identity)과 동등성(equality)을 보장한다.
동일성은 같은 객체인지 아닌지를 판단하며,
동등성은 DB에서 조회한 엔티티와 메모리에 있는 엔티티가 같은지 판단한다.
따라서 영속성 컨텍스트는 엔티티의 중복 저장을 방지하고, 성능과 일관성을 유지한다.
Service
Comment와 Article의 DB에 접근해야 하기 때문에 CommentRepository와 ArticleRepository를 의존성 주입.
비즈니스 로직을 구현한 Service 부분이다.
해당 코드의 comments 메서드를 살펴보자.
1. commentRepository의 findByArticleId 메서드를 통해 매개변수로 받은 articleId를 id로 가지는 엔티티의 댓글들을
List <Comment> comments에 담아 온다.
2. comments에 저장된 엔티티 형태의 댓글들을 Dto로 변환해 주기 위해 List <CommentDto> dtos를 선언하고
for 문으로 데이터를 하나하나 변환해 준다.
복잡하고 가독성이 떨어지는 for문 대신에 stream 문법을 통해 간편하게 구현할 수 있다.
Controller
마지막으로 Controller를 통해 get 요청을 통한 응답을 처리해 주자.
id를 '4'로 가지는 article에 달린 댓글을 모두 가져오는 get 요청이 잘 작동한다.
'Spring Boot' 카테고리의 다른 글
[Spring Boot] 테스트 코드 작성 (0) | 2023.03.18 |
---|---|
[Spring Boot] Transaction (0) | 2023.03.17 |
[Spring Boot] Service (0) | 2023.03.17 |
[Spring Boot] Rest API (0) | 2023.03.17 |
[Spring Boot] 데이터 삭제하기 (0) | 2023.03.15 |