Spring/[인프런 김영한 실전 스프링 부트와 JPA 활용 1]

[인프런 김영한 실전 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발] 프로젝트 환경설정

h2boom 2024. 8. 29. 15:42

라이브러리

  • 스프링 부트 라이브러리
    • 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 프레임워크의 핵심 요소로 IoC / DI 기능을 지원한다.
      • spring-boot-starter-logging
        • logback, slf4j : slf4j는 log 기능을 제공하는 인터페이스 집합이고 구현체로 logback을 주로 사용한다.

 

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

 

  • spring-boot-devtools 라이브러리 사용 시 파일 내용에 변경 사항이 생겨도 서버를 재시작 할 필요없이 해당 파일만 컴파일함으로 더 빠르고 편하게 변경사항을 적용시킬 수 있다.

H2 Database

  • Spring Boot 버전에 호환되는 H2 database 설치

 

  • 처음 Database 생성 시
    • jdbc:h2:~/DB명으로 생성
    • ~/DB명.mv.db으로 파일이 생성된다.
    • 처음 생성 이후 jdbc:h2:~/DB명 처럼 파일 명으로 접속 시 파일 락이 걸려서 한 군데에서 밖에 접근이 되지 않기에 네트워크를 통해서 원격으로 접속 => jdbc:h2:tcp://localhost/~/DB명

 

  • 새로운 DB 생성하는 방법
    1. 우측 하단 아이콘 우클릭을 통해 create a new database 선택
    2. Database Path, Username, Password 입력 후 생성
      • 패스워드는 필수로 입력해야하기에 나중에 제거해야한다.
      • 만약 IO Exception 발생 시 Database Path에 전체 경로를 다 작성
    3. DB 처음 생성 이후 jdbc:h2:~/DB명과 같이 파일 명으로 접속
      • 패스워드 제거 방법 :SQL 문 실행 =>  ALTER USER SA SET PASSWORD ''; 
    4. 이후 접속 시 처음 접속과 동일하게 접속하면 파일 락이 걸려서 한 군데에서 밖에 접근이 되지 않기에 네트워크를 통해서 원격으로 접속
      • jdbc:h2:tcp://localhost/~/DB명

JPA, DB 설정

  • 스프링 부트를 통한 자동화로 인해 persistence.xml을 따로 만들 필요 없다.
  • 추가적으로 설정이 필요한 것들은 application.yml 파일에 설정해서 사용

 

@PersistenceContext
private EntityManager em;
  • 영속성 컨텍스트를 사용하기 위해서 @PersistenceContext로 EntityManager를 빈으로 주입 받는다.
    • 스프링 자체에 영속성 관리를 위한 EntityManager가 존재하고 그것을 빈으로 주입받는 것

 

public Long save(Member memeber){...}
  • Member를 반환받지 않고 Long 타입 id를 받환 받는 이유?
    • CQS 패턴에 의해 작성하고 사이드 이펙트를 일으키지 않도록 하기 위함
    • ID 값을 활용할 수 있기에 최소한의 ID 값만 반환 받는 형태로 설계

 

  • CQS (Command Query Separation) : Command와 Query를 분리하는 디자인 패턴이다.
    • Command : 객체의 상태를 변경하는 메소드로 값을 반환하지 않는다. ( = Setter)
    • Query : 값을 반환하는 메소드로 객체의 상태는 변경하지 않는다. (= Getter )

 

@SpringBootTest
@ExtendWith(SpringExtension.class)
public class MemberRepositoryTest {...}
  • 스프링 부트 환경으로 테스트하기 위해서 @SpringBootTest와 @ExtendWith(SpringExtension.class) 어노테이션은 필수
    • JUnit4 이하는 @ExtendWith 대신 @RunWith(SpringRunner.class)를 사용한다.
    • JUnit5 부터는 @SpringBootTest에 @ExtendWith(SpringExtension.class)가 포함되어 있기에 생략 가능하다.
  • 트랜잭션에 의해서 동작하기에 Test 케이스에서도 @Transactional은 필수
    • @Transactional은 Test 케이스에서만 동작이 끝난 후에 DB를 항상 롤백한다.
    • @Rollback(value = false)로 테스트 케이스에서 롤백하지 않도록 설정할 수 있다.

 

@Test
@Transactional
@Rollback(value = false)
public void testMember() throws Exception {
	//given
	Member member = new Member();
	member.setUsername("memberA");

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

	//then
	//hashCode(), equals() 오버라이딩x
	Assertions.assertThat(findMember).isEqualTo(member);   
}
  • 테스트 케이스에서 findMember와 member를 equals로 비교했을 경우
    (hashCode()와 equals()는 오버라이딩 하지 않은 상태로 ==비교와 같다.)
    • 같은 트랜잭션 내에서 저장하고 조회를 했기 때문에 같은 영속성 컨텍스트 안에서 식별자(ID)값이 같기 때문에 같은 엔티티로 식별하고 == 비교를 하더라도 결과는 TRUE가 나온다.
      => 식별자가 같기 때문에 영속성 컨텍스트의 1차 캐시에서 같은 값을 조회한 것

 

  • 해당 프로젝트 디렉토리에서 gradlew clean build로 build/libs에 jar 파일 생성
    • 해당 jar 파일로 배포 가능

Spring Boot SQL 설정

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

logging:
  level:
    org.hibernate.sql: debug
    org.hibernate.type: trace
    org.hibernate.orm.jdbc.bind: trace
  • application.yml 파일 설정 내용
    • ddl-auto: 자동으로 DB 테이블을 생성, 수정해주는 옵션
      • create : 기존 테이블 삭제 후 다시 생성 (DROP + CREATE)
      • create-drop : create와 같으나 종료시점에 테이블 DROP
        • 주로 테스트 케이스 실행 후 데이터를 제거하고 싶을 때 사용한다.
      • update : 변경분만 반영 (운영 DB에서 사용x)
        • 테이블 컬럼을 추가하는 것은 되지만 삭제하는 것은 안된다.
      • validate : 엔티티와 테이블이 정상 매핑되었는지만 확인
      • none : 사용하지 않음
    • show_sql : Hibernate가 DB로 날리는 모든 쿼리를 콘솔에 출력 (System.out)
    • format_sql : 로그, 콘솔의 SQL을 보기좋게 출력
    • org.hibernate.sql:debug => logger를 이용해 쿼리를 보여준다.
    • org.hibernate.orm.jdbc.bind: trace (hibernate6) => 쿼리 파라미터로 전달된 실제 값을 확인할 수 있다.

 

implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'
  • 외부 라이브러리를 추가함으로 쿼리 파라미터 로그를 쉽게 확인할 수 있다.

 

  • Spring Boot SQL 설정과 같은 것들은 운영, 배포 시 병목 현상이 발생할 수 있기에 확인하고 사용하거나 개발 단계에서만 사용하는 것이 좋다.

출처: [인프런 김영한 실전 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발]

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-JPA-%ED%99%9C%EC%9A%A9-1

 

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발 강의 | 김영한 - 인프런

김영한 | 실무에 가까운 예제로, 스프링 부트와 JPA를 활용해서 웹 애플리케이션을 설계하고 개발합니다. 이 과정을 통해 스프링 부트와 JPA를 실무에서 어떻게 활용해야 하는지 이해할 수 있습니

www.inflearn.com