ASP.NET Core 및 MongoDB를 사용하여 웹 API 만들기

참고 항목

이 문서의 최신 버전은 아닙니다. 현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

Important

이 정보는 상업적으로 출시되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적, 또는 묵시적인 보증을 하지 않습니다.

현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

작성자: Pratik KhandelwalScott Addie

이 자습서에서는 MongoDB NoSQL 데이터베이스에 대해 CRUD(만들기, 읽기, 업데이트 및 삭제) 작업을 실행하는 웹 API를 만듭니다.

이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.

  • MongoDB 구성
  • MongoDB 데이터베이스 만들기
  • MongoDB 컬렉션 및 스키마 정의
  • 웹 API에서 MongoDB CRUD 작업 수행
  • JSON serialization 사용자 지정

필수 조건

MongoDB 구성

개발 머신의 어디에서나 MongoDB 및 Mongo DB Shell 액세스를 사용하도록 설정합니다.

  1. Windows에서 MongoDB는 기본적으로 C:\Program Files\MongoDB에 설치됩니다. C:\Program Files\MongoDB\Server\<version_number>\binPATH 환경 변수에 추가합니다.

  2. MongoDB 셸을 다운로드하고 추출할 디렉터리를 선택합니다. 환경 변수에 대한 mongosh.exePATH 결과 경로를 추가합니다.

  3. 데이터를 저장하기 위해 개발 머신에서 디렉터리를 선택합니다. 예를 들어 Windows의 경우 C:\BooksData 등을 선택합니다. 디렉터리가 없을 경우 새로 만듭니다. mongo 셸은 새 디렉터리를 만들지 않습니다.

  4. OS 명령 셸(MongoDB 셸 아님)에서 다음 명령을 사용하여 기본 포트 27017에서 MongoDB에 연결합니다. 이전 단계에서 선택한 디렉터리로 바꿉 <data_directory_path> 다.

    mongod --dbpath <data_directory_path>
    

다음 단계에서 이전에 설치된 MongoDB Shell을 사용하여 데이터베이스 및 컬렉션을 만들고 문서를 저장합니다. MongoDB Shell 명령에 대한 자세한 내용은 mongosh를 참조하세요.

  1. 를 시작하여 MongoDB 명령 셸 인스턴스를 엽니다 mongosh.exe.

  2. 명령 셸에서 다음 명령을 실행하여 기본 테스트 데이터베이스에 연결합니다.

    mongosh
    
  3. 명령 셸에서 다음 명령을 실행합니다.

    use BookStore
    

    아직 존재하지 않는 경우 BookStore라는 데이터베이스가 생성됩니다. 데이터베이스가 있는 경우 트랜잭션을 위해 해당 연결이 열립니다.

  4. 다음 명령을 사용하여 Books 컬렉션을 만듭니다.

    db.createCollection('Books')
    

    다음 결과가 표시됩니다.

    { "ok" : 1 }
    
  5. 다음 명령을 사용하여 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이전 결과에 표시된 내용이 명령 셸에 표시된 것과 일치하지 않습니다.

  6. 다음 명령을 사용하여 데이터베이스의 문서를 봅니다.

    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"
     }
    

    스키마가 각 문서에 대해 자동 생성된 ObjectId 형식의 _id 속성을 추가합니다.

ASP.NET Core 웹 API 프로젝트 만들기

  1. 파일>새로 만들기>프로젝트로 이동합니다.

  2. ASP.NET Core Web API 프로젝트 형식을 선택하고 다음을 선택합니다.

  3. 프로젝트 이름을 BookStoreApi로 지정하고 다음을 선택합니다.

  4. .NET 8.0(장기 지원) 프레임워크를 선택하고 만들기를 선택합니다.

  5. 패키지 관리자 콘솔 창에서 프로젝트 루트로 이동합니다. 다음 명령을 실행하여 MongoDB용 .NET 드라이버를 설치합니다.

    Install-Package MongoDB.Driver
    

엔터티 모델 추가

  1. 프로젝트 루트에 Models 디렉터리를 추가합니다.

  2. 다음 코드를 사용하여 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]로 주석이 추가됩니다.
    • ObjectId 구조체 대신 string 형식으로 매개 변수를 전달할 수 있도록 [BsonRepresentation(BsonType.ObjectId)]로 주석이 추가됩니다. Mongo는 string에서 ObjectId로 변환을 처리합니다.

    BookName 속성은 [BsonElement] 특성으로 주석이 추가됩니다. Name의 특성 값은 MongoDB 컬렉션의 속성 이름을 나타냅니다.

구성 모델 추가

  1. 다음 데이터베이스 구성 값을 appsettings.json에 추가합니다.

    {
        "BookStoreDatabase": {
            "ConnectionString": "mongodb://localhost:27017",
            "DatabaseName": "BookStore",
            "BooksCollectionName": "Books"
        },
        "Logging": {
            "LogLevel": {
                "Default": "Information",
                "Microsoft.AspNetCore": "Warning"
            }
        },
        "AllowedHosts": "*"
    }
    
  2. 다음 코드를 사용하여 Models 디렉터리에 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# 속성 이름은 매핑 프로세스를 용이하게 하기 위해 동일한 이름이 지정됩니다.

  3. 다음 강조 표시된 코드를 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 속성은 appsettings.jsonBookStoreDatabase:ConnectionString 속성으로 채워집니다.

  4. Program.cs의 맨 위에 다음 코드를 추가하여 BookStoreDatabaseSettings 참조를 확인합니다.

    using BookStoreApi.Models;
    

CRUD 작업 서비스 추가

  1. 프로젝트 루트에 Services 디렉터리를 추가합니다.

  2. 다음 코드를 사용하여 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 구성 값에 대한 액세스를 제공합니다.

  3. 다음 강조 표시된 코드를 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로 등록됩니다. BooksServiceMongoClient에 직접 종속되기 때문에 싱글톤 서비스 수명이 가장 적합합니다. 공식 Mongo 클라이언트 재사용 지침에 따라 MongoClient를 싱글톤 수명으로 DI에 등록해야 합니다.

  4. 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: 제공된 검색 조건과 일치하는 단일 문서를 제공된 개체로 바꿉니다.

컨트롤러 추가

다음 코드를 사용하여 Controllers 디렉터리에 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 요청을 지원하는 작업 메서드를 포함합니다.
  • Create 작업 메서드에서 CreatedAtAction를 호출하여 HTTP 201 응답을 반환합니다. 상태 코드 201은 서버에서 새 리소스를 만드는 HTTP POST 메서드의 표준 응답입니다. 또한 CreatedAtActionLocation 헤더를 응답에 추가합니다. Location 헤더는 새로 만든 책의 URI를 지정합니다.

웹 API 테스트

  1. 앱을 빌드하고 실행합니다.

  2. 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"
      }
    ]
    
  3. 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으로 반환되어야 합니다.

앞의 요구 사항을 충족하기 위해 다음과 같이 변경합니다.

  1. 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로 직렬화됩니다.

  2. Models/Book.cs에서 BookName 속성은 [JsonPropertyName] 특성으로 주석이 추가됩니다.

    [BsonElement("Name")]
    [JsonPropertyName("Name")]
    public string BookName { get; set; } = null!;
    

    Name[JsonPropertyName] 특성 값은 웹 API의 직렬화된 JSON 응답의 속성 이름을 나타냅니다.

  3. Models/Book.cs의 맨 위에 다음 코드를 추가하여 [JsonProperty] 특성 참조를 확인합니다.

    using System.Text.Json.Serialization;
    
  4. 웹 API 테스트 섹션에 정의된 단계를 반복합니다. JSON 속성 이름의 차이를 확인합니다.

웹 API에 인증 지원 추가

ASP.NET Core Identity는 ASP.NET Core 웹앱에 UI(사용자 인터페이스) 로그인 기능을 추가합니다. 웹 API 및 SPA를 보호하려면 다음 중 하나를 사용합니다.

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에 대한 액세스 제어
  • 페더레이션 게이트웨이

Important

Duende Software에서 Duende Identity 서버의 프로덕션 사용에 대한 라이선스 요금 지불을 요구할 수 있습니다. 자세한 내용은 ASP.NET Core 5.0에서 6.0으로 마이그레이션을 참조하세요.

자세한 내용은 Duende Identity Server 설명서(Duende Software 웹 사이트)를 참조하세요.

추가 리소스

이 자습서에서는 MongoDB NoSQL 데이터베이스에 대해 CRUD(만들기, 읽기, 업데이트 및 삭제) 작업을 실행하는 웹 API를 만듭니다.

이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.

  • MongoDB 구성
  • MongoDB 데이터베이스 만들기
  • MongoDB 컬렉션 및 스키마 정의
  • 웹 API에서 MongoDB CRUD 작업 수행
  • JSON serialization 사용자 지정

필수 조건

MongoDB 구성

개발 머신의 어디에서나 MongoDB 및 Mongo DB Shell 액세스를 사용하도록 설정합니다.

  1. Windows에서 MongoDB는 기본적으로 C:\Program Files\MongoDB에 설치됩니다. C:\Program Files\MongoDB\Server\<version_number>\binPATH 환경 변수에 추가합니다.

  2. MongoDB 셸을 다운로드하고 추출할 디렉터리를 선택합니다. 환경 변수에 대한 mongosh.exePATH 결과 경로를 추가합니다.

  3. 데이터를 저장하기 위해 개발 머신에서 디렉터리를 선택합니다. 예를 들어 Windows의 경우 C:\BooksData 등을 선택합니다. 디렉터리가 없을 경우 새로 만듭니다. mongo 셸은 새 디렉터리를 만들지 않습니다.

  4. OS 명령 셸(MongoDB 셸 아님)에서 다음 명령을 사용하여 기본 포트 27017에서 MongoDB에 연결합니다. 이전 단계에서 선택한 디렉터리로 바꿉 <data_directory_path> 다.

    mongod --dbpath <data_directory_path>
    

다음 단계에서 이전에 설치된 MongoDB Shell을 사용하여 데이터베이스 및 컬렉션을 만들고 문서를 저장합니다. MongoDB Shell 명령에 대한 자세한 내용은 mongosh를 참조하세요.

  1. 를 시작하여 MongoDB 명령 셸 인스턴스를 엽니다 mongosh.exe.

  2. 명령 셸에서 다음 명령을 실행하여 기본 테스트 데이터베이스에 연결합니다.

    mongosh
    
  3. 명령 셸에서 다음 명령을 실행합니다.

    use BookStore
    

    아직 존재하지 않는 경우 BookStore라는 데이터베이스가 생성됩니다. 데이터베이스가 있는 경우 트랜잭션을 위해 해당 연결이 열립니다.

  4. 다음 명령을 사용하여 Books 컬렉션을 만듭니다.

    db.createCollection('Books')
    

    다음 결과가 표시됩니다.

    { "ok" : 1 }
    
  5. 다음 명령을 사용하여 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이전 결과에 표시된 내용이 명령 셸에 표시된 것과 일치하지 않습니다.

  6. 다음 명령을 사용하여 데이터베이스의 문서를 봅니다.

    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"
     }
    

    스키마가 각 문서에 대해 자동 생성된 ObjectId 형식의 _id 속성을 추가합니다.

ASP.NET Core 웹 API 프로젝트 만들기

  1. 파일>새로 만들기>프로젝트로 이동합니다.

  2. ASP.NET Core Web API 프로젝트 형식을 선택하고 다음을 선택합니다.

  3. 프로젝트 이름을 BookStoreApi로 지정하고 다음을 선택합니다.

  4. .NET 7.0(표준 용어 지원) 프레임워크를 선택하고 만들기를 선택합니다.

  5. 도구 메뉴에서 NuGet 패키지 관리자>패키지 관리자 콘솔을 선택합니다.

  6. 패키지 관리자 콘솔 창에서 프로젝트 루트로 이동합니다. 다음 명령을 실행하여 MongoDB용 .NET 드라이버를 설치합니다.

    Install-Package MongoDB.Driver
    

엔터티 모델 추가

  1. 프로젝트 루트에 Models 디렉터리를 추가합니다.

  2. 다음 코드를 사용하여 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]로 주석이 추가됩니다.
    • ObjectId 구조체 대신 string 형식으로 매개 변수를 전달할 수 있도록 [BsonRepresentation(BsonType.ObjectId)]로 주석이 추가됩니다. Mongo는 string에서 ObjectId로 변환을 처리합니다.

    BookName 속성은 [BsonElement] 특성으로 주석이 추가됩니다. Name의 특성 값은 MongoDB 컬렉션의 속성 이름을 나타냅니다.

구성 모델 추가

  1. 다음 데이터베이스 구성 값을 appsettings.json에 추가합니다.

    {
      "BookStoreDatabase": {
        "ConnectionString": "mongodb://localhost:27017",
        "DatabaseName": "BookStore",
        "BooksCollectionName": "Books"
      },
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning"
        }
      },
      "AllowedHosts": "*"
    }
    
  2. 다음 코드를 사용하여 Models 디렉터리에 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# 속성 이름은 매핑 프로세스를 용이하게 하기 위해 동일한 이름이 지정됩니다.

  3. 다음 강조 표시된 코드를 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 속성은 appsettings.jsonBookStoreDatabase:ConnectionString 속성으로 채워집니다.

  4. Program.cs의 맨 위에 다음 코드를 추가하여 BookStoreDatabaseSettings 참조를 확인합니다.

    using BookStoreApi.Models;
    

CRUD 작업 서비스 추가

  1. 프로젝트 루트에 Services 디렉터리를 추가합니다.

  2. 다음 코드를 사용하여 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 구성 값에 대한 액세스를 제공합니다.

  3. 다음 강조 표시된 코드를 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로 등록됩니다. BooksServiceMongoClient에 직접 종속되기 때문에 싱글톤 서비스 수명이 가장 적합합니다. 공식 Mongo 클라이언트 재사용 지침에 따라 MongoClient를 싱글톤 수명으로 DI에 등록해야 합니다.

  4. 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: 제공된 검색 조건과 일치하는 단일 문서를 제공된 개체로 바꿉니다.

컨트롤러 추가

다음 코드를 사용하여 Controllers 디렉터리에 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 요청을 지원하는 작업 메서드를 포함합니다.
  • Create 작업 메서드에서 CreatedAtAction를 호출하여 HTTP 201 응답을 반환합니다. 상태 코드 201은 서버에서 새 리소스를 만드는 HTTP POST 메서드의 표준 응답입니다. 또한 CreatedAtActionLocation 헤더를 응답에 추가합니다. Location 헤더는 새로 만든 책의 URI를 지정합니다.

웹 API 테스트

  1. 앱을 빌드하고 실행합니다.

  2. 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"
      }
    ]
    
  3. 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으로 반환되어야 합니다.

앞의 요구 사항을 충족하기 위해 다음과 같이 변경합니다.

  1. 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로 직렬화됩니다.

  2. Models/Book.cs에서 BookName 속성은 [JsonPropertyName] 특성으로 주석이 추가됩니다.

    [BsonElement("Name")]
    [JsonPropertyName("Name")]
    public string BookName { get; set; } = null!;
    

    Name[JsonPropertyName] 특성 값은 웹 API의 직렬화된 JSON 응답의 속성 이름을 나타냅니다.

  3. Models/Book.cs의 맨 위에 다음 코드를 추가하여 [JsonProperty] 특성 참조를 확인합니다.

    using System.Text.Json.Serialization;
    
  4. 웹 API 테스트 섹션에 정의된 단계를 반복합니다. JSON 속성 이름의 차이를 확인합니다.

웹 API에 인증 지원 추가

ASP.NET Core Identity는 ASP.NET Core 웹앱에 UI(사용자 인터페이스) 로그인 기능을 추가합니다. 웹 API 및 SPA를 보호하려면 다음 중 하나를 사용합니다.

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에 대한 액세스 제어
  • 페더레이션 게이트웨이

Important

Duende Software에서 Duende Identity 서버의 프로덕션 사용에 대한 라이선스 요금 지불을 요구할 수 있습니다. 자세한 내용은 ASP.NET Core 5.0에서 6.0으로 마이그레이션을 참조하세요.

자세한 내용은 Duende Identity Server 설명서(Duende Software 웹 사이트)를 참조하세요.

추가 리소스

이 자습서에서는 MongoDB NoSQL 데이터베이스에 대해 CRUD(만들기, 읽기, 업데이트 및 삭제) 작업을 실행하는 웹 API를 만듭니다.

이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.

  • MongoDB 구성
  • MongoDB 데이터베이스 만들기
  • MongoDB 컬렉션 및 스키마 정의
  • 웹 API에서 MongoDB CRUD 작업 수행
  • JSON serialization 사용자 지정

필수 조건

MongoDB 구성

개발 머신의 어디에서나 MongoDB 및 Mongo DB Shell 액세스를 사용하도록 설정합니다.

  1. Windows에서 MongoDB는 기본적으로 C:\Program Files\MongoDB에 설치됩니다. C:\Program Files\MongoDB\Server\<version_number>\binPATH 환경 변수에 추가합니다.

  2. MongoDB 셸을 다운로드하고 추출할 디렉터리를 선택합니다. 환경 변수에 대한 mongosh.exePATH 결과 경로를 추가합니다.

  3. 데이터를 저장하기 위해 개발 머신에서 디렉터리를 선택합니다. 예를 들어 Windows의 경우 C:\BooksData 등을 선택합니다. 디렉터리가 없을 경우 새로 만듭니다. mongo 셸은 새 디렉터리를 만들지 않습니다.

  4. OS 명령 셸(MongoDB 셸 아님)에서 다음 명령을 사용하여 기본 포트 27017에서 MongoDB에 연결합니다. 이전 단계에서 선택한 디렉터리로 바꿉 <data_directory_path> 다.

    mongod --dbpath <data_directory_path>
    

다음 단계에서 이전에 설치된 MongoDB Shell을 사용하여 데이터베이스 및 컬렉션을 만들고 문서를 저장합니다. MongoDB Shell 명령에 대한 자세한 내용은 mongosh를 참조하세요.

  1. 를 시작하여 MongoDB 명령 셸 인스턴스를 엽니다 mongosh.exe.

  2. 명령 셸에서 다음 명령을 실행하여 기본 테스트 데이터베이스에 연결합니다.

    mongosh
    
  3. 명령 셸에서 다음 명령을 실행합니다.

    use BookStore
    

    아직 존재하지 않는 경우 BookStore라는 데이터베이스가 생성됩니다. 데이터베이스가 있는 경우 트랜잭션을 위해 해당 연결이 열립니다.

  4. 다음 명령을 사용하여 Books 컬렉션을 만듭니다.

    db.createCollection('Books')
    

    다음 결과가 표시됩니다.

    { "ok" : 1 }
    
  5. 다음 명령을 사용하여 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이전 결과에 표시된 내용이 명령 셸에 표시된 것과 일치하지 않습니다.

  6. 다음 명령을 사용하여 데이터베이스의 문서를 봅니다.

    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"
     }
    

    스키마가 각 문서에 대해 자동 생성된 ObjectId 형식의 _id 속성을 추가합니다.

ASP.NET Core 웹 API 프로젝트 만들기

  1. 파일>새로 만들기>프로젝트로 이동합니다.

  2. ASP.NET Core Web API 프로젝트 형식을 선택하고 다음을 선택합니다.

  3. 프로젝트 이름을 BookStoreApi로 지정하고 다음을 선택합니다.

  4. .NET 6.0(장기 지원) 프레임워크를 선택하고 만들기를 선택합니다.

  5. 패키지 관리자 콘솔 창에서 프로젝트 루트로 이동합니다. 다음 명령을 실행하여 MongoDB용 .NET 드라이버를 설치합니다.

    Install-Package MongoDB.Driver
    

엔터티 모델 추가

  1. 프로젝트 루트에 Models 디렉터리를 추가합니다.

  2. 다음 코드를 사용하여 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]로 주석이 추가됩니다.
    • ObjectId 구조체 대신 string 형식으로 매개 변수를 전달할 수 있도록 [BsonRepresentation(BsonType.ObjectId)]로 주석이 추가됩니다. Mongo는 string에서 ObjectId로 변환을 처리합니다.

    BookName 속성은 [BsonElement] 특성으로 주석이 추가됩니다. Name의 특성 값은 MongoDB 컬렉션의 속성 이름을 나타냅니다.

구성 모델 추가

  1. 다음 데이터베이스 구성 값을 appsettings.json에 추가합니다.

    {
        "BookStoreDatabase": {
            "ConnectionString": "mongodb://localhost:27017",
            "DatabaseName": "BookStore",
            "BooksCollectionName": "Books"
        },
        "Logging": {
            "LogLevel": {
                "Default": "Information",
                "Microsoft.AspNetCore": "Warning"
            }
        },
        "AllowedHosts": "*"
    }
    
  2. 다음 코드를 사용하여 Models 디렉터리에 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# 속성 이름은 매핑 프로세스를 용이하게 하기 위해 동일한 이름이 지정됩니다.

  3. 다음 강조 표시된 코드를 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 속성은 appsettings.jsonBookStoreDatabase:ConnectionString 속성으로 채워집니다.

  4. Program.cs의 맨 위에 다음 코드를 추가하여 BookStoreDatabaseSettings 참조를 확인합니다.

    using BookStoreApi.Models;
    

CRUD 작업 서비스 추가

  1. 프로젝트 루트에 Services 디렉터리를 추가합니다.

  2. 다음 코드를 사용하여 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 구성 값에 대한 액세스를 제공합니다.

  3. 다음 강조 표시된 코드를 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로 등록됩니다. BooksServiceMongoClient에 직접 종속되기 때문에 싱글톤 서비스 수명이 가장 적합합니다. 공식 Mongo 클라이언트 재사용 지침에 따라 MongoClient를 싱글톤 수명으로 DI에 등록해야 합니다.

  4. 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: 제공된 검색 조건과 일치하는 단일 문서를 제공된 개체로 바꿉니다.

컨트롤러 추가

다음 코드를 사용하여 Controllers 디렉터리에 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 요청을 지원하는 작업 메서드를 포함합니다.
  • Create 작업 메서드에서 CreatedAtAction를 호출하여 HTTP 201 응답을 반환합니다. 상태 코드 201은 서버에서 새 리소스를 만드는 HTTP POST 메서드의 표준 응답입니다. 또한 CreatedAtActionLocation 헤더를 응답에 추가합니다. Location 헤더는 새로 만든 책의 URI를 지정합니다.

웹 API 테스트

  1. 앱을 빌드하고 실행합니다.

  2. 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"
      }
    ]
    
  3. 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으로 반환되어야 합니다.

앞의 요구 사항을 충족하기 위해 다음과 같이 변경합니다.

  1. 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로 직렬화됩니다.

  2. Models/Book.cs에서 BookName 속성은 [JsonPropertyName] 특성으로 주석이 추가됩니다.

    [BsonElement("Name")]
    [JsonPropertyName("Name")]
    public string BookName { get; set; } = null!;
    

    Name[JsonPropertyName] 특성 값은 웹 API의 직렬화된 JSON 응답의 속성 이름을 나타냅니다.

  3. Models/Book.cs의 맨 위에 다음 코드를 추가하여 [JsonProperty] 특성 참조를 확인합니다.

    using System.Text.Json.Serialization;
    
  4. 웹 API 테스트 섹션에 정의된 단계를 반복합니다. JSON 속성 이름의 차이를 확인합니다.

웹 API에 인증 지원 추가

ASP.NET Core Identity는 ASP.NET Core 웹앱에 UI(사용자 인터페이스) 로그인 기능을 추가합니다. 웹 API 및 SPA를 보호하려면 다음 중 하나를 사용합니다.

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에 대한 액세스 제어
  • 페더레이션 게이트웨이

Important

Duende Software에서 Duende Identity 서버의 프로덕션 사용에 대한 라이선스 요금 지불을 요구할 수 있습니다. 자세한 내용은 ASP.NET Core 5.0에서 6.0으로 마이그레이션을 참조하세요.

자세한 내용은 Duende Identity Server 설명서(Duende Software 웹 사이트)를 참조하세요.

추가 리소스

이 자습서에서는 MongoDB NoSQL 데이터베이스에 대해 CRUD(만들기, 읽기, 업데이트 및 삭제) 작업을 실행하는 웹 API를 만듭니다.

이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.

  • MongoDB 구성
  • MongoDB 데이터베이스 만들기
  • MongoDB 컬렉션 및 스키마 정의
  • 웹 API에서 MongoDB CRUD 작업 수행
  • JSON serialization 사용자 지정

샘플 코드 보기 및 다운로드(다운로드 방법)

필수 조건

MongoDB 구성

Windows를 사용하는 경우 MongoDB는 기본적으로 C:\Program Files\MongoDB에 설치됩니다. C:\Program Files\MongoDB\Server\<version_number>\binPath 환경 변수에 추가합니다. 이렇게 변경하면 개발 머신의 어디에서나 MongoDB에 액세스할 수 있습니다.

다음 단계에서 mongo 셸을 사용하여 데이터베이스 및 컬렉션을 만들고 문서를 저장합니다. mongo 셸 명령에 대한 자세한 내용은 mongo 셸 작업을 참조하세요.

  1. 개발 머신에서 데이터를 저장할 디렉터리를 선택합니다. 예를 들어 Windows의 경우 C:\BooksData 등을 선택합니다. 디렉터리가 없을 경우 새로 만듭니다. mongo 셸은 새 디렉터리를 만들지 않습니다.

  2. 명령 셸을 엽니다. 다음 명령을 실행하여 기본 포트 27017에서 MongoDB에 연결합니다. <data_directory_path>를 이전 단계에서 선택한 디렉터리로 바꿔야 합니다.

    mongod --dbpath <data_directory_path>
    
  3. 다른 명령 셸 인스턴스를 엽니다. 다음 명령을 실행하여 기본 테스트 데이터베이스에 연결합니다.

    mongo
    
  4. 명령 셸에서 다음 명령을 실행합니다.

    use BookstoreDb
    

    아직 존재하지 않는 경우 BookstoreDb라는 데이터베이스가 생성됩니다. 데이터베이스가 있는 경우 트랜잭션을 위해 해당 연결이 열립니다.

  5. 다음 명령을 사용하여 Books 컬렉션을 만듭니다.

    db.createCollection('Books')
    

    다음 결과가 표시됩니다.

    { "ok" : 1 }
    
  6. 다음 명령을 사용하여 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와 일치하지 않습니다.

  7. 다음 명령을 사용하여 데이터베이스의 문서를 봅니다.

    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"
    }
    

    스키마가 각 문서에 대해 자동 생성된 ObjectId 형식의 _id 속성을 추가합니다.

데이터베이스가 준비되었습니다. 이제 ASP.NET Core 웹 API를 만들기 시작할 수 있습니다.

ASP.NET Core 웹 API 프로젝트 만들기

  1. 파일>새로 만들기>프로젝트로 이동합니다.

  2. ASP.NET Core 웹 애플리케이션 프로젝트 유형을 선택하고 다음을 선택합니다.

  3. 프로젝트 이름을 BooksApi로 지정하고 만들기를 선택합니다.

  4. .NET Core 대상 프레임워크 및 ASP.NET Core 3.0을 선택합니다. API 프로젝트 템플릿을 선택하고 만들기를 선택합니다.

  5. MongoDB용 .NET 드라이버의 안정적인 최신 버전을 확인하려면 NuGet 갤러리: MongoDB.Driver를 방문하세요. 패키지 관리자 콘솔 창에서 프로젝트 루트로 이동합니다. 다음 명령을 실행하여 MongoDB용 .NET 드라이버를 설치합니다.

    Install-Package MongoDB.Driver -Version {VERSION}
    

엔터티 모델 추가

  1. 프로젝트 루트에 Models 디렉터리를 추가합니다.

  2. 다음 코드를 사용하여 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]로 주석이 추가됩니다.
    • ObjectId 구조체 대신 string 형식으로 매개 변수를 전달할 수 있도록 [BsonRepresentation(BsonType.ObjectId)]로 주석이 추가됩니다. Mongo는 string에서 ObjectId로 변환을 처리합니다.

    BookName 속성은 [BsonElement] 특성으로 주석이 추가됩니다. Name의 특성 값은 MongoDB 컬렉션의 속성 이름을 나타냅니다.

구성 모델 추가

  1. 다음 데이터베이스 구성 값을 appsettings.json에 추가합니다.

    {
      "BookstoreDatabaseSettings": {
        "BooksCollectionName": "Books",
        "ConnectionString": "mongodb://localhost:27017",
        "DatabaseName": "BookstoreDb"
      },
      "Logging": {
        "IncludeScopes": false,
        "Debug": {
          "LogLevel": {
            "Default": "Warning"
          }
        },
        "Console": {
          "LogLevel": {
            "Default": "Warning"
          }
        }
      }
    }
    
  2. 다음 코드를 사용하여 BookstoreDatabaseSettings.csModels 디렉터리에 파일을 추가합니다.

    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# 속성 이름은 매핑 프로세스를 용이하게 하기 위해 동일한 이름이 지정됩니다.

  3. 다음 강조 표시된 코드를 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 속성은 appsettings.jsonBookstoreDatabaseSettings:ConnectionString 속성으로 채워집니다.
    • IBookstoreDatabaseSettings 인터페이스는 싱글톤 서비스 수명으로 DI에 등록됩니다. 삽입하면 인터페이스 인스턴스가 BookstoreDatabaseSettings 개체로 확인됩니다.
  4. Startup.cs의 맨 위에 다음 코드를 추가하여 BookstoreDatabaseSettingsIBookstoreDatabaseSettings 참조를 확인합니다.

    using BooksApi.Models;
    

CRUD 작업 서비스 추가

  1. 프로젝트 루트에 Services 디렉터리를 추가합니다.

  2. 다음 코드를 사용하여 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 구성 값에 대한 액세스를 제공합니다.

  3. 다음 강조 표시된 코드를 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로 등록됩니다. BookServiceMongoClient에 직접 종속되기 때문에 싱글톤 서비스 수명이 가장 적합합니다. 공식 Mongo 클라이언트 재사용 지침에 따라 MongoClient를 싱글톤 수명으로 DI에 등록해야 합니다.

  4. 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: 제공된 검색 조건과 일치하는 단일 문서를 제공된 개체로 바꿉니다.

컨트롤러 추가

다음 코드를 사용하여 Controllers 디렉터리에 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 요청을 지원하는 작업 메서드를 포함합니다.
  • Create 작업 메서드에서 CreatedAtRoute를 호출하여 HTTP 201 응답을 반환합니다. 상태 코드 201은 서버에서 새 리소스를 만드는 HTTP POST 메서드의 표준 응답입니다. 또한 CreatedAtRouteLocation 헤더를 응답에 추가합니다. Location 헤더는 새로 만든 책의 URI를 지정합니다.

웹 API 테스트

  1. 앱을 빌드하고 실행합니다.

  2. 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"
      }
    ]
    
  3. 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으로 반환되어야 합니다.

앞의 요구 사항을 충족하기 위해 다음과 같이 변경합니다.

  1. ASP.NET 공유 프레임워크에서 JSON.NET이 제거되었습니다. Microsoft.AspNetCore.Mvc.NewtonsoftJson에 대한 패키지 참조를 추가합니다.

  2. 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로 직렬화합니다.

  3. Models/Book.cs에서 다음 [JsonProperty] 특성을 사용하여 BookName 속성에 주석을 추가합니다.

    [BsonElement("Name")]
    [JsonProperty("Name")]
    public string BookName { get; set; }
    

    Name[JsonProperty] 특성 값은 웹 API의 직렬화된 JSON 응답의 속성 이름을 나타냅니다.

  4. Models/Book.cs의 맨 위에 다음 코드를 추가하여 [JsonProperty] 특성 참조를 확인합니다.

    using Newtonsoft.Json;
    
  5. 웹 API 테스트 섹션에 정의된 단계를 반복합니다. JSON 속성 이름의 차이를 확인합니다.

웹 API에 인증 지원 추가

ASP.NET Core Identity는 ASP.NET Core 웹앱에 UI(사용자 인터페이스) 로그인 기능을 추가합니다. 웹 API 및 SPA를 보호하려면 다음 중 하나를 사용합니다.

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 빌드 방법에 대한 자세한 내용은 다음 리소스를 참조하세요.