Post

[Architecture] 설계를 코드로 빚어내는 5단계 계층형 아키텍처 명세

[Architecture] 설계를 코드로 빚어내는 5단계 계층형 아키텍처 명세

Config-Data-Driven 구현을 위한 5-Layer Architecture

1. 서론 (Introduction)

앞선 글을 통해 소스 코드와 구동 설정을 분리하여 영속성을 확보하는 ‘Config-Data-Driven’ 패러다임의 명확한 당위성과 공학적 이점을 검증하고, 이를 프로젝트의 핵심 기법으로 도입하기로 최종 결정했습니다. 그러나 아무리 뛰어난 개념적 패러다임과 단점 상쇄 전략을 정립했다 할지라도, 이를 뒷받침할 구체적인 물리적 구조가 없다면 설계는 한낱 이상론에 그치고 맙니다. 설정 데이터가 런타임 제어권을 유연하게 쥐고 흔드는 엔진을 실제로 가동하기 위해서는, 각 컴포넌트가 코드 내 어디에 위치해야 하며 서로 어떻게 통신해야 하는지 규격화하는 물리적 아키텍처의 확립이 필수적인 다음 단계입니다.

저는 Config-Data-Driven 패러다임을 소스 코드로 완벽하게 구현하는 동시에, 필요한 제약 조건들(설정 매니저의 격리, 명시적 파라미터 주입, 예외 전파 체계)을 아키텍처 수준에서 시스템적으로 강제하기 위해 ‘5단계 계층형 아키텍처(Layered Architecture)’를 구축했습니다. 이 구조 속에서 소스 코드는 외부 설정 데이터가 제공하는 유연함을 안전하게 수용하는 단단한 그릇이 됩니다. 본 글에서는 이 5단계 아키텍처가 탄생하게 된 사상적 배경과 함께, 정보처리기사 등에서 다뤄지는 전통적인 GoF 디자인 패턴들을 실무 데이터 파이프라인 레이어에 유기적으로 이식하여 결합도를 제어한 구체적인 아키텍처 구조 명세를 상세히 공유하고자 합니다.

2. 아키텍처의 원류: 헥사고날 아키텍처(Hexagonal Architecture)의 영감

이 5단계 계층형 구조를 설계하고 코드로 구체화할 때, 가장 큰 영감을 얻었던 설계 사상의 원류는 ‘헥사고날 아키텍처(Hexagonal Architecture, 포트 앤 어댑터 아키텍처)’였습니다 [1]. 헥사고날 아키텍처의 핵심 본질은 내부에 존재하는 순수한 비즈니스 도메인 로직을 외부의 가변적인 인프라 기술(특정 데이터베이스, 웹 프레임워크, 외부 UI 등)로부터 완전히 격리하는 데 있습니다. 외부 기술은 언제든 갈아 끼울 수 있는 ‘어댑터(Adapter)’에 불과하며, 내부 코어는 오직 ‘포트(Port)’라는 인터페이스를 통해서만 외부와 소통한다는 이 강력한 격리 사상은 내가 구상한 설정 기반 파이프라인을 코드로 실현할 가장 완벽한 뼈대였습니다.

데이터 파이프라인 환경에서 ‘외부 인프라 기술’이란 수시로 변하는 데이터 소스의 API 규격, 데이터를 처리하는 특정 라이브러리(Pandas, Polars, Scikit-Learn 등), 그리고 최종 적재되는 데이터베이스 환경(PostgreSQL, AWS S3 등)을 의미합니다. Config-Data-Driven 패러다임이 성공적으로 작동하려면, 파이프라인의 핵심 제어 엔진이 이러한 외부 기술이나 데이터 스키마에 강하게 결합(Coupling)되지 않고 완전히 독립되어 있어야만 합니다.

저는 이 육각형 아키텍처의 포트 앤 어댑터 개념을 데이터 도메인의 물리적 코드로 이식했습니다. 파이프라인의 중심부(Core)에는 변하지 않는 거시적 흐름 제어 체계와 추상 인터페이스(Port)를 배치하여 단단히 보호하고, 가변적인 세부 전처리 알고리즘이나 수집/적재 모듈은 외부 설정 데이터(.yml)에 의해 동적으로 장착되는 구현체(Adapter) 형태로 격리한 것입니다. 이 사상적 원류를 수직적 계층 구조와 실행 순서로 정교하게 정렬하여 본 프로젝트의 ‘5단계 계층형 아키텍처’라는 구체적인 코드로 구현하게 되었습니다.

3. 디자인 패턴 기반의 5대 레이어 심층 명세 (Deep Dive into the 5-Layers)

사상적 원류인 헥사고날 아키텍처를 프로덕션 코드로 구현하기 위해, 본 시스템은 제어권과 데이터의 흐름이 오직 수직 방향으로만 흐르도록 물리적 계층을 5단계로 엄격히 제한합니다. 이때 각 계층 간의 결합도를 제어하고 단일 책임(SRP)을 명확히 하기 위해, 정보처리기사 표준 수험 과정에서 다뤄지는 GoF 디자인 패턴의 생성, 구조, 행위 패턴을 아키텍처 전반에 유기적으로 매핑했습니다.

각 레이어가 담당하는 책임과 디자인 패턴 도입 배경, 그리고 이에 따른 장단점과 상쇄 전술은 다음과 같습니다.

3.1. 실행 레이어 (Execution Layer: main.py)

  • 적용 패턴: 단일 책임 원칙(SRP) 기반의 단일 엔트리 포인트 구조
  • 책임: 시스템의 유일한 시작점으로서, 전체 애플리케이션의 구동 환경(Environment) 초기화 및 최상위 파이프라인의 트리거링 책임을 전담합니다.

득과 실 및 상쇄 전술 (Pros, Cons & Mitigation)

  • 장점: 비즈니스 로직과 시스템 시동 로직이 완벽히 분리됩니다. 어떤 자산군의 파이프라인을 가동하든 시스템의 진입점이 단 하나로 통일되므로 인프라적 모니터링이 극도로 단순해집니다.
  • 단점: 환경 변수 로드, 전역 로거 설정, 로컬 경로 검증 등 시스템 초기화 코드가 한데 뭉치면서 main.py 파일 자체가 불필요하게 비대해질 위험이 존재합니다.
  • 상쇄 전술: 구체적인 인프라 속성은 외부 .env 파일과 configs/ 폴더 내부의 정적 YAML 설정으로 위임합니다. main.py 소스 코드는 단 10줄 내외의 추상화된 시동 메서드만 호출하도록 제약하여 인지적 비용을 최소화했습니다.

3.2. 파이프라인 레이어 (Pipeline Layer: src/pipeline/)

  • 적용 패턴: 템플릿 메서드 패턴 (Template Method Pattern) 구조의 수직 제어
  • 책임: 거대 도메인 컴포넌트들(수집, 변환, 적재 등) 간의 매크로 실행 흐름(Workflow Sequence)을 관장합니다. Airflow의 DAG 태스크들과 1:1로 유기적으로 매핑되는 계층입니다.

득과 실 및 상쇄 전술 (Pros, Cons & Mitigation)

  • 장점: 파이프라인 전체 공정의 ‘조감도’ 역할을 수행합니다. 미래의 협업 개발자가 이 레이어의 코드를 읽으면 세부 연산을 몰라도 “데이터가 수집(Extractor)을 거쳐 변환(Transformer)된 후 저장(Loader)되는구나”를 한눈에 파악할 수 있어 가독성과 통일성이 극대화됩니다.
  • 단점: 미시적인 데이터나 하이퍼파라미터 제어에 직접 관여할 수 없기 때문에, 상위 계층에서 하위 계층으로 대용량 데이터를 무분별하게 주고받을 때 레이어 간 전달 오버헤드가 발생할 수 있습니다.
  • 상쇄 전술: 파이프라인 레이어는 하위 데이터 객체를 직접 만지지 않습니다. 오직 하위 오케스트레이터의 규격화된 추상 인터페이스만을 호출하며, 계층 간 데이터 전달은 원시 딕셔너리가 아닌 경량화된 전역 DTO(Data Transfer Object) 구조로 제한하여 결합도를 최소화했습니다.

3.3. 오케스트레이터 레이어 (Orchestrator Layer: ***_service.py)

  • 적용 패턴: GoF 구조 패턴 — 퍼사드 패턴 (Facade Pattern)
  • 책임: 하위 도메인 시스템(네트워크 통신, 파싱, 검증 등)의 복잡한 의존성을 단 하나의 인터페이스 뒤로 완전히 캡슐화합니다. 또한, 본 시스템에서 ConfigManager에 접근하여 외부 설정을 파싱할 수 있는 유일한 특권을 가진 핵심 관제탑입니다.

득과 실 및 상쇄 전술 (Pros, Cons & Mitigation)

  • 장점: 상위 레이어에 복잡한 하위 시스템을 은닉하고 극상의 가독성을 제공합니다. 외부 설정을 파싱하여 하위 팩토리에 명시적으로 파라미터를 주입하는 주체를 이 계층으로 단일화함으로써 설정 오염의 위험을 통제합니다.
  • 단점: 퍼사드 객체가 하위 레이어의 수많은 태스크를 조율하다 보면, 혼자 모든 비즈니스 로직을 떠안고 비대해지는 최악의 안티 패턴인 ‘신형 객체(God Object)’가 될 위험이 큽니다.
  • 상쇄 전술: 서비스 계층 내부에는 실질적인 ‘데이터 연산 및 전처리 알고리즘’ 코드를 단 한 줄도 작성하지 못하도록 엄격히 제한합니다. 오직 설정을 파싱해 하위 계층에 전달하고, 하위에서 올라온 예외를 수집하여 완료 시점에 단 1회 ‘종합 요약 리포트’를 발표하는 ‘순수 흐름 관제 및 매개변수 주입’의 책임만 부여하여 비대화를 원천 차단했습니다.

3.4. 팩토리 레이어 (Factory Layer: ***_factory.py)

  • 적용 패턴: GoF 생성 패턴 — 팩토리 메서드 패턴 (Factory Method Pattern)
  • 책임: 설정 데이터(.yml)에 명시된 문자열 조건에 따라 최하위 세부 태스크 객체를 동적으로 생성하여 반환하는 정보 은닉(Information Hiding) 역할을 수행합니다.

득과 실 및 상쇄 전술 (Pros, Cons & Mitigation)

  • 장점: 상위 서비스 레이어가 구체적인 클래스의 타입이나 복잡한 생성 조건 분기문(if-else)을 알 필요가 없어집니다. 설정 기반 구동을 실현하기 위한 핵심 동적 객체 주입(DI) 계층입니다.
  • 단점: 새로운 분석 알고리즘이나 수집 태스크가 추가될 때마다 팩토리 코드 내부의 매핑 조건문을 수정해야 하므로, 개방 폐쇄 원칙(OCP)을 완벽히 만족하지 못하고 코드를 건드려야 하는 구조적 모순이 발생할 수 있습니다.
  • 상쇄 전술: 파이썬의 동적 모듈 임포트 메커니즘(importlib)을 팩토리에 결합했습니다. 설정 파일의 텍스트 명칭과 실제 클래스의 물리적 패스를 동적으로 매핑하여, 새로운 클래스가 추가되더라도 팩토리 소스 코드를 단 한 줄도 수정하지 않는 ‘완전한 Config-Driven 팩토리’를 구축해 단점을 상쇄했습니다.

3.5. 세부 태스크 레이어 (Detailed Task Layer: ***.py & abstract_***.py)

  • 적용 패턴: GoF 행위 패턴 — 전략 패턴 (Strategy Pattern)
  • 책임: abstract_***.py 추상 클래스 인터페이스를 상속받아, 원자적 단위의 실질적인 데이터 처리 및 비즈니스 알고리즘 연산을 물리적으로 수행하는 최하위 계층입니다.

득과 실 및 상쇄 전술 (Pros, Cons & Mitigation)

  • 장점: 규격화된 인터페이스를 강제함으로써 상위 계층의 코드 수정 없이 언제든 새로운 알고리즘 구현체(전략)로 갈아 끼울 수 있는 극상의 유연성과 확장성을 확보합니다. 단위 테스트(Unit Test) 작성이 가장 용이한 청정 공간이 됩니다.
  • 단점: 전처리 기법이나 자산군별 수집 로직마다 개별 파일과 구현 클래스가 생성되므로, 물리적 파일 개수가 많아져 프로젝트 구조의 파편화가 발생할 수 있습니다.
  • 상쇄 전술: 도메인별 폴더 격리를 철저히 이행하고, ‘단일 목적 주석 표준’ 및 ‘완전한 단어 명명 규칙’을 지켰습니다. 이를 통해 파일 단위의 인지적 비용을 통제하고 복잡성을 묶어두었습니다. 또한, 이 계층에서는 ConfigManager에 대한 직접 접근을 원천 금지하여 의존성 역오염을 차단했습니다.

4. 데이터 및 제어 흐름의 공학적 메커니즘 (Data & Control Flow)

4.1. 포트 앤 어댑터 메커니즘의 데이터 도메인 구현 검증

5단계 계층형 아키텍처가 실제로 가동될 때, 시스템 내부의 제어권(Control Flow)과 데이터 흐름(Data Flow)은 사전에 정의된 규칙에 따라 철저하게 단방향(Top-Down) 수직적 제약을 받습니다. 외부 설정(.yml) 데이터가 전용 파서에 의해 로드되는 순간부터 최하위 레이어에서 원자적 데이터 연산이 수행되기까지의 매커니즘은 헥사고날 아키텍처의 포트 앤 어댑터 원리를 완벽하게 물리 코드로 재현합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[실행 레이어: main.py] 
       │ 환경 초기화 및 시동
       ▼
[파이프라인 레이어: ***_pipeline.py] 
       │ 대단위 도메인 공정 순서 제어 (Workflow)
       ▼
[오케스트레이터 레이어: ***_service.py] ◀── (ConfigManager 설정 파싱 및 격리)
       │ 퍼사드 패턴: 하위 복잡성 은닉 & 명시적 파라미터 주입
       ▼
[팩토리 레이어: ***_factory.py]
       │ 팩토리 메서드 패턴: 문자열 기반 동적 객체 생성 (DI)
       ▼
[세부 태스크 레이어: ***.py] ◀── (abstract_***.py: 인터페이스 규격 강제)
         전략 패턴: 원자적 데이터 연산 및 알고리즘 실행 (Adapter)

이 흐름에서 헥사고날 아키텍처의 핵심인 ‘포트(Port)’ 역할을 수행하는 것은 최하위 계층의 추상 클래스(abstract_***.py) 인터페이스입니다. 이 인터페이스는 데이터 파이프라인 엔진이 외부 세계(특정 라이브러리, API 규격)와 소통하기 위해 준수해야 하는 엄격한 계약(Contract)을 정의합니다. 그리고 ‘어댑터(Adapter)’ 역할을 수행하는 것이 바로 팩토리에 의해 동적으로 주입되는 세부 태스크 구현체(***.py)들입니다.

오케스트레이터 계층(_service.py)이 외부 설정을 해석하여 특정 태스크의 명칭을 팩토리에 넘기면, 팩토리 계층(_factory.py)은 파이썬의 동적 임포트 메커니즘을 활용해 알맞은 어댑터 객체를 생성합니다. 서비스 계층은 이 어댑터가 구체적으로 어떻게 구현되어 있는지 알지 못한 채, 오직 포트(추상 클래스)에 정의된 메서드만을 호출하여 데이터를 처리합니다.

이때 느슨한 결합을 유지한다는 명목하에 많은 시스템이 범하는 가변 인자(**kwargs)의 무분별한 사용을 전면 배제했습니다. 매개변수가 하위 계층으로 내려갈 때마다 명시적인 타입 힌팅(Type Hinting) 구조를 거치도록 강제함으로써, 동적 구동 아키텍처가 가질 수 있는 최악의 약점인 ‘데이터 추적성 저하’를 완벽히 극복하고 컴파일 타임에 준하는 안정성을 소스 코드 수준에서 복원해 냈습니다.

5. 결론 (Conclusion)

결론적으로, 헥사고날 사상에 기반한 5단계 계층형 아키텍처의 구축은 개념적으로만 존재하던 Config-Data-Driven 패러다임을 프로덕션 환경에서 안전하게 작동시키게 되었습니다. 시스템의 구동 진입점부터 최하위 연산 레이어까지의 책임을 엄격하게 수직 격리하고, 퍼사드, 팩토리 메서드, 전략 패턴 등의 GoF 디자인 패턴을 적재적소에 배치함으로써 결합도가 극도로 낮은 청정한 시스템을 완성할 수 있었습니다 [2].

이러한 물리적 제약이 가져다준 공학적 이점은 명확합니다. 첫째, 테스트 용이성(Testability)의 극대화입니다. 각 계층이 단 하나의 책임만을 지고 인터페이스로 분리되어 있기 때문에, 상위 계층의 로직을 검증할 때 하위 계층을 가볍게 모킹(Mocking)하여 독립적인 단위 테스트를 수행할 수 있습니다. 둘째, 미래의 협업 오버헤드 단축입니다. 새로운 전처리 알고리즘이나 수집 도메인이 추가될 때, 미래의 개발자는 시스템의 전체 코드를 헤매지 않고 오직 최하위 태스크 폴더와 외부 설정 파일만 수정하면 된다는 명확한 이정표를 얻게 되었습니다.

본 프로젝트에 구현된 5단계 계층 아키텍처는 범용적이고 보편적인 GoF 디자인 패턴을 기반으로 설계되었습니다. 이러한 소프트웨어 공학의 고전적 기법들은 객체지향 세계관에서 의존성을 낮추고 안정적인 아키텍처 구조를 빌딩하는 데 더할 나위 없이 훌륭한 디딤돌이 되어 주었습니다. 그러나 냉정하게 평가하자면, 소프트웨어 일반론을 다루는 GoF 패턴의 기계적 적용이 대용량 데이터 파이프라인이 마주하는 엔지니어링적 특수성까지 완벽하게 통제하는 최선의 정답은 아닙니다. 데이터 수집의 인프라적 병목 현상, 데이터 품질(Quality)의 동적 검증 체계, 파이프라인의 관찰 가능성 확보 등은 고전적인 객체 생성 및 행위 패턴만으로 해결하기에 추상화의 결이 다르기 때문입니다.

이에 저는 현재 안착시킨 구조적 가용성에 만족하지 않고, 한 단계 더 진화된 데이터 아키텍처를 향한 지속적인 개선(Refactoring)을 계획하고 있습니다. 데이터 생태계에서 발생하는 반복적인 문제를 해결하기 위해 70가지 전략을 정립한 바르토시 코니에치니의 《데이터 엔지니어링 디자인 패턴》(2026) 구조를 깊이 있게 연구하고자 합니다 [3]. 기존에 완성한 5단계 계층 아키텍처의 견고한 의존성 격리 장치를 기반 삼아, 데이터 수집 안정성과 실시간 품질 제어에 최적화된 데이터 도메인 특화 패턴들을 상위 레이어에 순차적으로 이식함으로써 데이터 엔지니어링 관점에서 완벽히 최적화된 차세대 파이프라인으로 시스템을 진화시켜 나갈 것입니다.

참고자료 (References)

[1] Hombergs, Tom. (2021). 만들면서 배우는 클린 아키텍쳐 : 자바 코드로 구현하는 클린 웹 애플리케이션

[2] Eric Freeman. (2022). 헤드 퍼스트 디자인 패턴 : 14가지 GoF 필살 패턴

[3] Bartosz Konieczny. (2026). 데이터 엔지니어링 디자인 패턴

This post is licensed under CC BY 4.0 by the author.