본문 바로가기
Dev/JPA

[JPA] JPA 활용 I - 프로젝트 환경설정

by dev_jsk 2021. 9. 14.
728x90
반응형

프로젝트 생성

  • Spring Initializr에서 프로젝트 생성
  • 프로젝트 구성
    - Gradle Project, Java Language
    - Spring 2.4.X version, Java 11 version
    - Group Id : jpabook, Artifact Id : jpashop
  • 의존성 구성
    - Spring Web Starter
    - Thymeleaf
    - Spring Data JPA
    - H2 Database
    - Lombok
    - Validation

프로젝트 구성

JUnit 4 설정

해당 강의는 JUnit4를 기준으로 진행하기 때문에 build.gradle내에 아래 구문을 추가해야 한다. 추가하지 않을 경우 JUnit5로 동작한다.

// JUnit4 추가
testImplementation("org.junit.vintage:junit-vintage-engine") {
    exclude group: "org.hamcrest", module: "hamcrest-core"
}

프로젝트 동작 확인

Main 클래스 실행

프로젝트가 정상적으로 생성, import 되었는지 JpashopApplication클래스를 실행시켜본다.

 

동작 결과

정상적으로 동작 시 로그, 내장 Tomcat이 구동되는 것을 확인 할 수 있다.
웹 페이지 접속 확인

Test Main 클래스 동작 확인

기본 테스트가 정상 동작 하는지 확인해본다.

 

동작 결과

좌측 녹색 결과가 나오며 정상 동작을 확인할 수 있다.

Lombok 동작 확인

Lombok이란 어노테이션을 기반으로 코드를 자동완성 해주는 라이브러리로 Getter, Setter, ToString, Equals 등 다양한 코드를 자동완성 해준다.

 

예제

- Hello.java

import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class Hello {
    
    private String name;
}

- JpashopApplication.java

@SpringBootApplication
public class JpashopApplication {

	public static void main(String[] args) {
		// Lombok 테스트
		Hello hello = new Hello();
		hello.setName("hello");
		System.out.println("hello : " + hello.getName());

		SpringApplication.run(JpashopApplication.class, args);
	}
}

동작 결과

Getter, Setter 정상 동작

라이브러리 살펴보기

스프링 부트 라이브러리

  • 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 : 스프링 통합 테스트 지원

핵심 라이브러리

  • Spring MVC
  • Spring ORM
  • JPA, Hibernate
  • Spring Data JPA

기타 라이브러리

  • H2 Database
  • Thymeleaf
  • 로깅 slf4j(인터페이스) & logback(구현체)
  • 테스트 관련

View 환경설정

Thymeleaf 템플릿 엔진 사용하여 View 구성한다.

정적파일 테스트

정적 페이지 및 파일은 resources/static경로에 생성하여 사용한다.

 

예제

최초 진입시 출력되는 index.html을 구성해보자

 

- 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>
    Hello
    <a href="/hello">hello</a>
  </body>
</html>

index 페이지 테스트 결과

템플릿 엔진 동작 테스트

Thymeleaf의 View Name은 resources/templates경로 내 파일명과 매핑된다.

 

예제

간단한 페이지를 구성하여 Thymeleaf 엔진 동작 테스트를 진행해보자.

 

- HelloController.java

@Controller
public class HelloController {
    
    @GetMapping("hello")
    public String hello(Model model) {
        model.addAttribute("data", "hello!!");
        return "hello";  // 화면명 리턴
    }
}

- 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>

동작 결과

전달된 data값이 정상 치환되면서 정상 동작 확인

Spring boot devtools

개발 편의를 위한 라이브러리로 주로 변경된 코드를 서버 또는 화면에 적용하는 동작을 한다.

  • Property Defaults : 속성 옵션 기본값 설정 (캐싱 등)
  • Automatic Restart : classpath 내 파일 변경 시 서버 재시작
  • Live Reload : JSP, CSS 파일 변경 시 자동 새로고침
  • Global Settings : 전역 프로퍼티 설정
  • Remote Applications : 원격 개발지원

적용하기

- build.gradle

runtimeOnly 'org.springframework.boot:spring-boot-devtools'

동작 결과

restartedMain 으로 동작하면 devtools가 정상 적용된 것이다.

H2 Database 설치

H2 데이터베이스는 가볍고 편리하며 웹 화면을 제공하기 때문에 개발이나 테스트 시 많이 사용한다. (해당 강의에서는 1.4.200 버전을 사용한다.)

실행하기

압축해제 후 h2-2019-10-14/h2/bin경로에서 h2.bat파일을 실행한다.

접속하기

접속 시 db파일을 생성시켜줘야 하는데 최초엔 jdbc:h2:~/jpashop URL로 접속 후 이후부턴 네트워크 모드로 tcp를 이용해 jdbc:h2:tcp://localhost/~/jpashop URL로 접속한다.

파일 접속 (좌측) / 네트워크 tcp 접속 (우측)

접속완료

접속 시 해당 화면이 표시된다.

JPA와 Database 설정 및 동작확인

YAML

YAML은 스프링부트의 설정파일 형식이다. 장점으로는 보기 쉬운 문법한 파일 내에서 profile로 다양한 설정을 관리할 수 있지만 단점으로는 띄어쓰기로 구분하기 때문에 주의해야 한다.

YAML 설정 적용하기

resources/경로에 application.yml파일을 생성하여 설정정보를 관리할 수 있다.

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

  jpa:
    hibernate:
      # 애플리케이션 실행 시점에 DB 초기화 후 다시 DDL 실행
      ddl-auto: create
    properties:
      hibernate:
        # sysout으로 출력
        # '[show_sql]': auto
        '[format_sql]': true

logging:
  level:
    # JPA나 hibernate가 남기는 SQL이 다 logger로 출력
    '[org.hibernate.SQL]': debug

YAML 설정 확인하기

애플리케이션 설정정보를 간단한 Member 정보를 찾는 테스트를 만들어 확인해보자

 

소스

- Member.java

@Entity
@Getter @Setter
public class Member {
    
    @Id @GeneratedValue
    private Long id;
    private String username;
}

- MemberRepository.java

@Repository
public class MemberRepository {
    
    @PersistenceContext  // 스프링부트가 알아서 EntityManager 생성
    private EntityManager em;

    /**
     * Member save
     * @param member
     * @return member.id
     */
    public Long save(Member member) {
        em.persist(member);
        return member.getId();
    }

    /**
     * Member find
     * @param id
     * @return member
     */
    public Member find(Long id) {
        return em.find(Member.class, id);
    }

}

- MemberRepositoryTest.java

@RunWith(SpringRunner.class)
@SpringBootTest
public class MemberRepositoryTest {
    
    @Autowired MemberRepository memberRepository;

    @Test
    @Transactional  // Test에서 사용 시 테스트 종료 후 롤백
    @Rollback(value = false)  // false 지정 시 롤백 안함
    public void testMember() throws Exception {
        // given
        Member member = new Member();
        member.setUsername("memberA");

        // when
        Long savedId = memberRepository.save(member);
        Member findMember = memberRepository.find(savedId);

        // then
        // 엔티티 없어서 테스트 실패, 트랜잭션이 없기 때문
        // @Transactional 어노테이션 추가하여 테스트 성공
        Assertions.assertThat(findMember.getId()).isEqualTo(member.getId());
        Assertions.assertThat(findMember.getUsername()).isEqualTo(member.getUsername());
        Assertions.assertThat(findMember).isEqualTo(member); // JPA 엔티티 동일성 보장
        System.out.println("findMember == member : " + (findMember == member));
    }
}

동작 결과

(1) @Transactional 추가 전 결과

EntityManager가 트랜잭션을 찾을 수 없다는 오류 발생

(2) @Transactional 추가 후 결과

트랜잭션오류가 해결되고 정상적으로 테스트가 완료
테스트 동작 로그

JAR 패키징 및 실행

jar 파일을 만들어서 빌드 및 실행을 할 수 있다.

 

JAR 패키징

프로젝트를 빌드한다.

JAR 파일 실행

jar 파일 위치 (좌측) / jar 파일 실행 확인 (우측)

쿼리 파라미터 로그 남기기

SQL에 들어가는 파라미터 로그를 설정 및 외부 라이브러리를 통해 남길 수 있다.

 

설정 변경

- application.yml

logging:
  level:
    '[org.hibernate.SQL]': debug
    # SQL 파라미터 로그 출력
    '[org.hibernate.type]': trace

설정 변경을 통한 SQL 파라미터 로그

외부 라이브러리

P6Spy 라이브러리를 통해 파라미터가 포함된 SQL 로그를 출력할 수 있다.

- build.gradle

// P6Spy 추가
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.6'

P6Spy 이용 SQL 파라미터 로그

※ 참고로 SQL 파라미터를 로그로 남기는 외부 라이브러리는 시스템 자원을 사용하므로 개발 단계에서는 편하게 사용해도 되지만, 운영 시스템에 적용하려면 충분한 성능 테스트 후 적용해야 한다.

728x90
반응형

댓글