1. 프로젝트 생성
이 링크에서 스프링 프로젝트를 편리하게 생성할 수 있다. 아래처럼 설정한 뒤 생성한다.
Project: Gradle - Groovy
Language: Java
Spring Boot: 3.x.x
Packaging: Jar
Java: 17 || 21
Dependencies: Spring Web, Thymeleaf, Spring Data JPA, H2 Database, Lombok, Validation
build.gradle에서 dependencies를 아래와 같이 작성하자.
- JUnit4 추가 코드를 입력하지 않으면 JUnit5로 동작한다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
//JUnit4 추가
testImplementation("org.junit.vintage:junit-vintage-engine") {
exclude group: "org.hamcrest", module: "hamcrest-core"
}
}
롬복을 적용하기 위해 [Settings]에서 Annotation Processors을 검색한 뒤 [Enable Annotation Processing]을 체크하고 IntelliJ를 재시작한다.
2. 라이브러리 살펴보기
스프링은 build.gradle의 dependencies에 implement 된 것들이 의존하는 모든 라이브러리를 자동으로 불러들인다. 스프링 부트가 지원하는 라이브러리는 스프링 부트 버전에 맞게 모두 세팅을 해둔다. IntelliJ의 Local Terminal에서 아래 명령어를 입력하면 dependencies의 구조를 확인할 수 있다.
$ ./gradlew dependencies --configuration compileClasspath
스프링 부트 라이브러리
spring-boot-starter-web
- spring-boot-starter-tomcat: 톰캣 (웹서버)
- spring-webmvc: 스프링 웹 MVC
spring-boot-starter-thymeleaf: 타임리프 템플릿 엔진 (View)
spring-boot-starter-data-jpa
- spring-boot-starter-aop
- spring-boot-starter-jdbc
- HikariCP 커넥션 풀 (스프링 부트 2.0부터 기본으로 설정됨)
- 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: 테스트 프레임워크
- mockito: 목 라이브러리
- assertj: 테스트 코드를 좀 더 편하게 작성하도록 도와주는 라이브러리
- spring-test: 스프링 통합 테스트 지원
핵심 라이브러리
- 스프링 MVC
- 스프링 ORM
- JPA, 하이버네이트
- 스프링 데이터 JPA
기타 라이브러리
- H2 데이터베이스 클라이언트
- 커넥션 풀: 스프링 부트 기본은 HikariCP
- WEB(thymeleaf)
- 로깅 SLF4J & LogBack
- 테스트
참고
스프링 데이터 JPA는 스프링과 JPA를 먼저 이해하고 사용해야 하는 응용 기술이다.
3. View 환경 설정
타임리프 템플릿 엔진에 대한 설명은 이 링크에서 확인할 수 있다.
참고
스프링 공식 튜토리얼
스프링부트 메뉴
스프링 부트 thymeleaf viewName 매핑 방법은 아래와 같다.
- resources:templates/ + {ViewName} + .html
thymeleaf 템플릿 엔진이 동작하는지 확인하기 위해 간단한 Controller와 html 파일을 만든다. /hello 경로로 GET 요청이 들어오면 SSR(서버 사이드 렌더링)을 통해 hello.html 화면이 보이게 된다.
- HelloController (위치: jpabook/jpashop/HelloController)
@Controller
public class HelloController {
@GetMapping("hello")
public String hello(Model model) {
model.addAttribute("data", "hello!!");
return "hello";
}
}
- hello.html (위치: resources/templates/hello.html)
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Hello</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'안녕하세요. ' + ${data}" >안녕하세요. 손님</p>
</body>
</html>
정적 리소스도 잘 동작하는지 확인하기 위해 index.html 파일을 만든다.
- index.html (위치: resources/static/index.html)
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Hello</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'안녕하세요. ' + ${data}" >안녕하세요. 손님</p>
</body>
</html>
참고
spring-boot-devtools 라이브러리를 추가하면 html 파일을 컴파일만 해주면 서버 재시작 없이 View 파일이 변경된 걸 확인할 수 있다.
IntelliJ 컴파일 방법: [menu - build - Recompile]
4. H2 데이터베이스 설치
H2 DB는 개발이나 테스트 용도로 가볍고 편리한 DB와 웹 콘솔 화면을 제공한다. 이 링크에서 2.1.214 버전 이상의 H2 DB를 다운로드하면 된다.
H2 폴더를 다운로드하고 터미널에서 /bin으로 이동해 ./h2.bat을 입력하면 자동으로 H2 웹 콘솔 화면이 뜬다.
자동으로 뜬 웹 주소에서 다른 건 건들지 말고 포트 번호(8082) 앞에 있는 IP 주소를 localhost로 변경한 뒤 JDBC URL에 jdbc:h2:~/jpashop(파일 모드 접근)를 입력해 DB 파일을 생성한다.
- JDBC URL = DB 파일을 생성할 경로
- 이때 파일을 생성할 때 권한이 필요하기 때문에, 세션키를 유지한 상태로 최소 한 번 JDBC URL을 입력해 실행해야 한다.
[연결]을 누르면 접속이 되고 아래 버튼을 눌러 연결을 해제할 수 있다. ~/jpashop.mv.db 파일이 생성됐는지 확인하고, 생성이 됐다면 이후부터는 JDBC URL에 jdbc:h2:tcp://localhost/~/jpashop(TCP 네트워크 모드 접근)를 입력해 편하게 접속할 수 있다.
5. JPA와 DB 설정 및 동작 확인
JPA와 DB를 설정하고 실제 동작하는지 확인해 본다.
JPA와 DB 설정
먼저 application.yml 파일을 아래와 같이 작성한다.
- logging.level.org.hibernate.orm.jdbc.bind: trace로 설정하면 쿼리 파라미터 로그를 남길 수 있다.
spring:
datasource:
url: jdbc:h2:tcp://localhost/~/jpashop
username: sa
password:
driver-class-name: org.h2.Driver
jpa:
hibernate:
ddl-auto: create # 애플리케이션 실행 시점에 테이블 drop 후 재생성
properties:
hibernate:
# show_sql: true # 하이버네이트 실행 SQL을 콘솔에 출력
format_sql: true
logging.level:
org.hibernate.SQL: debug # 하이버네이트 실행 SQL을 로깅으로 출력
스프링 부트를 사용하면 아래 라이브러리만 추가하면 된다. 스프링 부트 3.0 이상을 사용한다면 라이브러리 버전을 1.9.0 이상으로 사용하자.
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'
참고
쿼리 파라미터 로그를 남기는 외부 라이브러리는 시스템 자원을 사용하므로, 개발 단계에서는 편하게 사용해도 된다. 그러나 운영 시스템에 적용하려면 꼭 성능 테스트를 하고 사용하는 것이 좋다.
테스트용 회원 엔티티, 회원 리포지토리 생성
멤버와 멤버 리포지토리를 만들고 테스트해 본다. MemberRepository에서 @PersistenceContext 애노테이션을 EntityManager 필드에 붙이면 Spring Data JPA에서 엔티티 매니저를 자동으로 주입해 준다.
@Repository
public class MemberRepository {
@PersistenceContext
private EntityManager em;
public Long save(Member member) {
em.persist(member);
return member.getId();
}
public Member find(Long id) {
return em.find(Member.class, id);
}
}
테스트
테스트용 코드를 아래와 같이 작성한다.
- 엔티티 매너저를 통한 모든 데이터 변경은 항상 Transaction 안에서 이루어져야 한다. 따라서 @Transactional 애노테이션을 작성하지 않으면 아래 에러가 뜨게 된다.
- No Entity Manager with actual transactional available for current thread
- 이때, 해당 애노테이션이 Test에 붙어있다면 Test가 끝난 후 Rollback을 하게 된다. 데이터가 저장되는지 확인하기 위해 @Rollback(false) 애노테이션을 통해 Rollback 대신 Commit 되도록 해야 한다.
- 같은 영속성 컨텍스트에서는 식별자가 같으면 같은 엔티티로 인식한다.
@SpringBootTest
public class MemberRepositoryTest {
@Autowired
MemberRepository memberRepository;
@Test
@Transactional
@Rollback(false)
public void testMember() {
// given
Member member = new Member();
member.setUsername("memberA");
// when
Long savedId = memberRepository.save(member);
Member findMember = memberRepository.find(savedId);
// then
Assertions.assertThat(findMember.getId()).isEqualTo(member.getId());
Assertions.assertThat(findMember.getUsername()).isEqualTo(member.getUsername());
Assertions.assertThat(findMember).isEqualTo(member);
}
}
참고
스프링 부트를 통해 복잡한 설정이 다 자동화됐다. persistence.xml도 없고 LocalContainerEntityManagerFactoryBean도 없다. 스프링 부트를 통한 추가 설정은 스프링 부트 매뉴얼을 참고하자. 스프링 부트를 사용하지 않고 순수 스프링과 JPA 설정 방법은 자바 ORM 표준 JPA 프로그래밍 책을 참고하자.
H2 DB를 확인하면 데이터가 잘 저장된 것을 확인할 수 있다.