스택큐힙리스트

Composite 패턴으로 백엔드 트리 구조 깔끔하게 다루기 본문

개발

Composite 패턴으로 백엔드 트리 구조 깔끔하게 다루기

스택큐힙리스트 2025. 7. 18. 09:13
반응형

“댓글 트리·카테고리·조직도… 백엔드에서 계층형 데이터를 손대다 보면 재귀-SQL과 if-else 지옥에 빠지기 쉽죠.”
Composite 패턴은 이런 ‘전체-부분(Part-Whole)’ 관계를 객체 수준에서 먼저 해결해, 서비스·리포지토리·쿼리 코드의 복잡도를 크게 낮춰 줍니다.


1️⃣ Composite 패턴, 한 줄 정의

“단일 객체(Leaf)와 복합 객체(Composite)를 동일한 인터페이스로 다루게 해 트리 구조를 재귀적으로 표현한다.”
백엔드에서는 폴더-파일, 메뉴-하위메뉴, 권한-하위권한처럼 ‘자기 자신을 다시 포함’하는 도메인에 특히 유용합니다.


2️⃣ 왜 백엔드에서 중요한가?

  • ORM 엔티티 계층화 – 댓글, 카테고리 같은 무한 깊이 구조를 객체-그래프로 깔끔히 매핑
  • 도메인 서비스 단순화 – getTotalSize()처럼 Leaf/Composite 구분 없는 재귀 메서드로 로직 축소
  • 리팩터링-친화적 – 새 Leaf 타입(예: VideoFile) 추가 시 트리 구조 전체 수정 없이 인터페이스만 구현
    이 덕분에 하위 모듈 교체나 마이크로서비스 분리 시 영향 범위를 최소화할 수 있습니다.

3️⃣ Spring Boot + JPA 구현 예시

// ① 공통 타입 – Component
public interface Node {
    String getName();
    long getSize();        // Leaf·Composite 모두 지원
}

// ② Leaf – 실제 파일
@Entity
public class FileNode implements Node {
    @Id @GeneratedValue private Long id;
    private String name;
    private long size;
    // getters…
}

// ③ Composite – 디렉터리
@Entity
public class DirectoryNode implements Node {
    @Id @GeneratedValue private Long id;
    private String name;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "parent_id")
    private List<Node> children = new ArrayList<>();

    @Override
    public long getSize() {          // 재귀 호출!
        return children.stream()
                       .mapToLong(Node::getSize)
                       .sum();
    }
}

Node 인터페이스만 바라보면 Leaf(파일)와 Composite(폴더)를 구분할 필요가 없습니다. 서비스·컨트롤러는 DirectoryNode.getSize()를 호출하기만 하면 전체 용량을 얻습니다.


4️⃣ 계층 데이터베이스 모델링 팁

JPA로 단순 @ManyToOne 관계(Adjacency List)를 쓰면 깊은 트리 탐색 시 N+1 문제가 생깁니다.
대안으로 Closure Table을 도입하면 전 경로를 별도 테이블에 저장해, “특정 노드의 모든 후손” 쿼리를 한 번에 해결할 수 있습니다.


5️⃣ 실전 적용 체크리스트

  1. 상속 대신 인터페이스 – JPA 상속 전략보다 컴포지트 계층을 @OneToMany로 표현하면 유연성이 높습니다.
  2. 재귀 로직은 서비스 안으로 – Repository는 쿼리만, 합산·삭제 같은 재귀는 도메인 서비스에서 캡슐화합니다.
  3. 트랜잭션 주의 – 깊은 트리 일괄 삭제 시 @Transactional과 배치 삭제 쿼리를 조합해 락을 최소화하세요.
  4. 캐시 전략 – 전체 트리 빈도 높은 읽기는 Redis Hash + 비동기 TTL 업데이트로 오버헤드를 줄입니다.

한 줄 요약

Composite 패턴은 “도메인 객체 트리를 코드 레벨에서 먼저 해결해, 복잡한 계층형 데이터를 한 방에 길들인다.”

반응형
Comments