경로 그룹, 매개 변수와 유효성 검사
MapGroup으로 엔드포인트를 구성하고 경로, 쿼리, 본문 매개 변수를 바인딩하며 데이터 주석으로 유효성을 검사합니다.
경로 그룹, 매개 변수와 유효성 검사은(는) CoddyKit의 무료 C# Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 C# Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
구성을 위한 라우트 그룹
MapGroup() (.NET 7에서 도입)을 사용하면 관련 엔드포인트를 공통 접두사 아래에 그룹화하고, 각 엔드포인트에 반복해서 적용하지 않고도 미들웨어, 인증 정책, 태그와 같은 공통 구성을 적용할 수 있습니다.
라우트 그룹 만들기
app.MapGroup("/api/products")를 호출한 다음 반환된 그룹에 엔드포인트를 매핑합니다. 접두사는 모든 라우트 앞에 자동으로 추가됩니다.
var products = app.MapGroup("/api/products").WithTags("Products");
products.MapGet("/", GetAll);
products.MapGet("/{id}", GetById);
products.MapPost("/", Create);
products.MapPut("/{id}", Update);
products.MapDelete("/{id}", Delete);
// Routes: /api/products, /api/products/{id}그룹에 인증 적용하기
그룹에서 RequireAuthorization()을 사용하면 모든 엔드포인트를 한 번에 보호할 수 있습니다. 개별 엔드포인트에서는 여전히 AllowAnonymous()로 재정의할 수 있습니다.
var adminGroup = app.MapGroup("/admin")
.RequireAuthorization("AdminPolicy")
.WithTags("Admin");
adminGroup.MapGet("/users", GetAllUsers);
adminGroup.MapDelete("/users/{id}", DeleteUser);
// This one inside the group opts out
adminGroup.MapGet("/status", () => "OK").AllowAnonymous();라우트 매개변수 제약 조건
형식 패턴으로 라우트 매개변수를 제한합니다. 라우터는 패턴과 일치하지 않는 요청을 거부하고 자동으로 404를 반환합니다.
// Only matches numeric IDs
app.MapGet("/products/{id:int}", (int id) => id);
// GUID constraint
app.MapGet("/orders/{orderId:guid}", (Guid orderId) => orderId);
// Length constraint
app.MapGet("/codes/{code:length(6)}", (string code) => code);
// Min value
app.MapGet("/page/{page:min(1)}", (int page) => page);다양한 소스에서 바인딩하기
특성을 사용하면 다양한 소스에서 매개변수를 바인딩할 수 있습니다. 기본적으로 단순 형식은 라우트나 쿼리에서, 복합 형식은 본문에서 가져옵니다.
app.MapPost("/search", (
[FromQuery] string q,
[FromQuery] int page,
[FromHeader(Name = "X-Api-Version")] string version,
[FromBody] SearchFilters filters,
AppDbContext db) =>
{
// q and page from query string
// version from request header
// filters from JSON body
return Results.Ok();
});TryParse를 사용한 사용자 지정 매개변수 바인딩
라우트 또는 쿼리 매개변수로 사용하는 사용자 지정 형식에는 정적 TryParse 메서드를 구현합니다. 프레임워크가 이 메서드를 자동으로 호출하여 문자열 값을 구문 분석합니다.
public record ProductFilter(string? Category, decimal? MinPrice)
{
public static bool TryParse(string value, out ProductFilter result)
{
var parts = value.Split(':');
result = new ProductFilter(
parts.Length > 0 ? parts[0] : null,
parts.Length > 1 && decimal.TryParse(parts[1], out var p) ? p : null);
return true;
}
}
// Usage: GET /products?filter=Electronics:50
app.MapGet("/products", ([FromQuery] ProductFilter filter) => filter);데이터 주석 유효성 검사
요청 데이터 전송 객체에 데이터 주석 특성을 지정합니다. 미니멀 API에서는 IValidatableObject 인터페이스나 유효성 검사 필터를 사용하여 유효성 검사를 실행합니다.
using System.ComponentModel.DataAnnotations;
record CreateProductRequest
{
[Required, MaxLength(200)]
public string Name { get; init; } = "";
[Range(0.01, 999999)]
public decimal Price { get; init; }
[Range(0, int.MaxValue)]
public int Stock { get; init; }
}유효성 검사를 위한 엔드포인트 필터
엔드포인트 필터는 처리기 전후에 실행됩니다. 필터를 사용하여 모델 유효성 검사를 추가하고, 잘못된 요청이 비즈니스 논리에 도달하기 전에 거부할 수 있습니다.
app.MapPost("/products", CreateProduct)
.AddEndpointFilter(async (ctx, next) =>
{
var req = ctx.GetArgument<CreateProductRequest>(0);
var errors = new List<ValidationResult>();
if (!Validator.TryValidateObject(req,
new ValidationContext(req), errors, true))
{
return Results.ValidationProblem(
errors.ToDictionary(e => e.MemberNames.First(),
e => new[] { e.ErrorMessage! }));
}
return await next(ctx);
});FluentValidation 통합
복잡한 유효성 검사 규칙에는 SharpGrip.FluentValidation.AutoValidation.Endpoints 패키지와 FluentValidation을 사용하여 미니멀 API에서 유효성 검사를 자동화합니다.
public class CreateProductValidator : AbstractValidator<CreateProductRequest>
{
public CreateProductValidator()
{
RuleFor(x => x.Name).NotEmpty().MaximumLength(200);
RuleFor(x => x.Price).GreaterThan(0);
RuleFor(x => x.Stock).GreaterThanOrEqualTo(0);
}
}
builder.Services.AddFluentValidationAutoValidation();
builder.Services.AddValidatorsFromAssemblyContaining<CreateProductValidator>();중첩된 라우트 그룹
라우트 그룹을 중첩하여 주문에 주문 항목이 포함되는 것과 같은 계층적 리소스를 모델링할 수 있습니다.
var api = app.MapGroup("/api").RequireAuthorization();
var orders = api.MapGroup("/orders");
orders.MapGet("/", GetAllOrders);
orders.MapGet("/{id:int}", GetOrder);
// Nested: /api/orders/{orderId}/lines
var lines = orders.MapGroup("/{orderId:int}/lines");
lines.MapGet("/", GetOrderLines);
lines.MapPost("/", AddOrderLine);
lines.MapDelete("/{id}", RemoveOrderLine);실전: 버전이 지정된 API 그룹
엔드포인트를 API 버전별로 그룹화하면 인증이나 태그 구성을 중복하지 않고 여러 버전을 동시에 지원할 수 있습니다.
var v1 = app.MapGroup("/api/v1")
.RequireAuthorization()
.WithTags("v1");
var v2 = app.MapGroup("/api/v2")
.RequireAuthorization()
.WithTags("v2");
v1.MapGet("/products", GetProductsV1);
v2.MapGet("/products", GetProductsV2); // richer response확인 문제
미니멀 API에서 MapGroup()의 목적은 무엇입니까?
복습: 라우트 그룹, 매개변수 및 유효성 검사
핵심 요점:
MapGroup(): 여러 엔드포인트에서 접두사와 구성을 공유합니다- 라우트 제약 조건(
:int,:guid,:min)은 일치하지 않는 라우트를 자동으로 거부합니다 [FromQuery],[FromHeader],[FromBody]로 바인딩 소스를 명시합니다- 사용자 지정 형식에
TryParse를 구현하면 라우트 및 쿼리 바인딩이 자동으로 수행됩니다 - 엔드포인트 필터로 유효성 검사와 같은 횡단 관심사를 처리할 수 있습니다
자주 묻는 질문
“경로 그룹, 매개 변수와 유효성 검사” 강의는 무료인가요?
네 — “경로 그룹, 매개 변수와 유효성 검사” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 C# Academy 강의 전체를 잠금 해제할 수 있습니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“경로 그룹, 매개 변수와 유효성 검사”에서 뭘 배우나요?
MapGroup으로 엔드포인트를 구성하고 경로, 쿼리, 본문 매개 변수를 바인딩하며 데이터 주석으로 유효성을 검사합니다. 브라우저에서 직접 실행하는 실습 코드로 C# Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
C# Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 C# Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“경로 그룹, 매개 변수와 유효성 검사” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 C# Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 C# Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 첫 번째 Minimal API 만들기
- 경로 그룹, 매개 변수와 유효성 검사
- Minimal API의 미들웨어와 필터
- OpenAPI, 버전 관리와 배포