푸터 콘텐츠로 바로가기
Iron Academy Logo
C# 배우기
C# 배우기

다른 카테고리

Linux에서 .NET Aspire에 유효성 검사와 함께 POST 삽입 엔드포인트 추가하기

[[academy-video-youtube({"vid": "oAMMHR8kKnw", "start_time": "0", "title": "Linux의 .NET Aspire에서 유효성 검사를 사용하여 POST 삽입 엔드포인트 추가", "creator": "Tim Corey", "length": "20m 31s"})]]

API에서 데이터를 읽는 것은 이야기의 절반에 불과합니다. 결국 모든 애플리케이션은 새로운 레코드를 받아들이는 것이 필요하며, 이는 요청 본문을 수신하고 입력을 검증하며, 이를 데이터베이스에 저장하고 의미 있는 상태 코드를 반환하는 POST 엔드포인트를 구축하는 것을 의미합니다. 프로토타입 작성 중에는 검증 단계를 건너뛰는 것이 유혹적이지만, 입력을 검증하지 않는 프로덕션 API은 오염된 데이터의 출처가 되어 정리를 더 어렵게 만듭니다.

비디오 "Adding a POST Insert Endpoint with Validation in .NET Aspire on Linux"에서 Tim Corey는 Tiny Ticket API에 입력 엔드포인트를 추가하고 전용 입력 레코드 유형을 생성하여 최소 API에 대해 .NET의 내장된 검증 파이프라인을 연결하고 API 시작 시 Swagger가 자동으로 실행되도록 구성합니다. 이번 에피소드에서는 저장 프로시저에서 테스트된 엔드포인트까지의 전체 사이클을 다루며, .NET이 기본적으로 반환하는 검증 오류 응답 형식도 포함합니다. Linux 시리즈의 C#을 따르거나 처음으로 최소 API에 쓰기 작업을 추가하는 경우, 이 기사는 각 단계를 안내합니다.

Insert 레코드 유형 생성

[1:46 - 4:43] 엔드포인트를 빌드하기 전에, Tim은 삽입 요청의 형태를 나타내는 데이터 전송 객체를 생성합니다. 기존의 TicketModel에는 데이터베이스에서 자동으로 생성하는 IdCreatedDate 같은 필드가 포함되어 있습니다. 이러한 필드를 POST 본문에서 허용하면 무시되거나 충돌을 일으킬 수 있으므로 별도의 유형이 호출자가 제공해야 할 필드로 입력을 제한합니다.

public record TicketInsertRecord(string Title, string Description, int Priority);
public record TicketInsertRecord(string Title, string Description, int Priority);

record 대신 class을 사용하는 것은 고의적인 선택입니다. 레코드는 기본적으로 값 기반의 평등성과 불변성을 제공하여, 요청 페이로드의 의미에 적합합니다: 데이터가 도착하고, 유효성 검사를 거쳐 데이터베이스로 전달되며, 그 사이에 절대 수정되지 않습니다. 세 가지 속성(Title, Description, Priority)은 spTickets_Insert 저장 프로시저의 매개 변수에 직접 매핑됩니다.

POST 엔드포인트 매핑

[4:43 - 9:51] 레코드 유형이 정의되면, 엔드포인트 등록이 GET 경로와 동일한 패턴을 따르지만 MapPost를 사용하여 요청 본문을 삽입 레코드에 바인딩합니다:

app.MapPost("/api/tickets", async (TicketInsertRecord ticket, IDbConnection db) =>
{
    await db.SaveDataAsync("spTickets_Insert", ticket);
    return Results.NoContent();
});
app.MapPost("/api/tickets", async (TicketInsertRecord ticket, IDbConnection db) =>
{
    await db.SaveDataAsync("spTickets_Insert", ticket);
    return Results.NoContent();
});

라우트는 /api/tickets ID 세그먼트 없이, POST를 컬렉션 URL로 수행하여 새로운 리소스를 생성한다는 REST 규칙과 일치합니다. 핸들러는 전체 ticket 객체를 매개 변수 백으로 하여 저장 프로시저를 호출합니다. Dapper는 레코드의 속성을 SQL 매개변수에 이름별로 매핑합니다.

Results.NoContent()를 반환하면 204 상태 코드를 전송합니다. Tim은 삽입이 성공했지만 응답 본문에 반환할 의미 있는 것이 없기 때문이라고 설명합니다. 일부 API는 새로 생성된 객체와 함께 201 Created 상태 및 새로운 리소스를 가리키는 Location 헤더를 반환하는데, 이는 유효한 대안입니다. Tiny Ticket 프로젝트에서는 204가 간결함을 유지합니다.

Swagger를 통한 삽입 테스트

[9:51 - 14:43] Tim은 프로젝트를 실행하고 Swagger로 이동합니다. POST 엔드포인트는 TicketInsertRecord 속성과 일치하는 요청 본문 스키마와 함께 나타납니다. 그는 제목, 설명, 우선순위로 테스트 티켓을 채우고 요청을 실행합니다.

204가 반환되어 삽입이 성공했음을 확인합니다. 데이터가 실제로 저장되었는지 확인하기 위해 그는 모든 엔드포인트를 가져와 실행합니다. 새 티켓은 원래의 테스트 기록과 함께 목록에 나타납니다.

테스트는 또한 검증 없이 발생하는 간극을 드러냅니다: 빈 제목, 설명 누락, 99와 같은 우선순위 전송은 모두 204로 성공합니다. 데이터베이스는 API가 보내는 모든 것을 수용합니다. 이 간격은 다음 섹션을 유도합니다.

내장된 유효성 검사 추가

[14:43 - 18:28] .NET 10부터 최소 API가 입력 유형에서 데이터 어노테이션 속성을 읽고 핸들러가 실행되기 전에 잘못된 요청을 거부하는 내장된 유효성 검사 파이프라인을 지원합니다. 팀은 이를 두 단계로 연결합니다.

먼저, Program.cs에 유효성 검사 서비스를 등록합니다. 이 한 줄로 전체 파이프라인을 활성화합니다:

builder.Services.AddValidation();
builder.Services.AddValidation();

서비스가 등록되면, 프레임워크는 핸들러가 실행되기 전에 모든 요청 본문을 유효성 검사 속성을 검사합니다. 두 번째 단계는 각 필드가 충족해야 하는 규칙으로 삽입 레코드를 주석 처리하는 것입니다:

public record TicketInsertRecord(
    [Required, MinLength(1)] string Title,
    [Required] string Description,
    [Range(1, 5)] int Priority
);
public record TicketInsertRecord(
    [Required, MinLength(1)] string Title,
    [Required] string Description,
    [Range(1, 5)] int Priority
);

[Required]는 필드가 존재하며 null이 아님을 보장합니다. [MinLength(1)]는 빈 문자열이 필수 검사(빈 문자열은 기술적으로 null이 아니기 때문에)를 통과하는 것을 방지합니다. [Range(1, 5)]는 우선순위를 유효한 등급으로 제한합니다. 이 속성들은 ASP.NET MVC 컨트롤러가 수년 동안 사용해온 동일한 System.ComponentModel.DataAnnotations 유형들로, 추가 미들웨어 없이 미니멀 API에서도 작동합니다.

저장하고 다시 시작한 후, 팀은 비어 있는 제목과 우선순위 10으로 요청을 보냅니다. 응답은 구조화된 오류 본문을 가진 400 잘못된 요청으로 돌아옵니다:

{
    "errors": {
        "Title": ["The Title field is required."],
        "Priority": ["The field Priority must be between 1 and 5."]
    }
}

유효성 검사 파이프라인이 핸들러가 실행되기 전에 요청을 단락 처리하므로, 잘못된 데이터가 데이터베이스에 도달하지 않습니다. 오류 응답은 API 소비자들이 프로그램 방식으로 구문 분석할 수 있는 RFC 7807 문제 세부사항 형식을 따릅니다.

시작 시 자동으로 Swagger 시작하기

[19:44 - 20:31] 작은 삶의 질 향상이 에피소드를 마무리합니다. Tim이 API를 실행할 때마다, 그는 수동으로 브라우저 URL에 /swagger을 입력해야 했습니다. 이를 자동화하기 위해, 그는 API 프로젝트의 Properties/launchSettings.json을 열고 HTTPS 프로파일에 launchUrl 속성을 추가합니다:

{
    "profiles": {
        "https": {
            "launchUrl": "swagger"
        }
    }
}

다음 실행에서 브라우저는 기본 페이지를 대신하여 Swagger UI로 직접 열립니다. 이는 전체 개발 세션 동안 몇 초를 줄일 수 있습니다.

결론

[20:09 - 20:31] 최소 API에 POST 엔드포인트를 추가하는 것은 전용 입력 레코드를 생성하고 이를 컬렉션 URL이 있는 MapPost에 매핑하며 저장 프로시저를 파라미터 객체로 레코드와 함께 호출하는 것을 포함합니다. .NET 10에서의 유효성 검사는 하나의 서비스 등록과 레코드 속성에 대한 표준 데이터 어노테이션 속성이 필요합니다. 프레임워크가 400 응답 형식을 자동으로 처리합니다.

시리즈 네비게이션: 이 기사는 Linux에서 Tiny Ticket 앱을 구축하는 C# 시리즈의 일부입니다. 이전: ID로 가져오기 엔드포인트 추가. 다음: PUT 업데이트 엔드포인트 추가.

예제 팁: 삽입 저장 프로시저가 새 레코드의 ID를 반환할 때, Results.NoContent()에서 Results.Created($"/api/tickets/{newId}", result)로 반환을 변경하여 호출자에게 201 상태와 따라가서 생성된 리소스를 가져올 수 있는 위치 헤더를 제공합니다.

그의 YouTube 채널에서 전체 비디오를 보고 C# 시리즈의 Linux에서 쓰기 엔드포인트 구축에 대한 더 많은 통찰력을 얻으세요.

Hero Worlddot related to Linux에서 .NET Aspire에 유효성 검사와 함께 POST 삽입 엔드포인트 추가하기
Hero Affiliate related to Linux에서 .NET Aspire에 유효성 검사와 함께 POST 삽입 엔드포인트 추가하기

사랑하는 것을 공유하여 더 많은 수익을 얻으세요

당신은 .NET, C#, Java, Python, 또는 Node.js를 다루는 개발자를 위한 콘텐츠를 만드나요? 당신의 전문성을 추가 수입으로 전환하세요!

아이언 서포트 팀

저희는 주 5일, 24시간 온라인으로 운영합니다.
채팅
이메일
전화해