본문으로 바로가기

https://www.inflearn.com/course/스프링-db-2

 

스프링 DB 2편 - 데이터 접근 활용 기술 - 인프런 | 강의

백엔드 개발에 필요한 DB 데이터 접근 기술을 활용하고, 완성할 수 있습니다. 스프링 DB 접근 기술의 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., - 강의 소개 | 인

www.inflearn.com

 

데이터 접근 기술 - 시작

데이터 접근 기술 진행 방식 소개
  • SQL Mapper (JdbcTemplate, MyBatis) , ORM (JPA, Hibernate, 스프링 데이터 JPA, Querydsl)
  • JPA 는 자바 진영의 ORM 표준이고, Hibernate(하이버네이트)는 JPA에서 가장 많이 사용하는 구현체
  • 스프링 데이터 JPA, Querydsl 은 JPA 를 더 편리하게 사용할 수 있게 도와주는 프로젝트
  • 메모리 기반으로 완성되어 있는 프로젝트를 확인하고, DB 기술을 사용해본다.
프로젝트 설정과 메모리 저장소 & 프로젝트 구조 설명1,2,3 - 기본,설정,테스트
  • ItemUpdateDto 와 ItemSearchCond 와 같은 경우, ItemRepository 가 최종 사용처이기 때문에
    ItemRepository 와 같은 패키지에 둔다.
  • ItemService 에 둘 경우, 패키지 순환참조 문제가 발생한다.
    - ItemRepository 에서 사용해야하는데 ItemService 가 있는 패키지 참조해야함
  • @EventListener(ApplicationReadyEvent.class) 쓰는 이유
    - 스프링 컨테이너가 완전히 초기화를 다 끝내고, 실행 준비가 되었을 때 발생하는 이벤트
    - @PostConstruct 를 사용할 경우, AOP 같은 부분이 아직 다 처리되지 않은 시점에 호출될 수 있다.
  • application.properties 에 spring.active.profiles 속성을 설정하면 해당 값이 기본으로 profile 로 설정되어 실행된다.
    TEST 패키지 하위의 properties 에서는 해당 profiles 이 우선된다.
  • 인터페이스를 테스트하자
    - 향후 교체되는 구현체에 대해 검증 할 수 있음
데이터베이스 테이블 생성
  • 권장하는 식별자 선택 전략
    - 데이터 베이스 기본키는 다음 3가지 조건을 만족해야 한다.
      - null 값은 허용하지 않는다.
      - 유일해야 한다.
      - 변해선 안된다.
  • 테이블의 기본 키를 선택하는 전략은 크게 2가지가 있다.
    - 자연키
      - 비즈니스에 의미가 있는 키
      - 예 : 주민등록번호, 이메일, 전화번호
    - 대리키
      - 비즈니스와 관련 없는 임의로 만들어진 키, 대체 키로도 불린다.
      - 예: 오라클 시퀀스, auto_increment
  • 자연키보다는 대리키를 권장한다.
    - 자연키와 대리키는 일장일단이 있지만 될 수 있으면 대리키의 사용을 권장한다.
    - 주민등록번호를 키로 하면될 것 같지만 미래에는 변하지 않는다는 보장이 없다. (비즈니스 환경은 언젠가 변한다.)
    - JPA는 모든 엔티티에 일관된 방식으로 대리키 사용을 권장한다.
    - 비즈니스 요구사항을 계속해서 변하는데 테이블은 한번 정의하면 변경하기 어렵다. 따라서 대리키를 키로 설정하는걸 권장한다.

 

데이터 접근 기술 - 스프링 JdbcTemplate

JdbcTemplate 소개와 설정
  • JdbcTemplate은 spring-jdbc 라이브러리에 포함되어있어서 별도의 복잡한 설정 없이 바로 사용 가능하다.
  • 템플릿 콜백 패턴을 사용하여, JDBC를 직접 사용할때 발생하는 반복작업을 대신 처리해준다.
  • 동적 SQL 을 해결하기 어렵다.
JdbcTemplate 적용1 - 기본
  • itemRowMapper
    - 데이터베이스의 조회 결과를 객체로 변환할 때 사용한다.
    - rowmapper 를 구현해서 그 내부 코드만 채우면 됨
    - resultSet 을 파라미터로 받는다.
JdbcTemplate 적용2,3 - 동적 쿼리 문제, 구성과 실행
  • MyBatis의 가장 큰 장점은 SQL을 직접 사용할떄 동적 쿼리를 쉽게 작성할 수 있음
JdbcTemplate - 이름 지정 파라미터 1
  • JdbcTemplate 에서 파라미터를 binding 할때 순서가 바뀌면 바뀌게 된다.
    - 큰 문제가 발생할 수 있다.
  • 버그 중에서 가장 고치기 힘든 버그는 데이터베이스에 데이터가 잘못 들어가는 버그
    - 코드 고치기 + 데이터를 복구해야함
  • 개발을 할때는 코드를 몇줄 줄이는 편리함도 중요하지만, 모호함을 제거해서 코드를 명확하게 만드는 것이 유지보수 관점에서 매우 중요하다.
  • SqlParamterSource, NamedParameterSource 등을 통해 키값을 통해 관리할 수 있다.
  • RowMapper 에서 BeanPropertyRowMapper.newInstance(**.class); 로 관리할 수 있다.

JdbcTemplate - 이름 지정 파라미터 2, 3
  • BeanPropertyRowMapper 는 ResultSet의 결과를 받아서 자바빈 규약에 맞추어 데이터를 변환한다.
    (리플렉션 같은 기능을 사용한다.)
    - 리플렉션 : https://ebabby.tistory.com/4
 

[Java] 리플렉션 (reflection) 개념 이해하기

리플렉션 들어가며 자바를 처음 배우던 시절 생각해 보면 리플렉션이라는 단어조차 들어 본 적이 없었습니다. 자바를 점점 학습하면서 종종 들어봤지만 그때 당시 '리플렉션을 모르면 사용하지

ebabby.tistory.com

      - Class 의 필드값등을 알아와서 setter, getter 가 있으면 참조하고 없어도 만들어서 속성을 지정해줌
      - Mybatis 에서는 기본 생성자만 있어도 가능함 (https://jasper-rabbit.github.io/posts/mybatis-refector/)

  • 별칭을 통해 데이터 베이스 칼럼 이름과 객체 이름을 일치 시켜 JdbcTemplate, MyBatis 에서 사용함
  • 관례의 불일치
    - 자바 객체는 카멜 표기법을 사용한다.
    - 반면에 관계형 데이터베이스에서는 주로 언더스코어를 사용하는 snake_case 표기법을 사용한다.
      - 과거에는 대소문자를 구분하지 않았음
    - 이렇다보니 BeanPropertyRowMapper 는 언더스코어 표기법을 카멜로 자동 변환해준다.
    - 따라서 item_name 으로 조회해도 setItemName() 에 문제 없이 값이 들어간다.
JdbcTemplate - SimpleJdbcInsert
  • SimpleJdbcInsert 는 datasource를 의존관계 주입을 받는다.
  • usingColumns 를 통해 insert에 사용할 칼럼을 지정할 수 있다. 생략할수도 있다.
  • 로그를 보면 Compiled insert 로그가 나온다.

JdbcTemplate 기능 정리
  • 순서 기반 파라미터 바인딩 지원
  • 이름 기반 파라미터 바인딩 지원
  • insert SQL 을 편리하게 사용할 수 있다.
  • 스토어드 프로시저를 편리하게 호출할 수 있다.
정리
  • 최대 단점은 동적쿼리를 해결하지 못함
  • 동적 쿼리 문제를 해결하면서 동시에 SQL도 편리하게 작성할 수 있게 도와주는 기술이 바로 MyBatis 이다.

 

데이터 접근 기술 - 테스트

테스트 - 데이터베이스 연동, 데이터베이스 분리
  • @SpringBootTest 는 @SpringBootApplication 을 찾아내서 설정으로 사용한다.
  • 테스트 전용 데이터베이스를 별도로 운영하여 다른 환경과 철저하게 분리해야한다.
  • 테스트는 매우 중요한 원칙이 있다.
    - 테스트는 다른 테스트와 격리해야한다.
    - 테스트는 반복해서 실행할 수 있어야 한다.

테스트 - 데이터 롤백
  • 트랜잭션과 롤백 전략
  • 트랜잭션 관리자는 PlatformTransactionManager 를 주입받아 사용하면 된다.
    - TransactionStatus 를 통해 트랜잭션 시작과 롤백을 설정한다.
    - JdbcTemplate CRUD, JdbcInsert의 경우, 트랜잭션동기화매니저 커넥션을 가져와서 사용한다.

 

테스트 - @Transactional
  • 스프링이 제공하는 @Transactional 애노테이션은 로직이 성공적으로 수행되면 커밋되도록 동작함
  • 그런데 테스트에 있으면 테스트가 끝나면 트랜잭션을 자동으로 롤백시켜 버린다.
  • 테스트 케이스가 아닌 경우, 커밋하긴한다.
  • 서비스, 리포지토리에 있는 @Transactional 도 테스트에서 시작한 트랜잭션에 참여한다.
  • 같은 트랜잭션을 사용한다는 것은 같은 커넥션을 사용한다는 뜻이기도 하다.
  • @Rollback(false), @Commit 을 사용하면 롤백이 되지 않는다.

 

테스트 - 임베디드 모드 DB
  • H2 데이터베이스는 자바로 개발되어 있고, JVM안에서 메모리 모드로 동작하는 특별한 기능을 제공함
  • 애플리케이션에서 자바 메모리를 함꼐 사용하는 라이브러리처럼 사용 가능 (임베디드 모드)
  • 임베디드 모드에서 데이터베이스 커넥션 연결이 모두 끊어지면 데이터베이스가 종료될수 있음 (방지하기 위해 DB_CLOSE_DELAY=-1 옵션을 둔다)
  • 임베디드 모드로 할 경우, 테이블을 어떻게 만들어줘야할까?
    - 기본 SQL 스크립트를 사용해서 데이터베이스를 초기화하는 기능이 있음
    - test/resources/schema.sql 로 만들면 된다.
테스트 - 스프링 부트와 임베디드 모드 & 정리
  • spring.datasource.generate-unique-name 옵션으로 테이블 이름을 유니크하지않게 할수있음