<aside> ❗

스프링 부트 플러그인

<aside> ❗

스프링 부트 라이브러리 살펴보기

./gradlew dependencies → 의존관계를 출력해준다.

스프링 부트 라이브러리 살펴보기

spring-boot-starter-web

spring-boot-starter-tomcat: 톰캣 (웹서버)

spring-webmvc: 스프링 웹 MVC

** 웹이 톰캣과 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

→ slf4j - 로거를 찍는 인터페이스 모음, 구현체로 logback 등을 사용

테스트 라이브러리

spring-boot-starter-test

junit: 테스트 프레임워크

mockito: 목 라이브러리

assertj: 테스트 코드를 좀 더 편하게 작성하게 도와주는 라이브러리

spring-test: 스프링 통합 테스트 지원

핵심 라이브러리

스프링 MVC

스프링 ORM

JPA, 하이버네이트

스프링 데이터 JPA

기타 라이브러리

H2 데이터베이스 클라이언트

커넥션 풀: 부트 기본은 HikariCP

WEB(thymeleaf)

로깅 SLF4J & LogBack

테스트

**

기본적으로 스프링 부트가 버전에 맞는 라이브러리를 세팅해둠

스프링 부트가 지원하지 않는 라이브러리들은 뒤에 버전 정보를 적어줘야 한다.

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-devtools'
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'

</aside>

<aside> ❗

View 환경 설정

thymeleaf 템플릿 엔진

thymeleaf 공식 사이트: https://www.thymeleaf.org/

스프링 공식 튜토리얼: https://spring.io/guides/gs/serving-web-content/

스프링부트 메뉴얼: https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/

boot-features-developing-web-applications.html#boot-features-spring-mvc-template-engines

resources:templates/ +{ViewName}+ .html

java

@Controller
public class HelloController {

	@GetMapping("hello")

	public String hello(Model model) {
		model.addAttribute("data", "hello!!");
		return "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>

위치: resources/templates/hello.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>

[참고]

spring-boot-devtools 라이브러리를 추가하면, html 파일을 컴파일만 해주면 서버 재시작 없이

View 파일 변경이 가능하다.

인텔리J 컴파일 방법: 메뉴 build Recompile


정적인 콘텐츠는 static 폴더에 - 렌더링 안 하는 HTML

동적인 콘텐츠는 templates 폴더에 - 렌더링 할 HTML implementation 'org.springframework.boot:spring-boot-devtools' → 캐시도 없애주고, 리로딩 되도록 해줌 (더 많은 기능 제공)

→ 실행 시 restartedMain이라고 뜨면 devtools가 잘 적용된 것

→ build → recompile(cmd + shift + F9)

</aside>

<aside> ❗

H2 데이터 베이스 설치

  1. H2 파일 다운로드
  2. bin 폴더에서 h2.sh 실행
  3. JDBC URL에 jdbc:h2:~/jpashop 넣고 연결 (최소 한번) ~/jpashop.mv.db` 파일 생성 확인
  4. 이후 부터 `jdbc:h2:tcp://localhost/~/jpashop 넣고 연결 </aside>

<aside> ❗

application.yml 파일 설정

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

  jpa:
    hibernate:
      ddl-auto: create
    properties:
      hibernate:
#        show_sql: true # System.out에 출력
        format_sql: true

logging:
  level:
    org.hibernate.SQL: debug # 하이버네이트가 남기는 로그가 다 보임(모든 SLQ 보임)
                             # 로거를 통해서 출력한다. 
                             # 로그는 System.out이 아닌 로거를 통해서 찍어야 한다.
    #org.hibernate.orm.jdbc.bind: trace
    

[참고]

[주의!!]

</aside>

<aside> ❗

JPA 동작 확인

회원 리포지토리

package jpabook.jpashop;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;

@Repository
public class MemberRepository {

    // 스프링 부트는. 스프링 컨테이너 위에서 모든 것이 동작
    // 스프링 부트가 @PersistenceContext가 있으면 EntityManager를 주입을 해준다.
    // @PersistenceContext는 EntityManager의 생명 주기 컨테이너가 관리도록 설정 - EntityManger 주입, 영속 컨텍스트 관리
    @PersistenceContext
    private EntityManager em;

    // 커맨드랑 쿼리를 분리해라
    // 저장 후, side effect를 일으키는 커맨드성이기 때문에
    // 리턴값을 만들지 않는다.
    // ID 값이 있으면 다음에 다시 조회할 수 있도록 할 수 있도록 설계
    public Long save(Member member) {
        em.persist(member);
        return member.getId();
    }

    public Member find(Long id) {
        return em.find(Member.class, id);
    }
}

테스트 코드

package jpabook.jpashop;

import org.assertj.core.api.Assertions;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

import static org.junit.Assert.*;
//JUnit한테 스프링과 관련된 걸로 테스트할 것이라는 걸 알려줘야 한다.
@RunWith(SpringRunner.class)
// 스프링 부트로 테스트 할 거야.
@SpringBootTest
public class MemberRepositoryTest {

    @Autowired MemberRepository memberRepository;

    @Test
    // 스프링 트랜잭션 애너테이션 권장
    // 트랜잭션 애너테이션이 테스트 코드에 있으면 실행 후 바로 롤백
    @Transactional
    // @Rollback(false)를 테스트 코드에 넣으면 롤백하지 않는다.
//    @Rollback(false)
    public void testMember() throws Exception{
        // EntityManager를 통한 모든 데이터 변경은 항상 트랜잭션 안에서 이루어져야 한다.

        //given
        Member member = new Member();
        member.setUserName("memberA");

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

        //then
        Assertions.assertThat(findMember.getId()).isEqualTo(member.getId());
        Assertions.assertThat(findMember.getUserName()).isEqualTo(member.getUserName());
        Assertions.assertThat(findMember).isEqualTo(member);

        System.out.println("findMember = " + findMember);
        System.out.println("member = " + member);
        // findMember == member가 true인 이유
        // 같은 트랜잭션 안에서 영속성 컨텍스트가 동일하다.
        // 같은 영속성 컨텍스트 안에서는 식별자가 같으면 같은 엔티티로 인식
    }

}
// 지우고 깔끔하게 빌드 - jpashop 폴더에서 실행
./gradlew clear build 

[참고]

</aside>

<aside> ❗

쿼리 파라미터 로그 남기기 - p6spy

implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.6'

**

로그를 어떻게 찍을지 옵션 설정하는 것은

[참고]

쿼리 파라미터 로그 남기기 - 스프링 부트 3.0

스프링 부트 3.0 이상을 사용하면 라이브러리 버전을 1.9.0 이상을 사용해야 한다.

implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'

</aside>