[내일배움캠프Spring-54일차] JPA 심화 강의 (중요한 부분만 되짚기!)

2025. 5. 2. 20:36·백엔드 부트캠프/TIL

✅ DB H2

- 내장형 H2 데이터베이스

H2는 Server Mode, In-memory Mode, Embeded Mode라는 세가지 방식으로 사용할 수 있다.

1. Server Mode

  • 서버 모드는 현업에서 사용하는 모드로 컴퓨터에 DB 엔진을 설치하고 엔진을 구동하여 사용하는 방식입니다.
  • 애플리케이션과 DB가 분리되어 있기 때문에 여러 애플리케이션에서 동일한 DB를 사용하기에 적합합니다.

- 직접 엔진을 설치하여 사용하는 방식.

- 애플리케이션과 상관 없는 외부에서 DB 엔진이 구동된다.

- 데이터가 애플리케이션 외부에 저장되므로 애플리케이션을 종료해도 데이터가 사라지지 않는다.

2. In-memory Mode

  • 인메모리 모드는 애플리케이션에 DB 엔진이 내장되어 애플리케이션과 함께 실행되고 종료되는 방식입니다.
  • 데이터가 애플리케이션의 메모리에 저장되기 때문에 애플리케이션이 종료되면 모든 데이터가 사라지는 휘발성의 특징을 갖고 있습니다.
  • 이러한 특징으로 인해 단위 테스트 등에서 많이 사용됩니다.
  • 스프링부트 프로젝트에서 H2를 인메모리 모드로 사용하려면 application.yml 또는 application.properties에서 아래와 같이 설정하면 됩니다.

- 엔진을 설치하지 않고 애플리케이션 내부의 엔진을 사용하는 방식.

    - `build.gradle` 및 `application.properties` 설정을 통해 실행 가능하다.

- 애플리케이션을 실행하면 DB 엔진이 함께 실행되고 애플리케이션을 종료하면 DB 엔진이 함께 종료된다.

    - 데이터가 애플리케이션의 **메모리**에 저장되기 때문에 애플리케이션을 종료하면 데이터가 사라진다.

# application.yml
spring:  
    datasource:    
        driver-class-name: org.h2.Driver
        url: jdbc:h2:mem:{DB 이름}
        username: sa
        password:

# application.properties
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:{DB 이름}
spring.datasource.username=sa
spring.datasource.password=

3. Embedded Mode

  • 임베디드(내장) 모드는 인메모리 모드와 동일하게 애플리케이션에 DB 엔진이 내장되어 애플리케이션과 함께 실행되고 종료되는 방식입니다.
  • 인메모리 모드와 다른 점은 데이터를 로컬에 저장하기 때문에 데이터 휘발에서 자유롭다는 점입니다. 이로 인해 간단한 애플리케이션에서 사용하기 좋습니다.
  • 스프링부트 프로젝트에서 H2를 임베디드 모드로 사용하는 방법은 url을 제외하고 동일하게 설정해주면 됩니다.

    - 엔진을 설치하지 않고 애플리케이션 내부의 엔진을 사용하는 방식.

        - `build.gradle` 및 `application.properties` 설정을 통해 실행 가능하다.

    - 애플리케이션을 실행하면 DB 엔진이 함께 실행되고 애플리케이션을 종료하면 DB 엔진이 함께 종료된다.

    - 데이터가 애플리케이션 **외부**에 저장되므로 애플리케이션을 종료해도 데이터가 사라지지 않는다.

# application.yml
spring:
  datasource:
      driver-class-name: org.h2.Driver
      url: jdbc:h2:{DB가 저장될 경로}    
      username: sa    
      password:
      
# application.properties
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:{DB가 저장될 경로}
spring.datasource.username=sa
spring.datasource.password=

✅ DB 드라이버

- 드라이버의 역할: 데이터베이스 드라이버는 애플리케이션과 데이터베이스 간의 통신을 중개하는 역할을 합니다. 마치 우체부가 편지를 전달하는 것처럼, 드라이버는 애플리케이션의 요청을 데이터베이스가 이해할 수 있는 언어로 변환합니다.

- 드라이버의 종류: 다양한 데이터베이스 시스템마다 호환되는 드라이버가 있습니다. 예를 들어, Oracle, MySQL, PostgreSQL 등 각 데이터베이스 제품에 맞는 특정 드라이버가 필요합니다.

✅ My Batis 

- MyBatis 는 RowMapper 가 가지고있는 단점인 “반복되는 코드”를 줄이고 “함께있는 프로그램 코드와 쿼리 코드를 분리하여 관리”하고 싶은 니즈를 반영하여 탄생하였습니다. 

  • SQL Mapper 두번째 주자로 MyBatis 탄생
    • 반복적인 JDBC 프로그래밍을 단순화 하고싶다.
    • SQL 쿼리들을 XML 파일에 작성하여 코드와 SQL 을 분리 하고싶다.
  • MyBatis 특징
    • jdbc로 처리하는 코드의 설정(Connection) 부분을 줄이고 실제 sql문에 연결함으로서 빠른 개발이 가능하게 한다. (SQL Mapper 특징)
    • MyBatis 코드는 map 인터페이스(또는 클래스)와 SQL 쿼리와 ResultSet 매핑을 위한 xml 및annotation을 사용한다.
    • 다른 방식에 비해 객체자체보다 쿼리에 집중할 수 있다.\
  • MyBatis 한계점
    • 결국 SQL을 직접 작성하는것은 피곤하다…(DB 기능에 종속적) 
    • 테이블마다 비슷한 CRUD 반복, DB타입 및 테이블에 종속적이다. 

 ✅ RDB 와 ORM

- 우리가 JAVA 를 사용하는 거면, 중요하게 짚고 넘어가야하는 것이 있다.

1. RDB와 Java의 패러다임 차이

RDB (관계형 데이터베이스)

  • 데이터 중심: 데이터는 테이블(행과 열)로 구성됨.
  • 정규화: 중복을 최소화하고 참조를 통해 관계를 표현 (예: user_id를 다른 테이블에서 참조).
  • 관계(Relation): 외래 키를 통해 여러 테이블을 조합해서 하나의 결과를 만들도록 설계.

Java (또는 대부분의 객체지향 언어)

  • 객체 중심: 현실 세계의 개념을 클래스와 객체로 표현.
  • 포함(Composition) 중심 설계: 다른 객체를 포함시켜 관계를 표현함.
  • 행위(Behavior)와 상태(State)를 함께 다룸.

2. 패러다임 충돌

측면 RDB JAVA
데이터 표현 테이블(정규화된 구조) 객체(캡슐화, 포함 관계)
관계 표현 외래 키, JOIN 객체 간 참조 (has-a 관계)
데이터 접근 SQL로 질의 (절차적 접근) 메서드 호출로 객체 조작
상태 관리 정적 데이터 중심 동적 객체 상태, 생명 주기 관리

 

  • 테이블과 객체의 구조가 일대일로 매칭되지 않음.
  • 객체의 계층적 구조를 테이블로 표현하기 어려움.
  • SQL을 직접 작성하고, 결과를 객체로 수동 변환해야 함 (반복 코드 증가).

3. 그래서 등장한 ORM

- ORM(Object-Relational Mapping)은 이 둘을 연결해주는 "자동 매핑 도구"입니다.

4. ORM의 핵심 역할:

  • 자바 클래스 ↔ 데이터베이스 테이블 자동 매핑
  • 객체의 속성 ↔ 테이블의 컬럼 자동 매핑
  • 객체 관계 ↔ 외래 키 관계 매핑
  • SQL을 직접 작성하지 않고도 CRUD 수행 가능

> 대표 ORM 프레임워크:

  • Java에서는 Hibernate, JPA(Java Persistence API) 가 대표적.

5. ORM 도입의 장점

  • 생산성 향상: SQL 작성이 줄고, 반복 코드 감소.
  • 유지보수 용이: 테이블 구조 변경 시 Java 코드만 수정하면 됨.
  • 객체 지향적으로 코드 구성 가능: OOP의 장점을 살릴 수 있음.
  • 트랜잭션, 캐싱 등 부가 기능 제공: 성능과 안정성 향상.

6. ORM이 필요한 이유 요약

- 관계형 DB는 테이블 중심이고, Java는 객체 중심이기 때문

- 구조가 다르므로 매핑을 자동화하는 기술이 필요함

- 객체와 관계형 테이블 간의 불일치를 해소하기 위해 ORM 도입

✅ 쓰기지연

1. 쓰기 지연이 발생하는 시점

  • flush() 동작이 발생하기 전까지 최적화한다.
  • flush() 동작으로 전송된 쿼리는 더이상 쿼리 최적화는 되지 않고, 이후 commit()으로 반영만 가능하다.

2. 쓰기 지연 효과

  • 여러개의 객체를 생성할 경우 모아서 한번에 쿼리를 전송한다.
  • 영속성 상태의 객체가 생성 및 수정이 여러번 일어나더라도 해당 트랜잭션 종료시 쿼리는 1번만 전송될 수 있다.
  • 영속성 상태에서 객체가 생성되었다 삭제되었다면 실제 DB에는 아무 동작이 전송되지 않을 수 있다.
  • 즉, 여러가지 동작이 많이 발생하더라도 쿼리는 트랜잭션당 최적화 되어 최소쿼리만 날라가게된다.

- 하지만, Indentity 같은 경우에는 쓰기지연 적용이 안된다.

✅ 객체끼리의 관계

@OneToOne

  • 일대일 관계를 나타내는 매핑 정보
  • 1:1 관계를 지정하기에 앞서 이것이 꼭 물리적으로 테이블이 분리되어야 하는지에 대해 생각해 봐야 합니다.
  • 1:1 관계로 구성 한다는 것은 결국 하나의 목적에 부합되는 공통된 데이타를 관리한다고 볼 수 있으며 이것은 하나의 테이블에서 관리 할 수 있는 데이타일 가능성이 높다는 의미입니다.
  • 즉, 의도적 중복이 아니라면 사용할일이 없다는 말
    • 의도적 중복 예시) 버블 구독상품을 사서 채팅방이 생길경우. 구독상품과 채팅방은 1:1 관계

@OneToMany

  • 일대다 관계를 나타내는 매핑 정보
  • @OneToMany가 단방향으로 쓰이면 문제가 발생할 수 있다.
  • 속도를 위해 기본적으로 FetchType 설정이 LAZY 로 설정되어 있습니다.
  • 속성
    • mappedBy : 연관관계의 주인 필드를 선택한다.
    • fetch : 글로벌 페치 전략 설정
    • cascade : 영속성 전이 기능을 사용한다.
    • targetEntity : 연관된 엔티티의 타입 정보를 설정한다.

@ManyToOne  

  • 다대일 관계를 나타내는 매핑 정보
  • 속성
    • optional (default true) : false로 설정하면 연관된 엔티티가 반드시 있어야 함.
    • fetch : 글로벌 패치 전략 설정
      • ✋ 기본이 EGEAR 로 설정되어있으나 실무에서는 기본 LAZY로 설정하는것 추천!
    • cascade : 영속성 전이 기능 사용
    • targetEntity : 연관된 엔티티의 타입 정보 설정 (targetEntity = Member.class 식으로 사용)

@JoinColumn

  • 외래 키 매핑 시 사용 (Join 을 요청하기 위한 매핑정보로 쓰인다.)
  • @ManyToOne 어노테이션과 주로 함께 쓰인다. (조인대상 컬럼 지정기능을 안쓸거면 생략해도 됨)
  • name 속성은 매핑할 외래키의 이름
  • 어노테이션을 생략해도 외래 키가 생성됨.
    • 생략 시 외래키의 이름이 기본 전략을 활용하여 생성된다.
  • 속성
    • name : 매핑할 외래 키의 이름
    • referencedColumnName : 외래 키가 참조하는 대상 테이블의 컬럼명
    • foreignKey : 외래 키 제약조건 지정 (테이블 생성 시에만 적용됨)
    • unique/nullable/insertable/updateable/columnDefinition/table : @Column의 속성과 같음

'백엔드 부트캠프 > TIL' 카테고리의 다른 글

[내일배움캠프Spring-56일차] 주특기 플러스 과제 SpringSecurity 로 전환하기 !  (0) 2025.05.07
[내일배움캠프Spring-55일차] Qeury Dsl 설정하기  (0) 2025.05.07
[내일배움캠프Spring-53일차] Spring Security에서 세션 기반 인증 vs JWT 기반 인증  (0) 2025.05.01
[내일배움캠프Spring-52일차] 트랜잭션 복습  (0) 2025.04.30
[내일배움캠프Spring-51일차] AOP 로깅 처리 를 구현하자 !  (0) 2025.04.29
'백엔드 부트캠프/TIL' 카테고리의 다른 글
  • [내일배움캠프Spring-56일차] 주특기 플러스 과제 SpringSecurity 로 전환하기 !
  • [내일배움캠프Spring-55일차] Qeury Dsl 설정하기
  • [내일배움캠프Spring-53일차] Spring Security에서 세션 기반 인증 vs JWT 기반 인증
  • [내일배움캠프Spring-52일차] 트랜잭션 복습
sintory-04
sintory-04
🚀🚀🚀
  • sintory-04
    Sintory Dev Blog
    sintory-04
    글쓰기 관리
  • 전체
    오늘
    어제
    • 분류 전체보기 (289)
      • 백엔드 부트캠프 (111)
        • TIL (97)
        • WIL (0)
        • 문제풀이 (7)
        • 기타 (6)
      • 백엔드 부트캠프[사전캠프] (35)
        • TIL (16)
        • 문제풀이 (17)
        • 기타 (1)
      • Troubleshooting (11)
      • 코딩 공부 (118)
        • Java (28)
        • Baekjoon-Java (24)
        • Programmers-Java (40)
        • Spirngboot (11)
        • typescript (1)
        • JavaScript (6)
        • Spring 입문 (8)
      • 프로젝트 (8)
        • ToDoApp(FireBase) (3)
        • ToDoApp(Spring) (5)
      • 기타 (4)
  • 블로그 메뉴

    • 소개
    • Github
  • 최근 글

  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.3
sintory-04
[내일배움캠프Spring-54일차] JPA 심화 강의 (중요한 부분만 되짚기!)
상단으로

티스토리툴바