c#

C# Clean Architecture 입문 및 예제 가이드

개발에대해 2025. 9. 29. 13:15
반응형
C# Clean Architecture 입문 및 예제 가이드

C# Clean Architecture 입문 및 예제 가이드

1. Clean Architecture란?

안녕하세요! 오늘은 C# 개발자에게 강력히 추천되는 소프트웨어 설계 원칙인 Clean Architecture를 소개하려고 합니다. Clean Architecture는 소프트웨어를 유지보수 가능하고, 테스트 가능하며, 의존성이 명확한 구조로 만드는 방법론입니다. 핵심 아이디어는 비즈니스 로직을 중심에 두고, 외부 프레임워크, UI, 데이터베이스 등 세부 구현에 의존하지 않는다는 것입니다.

Robert C. Martin(Uncle Bob)이 제안한 Clean Architecture는 SOLID 원칙을 철저히 따르며, 프로젝트가 커져도 안정적으로 확장할 수 있도록 도와줍니다.

2. Clean Architecture 레이어 구조

Clean Architecture는 크게 4가지 레이어로 나눌 수 있습니다.

  1. Entities: 핵심 비즈니스 객체와 규칙을 정의합니다. 다른 레이어에 의존하지 않습니다.
  2. Use Cases / Application: 애플리케이션의 특정 기능(유즈케이스)을 정의합니다. Entities에 의존할 수 있습니다.
  3. Interface / Adapters: UI, DB, 외부 API 등과 애플리케이션을 연결하는 어댑터입니다.
  4. Frameworks & Drivers: ASP.NET Core, EF Core, 외부 라이브러리 등 실제 구현체가 위치합니다.

핵심 규칙: 안쪽 레이어는 바깥 레이어에 의존하지 않는다. 즉, Entities와 Use Cases는 UI, DB, 프레임워크에 의존하지 않습니다.

3. 간단한 예제 프로젝트 구조

예제로 Todo 관리 애플리케이션을 만들어 보겠습니다. 레이어별 폴더 구조는 다음과 같습니다.

CleanArchitectureExample/
├─ Core/
│  └─ Entities/
│     └─ Todo.cs
├─ Application/
│  ├─ Interfaces/
│  │  └─ ITodoRepository.cs
│  └─ UseCases/
│     └─ CreateTodoUseCase.cs
├─ Infrastructure/
│  └─ Persistence/
│     └─ TodoRepository.cs
├─ WebAPI/
│  └─ Controllers/
│     └─ TodoController.cs

이렇게 레이어를 나누면 각 레이어의 책임이 명확해지고, 테스트 코드 작성도 쉬워집니다.

4. 예제 코드

Core/Entities/Todo.cs

public class Todo
{
    public Guid Id { get; private set; } = Guid.NewGuid();
    public string Title { get; private set; }
    public bool IsCompleted { get; private set; } = false;

    public Todo(string title)
    {
        if(string.IsNullOrWhiteSpace(title))
            throw new ArgumentException("Title cannot be empty");
        Title = title;
    }

    public void Complete() => IsCompleted = true;
}

Application/UseCases/CreateTodoUseCase.cs

public class CreateTodoUseCase
{
    private readonly ITodoRepository _repository;

    public CreateTodoUseCase(ITodoRepository repository)
    {
        _repository = repository;
    }

    public async Task<Todo> ExecuteAsync(string title)
    {
        var todo = new Todo(title);
        await _repository.AddAsync(todo);
        return todo;
    }
}

Infrastructure/Persistence/TodoRepository.cs

public class TodoRepository : ITodoRepository
{
    private readonly List<Todo> _todos = new();

    public Task AddAsync(Todo todo)
    {
        _todos.Add(todo);
        return Task.CompletedTask;
    }

    public Task<IEnumerable<Todo>> GetAllAsync() => Task.FromResult(_todos.AsEnumerable()); 
}

WebAPI/Controllers/TodoController.cs

[ApiController]
[Route("api/[controller]")]
public class TodoController : ControllerBase
{
    private readonly CreateTodoUseCase _createTodoUseCase;

    public TodoController(CreateTodoUseCase createTodoUseCase)
    {
        _createTodoUseCase = createTodoUseCase;
    }

    [HttpPost]
    public async Task<ActionResult<Todo>> Create(string title)
    {
        var todo = await _createTodoUseCase.ExecuteAsync(title);
        return Ok(todo);
    }
}

이렇게 하면 WebAPI는 애플리케이션 레이어와 Entities에만 의존하고, Infrastructure 레이어는 DI를 통해 주입됩니다. 따라서 코드 구조가 깔끔하고 테스트가 용이합니다.

5. Clean Architecture 적용 장점

  • 레이어별 책임이 명확하여 유지보수가 쉬움
  • 의존성 규칙 덕분에 외부 프레임워크 변경이 용이
  • 단위 테스트 작성이 쉬워 테스트 주도 개발(TDD) 가능
  • 프로젝트 확장 시 구조적 안정성 유지
  • SOLID 원칙 기반 설계로 코드 품질 향상

6. 실무 적용 팁

  • 레이어 간 의존성은 항상 안쪽 → 바깥쪽 방향만 허용
  • 인터페이스를 활용해 Infrastructure 구현체 주입
  • Use Cases는 반드시 비즈니스 규칙 중심으로 작성
  • WebAPI나 UI 레이어에서는 Entities/Use Cases를 직접 조작하지 않음
  • 작은 프로젝트라도 Clean Architecture 구조를 적용하면 장기 유지보수에 유리

7. 마무리

오늘은 C#에서 Clean Architecture를 이해하고, 간단한 Todo 애플리케이션 예제를 통해 구조를 실습해보았습니다. 처음에는 레이어가 많아 복잡하게 느껴질 수 있지만, 실제로 적용하면 테스트와 유지보수가 훨씬 쉬워지고, 프로젝트 확장에도 강력합니다. Clean Architecture는 단순한 설계 규칙이 아니라, 장기적으로 안정적이고 품질 높은 소프트웨어를 만드는 철학이에요. 😊

반응형