[SpringBoot] 2024 게시판 만들기 실습 ③ - Entity, DTO

SihoonCho·2024년 11월 21일
0
post-thumbnail

※ 읽기에 앞서


본 시리즈는 작성자의 이해와 경험을 바탕으로 실습 위주의 설명을 제공하고자 작성되었습니다.
실습 중심의 이해를 목표로 작성되었기 때문에, 다소 과장되거나 생략된 부분이 있을 수 있습니다.
따라서, 이론적으로 미흡한 부분이 있을 수 있는 점에 유의하시고 양해 부탁드립니다.

또한, Spring Boot 기반의 Backend 개발에 중점을 두고 설명하고 있으므로,
Frontend와 관련된 내용은 별도의 참고자료를 검색/활용하실 것을 권장드립니다.

본 예제에서는 LombokJPA를 사용한 실습을 설명하고 있으므로,
만약 설치되어있지 않다면 미리 세팅하고 오셔야 오류없이 실행됩니다.


📌 패키지 구조


├── src
│   ├── main
│   │   ├── java
│   │   │   └── com.companyname.projectname
│   │   │       ├── post							// 패키지 추가
│   │   │       │   ├── dto						// 패키지 추가
│   │   │       │   │   ├── PostCreateRequestDto.java	// 클래스 추가
│   │   │       │   │   ├── PostUpdateRequestDto.java	// 클래스 추가
│   │   │       │   │   ├── PostDetailResponseDto.java	// 클래스 추가
│   │   │       │   │   └── PostListResponseDto.java		// 클래스 추가
│   │   │       │   └── model					// 패키지 추가
│   │   │       │       └── Post.java					// 클래스 추가
│   │   │       └── ProjectNameApplication.java
│   │   └── resources
│   └── test

📌 Entity


사실 Entity는 특별히 대단할 것이 없습니다.

Entity는 테이블 정의이자 데이터의 단위인데
'Java에서는 이것을 Class라고 합니다.'

Java를 좀 공부해보셨던 분들이라면, 이 말을 듣고 아마 이런 생각을 하셨을겁니다.

"아, '데이터의 정의`는 'Class' 였지!"


📖 Post.java


package com.companyname.projectname.post.model;

import com.companyname.projectname.post.dto.PostRequestDto;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import java.time.LocalDateTime;

@Entity
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    private String content;

    @CreationTimestamp
    private LocalDateTime createdDate;
    @UpdateTimestamp
    private LocalDateTime updatedDate;

    // Method, for updating data
    public Post update(PostRequestDto requestDto) {
        this.title = requestDto.getTitle();
        this.content = requestDto.getContent();
        return this;
    }
}
  • @Entity: 이 클래스가 JPA 엔티티임을 명시
  • @Getter: 클래스의 모든 필드에 대해 Getter 메서드를 자동 생성
  • @Builder: 빌더 패턴을 통해 객체 생성 지원
  • @NoArgsConstructor: 매개변수가 없는 기본 생성자 자동 생성
  • @AllArgsConstructor: 모든 필드를 매개변수로 갖는 생성자 자동 생성
    변수명을 기준으로 매개변수를 필드에 자동으로 초기화
  • @Id: 해당 필드가 엔티티의 기본 키(Primary Key)임을 지정
  • @GeneratedValue: 데이터베이스에서 기본 키가 자동으로 생성되도록 설정
    • (strategy = GenerationType.IDENTITY):
      데이터베이스의 AUTO_INCREMENT 기능을 사용하여 기본 키를 생성
  • @CreationTimestamp: 엔티티가 생성될 때 자동으로 현재 시간을 설정
  • @UpdateTimestamp: 엔티티가 업데이트될 때 자동으로 현재 시간을 설정

각각의 @Annotation은 이를 사용하거나, 사용하지 말아야 할 이유가 존재합니다.

  • @Builder는 추후 RequestDto -> Entity 클래스로 변환하는데 사용한다.
  • 데이터베이스와 직접 연결되는 엔티티는, @Setter 사용을 지양한다.
  • 수정이 필요한 경우 필요한 데이터에 대해서 메서드로 처리한다.
  • update() 메서드는 매개변수가 RequestDto임에 주의한다.
    • 아직 구현되지 않았다면 RequestDto부터 구현한다.

@Annotation에 대한 더 자세한 정보는 구글링을 통해 알아보시기 바랍니다.
검색 키워드는 Lombok Annotation, JPA Annotation입니다.


📌 RequestDTO


각각의 @Annotation은 이를 사용하거나, 사용하지 말아야 할 이유가 존재합니다.

  • @Data: 간단한 데이터 클래스 작성을 위한 종합적인 기능 제공
    • @Getter, @Setter, @ToString 포함
    • @EqualsAndHashCode, @RequiredArgsConstructor 포함
  • @Builder: 빌더 패턴을 통해 객체 생성 지원
  • @NoArgsConstructor: 매개변수가 없는 기본 생성자 자동 생성
  • @AllArgsConstructor: 모든 필드를 매개변수로 갖는 생성자 자동 생성
    변수명을 기준으로 매개변수를 필드에 자동으로 초기화
  • DTO는 비교적 데이터 수정에 관대하므로, @Data를 사용해 중복 코드를 감소
  • toEntity() 메서드는 Post.java 엔티티의 @Builder 패턴을 사용해,
    RequestDto -> Entity 클래스로 변환한다.

📖 PostCreateRequestDto.java


package com.companyname.projectname.post.dto;

import com.companyname.projectname.post.model.Post;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PostCreateRequestDto {
    private String title;
    private String content;

    public Post toEntity() {
        return Post.builder()
                .title(this.title)
                .content(this.content)
                .build();
    }
}

데이터베이스에 아직 데이터가 없는 상태이므로 Long id를 기입하지 않습니다.


📖 PostUpdateRequestDto.java


package com.companyname.projectname.post.dto;

import com.companyname.projectname.post.model.Post;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PostUpdateRequestDto {
    private Long id;
    private String title;
    private String content;

    public Post toEntity() {
        return Post.builder()
                .id(this.id)
                .title(this.title)
                .content(this.content)
                .build();
    }
}

데이터베이스에 존재하는 데이터를 수정하는 것이므로, Long id를 기입합니다.


📌 ResponseDTO


각각의 @Annotation은 이를 사용하거나, 사용하지 말아야 할 이유가 존재합니다.

  • @Data: 간단한 데이터 클래스 작성을 위한 종합적인 기능 제공
    • @Getter, @Setter, @ToString 포함
    • @EqualsAndHashCode, @RequiredArgsConstructor 포함
  • @Builder: 빌더 패턴을 통해 객체 생성 지원
  • @NoArgsConstructor: 매개변수가 없는 기본 생성자 자동 생성
  • @AllArgsConstructor: 모든 필드를 매개변수로 갖는 생성자 자동 생성
    변수명을 기준으로 매개변수를 필드에 자동으로 초기화
  • DTO는 비교적 데이터 수정에 관대하므로, @Data를 사용해 중복 코드를 감소
  • 생성자는, 데이터베이스로부터 읽은 Entity 데이터를 DTO로 변환하는데 사용
    Entity -> RequestDto 클래스로 변환한다.

📖 PostListResponseDto.java


package com.companyname.projectname.post.dto;

import com.companyname.projectname.post.model.Post;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PostListResponseDto {
    private Long id;
    private String title;
    private LocalDateTime createdDate;
    private LocalDateTime updatedDate;

    // Custom Constructor, convert data from entity to dto
    public PostListResponseDto(Post entity) {
        this.id = entity.getId();
        this.title = entity.getTitle();
        this.createdDate = entity.getCreatedDate();
        this.updatedDate = entity.getUpdatedDate();
    }
}

게시글의 목록을 조회할 때, content(내용)은 불필요하므로 필드에 기입하지 않습니다.


📖 PostDetailResponseDto.java


package com.companyname.projectname.post.dto;

import com.companyname.projectname.post.model.Post;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PostDetailResponseDto {
    private Long id;
    private String title;
    private String content;
    private LocalDateTime createdDate;
    private LocalDateTime updatedDate;

    // Custom Constructor, convert data from entity to dto
    public PostDetailResponseDto(Post entity) {
        this.id = entity.getId();
        this.title = entity.getTitle();
        this.content = entity.getContent();
        this.createdDate = entity.getCreatedDate();
        this.updatedDate = entity.getUpdatedDate();
    }
}

게시글을 상세 조회할 때, content(내용)이 필요하므로 필드에 기입합니다.



본 시리즈는 작성자의 이해와 경험을 바탕으로 실습 위주의 설명을 제공하고자 작성되었습니다.
실습 중심의 이해를 목표로 작성되었기 때문에, 다소 과장되거나 생략된 부분이 있을 수 있습니다.
따라서, 이론적으로 미흡한 부분이 있을 수 있는 점에 유의하시고 양해 부탁드립니다.

또한, Spring Boot 기반의 Backend 개발에 중점을 두고 설명하고 있으므로,
Frontend와 관련된 내용은 별도의 참고자료를 검색/활용하실 것을 권장드립니다.
profile
개발을 즐길 줄 아는 백엔드 개발자

0개의 댓글