C# Web API – Derek Comartin의 접근 방식으로 API 구조 완벽 살펴보기
C# 웹 API 프로젝트를 시작할 때 개발자들은 코드 구조를 어떻게 설계할지에 대한 수많은 선택지에 직면하는 경우가 많습니다. ASP.NET Core 웹 API에서 계층형 패턴을 따라야 할까요? Visual Studio의 기본 템플릿에 있는 컨트롤러 폴더를 그대로 사용해야 할까요? 아니면 Minimal APIs처럼 좀 더 현대적인 스타일을 시도해 보는 건 어떨까요?
CodeOpinion.com 의 데릭 코마틴은 " 프로젝트 구조를 단순하게 유지하세요! "라는 제목의 영상에서 다소 주관적이지만 신선하고 실용적인 입장을 취합니다. 그는 실제 소프트웨어 시스템에서 작동하는 방식으로 웹 API를 구축하고 구성하는 자신의 아이디어를 설명하면서, 실제로 중요한 것, 즉 단순함에 초점을 맞춥니다.
이 글에서는 데릭의 영상을 단계별로 따라가며, ASP.NET Core 웹 API 프로젝트를 명확성, 유지보수성 및 실제 확장성을 고려하여 구성하는 방법을 안내합니다.
일반적인 API 구조 살펴보기
데릭은 Visual Studio에서 새로운 웹 API 프로젝트를 만들 때 대부분의 개발자가 마주하는 질문으로 이야기를 시작합니다.
"HTTP API는 어떻게 구성해야 할까요?"
그는 웹 API 프로젝트를 구성하는 방식이 여러 가지일 수 있다는 점을 즉시 인정합니다. 데릭이 가장 흔히 보는 폴더 구조는 다음과 같습니다.
기술적 고려 사항에 따른 그룹화 – 모델은 Models 폴더에, 컨트롤러는 Controllers 폴더에, 서비스는 Services 폴더에 넣습니다.
클린 아키텍처 또는 어니언 아키텍처를 사용하여 프로젝트를 계층별(API, 애플리케이션, 도메인, 인프라)로 분리하여 종속성을 파악합니다.
- 도메인 주도 설계(DDD)와 수직 슬라이스 아키텍처를 결합하여 기능별로 엔드포인트를 그룹화하면서도 도메인 정보가 풍부한 객체를 유지합니다.
데릭은 이러한 패턴 각각이 리소스와 상호 작용하는 데 필요한 HTTP 메서드(GET, POST, PUT, DELETE)를 사용하는 RESTful API를 생성할 수 있다고 강조합니다. 하지만 그는 폴더 구조만으로 너무 많은 의미를 해석하는 것을 경고합니다.
"엔티티, 애그리게이트 또는 도메인 서비스와 같은 개념을 볼 수도 있지만, 그렇다고 해서 코드가 실제로 도메인 주도 설계를 수행하고 있다는 의미는 아닙니다. 단지 그러한 패턴을 사용하고 있을 뿐입니다."
복잡함이 아닌 단순함에서 시작하세요
데릭은 자신의 목표가 간단하다고 말합니다.
"이 구조를 통해 달성하고 싶었던 가장 중요한 목표 중 하나는 단순함입니다."
데릭은 무거운 .NET Framework 스타일의 아키텍처를 그대로 따라 하거나 교과서에 나오는 패턴을 그대로 복제하는 대신, ASP.NET Core 최소 API를 선택했습니다. 그 이유는 무엇일까요? 컨트롤러와 반복적인 코드 작성 없이도 API를 쉽게 만들 수 있기 때문입니다.
Visual Studio 또는 Visual Studio Code에서 새 웹 API 프로젝트를 만들 때 새 프로젝트 대화 상자에서 ASP.NET Core 웹 API를 선택하는 것으로 시작할 수 있습니다. 기본적으로 컨트롤러, 폴더 및 많은 기본 구조가 제공됩니다. 데릭은 작고 단순하며 깔끔한 구조로 시작하는 것이 종종 더 낫다고 주장합니다.
데릭의 웹 API 핵심 구조
데릭은 .NET Core 사용한 웹 애플리케이션 구조를 소개합니다. 이 플랫폼은 다양한 소프트웨어 애플리케이션 간의 통신을 가능하게 하는 일반적인 HTTP 서비스와 RESTful API를 지원하도록 설계되었습니다.
그는 다음과 같은 방식으로 웹 API 프로젝트를 구성합니다.
엔드포인트 파일 – API에서 사용 가능한 모든 경로를 확인할 수 있는 단일 파일입니다. 데릭은 여러 컨트롤러를 일일이 살펴보는 대신, API가 지원하는 모든 GET 메서드, POST 메서드, PUT 요청, DELETE 요청에 대한 빠른 개요를 원합니다.
공용 폴더 – 여러 소프트웨어 시스템에서 사용되는 필터 및 확장 프로그램과 같은 공유 코드를 저장합니다.
기능 폴더 – 수직적 분류 방식을 따라, 새 리소스 또는 기존 리소스 각각에 고유한 폴더가 생성됩니다. 예를 들어, Posts 폴더에는 GET /posts/{id}, POST /posts, PUT /posts/{id} 및 DELETE /posts/{id}에 필요한 모든 것이 포함될 수 있습니다.
- 데이터 폴더 – 데이터 모델 및 엔티티 매핑이 포함되어 있습니다. 이 경우, 원활한 데이터베이스 통합을 위해 Entity Framework Core를 사용할 수 있습니다.
데릭은 엔드포인트를 기능별로 그룹화함으로써 여러 관련 없는 폴더에 로직이 분산되는 것을 방지합니다.
그가 도메인 주도 설계를 강요하지 않는 이유
데릭은 과거에 도메인 주도 설계(Domain-Driven Design)를 사용해 왔지만, 이번 C# 웹 API 구조에서는 중요한 선택을 했습니다.
"저희는 도메인 주도 설계 방식을 사용하지 않을 겁니다."
대신 그는 "데이터를 데이터 그대로 두는" 방식을 택합니다. 그의 데이터 모델은 다음과 같은 간단한 속성을 가진 일반 클래스입니다.
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
}public class Post
{
public int Id { get; set; }
public string Title { get; set; }
}불필요한 행동은 전혀 포함되어 있지 않습니다. 새로운 리소스를 생성하기 위해 POST 요청을 보내면 API는 단순히 해당 리소스를 저장합니다. id 매개변수를 포함하여 DELETE 요청을 보내면 해당 리소스가 삭제됩니다.
이 접근 방식은 API 엔드포인트를 게시물, 사용자 또는 댓글과 같은 리소스에 작용하는 동사(get 메서드, post 메서드, put 메서드, delete 메서드)로 취급함으로써 REST(Representational State Transfer)의 아키텍처 스타일을 수용합니다.
Visual Studio에서 해결 방법을 단계별로 살펴보겠습니다.
이때 데릭은 Visual Studio 솔루션을 열고 우리에게 둘러보도록 안내합니다.
엔드포인트 파일에는 데이터를 가져오는 GET 요청, 새 리소스를 추가하는 POST 요청, 데이터를 업데이트하는 PUT 요청 또는 기존 리소스를 삭제하는 DELETE 메서드 등 모든 경로가 나열됩니다.
Data 폴더에는 Entity Framework를 통해 데이터베이스에 연결된 Post, User, Comment와 같은 엔티티에 대한 매핑이 포함되어 있습니다.
Common 폴더에는 유효성 검사 필터 및 확장 기능과 같은 HTTP 서비스에 대한 공유 로직이 포함되어 있습니다.
- 각 기능 폴더(게시물, 댓글, 인증)에는 해당 리소스에 필요한 모든 코드가 포함되어 있습니다.
이 깔끔한 프로젝트 폴더 레이아웃은 지나치게 복잡한 프로젝트 대화 상자나 흩어져 있는 컨트롤러 폴더를 뒤지는 번거로움을 방지합니다.
엔드포인트 분석
데릭은 자신의 ASP.NET Core 웹 API의 각 엔드포인트가 세 가지 명확한 단계를 거치는 독립적인 작업 단위라고 설명합니다.
매핑 – HTTP 메서드와 경로를 정의합니다. 예를 들어, 삭제 요청은
DELETE /posts/{id}와 같은 핸들러 메서드에 매핑될 수 있습니다.요청 및 응답 계약 – 각 엔드포인트는 고유한 요청 본문과 응답 유형을 가집니다. 이렇게 하면 HTTP 서비스가 더 명확해지고 중복된 DTO가 여러 겹으로 생성되는 것을 방지할 수 있습니다.
- 로직 – API가 데이터베이스에서 데이터를 가져오거나, 데이터 모델을 업데이트하거나,
return CreatedAtAction또는return NoContent와 같은 상태 코드를 반환하는 실제 핸들러 메서드입니다.
데릭은 Minimal API를 사용하기 때문에 이러한 핸들러는 정적 메서드입니다. ASP.NET Core 사용하면 복잡한 컨트롤러 클래스 없이도 종속성을 직접 주입할 수 있습니다.
최소한의 API가 적합한 이유
데릭은 미니멀 API의 단순함을 칭찬합니다. ASP.NET Core의 최소 템플릿을 사용하면 Program.cs 파일에 몇 줄의 코드만으로 웹 API 프로젝트를 시작할 수 있습니다.
var app = WebApplication.CreateBuilder(args).Build();var app = WebApplication.CreateBuilder(args).Build();그 다음에는 GET 메서드, POST 메서드, PUT 요청을 간단하게 추가할 수 있습니다.
이러한 단순함은 과도한 설계를 방지하는 데 도움이 됩니다. 데릭은 개발자들이 NuGet 패키지 템플릿을 맹목적으로 복사하거나 사소한 엔드포인트마다 새로운 컨트롤러 클래스를 억지로 만들 때 이러한 과도한 설계를 너무 자주 목격한다고 말합니다.
복잡성은 시간이 지남에 따라 어떻게 진화할 수 있는가
데릭은 실제 사례를 들어 설명합니다. 바로 "게시물에 좋아요 누르기" 기능입니다.
- 처음에는 간단합니다. 같은 항목이 있는지 확인하고, 없으면 추가하면 됩니다.
하지만 나중에 소프트웨어 애플리케이션은 웹 페이지나 모바일 기기에 대한 좋아요 수를 즉시 반환해야 할 수도 있습니다.
- 확장성을 확보하기 위해 Post 데이터 모델에 LikeCount 속성을 추가하여 데이터를 비정규화할 수 있습니다.
이는 새로운 과제를 제기합니다.
좋아요에 영향을 미치는 모든 추가 또는 삭제 메서드는 좋아요 수를 정확하게 업데이트해야 합니다.
- API를 호출하지 않고 누군가가 '좋아요'를 추가하면, 좋아요 개수가 잘못 계산됩니다.
데릭은 복잡성이 증가함에 따라 다음과 같은 패턴을 추가할 수 있음을 보여줍니다.
데이터 접근을 캡슐화하기 위한 리포지토리 패턴.
(LikeCount 증가와 같은) 동작을 처리하기 위한 집계 루트입니다.
- "PostLiked"와 같은 이벤트가 게시되도록 보장하는 아웃박스 패턴입니다.
하지만 그의 핵심 주장은 분명합니다.
"여기서부터 시작하지 마세요." 간단한 것부터 시작하고 필요할 때만 발전시키세요.
데릭의 결론으로 마무리하겠습니다.
데릭은 마지막으로 C# 웹 API 개발자를 위한 핵심 교훈으로 돌아갑니다.
"간단한 것부터 시작하세요."
ASP.NET Core Web API 또는 Visual Studio의 ASP.NET Web API를 사용할 때, 처음부터 모든 폴더, 패턴, NuGet 패키지를 추가하면서 과도하게 설계하기 쉽습니다.
하지만 데릭은 해결책을 맹목적으로 적용하지 말라고 경고합니다. 필요한 HTTP 메서드, 다루는 데이터, 그리고 통신을 가능하게 하는 소프트웨어 시스템을 이해해야 합니다. RESTful API를 단계별로 구축해 보세요.
Visual Studio Code 또는 다른 통합 개발 환경을 사용하는 사람들에게도 그의 조언은 유효합니다. 새 프로젝트든 기존 리소스든 프로젝트 구조를 최대한 단순하게 유지하고, 실제 복잡성이 요구될 때만 패턴을 추가하십시오.
결론
데릭 코마틴의 영상은 C# 웹 API 구축 가이드 그 이상입니다. 좋은 아키텍처는 복잡함이 아닌 명확성에서 시작된다는 것을 일깨워줍니다. 그는 Visual Studio에서 실제 ASP.NET Core 웹 API 설정 과정을 단계별로 설명하면서, 최소한의 API, 기능 폴더, 그리고 간결한 데이터 모델이 어떻게 복잡한 설계 없이도 다양한 소프트웨어 애플리케이션 간의 원활한 통신을 가능하게 하는 RESTful API의 기반을 형성할 수 있는지 보여줍니다.
이러한 접근 방식이 실제로 어떻게 적용되는지 보고 데릭의 관점을 직접 들어보고 싶다면 그의 영상이 훌륭한 자료가 될 것입니다. 그의 채널은 소프트웨어 시스템, 웹 서비스, ASP.NET Core 개발에 대한 통찰력 넘치는 토론으로 가득 차 있어, 실력을 향상시키고 프로젝트를 깔끔하고 실용적이며 미래 지향적으로 만들고자 하는 모든 개발자에게 꼭 필요한 채널입니다.

