Today I Learn/React

[React/TypeScript]트리구조 데이터를 기반으로 트리뷰를 렌더링하는 UI 구현하기 2depth메뉴 구현하기

단추언니 2025. 3. 7. 10:33
반응형

TreeNodeProps 타입 정의

type TreeNodeProps = {
  id: number;
  name: string;
  children?: TreeNodeProps[];
};
  • 트리 노드의 구조를 타입으로 정의한다.
  • 각 노드는 id, name, children(자식 노드 배열, 선택적)을 가질 수 있다.
  • children이 없는 노드는 리프 노드(자식이 없는 노드)다.

 

트리 데이터 예시

const treeData: TreeNodeProps[] = [
  {
    id: 1,
    name: "Parent",
    children: [
      {
        id: 2,
        name: "Child 1",
        children: [
          { id: 3, name: "Grandchild 1" },
          { id: 4, name: "Grandchild 2" },
        ],
      },
      { id: 5, name: "Child 2" },
    ],
  },
];
  • 트리 데이터는 계층적 구조를 가지고 있다.
  • Parent → Child 1, Child 2 → Grandchild 1, Grandchild 2 로 이어지는 트리 형태이다.

 

Page 컴포넌트 (최상위 페이지)

export default function Page() {
  return (
    <div className="p-4">
      <h1 className="text-lg font-bold">Tree View</h1>
      <TreeView data={treeData} />
    </div>
  );
}
  • TreeView 컴포넌트를 사용해 트리 데이터를 화면에 출력

 

LeafNode 컴포넌트 (리프 노드 전용)

const LeafNode: React.FC<{ name: string }> = ({ name }) => {
  return <div className="ml-6 text-green-600">🌿 {name}</div>;
};
  • 리프 노드(자식이 없는 노드)만 따로 스타일링해서 표시

 

TreeNode 컴포넌트 (트리의 개별 노드)

const TreeNode = React.memo(({ node }: { node: TreeNodeProps }) => {
  if (!node.children || node.children.length === 0) {
    return <LeafNode name={node.name} />;
  }

  return (
    <div className="ml-4 border-l-2 border-gray-300 pl-4">
      <p className="font-bold">{node.name}</p>
      {node.children.map((child) => (
        <TreeNode key={child.id} node={child} />
      ))}
    </div>
  );
});

 

(1) React.memo 사용

  • TreeNode는 재귀적으로 호출되기 때문에 불필요한 리렌더링을 방지하기 위해 React.memo를 사용함
  • 같은 데이터를 가진 노드가 다시 렌더링되지 않도록 최적화할 수 있다.

 

(2) 리프 노드인지 확인

if (!node.children || node.children.length === 0) {
  return <LeafNode name={node.name} />;
}
  • children이 없거나 비어 있다면 리프 노드라고 판단하고, LeafNode를 렌더링 한다.

 

(3) 재귀적으로 자식 노드 렌더링

{node.children.map((child) => (
  <TreeNode key={child.id} node={child} />
))}
  • 자식 노드가 있으면, TreeNode를 재귀적으로 호출해서 모든 하위 노드를 계속 그린다.

 

TreeView 컴포넌트 (최상위 트리 렌더링)

const TreeView: React.FC<{ data: TreeNodeProps[] }> = ({ data }) => {
  return (
    <div>
      {data.map((node) => (
        <TreeNode key={node.id} node={node} />
      ))}
    </div>
  );
};
  • treeData 배열을 받아서 각 노드별로 TreeNode를 렌더링.
  • TreeNode가 재귀적으로 동작하면서 전체 트리를 그린다.

 

최종 트리 구조 (렌더링 결과)

Tree View
├── Parent
│   ├── Child 1
│   │   ├── 🌿 Grandchild 1
│   │   ├── 🌿 Grandchild 2
│   ├── 🌿 Child 2

 

반응형