Web/Spring

스프링 DB 접근 기술

느낌표 공장장 2021. 7. 25. 17:01

H2 데이터베이스 설치

: 개발이나 테스트 용도로 가볍고 편리한 DB, 웹 화면 제공 ( https://www.h2database.com )

 

다운로드 및 설치

  • h2 데이터베이스 버전은 스프링 부트 버전에 맞춘다. 
  • 권한 주기: chmod 755 h2.sh
  • 실행: ./h2.sh
  • 데이터베이스 파일 생성 방법
    • jdbc:h2:~/test (최초 한번) (파일 경로)
    • ~/test.mv.db 파일 생성 확인
    • 이후부터는 jdbc:h2:tcp://localhost/~/test 이렇게 접속
      (이렇게 하면 직접 접근이 아니라 소켓 통해서 접근하는 것. 그럼 여러 군데에서 접근할 수 있다.)

 

* sql 폴더 따로 만들어서 (아예 밖에) 파일 만들어서 sql문 적어두면, git 쓰면 변경내역 관리되고 그거보고 파악되니까 좋음

 


 

순수 Jdbc

< 환경 설정 >

1. build.gradle 파일에 jdbc, h2 데이터베이스 관련 라이브러리 추가

  • 자바는 기본적으로 db랑 붙으려면 jdbc가 있어야 한다. 이걸로 연동한다!!
  • h2는 db랑 붙을 때 데이터베이스가 제공하는 클라이언트가 필요해서 넣어야 한다. 

 

2. 스프링 부트 데이터베이스 연결 설정 추가

  • db에 붙으려면 접속 정보 넣어야 하는데 요즘은 스프링 부트가 다 해줘서 경로만 넣으면 된다.
  • 연결 설정 추가하면 스프링이 필요한 데이터 소스 (db연결 작업) 다 해준다. 이걸 가져다 쓰기만 하면 된다.

 

Jdbc 리포지토리 구현 

회원을 저장하는 역할은 memberRepository가 하지만, 구현을 메모리에 할 거야 아니면 db랑 연결해서 jdbc에 할거야 이 차이가 있다.

 

  • 개방-폐쇄 원칙(OCP, Open-Closed Principle)
    •  확장에는 열려있고, 수정, 변경에는 닫혀있다.
  • 스프링의 DI (Dependencies Injection)을 사용하면 기존 코드를 전혀 손대지 않고, 설정만으로 구현 클래스를 변경할 수 있다.
  • 데이터를 DB에 저장하므로 스프링 서버를 다시 실행해도 데이터가 안전하게 저장된다.

 


 

스프링 통합 테스트

✔︎ @SpringBootTest : 스프링 컨테이너와 테스트를 함께 실행한다.

✔︎  @commit : 테스트 케이스 끝나면 커밋한다.

 

✔︎ 테스트는 반복할 수 있어야 한다.

  • DB는 기본적으로 transaction이라는 개념이 있다. commit을 해줘야 db에 반영이 된다. 근데 test 끝나고 롤백해버리면 DB에서 그 데이터 반영 안 된다.
  • 그걸 @Transactional을 테스트 케이스에 달면 테스트에 실행할 때 트렌젝션 먼저 실행하고, db데이터 인서트 쿼리하고 다 넣은 다음에 테스트 완료 후에 항상 롤백해준다. 그래서 DB에 데이터가 남지 않으므로 다음 테스트에 영향을 주지 않는다.
    • 테스트 메서드마다 일일이 작동한다!!! 
    • 참고로 @Transactinal은 서비스나 이런 곳에 붙으면 롤백하지 않고 정상적으로 돌고, 테스트 케이스에 붙었을 때만 항상 롤백하도록 동작한다.

 

✔︎  단위 테스트 : 순수하게 자바 코드로 하면서 최소한의 단위로 테스트하는 것.

  • (통합 테스트는 스프링 컨테이너랑 db까지 연동하고 테스트하므로 오래 걸린다.)
  • 가급적이면 순수한 단위 테스트가 훨씬 좋은 테스트일 확률이 높다.
  • 따라서 단위 단위 쪼개서 잘 테스트하고, 스프링 컨테이너 없이 테스트할 수 있도록 연습해야 한다!!! (통합 테스트도 물론 필요하다)

 


 

스프링 JdbcTemplate

  • 순수 Jdbc와 동일한 환경설정을 하면 된다.
  • 스프링 JdbcTemplate과 MyBatis 같은 라이브러리는 JDBC API에서 본 반복 코드를 대부분 제거해준다. 하지만 SQL은 직접 작성해야 한다.
  • jdbctemplate은 실무에서도 많이 쓴다.

✔︎ 순수 jdbc와 비교하면 많이 줄여진다. 

  • 디자인 패턴 중에 템플릿 메서드 패턴이 많이 들어가 있기 때문에 코드를 줄였다. 그래서 jdbctemplate인 이유이다.

 


 

JPA

  • JPA는 기존의 반복 코드는 물론이고, 기본적인 SQL도 JPA가 직접 만들어서 실행해준다.
    • JPA에 객체를 메모리에 넣듯이 객체를 넣으면 JPA가 중간에서 DB에 SQL 날리고 데이터를 DB 통해서 가져온다.
  • JPA를 사용하면, SQL과 데이터 중심의 설계에서 객체 중심의 설계로 패러다임을 전환을 할 수 있다.
  • JPA를 사용하면 개발 생산성을 크게 높일 수 있다.
  • 객체를 바로 db에 쿼리 없이 저장할 수 있다.  

 

1. build.gradle 파일에 JPA, h2 데이터베이스 관련 라이브러리 추가

 

2. 스프링 부트에 JPA 설정 추가

spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
  • show-sql : JPA가 생성하는 SQL을 출력한다.
  • ddl-auto : JPA는 회원 객체를 보고 테이블을 자동으로 생성하는 기능을 제공하는데 none를 사용하면 해당 기능을 끈다.
    • create 를 사용하면 엔티티 정보를 바탕으로 테이블도 직접 생성해준다.

 

3. JPA 엔티티 매핑

  • JPA는 자바 진영의 표준 인터페이스인데, 딱 인터페이스만 제공된다. 구현은 여러 업체들이 하는 것이다. 구현체로 Hibernate, 이클립스 여러 Vendor(공급업체)들이 있다. ( 여기선 JPA 인터페이스의 Hibernate만 쓴다고 생각하면 된다.)
  • jpa는 객체와 ORM(Object Relational Mapping) 이라는 기술이다. 
    • ORM : 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑해주는 것
      • Mapping을 어떻게? → 어노테이션 한다.

 

4. jpa 회원 리포지토리

  • JPA는 EntityManager라는 것으로 모든 것을 동작한다. (따라서 JPA를 다루려면 EntityManager을 주입받아야 한다.)
    • build.gradle에 JPA 라이브러리 받아오면 스프링 부트가 자동으로 EntityManager을 생성해준다.
    • 현재 데이터베이스랑 연결해서 만들어준다. 그럼 우리는 만들어진걸 인젝션 하면 된다!

 

5. 서비스 계층에 트랜잭선 추가

 

  • org.springframework.transaction.annotation.Transactional 를 사용하자.
  • 스프링은 해당 클래스의 메서드를 실행할 때 트랜잭션을 시작하고, 메서드가 정상 종료되면 트랜잭션을 커밋한다. 만약 런타임 예외가 발생하면 롤백한다.
  • JPA를 통한 모든 데이터 변경은 트랜잭션 안에서 실행해야 한다. (JPA 쓸 때 주의해야 할 점)
    •  @Transaction (데이터를 저장하거나 변경할 때 항상 있어야 한다.)

 

6. JPA를 사용하도록 스프링 설정 변경

 


 

스프링 데이터 JPA

스프링 부트와 JPA만 사용해도 개발 생산성이 정말 많이 증가하고, 개발해야 할 코드도 확연히 줄어든다. 여기에 스프링 데이터 JPA를 사용하면, 기존의 한계를 넘어 마치 마법처럼, 리포지토리에 구현 클래스 없이 인터페이스 만으로 개발을 완료할 수 있다. 그리고 반복 개발해온 기본 CRUD 기능도 스프링 데이터 JPA가 모두 제공한다.

스프링 부트와 JPA라는 기반 위에, 스프링 데이터 JPA라는 환상적인 프레임워크를 더하면 개발이 정말 즐거워진다. 지금까지 조금이라도 단순하고 반복이라 생각했던 개발 코드들이 확연하게 줄어든다. 따라서 개발자는 핵심 비즈니스 로직을 개발하는데, 집중할 수 있다.
실무에서 관계형 데이터베이스를 사용한다면 스프링 데이터 JPA는 이제 선택이 아니라 필수이다.

 

! 주의 ! 스프링 데이터 JPA는 JPA를 편리하게 사용하도록 도와주는 기술입니다. (JPA먼저 학습해야 함)

 

 

1. 인터페이스 만든다. extends해서 JpaRepository 받아온다. 

// 인터페이스는 다중 상속된다. JpaRepository<멤버, 식별자 pk>, MemberRepository
// 인터페이스만 만들고 이걸 받으면 스프링 데이터 jpa가 인터페이스에다가 구현체를 만들어낸다.

// 스프링 데이터 jpa가 Jparepository을 받고 있으면 구현체를 만들어주고 스프링 빈에 자동으로 등록해준다.
public interface SpringDataJpaMemberRepository extends JpaRepository<Member,Long>, MemberRepository {
      
      // JPQL을 짜준다. select m from Member m where m.name = ?
     // 그럼 sql로 번역해서 실행
      Optional<Member> findByName(String name);
  }

 

2. 스프링 데이터 JPA 회원 리포지토리를 사용하도록 스프링 설정 변경 

  • 스프링 데이터 JPA가 SpringDataJpaMemberRepository 를 스프링 빈으로 자동 등록해준다.

 

✔︎ 스프링 데이터 JPA 제공 기능 

  • 인터페이스를 통한 기본적인 CRUD
  • findByName() , findByEmail() 처럼 메서드 이름 만으로 조회 기능
  • 제공 페이징 기능 자동 제공
  • 참고실무에서는 JPA와 스프링 데이터 JPA를 기본으로 사용하고복잡한 동적 쿼리는 Querydsl이라는 라이브러리를 사용하면 된다. Querydsl을 사용하면 쿼리도 자바 코드로 안전하게 작성할 수 있고동적 쿼리도 편리하게 작성할 수 있다이 조합으로 해결하기 어려운 쿼리는 JPA가 제공하는 네이티브 쿼리를 사용하거나앞서 학습한 스프링 JdbcTemplate를 사용하면 된다.

 

 

 

 


참조

이 게시물은 인프런 > 김영한님의 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술의 강의를 토대로 작성한 게시물입니다.