카테고리 없음

2024-05-08 [Kotlin+Spring DTO(Data Transfer Object), Domain Model]

Glen_check 2024. 5. 8. 15:49

DTO 그리고 Domin Model 을 학습하기 전,

Web Application을 만들기 위해 필요한 요구사항들과 Spring에서 일반적으로 많이 사용하는 Layer 구조를 짚고 넘어가려 합니다.

 

 

Web Application을 만들기 위해 필요한 요구사항

1. 클라이언트 혹은 Frontend Application의 요청을 처리하고 적절한 응답을 줄 수 있어야 합니다.

2. 예외 처리를 할 수 있고, 예외가 발생했을 때 적절한 응답을 줄 수 있어야 합니다. (예외가 발생할 수 있는 상황을 사전에 대비)

3. 인증과 인가 처리를 할 수 있어야 합니다. 

 

인증과 인가 처리의 차이점이 무엇인가요?

[인증]

인증은 사용자의 신원을 검증하는 행위로서 보안 프로세스에서 첫 번째 단계입니다. 

인증 프로세스는 다음과 같이 구성됩니다.

  • 비밀번호 : 사용자 이름과 비밀번호는 가장 많이 사용되는 인증 요소입니다. 사용자가 데이터를 올바르게 입력하면 시스템은 아이덴티티가 유효하다고 판단하고 액세스를 허용합니다.
  • 일회용 핀 : 단일 세션이나 트랜잭션에 한하여 액세스를 허용합니다.
  • 인증 앱 : 액세스를 허용하는 외부 기관을 통해 보안 코드를 생성합니다.
  • 생체인식 : 사용자가 시스템에 액세스하기 위해 지문이나 망막 스캔을 제출합니다. 

상황에 따라 인증 요소를 2가지 이상 성공적으로 확인해야만 시스템에 액세스할 수 있는 여러 사이트들이 등장하고 있고,

이러한 다중 요소 인증(MFA) 요건이 배포되어 비밀번호의 한계를 넘어 보안을 강화하는 경우도 증가하고 있습니다.

 

[인가(권한 부여)]

시스템 보안에서 인가란, 사용자에게 특정 리소스나 기능에 액세스할 수 있는 권한을 부여하는 프로세스를 말합니다. 이 용어는 흔히 액세스 제어나 클라이언트 권한을 서로 대체하여 사용되기도 합니다.

대표적으로 서버에서 특정 파일을 다운로드 할 수 있는 권한을 부여하거나, 개별 사용자에게 관리자 권한으로 애플리케이션에 액세스할 수 있는 권한을 부여하는 경우가 여기에 해당합니다.

보안 환경에서 권한 인증은 항상 인증 이후에 진행되어야 합니다. 사용자가 먼저 자신의 자격 증명을 입증하면 기업의 관리자가 해당 사용자에게 요청한 리소스에 액세스할 수 있는 권한을 부여합니다.

 

4. 비즈니스 로직을 처리할 수 있어야 합니다.

5. Transaction 관리 전략이 있어야 합니다.

(결제 시스템을 예를 들어보면 (1) 판매처에 송금하기, (2) 판매처에서 송금받기 를 진행하고 있다하면, (1)은 성공했지만 (2)가 실패를 하게되면, 작업의 실행하기 전 상태로 돌리(rollback)는것을 하는 것이 트렌젝션입니다.)

6. 스토리지 및 다른 외부 시스템과 통신할 수 있어야 합니다.

 

Spring 의 Layer 구조

 

위에서 설명한 요구사항들을 처리하기 위해 Spring을 통해 개발할 시 일반적으로 Layer(계층)를 나누는데요,

Layer를 나누는 이유는 관심사의 분리(Seperation Of Concerns)를 위해서 입니다. 관심사의 분리를 통해서 코드의 재사용성, 유지보수성을 높일 수 있습니다.

Layer를 분리하는 방식은 여러가지가 있겠으나 일반적으로 많이 쓰는 방식으로, (Web Layer)  (Service Layer) (Repository Layer)로 구성됩니다.

 

Web Layer (Controller)

  • Web Layer는 Application의 최상위 Layer로,  웹 클라이언트의 요청 및 응답을 처리하는 레이어이다.
  • 서비스 계층, 데이터 엑세스 계층에서 발생하는 Exception을 처리해준다. (Exception Handlers)
  • 인증과 인가 처리를 담당합니다. (Filters)

Service Layer (Business Layer)

  • 애플리케이션 비즈니스 로직 처리와 비즈니스와 관련된 도메인 모델의 적합성 검증합니다.
  • Transaction(DB 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산들) 관리하며 경계의 역할을 수행합니다.
    • 트랜잭션 ACID
      • Atomicity (원자성) : Transaction 내의 작업들은 모두 성공 또는 모두 실패해야 합니다.
      • Consistency (일관성) : 모든 Transaction 일관성 있는 DB 상태를 유지합니다. (EX. DB의 무결성 제약 조건 항상 만족)
      • Isolation (격리성) : 동시에 실행되는 트랜잭션들은 서로 영향을 미치지 않아야 합니다. (EX. 동시에 같은 데이터 수정 X)
      • Durability (지속성) : 트랜잭션이 성공적으로 끝나면 그 결과는 항상 기록되어야 합니다.
  • Web Layer 와 Repository Layer 사이를 연결하는 역할로서 두 계층이 직접적으로 통신하지 않도록 해야 합니다.
  • Application Service, Infrastructure Service로 나뉘어집니다.
    • Application Service: 요청의 처리에 대한 주요 로직을 담당하고, 최종적으로 응답을 WebLayer에 넘겨주는 역할을 합니다.
    • Infrastructure Service: 데이터 베이스, 이메일 서버 같은 외부 서비스와 통신하는 역할을 합니다. Application Service에서 Infrastructure Service를 사용합니다.

Repository Layer (Data Access Layer)

  • 가장 하위에 존재하는 Layer입니다.
  • 데이터베이스와 통신하는 역할을 담당합니다.

 

정리하자면 Web Layer가 Service Layer를 호출, 다시 Service Layer에서 Repository Layer를 호출하게 되는 구조인데요,

이제는 각 Layer를 호출할 때 어떤 인터페이스를 통해 호출이 되어야 하는지에 대해 파악할 차례입니다.

크게 보자면 DTO와 Domain Model 이 각 Layer사이의 변수로 넘겨진다고 볼 수 있습니다.

 

DTO(Data Transfer Object)에 대해

DTO(Data Transfer Object)는 계층간 데이터 교환을 위해 사용하는 객체로 쉽게 말해, 데이터를 담을 수 있는 간단한 객체를 의미합니다.

Application 내에서 각 Layer 사이의 데이터를 전달하는데 쓰이며, 응답과 요청 또한 DTO로 표현될 수 있습니다.

 

Spring boot와 JPA를 사용하다 보면, Enitity 클래스의 중요성과 민감성에 대해서 알 수 있습니다.

Entity 클래스는 데이터베이스와 맞닿는 핵심 클래스이며, Entity 클래스를 기준으로 테이블이 생성되고 스키마가 변경됩니다.

그렇기 때문에 다양한 계층에서 Entity를 직접적으로 사용하게 된다면 원치 않게 Entity의 속성을 변경시킬 위험이 존재하며, Entitiy의 모든 속성이 불필요하게 외부에 노출될 가능성이 있습니다.

그래서 우리는 DTO를 사용합니다.
Entity 클래스에서 필요한 데이터만 선택적으로 DTO에 담아서 생성해 사용함으로써, Entitiy 클래스를 감추며 보호할 수 있습니다.

때문에 DTO의 사용은 당연히 사용 되어야하는 패턴입니다

 

 

Domain Model

Domain Model은 Domain Service, Entity, VO(Value Object) 를 포함하는 개념입니다.

 

[Domain Service]

도메인에 대한 특정 로직을 수행하는 Stateless 한 Class 입니다.

(여기서 도메인은 우리가 만드는 Application을 통해 해결하고자 하는 문제라 할 수 있습니다.)

기본적으로 비즈니스 로직들은 Entity나 Value Object에 담기는 것을 권장하지만, 특정 객체가 책임을 가지기 애매한 경우가 있는데 이 때, Domain Service를 사용합니다.

 

[Entity]

Database에 저장될 수 있는 Data를 표현하는 객체로 table과 대응됩니다. Entity의 Instance는 Table의 한 Row와 대응됩니다.

물건을 판매하는 사이트로 예시를 들자면 주문, 회원, 상품과 같은 도메인 레이어의 핵심 객체들은 Entity를 이용해 표현됩니다.

각각의 Entity들은 고유 식별자를 가져 구분이 가능합니다. 예를 들면, 주문 id를 제시하면 그와 일치하는 단 하나의 주문 정보를 불러올 수 있습니다.

도메인 레이어의 많은 비즈니스 로직들은 이 Entity가 가지게 됩니다.

 

[VO(Value Object)]

값을 표현하는 객체로, Entity와 Lifecycle을 함께합니다. Entity가 갖고 있는 속성 중 하나라 할 수 있습니다.

Value Object들은 금액이나 색깔과 같이 그 내용을 기반으로 다른 Value Object와 같은지 판별 가능합니다.

Spring에서는 Value Object를 Embeddable annotation으로 정의합니다. 말 그대로 다른 Entity에 끼워 넣어질 수 있기 때문에 지어진 명칭입니다.

 

++ 내용보충

 - 위 그림처럼, DTO는 Web Layer와 Service Layer에서 사용됩니다. Web Layer는 DTO를 input으로 받고, DTO를 응답합니다. 각각 Request와 Response에 대응된다 볼 수 있습니다.

 - Service Layer는 Web Layer로 부터 DTO 혹은 Basic Type(Int, String …) 을 넘겨 받아 로직을 수행한 후 다시 DTO를 WebLayer에 응답합니다. Service Layer는 내부에서 로직을 수행하기 위해 Domain Model을 사용합니다.

 - Repository Layer는 Entity와 BasicType 을 파라미터로 받고, Entity를 응답합니다.