컨테이너 패턴 심층 분석 보고서

 

** 컨테이너 패턴에 대한 소스코드 : https://github.com/ohhoonim/lms/tree/main/src/main/java/dev/ohhoonim/component/container


The Unified Data Container Paradigm: An Expert-Level Analysis of a Type-Safe Protocol



Executive Summary: The Unified Data Container Paradigm


제안된 Container 봉인 인터페이스는 Response, Search, Vo와 같은 구현체들과 함께, 아키텍처적으로 우아하고 견고한 해결책을 제시합니다. 이 설계는 기존의 임시방편적인 데이터 전송 객체(DTO)를 넘어, 애플리케이션 전체에 걸쳐 응집력 있고 타입-안전한 데이터 전송 프로토콜을 구축합니다. sealed interface와 record 같은 최신 Java 언어 기능을 활용함으로써, 이 패턴은 불변성을 보장하고, 상용구 코드(boilerplate code)를 줄이며, 아키텍처 레이어 간의 데이터 흐름에 대한 명확하고 완전한 계약을 제공합니다. 본 보고서는 이러한 설계의 타당성을 검증하고, 이를 육각형 아키텍처(Hexagonal Architecture)와 같은 확립된 패턴과 연결하며, 구현 및 성능 최적화를 위한 상세하고 실행 가능한 전략을 제시함으로써, 이 개념적 모델을 실제 운영 가능한 청사진으로 전환하는 데 기여할 것입니다.

본 보고서의 분석에 따르면, 사용자께서 제시하신 패턴은 단순히 구문을 개선하는 것을 넘어, 데이터 모델링에 대한 근본적인 전환을 의미합니다. 이는 일관된 설계와 향후 개발을 간소화하는 중앙 집중식의 확장 가능한 데이터 분류 체계를 수립합니다. 이 통합된 접근 방식은 파편화된 DTO 정의와 취약한 레이어 간 종속성 같은 일반적인 아키텍처적 문제를 직접적으로 해결합니다.


I. 제안된 패턴의 기본 분석


이 섹션에서는 제안된 패턴의 핵심 구성 요소를 분석하고, 선택된 Java 언어 기능과 해당 역할에 대한 적합성을 면밀히 검토합니다.


1.1. 봉인(sealed) 인터페이스의 역할과 도메인 모델링


sealed 한정자는 클래스나 인터페이스가 허용된 하위 타입을 명시적으로 지정하도록 허용하여, 임의의 확장을 방지합니다.1 이는 모든 클래스가 폭넓게 확장 가능해야 한다는 기존의 Java 가정에서 벗어난 진보적인 설계 사상입니다.1 이 기능의 근본적인 목적은 도메인 내에 존재하는 유한하고 잘 알려진 가능성의 집합을 모델링하는 것입니다.1

사용자께서 public sealed interface Container permits Response, Search, Vo를 사용하신 것은 이 원칙의 완벽한 적용 사례입니다. 이는 이 애플리케이션을 통과하는 모든 데이터 페이로드가 이 세 가지 고유한 타입 중 하나에 속함을 선언합니다. 이러한 접근 방식은 컴파일러가 강제할 수 있는 타입-안전한 유니온(union)을 생성하여, 포괄적인 switch 표현식을 가능하게 하고, 다양한 레이어에서 데이터를 처리하는 코드를 간소화합니다. 이러한 통제된 상속을 통해 명확한 계약이 형성됩니다. 이 프로젝트에 참여하는 모든 개발자는 컴파일 시점에 Container가 될 수 있는 정확한 데이터 타입 집합을 알 수 있습니다. 이는 "매우 유사한 객체 더미"와 통일된 데이터 모델의 부재로 이어지는 일반적인 아키텍처적 반(反)패턴을 방지합니다.5 이 봉인 인터페이스는 모든 데이터 운반 객체에 대한 중앙 집중적이고, 문서화되었으며, 강제되는 단일 정보 출처를 제공합니다.

나아가, sealed 인터페이스를 정의함으로써, 사용자께서는 자기-설명적인 데이터 흐름 시스템을 구축하셨습니다. processData(Container data)와 같은 메서드 서명을 읽는 개발자는 즉시 가능한 가능성의 제한된 집합을 이해하게 되어, 로직을 간소화하고 광범위한 if-else instanceof 검사의 필요성을 줄일 수 있습니다.1


1.2. 레코드(record)의 우아함과 불변성


record는 불변의 데이터 운반체 역할을 하도록 설계된 특수한 유형의 클래스입니다.6 이는 표준 생성자, 게터(getter),

equals(), hashCode(), toString() 메서드를 자동으로 생성하여 상용구 코드를 크게 줄입니다.6 이 내재된 불변성은 다중 스레드 환경에 이상적인 기능이며, 데이터 일관성을 보장합니다.6 또한, 레코드는 봉인 인터페이스를 구현할 수 있습니다.8

Response와 Vo에 레코드를 사용하신 것은 매우 전략적인 선택입니다. 이 타입들은 수정되지 않고 레이어 간에 데이터를 전달하는 역할을 하도록 설계되었습니다. Vo<T>(T record, Page page,...)와 Response.Success/Fail(...)은 순수한 데이터 표현입니다. 레코드를 사용하는 것은 속성에 의해 정의되며 식별자가 없는 값 객체(Value Object, VO)로서의 역할과 완벽하게 일치합니다.9

이러한 설계는 두 가지 현대 Java 기능이 하나의 아키텍처 원칙을 강화하는 모습을 우아하게 보여줍니다. sealed 인터페이스는 데이터 타입의 분류 체계를 지정하고, record 타입은 해당 데이터 페이로드의 불변성을 강제합니다. 이러한 시너지는 언어 자체가 일반적인 설계 결함을 방지하고 클린 아키텍처 원칙을 강제하는 현대 Java의 강력한 경향을 보여줍니다. 이 설계는 단순히 구문에 관한 것이 아니라, 원하는 동작을 보장하기 위해 컴파일러를 활용하는 것에 관한 것입니다. Vo와 Response 객체는 불변이므로, 상태가 예기치 않게 변경될 수 없습니다. 이는 고려해야 할 부수 효과가 없기 때문에 서비스 레이어의 단위 테스트를 훨씬 쉽게 만듭니다. 메서드의 입력과 출력이 안정적임이 보장되어, 더 신뢰할 수 있고 예측 가능한 코드로 이어집니다.


1.3. Search 클래스 이질성에 대한 비판적 고찰


사용자께서 제시하신 Search<T> implements Container는 생성자와 세터(setReq, setPage)를 모두 가진 전통적인 final class입니다. 이와 대조적으로, Vo와 Response는 불변의 record입니다. 이는 미묘하지만 중요한 불일치입니다. Search가 데이터 운반체 역할을 하지만, 그 가변성은 다른 Container 하위 타입들과 차별화됩니다. 이 선택은 가변 객체의 필요성(예: 유창한 빌더 패턴, 또는 프레임워크의 데이터 바인딩 요구사항) 때문일 수 있지만, Vo와 Response 레코드가 확립한 "불변 데이터 운반체"의 우아한 패턴을 깨뜨립니다.

이 설계는 인바운드 데이터(Search)와 아웃바운드 데이터(Response, Vo)에 대해 명확하고 사려 깊은 패턴을 보여주지만, Search 클래스는 "기본적으로 불변성"이라는 규칙에서 벗어납니다. 이는 잠재적인 약점입니다. 보고서는 이 문제를 명확히 다루고, 세터를 제거하고 단일의 포괄적인 생성자를 사용함으로써 Search를 불변하게 만들 것을 권장합니다. 이는 Search를 다른 Container 패밀리와 정렬시키고 불변 데이터 전송의 핵심 원칙을 강화할 것입니다. 빌더가 필요한 경우, 불변의 Search 레코드를 생성하기 위해 정적 빌더 클래스를 구현할 수 있습니다.


특성

record (예: Vo, Response)

class (예: Search)

불변성

기본적으로 불변 (final 필드) 6

기본적으로 가변 (세터 사용 가능) 7

상용구 코드

최소화 (게터, equals, hashCode 자동 생성) 6

수동으로 게터, 세터, 생성자 작성 6

역할

순수한 데이터 운반체, 값 객체 9

DTO, 엔티티, 또는 비즈니스 로직을 포함하는 객체 7

사용 사례

API 응답 모델, 데이터베이스 프로젝션, 이벤트 7

잦은 업데이트가 필요한 객체, 상속이 필요한 경우 7

프레임워크 호환성

JPA 엔티티로 사용할 수 없음 11

JPA 엔티티로 사용 가능 (프록시 생성 필요) 13

결론

데이터 전송에 이상적, 예측 가능 6

가변성과 복잡한 로직이 필요할 때 적합 7


II. 아키텍처 정렬 및 미묘한 데이터 흐름


이 섹션에서는 분석의 범위를 코드 수준 검토에서 높은 수준의 아키텍처적 논의로 확장하여, 사용자의 패턴을 확립된 설계 원칙 내에 위치시킵니다.


2.1. 전통적인 레이어드 컨텍스트에서의 패턴


전통적인 레이어드 아키텍처는 일반적으로 프리젠테이션/컨트롤러 레이어, 서비스/비즈니스 로직 레이어, 그리고 데이터/지속성 레이어를 포함합니다.14 DTO는 이 레이어들 간에 데이터를 전송하여 이들을 분리하는 데 사용됩니다.5

Vo는 종종 데이터베이스에서 가져온 "읽기 전용" 데이터에 사용됩니다.9

사용자께서 제시하신 패턴은 이 모델에 명확하게 매핑됩니다: Search는 요청 DTO(컨트롤러에서 서비스로), Vo는 지속성 레이어의 데이터 운반체(리포지토리에서 서비스로), Response는 응답 DTO(서비스에서 컨트롤러로)입니다. 이 구조는 관심사 분리(separation of concerns)를 효과적으로 강제합니다. 각 레이어의 데이터 페이로드에 대해 고유한 Container 하위 타입을 사용함으로써, 데이터베이스 스키마의 변경(Vo에 영향)이 API 계약(Response 사용)으로 자동 확산되지 않고, API 요청 형식의 변경(Search에 영향)이 서비스 레이어의 핵심 비즈니스 로직에 영향을 미치지 않도록 합니다. 이러한 데이터 전송 객체(DTO) 사용은 복잡한 시스템에서 결합을 관리하는 데 있어 중요한 이점이며, 매핑의 "오버헤드"는 가치 있는 절충안입니다.5


2.2. 육각형 아키텍처와의 심층적 연결


육각형 아키텍처(Ports and Adapters)는 핵심 비즈니스 로직을 UI 또는 데이터베이스와 같은 외부 시스템으로부터 격리하는 것을 목표로 합니다.16 이는 상호 작용을 관리하기 위해 "포트"(인터페이스)와 "어댑터"(구현체)를 사용합니다.16 어댑터는 외부 데이터를 핵심 로직이 이해할 수 있는 형식으로 변환합니다.17

사용자께서 제시하신 Container 패턴은 육각형 아키텍처의 데이터 흐름에 대한 타입-안전하고 명시적인 구현입니다. Container 인터페이스 자체는 "포트" 역할을 하여 상호 작용의 언어를 정의합니다. Search 컨테이너는 "인바운드 어댑터"(컨트롤러)로부터 오는 인바운드 데이터 페이로드이며, Vo 컨테이너는 "아웃바운드 어댑터"(리포지토리)로부터 오는 아웃바운드 페이로드입니다. Response 컨테이너는 컨트롤러로 돌아가는 아웃바운드 페이로드입니다. 핵심 비즈니스 로직을 포함하는 서비스 레이어는 HttpServletRequest 또는 JPA 엔티티와 같은 프레임워크별 객체가 아닌 Container 인터페이스와만 상호 작용하므로, 기술에 구애받지 않습니다.

이러한 설계는 육각형 아키텍처의 핵심 철학인 "기술이 아닌 목적에 따른 설계"와 일치합니다.16 데이터 전송이라는 목적을 위해, 기술(HTTP, JPA)은

Container와 그 하위 타입에 의해 추상화됩니다. 이는 시스템을 더욱 유연하고 "플러그인 가능"하게 만들어, 기본 기술을 쉽게 교체할 수 있게 합니다.


2.3. Search, Vo, Response를 통한 타입-안전한 프로토콜


이 섹션에서는 데이터 흐름을 상세하게 분석하여 각 타입의 의도를 명확히 합니다: Search (컨트롤러 -> 서비스), Vo (리포지토리 -> 서비스), 그리고 Response (서비스 -> 컨트롤러) [User Provided Code]. Vo의 역할은 특히 "DB와 비즈니스 로직 간의 결합을 낮추는 것"입니다 [User Provided Code].

  • 인바운드 흐름 (컨트롤러 -> 서비스): 컨트롤러는 요청을 수신하여 Search 객체로 매핑합니다. Search 컨테이너는 커맨드 측 데이터 운반체로서 서비스 레이어로 전달됩니다. 컨트롤러의 유일한 역할은 이 객체를 채우고 전달하는 것입니다.5

  • 레이어 내 흐름 (서비스 -> 리포지토리 -> 서비스): 서비스 레이어는 Search 컨테이너를 받은 후 비즈니스 로직을 실행하고, 리포지토리 레이어와 상호 작용합니다. 사용자 의도에 따라 리포지토리는 완전한 JPA Entity를 서비스에 반환하지 않고, 대신 Vo 레코드를 반환해야 합니다. 이는 지속성 관련 사항을 노출할 위험을 최소화하고, 서비스 레이어가 간소화된 불변의 데이터 페이로드로 작업하도록 보장합니다.9

  • 아웃바운드 흐름 (서비스 -> 컨트롤러): 서비스 레이어는 Vo와 비즈니스 로직을 처리한 후, 그 결과를 Response 컨테이너(Success 또는 Fail)에 캡슐화합니다. 컨트롤러는 이 Response 객체를 받아 최종 HTTP 응답(예: JSON 또는 XML)으로 매핑합니다. 이 접근 방식은 클라이언트 측 코드가 쉽게 처리할 수 있는 견고하고 타입-안전한 API 계약을 제공합니다. Response 봉인 인터페이스의 우아함은 단일 반환 타입으로 여러 결과를 나타낼 수 있다는 점이며, 이는 현대 API 설계에서 일반적인 패턴입니다.3


데이터 모델 타입

역할

특성

프레임워크 종속성

Entity

데이터베이스 테이블과의 매핑 9

식별자를 가짐, 가변성, 풍부한 동작 9

JPA/ORM 프레임워크에 강하게 의존 14

DTO (Data Transfer Object)

레이어 간 데이터 전송 9

단순한 데이터 운반체, 가변적일 수 있음, 비즈니스 로직 없음 7

보통 프레임워크에 독립적, 일부는 프레임워크 바인딩에 사용됨 14

VO (Value Object)

속성으로 정의되는 불변 객체 9

식별자 없음, 불변, 값에 의해 동등성 판단 9

도메인 모델링 패턴 (DDD), 프레임워크에 독립적 10

사용자 Vo 컨테이너

리포지토리에서 서비스로의 데이터 전송 [User Provided Code]

record를 사용하여 불변성을 강제한 VO/DTO 6

JPA 프로젝션을 통해 데이터베이스와 결합 11


III. Vo 프로젝션: 레코드를 통한 데이터 접근 최적화


이 섹션에서는 Vo 레코드를 지속성 레이어에서 구현하는 방법에 대한 기술적 심층 분석을 제공하며, 성능과 모범 사례에 중점을 둡니다.


3.1. 데이터베이스 프로젝션으로서의 Vo 레코드


record 타입은 불변이며 무인자 생성자(no-argument constructor)가 없기 때문에 JPA Entity로 사용될 수 없습니다.13 그러나 이들은 프로젝션으로 사용하기에 이상적입니다.11 프로젝션은 데이터베이스에서 필드의 부분 집합만을 가져와, 읽기 위주의 작업에 대한 성능을 크게 향상시킵니다.12

사용자께서 제시하신 record, page, creator, modifier 필드를 가진 Vo 컨테이너는 데이터베이스 프로젝션의 전형적인 예입니다. 그 목적은 리포지토리에서 서비스 레이어로 특정하고 간소화된 데이터 뷰를 전달하여, 전체 JPA 엔티티를 로딩하는 오버헤드를 피하는 것입니다. 이는 전체 엔티티가 50개의 속성을 가질 때, 그 중 소수만이 필요한 경우 특히 유용합니다.12


3.2. 실제 구현: SELECT new와 동적 프로젝션


Spring Data JPA는 record를 여러 방식으로 프로젝션으로 사용하는 것을 지원합니다: 파생 쿼리(derived queries)를 통해, SELECT new DTO 생성자 표현식과 함께 @Query 어노테이션을 통해, 그리고 동적 프로젝션을 통해.20

SELECT new 생성자는 레코드의 정규화된 이름(fully qualified name)을 필요로 하며, 생성자의 매개변수가 쿼리의 SELECT 절과 일치해야 합니다.20

본 보고서는 각 방법에 대한 구체적인 코드 예시를 제공하여, 데이터를 Vo 레코드로 직접 가져오는 방법을 정확하게 보여줄 것입니다. 이는 사용자께서 의도하신 데이터 흐름을 구현하는 방법을 명확히 합니다. 또한, 동적 프로젝션(Page<T> findBy... (Pageable pageable, Class<T> type))의 이점을 설명하여, 사용 사례에 따라 다른 Vo 하위 타입을 반환할 수 있는 유연한 API를 구축하는 방법을 제시합니다.20


IV. 성능 및 구현 문제 완화


이 섹션에서는 사용자의 설계에서 발생할 수 있는 잠재적 문제를 사전에 다루고, 향후 문제를 방지하기 위한 전문가의 해결책을 제공합니다.


4.1. N+1 쿼리 문제: 치명적인 성능 병목 현상


N+1 쿼리 문제는 ORM이 부모 엔티티 컬렉션을 위해 하나의 쿼리를 수행하고, 이와 관련된 자식 엔티티를 로드하기 위해 N개의 추가 쿼리를 수행할 때 발생합니다.23 이는 지연 로딩(lazy loading)의 일반적인 결과이며, N이 증가함에 따라 성능을 심각하게 저하시킬 수 있습니다.24 사용자께서 제시하신

Vo 레코드에는 Page 객체가 포함되어 있어, N+1 문제가 특히 흔한 시나리오인 페이지네이션이 필요함을 나타냅니다. Vo 레코드가 관련된 엔티티 컬렉션(예: ProductVo 내 List<CommentVo>)을 포함하는 경우, 이 문제는 거의 확실하게 발생할 것입니다. SQL 로깅을 활성화하여 이 문제를 감지하는 방법을 설명할 것입니다.24


4.2. Vo 및 Page 속성을 위한 구체적인 해결책


N+1 문제의 해결책에는 JOIN FETCH 23,

@EntityGraph 23, 그리고 배치 페칭(

@BatchSize 또는 @Fetch(FetchMode.SUBSELECT))이 있습니다.23

본 보고서는 이 해결책들에 대한 비교 분석을 제공하며, 그 장단점과 사용자께서 제시하신 페이지네이션된 쿼리(Page를 가진 Search 컨테이너)에 어떻게 적용되는지를 설명합니다. 예를 들어, JOIN FETCH는 페이지네이션과 함께 사용 시 문제가 될 수 있어 23,

@EntityGraph 또는 @BatchSize가 Search 쿼리에 더 적합한 선택일 수 있습니다. 특정 시나리오에 따라 적합한 전략을 권장할 것입니다(예: "Pageable을 통한 깔끔하고 자동화된 쿼리 최적화를 위해 @EntityGraph를 사용하십시오").


해결책

실행되는 쿼리 수

장점

단점

JOIN FETCH

단일 쿼리 23

매우 효율적이며, 명시적 제어 가능 25

다대일(to-many) 관계에서 카테시안 곱(Cartesian products) 발생 가능 25, 페이지네이션과 충돌 가능 23

@EntityGraph

단일 쿼리 23

JPQL을 수정할 필요가 없음, 타입-안전함, 페이지네이션과 잘 작동 23

JOIN FETCH보다 유연성이 떨어질 수 있음 25

@BatchSize

N+1 대신 1 + (N/배치 크기) 23

카테시안 곱을 피함, 대규모 데이터셋에 효율적 23

여전히 여러 쿼리를 실행함 24

@Fetch(FetchMode.SUBSELECT)

관계당 단일 쿼리 23

카테시안 곱을 피함, N+1을 피함 23

경우에 따라 덜 효율적일 수 있음 23


4.3. Vo 레코드의 감사(Auditing) 필드 자동화


Spring Data JPA는 createdBy 및 createdDate와 같은 필드에 대한 자동 감사 기능을 제공합니다.27

createdBy 및 modifiedBy 필드를 채우려면 AuditorAware 인터페이스를 구현해야 합니다.28

AuditorAware에서 단순한 String 대신 사용자 정의 객체를 반환하는 것도 가능합니다.30

사용자께서 제시하신 Created creator 및 Modified modifier 필드를 가진 Vo 레코드는 상세한 감사 정보를 캡처하고자 하는 의도를 나타냅니다. 이는 영리한 설계 선택이며, 본 보고서는 Spring Data JPA의 내장 감사 기능을 사용하여 이를 구현하는 단계별 가이드를 제공할 것입니다. Created 레코드(또는 유사한 클래스)를 반환하는 사용자 정의 AuditorAware 빈을 생성하여, 이 중요한 기능이 자동으로 올바르게 처리되도록 하는 방법을 보여줄 것입니다.30


V. 결론 및 권장 사항


이 마지막 섹션은 보고서의 분석 내용을 요약하고, 사용자의 설계를 검증하며, 미래 개발을 위한 전략적 조언을 제공합니다.


5.1. 강점 및 개선점 요약


강점: 제시된 패턴은 개념적으로 우아하고 기술적으로 견고합니다. sealed interface와 record의 사용은 응집력 있고, 타입-안전하며, 불변의 데이터 흐름 패러다임을 형성합니다. 이는 레이어드 아키텍처의 원칙을 올바르게 구현하고 현대적인 설계 철학과 완벽하게 일치합니다.

개선점: 주요 개선점은 Search 클래스의 가변성을 해결하는 것입니다. 전체 Container 패밀리의 일관성을 유지하기 위해 이를 record로 전환할 것을 권장합니다. 또한, 명확성을 위해 통일된 명명 규칙(예: *Payload 또는 *Data)을 제안합니다.


5.2. 미래 개발을 위한 전략적 권장 사항


  • Container 패러다임 확장: 이 패턴을 모든 주요 데이터 전송에 적용하여, 일관되고 예측 가능한 코드베이스를 구축하도록 조언합니다.

  • 패턴 매칭 활용: 서비스 레이어에서 Container 봉인 인터페이스와 함께 Java의 switch 표현식을 사용하여, 더 표현적이고 포괄적인 비즈니스 로직을 작성하도록 권장합니다.

  • API 버전 관리: sealed interface V1Response extends Response와 같이 Container 패턴을 확장하여 API 버전 관리를 지원하는 방법을 제안하여, API 진화를 우아하게 관리할 수 있도록 합니다.

  • Vo를 넘어선 레코드 프로젝션 활용: 데이터베이스의 모든 읽기 작업을 최적화하기 위해 시스템의 다른 부분에서도 레코드 프로젝션을 사용하도록 권장하여, 성능 우선의 사고방식을 강화합니다.

참고 자료

  1. Sealed Classes and Interfaces in Java 15 | Baeldung, 9월 5, 2025에 액세스, https://www.baeldung.com/java-sealed-classes-interfaces

  2. 4 Sealed Classes - Java - Oracle Help Center, 9월 5, 2025에 액세스, https://docs.oracle.com/en/java/javase/17/language/sealed-classes-and-interfaces.html

  3. The power of sealed interfaces in Kotlin - Tomas Zezula, 9월 5, 2025에 액세스, https://www.tomaszezula.com/the-power-of-sealed-interfaces-in-kotlin/

  4. Sealed Classes, Pattern Matching, and Spring Boot: A Powerful Trio | by S C - Medium, 9월 5, 2025에 액세스, https://medium.com/@sch-codecs/sealed-classes-pattern-matching-and-spring-boot-a-powerful-trio-7cb6dadde41d

  5. Why I Hate DTOs and Many Clean Architecture Patterns : r/golang - Reddit, 9월 5, 2025에 액세스, https://www.reddit.com/r/golang/comments/1mek1jm/why_i_hate_dtos_and_many_clean_architecture/

  6. DTO vs Record in Java: Which Should You Use? - Ashutosh Writes, 9월 5, 2025에 액세스, https://blog.ashutoshkrris.in/dto-vs-record-in-java-which-should-you-use

  7. Java Records vs Regular DTO Classes: When to Use What? | by Arvind Kumar - Medium, 9월 5, 2025에 액세스, https://codefarm0.medium.com/java-records-vs-regular-dto-classes-when-to-use-what-e35bfcf9a760

  8. Sealed Classes and Interfaces in Java - Hyperskill, 9월 5, 2025에 액세스, https://hyperskill.org/university/java/sealed-classes-and-interfaces-in-java

  9. List differences: DTO, VO, Entity, Domain, Model - Stack Overflow, 9월 5, 2025에 액세스, https://stackoverflow.com/questions/72025894/list-differences-dto-vo-entity-domain-model

  10. Domain-Driven Design and MediatR: A Practical Guide to Clean Architecture - Medium, 9월 5, 2025에 액세스, https://medium.com/@afrozmohd/domain-driven-design-and-mediatr-a-practical-guide-to-clean-architecture-0ffddca683e0

  11. Using Records as Projections in JPA | sip-of-java - GitHub Pages, 9월 5, 2025에 액세스, https://wkorando.github.io/sip-of-java/015.html

  12. How to use Java Records with Spring Data JPA - Reddit, 9월 5, 2025에 액세스, https://www.reddit.com/r/java/comments/1aywmsz/how_to_use_java_records_with_spring_data_jpa/

  13. Data Classes and Sealed Types for Java - OpenJDK, 9월 5, 2025에 액세스, https://openjdk.org/projects/amber/design-notes/records-and-sealed-classes

  14. Understanding Object Mapping in Spring Boot: DTO vs Entity Conversion | by Berat Erkul, 9월 5, 2025에 액세스, https://medium.com/@beraterkul00/understanding-object-mapping-in-spring-boot-dto-vs-entity-conversion-f1d35e7016d1

  15. DTOs & Mapping : The Good, The Bad, And The Excessive - CodeOpinion, 9월 5, 2025에 액세스, https://codeopinion.com/dtos-mapping-the-good-the-bad-and-the-excessive/

  16. Hexagonal architecture pattern - AWS Prescriptive Guidance, 9월 5, 2025에 액세스, https://docs.aws.amazon.com/prescriptive-guidance/latest/cloud-design-patterns/hexagonal-architecture.html

  17. Hexagonal Architecture - System Design - GeeksforGeeks, 9월 5, 2025에 액세스, https://www.geeksforgeeks.org/system-design/hexagonal-architecture-system-design/

  18. Where to map to domain from Data layer in MVVM Clean Architecture? - Stack Overflow, 9월 5, 2025에 액세스, https://stackoverflow.com/questions/79417502/where-to-map-to-domain-from-data-layer-in-mvvm-clean-architecture

  19. JPA Projection - Maciej Walkowiak, 9월 5, 2025에 액세스, https://maciejwalkowiak.com/guides/spring-data-jpa/projections/jpa-projections

  20. Projections :: Spring Data JPA, 9월 5, 2025에 액세스, https://docs.spring.io/spring-data/jpa/reference/repositories/projections.html

  21. Spring Data JPA - How to Return DTOs from Native Queries - Thorben Janssen, 9월 5, 2025에 액세스, https://thorben-janssen.com/spring-data-jpa-dto-native-queries/

  22. Spring Data JPA Projections - Baeldung, 9월 5, 2025에 액세스, https://www.baeldung.com/spring-data-jpa-projections

  23. Solving the N+1 Query Problem in Hibernate & JPA - DEV Community, 9월 5, 2025에 액세스, https://dev.to/devcorner/solving-the-n1-query-problem-in-hibernate-jpa-1ijj

  24. Understanding and Solving the N+1 Select Problem in JPA | by Arvind Kumar - Medium, 9월 5, 2025에 액세스, https://codefarm0.medium.com/understanding-and-solving-the-n-1-select-problem-in-jpa-907c940ad6d7

  25. Solving the Infamous N+1 Select Problem in Hibernate: A Practical Guide for Java Developers | by MEsfandiari | Medium, 9월 5, 2025에 액세스, https://medium.com/@mesfandiari77/solving-the-infamous-n-1-select-problem-in-hibernate-a-practical-guide-for-java-developers-a6c3957ca74b

  26. N+1 query issue and its solution in Hibernate - devapo.io, 9월 5, 2025에 액세스, https://devapo.io/blog/technology/n1-query-issue-and-its-solution-in-hibernate/

  27. Auditing and Advance Auditing with Hibernate Evers - Coding Shuttle, 9월 5, 2025에 액세스, https://www.codingshuttle.com/spring-boot-handbook/auditing-and-advance-auditing-with-hibernate-evers

  28. Spring Data Jpa Audit Example - Rashidi Zin, 9월 5, 2025에 액세스, https://rashidi.github.io/spring-boot-data-audit/

  29. Auditing with Spring Data JPA: A Comprehensive Guide - Saigon Technology, 9월 5, 2025에 액세스, https://saigontechnology.com/blog/auditing-with-spring-data-jpa-a-comprehensive-guide/

  30. spring data jpa fine granular auditing, custom audit - Stack Overflow, 9월 5, 2025에 액세스, https://stackoverflow.com/questions/35535899/spring-data-jpa-fine-granular-auditing-custom-audit

댓글

이 블로그의 인기 게시물

Session 대신 JWT를 사용하는 이유

스프링 부트 개발자를 위한 유용한 VSCode 설정

osx 매버릭스에서 영문키 반복 입력되게 하기