.NET 10에서는 Swagger가 기본으로 제공될까요? 정확히는 OpenAPI 문서 생성 기능을 Microsoft가 공식 지원하며, Swagger UI와 Scalar 같은 웹 기반 API 테스트 화면은 별도 패키지를 설치하여 사용할 수 있습니다. 이 글에서는 Visual Studio Code 환경에서 .NET 10 Web API를 생성하고, OpenAPI JSON과 Swagger UI 및 Scalar를 각각 실행하는 방법을 단계별로 정리합니다.
OpenAPI 명세 JSON:
/openapi/v1.jsonSwagger UI:
/swagger (별도 설치)Scalar:
/scalar (별도 설치)기본 권장:
Microsoft.AspNetCore.OpenApi + 필요한 UI 하나 선택1. .NET 8과 .NET 10의 OpenAPI·Swagger 비교
| 항목 | .NET 8 일반적인 구성 | .NET 10 기본 구성 |
|---|---|---|
| 문서 생성 | Swashbuckle 많이 사용 | Microsoft.AspNetCore.OpenApi |
| 서비스 등록 | AddSwaggerGen() (Swashbuckle) |
AddOpenApi() |
| JSON 노출 | UseSwagger() (Swashbuckle) |
MapOpenApi() |
| 기본 JSON 경로 | /swagger/v1/swagger.json |
/openapi/v1.json |
| UI 포함 여부 | 패키지/템플릿 구성에 따름 | 기본 템플릿에 UI 미포함 |
| 기본 OpenAPI 버전 | 패키지 설정에 따라 다름 | 3.1 |
참고: .NET 8에서도 다른 패키지 조합으로 OpenAPI를 구현할 수 있습니다. 위 표는 흔히 사용하는 프로젝트 구성을 비교한 것입니다.
2. .NET 10 SDK 확인 및 Web API 프로젝트 생성
먼저 Microsoft .NET 10 SDK를 설치합니다. VS Code의 터미널을 열고 설치 여부를 확인합니다.
|
1 2 3 4 |
dotnet --version dotnet --list-sdks |
새 프로젝트를 생성하고 폴더로 이동합니다.
|
1 2 3 4 5 |
dotnet new webapi -n MyApi -f net10.0 cd MyApi code . |
일반적인 .NET 10 Web API 템플릿은 Microsoft.AspNetCore.OpenApi 관련 구성을 포함합니다. 기존 프로젝트라면 NuGet 패키지를 추가할 수 있습니다.
|
1 2 3 |
dotnet add package Microsoft.AspNetCore.OpenApi |
3. .NET 10 기본 OpenAPI 기능 활성화
Program.cs를 다음과 같이 구성합니다. 아래 예제는 최소 API(Minimal API) 프로젝트로, 외부 Swagger 문서 생성 패키지 없이 OpenAPI JSON을 제공하는 방식입니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
var builder = WebApplication.CreateBuilder(args); builder.Services.AddOpenApi(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.MapOpenApi(); } app.MapGet("/hello", () => Results.Ok(new { Message = "Hello .NET 10" })) .WithName("GetHello"); app.Run(); |
프로젝트를 실행합니다.
|
1 2 3 |
dotnet run |
터미널에 표시되는 포트를 확인한 뒤 브라우저에서 다음 URL을 엽니다.
|
1 2 3 |
https://localhost:포트번호/openapi/v1.json |
정상 응답에서는 문서의 최상단에서 "openapi": "3.1.0"과 같은 버전 필드를 확인할 수 있습니다. 단, 이 단계에서는 시각적인 Swagger UI 화면이 아니라 JSON 문서가 출력됩니다.
4. Swagger UI 설치 및 사용
API 목록을 브라우저에서 보고 Try it out으로 직접 테스트하려면 UI 전용 패키지를 추가합니다. .NET 10의 기본 OpenAPI 생성 기능을 사용한다면 문서 생성기를 중복 등록할 필요가 없습니다.
|
1 2 3 |
dotnet add package Swashbuckle.AspNetCore.SwaggerUi |
다음은 Swagger UI까지 활성화한 전체 Program.cs입니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
var builder = WebApplication.CreateBuilder(args); builder.Services.AddOpenApi(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.MapOpenApi(); app.UseSwaggerUI(options => { options.SwaggerEndpoint("/openapi/v1.json", "MyApi v1"); }); } app.MapGet("/hello", () => Results.Ok(new { Message = "Hello .NET 10" })) .WithName("GetHello"); app.Run(); |
실행 후 https://localhost:포트번호/swagger로 접속합니다. 실제 포트 번호는 dotnet run 출력에 표시된 주소를 따릅니다.
5. Swagger UI 대신 Scalar 사용하기
Scalar는 OpenAPI 문서를 읽어 API 목록과 요청/응답을 시각적으로 표시하는 현대적인 대화형 API 문서 도구입니다. 원하는 UI에 따라 Swagger UI 대신 선택할 수 있습니다.
|
1 2 3 |
dotnet add package Scalar.AspNetCore |
Scalar를 사용하는 경우 Program.cs 예제:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
using Scalar.AspNetCore; var builder = WebApplication.CreateBuilder(args); builder.Services.AddOpenApi(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.MapOpenApi(); app.MapScalarApiReference(); } app.MapGet("/hello", () => Results.Ok(new { Message = "Hello .NET 10" })) .WithName("GetHello"); app.Run(); |
실행 후 https://localhost:포트번호/scalar로 접속합니다. Swagger UI와 Scalar는 둘 다 OpenAPI JSON을 소비하는 도구이며, 일반적인 개인 개발 환경에서는 둘 중 하나만 설치해도 충분합니다.
5-1. Scalar 실전 사용법: GET·POST API 직접 테스트
Scalar는 단순한 API 문서 뷰어가 아닙니다. API 엔드포인트를 선택하여 요청을 전송하고 HTTP 상태 코드와 JSON 응답을 확인하는 대화형 API 테스트 기능을 제공합니다. 아래 예제는 앞서 만든 .NET 10 프로젝트에서 바로 실습할 수 있습니다.
① 실습용 GET·POST 엔드포인트 작성
기존 Program.cs를 아래 예제로 바꿉니다. 메모리에 상품 목록을 저장하는 단순한 샘플이며 데이터베이스가 필요하지 않습니다. 프로그램을 재시작하면 상품 목록이 초기화됩니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
using Scalar.AspNetCore; var builder = WebApplication.CreateBuilder(args); builder.Services.AddOpenApi(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.MapOpenApi(); app.MapScalarApiReference(options => { options.WithTitle("MyApi - Scalar API 테스트"); }); } var products = new List<Product> { new(1, "Keyboard", 35000), new(2, "Mouse", 19000) }; // GET /api/products : 목록 조회 app.MapGet("/api/products", () => Results.Ok(products)) .WithName("GetProducts"); // GET /api/products/1 : 상품 한 개 조회 app.MapGet("/api/products/{id:int}", (int id) => { var item = products.FirstOrDefault(p => p.Id == id); return item is null ? Results.NotFound() : Results.Ok(item); }).WithName("GetProductById"); // POST /api/products : 상품 등록 app.MapPost("/api/products", (CreateProductRequest request) => { var newId = products.Count == 0 ? 1 : products.Max(p => p.Id) + 1; var item = new Product(newId, request.Name, request.Price); products.Add(item); return Results.Created($"/api/products/{item.Id}", item); }).WithName("CreateProduct"); app.Run(); record Product(int Id, string Name, decimal Price); record CreateProductRequest(string Name, decimal Price); |
실행 명령:
|
1 2 3 |
dotnet run |
터미널의 실제 주소를 기준으로 https://localhost:포트번호/scalar에 접속합니다. HTTPS 주소가 없다면 터미널에 표시된 HTTP 주소에서 동일한 경로를 사용하세요. /openapi/v1.json에는 이 세 가지 API가 문서화되어 있어야 합니다.
② Scalar 화면에서 API 찾기
- 브라우저에서
/scalar페이지를 엽니다. - API 목록에서
GET /api/products,GET /api/products/{id},POST /api/products항목을 찾습니다. - 메서드와 경로를 클릭해 설명, 매개변수, 요청 및 응답 형식을 확인합니다.
- Test Request 기능을 열어 테스트 요청을 준비합니다. 메뉴 이름이나 배치는 Scalar 버전에 따라 조금 다를 수 있습니다.
③ GET 요청 테스트
GET /api/products를 선택하고 테스트 요청을 전송합니다. 정상 응답이라면 상태 코드는 200 OK이며 아래와 비슷한 JSON 목록이 표시됩니다.
|
1 2 3 4 5 6 |
[ { "id": 1, "name": "Keyboard", "price": 35000 }, { "id": 2, "name": "Mouse", "price": 19000 } ] |
GET /api/products/{id}를 선택하여 경로 매개변수 id에 1을 입력하고 전송하면 Keyboard 상품 한 건을 받습니다. 존재하지 않는 id를 입력하면 예제 코드에서 404 Not Found를 반환합니다.
④ POST 요청: JSON 등록하기
POST /api/products를 선택한 뒤 요청 본문(Body)에 다음 JSON을 입력합니다. Content-Type: application/json을 사용해야 하며 Scalar의 요청 화면에서 해당 헤더를 확인할 수 있습니다.
|
1 2 3 4 5 6 |
{ "name": "Monitor", "price": 250000 } |
요청을 전송하면 샘플 API는 201 Created를 반환합니다. 응답 본문은 다음과 비슷합니다. 다시 GET /api/products를 호출하면 신규 상품이 목록에 포함된 것을 확인할 수 있습니다.
|
1 2 3 4 5 6 7 |
{ "id": 3, "name": "Monitor", "price": 250000 } |
⑤ 응답 결과에서 확인할 사항
- Status: 200(조회 성공), 201(생성 성공), 400(잘못된 요청), 401(인증 필요), 403(권한 부족), 404(경로/리소스 없음), 500(서버 예외) 등
- Response Body: API가 반환한 JSON 및 오류 설명
- Headers: 응답 Content-Type 등 HTTP 헤더
- Code Samples: 지원되는 언어·HTTP 클라이언트별 요청 예시를 확인하고 복사하여 재사용
⑥ JWT Bearer 토큰이 필요한 API 테스트
인증이 필요한 엔드포인트를 테스트하는 경우 Scalar의 인증(Auth/Authentication) 입력 영역에서 Bearer 토큰을 입력할 수 있습니다. 정상적인 요청에는 일반적으로 아래 헤더가 추가됩니다.
|
1 2 3 |
Authorization: Bearer eyJhbGciOi... |
주의: Scalar의 인증 UI에 선택할 항목을 표시하려면 OpenAPI 문서에 해당 보안 스키마가 정의되어 있어야 합니다. 단순히 app.MapScalarApiReference()를 호출한다고 ASP.NET Core 서버에 JWT 인증 기능이 추가되지는 않습니다. 실제 API에도 인증 미들웨어와 권한 설정이 필요합니다. 개발 중에도 토큰·비밀번호를 Program.cs에 하드코딩하거나 공개 문서에 포함하지 마세요.
⑦ Scalar의 제목·레이아웃·접속 경로 변경
Scalar UI 제목과 배치를 변경할 수 있습니다. 아래 코드는 app.MapScalarApiReference() 부분을 대체하는 예제입니다.
|
1 2 3 4 5 6 7 |
app.MapScalarApiReference("/docs", options => { options.WithTitle("MyApi 개발자 API 문서") .WithClassicLayout(); }); |
이 설정을 적용한 뒤 브라우저에서 https://localhost:포트번호/docs로 접속합니다. WithClassicLayout()은 사용하기 쉬운 문서 레이아웃 선택지 중 하나입니다.
⑧ 자주 발생하는 문제 해결
- /scalar가 404:
Scalar.AspNetCore설치와MapScalarApiReference()호출, 그리고 Development 환경인지 확인합니다. - API 목록이 비어 있음:
/openapi/v1.json이 정상 JSON을 반환하는지 확인하고 최소 API가app.Run()보다 앞에 등록되어 있는지 점검합니다. - 404/405 응답: 요청 URL, HTTP 메서드(GET/POST),
id등 경로 값을 확인합니다. - 400 응답: Body의 JSON 문법과 속성명·값 유형을 확인합니다.
- 401/403 응답: 인증 토큰, 만료 여부, 서버의 권한 정책을 점검합니다.
- 브라우저 요청 실패: API 서버가 실행 중인지, 실제 포트/HTTP·HTTPS 주소가 맞는지, 인증서나 CORS 정책 문제는 없는지 확인합니다.
추가 참고: Scalar는 웹 API 문서 페이지 외에도 별도 API Client 제품을 제공합니다. 독립형 클라이언트에서는 컬렉션, 환경 변수, 요청 자동화 및 응답 테스트를 더 폭넓게 활용할 수 있습니다. 두 제품을 동일한 UI로 혼동하지 마세요.
Scalar 공식 사용 안내: ASP.NET Core + Scalar 시작하기 / Scalar.AspNetCore 설정과 인증 / Scalar API Client 사용 가이드
6. Swagger UI와 Scalar 비교
| 구분 | Swagger UI | Scalar |
|---|---|---|
| 기본 용도 | API 문서 확인·요청 테스트 | API 문서 확인·요청 테스트 |
| 화면 구성 | 전통적인 Swagger UI | 현대적인 문서 UI |
| NuGet 패키지 | Swashbuckle.AspNetCore.SwaggerUi | Scalar.AspNetCore |
| 접속 주소 | /swagger |
/scalar |
7. 자주 발생하는 오류와 해결 방법
오류 ① Unable to render this definition
|
1 2 3 4 |
The provided definition does not specify a valid version field. Supported version fields are swagger: "2.0" and openapi: 3.x.y |
먼저 /openapi/v1.json을 직접 열어서 openapi 버전 필드가 있는지 확인합니다. 404나 500 오류 또는 HTML 오류 페이지가 나오면 Swagger UI보다 서버의 JSON 생성 오류부터 해결해야 합니다. .NET 10 기본 구성과 이전 Swashbuckle 경로(/swagger/v1/swagger.json)를 혼동하지 않도록 주의하세요.
오류 ② Microsoft.OpenApi.Models.OpenApiOperation TypeLoadException
|
1 2 3 4 5 |
System.TypeLoadException: Could not load type 'Microsoft.OpenApi.Models.OpenApiOperation' from assembly 'Microsoft.OpenApi, Version=2.7.5.0' |
이 오류는 일반적으로 오래된 OpenAPI 관련 코드·패키지가 새로운 Microsoft.OpenApi 2.x와 충돌할 때 나타납니다. 예를 들어 .NET 8의 일부 .WithOpenApi() 구현과 OpenAPI.NET 2.x 조합은 호환되지 않을 수 있습니다.
프로젝트에서 직접 참조한 패키지와 간접 참조한 패키지를 확인합니다.
|
1 2 3 |
dotnet list package --include-transitive |
중요: .NET 10에서는 Microsoft.OpenApi 2.x 기반 변경 사항이 있으므로, 이전 오류를 해결하기 위해 무조건 1.x로 다운그레이드하는 방법은 권장하지 않습니다. .NET 버전과 OpenAPI 패키지의 호환 조합을 확인하고, 사용하지 않는 오래된 Swagger 설정이나 .WithOpenApi() 코드를 정리하세요.
오류 ③ /swagger 또는 /scalar 접속 시 404
해당 UI 패키지를 설치했는지, UseSwaggerUI() 또는 MapScalarApiReference()를 등록했는지 확인합니다. 예제처럼 IsDevelopment() 조건 안에 두었다면 환경이 Development가 아닐 때는 UI가 표시되지 않습니다.
오류 ④ 설치 후에도 이전 오류가 반복됨
브라우저 캐시를 강력 새로고침(Ctrl + F5)하고 패키지 참조를 점검한 뒤 다시 빌드합니다.
|
1 2 3 4 5 6 |
dotnet clean dotnet restore dotnet build dotnet run |
8. 운영 환경에서 주의할 점
OpenAPI 문서에는 API 엔드포인트·매개변수·데이터 모델 정보가 포함될 수 있습니다. 일반적으로 Swagger UI나 Scalar 같은 대화형 API 문서 UI는 개발 환경에서만 활성화하는 것이 안전합니다. 운영 환경에 공개해야 한다면 인증·인가 및 접근 제어를 적용하세요.
9. 결론
.NET 10에서는 OpenAPI JSON 생성에 AddOpenApi()와 MapOpenApi()를 사용하면 됩니다. API 테스트 화면이 필요하다면 Swagger UI 또는 Scalar를 추가하세요. 새로 만드는 API 프로젝트에서는 .NET 10 기본 OpenAPI + Scalar 조합이 간단하고 편리한 선택이며, 기존 Swagger UI에 익숙하다면 UI 전용 패키지를 사용하는 방식도 좋습니다.