UI 개발을 위한 도메인 모델링: 효과적인 시작을 위한 전략
새로운 프로젝트를 시작할 때 가장 어려운 부분은 어디서부터 시작해야 할지 모른다는 점이다. 깨끗한 코드와 최적의 아키텍처를 구축할 기회가 있지만, 동시에 빈 화면을 마주하면 막막함을 느끼기 쉽다. 이때 유용한 접근 방식이 도메인 모델링(Domain Modeling)이다.
도메인 모델링은 UI를 구축할 때 시스템의 핵심 엔티티(객체)와 그 관계를 정의하는 과정이다. 백엔드 개발자들이 주로 사용하는 개념처럼 보이지만, 프론트엔드에서도 효과적으로 활용할 수 있다. 이를 통해 개발 과정에서 일관된 구조와 네이밍을 정립하고, 유지보수성을 높일 수 있다.
도메인 모델링이란?
도메인 모델링은 시스템에서 중요한 개체(엔티티)와 이들 간의 관계를 정의하는 것을 의미한다. 예를 들어, 음식 배달 서비스(Uber Eats)를 구축한다고 가정해보자. 이 서비스에서는 다음과 같은 엔티티가 존재한다.
•
고객(Customer): 주문을 하는 사용자
•
레스토랑(Restaurant): 음식을 제공하는 업체
•
메뉴 아이템(Menu Item): 주문할 수 있는 개별 음식
•
장바구니(Shopping Cart): 고객이 선택한 음식들을 담아두는 곳
이러한 엔티티들은 단순한 개념이 아니라, 서로 다양한 관계를 가진다. 예를 들어, 고객은 레스토랑을 즐겨찾기에 추가할 수 있고, 여러 메뉴 아이템을 장바구니에 추가할 수 있다.
도메인 모델링의 필요성
도메인 모델링을 하면 초기 설계 단계에서 시스템의 핵심 개념을 명확히 정의할 수 있다. 이를 통해 다음과 같은 장점을 얻는다.
1. 핵심 구조를 먼저 확립할 수 있다.
도메인 모델링을 하면, 시스템에서 가장 중요한 요소가 무엇인지 명확해진다. 예를 들어, 음식 배달 앱에서는 고객(Customer), 레스토랑(Restaurant), 메뉴 아이템(Menu Item) 등의 개념이 핵심이다. 이들은 서비스가 운영되는 동안 변하지 않는 요소이므로, 초기에 이를 기반으로 코드 구조를 잡으면 이후 개발 과정이 더욱 원활해진다.
2. 일관된 네이밍을 유지할 수 있다.
프론트엔드 개발에서는 명확한 네이밍이 코드의 가독성과 유지보수성을 높이는 핵심 요소다. 예를 들어, 음식 배달 서비스에서 "Restaurant Category"와 "Menu Item Category"라는 두 개의 다른 개념이 존재한다. 이를 미리 정의하지 않으면, 개발 과정에서 혼란이 생기고 "Category"라는 모호한 용어가 여러 곳에서 사용될 가능성이 있다.
3. API와 UI의 연결을 효과적으로 설계할 수 있다.
프론트엔드에서는 API 데이터를 그대로 사용하는 것이 아니라, UI에 적합한 형태로 변환해야 하는 경우가 많다. 예를 들어, JSON:API 스펙을 따르는 API에서는 restaurant.attributes.name과 같은 중첩된 데이터 구조가 반환될 수 있다. 하지만 UI에서는 단순히 restaurant.name처럼 사용할 수도 있다.
도메인 모델링을 통해 이러한 차이를 미리 정의하면, API 응답을 어떻게 가공해야 하는지 명확해지고, 불필요한 데이터 변환을 줄일 수 있다.
도메인 모델링 방법론
도메인 모델링은 크게 세 가지 단계로 진행할 수 있다.
1. 엔티티와 관계 정의하기
먼저, 시스템에서 중요한 개체(엔티티)를 정의하고, 이들 간의 관계를 파악한다.
음식 배달 서비스의 예를 들면 다음과 같다.
•
엔티티(Entity)
◦
고객(Customer)
◦
레스토랑(Restaurant)
◦
메뉴 아이템(Menu Item)
◦
장바구니(Shopping Cart)
•
관계(Relationship)
◦
고객은 레스토랑을 즐겨찾기에 추가할 수 있다.
◦
고객은 여러 메뉴 아이템을 장바구니에 추가할 수 있다.
◦
고객은 하나 이상의 장바구니를 가질 수 있다.
이러한 관계를 시각적으로 표현하면 다음과 같은 다이어그램이 될 수 있다.
Customer -- (1:N) --> ShoppingCart
ShoppingCart -- (N:M) --> MenuItem
Restaurant -- (1:N) --> MenuItem
Mathematica
복사
2. 엔티티의 속성과 연산 정의하기
각 엔티티는 속성(Attributes)과 연산(Operations)으로 구성된다.
예시: 레스토랑(Restaurant) 엔티티
•
속성(Attributes)
◦
id: 고유 식별자
◦
name: 레스토랑 이름
◦
address: 주소
◦
category: 음식 종류(예: 한식, 중식, 일식)
◦
menuItems: 제공하는 음식 목록
•
연산(Operations)
◦
addToFavorites(): 고객이 레스토랑을 즐겨찾기에 추가
◦
searchMenuItem(): 메뉴에서 특정 음식을 검색
이처럼 속성과 연산을 정의하면, 각 엔티티의 역할이 더욱 명확해지고 UI 및 API 설계가 자연스럽게 진행될 수 있다.
3. UI 요구사항과 비교하며 보완하기
도메인 모델링을 마쳤다면, 실제 UI 디자인과 비교하여 보완해야 한다.
예를 들어, 레스토랑 상세 페이지 UI를 보면 다음과 같은 정보를 포함하고 있을 수 있다.
•
레스토랑 이름
•
레스토랑 카테고리
•
별점
•
메뉴 목록
이 정보를 바탕으로, 도메인 모델에 추가적인 속성이나 관계가 필요한지 검토한다. 이를 통해 UI와 API 간의 불일치를 줄이고, 실제 서비스 요구사항을 반영할 수 있다.
도메인 모델링을 코드에 적용하기
도메인 모델링이 끝나면, TypeScript 등의 언어를 활용하여 실제 코드로 변환할 수 있다.
interface Restaurant {
id: string;
name: string;
address: string;
category: string;
menuItems: MenuItem[];
}
interface MenuItem {
id: string;
name: string;
price: number;
}
class Customer {
id: string;
name: string;
favorites: Restaurant[] = [];
addToFavorites(restaurant: Restaurant) {
this.favorites.push(restaurant);
}
}
TypeScript
복사
이처럼 TypeScript를 활용하면 모델을 기반으로 타입을 정의하고, UI와 API를 연결하는 과정이 훨씬 수월해진다.
Zod를 활용한 안전한 모델링
하지만 TypeScript 타입만으로는 런타임에서 데이터 유효성을 검증할 수 없다. 예를 들어, price 값이 문자열로 넘어온다면 TypeScript는 이를 잡아내지 못하고 런타임에서 오류가 발생할 수 있다.
이를 해결하기 위해 Zod를 활용하여 안전한 모델링을 적용할 수 있다.
Zod는 런타임에서 데이터 타입을 안전하게 검증할 수 있도록 도와주는 TypeScript 친화적인 라이브러리이다.
Zod를 활용한 레스토랑 모델링
import { z } from "zod";
// 레스토랑 스키마 정의
const RestaurantSchema = z.object({
id: z.string(),
name: z.string().min(1, "이름은 필수입니다."),
address: z.string(),
category: z.string(),
menuItems: z.array(
z.object({
id: z.string(),
name: z.string(),
price: z.number().positive("가격은 0보다 커야 합니다."),
})
),
});
// 타입 생성
type Restaurant = z.infer<typeof RestaurantSchema>;
// 예제 데이터 검증
const restaurantData = {
id: "1",
name: "맛있는 피자집",
address: "서울시 강남구",
category: "피자",
menuItems: [
{ id: "m1", name: "페퍼로니 피자", price: 15000 },
{ id: "m2", name: "치즈 피자", price: 14000 },
],
};
const result = RestaurantSchema.safeParse(restaurantData);
if (!result.success) {
console.error(result.error.format());
} else {
console.log("유효한 데이터:", result.data);
}
TypeScript
복사
Zod를 활용한 장점
•
런타임 타입 검증 가능: TypeScript는 컴파일 타임에만 타입을 체크하지만, Zod는 실제 런타임에서 데이터를 검증할 수 있다.
•
API 응답 데이터 검증 가능: 프론트엔드에서 백엔드 API 응답을 받을 때, 예상한 데이터 구조가 아닐 경우 미리 감지할 수 있다.
•
직관적인 오류 메시지 제공: safeParse()를 사용하면 구체적인 오류 메시지를 받을 수 있어 디버깅이 쉽다.
•
타입과 유효성 검사를 동시에 처리: z.infer<typeof Schema>를 활용하면 TypeScript 타입을 자동으로 생성할 수 있어 코드 중복을 줄일 수 있다.
도메인 모델링은 UI 개발에서도 강력한 도구가 될 수 있다.
•
프로젝트 초기에 핵심 엔터티와 관계를 정의하여 구조를 명확히 한다.
•
일관된 네이밍을 유지하여 코드의 가독성을 높인다.
•
API 데이터를 어떻게 가공할지 미리 결정하여 UI와 API의 연결을 최적화한다.
•
코드 구조를 미리 설계하여 유지보수성을 높인다.
•
Zod를 활용한 데이터 검증을 추가하여 API 응답과 유저 입력 값을 안전하게 다룬다.
•
유효성 검사를 자동화하여 예상치 못한 데이터 오류를 방지한다.
이 과정은 시간이 걸릴 수 있지만, 장기적으로 볼 때 개발 속도를 높이고 코드 품질을 개선하는 데 큰 도움이 된다. 따라서 새로운 프로젝트를 시작할 때 도메인 모델링을 활용하여 더욱 체계적인 UI 개발을 진행하는 것이 좋다.