스프링부트로 웹 페이지 만들어보기

이번엔 글 작성 기능에 대한 백엔드 코드에 대해서 기록해 볼 것입니다.

전에 작성한 글을 통해 이해한 스프링부트 구조에 맞게, 기능을 담당하는 서비스와 DB 연결의 중심이 되는 레파지토리, DB 테이블을 뜻하는 엔티티까지 작성하고 컨트롤러로 연결하여 마무리 해보겠습니다.

 

1. 엔티티 작성

//BoardEntity.java
package com.example.demo.entity;

import com.example.demo.dto.BoardDTO;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "board_table_2025")
public class BoardEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String boardWriter;

    @Column
    private String boardPass;

    @Column
    private String boardTitle;

    @Column
    private String boardContents;

    @Column
    private int boardHits;

    public static BoardEntity toSaveEntity(BoardDTO boardDTO) {
        BoardEntity boardEntity = new BoardEntity();
        boardEntity.boardWriter = boardDTO.getBoardWriter();
        boardEntity.boardPass = boardDTO.getBoardPass();
        boardEntity.boardTitle = boardDTO.getBoardTitle();
        boardEntity.boardContents = boardDTO.getBoardContents();
        boardEntity.boardHits = 0;
        return boardEntity;
    }
}

 

데이터베이스의 테이블을 정의해주는 파일입니다.

@Entity 어노테이션으로 이 자바 파일이 엔티티 파일이라는 것을 스프링부트에 알려줍니다.

엔티티 파일은 테이블의 역할을 하는 파일이기에, 외부에서 이 파일에 접근하여 엔티티의 값을 변경하지 말라고 권고한다합니다.

때문에 Getter는 만들어두지만, Setter를 만들어두지 않음으로써 이 엔티티에 접근하는 것을 미리 방지하겠습니다.

 

@NoArgsConstructor 어노테이션을 통하여 생성자 역시 아무 클래스에서 객체로 만들어 쓰지 못 하도록 기본 생성자를 두되 접근제어를 추가하여 엔티티를 보호하였습니다.

이거저거 찾아보니 권고사항이다 라고 해서 위와 같이 만들어보았는데, 자세한 사항까지는 아직 공부하지 못 했습니다.

차차 더 만들어가면서 공부해보아야겠네요.

 

이후 @Table 어노테이션으로 테이블 이름을 선언해주고, @Id를 통해 PK를 정의해주었습니다.

@Column 어노테이션으로 테이블의 컬럼들을 차례차례 만들어주었습니다.

 

static으로 선언한 toSaveEntity 메서드는 DTO에 담겨있는 값을 Entity에 옮겨주는 역할을 합니다.

또한 위에서 설명한것 처럼 다른 클래스에서 Entity에 대해 객체를 만들어서 쓰지 못하게 하였기에, 클래스의 메서드를 통하여 접근하도록 만들어 보았습니다.

 

2. 서비스 작성

//BoardService.java
package com.example.demo.service;

import com.example.demo.dto.BoardDTO;
import com.example.demo.entity.BoardEntity;
import com.example.demo.repository.BoardRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class BoardService {
    private final BoardRepository boardRepository;

    public void save(BoardDTO boardDTO) {
        BoardEntity boardEntity = BoardEntity.toSaveEntity(boardDTO);
        boardRepository.save(boardEntity);
    }
}

 

@Service 어노테이션을 통하여 이 파일이 서비스의 역할을 한다고 스프링부트에 알려주었습니다.

글 저장에 대한 기능을 만들어주었습니다.

BoardEntity 클래스의 toSaveEntity 메서드에 접근하여 사용하였습니다.

boardRepository.save(boardEntity); 라고 작성된 코드가 레파지토리를 사용한다는 코드입니다.

아직은 기능이 저장 밖에 없기에 짧게 작성되었네요.

 

3. 레파지토리 작성

//BoardRepository.java
package com.example.demo.repository;

import com.example.demo.entity.BoardEntity;
import org.springframework.data.jpa.repository.JpaRepository;

public interface BoardRepository extends JpaRepository<BoardEntity, Long> {
}

 

서비스가 레파지토리를 사용하여 DB에 데이터 저장을 요청하도록 작성하였으니, 그 중간을 담당하는 레파지토리를 작성해줘야겠네요.

굉장히 짧아보여서 처음엔 의아했지만, 찾아보니 많은 기능이 함축된 코드였습니다.

interface로 선언됨에 따라 직접 구현하는게 아닌 JPA가 자동으로 구현체를 만들어줍니다.

특별히 쿼리를 작성할 것 없이 스프링이 내부적으로 처리해준다네요.

extends 를 통해 JpaRepository를 상속하고 있습니다.

 

JpaRepositorysms 스프링에서 제공하는 인터페이스로, DB에 필요한 기본 메서드들을 다 만들어 둔 모음집 같은겁니다.

때문에 특별히 작성할 것 없이 다양한 메서드들을 자동으로 제공해준다네요.

뒤에 적인 <BoardEntity, Long>은 각각 어떤 엔티티와 연결된 건지, 뒤는 엔티티의 PK(기본키)의 자료형을 뜻합니다.

위에서 엔티티에서 id를 만들때 Long 자료형으로 선언해줬죠, 그에 맞게 작성해주었습니다.

 

거의 대부분의 기능을 직접 작성 할 것 없이 스프링이 해줘서, 코드가 매우 간결해졌습니다.

이 상태에서 컨트롤러가 요청을 받아 서비스가 이를 실행해주고 레파지토리가 쿼리를 자동 생성하여 저장하는 쿼리를 DB에 전달합니다. 정확힌 JPA가 내부에서 쿼리를 만들어준다고하네요.

그 다음 연결된 DB에 쿼리가 실행되어, 결과적으로 요청받은 값들이 DB에 저장됩니다.

 

이번엔 엔티티와 서비스, 레파지토리까지 작성해보았습니다.

레파지토리를 작성할 때 뭔가 허전한 느낌을 많이 받았는데, 찾아보니 사실 내부에서 다 해주는 거였더라고요.

저 한줄로 많은 기능이 뒤에서 동작해준다니 신기한 기분이었습니다.

 

다음에는 글 목록 기능을 추가해보고 정리해보겠습니다.

 

+ Recent posts