Communitygithub.com

Aurelian1974/TestRepo

.NET에서 수직 슬라이스 아키텍처를 구축하고 유지 관리하는 방법 — 슬라이스 구조(단일 파일 및 폴더 변형), 중재자 없이 직접 핸들러 디스패치, 교차 관심사, 슬라이스 간 공유, 도메인 모델 또는 Clean 레이어와의 상호작용, 슬라이스 수준 테스팅을 다룹니다. 수직 슬라이스로 구성된 모듈에서 유스케이스/엔드포인트/기능을 추가하거나 수정할 때, 또는 슬라이스 간 중복이 논의될 때 사용하십시오.

TestRepo란 무엇인가요?

이 스킬은 .NET 애플리케이션에서 수직 슬라이스 아키텍처(Vertical Slice Architecture)를 효과적으로 구축하고 유지 관리하기 위한 포괄적인 가이드를 제공합니다. 주요 내용으로는 단일 파일 또는 폴더 기반 슬라이스 구조, MediatR과 같은 중재자 없이 직접 핸들러를 디스패치하는 방법, 로깅 및 유효성 검사와 같은 교차 관심사를 처리하는 방법, 그리고 슬라이스가 서로 공유할 수 있는(또는 공유하지 말아야 할) 요소들을 명확히 설명합니다. 또한 도메인 모델이나 Clean Architecture 레이어와 슬라이스가 어떻게 상호작용하는지 다루며, 슬라이스 수준의 테스트 전략도 포함되어 있어 개발자가 새로운 유스케이스나 엔드포인트를 추가할 때 일관된 패턴을 따를 수 있도록 돕습니다. 이 스킬은 C#과 .NET 생태계를 사용하는 모든 프로젝트(예: ASP.NET Core, Blazor 등)에 적용 가능하며, 수직 슬라이스로 조직된 모듈에서 작업할 때 특히 유용합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Aurelian1974/TestRepo/tree/main/.claude/skills/vertical-slice-architecture

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

TestRepo은(는) 무엇을 하나요?

.NET에서 수직 슬라이스 아키텍처(Vertical Slice Architecture)를 구축하고 유지 관리하는 방법 — 슬라이스 구조(단일 파일 및 폴더 변형), 중재자 없이 직접 핸들러 디스패치, 교차 관심사, 슬라이스 간 공유 가능 요소, 도메인 모델 또는 Clean 레이어와의 상호작용, 슬라이스 수준 테스팅을 다룹니다. 수직 슬라이스로 구성된 모듈에서 유스케이스/엔드포인트/기능을 추가하거나 수정할 때, 또는 슬라이스 간 중복이 논의될 때 사용하십시오.

슬라이스 구조

수직 슬라이스는 두 가지 주요 변형으로 구성할 수 있습니다:

  • 단일 파일 슬라이스: 모든 요청, 핸들러, 응답 및 유효성 검사 로직을 하나의 파일에 포함합니다. 간단한 유스케이스에 적합합니다.
  • 폴더 기반 슬라이스: 각 슬라이스가 고유한 폴더를 가지며, 내부에 Request.cs, Handler.cs, Response.cs 등의 파일로 분리합니다. 복잡한 유스케이스에 적합합니다.

직접 핸들러 디스패치 (MediatR 대신)

중재자(MediatR)를 사용하지 않고 직접 핸들러를 호출하는 방법:

public class CreateUserHandler
{
    private readonly AppDbContext _db;

    public CreateUserHandler(AppDbContext db)
    {
        _db = db;
    }

    public async Task<Response> HandleAsync(Request request)
    {
        // 비즈니스 로직 구현
        var user = new User(request.Name, request.Email);
        _db.Users.Add(user);
        await _db.SaveChangesAsync();
        return new Response(user.Id);
    }
}

컨트롤러 또는 엔드포인트에서 직접 호출:

app.MapPost("/users", async (CreateUserHandler handler, CreateUserRequest request) =>
{
    var response = await handler.HandleAsync(request);
    return Results.Ok(response);
});

교차 관심사 처리

  • 로깅: 핸들러 내에서 ILogger<T>를 직접 주입받아 사용하거나, AOP 방식의 데코레이터 패턴을 적용할 수 있습니다.
  • 유효성 검사: FluentValidation과 같은 라이브러리를 사용하여 각 슬라이스 내에서 요청 유효성 검사를 수행합니다.
  • 권한 부여: 핸들러 또는 엔드포인트 레벨에서 [Authorize] 특성 또는 정책 기반 검사를 적용합니다.

슬라이스 간 공유 요소

수직 슬라이스는 다음 요소를 공유할 수 있습니다:

  • 데이터베이스 컨텍스트: DbContext는 공유되지만, 각 슬라이스는 자신의 유스케이스에 필요한 엔티티만 사용합니다.
  • 도메인 모델: 공통 도메인 엔티티와 값 객체를 공유합니다.
  • 서비스: 인프라 서비스(예: 이메일 발송, 파일 저장)는 공유 가능하지만, 비즈니스 로직은 각 슬라이스에 캡슐화됩니다.

공유하지 말아야 할 것: 슬라이스 간의 비즈니스 로직, 유효성 검사 규칙, 프레젠테이션 로직은 중복을 허용하더라도 공유하지 않습니다.

도메인 모델 및 Clean 레이어와의 상호작용

  • 수직 슬라이스는 Clean Architecture의 레이어(도메인, 애플리케이션, 인프라)를 침범하지 않고 사용합니다. 각 슬라이스는 애플리케이션 레이어의 일부로 볼 수 있습니다.
  • 도메인 모델은 모든 슬라이스가 참조하는 공유 계층으로 유지됩니다.
  • 각 슬라이스는 도메인 모델을 사용하여 비즈니스 로직을 수행하며, 인프라(예: 데이터베이스, 외부 API)는 핸들러 내에서 직접 해결합니다.

슬라이스 수준 테스팅

각 슬라이스에 대해 독립적인 단위 테스트 및 통합 테스트를 작성합니다:

[Fact]
public async Task CreateUser_ValidRequest_ReturnsUserId()
{
    // Arrange
    var db = new AppDbContext(Options);
    var handler = new CreateUserHandler(db);
    var request = new CreateUserRequest { Name = "Test", Email = "[email protected]" };

    // Act
    var response = await handler.HandleAsync(request);

    // Assert
    Assert.True(response.UserId > 0);
}

테스트는 특정 슬라이스의 동작에 집중하며, 다른 슬라이스에 의존하지 않도록 설계됩니다.

관련 스킬