문제 상황
사용자 지역 정보를 입력받는 Form을 개발하면서, 서버에서 전달하는 평면 데이터(flat data)를 Cascader 컴포넌트에서 요구하는 트리 구조로 변환해야 하는 문제가 있었습니다.
예를 들어, 서버에서는 아래와 같이 데이터가 전달됩니다.
{
"data": [
{ "name": "서울시", "last": false, "id": 1, "parentId": null },
{ "name": "중구", "last": true, "id": 2, "parentId": 1 }
]
}
하지만 실제로는 다음과 같은 트리 형태가 필요했습니다.
{
"data": [
{
"name": "서울시",
"id": 1,
"children": [
{
"name": "중구",
"id": 2,
"children": [ /* 추가 하위 지역이 있을 경우 */ ]
}
]
}
]
}
이러한 문제는 크게 세 가지로 요약됩니다.
- 프론트엔드와 백엔드 데이터의 타입 불일치
- 컴포넌트를 재사용하기 위해 부모 노드만 표기, Multiple 선택, 선택 경로(breadcrumb) 표시 등의 옵션 구현 필요
- 최종 Form 제출 시, 최상위 노드 선택 시 부모 노드를 제거하고 자식 노드들만 반환해야 함
이를 해결하기 위해 재귀적 데이터 변환과 자식 노드 추출을 담당하는 클래스를 작성했습니다. 재귀 호출을 활용함으로써 복잡한 계층 구조를 간결하게 변환할 수 있었으며, 관련 로직을 한 곳에 모아 유지보수성과 재사용성을 크게 향상시켰습니다.
예시 코드 (AreaHelper.ts)
class AreaHelper {
// 평면 데이터를 재귀적으로 트리 형태로 변환
static buildTree(flatData: any[], parentId: number | null = null, maxDepth?: number) {
const recursiveBuild = (parent: number | null, depth: number): any[] => {
return flatData
.filter(item => item.parentId === parent)
.map(item => {
const children = (!maxDepth || depth < maxDepth)
? recursiveBuild(item.id, depth + 1)
: [];
return { ...item, children: children.length ? children : undefined };
});
};
return recursiveBuild(parentId, 0);
}
// 부모 노드로부터 최종 자식(Leaf) 노드들의 id만 추출
static getLeafIds(parentId: number, flatData: any[]): number[] {
const children = flatData.filter(item => item.parentId === parentId);
let leafIds: number[] = [];
children.forEach(child => {
if (child.isLeaf) {
leafIds.push(child.id);
} else {
leafIds.push(...this.getLeafIds(child.id, flatData));
}
});
return leafIds;
}
}
설계 근거 및 추가 대안
- 재귀 호출 활용:
재귀 함수를 사용하면 데이터의 깊이에 상관없이 간단한 코드로 트리 구조를 생성할 수 있어 코드의 간결성과 유지보수성이 높아집니다. - 모듈화:
AreaHelper 클래스로 기능을 모듈화함으로써, Custom Cascader 내부에서 API로 받은 데이터를 쉽게 트리 구조로 변환하고, onChange 이벤트 발생 시 선택 경로의 최종 노드 ID를 추출해 Form에 전달할 수 있습니다. - 추가 대안:
- 서버 사이드 변환: 서버에서 미리 트리 구조로 데이터를 가공하여 클라이언트로 전달하는 방법
- 라이브러리 사용: 이미 검증된 데이터 변환 라이브러리를 도입하여 자동으로 원하는 형태로 데이터를 변환하는 방법
이와 같이 구현하면, 사용자에게 계층 구조의 데이터를 효과적으로 제공하면서 동시에 다양한 선택 옵션 및 상태 관리 기능을 유연하게 처리할 수 있습니다.
'개발' 카테고리의 다른 글
Ref를 이용해 전역 모달 시스템 구축하기 (0) | 2025.03.24 |
---|---|
TanStack의 QueryClient를 이용해 Cache 데이터 활용하기 (0) | 2025.03.23 |