요구사항 분석
- 어떤 프로젝트든 요구사항 분석이 첫번째이다.
게시판 기능 | 회원 기능 |
- 게시글 조회 - 게시글 등록 - 게시글 수정 - 게시글 삭제 |
- 구글 / 네이버 로그인 - 로그인한 사용자 글 작성 권한 - 본인 작성 글에 대한 권한 관리 |
프로젝트에 Spring Data Jpa 적용하기
1. build.gradle에 의존성 등록
org.springframework.boot:spring-boot-starter-data-jpa
com.h2database:h2
- spring-boot-starter-data-jpa
- 스프링 부트용 Spring Data Jpa 추상화 라이브러리
- 스프링 부트 버전에 맞춰 자동으로 JPA관련 라이브러리들의 버전을 관리해준다
- h2
- 인메모리 관계형 데이터베이스이다
- 별도의 설치가 필요 없이 프로젝트 의존성만으로 관리할 수 있다
- 메모리에서 실행되기 때문에 애플리케이션을 재시작할 때마다 초기화된다는 점을 이용하여 테스트 용도로 많이 사용
- 이 책에서는 JPA의 테스트, 로컬 환경에서의 구동에서 사용할 예정
2. domain 패키지 생성
- domain 패키지 : 도메인을 담을 패키지(게시글, 댓글, 회원, 정산, 결제 등 소프트웨어에 대한 요구사항 혹은 문제 영역)
- 기존에 Mybatis와 같은 쿼리 매퍼를 사용했다면 dao 패키지가 떠오르지만, dao 패키지와는 결이 조금 다르다.
- 기존 spring에서는 mybatis 쿼리를 xml에 담고 클래스에는 오로지 쿼리의 결과만을 담았었던 일들을 모두 도메인 클래스라고 불리는 곳에서 해결
3. posts 패키지와 Posts 클래스를 만든다
- @Entity : JPA의 어노테이션
- @Getter, @NoArgsContructor 롬복의 어노테이션
- Posts 클래스는 실제 DB의 테이블과 매칭될 클래스이며 보통 Entity클래스 라고 한다.
- JPA를 사용하면 DB 데이터에 작업할 경우 실제 쿼리를 날리기보다는, 이 Entity 클래스의 수정을 통해 작업한다
코드 설명
- @Entity
- 테이블과 링크될 클래스임을 나타낸다
- 기본값으로 클래스의 카멜케이스 이름을 언더스코어 네이밍(_)으로 테이블 이름을 매칭한다.
- ex) SalesManager.java -> sales_manager table
- @Id
- 해당 테이블의 PK 필드를 나타낸다.
- @GeneratedValue
- PK의 생성 규칙을 나타낸다.
- 스프링 부트 2.0에서는 GenerationType.IDENTITY 옵션을 추가해야만 auto_increment가 된다.
- 스프링 부트 2.0 버전과 1.5 버전의 차이는 https://jojoldu.tistory.com/295예정
- @Column
- 테이블의 칼럼을 나타내며 굳이 선언하지 않더라도 해당 클래스의 필드는 모두 컬럼이 된다.
- 사용하는 이유 : 기본값 외에 추가로 변경이 필요한 옵션이 있으면 사용
- 문자열의 경우 VARCHAR(255)가 기본값인데, 사이즈를 500으로 늘리고 싶거나(ex)title), 타입을 변경하고 싶거나 (ex:content)등의 경우에 사용
- @NoArgsConstructor
- 기본 생성자 자동 추가
- public Posts(){}과 같은 효과
- @Getter
- 클래스 내 모든 필드의 Getter 메소드를 자동완성
- @Builder
- 해당 클래스의 빌더 패턴 클래스를 생성
- 생성자 상단에 선언 시 생성자에 포함된 필드만 빌더에 포함
- 특이점
- setter 메소드가 없다.
- 자바빈 규약을 생각하면서 getter/setter를 무작정 생성하는 경우가 있다.
- 해당 클래스의 인스턴스 값들이 언제 어디에서 변해야 하는지 코드상으로 명확하게 구분할 수가 없어, 차후 기능 변경 시 정말 복잡해지기 때문
- 해당 필드의 값 변경이 필요하면 명확히 그 목적과 의도를 나타낼 수 있는 메소드를 추가해야만 한다.
- 잘못된 사용 예
public class Order{
public void setStatus(boolean status){
this.status = status;
}
}
public void 주문서비스의_취소이벤트(){
order.setStatus(false);
}
- 올바른 사용 예
public class Order{
public void cancleOrder(){
this.status = false;
}
}
public void 주문서비스의_취소이벤트(){
order.cancleOrder();
}
setter를 써서 값을 바꾸는게 아니라 메소드를 통해 값을 변경한다.
- Setter가 없는 상황에서 어떻게 값을 채워 DB에 삽입(insert)할 수 있을까?
- 기본적인 구조 : 생성자를 통해 최종 값을 채운 후 DB에 삽입하는 것, 값 변경이 필요한 경우 해당 이벤트에 맞는 public 메소드를 호출하여 변경하는 것을 전제로 한다.
- 이 책에서는 @Builder를 통해 제공되는 빌더 클래스를 사용한다.
- 생성자와 빌더 둘다 생성 시점에 값을 채워주는 역할은 똑같다.
- 다만, 생성자의 경우 지금 채워야 할 필드가 무엇인지 명확히 지정할 수 없다.
- 예를들어 다음과 같은 생성자가 있다면 개발자가 new Example(b,a)처럼 a와 b의 위치를 변경해도 코드를 실행하기 전까지는 문제를 찾을 수가 없다.
public Example(String a, String b){
this.a = a;
this.b = b;
}
- 하지만 빌더를 사용하면 다음과 같이 어느 필드에 어떤 값을 채워야 할지 명확하게 인지할 수 있다.
Example.builder()
.a(a)
.b(b)
.build();
- Posts클래스 생성이 끝이 나면 Posts클래스로 Database를 접근하게 해줄 JpaRepository를 생성한다.
4. PostsRepository 생성
- 보통 ibatis, mybatis 등에서 DAO라고 불리는 DB Layer 접근자
- JPA에서는 Repository라고 부르며 인터페이스로 생성한다.
- 단순히 인터페이스를 생성 후, JpaRepository<Entity 클래스, PK 타입>를 상속하면 기본적인 CRUD 메소드가 자동으로 생성
- @Repository를 추가할 필요도 없다.
- 주의할 점 : Entity클래스와 기본 Entity Repository는 함께 위치해야 하는 점
- 둘은 아주 밀접한 관계, Entity클래스는 기본 Repository 없이는 제대로 역할을 할 수 없다.
- 나중에 프로젝트 규모가 커져 도메인별로 프로젝트를 분리해야 한다면 이때 Entity 클래스와 기본 Repository는 함께 움직여야 하므로 도메인 패키지에서 함께 관리한다.
5. Spring Data JPA 테스트코드 작성하기
- test 디렉토리에 domain.posts 패키지를 생성하고, 테스트 클래스는 PostsRepositoryTest란 이름으로 생성
- @After
- Junit에서 단위 테스트가 끝날 때마다 수행되는 메소드를 지정
- 보통은 배포 전 전체 테스트를 수행할 때 테스트간 데이터 침범을 막기 위해 사용한다.
- 여러 테스트가 동시에 수행되면 테스트용 데이터베이스인 H2에 데이터가 그대로 남아 있어 다음 테스트 실행 시 테스 실패
- postRepository.save
- 테이블 posts에 insert/update 쿼리를 실행한다.
- id 값이 있다면 update, 없다면 insert 쿼리 실행
- postsRepository.findAll
- 테이블 posts에 있는 모든 데이터를 조회해오는 메소드
- 실행된 쿼리를 로그로 보려면 ?
- src/main/resources 디렉토리 아래에 application.properties 파일을 생성
spring.jpa.show_sql=true
이 부분을 입력하면 콘솔에서 쿼리 로그를 확인할 수 있다.
- create_date와 modified_date는 이미 실습을 진행한 상태이기 때문에 콘솔에 나와있다.
- 원래는 H2 쿼리 문법이 적용 되어 있지만 미리 application.properties에 mysql버전으로 로그가 출력되게
spring.jpa.properties.hibernate.dialect=org.hibernate.\
dialect.MySQL5InnoDBDialect
spring.h2.console.enabled=true
- 이 부분을 추가해주었고, 정상적으로 mysql version으로 로그를 볼 수 있다.
'스프링부트와 AWS로 혼자 구현하는 웹 서비스' 카테고리의 다른 글
9. 머스테치로 화면 구성하기 (0) | 2022.01.22 |
---|---|
8. 등록/수정/조회 API 만들기 (0) | 2022.01.19 |
6. JPA로 데이터베이스 다뤄보자 (0) | 2022.01.18 |
5. Hello Controller 테스트 코드 작성하기 (0) | 2022.01.17 |
4. 스프링부트에서 테스트 코드를 작성하자 (0) | 2022.01.17 |