
프로젝트의 규모가 커질수록 개발자는 코드의 복잡성이라는 거대한 벽에 부딪힙니다. 처음에는 단순했던 프레임워크 기반의 코드가 시간이 지나면서 비즈니스 로직과 데이터베이스 접근 코드, 외부 API 호출이 뒤섞인 '스파게티 코드'가 되기 일쑤입니다. 로버트 C. 마틴이 제안한 클린 아키텍처(Clean Architecture)는 이러한 혼돈 속에서 파이썬 프로젝트를 구원할 강력한 아키텍처 설계 도구입니다. 본 포스팅에서는 파이썬 특유의 유연성을 살리면서도 견고한 시스템을 유지할 수 있는 3단계 폴더 구조와, 구체적인 의존성 역전(Dependency Inversion) 해결 방법을 제시합니다.
1. 파이썬 프로젝트에서 클린 아키텍처가 필요한 이유
많은 파이썬 웹 프레임워크(Django, FastAPI 등)는 각자의 기본 구조를 가지고 있습니다. 하지만 프레임워크 중심의 설계는 시간이 흐를수록 핵심 비즈니스 로직이 프레임워크에 종속되게 만듭니다. 클린 아키텍처의 핵심은 "프레임워크는 세부 사항일 뿐이다"라는 철학입니다.
테스트 용이성 (Testability)
데이터베이스나 외부 UI 없이도 핵심 비즈니스 규칙을 독립적으로 테스트할 수 있습니다. 이는 파이썬의 Pytest 환경에서 매우 강력한 장점이 됩니다.
유지보수의 독립성
데이터베이스를 MySQL에서 PostgreSQL로 바꾸거나, Web 프레임워크를 Flask에서 FastAPI로 전환하더라도 핵심 도메인 로직은 단 한 줄의 수정도 필요하지 않아야 합니다.
2. 클린 아키텍처 계층 구조 및 파이썬 폴더 매핑 차이
이론적인 클린 아키텍처의 4개 계층을 파이썬 프로젝트의 실제 폴더 구조로 어떻게 치환하는지 아래 표를 통해 비교해 보겠습니다.
| 계층 (Layer) | 주요 역할 | 파이썬 폴더명 추천 | 포함되는 요소 |
|---|---|---|---|
| Entities | 가장 핵심적인 비즈니스 규칙 | domain/ |
Model, Entity, Domain Exception |
| Use Cases | 애플리케이션 특화 비즈니스 로직 | application/ |
Service, Interactor, Repository Interface |
| Interface Adapters | 데이터 변환 및 전달 | adapters/ |
Controller, Repository Impl, Serializer |
| Frameworks & Drivers | 외부 도구 및 인프라 | infrastructure/ |
DB Config, Web Framework, Third-party SDK |
3. 실무적인 3단계 폴더 구조 설계 해결 방법
파이썬의 패키지 시스템을 활용하여 의존성 방향이 항상 안쪽(Domain)으로 향하게 만드는 실전 폴더 구조 설계법입니다.
1단계: Domain(Core) 계층 분리
domain 폴더에는 순수한 파이썬 클래스만 존재해야 합니다. 여기서 중요한 점은 이 폴더의 코드가 외부의 그 어떤 패키지(예: SQLAlchemy, FastAPI)도 import 하지 않아야 한다는 것입니다. 오직 파이썬 기본 라이브러리와 데이터 타입만 사용합니다.
2단계: Application Use Cases 및 Interface 정의
사용자의 요청을 처리하는 흐름을 정의합니다. 여기서 핵심은 추상화입니다. 데이터베이스 저장 기능이 필요하다면 실제 DB 코드를 쓰는 것이 아니라, 추상 클래스(Abstract Base Class, ABC)를 통해 Repository 인터페이스를 정의합니다.
3단계: Infrastructure 및 Dependency Injection 구현
가장 바깥쪽 폴더에서 실제 프레임워크를 조립합니다. 여기서 의존성 주입(DI) 도구를 사용하거나 수동으로 객체를 조립하여 의존성 역전 문제를 해결합니다. 이는 코드를 유연하게 만드는 결정적인 해결 방법이 됩니다.
4. 실전 코드 예시 (Sample Example)
의존성 역전을 통해 도메인 로직을 보호하는 파이썬 클린 아키텍처 구조의 예시입니다.
# 1. domain/models.py (엔티티: 순수 파이썬)
class User:
def __init__(self, id: int, name: str):
self.id = id
self.name = name
# 2. application/interfaces.py (추상화 인터페이스)
from abc import ABC, abstractmethod
class UserRepository(ABC):
@abstractmethod
def save(self, user: User):
pass
# 3. application/use_cases.py (유스케이스)
class RegisterUserUseCase:
def __init__(self, user_repo: UserRepository):
self.user_repo = user_repo
def execute(self, name: str):
user = User(id=None, name=name)
self.user_repo.save(user)
return user
# 4. adapters/repositories.py (인프라 구현체)
class SQLUserRepository(UserRepository):
def save(self, user: User):
print(f"SQL DB에 {user.name} 저장 완료")
# 5. main.py (진입점: 의존성 주입)
sql_repo = SQLUserRepository()
use_case = RegisterUserUseCase(user_repo=sql_repo)
use_case.execute("Chaewon")
5. 결론: 클린 아키텍처가 가져다주는 장기적 가치
클린 아키텍처를 파이썬 프로젝트에 적용하는 것은 초기 비용이 발생할 수 있습니다. 하지만 시스템이 복잡해질수록 변경에 유연하게 대응하고, 버그 발생 시 영향 범위를 최소화할 수 있는 가장 확실한 전략입니다. 폴더 구조는 단순한 파일 정리가 아니라 의존성의 경계를 만드는 작업임을 명심해야 합니다. 오늘 소개한 3단계 설계와 의존성 역전 해결 방법을 통해, 시간이 지나도 썩지 않는 견고한 파이썬 프로젝트를 구축해 보시기 바랍니다.
'Artificial Intelligence > 60. Python' 카테고리의 다른 글
| [PYTHON] Pydantic v2를 활용한 데이터 검증 3단계 및 직렬화 성능 최적화 해결 방법 (0) | 2026.02.22 |
|---|---|
| [PYTHON] 파이썬 패키징 표준 PEP 517과 518의 핵심 차이 및 빌드 에러 해결 방법 2가지 (0) | 2026.02.22 |
| [PYTHON] 성능 최적화를 위한 C++ Binary Extension 작성 시 PyBind11 활용 방법과 기존 방식의 차이 해결 (0) | 2026.02.21 |
| [PYTHON] Pre-commit 훅을 활용한 코드 퀄리티 강제화 방법과 팀 협업 시 생산성 차이 해결 (0) | 2026.02.21 |
| [PYTHON] 안정적인 협업을 위한 Mypy CI/CD 파이프라인 통합 및 타입 체크 최적화 방법 (0) | 2026.02.21 |