https://product.kyobobook.co.kr/detail/S000001019679
스프링 부트와 AWS로 혼자 구현하는 웹 서비스 | 이동욱 - 교보문고
스프링 부트와 AWS로 혼자 구현하는 웹 서비스 | 가장 빠르고 쉽게 웹 서비스의 모든 과정을 경험한다. 경험이 실력이 되는 순간!이 책은 제목 그대로 스프링 부트와 AWS로 웹 서비스를 구현합니다
product.kyobobook.co.kr
이제 이 책을 따라 하나씩 실습을 해볼려고 한다.
이 책의 목표는 게시판(웹 애플리케이션)을 만들어보고 이것을 AWS에 무중단 배포를 하는 것이다.
구현할 요구사항
게시판 기능
- 게시글 조회
- 게시글 등록
- 게시글 수정
- 게시글 삭제
회원 기능
- 구글 / 네이버 로그인
- 로그인한 사용자 글 작성 권한
- 본인 작성 글에 대한 권한 관리
Posts Entity 생성
게시글을 저장할 제일 기초적인 Entity를 생성해 볼 것이다.
제일 처음 domain 패키지를 만든다. 이 패키지는 도메인을 담을 패키지이다. 도메인 안에는 게시글, 댓글, 회원, 정산, 결제 등 소프트웨어에 대한 요구사항 혹은 문제영역이다.
package com.jojoidu.book.freelecspringboot2webservice.domain.posts;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Getter
@NoArgsConstructor
@Entity
public class Posts {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 500, nullable = false)
private String title;
@Column(columnDefinition = "TEXT", nullable = false)
private String content;
private String author;
@Builder
public Posts(String title, String content, String author){
this.title= title;
this.content = content;
this.author = author;
}
}
이 책을 쓰신 분은 주요 어노테이션을 클레스에 가깝게 둔다고 한다.
그 이유는 코트린 등의 새 언어 전환으로 롬복이 더 이상 필요 없는 경우 쉽게 삭제하기 위해서라고 하신다.
좋은 내용인 것 같다. 지금까지는 생각나는 순서대로 어노테이션을 설정했는다. 나도 이제부터 이렇게 설계해야 겠다.
Entity
- 테이블과 링크될 클래스임을 나타낸다.
- 기본값으로 클래스의 카멜케이스 이름을 언더스코어 네이밍으로 테이블 이름을 매칭한다.
@Id
- 해당 테이블의 PK 필드를 나타낸다
@GeneratedValue
- PK의 생성 규칙을 나타낸다.
- 스프링 부트 2.0 에서는 GenerationType.IDENTITY 옵셥을 추가해야만 auto_increment가 가능해진다.
- 내가 알기론 IDENTITY와 SEQUENCE, TABLE 이렇게 3개의 전략이 있다.
@Column
- 테이블의 칼럼을 나타내면 굳이 선언하지 않더라도 해당 클래스의 필드는 모두 칼럼이 된다.
- 사용할 때는, 기본값 외에 추가로 변경이 필요한 옵션이 있으면 사용한다.
- 문자열의 경우 VARCHAR(225)가 기본값인데, 사이즈를 500 또는 TEXT로 변경할 수 있다.
@NoArgsConstructor
- 기본 생성자 자동 추가
- public Posts() {} 와 같은 효과이다.
@Getter
- 클래스 내 모든 필드의 Getter 메소드를 자동생성
@Builder
- 해당 클래스의 빌더 패턴 클래스를 생성한다.
- 생성자 상단에 선언 시 생성자에 포함된 필드만 빌더에 포함된다.
다른 JPA수업에서도 배웠지만 Setter 메소드를 사용하는 것은 굉장히 위험한 행동이라고 한다. DB에 들어간 내용은 쉽게 바뀌면 안된다.
DB에 삽입하는 기본적인 구조는 생성자를 통해 최종값을 채운 후 DB에 삽입하는 것이며, 값 변경이 필요한 경우 해당 이벤트에 맞는 public 메소드를 호출하여 변경하는 것을 전제로 한다.(비즈니스 로직, 객체생성 메소드, 연관관계 메소드 등등)
지금까지 나는 이렇게 구현을 해왔다. 이 책에서는 @Builder를 통해 제공되는 빌더 클래스를 사용한다. 생성자나 빌더나 생성 시점에 값을 채워주는 역할은 똑같다고 한다. 생성자로 할 경우 지금 채워야 할 필드가 무엇인지 명확히 지정할 수가 없다. Builder를 사용할 경우 어느 필드에 어떤 값을 채워야할지 명확하게 인지할 수 있다.
PostRepository 생성
package com.jojoidu.book.freelecspringboot2webservice.domain.posts;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PostsRepository extends JpaRepository<Posts, Long> {
}
JpaRepository<Entity 클래스, PK 타입>을 상속하면 기본적인 CRUD 메소드가 자동으로 생성된다.
Entity와 Repository는 아주 밀접한 관계를 가지고 있다. 그러므로 도메인 패키지에서 함께 관리하는 것이 좋다.
Spring Data JPA 테스트 코드 작성하기
package com.jojoidu.book.freelecspringboot2webservice.domain.posts;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest
public class PostsRepositoryTest {
@Autowired
PostsRepository postsRepository;
@After
public void cleanup(){
postsRepository.deleteAll();
}
@Test
public void 게시글저장_불러오기() {
//given
String title = "테스트 게시글";
String content = "테스트 본문";
postsRepository.save(Posts.builder()
.title(title)
.content(content)
.author("lympsw7@gmail.com")
.build()
);
//when
List<Posts> postsList = postsRepository.findAll();
//then
Posts posts = postsList.get(0);
assertThat(posts.getTitle()).isEqualTo(title);
assertThat(posts.getContent()).isEqualTo(content);
}
}
@After
- Junit에서 단위 테스트가 끝날 때마다 수행되는 메소드를 지정
- 보통은 배포 전 전체 테스트를 수행할 때 테스트간 데이터 침범을 막기 위해 사용한다.
- 여러 테스트가 동시에 수행되면 테스트용 데이터베이스인 H2에 데이터가 그대로 남아 있어 다음 테스트 실행 시 테스트가 실패할 수 있다.
@postsRepository.save
- 테이블 posts에 insert/update 쿼리를 실행한다.
- id 값이 있다면 update가, 없다면 쿼리가 실행된다.
@postsRepository.findAll
- 테이블 posts에 있는 모든 데이터를 조회해오는 메소드이다.
나는 Test를 만들 때, Live Templates를 설정했다. 그래서 test를 치면 자동으로 @Test 하고 밑에 메소드 형태가 만들어진다. 굉장히 유요하므로 사용하면 좋다.
실행
당연히 성공했다. 이제 SQL을 살펴봐야 한다.
제일처음 save를 할 때 insert문이 실행 된 것을 볼 수 있다.
그 후 findAll을 했기 때문에 모든 post를 찾아본다.
그리고 list로 저장한 다음에 다음 test를 실행한다.
그리고 나서 select를 한번 더한다. select를 왜 한번 더하는 걸까??
그건 @After로 설정한 data를 모두 지워주는 메서드를 실행했기 때문이다.
이번에는 가볍게 JPA를 테스트해보았다!!
'혼자하는 프로젝트 > 스프링 부트로 구현한 웹' 카테고리의 다른 글
머스테치로 화면 구성하기(2) 등록, 조회 (0) | 2023.03.03 |
---|---|
머스테치로 화면 구성하기(1) (0) | 2023.03.03 |
JPA를 사용한 게시판 구현(2) - 등록/수정/조회 API 만들기 (1) | 2023.02.28 |
스프링 부트 JPA를 사용해야하는 이유 (0) | 2023.02.27 |
스프링 부트에서 테스트 코스 작성하기 (0) | 2023.02.26 |