참고
이 문서의 최신 버전은 아닙니다. 현재 릴리스는 이 문서의 .NET 9 버전을 참조 하세요.
중요한
이 정보는 상업적으로 출시되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적, 또는 묵시적인 보증을 하지 않습니다.
현재 릴리스는 이 문서의 .NET 9 버전을 참조 하세요.
작성자: Pratik Khandelwal 및 Scott Addie
이 자습서에서는 MongoDB NoSQL 데이터베이스에 대해 CRUD(만들기, 읽기, 업데이트 및 삭제) 작업을 실행하는 웹 API를 만듭니다.
이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.
- MongoDB 구성
- MongoDB 데이터베이스 만들기
- MongoDB 컬렉션 및 스키마 정의
- 웹 API에서 MongoDB CRUD 작업 수행
- JSON 직렬화 사용자 지정
필수 조건
ASP.NET 및 웹 개발 워크로드가 있는 Visual Studio 2022
MongoDB 구성
개발 컴퓨터(Windows/Linux/macOS)의 어디에서나 MongoDB 및 MongoDB Shell 액세스를 사용하도록 설정합니다.
MongoDB 셸 다운로드 및 설치:
- macOS/Linux: MongoDB 셸을 추출할 디렉터리를 선택합니다. 환경 변수에 대한
mongosh
PATH
결과 경로를 추가합니다. - Windows: MongoDB Shell(mongosh.exe)은 C:\Users\user<\>AppData\Local\Programs\mongosh에 설치됩니다. 환경 변수에 대한
mongosh.exe
PATH
결과 경로를 추가합니다.
- macOS/Linux: MongoDB 셸을 추출할 디렉터리를 선택합니다. 환경 변수에 대한
MongoDB 다운로드 및 설치:
- macOS/Linux: MongoDB가 설치된 디렉터리(일반적으로 /usr/local/mongodb)를 확인합니다. 환경 변수에 대한
mongodb
PATH
결과 경로를 추가합니다. - Windows: MongoDB는 기본적으로 C:\Program Files\MongoDB에 설치됩니다.
C:\Program Files\MongoDB\Server\<version_number>\bin을
PATH
환경 변수에 추가합니다.
- macOS/Linux: MongoDB가 설치된 디렉터리(일반적으로 /usr/local/mongodb)를 확인합니다. 환경 변수에 대한
Data Storage 디렉터리 선택: 데이터 저장을 위해 개발 머신에서 디렉터리를 선택합니다. 디렉터리가 없을 경우 새로 만듭니다. MongoDB 셸은 새 디렉터리를 만들지 않습니다.
- macOS/Linux: 예를 들면 다음과 같습니다
/usr/local/var/mongodb
. - Windows: 예를 들면 다음과 같습니다
C:\\BooksData
.
- macOS/Linux: 예를 들면 다음과 같습니다
OS 명령 셸(MongoDB 셸 아님)에서 다음 명령을 사용하여 기본 포트 27017에서 MongoDB에 연결합니다. 이전 단계에서 선택한 디렉터리로
<data_directory_path>
을(를) 바꾸십시오.mongod --dbpath <data_directory_path>
다음 단계에서 이전에 설치된 MongoDB Shell을 사용하여 데이터베이스 및 컬렉션을 만들고 문서를 저장합니다. MongoDB Shell 명령에 대한 자세한 내용은 mongosh
를 참조하세요.
MongoDB 명령 셸 인스턴스를 시작
mongosh.exe
하거나 명령 셸에서 다음 명령을 실행하여 엽니다.mongosh
명령 셸에서 다음을 실행하여 기본 테스트 데이터베이스에 연결합니다.
use BookStore
아직 존재하지 않는 경우 BookStore라는 데이터베이스가 생성됩니다. 데이터베이스가 있는 경우 트랜잭션을 위해 해당 연결이 열립니다.
다음 명령을 사용하여
Books
컬렉션을 만듭니다.db.createCollection('Books')
다음 결과가 표시됩니다.
{ "ok" : 1 }
다음 명령을 사용하여
Books
컬렉션에 대한 스키마를 정의하고 두 개의 문서를 삽입합니다.db.Books.insertMany([{ "Name": "Design Patterns", "Price": 54.93, "Category": "Computers", "Author": "Ralph Johnson" }, { "Name": "Clean Code", "Price": 43.15, "Category": "Computers","Author": "Robert C. Martin" }])
다음과 비슷한 결과가 표시됩니다.
{ "acknowledged" : true, "insertedIds" : [ ObjectId("61a6058e6c43f32854e51f51"), ObjectId("61a6058e6c43f32854e51f52") ] }
참고
ObjectId
이전 결과에 표시된 내용이 명령 셸에 표시된 것과 일치하지 않습니다.다음 명령을 사용하여 데이터베이스의 문서를 봅니다.
db.Books.find().pretty()
다음과 비슷한 결과가 표시됩니다.
{ "_id" : ObjectId("61a6058e6c43f32854e51f51"), "Name" : "Design Patterns", "Price" : 54.93, "Category" : "Computers", "Author" : "Ralph Johnson" } { "_id" : ObjectId("61a6058e6c43f32854e51f52"), "Name" : "Clean Code", "Price" : 43.15, "Category" : "Computers", "Author" : "Robert C. Martin" }
스키마가 각 문서에 대해 자동 생성된
_id
형식의ObjectId
속성을 추가합니다.
ASP.NET Core 웹 API 프로젝트 만들기
- 파일>새로 만들기>프로젝트로 이동합니다.
- ASP.NET Core Web API 프로젝트 형식을 선택하고 다음을 선택합니다.
- 프로젝트 이름을 BookStoreApi로 지정하고 다음을 선택합니다.
- 추가 정보 대화 상자에서 다음을 수행합니다.
- Framework이 .NET 9.0(표준 용어 지원)입니다.
- 컨트롤러 사용 확인란이 선택되어 있는지 확인합니다.
- OpenAPI 지원 사용을 위한 확인란이 선택되어 있는지 확인합니다.
- 선택하기만들기.
패키지 관리자 콘솔 창에서 프로젝트 루트로 이동합니다. 다음 명령을 실행하여 MongoDB용 .NET 드라이버를 설치합니다.
Install-Package MongoDB.Driver
엔터티 모델 추가
프로젝트 루트에 Models 디렉터리를 추가합니다.
다음 코드를 사용하여
Book
디렉터리에 클래스를 추가합니다.using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; namespace BookStoreApi.Models; public class Book { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } [BsonElement("Name")] public string BookName { get; set; } = null!; public decimal Price { get; set; } public string Category { get; set; } = null!; public string Author { get; set; } = null!; }
앞의 클래스에서
Id
속성은- CLR(공용 언어 런타임) 개체를 MongoDB 컬렉션에 매핑하는 데 필요합니다.
- 이 속성을 문서의 기본 키로 설정하기 위해
[BsonId]
로 주석이 추가됩니다. -
[BsonRepresentation(BsonType.ObjectId)]
의 주석은 매개 변수를string
구조체 대신 형식으로 전달할 수 있도록 추가됩니다. Mongo는string
에서ObjectId
로 변환을 처리합니다.
BookName
속성에[BsonElement]
특성이 주석으로 추가되었습니다.Name
의 특성 값은 MongoDB 컬렉션의 속성 이름을 나타냅니다.
구성 모델 추가
다음 데이터베이스 구성 값을
appsettings.json
에 추가합니다.{ "BookStoreDatabase": { "ConnectionString": "mongodb://localhost:27017", "DatabaseName": "BookStore", "BooksCollectionName": "Books" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
다음 코드를 사용하여
BookStoreDatabaseSettings
디렉터리에 클래스를 추가합니다.namespace BookStoreApi.Models; public class BookStoreDatabaseSettings { public string ConnectionString { get; set; } = null!; public string DatabaseName { get; set; } = null!; public string BooksCollectionName { get; set; } = null!; }
위의
BookStoreDatabaseSettings
클래스는appsettings.json
파일의BookStoreDatabase
속성 값을 저장하는 데 사용됩니다. JSON 및 C# 속성 이름은 매핑 프로세스를 용이하게 하기 위해 동일한 이름이 지정됩니다.다음 강조 표시된 코드를
Program.cs
에 추가합니다.var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase"));
위의 코드에서
appsettings.json
파일의BookStoreDatabase
섹션이 바인딩되는 구성 인스턴스가 DI(종속성 주입) 컨테이너에 등록됩니다. 예를 들어BookStoreDatabaseSettings
개체의ConnectionString
속성은BookStoreDatabase:ConnectionString
의appsettings.json
속성으로 채워집니다.Program.cs
의 맨 위에 다음 코드를 추가하여BookStoreDatabaseSettings
참조를 확인합니다.using BookStoreApi.Models;
CRUD 작업 서비스 추가
프로젝트 루트에 Services 디렉터리를 추가합니다.
다음 코드를 사용하여
BooksService
디렉터리에 클래스를 추가합니다.using BookStoreApi.Models; using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BookStoreApi.Services; public class BooksService { private readonly IMongoCollection<Book> _booksCollection; public BooksService( IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings) { var mongoClient = new MongoClient( bookStoreDatabaseSettings.Value.ConnectionString); var mongoDatabase = mongoClient.GetDatabase( bookStoreDatabaseSettings.Value.DatabaseName); _booksCollection = mongoDatabase.GetCollection<Book>( bookStoreDatabaseSettings.Value.BooksCollectionName); } public async Task<List<Book>> GetAsync() => await _booksCollection.Find(_ => true).ToListAsync(); public async Task<Book?> GetAsync(string id) => await _booksCollection.Find(x => x.Id == id).FirstOrDefaultAsync(); public async Task CreateAsync(Book newBook) => await _booksCollection.InsertOneAsync(newBook); public async Task UpdateAsync(string id, Book updatedBook) => await _booksCollection.ReplaceOneAsync(x => x.Id == id, updatedBook); public async Task RemoveAsync(string id) => await _booksCollection.DeleteOneAsync(x => x.Id == id); }
위의 코드에서 생성자 주입을 통해 DI에서
BookStoreDatabaseSettings
인스턴스가 검색됩니다. 이 방법은appsettings.json
섹션에 추가된 구성 값에 대한 액세스를 제공합니다.다음 강조 표시된 코드를
Program.cs
에 추가합니다.var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>();
위의 코드에서
BooksService
클래스는 사용 클래스에서 생성자 주입을 지원하는 DI로 등록됩니다.BooksService
가MongoClient
에 직접 종속되기 때문에 싱글톤 서비스 수명이 가장 적합합니다. 공식 Mongo 클라이언트 재사용 지침에 따라MongoClient
를 싱글톤 수명으로 DI에 등록해야 합니다.Program.cs
의 맨 위에 다음 코드를 추가하여BooksService
참조를 확인합니다.using BookStoreApi.Services;
BooksService
클래스는 다음 MongoDB.Driver
멤버를 사용하여 데이터베이스에 대해 CRUD 작업을 실행합니다.
MongoClient: 데이터베이스 작업을 실행하기 위한 서버 인스턴스를 읽습니다. 이 클래스의 생성자는 MongoDB 연결 문자열에 제공됩니다.
public BooksService( IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings) { var mongoClient = new MongoClient( bookStoreDatabaseSettings.Value.ConnectionString); var mongoDatabase = mongoClient.GetDatabase( bookStoreDatabaseSettings.Value.DatabaseName); _booksCollection = mongoDatabase.GetCollection<Book>( bookStoreDatabaseSettings.Value.BooksCollectionName); }
IMongoDatabase: 작업을 실행하기 위한 Mongo 데이터베이스를 나타냅니다. 이 자습서에서는 인터페이스의 제네릭 GetCollection<TDocument>(collection) 메서드를 사용하여 특정 컬렉션의 데이터에 액세스합니다. 이 메서드를 호출한 후 컬렉션에 대해 CRUD 작업을 실행합니다.
GetCollection<TDocument>(collection)
메서드 호출에서 다음을 수행합니다.-
collection
은 컬렉션 이름을 나타냅니다. -
TDocument
는 컬렉션에 저장된 CLR 개체 형식을 나타냅니다.
-
GetCollection<TDocument>(collection)
는 컬렉션을 나타내는 MongoCollection 개체를 반환합니다. 이 자습서에서는 컬렉션에 대해 다음 메서드를 호출합니다.
- DeleteOneAsync: 제공된 검색 조건과 일치하는 단일 문서를 삭제합니다.
- Find<TDocument>: 제공된 검색 조건과 일치하는 컬렉션의 모든 문서를 반환합니다.
- InsertOneAsync: 제공된 개체를 컬렉션에 새 문서로 삽입합니다.
- ReplaceOneAsync: 제공된 검색 조건과 일치하는 단일 문서를 제공된 개체로 바꿉니다.
컨트롤러 추가
다음 코드를 사용하여 BooksController
디렉터리에 클래스를 추가합니다.
using BookStoreApi.Models;
using BookStoreApi.Services;
using Microsoft.AspNetCore.Mvc;
namespace BookStoreApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class BooksController : ControllerBase
{
private readonly BooksService _booksService;
public BooksController(BooksService booksService) =>
_booksService = booksService;
[HttpGet]
public async Task<List<Book>> Get() =>
await _booksService.GetAsync();
[HttpGet("{id:length(24)}")]
public async Task<ActionResult<Book>> Get(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
return book;
}
[HttpPost]
public async Task<IActionResult> Post(Book newBook)
{
await _booksService.CreateAsync(newBook);
return CreatedAtAction(nameof(Get), new { id = newBook.Id }, newBook);
}
[HttpPut("{id:length(24)}")]
public async Task<IActionResult> Update(string id, Book updatedBook)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
updatedBook.Id = book.Id;
await _booksService.UpdateAsync(id, updatedBook);
return NoContent();
}
[HttpDelete("{id:length(24)}")]
public async Task<IActionResult> Delete(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
await _booksService.RemoveAsync(id);
return NoContent();
}
}
앞의 웹 API 컨트롤러는 다음과 같습니다.
-
BooksService
클래스를 사용하여 CRUD 작업을 실행합니다. - GET, POST, PUT 및 DELETE HTTP 요청을 지원하는 작업 메서드를 포함합니다.
-
CreatedAtAction 작업 메서드에서
Create
를 호출하여 HTTP 201 응답을 반환합니다. 상태 코드 201은 서버에서 새 리소스를 만드는 HTTP POST 메서드의 표준 응답입니다. 또한CreatedAtAction
는Location
헤더를 응답에 추가합니다.Location
헤더는 새로 만든 책의 URI를 지정합니다.
JSON serialization 옵션 구성
웹 API 테스트 섹션에서 반환된 JSON 응답에 대해 변경하는 두 개의 세부 정보가 있습니다.
- 속성 이름의 기본 카멜 대소문자 방식은 CLR 객체의 속성 이름에 맞춰 파스칼 대소문자 방식으로 변경해야 합니다.
-
bookName
속성은Name
으로 반환되어야 합니다.
앞의 요구 사항을 충족하기 위해 다음과 같이 변경합니다.
Program.cs
에서 다음 강조 표시된 코드를AddControllers
메서드 호출에 연결합니다.var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>(); builder.Services.AddControllers() .AddJsonOptions( options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
이전 변경으로 웹 API의 직렬화된 JSON 응답에서 속성 이름은 CLR 개체 형식의 해당 속성 이름과 일치합니다. 예를 들어
Book
클래스의Author
속성은Author
대신author
로 직렬화됩니다.Models/Book.cs
에서BookName
속성에[JsonPropertyName]
특성을 주석으로 답니다.[BsonElement("Name")] [JsonPropertyName("Name")] public string BookName { get; set; } = null!;
[JsonPropertyName]
의Name
특성 값은 웹 API의 직렬화된 JSON 응답의 속성 이름을 나타냅니다.Models/Book.cs
의 맨 위에 다음 코드를 추가하여[JsonProperty]
특성 참조를 확인합니다.using System.Text.Json.Serialization;
웹 API 테스트 섹션에 정의된 단계를 반복합니다. JSON 속성 이름의 차이를 확인합니다.
웹 API 테스트
이 자습서에서는 엔드포인트 탐색기 및 .http 파일을 사용하여 API를 테스트합니다.
앱을 빌드하고 실행합니다.
엔드포인트 탐색기에서 첫 번째 GET 엔드포인트
/api/books
를 마우스 오른쪽 단추로 클릭하고 요청 생성을 선택합니다.다음 콘텐츠가
BookStoreApi.http
파일에 추가됩니다. 요청이 처음 생성되는 경우 파일은 프로젝트 루트에 만들어집니다.@BookStoreApi_HostAddress = https://localhost:<port> GET {{BookStoreApi_HostAddress}}/api/books ###
예를 들어
https://localhost:56874
포트 번호는 앱에서 사용하는 포트로 이미 설정되어 있어야 합니다. 그렇지 않은 경우 앱을 시작할 때 출력 창에서 포트 번호를 찾을 수 있습니다.새 요청 줄 위에 있는
GET
링크를 선택합니다.GET 요청이 앱으로 전송되고 응답 창에 응답이 표시됩니다.
응답 본문은 다음과 유사한 책 항목을 포함하는 JSON 결과를 보여 줍니다.
[ { "Id": "61a6058e6c43f32854e51f51", "Name": "Design Patterns", "Price": 54.93, "Category": "Computers", "Author": "Ralph Johnson" }, { "Id": "61a6058e6c43f32854e51f52", "Name": "Clean Code", "Price": 43.15, "Category": "Computers", "Author": "Robert C. Martin" } ]
단일 책을 검색하려면
/api/books/{id}, params (string id)
에서 GET 엔드포인트를 마우스 오른쪽 단추로 클릭하고 요청 생성을 선택합니다.다음 콘텐츠가 파일에 추가됩니다
BookStoreApi.http
.@id=string GET {{BookStoreApi_HostAddress}}/api/books/{{id}} ###
예를 들어 변수를 이전 요청에서 반환된 ID 중 하나로 바꿉
id
니다.@id="61a6058e6c43f32854e51f52" GET {{BookStoreApi_HostAddress}}/api/books/{{id}} ###
새 요청 줄 위에 있는
GET
링크를 선택합니다.GET 요청이 앱으로 전송되고 응답 창에 응답이 표시됩니다.
응답 본문은 다음과 유사한 JSON을 보여 줍니다.
{ "Id": "61a6058e6c43f32854e51f52", "Name": "Clean Code", "Price": 43.15, "Category": "Computers", "Author": "Robert C. Martin" }
POST 엔드포인트를 테스트하려면
/api/books
엔드포인트를 마우스 오른쪽 단추로 클릭하고 요청 생성을 선택합니다.다음 콘텐츠가
BookStoreApi.http
파일에 추가됩니다.POST {{BookStoreApi_HostAddress}}/api/books Content-Type: application/json { //Book } ###
Book 주석을 책 개체로 JSON 요청 본문으로 교체합니다.
POST {{BookStoreApi_HostAddress}}/api/books Content-Type: application/json { "Name": "The Pragmatic Programmer", "Price": 49.99, "Category": "Computers", "Author": "Andy Hunt" } ###
요청 줄 위에 있는
POST
링크를 선택합니다.POST 요청이 앱으로 전송되고 응답 창에 응답 이 표시됩니다. 응답에는 할당된 ID가 있는 새로 만든 책이 포함되어야 합니다.
마지막으로, 책을 삭제하려면
/api/books/{id}, params (string id)
엔드포인트를 마우스 오른쪽 단추로 클릭하고 요청 생성을 선택합니다.다음 콘텐츠가 파일에 추가됩니다
BookStoreApi.http
.DELETE {{BookStoreApi_HostAddress}}/api/Books/{{id}} ###
변수를
id
이전 요청에서 반환된 ID 중 하나로 바꾸고 요청 보내기를 클릭합니다. 다음은 그 예입니다.DELETE {{BookStoreApi_HostAddress}}/api/Books/67f417517ce1b36aeab71236 ###
웹 API에 인증 지원 추가
ASP.NET Core Identity는 ASP.NET Core 웹앱에 UI(사용자 인터페이스) 로그인 기능을 추가합니다. 웹 API 및 SPA를 보호하려면 다음 중 하나를 사용합니다.
- Microsoft Entra ID
- Azure Active Directory B2C(Azure AD B2C)
- Duende Identity 서버
Duende Identity Server는 ASP.NET Core용 OpenID Connect 및 OAuth 2.0 프레임워크입니다. Duende Identity Server에서는 다음과 같은 보안 기능을 사용할 수 있습니다.
- AaaS(Authentication as a Service)
- 여러 응용 프로그램 유형에 대한 SSO(Single Sign-On/Off)
- API에 대한 액세스 제어
- 페더레이션 게이트웨이
중요한
Duende Software에서 Duende Identity 서버의 프로덕션 사용에 대한 라이선스 요금 지불을 요구할 수 있습니다. 자세한 내용은 .NET 5의 ASP.NET Core에서 .NET 6으로 마이그레이션을 참조하세요.
자세한 내용은 Duende Identity Server 설명서(Duende Software 웹 사이트)를 참조하세요.
추가 리소스
이 자습서에서는 MongoDB NoSQL 데이터베이스에 대해 CRUD(만들기, 읽기, 업데이트 및 삭제) 작업을 실행하는 웹 API를 만듭니다.
이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.
- MongoDB 구성
- MongoDB 데이터베이스 만들기
- MongoDB 컬렉션 및 스키마 정의
- 웹 API에서 MongoDB CRUD 작업 수행
- JSON 직렬화 사용자 지정
필수 조건
ASP.NET 및 웹 개발 워크로드가 있는 Visual Studio 2022
MongoDB 구성
개발 컴퓨터(Windows/Linux/macOS)의 어디에서나 MongoDB 및 MongoDB Shell 액세스를 사용하도록 설정합니다.
MongoDB 셸 다운로드 및 설치:
- macOS/Linux: MongoDB 셸을 추출할 디렉터리를 선택합니다. 환경 변수에 대한
mongosh
PATH
결과 경로를 추가합니다. - Windows: MongoDB Shell(mongosh.exe)은 C:\Users\user<\>AppData\Local\Programs\mongosh에 설치됩니다. 환경 변수에 대한
mongosh.exe
PATH
결과 경로를 추가합니다.
- macOS/Linux: MongoDB 셸을 추출할 디렉터리를 선택합니다. 환경 변수에 대한
MongoDB 다운로드 및 설치:
- macOS/Linux: MongoDB가 설치된 디렉터리(일반적으로 /usr/local/mongodb)를 확인합니다. 환경 변수에 대한
mongodb
PATH
결과 경로를 추가합니다. - Windows: MongoDB는 기본적으로 C:\Program Files\MongoDB에 설치됩니다.
C:\Program Files\MongoDB\Server\<version_number>\bin을
PATH
환경 변수에 추가합니다.
- macOS/Linux: MongoDB가 설치된 디렉터리(일반적으로 /usr/local/mongodb)를 확인합니다. 환경 변수에 대한
Data Storage 디렉터리 선택: 데이터 저장을 위해 개발 머신에서 디렉터리를 선택합니다. 디렉터리가 없을 경우 새로 만듭니다. MongoDB 셸은 새 디렉터리를 만들지 않습니다.
- macOS/Linux: 예를 들면 다음과 같습니다
/usr/local/var/mongodb
. - Windows: 예를 들면 다음과 같습니다
C:\\BooksData
.
- macOS/Linux: 예를 들면 다음과 같습니다
OS 명령 셸(MongoDB 셸 아님)에서 다음 명령을 사용하여 기본 포트 27017에서 MongoDB에 연결합니다. 이전 단계에서 선택한 디렉터리로
<data_directory_path>
을(를) 바꾸십시오.mongod --dbpath <data_directory_path>
다음 단계에서 이전에 설치된 MongoDB Shell을 사용하여 데이터베이스 및 컬렉션을 만들고 문서를 저장합니다. MongoDB Shell 명령에 대한 자세한 내용은 mongosh
를 참조하세요.
MongoDB 명령 셸 인스턴스를 시작
mongosh.exe
하거나 명령 셸에서 다음 명령을 실행하여 엽니다.mongosh
명령 셸에서 다음을 실행하여 기본 테스트 데이터베이스에 연결합니다.
use BookStore
아직 존재하지 않는 경우 BookStore라는 데이터베이스가 생성됩니다. 데이터베이스가 있는 경우 트랜잭션을 위해 해당 연결이 열립니다.
다음 명령을 사용하여
Books
컬렉션을 만듭니다.db.createCollection('Books')
다음 결과가 표시됩니다.
{ "ok" : 1 }
다음 명령을 사용하여
Books
컬렉션에 대한 스키마를 정의하고 두 개의 문서를 삽입합니다.db.Books.insertMany([{ "Name": "Design Patterns", "Price": 54.93, "Category": "Computers", "Author": "Ralph Johnson" }, { "Name": "Clean Code", "Price": 43.15, "Category": "Computers","Author": "Robert C. Martin" }])
다음과 비슷한 결과가 표시됩니다.
{ "acknowledged" : true, "insertedIds" : [ ObjectId("61a6058e6c43f32854e51f51"), ObjectId("61a6058e6c43f32854e51f52") ] }
참고
ObjectId
이전 결과에 표시된 내용이 명령 셸에 표시된 것과 일치하지 않습니다.다음 명령을 사용하여 데이터베이스의 문서를 봅니다.
db.Books.find().pretty()
다음과 비슷한 결과가 표시됩니다.
{ "_id" : ObjectId("61a6058e6c43f32854e51f51"), "Name" : "Design Patterns", "Price" : 54.93, "Category" : "Computers", "Author" : "Ralph Johnson" } { "_id" : ObjectId("61a6058e6c43f32854e51f52"), "Name" : "Clean Code", "Price" : 43.15, "Category" : "Computers", "Author" : "Robert C. Martin" }
스키마가 각 문서에 대해 자동 생성된
_id
형식의ObjectId
속성을 추가합니다.
ASP.NET Core 웹 API 프로젝트 만들기
파일>새로 만들기>프로젝트로 이동합니다.
ASP.NET Core Web API 프로젝트 형식을 선택하고 다음을 선택합니다.
프로젝트 이름을 BookStoreApi로 지정하고 다음을 선택합니다.
.NET 8.0(장기 지원) 프레임워크를 선택하고 만들기를 선택합니다.
패키지 관리자 콘솔 창에서 프로젝트 루트로 이동합니다. 다음 명령을 실행하여 MongoDB용 .NET 드라이버를 설치합니다.
Install-Package MongoDB.Driver
엔터티 모델 추가
프로젝트 루트에 Models 디렉터리를 추가합니다.
다음 코드를 사용하여
Book
디렉터리에 클래스를 추가합니다.using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; namespace BookStoreApi.Models; public class Book { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } [BsonElement("Name")] public string BookName { get; set; } = null!; public decimal Price { get; set; } public string Category { get; set; } = null!; public string Author { get; set; } = null!; }
앞의 클래스에서
Id
속성은- CLR(공용 언어 런타임) 개체를 MongoDB 컬렉션에 매핑하는 데 필요합니다.
- 이 속성을 문서의 기본 키로 설정하기 위해
[BsonId]
로 주석이 추가됩니다. -
[BsonRepresentation(BsonType.ObjectId)]
의 주석은 매개 변수를string
구조체 대신 형식으로 전달할 수 있도록 추가됩니다. Mongo는string
에서ObjectId
로 변환을 처리합니다.
BookName
속성에[BsonElement]
특성이 주석으로 추가되었습니다.Name
의 특성 값은 MongoDB 컬렉션의 속성 이름을 나타냅니다.
구성 모델 추가
다음 데이터베이스 구성 값을
appsettings.json
에 추가합니다.{ "BookStoreDatabase": { "ConnectionString": "mongodb://localhost:27017", "DatabaseName": "BookStore", "BooksCollectionName": "Books" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
다음 코드를 사용하여
BookStoreDatabaseSettings
디렉터리에 클래스를 추가합니다.namespace BookStoreApi.Models; public class BookStoreDatabaseSettings { public string ConnectionString { get; set; } = null!; public string DatabaseName { get; set; } = null!; public string BooksCollectionName { get; set; } = null!; }
위의
BookStoreDatabaseSettings
클래스는appsettings.json
파일의BookStoreDatabase
속성 값을 저장하는 데 사용됩니다. JSON 및 C# 속성 이름은 매핑 프로세스를 용이하게 하기 위해 동일한 이름이 지정됩니다.다음 강조 표시된 코드를
Program.cs
에 추가합니다.var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase"));
위의 코드에서
appsettings.json
파일의BookStoreDatabase
섹션이 바인딩되는 구성 인스턴스가 DI(종속성 주입) 컨테이너에 등록됩니다. 예를 들어BookStoreDatabaseSettings
개체의ConnectionString
속성은BookStoreDatabase:ConnectionString
의appsettings.json
속성으로 채워집니다.Program.cs
의 맨 위에 다음 코드를 추가하여BookStoreDatabaseSettings
참조를 확인합니다.using BookStoreApi.Models;
CRUD 작업 서비스 추가
프로젝트 루트에 Services 디렉터리를 추가합니다.
다음 코드를 사용하여
BooksService
디렉터리에 클래스를 추가합니다.using BookStoreApi.Models; using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BookStoreApi.Services; public class BooksService { private readonly IMongoCollection<Book> _booksCollection; public BooksService( IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings) { var mongoClient = new MongoClient( bookStoreDatabaseSettings.Value.ConnectionString); var mongoDatabase = mongoClient.GetDatabase( bookStoreDatabaseSettings.Value.DatabaseName); _booksCollection = mongoDatabase.GetCollection<Book>( bookStoreDatabaseSettings.Value.BooksCollectionName); } public async Task<List<Book>> GetAsync() => await _booksCollection.Find(_ => true).ToListAsync(); public async Task<Book?> GetAsync(string id) => await _booksCollection.Find(x => x.Id == id).FirstOrDefaultAsync(); public async Task CreateAsync(Book newBook) => await _booksCollection.InsertOneAsync(newBook); public async Task UpdateAsync(string id, Book updatedBook) => await _booksCollection.ReplaceOneAsync(x => x.Id == id, updatedBook); public async Task RemoveAsync(string id) => await _booksCollection.DeleteOneAsync(x => x.Id == id); }
위의 코드에서 생성자 주입을 통해 DI에서
BookStoreDatabaseSettings
인스턴스가 검색됩니다. 이 방법은appsettings.json
섹션에 추가된 구성 값에 대한 액세스를 제공합니다.다음 강조 표시된 코드를
Program.cs
에 추가합니다.var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>();
위의 코드에서
BooksService
클래스는 사용 클래스에서 생성자 주입을 지원하는 DI로 등록됩니다.BooksService
가MongoClient
에 직접 종속되기 때문에 싱글톤 서비스 수명이 가장 적합합니다. 공식 Mongo 클라이언트 재사용 지침에 따라MongoClient
를 싱글톤 수명으로 DI에 등록해야 합니다.Program.cs
의 맨 위에 다음 코드를 추가하여BooksService
참조를 확인합니다.using BookStoreApi.Services;
BooksService
클래스는 다음 MongoDB.Driver
멤버를 사용하여 데이터베이스에 대해 CRUD 작업을 실행합니다.
MongoClient: 데이터베이스 작업을 실행하기 위한 서버 인스턴스를 읽습니다. 이 클래스의 생성자는 MongoDB 연결 문자열에 제공됩니다.
public BooksService( IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings) { var mongoClient = new MongoClient( bookStoreDatabaseSettings.Value.ConnectionString); var mongoDatabase = mongoClient.GetDatabase( bookStoreDatabaseSettings.Value.DatabaseName); _booksCollection = mongoDatabase.GetCollection<Book>( bookStoreDatabaseSettings.Value.BooksCollectionName); }
IMongoDatabase: 작업을 실행하기 위한 Mongo 데이터베이스를 나타냅니다. 이 자습서에서는 인터페이스의 제네릭 GetCollection<TDocument>(collection) 메서드를 사용하여 특정 컬렉션의 데이터에 액세스합니다. 이 메서드를 호출한 후 컬렉션에 대해 CRUD 작업을 실행합니다.
GetCollection<TDocument>(collection)
메서드 호출에서 다음을 수행합니다.-
collection
은 컬렉션 이름을 나타냅니다. -
TDocument
는 컬렉션에 저장된 CLR 개체 형식을 나타냅니다.
-
GetCollection<TDocument>(collection)
는 컬렉션을 나타내는 MongoCollection 개체를 반환합니다. 이 자습서에서는 컬렉션에 대해 다음 메서드를 호출합니다.
- DeleteOneAsync: 제공된 검색 조건과 일치하는 단일 문서를 삭제합니다.
- Find<TDocument>: 제공된 검색 조건과 일치하는 컬렉션의 모든 문서를 반환합니다.
- InsertOneAsync: 제공된 개체를 컬렉션에 새 문서로 삽입합니다.
- ReplaceOneAsync: 제공된 검색 조건과 일치하는 단일 문서를 제공된 개체로 바꿉니다.
컨트롤러 추가
다음 코드를 사용하여 BooksController
디렉터리에 클래스를 추가합니다.
using BookStoreApi.Models;
using BookStoreApi.Services;
using Microsoft.AspNetCore.Mvc;
namespace BookStoreApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class BooksController : ControllerBase
{
private readonly BooksService _booksService;
public BooksController(BooksService booksService) =>
_booksService = booksService;
[HttpGet]
public async Task<List<Book>> Get() =>
await _booksService.GetAsync();
[HttpGet("{id:length(24)}")]
public async Task<ActionResult<Book>> Get(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
return book;
}
[HttpPost]
public async Task<IActionResult> Post(Book newBook)
{
await _booksService.CreateAsync(newBook);
return CreatedAtAction(nameof(Get), new { id = newBook.Id }, newBook);
}
[HttpPut("{id:length(24)}")]
public async Task<IActionResult> Update(string id, Book updatedBook)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
updatedBook.Id = book.Id;
await _booksService.UpdateAsync(id, updatedBook);
return NoContent();
}
[HttpDelete("{id:length(24)}")]
public async Task<IActionResult> Delete(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
await _booksService.RemoveAsync(id);
return NoContent();
}
}
앞의 웹 API 컨트롤러는 다음과 같습니다.
-
BooksService
클래스를 사용하여 CRUD 작업을 실행합니다. - GET, POST, PUT 및 DELETE HTTP 요청을 지원하는 작업 메서드를 포함합니다.
-
CreatedAtAction 작업 메서드에서
Create
를 호출하여 HTTP 201 응답을 반환합니다. 상태 코드 201은 서버에서 새 리소스를 만드는 HTTP POST 메서드의 표준 응답입니다. 또한CreatedAtAction
는Location
헤더를 응답에 추가합니다.Location
헤더는 새로 만든 책의 URI를 지정합니다.
웹 API 테스트
앱을 빌드하고 실행합니다.
https://localhost:<port>/api/books
로 이동합니다. 여기서<port>
는 앱에 자동으로 할당된 포트 번호이며, 컨트롤러의 매개 변수가 없는Get
작업 메서드를 테스트합니다. 다음과 비슷한 JSON 응답이 표시됩니다.[ { "id": "61a6058e6c43f32854e51f51", "bookName": "Design Patterns", "price": 54.93, "category": "Computers", "author": "Ralph Johnson" }, { "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" } ]
https://localhost:<port>/api/books/{id here}
로 이동하여 컨트롤러의 오버로드된Get
작업 메서드를 테스트합니다. 다음과 비슷한 JSON 응답이 표시됩니다.{ "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" }
JSON serialization 옵션 구성
웹 API 테스트 섹션에서 반환된 JSON 응답에 대해 변경하는 두 개의 세부 정보가 있습니다.
- 속성 이름의 기본 카멜 대소문자 방식은 CLR 객체의 속성 이름에 맞춰 파스칼 대소문자 방식으로 변경해야 합니다.
-
bookName
속성은Name
으로 반환되어야 합니다.
앞의 요구 사항을 충족하기 위해 다음과 같이 변경합니다.
Program.cs
에서 다음 강조 표시된 코드를AddControllers
메서드 호출에 연결합니다.var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>(); builder.Services.AddControllers() .AddJsonOptions( options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
이전 변경으로 웹 API의 직렬화된 JSON 응답에서 속성 이름은 CLR 개체 형식의 해당 속성 이름과 일치합니다. 예를 들어
Book
클래스의Author
속성은Author
대신author
로 직렬화됩니다.Models/Book.cs
에서BookName
속성에[JsonPropertyName]
특성을 주석으로 답니다.[BsonElement("Name")] [JsonPropertyName("Name")] public string BookName { get; set; } = null!;
[JsonPropertyName]
의Name
특성 값은 웹 API의 직렬화된 JSON 응답의 속성 이름을 나타냅니다.Models/Book.cs
의 맨 위에 다음 코드를 추가하여[JsonProperty]
특성 참조를 확인합니다.using System.Text.Json.Serialization;
웹 API 테스트 섹션에 정의된 단계를 반복합니다. JSON 속성 이름의 차이를 확인합니다.
웹 API에 인증 지원 추가
ASP.NET Core Identity는 ASP.NET Core 웹앱에 UI(사용자 인터페이스) 로그인 기능을 추가합니다. 웹 API 및 SPA를 보호하려면 다음 중 하나를 사용합니다.
- Microsoft Entra ID
- Azure Active Directory B2C(Azure AD B2C)
- Duende Identity 서버
Duende Identity Server는 ASP.NET Core용 OpenID Connect 및 OAuth 2.0 프레임워크입니다. Duende Identity Server에서는 다음과 같은 보안 기능을 사용할 수 있습니다.
- AaaS(Authentication as a Service)
- 여러 응용 프로그램 유형에 대한 SSO(Single Sign-On/Off)
- API에 대한 액세스 제어
- 페더레이션 게이트웨이
중요한
Duende Software에서 Duende Identity 서버의 프로덕션 사용에 대한 라이선스 요금 지불을 요구할 수 있습니다. 자세한 내용은 .NET 5의 ASP.NET Core에서 .NET 6으로 마이그레이션을 참조하세요.
자세한 내용은 Duende Identity Server 설명서(Duende Software 웹 사이트)를 참조하세요.
추가 리소스
이 자습서에서는 MongoDB NoSQL 데이터베이스에 대해 CRUD(만들기, 읽기, 업데이트 및 삭제) 작업을 실행하는 웹 API를 만듭니다.
이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.
- MongoDB 구성
- MongoDB 데이터베이스 만들기
- MongoDB 컬렉션 및 스키마 정의
- 웹 API에서 MongoDB CRUD 작업 수행
- JSON 직렬화 사용자 지정
필수 조건
ASP.NET 및 웹 개발 워크로드가 있는 Visual Studio 2022
MongoDB 구성
개발 머신의 어디에서나 MongoDB 및 Mongo DB Shell 액세스를 사용하도록 설정합니다.
Windows에서 MongoDB는 기본적으로 C:\Program Files\MongoDB에 설치됩니다. C:\Program Files\MongoDB\Server\<version_number>\bin을
PATH
환경 변수에 추가합니다.MongoDB 셸을 다운로드하고 추출할 디렉터리를 선택합니다. 환경 변수에 대한
mongosh.exe
PATH
결과 경로를 추가합니다.데이터를 저장하기 위해 개발 머신에서 디렉터리를 선택합니다. 예를 들어 Windows의 경우 C:\BooksData 등을 선택합니다. 디렉터리가 없을 경우 새로 만듭니다. mongo 셸은 새 디렉터리를 만들지 않습니다.
OS 명령 셸(MongoDB 셸 아님)에서 다음 명령을 사용하여 기본 포트 27017에서 MongoDB에 연결합니다. 이전 단계에서 선택한 디렉터리로
<data_directory_path>
을(를) 바꾸십시오.mongod --dbpath <data_directory_path>
다음 단계에서 이전에 설치된 MongoDB Shell을 사용하여 데이터베이스 및 컬렉션을 만들고 문서를 저장합니다. MongoDB Shell 명령에 대한 자세한 내용은 mongosh
를 참조하세요.
MongoDB 명령 셸 인스턴스를 시작
mongosh.exe
하거나 명령 셸에서 다음 명령을 실행하여 엽니다.mongosh
명령 셸에서 다음을 실행하여 기본 테스트 데이터베이스에 연결합니다.
use BookStore
아직 존재하지 않는 경우 BookStore라는 데이터베이스가 생성됩니다. 데이터베이스가 있는 경우 트랜잭션을 위해 해당 연결이 열립니다.
다음 명령을 사용하여
Books
컬렉션을 만듭니다.db.createCollection('Books')
다음 결과가 표시됩니다.
{ "ok" : 1 }
다음 명령을 사용하여
Books
컬렉션에 대한 스키마를 정의하고 두 개의 문서를 삽입합니다.db.Books.insertMany([{ "Name": "Design Patterns", "Price": 54.93, "Category": "Computers", "Author": "Ralph Johnson" }, { "Name": "Clean Code", "Price": 43.15, "Category": "Computers","Author": "Robert C. Martin" }])
다음과 비슷한 결과가 표시됩니다.
{ "acknowledged" : true, "insertedIds" : [ ObjectId("61a6058e6c43f32854e51f51"), ObjectId("61a6058e6c43f32854e51f52") ] }
참고
ObjectId
이전 결과에 표시된 내용이 명령 셸에 표시된 것과 일치하지 않습니다.다음 명령을 사용하여 데이터베이스의 문서를 봅니다.
db.Books.find().pretty()
다음과 비슷한 결과가 표시됩니다.
{ "_id" : ObjectId("61a6058e6c43f32854e51f51"), "Name" : "Design Patterns", "Price" : 54.93, "Category" : "Computers", "Author" : "Ralph Johnson" } { "_id" : ObjectId("61a6058e6c43f32854e51f52"), "Name" : "Clean Code", "Price" : 43.15, "Category" : "Computers", "Author" : "Robert C. Martin" }
스키마가 각 문서에 대해 자동 생성된
_id
형식의ObjectId
속성을 추가합니다.
ASP.NET Core 웹 API 프로젝트 만들기
파일>새로 만들기>프로젝트로 이동합니다.
ASP.NET Core Web API 프로젝트 형식을 선택하고 다음을 선택합니다.
프로젝트 이름을 BookStoreApi로 지정하고 다음을 선택합니다.
.NET 7.0(표준 용어 지원) 프레임워크를 선택하고 만들기를 선택합니다.
도구 메뉴에서 NuGet 패키지 관리자>패키지 관리자 콘솔을 선택합니다.
패키지 관리자 콘솔 창에서 프로젝트 루트로 이동합니다. 다음 명령을 실행하여 MongoDB용 .NET 드라이버를 설치합니다.
Install-Package MongoDB.Driver
엔터티 모델 추가
프로젝트 루트에 Models 디렉터리를 추가합니다.
다음 코드를 사용하여
Book
디렉터리에 클래스를 추가합니다.using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; namespace BookStoreApi.Models; public class Book { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } [BsonElement("Name")] public string BookName { get; set; } = null!; public decimal Price { get; set; } public string Category { get; set; } = null!; public string Author { get; set; } = null!; }
앞의 클래스에서
Id
속성은- CLR(공용 언어 런타임) 개체를 MongoDB 컬렉션에 매핑하는 데 필요합니다.
- 이 속성을 문서의 기본 키로 설정하기 위해
[BsonId]
로 주석이 추가됩니다. -
[BsonRepresentation(BsonType.ObjectId)]
의 주석은 매개 변수를string
구조체 대신 형식으로 전달할 수 있도록 추가됩니다. Mongo는string
에서ObjectId
로 변환을 처리합니다.
BookName
속성에[BsonElement]
특성이 주석으로 추가되었습니다.Name
의 특성 값은 MongoDB 컬렉션의 속성 이름을 나타냅니다.
구성 모델 추가
다음 데이터베이스 구성 값을
appsettings.json
에 추가합니다.{ "BookStoreDatabase": { "ConnectionString": "mongodb://localhost:27017", "DatabaseName": "BookStore", "BooksCollectionName": "Books" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
다음 코드를 사용하여
BookStoreDatabaseSettings
디렉터리에 클래스를 추가합니다.namespace BookStoreApi.Models; public class BookStoreDatabaseSettings { public string ConnectionString { get; set; } = null!; public string DatabaseName { get; set; } = null!; public string BooksCollectionName { get; set; } = null!; }
위의
BookStoreDatabaseSettings
클래스는appsettings.json
파일의BookStoreDatabase
속성 값을 저장하는 데 사용됩니다. JSON 및 C# 속성 이름은 매핑 프로세스를 용이하게 하기 위해 동일한 이름이 지정됩니다.다음 강조 표시된 코드를
Program.cs
에 추가합니다.var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase"));
위의 코드에서
appsettings.json
파일의BookStoreDatabase
섹션이 바인딩되는 구성 인스턴스가 DI(종속성 주입) 컨테이너에 등록됩니다. 예를 들어BookStoreDatabaseSettings
개체의ConnectionString
속성은BookStoreDatabase:ConnectionString
의appsettings.json
속성으로 채워집니다.Program.cs
의 맨 위에 다음 코드를 추가하여BookStoreDatabaseSettings
참조를 확인합니다.using BookStoreApi.Models;
CRUD 작업 서비스 추가
프로젝트 루트에 Services 디렉터리를 추가합니다.
다음 코드를 사용하여
BooksService
디렉터리에 클래스를 추가합니다.using BookStoreApi.Models; using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BookStoreApi.Services; public class BooksService { private readonly IMongoCollection<Book> _booksCollection; public BooksService( IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings) { var mongoClient = new MongoClient( bookStoreDatabaseSettings.Value.ConnectionString); var mongoDatabase = mongoClient.GetDatabase( bookStoreDatabaseSettings.Value.DatabaseName); _booksCollection = mongoDatabase.GetCollection<Book>( bookStoreDatabaseSettings.Value.BooksCollectionName); } public async Task<List<Book>> GetAsync() => await _booksCollection.Find(_ => true).ToListAsync(); public async Task<Book?> GetAsync(string id) => await _booksCollection.Find(x => x.Id == id).FirstOrDefaultAsync(); public async Task CreateAsync(Book newBook) => await _booksCollection.InsertOneAsync(newBook); public async Task UpdateAsync(string id, Book updatedBook) => await _booksCollection.ReplaceOneAsync(x => x.Id == id, updatedBook); public async Task RemoveAsync(string id) => await _booksCollection.DeleteOneAsync(x => x.Id == id); }
위의 코드에서 생성자 주입을 통해 DI에서
BookStoreDatabaseSettings
인스턴스가 검색됩니다. 이 방법은appsettings.json
섹션에 추가된 구성 값에 대한 액세스를 제공합니다.다음 강조 표시된 코드를
Program.cs
에 추가합니다.var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>();
위의 코드에서
BooksService
클래스는 사용 클래스에서 생성자 주입을 지원하는 DI로 등록됩니다.BooksService
가MongoClient
에 직접 종속되기 때문에 싱글톤 서비스 수명이 가장 적합합니다. 공식 Mongo 클라이언트 재사용 지침에 따라MongoClient
를 싱글톤 수명으로 DI에 등록해야 합니다.Program.cs
의 맨 위에 다음 코드를 추가하여BooksService
참조를 확인합니다.using BookStoreApi.Services;
BooksService
클래스는 다음 MongoDB.Driver
멤버를 사용하여 데이터베이스에 대해 CRUD 작업을 실행합니다.
MongoClient: 데이터베이스 작업을 실행하기 위한 서버 인스턴스를 읽습니다. 이 클래스의 생성자에 MongoDB 연결 문자열이 제공됩니다.
public BooksService( IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings) { var mongoClient = new MongoClient( bookStoreDatabaseSettings.Value.ConnectionString); var mongoDatabase = mongoClient.GetDatabase( bookStoreDatabaseSettings.Value.DatabaseName); _booksCollection = mongoDatabase.GetCollection<Book>( bookStoreDatabaseSettings.Value.BooksCollectionName); }
IMongoDatabase: 작업을 실행하기 위한 Mongo 데이터베이스를 나타냅니다. 이 자습서에서는 인터페이스의 제네릭 GetCollection<TDocument>(collection) 메서드를 사용하여 특정 컬렉션의 데이터에 액세스합니다. 이 메서드를 호출한 후 컬렉션에 대해 CRUD 작업을 실행합니다.
GetCollection<TDocument>(collection)
메서드 호출에서 다음을 수행합니다.-
collection
은 컬렉션 이름을 나타냅니다. -
TDocument
는 컬렉션에 저장된 CLR 개체 형식을 나타냅니다.
-
GetCollection<TDocument>(collection)
는 컬렉션을 나타내는 MongoCollection 개체를 반환합니다. 이 자습서에서는 컬렉션에 대해 다음 메서드를 호출합니다.
- DeleteOneAsync: 제공된 검색 조건과 일치하는 단일 문서를 삭제합니다.
- Find<TDocument>: 제공된 검색 조건과 일치하는 컬렉션의 모든 문서를 반환합니다.
- InsertOneAsync: 제공된 개체를 컬렉션에 새 문서로 삽입합니다.
- ReplaceOneAsync: 제공된 검색 조건과 일치하는 단일 문서를 제공된 개체로 바꿉니다.
컨트롤러 추가
다음 코드를 사용하여 BooksController
디렉터리에 클래스를 추가합니다.
using BookStoreApi.Models;
using BookStoreApi.Services;
using Microsoft.AspNetCore.Mvc;
namespace BookStoreApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class BooksController : ControllerBase
{
private readonly BooksService _booksService;
public BooksController(BooksService booksService) =>
_booksService = booksService;
[HttpGet]
public async Task<List<Book>> Get() =>
await _booksService.GetAsync();
[HttpGet("{id:length(24)}")]
public async Task<ActionResult<Book>> Get(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
return book;
}
[HttpPost]
public async Task<IActionResult> Post(Book newBook)
{
await _booksService.CreateAsync(newBook);
return CreatedAtAction(nameof(Get), new { id = newBook.Id }, newBook);
}
[HttpPut("{id:length(24)}")]
public async Task<IActionResult> Update(string id, Book updatedBook)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
updatedBook.Id = book.Id;
await _booksService.UpdateAsync(id, updatedBook);
return NoContent();
}
[HttpDelete("{id:length(24)}")]
public async Task<IActionResult> Delete(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
await _booksService.RemoveAsync(id);
return NoContent();
}
}
앞의 웹 API 컨트롤러는 다음과 같습니다.
-
BooksService
클래스를 사용하여 CRUD 작업을 실행합니다. - GET, POST, PUT 및 DELETE HTTP 요청을 지원하는 작업 메서드를 포함합니다.
-
CreatedAtAction 작업 메서드에서
Create
를 호출하여 HTTP 201 응답을 반환합니다. 상태 코드 201은 서버에서 새 리소스를 만드는 HTTP POST 메서드의 표준 응답입니다. 또한CreatedAtAction
는Location
헤더를 응답에 추가합니다.Location
헤더는 새로 만든 책의 URI를 지정합니다.
웹 API 테스트
앱을 빌드하고 실행합니다.
https://localhost:<port>/api/books
로 이동합니다. 여기서<port>
는 앱에 자동으로 할당된 포트 번호이며, 컨트롤러의 매개 변수가 없는Get
작업 메서드를 테스트합니다. 다음과 비슷한 JSON 응답이 표시됩니다.[ { "id": "61a6058e6c43f32854e51f51", "bookName": "Design Patterns", "price": 54.93, "category": "Computers", "author": "Ralph Johnson" }, { "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" } ]
https://localhost:<port>/api/books/{id here}
로 이동하여 컨트롤러의 오버로드된Get
작업 메서드를 테스트합니다. 다음과 비슷한 JSON 응답이 표시됩니다.{ "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" }
JSON serialization 옵션 구성
웹 API 테스트 섹션에서 반환된 JSON 응답에 대해 변경하는 두 개의 세부 정보가 있습니다.
- 속성 이름의 기본 카멜 대소문자 방식은 CLR 객체의 속성 이름에 맞춰 파스칼 대소문자 방식으로 변경해야 합니다.
-
bookName
속성은Name
으로 반환되어야 합니다.
앞의 요구 사항을 충족하기 위해 다음과 같이 변경합니다.
Program.cs
에서 다음 강조 표시된 코드를AddControllers
메서드 호출에 연결합니다.var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>(); builder.Services.AddControllers() .AddJsonOptions( options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
이전 변경으로 웹 API의 직렬화된 JSON 응답에서 속성 이름은 CLR 개체 형식의 해당 속성 이름과 일치합니다. 예를 들어
Book
클래스의Author
속성은Author
대신author
로 직렬화됩니다.Models/Book.cs
에서BookName
속성에[JsonPropertyName]
특성을 주석으로 답니다.[BsonElement("Name")] [JsonPropertyName("Name")] public string BookName { get; set; } = null!;
[JsonPropertyName]
의Name
특성 값은 웹 API의 직렬화된 JSON 응답의 속성 이름을 나타냅니다.Models/Book.cs
의 맨 위에 다음 코드를 추가하여[JsonProperty]
특성 참조를 확인합니다.using System.Text.Json.Serialization;
웹 API 테스트 섹션에 정의된 단계를 반복합니다. JSON 속성 이름의 차이를 확인합니다.
웹 API에 인증 지원 추가
ASP.NET Core Identity는 ASP.NET Core 웹앱에 UI(사용자 인터페이스) 로그인 기능을 추가합니다. 웹 API 및 SPA를 보호하려면 다음 중 하나를 사용합니다.
- Microsoft Entra ID
- Azure Active Directory B2C(Azure AD B2C)
- Duende Identity 서버
Duende Identity Server는 ASP.NET Core용 OpenID Connect 및 OAuth 2.0 프레임워크입니다. Duende Identity Server에서는 다음과 같은 보안 기능을 사용할 수 있습니다.
- AaaS(Authentication as a Service)
- 여러 응용 프로그램 유형에 대한 SSO(Single Sign-On/Off)
- API에 대한 액세스 제어
- 페더레이션 게이트웨이
중요한
Duende Software에서 Duende Identity 서버의 프로덕션 사용에 대한 라이선스 요금 지불을 요구할 수 있습니다. 자세한 내용은 .NET 5의 ASP.NET Core에서 .NET 6으로 마이그레이션을 참조하세요.
자세한 내용은 Duende Identity Server 설명서(Duende Software 웹 사이트)를 참조하세요.
추가 리소스
이 자습서에서는 MongoDB NoSQL 데이터베이스에 대해 CRUD(만들기, 읽기, 업데이트 및 삭제) 작업을 실행하는 웹 API를 만듭니다.
이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.
- MongoDB 구성
- MongoDB 데이터베이스 만들기
- MongoDB 컬렉션 및 스키마 정의
- 웹 API에서 MongoDB CRUD 작업 수행
- JSON 직렬화 사용자 지정
필수 조건
- ASP.NET 및 웹 개발 워크로드가 있는 Visual Studio 2022
- .NET 6 SDK
MongoDB 구성
개발 머신의 어디에서나 MongoDB 및 Mongo DB Shell 액세스를 사용하도록 설정합니다.
Windows에서 MongoDB는 기본적으로 C:\Program Files\MongoDB에 설치됩니다. C:\Program Files\MongoDB\Server\<version_number>\bin을
PATH
환경 변수에 추가합니다.MongoDB 셸을 다운로드하고 추출할 디렉터리를 선택합니다. 환경 변수에 대한
mongosh.exe
PATH
결과 경로를 추가합니다.데이터를 저장하기 위해 개발 머신에서 디렉터리를 선택합니다. 예를 들어 Windows의 경우 C:\BooksData 등을 선택합니다. 디렉터리가 없을 경우 새로 만듭니다. mongo 셸은 새 디렉터리를 만들지 않습니다.
OS 명령 셸(MongoDB 셸 아님)에서 다음 명령을 사용하여 기본 포트 27017에서 MongoDB에 연결합니다. 이전 단계에서 선택한 디렉터리로
<data_directory_path>
을(를) 바꾸십시오.mongod --dbpath <data_directory_path>
다음 단계에서 이전에 설치된 MongoDB Shell을 사용하여 데이터베이스 및 컬렉션을 만들고 문서를 저장합니다. MongoDB Shell 명령에 대한 자세한 내용은 mongosh
를 참조하세요.
MongoDB 명령 셸 인스턴스를 시작
mongosh.exe
하거나 명령 셸에서 다음 명령을 실행하여 엽니다.mongosh
명령 셸에서 다음을 실행하여 기본 테스트 데이터베이스에 연결합니다.
use BookStore
아직 존재하지 않는 경우 BookStore라는 데이터베이스가 생성됩니다. 데이터베이스가 있는 경우 트랜잭션을 위해 해당 연결이 열립니다.
다음 명령을 사용하여
Books
컬렉션을 만듭니다.db.createCollection('Books')
다음 결과가 표시됩니다.
{ "ok" : 1 }
다음 명령을 사용하여
Books
컬렉션에 대한 스키마를 정의하고 두 개의 문서를 삽입합니다.db.Books.insertMany([{ "Name": "Design Patterns", "Price": 54.93, "Category": "Computers", "Author": "Ralph Johnson" }, { "Name": "Clean Code", "Price": 43.15, "Category": "Computers","Author": "Robert C. Martin" }])
다음과 비슷한 결과가 표시됩니다.
{ "acknowledged" : true, "insertedIds" : [ ObjectId("61a6058e6c43f32854e51f51"), ObjectId("61a6058e6c43f32854e51f52") ] }
참고
ObjectId
이전 결과에 표시된 내용이 명령 셸에 표시된 것과 일치하지 않습니다.다음 명령을 사용하여 데이터베이스의 문서를 봅니다.
db.Books.find().pretty()
다음과 비슷한 결과가 표시됩니다.
{ "_id" : ObjectId("61a6058e6c43f32854e51f51"), "Name" : "Design Patterns", "Price" : 54.93, "Category" : "Computers", "Author" : "Ralph Johnson" } { "_id" : ObjectId("61a6058e6c43f32854e51f52"), "Name" : "Clean Code", "Price" : 43.15, "Category" : "Computers", "Author" : "Robert C. Martin" }
스키마가 각 문서에 대해 자동 생성된
_id
형식의ObjectId
속성을 추가합니다.
ASP.NET Core 웹 API 프로젝트 만들기
파일>새로 만들기>프로젝트로 이동합니다.
ASP.NET Core Web API 프로젝트 형식을 선택하고 다음을 선택합니다.
프로젝트 이름을 BookStoreApi로 지정하고 다음을 선택합니다.
.NET 6.0(장기 지원) 프레임워크를 선택하고 만들기를 선택합니다.
패키지 관리자 콘솔 창에서 프로젝트 루트로 이동합니다. 다음 명령을 실행하여 MongoDB용 .NET 드라이버를 설치합니다.
Install-Package MongoDB.Driver
엔터티 모델 추가
프로젝트 루트에 Models 디렉터리를 추가합니다.
다음 코드를 사용하여
Book
디렉터리에 클래스를 추가합니다.using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; namespace BookStoreApi.Models; public class Book { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } [BsonElement("Name")] public string BookName { get; set; } = null!; public decimal Price { get; set; } public string Category { get; set; } = null!; public string Author { get; set; } = null!; }
앞의 클래스에서
Id
속성은- CLR(공용 언어 런타임) 개체를 MongoDB 컬렉션에 매핑하는 데 필요합니다.
- 이 속성을 문서의 기본 키로 설정하기 위해
[BsonId]
로 주석이 추가됩니다. -
[BsonRepresentation(BsonType.ObjectId)]
의 주석은 매개 변수를string
구조체 대신 형식으로 전달할 수 있도록 추가됩니다. Mongo는string
에서ObjectId
로 변환을 처리합니다.
BookName
속성에[BsonElement]
특성이 주석으로 추가되었습니다.Name
의 특성 값은 MongoDB 컬렉션의 속성 이름을 나타냅니다.
구성 모델 추가
다음 데이터베이스 구성 값을
appsettings.json
에 추가합니다.{ "BookStoreDatabase": { "ConnectionString": "mongodb://localhost:27017", "DatabaseName": "BookStore", "BooksCollectionName": "Books" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
다음 코드를 사용하여
BookStoreDatabaseSettings
디렉터리에 클래스를 추가합니다.namespace BookStoreApi.Models; public class BookStoreDatabaseSettings { public string ConnectionString { get; set; } = null!; public string DatabaseName { get; set; } = null!; public string BooksCollectionName { get; set; } = null!; }
위의
BookStoreDatabaseSettings
클래스는appsettings.json
파일의BookStoreDatabase
속성 값을 저장하는 데 사용됩니다. JSON 및 C# 속성 이름은 매핑 프로세스를 용이하게 하기 위해 동일한 이름이 지정됩니다.다음 강조 표시된 코드를
Program.cs
에 추가합니다.var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase"));
위의 코드에서
appsettings.json
파일의BookStoreDatabase
섹션이 바인딩되는 구성 인스턴스가 DI(종속성 주입) 컨테이너에 등록됩니다. 예를 들어BookStoreDatabaseSettings
개체의ConnectionString
속성은BookStoreDatabase:ConnectionString
의appsettings.json
속성으로 채워집니다.Program.cs
의 맨 위에 다음 코드를 추가하여BookStoreDatabaseSettings
참조를 확인합니다.using BookStoreApi.Models;
CRUD 작업 서비스 추가
프로젝트 루트에 Services 디렉터리를 추가합니다.
다음 코드를 사용하여
BooksService
디렉터리에 클래스를 추가합니다.using BookStoreApi.Models; using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BookStoreApi.Services; public class BooksService { private readonly IMongoCollection<Book> _booksCollection; public BooksService( IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings) { var mongoClient = new MongoClient( bookStoreDatabaseSettings.Value.ConnectionString); var mongoDatabase = mongoClient.GetDatabase( bookStoreDatabaseSettings.Value.DatabaseName); _booksCollection = mongoDatabase.GetCollection<Book>( bookStoreDatabaseSettings.Value.BooksCollectionName); } public async Task<List<Book>> GetAsync() => await _booksCollection.Find(_ => true).ToListAsync(); public async Task<Book?> GetAsync(string id) => await _booksCollection.Find(x => x.Id == id).FirstOrDefaultAsync(); public async Task CreateAsync(Book newBook) => await _booksCollection.InsertOneAsync(newBook); public async Task UpdateAsync(string id, Book updatedBook) => await _booksCollection.ReplaceOneAsync(x => x.Id == id, updatedBook); public async Task RemoveAsync(string id) => await _booksCollection.DeleteOneAsync(x => x.Id == id); }
위의 코드에서 생성자 주입을 통해 DI에서
BookStoreDatabaseSettings
인스턴스가 검색됩니다. 이 방법은appsettings.json
섹션에 추가된 구성 값에 대한 액세스를 제공합니다.다음 강조 표시된 코드를
Program.cs
에 추가합니다.var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>();
위의 코드에서
BooksService
클래스는 사용 클래스에서 생성자 주입을 지원하는 DI로 등록됩니다.BooksService
가MongoClient
에 직접 종속되기 때문에 싱글톤 서비스 수명이 가장 적합합니다. 공식 Mongo 클라이언트 재사용 지침에 따라MongoClient
를 싱글톤 수명으로 DI에 등록해야 합니다.Program.cs
의 맨 위에 다음 코드를 추가하여BooksService
참조를 확인합니다.using BookStoreApi.Services;
BooksService
클래스는 다음 MongoDB.Driver
멤버를 사용하여 데이터베이스에 대해 CRUD 작업을 실행합니다.
MongoClient: 데이터베이스 작업을 실행하기 위한 서버 인스턴스를 읽습니다. 이 클래스의 생성자에 MongoDB 연결 문자열이 제공됩니다.
public BooksService( IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings) { var mongoClient = new MongoClient( bookStoreDatabaseSettings.Value.ConnectionString); var mongoDatabase = mongoClient.GetDatabase( bookStoreDatabaseSettings.Value.DatabaseName); _booksCollection = mongoDatabase.GetCollection<Book>( bookStoreDatabaseSettings.Value.BooksCollectionName); }
IMongoDatabase: 작업을 실행하기 위한 Mongo 데이터베이스를 나타냅니다. 이 자습서에서는 인터페이스의 제네릭 GetCollection<TDocument>(collection) 메서드를 사용하여 특정 컬렉션의 데이터에 액세스합니다. 이 메서드를 호출한 후 컬렉션에 대해 CRUD 작업을 실행합니다.
GetCollection<TDocument>(collection)
메서드 호출에서 다음을 수행합니다.-
collection
은 컬렉션 이름을 나타냅니다. -
TDocument
는 컬렉션에 저장된 CLR 개체 형식을 나타냅니다.
-
GetCollection<TDocument>(collection)
는 컬렉션을 나타내는 MongoCollection 개체를 반환합니다. 이 자습서에서는 컬렉션에 대해 다음 메서드를 호출합니다.
- DeleteOneAsync: 제공된 검색 조건과 일치하는 단일 문서를 삭제합니다.
- Find<TDocument>: 제공된 검색 조건과 일치하는 컬렉션의 모든 문서를 반환합니다.
- InsertOneAsync: 제공된 개체를 컬렉션에 새 문서로 삽입합니다.
- ReplaceOneAsync: 제공된 검색 조건과 일치하는 단일 문서를 제공된 개체로 바꿉니다.
컨트롤러 추가
다음 코드를 사용하여 BooksController
디렉터리에 클래스를 추가합니다.
using BookStoreApi.Models;
using BookStoreApi.Services;
using Microsoft.AspNetCore.Mvc;
namespace BookStoreApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class BooksController : ControllerBase
{
private readonly BooksService _booksService;
public BooksController(BooksService booksService) =>
_booksService = booksService;
[HttpGet]
public async Task<List<Book>> Get() =>
await _booksService.GetAsync();
[HttpGet("{id:length(24)}")]
public async Task<ActionResult<Book>> Get(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
return book;
}
[HttpPost]
public async Task<IActionResult> Post(Book newBook)
{
await _booksService.CreateAsync(newBook);
return CreatedAtAction(nameof(Get), new { id = newBook.Id }, newBook);
}
[HttpPut("{id:length(24)}")]
public async Task<IActionResult> Update(string id, Book updatedBook)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
updatedBook.Id = book.Id;
await _booksService.UpdateAsync(id, updatedBook);
return NoContent();
}
[HttpDelete("{id:length(24)}")]
public async Task<IActionResult> Delete(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
await _booksService.RemoveAsync(id);
return NoContent();
}
}
앞의 웹 API 컨트롤러는 다음과 같습니다.
-
BooksService
클래스를 사용하여 CRUD 작업을 실행합니다. - GET, POST, PUT 및 DELETE HTTP 요청을 지원하는 작업 메서드를 포함합니다.
-
CreatedAtAction 작업 메서드에서
Create
를 호출하여 HTTP 201 응답을 반환합니다. 상태 코드 201은 서버에서 새 리소스를 만드는 HTTP POST 메서드의 표준 응답입니다. 또한CreatedAtAction
는Location
헤더를 응답에 추가합니다.Location
헤더는 새로 만든 책의 URI를 지정합니다.
웹 API 테스트
앱을 빌드하고 실행합니다.
https://localhost:<port>/api/books
로 이동합니다. 여기서<port>
는 앱에 자동으로 할당된 포트 번호이며, 컨트롤러의 매개 변수가 없는Get
작업 메서드를 테스트합니다. 다음과 비슷한 JSON 응답이 표시됩니다.[ { "id": "61a6058e6c43f32854e51f51", "bookName": "Design Patterns", "price": 54.93, "category": "Computers", "author": "Ralph Johnson" }, { "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" } ]
https://localhost:<port>/api/books/{id here}
로 이동하여 컨트롤러의 오버로드된Get
작업 메서드를 테스트합니다. 다음과 비슷한 JSON 응답이 표시됩니다.{ "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" }
JSON serialization 옵션 구성
웹 API 테스트 섹션에서 반환된 JSON 응답에 대해 변경하는 두 개의 세부 정보가 있습니다.
- 속성 이름의 기본 카멜 대소문자 방식은 CLR 객체의 속성 이름에 맞춰 파스칼 대소문자 방식으로 변경해야 합니다.
-
bookName
속성은Name
으로 반환되어야 합니다.
앞의 요구 사항을 충족하기 위해 다음과 같이 변경합니다.
Program.cs
에서 다음 강조 표시된 코드를AddControllers
메서드 호출에 연결합니다.var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>(); builder.Services.AddControllers() .AddJsonOptions( options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
이전 변경으로 웹 API의 직렬화된 JSON 응답에서 속성 이름은 CLR 개체 형식의 해당 속성 이름과 일치합니다. 예를 들어
Book
클래스의Author
속성은Author
대신author
로 직렬화됩니다.Models/Book.cs
에서BookName
속성에[JsonPropertyName]
특성을 주석으로 답니다.[BsonElement("Name")] [JsonPropertyName("Name")] public string BookName { get; set; } = null!;
[JsonPropertyName]
의Name
특성 값은 웹 API의 직렬화된 JSON 응답의 속성 이름을 나타냅니다.Models/Book.cs
의 맨 위에 다음 코드를 추가하여[JsonProperty]
특성 참조를 확인합니다.using System.Text.Json.Serialization;
웹 API 테스트 섹션에 정의된 단계를 반복합니다. JSON 속성 이름의 차이를 확인합니다.
웹 API에 인증 지원 추가
ASP.NET Core Identity는 ASP.NET Core 웹앱에 UI(사용자 인터페이스) 로그인 기능을 추가합니다. 웹 API 및 SPA를 보호하려면 다음 중 하나를 사용합니다.
- Microsoft Entra ID
- Azure Active Directory B2C(Azure AD B2C)
- Duende Identity 서버
Duende Identity Server는 ASP.NET Core용 OpenID Connect 및 OAuth 2.0 프레임워크입니다. Duende Identity Server에서는 다음과 같은 보안 기능을 사용할 수 있습니다.
- AaaS(Authentication as a Service)
- 여러 응용 프로그램 유형에 대한 SSO(Single Sign-On/Off)
- API에 대한 액세스 제어
- 페더레이션 게이트웨이
중요한
Duende Software에서 Duende Identity 서버의 프로덕션 사용에 대한 라이선스 요금 지불을 요구할 수 있습니다. 자세한 내용은 .NET 5의 ASP.NET Core에서 .NET 6으로 마이그레이션을 참조하세요.
자세한 내용은 Duende Identity Server 설명서(Duende Software 웹 사이트)를 참조하세요.
추가 리소스
이 자습서에서는 MongoDB NoSQL 데이터베이스에 대해 CRUD(만들기, 읽기, 업데이트 및 삭제) 작업을 실행하는 웹 API를 만듭니다.
이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.
- MongoDB 구성
- MongoDB 데이터베이스 만들기
- MongoDB 컬렉션 및 스키마 정의
- 웹 API에서 MongoDB CRUD 작업 수행
- JSON 직렬화 사용자 지정
필수 조건
- .NET Core SDK 3.0 이상
- ASP.NET 및 웹 개발 워크로드가 있는 Visual Studio 2019
- 몽고DB
MongoDB 구성
Windows를 사용하는 경우 MongoDB는 기본적으로 C:\Program Files\MongoDB에 설치됩니다.
C:\Program Files\MongoDB\Server\<version_number>\bin을 Path
환경 변수에 추가합니다. 이렇게 변경하면 개발 머신의 어디에서나 MongoDB에 액세스할 수 있습니다.
다음 단계에서 mongo 셸을 사용하여 데이터베이스 및 컬렉션을 만들고 문서를 저장합니다. mongo 셸 명령에 대한 자세한 내용은 mongo 셸 작업을 참조하세요.
개발 머신에서 데이터를 저장할 디렉터리를 선택합니다. 예를 들어 Windows의 경우 C:\BooksData 등을 선택합니다. 디렉터리가 없을 경우 새로 만듭니다. mongo 셸은 새 디렉터리를 만들지 않습니다.
명령 셸을 엽니다. 다음 명령을 실행하여 기본 포트 27017에서 MongoDB에 연결합니다.
<data_directory_path>
를 이전 단계에서 선택한 디렉터리로 바꿔야 합니다.mongod --dbpath <data_directory_path>
다른 명령 셸 인스턴스를 엽니다. 다음 명령을 실행하여 기본 테스트 데이터베이스에 연결합니다.
mongo
명령 셸에서 다음 명령을 실행합니다.
use BookstoreDb
아직 존재하지 않는 경우 BookstoreDb라는 데이터베이스가 생성됩니다. 데이터베이스가 있는 경우 트랜잭션을 위해 해당 연결이 열립니다.
다음 명령을 사용하여
Books
컬렉션을 만듭니다.db.createCollection('Books')
다음 결과가 표시됩니다.
{ "ok" : 1 }
다음 명령을 사용하여
Books
컬렉션에 대한 스키마를 정의하고 두 개의 문서를 삽입합니다.db.Books.insertMany([{'Name':'Design Patterns','Price':54.93,'Category':'Computers','Author':'Ralph Johnson'}, {'Name':'Clean Code','Price':43.15,'Category':'Computers','Author':'Robert C. Martin'}])
다음 결과가 표시됩니다.
{ "acknowledged" : true, "insertedIds" : [ ObjectId("5bfd996f7b8e48dc15ff215d"), ObjectId("5bfd996f7b8e48dc15ff215e") ] }
참고
이 문서에 표시된 ID는 이 샘플을 실행할 때의 ID와 일치하지 않습니다.
다음 명령을 사용하여 데이터베이스의 문서를 봅니다.
db.Books.find({}).pretty()
다음 결과가 표시됩니다.
{ "_id" : ObjectId("5bfd996f7b8e48dc15ff215d"), "Name" : "Design Patterns", "Price" : 54.93, "Category" : "Computers", "Author" : "Ralph Johnson" } { "_id" : ObjectId("5bfd996f7b8e48dc15ff215e"), "Name" : "Clean Code", "Price" : 43.15, "Category" : "Computers", "Author" : "Robert C. Martin" }
스키마가 각 문서에 대해 자동 생성된
_id
형식의ObjectId
속성을 추가합니다.
데이터베이스가 준비되었습니다. 이제 ASP.NET Core 웹 API를 만들기 시작할 수 있습니다.
ASP.NET Core 웹 API 프로젝트 만들기
파일>새로 만들기>프로젝트로 이동합니다.
ASP.NET Core 웹 애플리케이션 프로젝트 유형을 선택하고 다음을 선택합니다.
프로젝트 이름을 BooksApi로 지정하고 만들기를 선택합니다.
.NET Core 대상 프레임워크 및 ASP.NET Core 3.0을 선택합니다. API 프로젝트 템플릿을 선택하고 만들기를 선택합니다.
MongoDB용 .NET 드라이버의 안정적인 최신 버전을 확인하려면 NuGet 갤러리: MongoDB.Driver를 방문하세요. 패키지 관리자 콘솔 창에서 프로젝트 루트로 이동합니다. 다음 명령을 실행하여 MongoDB용 .NET 드라이버를 설치합니다.
Install-Package MongoDB.Driver -Version {VERSION}
엔터티 모델 추가
프로젝트 루트에 Models 디렉터리를 추가합니다.
다음 코드를 사용하여
Book
디렉터리에 클래스를 추가합니다.using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; namespace BooksApi.Models { public class Book { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string Id { get; set; } [BsonElement("Name")] public string BookName { get; set; } public decimal Price { get; set; } public string Category { get; set; } public string Author { get; set; } } }
앞의 클래스에서
Id
속성은- CLR(공용 언어 런타임) 개체를 MongoDB 컬렉션에 매핑하는 데 필요합니다.
- 이 속성을 문서의 기본 키로 설정하기 위해
[BsonId]
로 주석이 추가됩니다. -
[BsonRepresentation(BsonType.ObjectId)]
의 주석은 매개 변수를string
구조체 대신 형식으로 전달할 수 있도록 추가됩니다. Mongo는string
에서ObjectId
로 변환을 처리합니다.
BookName
속성에[BsonElement]
특성이 주석으로 추가되었습니다.Name
의 특성 값은 MongoDB 컬렉션의 속성 이름을 나타냅니다.
구성 모델 추가
다음 데이터베이스 구성 값을
appsettings.json
에 추가합니다.{ "BookstoreDatabaseSettings": { "BooksCollectionName": "Books", "ConnectionString": "mongodb://localhost:27017", "DatabaseName": "BookstoreDb" }, "Logging": { "IncludeScopes": false, "Debug": { "LogLevel": { "Default": "Warning" } }, "Console": { "LogLevel": { "Default": "Warning" } } } }
다음 코드를 사용하여
BookstoreDatabaseSettings.cs
Models 디렉터리에 파일을 추가합니다.namespace BooksApi.Models { public class BookstoreDatabaseSettings : IBookstoreDatabaseSettings { public string BooksCollectionName { get; set; } public string ConnectionString { get; set; } public string DatabaseName { get; set; } } public interface IBookstoreDatabaseSettings { string BooksCollectionName { get; set; } string ConnectionString { get; set; } string DatabaseName { get; set; } } }
위의
BookstoreDatabaseSettings
클래스는appsettings.json
파일의BookstoreDatabaseSettings
속성 값을 저장하는 데 사용됩니다. JSON 및 C# 속성 이름은 매핑 프로세스를 용이하게 하기 위해 동일한 이름이 지정됩니다.다음 강조 표시된 코드를
Startup.ConfigureServices
에 추가합니다.public void ConfigureServices(IServiceCollection services) { // requires using Microsoft.Extensions.Options services.Configure<BookstoreDatabaseSettings>( Configuration.GetSection(nameof(BookstoreDatabaseSettings))); services.AddSingleton<IBookstoreDatabaseSettings>(sp => sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value); services.AddControllers(); }
위의 코드에서
-
appsettings.json
파일의BookstoreDatabaseSettings
섹션이 바인딩되는 구성 인스턴스가 DI(종속성 주입) 컨테이너에 등록됩니다. 예를 들어BookstoreDatabaseSettings
개체의ConnectionString
속성은BookstoreDatabaseSettings:ConnectionString
의appsettings.json
속성으로 채워집니다. -
IBookstoreDatabaseSettings
인터페이스는 싱글톤 서비스 수명으로 DI에 등록됩니다. 삽입하면 인터페이스 인스턴스가BookstoreDatabaseSettings
개체로 확인됩니다.
-
Startup.cs
의 맨 위에 다음 코드를 추가하여BookstoreDatabaseSettings
및IBookstoreDatabaseSettings
참조를 확인합니다.using BooksApi.Models;
CRUD 작업 서비스 추가
프로젝트 루트에 Services 디렉터리를 추가합니다.
다음 코드를 사용하여
BookService
디렉터리에 클래스를 추가합니다.using BooksApi.Models; using MongoDB.Driver; using System.Collections.Generic; using System.Linq; namespace BooksApi.Services { public class BookService { private readonly IMongoCollection<Book> _books; public BookService(IBookstoreDatabaseSettings settings) { var client = new MongoClient(settings.ConnectionString); var database = client.GetDatabase(settings.DatabaseName); _books = database.GetCollection<Book>(settings.BooksCollectionName); } public List<Book> Get() => _books.Find(book => true).ToList(); public Book Get(string id) => _books.Find<Book>(book => book.Id == id).FirstOrDefault(); public Book Create(Book book) { _books.InsertOne(book); return book; } public void Update(string id, Book bookIn) => _books.ReplaceOne(book => book.Id == id, bookIn); public void Remove(Book bookIn) => _books.DeleteOne(book => book.Id == bookIn.Id); public void Remove(string id) => _books.DeleteOne(book => book.Id == id); } }
위의 코드에서 생성자 주입을 통해 DI에서
IBookstoreDatabaseSettings
인스턴스가 검색됩니다. 이 방법은appsettings.json
섹션에 추가된 구성 값에 대한 액세스를 제공합니다.다음 강조 표시된 코드를
Startup.ConfigureServices
에 추가합니다.public void ConfigureServices(IServiceCollection services) { services.Configure<BookstoreDatabaseSettings>( Configuration.GetSection(nameof(BookstoreDatabaseSettings))); services.AddSingleton<IBookstoreDatabaseSettings>(sp => sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value); services.AddSingleton<BookService>(); services.AddControllers(); }
위의 코드에서
BookService
클래스는 사용 클래스에서 생성자 주입을 지원하는 DI로 등록됩니다.BookService
가MongoClient
에 직접 종속되기 때문에 싱글톤 서비스 수명이 가장 적합합니다. 공식 Mongo 클라이언트 재사용 지침에 따라MongoClient
를 싱글톤 수명으로 DI에 등록해야 합니다.Startup.cs
의 맨 위에 다음 코드를 추가하여BookService
참조를 확인합니다.using BooksApi.Services;
BookService
클래스는 다음 MongoDB.Driver
멤버를 사용하여 데이터베이스에 대해 CRUD 작업을 실행합니다.
MongoClient: 데이터베이스 작업을 실행하기 위한 서버 인스턴스를 읽습니다. 이 클래스의 생성자에 MongoDB 연결 문자열이 제공됩니다.
public BookService(IBookstoreDatabaseSettings settings) { var client = new MongoClient(settings.ConnectionString); var database = client.GetDatabase(settings.DatabaseName); _books = database.GetCollection<Book>(settings.BooksCollectionName); }
IMongoDatabase: 작업을 실행하기 위한 Mongo 데이터베이스를 나타냅니다. 이 자습서에서는 인터페이스의 제네릭 GetCollection<TDocument>(collection) 메서드를 사용하여 특정 컬렉션의 데이터에 액세스합니다. 이 메서드를 호출한 후 컬렉션에 대해 CRUD 작업을 실행합니다.
GetCollection<TDocument>(collection)
메서드 호출에서 다음을 수행합니다.-
collection
은 컬렉션 이름을 나타냅니다. -
TDocument
는 컬렉션에 저장된 CLR 개체 형식을 나타냅니다.
-
GetCollection<TDocument>(collection)
는 컬렉션을 나타내는 MongoCollection 개체를 반환합니다. 이 자습서에서는 컬렉션에 대해 다음 메서드를 호출합니다.
- DeleteOne: 제공된 검색 조건과 일치하는 단일 문서를 삭제합니다.
- Find<TDocument>: 제공된 검색 조건과 일치하는 컬렉션의 모든 문서를 반환합니다.
- InsertOne: 제공된 개체를 컬렉션에 새 문서로 삽입합니다.
- ReplaceOne: 제공된 검색 조건과 일치하는 단일 문서를 제공된 개체로 바꿉니다.
컨트롤러 추가
다음 코드를 사용하여 BooksController
디렉터리에 클래스를 추가합니다.
using BooksApi.Models;
using BooksApi.Services;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
namespace BooksApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class BooksController : ControllerBase
{
private readonly BookService _bookService;
public BooksController(BookService bookService)
{
_bookService = bookService;
}
[HttpGet]
public ActionResult<List<Book>> Get() =>
_bookService.Get();
[HttpGet("{id:length(24)}", Name = "GetBook")]
public ActionResult<Book> Get(string id)
{
var book = _bookService.Get(id);
if (book == null)
{
return NotFound();
}
return book;
}
[HttpPost]
public ActionResult<Book> Create(Book book)
{
_bookService.Create(book);
return CreatedAtRoute("GetBook", new { id = book.Id.ToString() }, book);
}
[HttpPut("{id:length(24)}")]
public IActionResult Update(string id, Book bookIn)
{
var book = _bookService.Get(id);
if (book == null)
{
return NotFound();
}
_bookService.Update(id, bookIn);
return NoContent();
}
[HttpDelete("{id:length(24)}")]
public IActionResult Delete(string id)
{
var book = _bookService.Get(id);
if (book == null)
{
return NotFound();
}
_bookService.Remove(id);
return NoContent();
}
}
}
앞의 웹 API 컨트롤러는 다음과 같습니다.
-
BookService
클래스를 사용하여 CRUD 작업을 실행합니다. - GET, POST, PUT 및 DELETE HTTP 요청을 지원하는 작업 메서드를 포함합니다.
-
CreatedAtRoute 작업 메서드에서
Create
를 호출하여 HTTP 201 응답을 반환합니다. 상태 코드 201은 서버에서 새 리소스를 만드는 HTTP POST 메서드의 표준 응답입니다. 또한CreatedAtRoute
는Location
헤더를 응답에 추가합니다.Location
헤더는 새로 만든 책의 URI를 지정합니다.
웹 API 테스트
앱을 빌드하고 실행합니다.
https://localhost:<port>/api/books
로 이동하여 컨트롤러의 매개 변수가 없는Get
작업 메서드를 테스트합니다. 다음 JSON 응답이 표시됩니다.[ { "id":"5bfd996f7b8e48dc15ff215d", "bookName":"Design Patterns", "price":54.93, "category":"Computers", "author":"Ralph Johnson" }, { "id":"5bfd996f7b8e48dc15ff215e", "bookName":"Clean Code", "price":43.15, "category":"Computers", "author":"Robert C. Martin" } ]
https://localhost:<port>/api/books/{id here}
로 이동하여 컨트롤러의 오버로드된Get
작업 메서드를 테스트합니다. 다음 JSON 응답이 표시됩니다.{ "id":"{ID}", "bookName":"Clean Code", "price":43.15, "category":"Computers", "author":"Robert C. Martin" }
JSON serialization 옵션 구성
웹 API 테스트 섹션에서 반환된 JSON 응답에 대해 변경하는 두 개의 세부 정보가 있습니다.
- 속성 이름의 기본 카멜 대소문자 방식은 CLR 객체의 속성 이름에 맞춰 파스칼 대소문자 방식으로 변경해야 합니다.
-
bookName
속성은Name
으로 반환되어야 합니다.
앞의 요구 사항을 충족하기 위해 다음과 같이 변경합니다.
ASP.NET 공유 프레임워크에서 JSON.NET이 제거되었습니다.
Microsoft.AspNetCore.Mvc.NewtonsoftJson
에 대한 패키지 참조를 추가합니다.Startup.ConfigureServices
에서 다음 강조 표시된 코드를AddControllers
메서드 호출에 연결합니다.public void ConfigureServices(IServiceCollection services) { services.Configure<BookstoreDatabaseSettings>( Configuration.GetSection(nameof(BookstoreDatabaseSettings))); services.AddSingleton<IBookstoreDatabaseSettings>(sp => sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value); services.AddSingleton<BookService>(); services.AddControllers() .AddNewtonsoftJson(options => options.UseMemberCasing()); }
이전 변경으로 웹 API의 직렬화된 JSON 응답에서 속성 이름은 CLR 개체 형식의 해당 속성 이름과 일치합니다. 예를 들어
Book
클래스의Author
속성은Author
로 직렬화합니다.Models/Book.cs
에서 다음BookName
특성을 사용하여[JsonProperty]
속성에 주석을 추가합니다.[BsonElement("Name")] [JsonProperty("Name")] public string BookName { get; set; }
[JsonProperty]
의Name
특성 값은 웹 API의 직렬화된 JSON 응답의 속성 이름을 나타냅니다.Models/Book.cs
의 맨 위에 다음 코드를 추가하여[JsonProperty]
특성 참조를 확인합니다.using Newtonsoft.Json;
웹 API 테스트 섹션에 정의된 단계를 반복합니다. JSON 속성 이름의 차이를 확인합니다.
웹 API에 인증 지원 추가
ASP.NET Core Identity는 ASP.NET Core 웹앱에 UI(사용자 인터페이스) 로그인 기능을 추가합니다. 웹 API 및 SPA를 보호하려면 다음 중 하나를 사용합니다.
- Microsoft Entra ID
- Azure Active Directory B2C(Azure AD B2C)
- Duende IdentityServer. Duende IdentityServer는 타사 제품입니다.
Duende IdentityServer는 ASP.NET Core용 OpenID Connect 및 OAuth 2.0 프레임워크입니다. Duende IdentityServer를 사용하면 다음과 같은 보안 기능을 사용할 수 있습니다.
- AaaS(Authentication as a Service)
- 여러 응용 프로그램 유형에 대한 SSO(Single Sign-On/Off)
- API에 대한 액세스 제어
- 페더레이션 게이트웨이
자세한 내용은 Duende IdentityServer 개요를 참조 하세요.
다른 인증 공급자에 대한 자세한 내용은 ASP.NET Core 대한 커뮤니티 OSS 인증 옵션을 참조하세요.
다음 단계
ASP.NET Core 웹 API 빌드 방법에 대한 자세한 내용은 다음 리소스를 참조하세요.
ASP.NET Core