Skip to content

Seminar/#7 - #11

Open
kaswhy wants to merge 18 commits into
mainfrom
seminar/#7
Open

kaswhy wants to merge 18 commits into
mainfrom
seminar/#7

Conversation

@kaswhy

@kaswhy kaswhy commented Dec 25, 2025 •

Copy link
Copy Markdown
Collaborator

🔥Pull requests

👷 과제 구현

필수과제

  • 댓글 CRUD 추가

구현한 내용에 대해서 설명해주세요

댓글 엔티티를 추가하고, CRUD를 구현했습니다. 유스케이스 엔티티에 대해서 퍼사드 패턴을 추가로 도입할 수 있을 것 같고, 시간 이슈로 레디스나 기타 성능 관련 내용에 대해 깊이 있게 생각해보지 못한 점이 아쉽습니다. 이번 과제는 트랜잭션에 대해서 조금 더 깊이 있게 생각해보면서 구현했고, 구현했을 때의 고민 내용은 아래와 같습니다.


구현하며 고민했던 내용을 적어주세요 (사소한 것도 좋아요)

트랜잭션 설계 관련 고민 및 결정 사항

1. @Transactional 적용 위치에 대한 고민 (클래스 단위 vs 메서드 단위)

유스케이스 분리 구조에서 @Transactional을 클래스 단위로 적용할지, 메서드 단위로 적용할지를 고민했습니다.

트랜잭션은 트랜잭션 경계에 적용하는 것이 원칙이며, 현재 프로젝트에서는 하나의 유스케이스 클래스가 하나의 비즈니스 흐름을 담당하고 있습니다.
즉, 유스케이스 자체가 트랜잭션 경계 역할을 하고 있다고 판단했습니다.

메서드 단위로 트랜잭션을 적용할 경우, 동일한 유스케이스 내에서 트랜잭션 경계가 분산되어 오히려 흐름을 파악하기 어려워질 수 있다고 보았습니다.

이에 따라 다음과 같은 기준으로 판단했습니다.

  • 하나의 유스케이스 = 하나의 트랜잭션 경계
  • 도메인 로직은 트랜잭션 안에서 일관되게 실행되어야 함
  • 예외적인 경우에만 메서드 단위 트랜잭션을 사용

이 기준에 따라, 기본 정책으로 클래스 단위에 @Transactional을 적용하고,
필요한 경우에만 메서드 단위로 분리하기로 결정했습니다.


2. readOnly = true 사용 여부에 대한 고민

조회 유스케이스에서 readOnly = true를 명시적으로 사용하는 것이 의미가 있는지 고민했습니다.

JPA 기준으로 readOnly = true 설정 시 다음 동작이 생략됩니다.

  • Dirty Checking을 위한 스냅샷 생성
  • flush 수행

엔티티 개수가 많아질수록 이 비용은 무시하기 어렵고,
특히 목록 조회나 대량 조회 API에서는 불필요한 오버헤드가 된다고 판단했습니다.

따라서 다음 기준으로 사용 여부를 결정했습니다.

  • 변경 가능성이 없는 조회 유스케이스
  • 엔티티를 조회하더라도 상태 변경이 없는 경우
  • 성능이 중요한 목록/대량 조회 API

위 조건에 해당하는 경우 readOnly = true를 명시적으로 적용하기로 했습니다.


3. 조회 시 트랜잭션 적용 여부에 대한 고민

조회 로직에도 항상 트랜잭션을 적용해야 하는지에 대해 고민했습니다.

트랜잭션을 사용하는 이유는 다음 세 가지로 정리할 수 있습니다.

  1. 여러 변경을 하나의 작업으로 묶기 위한 원자성 보장
  2. 영속성 컨텍스트 유지
  3. Lazy Loading 지원

조회 로직에서는 주로 2번과 3번이 쟁점이 됩니다.

DTO Projection 기반 조회의 경우 다음과 같은 특성이 있습니다.

  • 엔티티를 변경하지 않음
  • 영속성 컨텍스트 유지가 필요 없음
  • Dirty Checking 불필요
  • Lazy Loading 발생하지 않음

이로 인해 DTO Projection 기반 조회에는 트랜잭션을 적용할 필요가 없다고 판단했습니다.

반면, 다음과 같은 경우에는 조회라도 트랜잭션이 필요하다고 보았습니다.

  • Entity를 직접 반환하는 경우
  • Lazy Loading이 필요한 경우
  • OSIV가 비활성화된 환경
  • 복수 쿼리를 조합하여 일관성이 필요한 경우
  • 조회 중 데이터 변경이 허용되지 않아야 하는 경우

이를 기준으로 조회 로직의 트랜잭션 적용 여부를 구분했습니다.

상황 트랜잭션 적용
DTO Projection 적용하지 않음
Entity 반환 + Lazy Loading 없음 적용하지 않음
Entity 반환 + Lazy Loading 필요 적용
단일 쿼리 조회 적용하지 않음
캐시 조회 적용하지 않음
Replica 조회 적용하지 않음
복수 쿼리 간 일관성 필요 적용

4. jakarta.transaction.Transactional vs Spring @Transactional 선택에 대한 고민

트랜잭션 어노테이션으로 jakarta.transaction.Transactional과
org.springframework.transaction.annotation.Transactional 중 어떤 것을 사용할지 고민했습니다.

본 프로젝트는 Spring 트랜잭션 AOP 기반으로 동작하며, 다음과 같은 설정이 필요합니다.

  • 전파 속성
  • 격리 수준
  • readOnly 설정
  • 롤백 조건 제어

이러한 요구사항을 고려했을 때, Spring에서 제공하는
org.springframework.transaction.annotation.Transactional이 더 적합하다고 판단했습니다.

이에 따라 본 프로젝트에서는 Spring 트랜잭션 어노테이션을 사용하기로 결정했습니다.


🚨 참고 사항

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant