우리가 개발을 하다보면 굉장히 짜증나고 위험한 문제 중 하나는 연쇄적인 코드의 수정일 것이다.
이를 방지하기 위해서 우리는 아키텍처를 사용한다.

그런데 이렇게 아키텍처를 구상하고 나름 잘 짜고 있다고 생각했는데.... 연쇄적인 코드의 수정이 필요한 이유 중 하나가
데이터 모델이 수정되니깐 다 수정해야하네... 이라면 꼭 이 글을 읽어보길 바란다.
우리가 아키텍처를 구성하는데 중요하게 보는것 중 하나는 관심사 분리이다.
클린 아키텍처의 경우 동심원 안쪽으로 들어갈 때, 자신의 안쪽에 있는 하나의 레이어에만 의존해야한다.
여기서 우리는 주목해야하는 점이 있다. 그것은 바로 데이터 모델은 왜 여기에 포함하지 않는가 이다.
처음 프로젝트에 들어가고 코드를 작성하다보면 흔히 하는 실수중 하나이다(적어도 나는 그랬었다...)
관심사를 분리해야하고 의존관계를 명확하게 해야하는 것을 알고 있었지만 이를 고려하지 않아서 생긴 사태이다.

위 그림에서 데이터의 흐름을 보면 알 수 있는 것이 데이터는 레이어와 레이어를 오가는 존재이다.
여기서 데이터는 "데이터" 그 자체를 의미하지 절대 데이터 모델까지 의미하지 않는다.
코틀린으로 예를 들자면
data class UserDataModel(
val id: String,
val name: String,
val email: String,
val isActive: Boolean
)
위의 데이터가 아닌 "클래스"는 절대 자유롭게 오가면 안된다...
그렇다면 데이터 모델은 레이어마다 다시 만들어줘야 하는가???
결론적으로 말하면 그렇다....
만약 데이터 레이어에서 해당 모델을 썼다면, 프레젠테이션 레이어나 도메인 레이어에서는 구조는 같을지언정 다른 클래스를 만들고, 변환하는 매퍼를 만들어주는것이 좋다.

// DTO 클래스 정의
data class UserDTO(
val id: String,
val name: String,
val email: String,
val isActive: Boolean
)
data class UserDomainModel(
val userId: String,
val fullName: String,
val contactEmail: String,
val status: String
)
// 매퍼 클래스 정의
class UserDTOMapper(
private val activeStatusLabel: String, // 상태를 나타내는 프로퍼티
private val inactiveStatusLabel: String
) {
// DTO -> Domain 변환
fun mapToDomain(dto: UserDTO): UserDomainModel {
return UserDomainModel(
userId = dto.id,
fullName = dto.name,
contactEmail = dto.email,
status = if (dto.isActive) activeStatusLabel else inactiveStatusLabel
)
}
// Domain -> DTO 변환
fun mapToDTO(domainModel: UserDomainModel): UserDTO {
return UserDTO(
id = domainModel.userId,
name = domainModel.fullName,
email = domainModel.contactEmail,
isActive = domainModel.status == activeStatusLabel
)
}
}
// 메인 함수에서 매퍼 사용
fun main() {
// 매퍼 인스턴스 생성 (상태를 설정)
val userMapper = UserDTOMapper(
activeStatusLabel = "Active",
inactiveStatusLabel = "Inactive"
)
// DTO 생성
val userDTO = UserDTO(
id = "001",
name = "John Doe",
email = "john.doe@example.com",
isActive = true
)
// DTO -> Domain 변환
val userDomainModel = userMapper.mapToDomain(userDTO)
println("Domain Model: $userDomainModel")
// Domain -> DTO 변환
val newUserDTO = userMapper.mapToDTO(userDomainModel)
println("DTO: $newUserDTO")
}
위와 같이 각각 데이터 모델을 만들어주고 매퍼를 통해 레이어간 분리를 확실하게 해주자!
'개발 > 아키텍처' 카테고리의 다른 글
| [Architecture] DataResource (0) | 2025.09.11 |
|---|---|
| [Architecture] 클린 아키텍처와 앱 아키텍처(Google) (6) | 2025.08.12 |