백엔드/스프링 데이터 JPA

[Spring Data JPA] [1] 프로젝트 환경 설정

RE-Heat 2023. 9. 7. 21:44

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%8D%B0%EC%9D%B4%ED%84%B0-JPA-%EC%8B%A4%EC%A0%84/dashboard

 

실전! 스프링 데이터 JPA - 인프런 | 강의

스프링 데이터 JPA는 기존의 한계를 넘어 마치 마법처럼 리포지토리에 구현 클래스 없이 인터페이스만으로 개발을 완료할 수 있습니다. 그리고 반복 개발해온 기본 CRUD 기능도 모두 제공합니다.

www.inflearn.com

인프런 김영한 님의 강의를 듣고 작성한 글입니다.

 

[1] 프로젝트 생성

스프링부트 스타터 : https://start.spring.io

 

  • SpringBoot 2.7.15, Java 11 선택
  • Spring Web, Spring Data JPA, Lombok, H2 Database 추가

 

HelloController - 확인

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello(){
        return "hello";
    }
}

 

■ RUN 설정

기본 설정으로 하면 인텔리제이가 Gradle을 통해서 실행돼 테스트가 느린 경향이 있다. 따라서 이 설정을 해줘야 한다.

 

■ Lombok 설정

  • 롬복 설치 후 Annotation Processors에서 Enable annotation processing을 체크해줘야 한다.

 

[2] 라이브러리 살펴보기

■ 스프링부트 라이브러리

spring-boot-starter-web

  • spring-boot-starter-tomcat: 톰캣 (웹서버)
  • spring-webmvc: 스프링 웹 MVC

spring-boot-starter-data-jpa

  • spring-boot-starter-aop
  • spring-boot-starter-jdbc
    • HikariCP 커넥션 풀 (부트 기본)
  • hibernate + JPA: 하이버네이트 + JPA
  • spring-data-jpa: 스프링 데이터 JPA

spring-boot-starter(공통): 스프링 부트 + 스프링 코어 + 로깅

  • spring-boot
    • spring-core
  • spring-boot-starter-logging
    • logback, slf4j

 

■ 테스트 라이브러리

spring-boot-starter-test

  • junit: 테스트 프레임워크(junit5)
  • mockito: 목 라이브러리
  • assertj: 테스트 코드를 좀 더 편하게 작성하게 도와주는 라이브러리
  • spring-test: 스프링 통합 테스트 지원

 

[3] H2 데이터베이스 설치

① 다운로드 및 설치

https://www.h2database.com

 

② h2 데이터베이스 버전은 스프링 부트 버전에 맞춘다.

이 순서대로 확인하면 스프링부트 버전에 맞는 h2 database 버전을 안내해 준다.

  • 데이터베이스파일 생성방법
    • jdbc:h2:~/datajpa  (최소한번) 
    • ~/datajpa.mv.db 파일생성확인
    • 이후부터는 jdbc:h2:tcp://localhost/~/datajpa 이렇게 접속

 

[4] 스프링 데이터 JPA와 DB 설정·동작 확인

application.yml

spring:
  datasource:
    url: jdbc:h2:tcp://localhost/~/datajpa
    username: sa
    password:
    driver-class-name: org.h2.Driver

  jpa:
    hibernate:
      ddl-auto: create
    properties:
      hibernate:
        format_sql: true
         #show_sql: true


logging.level:
  org.hibernate.SQL: debug
  #org.hibernate.type: trace
  • ddl-auto: create는 애플리케이션 실행 시점에 테이블을 drop 후 생성한다.
  • org.hibernate.SQL : logger를 통해 실행된 SQL을 남긴다.

 

■ 동작확인

① Spring Data JPA 적용 전

Member 엔티티

@Entity
@Getter @Setter
public class Member {
 
    @Id @GeneratedValue
    private Long id;
    private String username;
 
    protected Member() {
    }
 
    public Member(String username) {
        this.username = username;
    }
}
  • JPA는 기본생성자가 필요하다. 함부로 못 고치게 하기 위해 protected로 지정
    • 참고로 @NoArgsConstructor(access = AccessLevel.PROTECTED) 애노테이션을 붙여도 된다.

 

MemberJpaRepository

@Repository
@RequiredArgsConstructor
public class MemberJpaRepository {
    private final EntityManager em;

    public Member save(Member member){
        em.persist(member);
        return member;
    }

    public Member find(Long id){
        return em.find(Member.class, id);
    }
}
  • EntityManger @PeersistenceContext를 붙이는 대신 생성자 주입 방식으로 해결

 

MemberJpaRepositoryTest

@SpringBootTest
@Transactional
@Rollback(false)
class MemberJpaRepositoryTest {
    @Autowired
    MemberJpaRepository memberJpaRepository;

    @Test
    public void testMember(){
        Member member = new Member("memberA");
        Member savedMember = memberJpaRepository.save(member);

        Member findMember = memberJpaRepository.find(savedMember.getId());

        assertThat(findMember.getId()).isEqualTo(member.getId());
        assertThat(findMember.getUserName()).isEqualTo(member.getUserName());
        assertThat(findMember).isEqualTo(member);
    }
}
  • 테스트 만드는 단축키는 ctrl+shift+t
  • @Transactional이 없으면 컴파일 시점에 에러가 뜬다.
  • @Rollback(false) 테스트에 @Transactional이 붙으면 DB가 자동으로 롤백돼 실행된 SQL을 볼 수 없으므로 롤백 옵션을 꺼줘야 한다.
  • isEqualTo가 테스트를 통과하는 건 영속성 컨텍스의 동일성 보장 덕분이다.

 

② Spring Data JPA 적용

 

MemberRepository - interface

public interface MemberRepository extends JpaRepository<Member, Long> {

}
  • CRUD 대부분 기능을 지원하는 JpaRepository<>를 상속받는 것을 잊지 말자!

 

MemberRepositoryTest

@SpringBootTest
@Transactional
@Rollback(value = false)
class MemberRepositoryTest {
    @Autowired
    MemberRepository memberRepository;

    @Test
    public void testMember(){
        Member member = new Member("memberA");
        Member savedMember = memberRepository.save(member);

        Member findMember = memberRepository.findById(savedMember.getId()).get();

        assertThat(findMember.getId()).isEqualTo(member.getId());
        assertThat(findMember.getUserName()).isEqualTo(member.getUserName());
        assertThat(findMember).isEqualTo(member);
    }
}
  • 기존 MemberJpaRepositoryTest처럼 save, find 등 메소드를 만들지 않아도 그대로 되는 것을 확인할 수 있다.
  • 단, find()는 findById()로 바꿔줘야 한다.
  • findById는 반환타입이 Optional<Member>이다. 왜냐면 값이 없을 수도 있기 때문이다. 하지만, 여기선 편의상 .get()으로 꺼내 사용했다.

 

■ 쿼리 파라미터 로그 남기기

① 로그에 다음을 추가하기 org.hibernate.type : SQL 실행 파라미터를 로그로 남긴다. 


② 외부라이브러리 사용
https://github.com/gavlyukovskiy/spring-boot-data-source-decorator
스프링부트를 사용하면 이 라이브러리만 추가하면 된다.

build.gradle


참고] 쿼리파라미터를 로그로 남기는 외부 라이브러리는 개발 단계에서는 편하게 사용해도 된다. 하지만 시스템 자원을 사용하므로, 운영시스템에 적용하려면 꼭 성능 테스트를 하고 사용하는 것이 좋다.