개발 공부용

Spring - ORM, JPA, 커넥션 풀 본문

Java|Spring

Spring - ORM, JPA, 커넥션 풀

솝제로 2025. 4. 1. 18:28

 

ORM(Object-Relational Mapping)

 

객체 지향 프로그래밍 언어의 객체와 관계형 데이터베이스의 테이블을 자동으로 연결해주는 기술

SQL 대신 객체 중심의 코드로 데이터 조작 가능

 

 

ORM이 제공하는 핵심 기능
  • 객체와 테이블의 매핑: 클래스 <=> 테이블, 객체 필드 <=> 테이블 컬럼 연결 자동화
  • CRUD 기능 자동화: 생성, 읽기, 수정, 삭제 작업을 객체 중심으로 제공
  • 영속성 관리: 객체의 상태를 추적하고 DB에 동기화
  • 트랜잭션: 데이터의 일관성 보장(트랜잭션, 롤백, 커밋 자동 관리)
  • 객체 지향 쿼리 지원: 객체 중심의 쿼리 제공

 

ORM의 단점

 

성능 저하 가능성: 내부적으로 복잡한 작업을 수행하는 ORM

=> 복잡한 조건이나 대량 데이터 처리 시 직접 작성한 SQL 대비 성능 저하 발생

복잡한 쿼리 작성의 한계: SQL 유연성 부족

 

 

JPA(Java Persistance API)

 

자바의 데이터베이스 접근 표준 ORM 기술

 

Hibernate(구현체)

 

JPA 기술 명세를 구현한 라이브러리

자바 코드를 최적화된 SQL로 자동 변환

JDBC를 연동하여 실제로 DB에 쿼리를 보내고 결과 처리

 

 

JPA Repository가 제공하는 기능

 

Entity

  • DB의 테이블과 Java 클래스를 1:1로 연결(mapping)한 객체
  •  영속성 컨텍스트에 의해 관리되어 상태 관리 및 DB 동기화
  • @Entity, @Id, @Column

 

Repository

  • 데이터에 접근하기 위한 인터페이스
  • CRUD 작업 기본 제공
  • 메서드 이름 규칙을 통해 데이터 가져옴.
  • ~ extends JpaRepository<Entity, Id>: ...

 

Persistence Context(창고)

  • JPA에서 관리하는 Entity의 저장소
  • Entity의 생명 주기를 관리하는 컨테이너 역할
  • 1차 캐시의 역할로, 같은 트랜잭션 내에서 같은 Entity를 조회하면 다시 DB를 호출하지 않는다.

 

EntityManager(창고지기/관리자)

  • Persistence Context를 직접 제어하고 접근하는 인터페이스
  • 엔티티의 생명 주기를 관리하는 핵심 객체
  • DB와 상호 작용하기 위한 API 제공
  • 복잡한 트랜잭션 작업 시 사용
  • Repository 내부에서 자동으로 관리

 

JPQL

  • 객체 기반의 쿼리 언어로 SQL과 유사하나 객체와 속성 기반으로 쿼리 작성
  • DB 독립적, 객체 지향적
  • JpaRepository 외의 매우 복잡한 상황은 QueryDSL 추천

 

    @Transactional(readOnly = true)
    public OrderResponse getOrder(Long orderId) {
        Optional<OrderEntity> optOrderEntity = orderJpaRepository.findByOrderId(orderId);
        if(optOrderEntity.isEmpty()){
            throw new EntityNotFoundException("주문 없음");
        }
        return OrderMapper.fromEntity(optOrderEntity.get());
    }

 

@Transactional(readOnly = true)를 해주면

읽기 전용 트랜잭션을 적용하여 변경 감지(Dirty Checking)를 위한 메모리 사용을 줄일 수 있다.

영속성 컨텍스트에 저장된 변경 내용을 DB에 즉시 반영하는 flush()를 생략한다.

 => 속도가 빨라진다.

 

    @Transactional
    public OrderResponse updateTotalAmount(Long orderId, Integer newAmount) {
        Optional<OrderEntity> optOrderEntity = orderJpaRepository.findByOrderId(orderId);
        if(optOrderEntity.isEmpty()){
            throw new EntityNotFoundException("주문 없음");
        }
        OrderEntity orderEntity = optOrderEntity.get();
        orderEntity.changeTotalAmount(newAmount);
//        orderJpaRepository.save(orderEntity);
        return OrderMapper.fromEntity(orderEntity);
    }

 

JPA의 변경 감지에 의해 변경 사항이 감지되고,

트랜잭션 종료시 자동으로 flush()에 의해 해당 내용이 DB에 반영되므로

save(orderEntity)를 해주지 않아도 변경사항이 적용된다.

 

커넥션 풀

 

DB와 연결할 때마다 새로운 커넥션을 생성하면 네트워크 통신, 인증, 세션 생성 등의 비용이 발생한다.

특히 요청이 많을 경우 매번 새 커넥션을 만들면 성능이 크게 저하된다.

따라서 미리 만들어둔 커넥션을 재사용하는 것을 커넥션 풀이라고 한다.

Spring Boot의 기본 JDBC Connection Pool로 HikariCP가 있다.

 

 

HikariCP

 

HikariCP는 Spring Boot에서 기본값으로 사용되므로 별도 설정이 필요하지 않다.

spring:
 datasource:
  hikari:
   maximum-pool-size: 20 #최대 커넥션 수
   minimum-idle: 5 		 #최소 유지 커넥션 수
   idle-timeout: 30000   #미사용 커넥션을 유지할 시간
   connection-timeout: 20000 #커넥션을 가져올 때 기다릴 시간(초과시 오류 발생)

 

'Java|Spring' 카테고리의 다른 글

[JAVA] 가변 인자  (0) 2025.05.16
Spring - Test, AssertJ, TDD  (0) 2025.04.03
Spring - Websocket, Simple Broker, External Broker  (0) 2025.03.28
Spring - 웹소켓과 STOMP  (0) 2025.03.27
Spring - IoC, DI, AOP  (0) 2025.03.26