기본 콘텐츠로 건너뛰기

Pinned Post

화제인 TypeSafe Jev, 실제로 어디에 쓰고 있을까?

  AI · AI Agent · Decision Model 요즘 화제인 TypeSafe Jev, 실제로 어디에 쓰고 있을까? ChatGPT나 Claude처럼 글을 생성하는 AI가 아니라, 소프트웨어가 바로 사용할 수 있는 판단 결과를 만들어내는 Jev 가 등장했습니다. 실제 공개 사례와 측정 결과를 통해 Jev가 어디에 쓰이고 있는지 살펴봅니다. 작성 기준일 : 2026년 9월 23일 검증 기준 : TypeSafe 공식 홈페이지·공식 블로그·공식 GitHub 및 공개 Jev 데모 1. Jev가 대체 무엇인가? 최근 AI 개발자 사이에서 TypeSafe의 Jev 가 빠르게 주목받고 있습니다. Jev를 처음 보면 "또 하나의 LLM인가?"라는 생각이 들 수 있습니다. 하지만 TypeSafe가 설명하는 방향은 조금 다릅니다. 일반적인 LLM 입력 → 자연어 생성 Jev 애플리케이션 상태 → Typed Judgment + Probability TypeSafe는 Jev를 자사의 첫 번째 System One Model 이라고 설명합니다. 일반적인 LLM이 사람이 읽을 텍스트를 생성하는 데 최적화되어 있다면, System One Model은 소프트웨어가 직접 사용할 수 있는 구조화된 판단을 반환하는 방향으로 설계됐습니다. [oai_citation:8‡TypeSafe AI](https://typesafe.ai/blog/introducing-system-one-models-and-jev?utm_source...

ASP.NET Core API 컨트롤러에서 피해야 할 12가지 나쁜 습관(Practices )

 




 

ASP.NET Core는 웹 애플리케이션 및 웹 API를 빌드하는 데 사용되는 Microsoft의 프레임워크입니다. 이 프레임워크를 사용하면 강력하고 안정적인 웹 애플리케이션을 개발할 수 있습니다.

해당 사이트의 글은 ASP.NET Core API 컨트롤러를 작성할 때 주의해야 할 12가지 잘못된 방법에 대해 설명하고 있습니다. 이러한 나쁜 실천 방법을 피하는 것은 코드의 품질과 성능을 향상시키는 데 도움이 됩니다.

예를 들어, 글에는 API 컨트롤러에서 비동기 코드를 적절하게 사용하는 방법, 예외 처리 및 오류 관리, 보안에 대한 지침 등이 포함되어 있습니다. 이러한 규칙을 따르면 애플리케이션의 안정성과 유지 보수성을 높일 수 있습니다.

여러분이 ASP.NET Core를 사용하여 웹 API를 개발하고 있다면, 해당 사이트의 글을 읽어보고 나쁜 실천 방법을 피해 최고의 코드를 작성하는 데 도움을 받을 수 있을 것입니다. 코드의 품질과 유지 보수성을 향상시켜 안정적이고 성능이 우수한 웹 애플리케이션을 개발하시기를 바랍니다.

 

 

ASP.NET Core에서 컨트롤러를 개발할 때 유지 관리 가능성, 성능 및 모범 사례 준수를 보장하기 위해 피해야 할 특정 관행이 있습니다. 다음은 컨트롤러에서 피해야 할 12가지 사항입니다.

 

 

1. 긴밀한 결합 (Tight coupling)


특정 종속성이나 프레임워크가 있는 컨트롤러에서 긴밀한 결합을 피하세요. 대신 의존성 주입을 사용하여 컨트롤러에 의존성을 주입하세요. 이렇게 하면 느슨한 결합이 촉진되고 코드의 테스트 및 유지 관리가 더 쉬워집니다.

 

// Avoid:
[ApiController]
[Route("[controller]")]
public class ProductController : ControllerBase
{
    ProductService productService = new ProductService();
    // ...
}


// Prefer:
[ApiController]
[Route("[controller]")]
public class ProductController : ControllerBase
{
    private readonly ILogger<ProductController> _logger;
    private readonly IProductService _productService;

    public ProductController(IProductService productService, ILogger<ProductController> logger)
    {
        _logger = logger;
        _productService = productService;
    }
    // ...
}

 

종속성 주입에 대해 자세히 알아보기

 

 

2. 혼합 문제 (Mixing concerns)


컨트롤러는 HTTP 요청을 처리하고 응답을 생성하는 데 집중해야 합니다. 데이터 액세스, 인증 또는 권한 부여와 같은 문제를 컨트롤러에서 직접 처리하지 마세요. 이러한 책임은 별도의 클래스나 미들웨어에 위임하세요.

 

// Avoid:
[HttpPost]
public async Task<IActionResult> CreateProduct(ProductDto productDto)
{
    // Authentication and authorization logic here
    // ...
    // Data access logic here
    // ...
    return Ok(StatusCodes.Status201Created);
}


// Prefer:
[HttpPost]
[Authorize]
public async Task<IActionResult> CreateProduct(ProductDto productDto)
{
    await _productService.CreateAsync(productDto);

    return Ok(StatusCodes.Status201Created);
}

 

단일 책임 원칙에 대해 자세히 알아보기 | 관심사 분리

 

 

3. 예외 처리 부족


컨트롤러는 예외를 정상적으로 처리하고 적절한 오류 응답을 반환해야 합니다. 적절한 처리 없이 예외가 클라이언트에 전파되지 않도록 하세요. 예외 필터 또는 미들웨어와 같은 글로벌 예외 처리 메커니즘을 구현하여 오류 처리를 중앙 집중화하세요.

 

// Avoid (Inconsistent error handling or try catch everywhere)
[HttpPost]
public async Task<IActionResult> CreateProduct(ProductDto productDto)
{
    try
    {
        await _productService.CreateAsync(productDto);

        return Ok(StatusCodes.Status201Created);
    }
    catch (ProductValidationException ex)
    {
        return BadRequest(ex.Message);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "An error occurred while creating the product.");
        return StatusCode(StatusCodes.Status500InternalServerError);
    }
}


// Prefer Exception filters or Middleware
[HttpPost]
public async Task<IActionResult> CreateProduct(ProductDto productDto)
{
    await _productService.CreateAsync(productDto);

    return Ok(StatusCodes.Status201Created);
}

 

예를 들어, global exception middleware 를 예시로 든다면,

 

public class ExceptionMiddleware
{
    private readonly RequestDelegate _next;

    public ExceptionMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            // Log the error
            // ...

            await HandleExceptionAsync(context, ex);
        }
    }

    private Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

        var response = new
        {
            StatusCode = context.Response.StatusCode,
            Message = "Internal Server Error"
        };

        return context.Response.WriteAsync(JsonConvert.SerializeObject(response));
    }
}

 

이 예외 미들웨어를 사용하면 HTTP 요청을 처리하는 동안 발생하는 처리되지 않은 예외가 모두 포착되고 일반 오류 메시지와 상태 코드 500(내부 서버 오류)이 포함된 JSON 응답이 클라이언트에 반환됩니다.
 
보다 자세한 오류 정보를 포함하거나 요구 사항에 따라 응답 구조를 수정하도록 HandleExceptionAsync 메서드를 사용자 지정할 수 있습니다.
 
 
이 미들웨어를 ASP.NET Core 웹 API 애플리케이션에서 사용하려면 Startup.cs 파일 또는 Program.cs에 다음 코드를 추가하면 됩니다. 
 
app.UseMiddleware<ExceptionMiddleware>();
 
 

자세히 알아보기 : Exception filters | Middleware

 

 

4. 장시간 실행 작업 (Long-running operations)


컨트롤러에서 오래 실행되는 작업을 수행하지 마십시오. 작업을 즉시 실행하는 대신 백그라운드에서 처리할 수 있도록 대기열에 넣으십시오.

 

// Avoid
[HttpGet]
public async Task<IActionResult> GenerateReport(Report report)
{
    // Long-running operation
    // ...
    // ...

    return Ok(report);
}


// Prefer
[HttpPost]
public async Task<IActionResult> GenerateReport(Report report)
{
    var taskIdentifier = await _messageQueueService.EnqueueAsync(report);

    return StatusCode(StatusCodes.Status202Accepted, taskIdentifier);
}

 

자세히 알아보기 :  Queue service | Background tasks | Hangfire scheduler

 

좀 더 코드를 상세히 알아봤습니다. 

// Import the necessary namespaces
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;

// Assuming Report is a class representing the report data
public class Report 
{
    // Properties of the report class
    // ...
}

// Controller class
public class ReportController : ControllerBase
{
    private readonly IMessageQueueService _messageQueueService;

    public ReportController(IMessageQueueService messageQueueService)
    {
        _messageQueueService = messageQueueService;
    }

    // POST: api/report/generate
    [HttpPost("generate")]
    public async Task<IActionResult> GenerateReport([FromBody] Report report)
    {
        // Enqueue the report for background processing
        var taskIdentifier = await _messageQueueService.EnqueueAsync(report);

        // Return the task identifier to the client
        return StatusCode(StatusCodes.Status202Accepted, taskIdentifier);
    }
}

// IMessageQueueService interface to represent the background task queue service
public interface IMessageQueueService
{
    Task<string> EnqueueAsync(Report report);
}

// Implementation of IMessageQueueService
public class MessageQueueService : IMessageQueueService
{
    // Implement the EnqueueAsync method to enqueue the task for background processing
    public async Task<string> EnqueueAsync(Report report)
    {
        // Perform any necessary background processing here
        // ...
        // ...

        // For demonstration purposes, we can return a simple task identifier as a string
        return Guid.NewGuid().ToString();
    }
}

이 코드에서는 백그라운드 작업 큐 서비스에 대한 컨트랙트를 정의하는 IMessageQueueService 인터페이스가 있다고 가정했습니다. MessageQueueService 클래스는 이 인터페이스를 구현하고, ReportController 클래스는 종속성 주입을 사용하여 생성자를 통해 IMessageQueueService 인스턴스를 주입합니다.

이제 컨트롤러의 GenerateReport 메서드는 요청 본문에서 Report 개체를 수신하고 _messageQueueService를 사용하여 백그라운드 처리를 위해 큐에 넣은 다음 즉시 202 수락됨 상태 코드와 작업 식별자가 포함된 응답을 클라이언트에 반환합니다.

이렇게 하면 클라이언트는 장기 실행 작업이 완료될 때까지 기다릴 필요 없이 자체 처리를 계속할 수 있습니다. 백그라운드 작업은 비동기식으로 처리되므로 서버의 응답성이 향상되고 컨트롤러에서 장기 실행 작업과 관련된 잠재적인 문제를 방지할 수 있습니다.

 

 

 

 

5. 유효성 검사 부족 (Lack of validation)


입력 유효성 검사는 애플리케이션의 무결성과 보안을 보장하는 데 매우 중요합니다. 컨트롤러에서 입력 유효성 검사를 소홀히 하지 마세요. [Required], [MaxLength], custom validation 로직과 같은 모델 유효성 검사 속성을 활용하여 들어오는 데이터를 유효성 검사하세요.

 

 

// Avoid:
[HttpPost]
public async Task<IActionResult> CreateProduct(ProductDto productDto)
{
    // No validation
    await _productService.CreateAsync(productDto);
    return Ok(StatusCodes.Status201Created);
}


// Prefer:
[HttpPost]
public async Task<IActionResult> CreateProduct([FromBody] ProductDto productDto)
{
    if (!ModelState.IsValid)
    {
        return StatusCode(StatusCodes.Status400BadRequest, ModelState);                
    }

    await _productService.CreateAsync(productDto);
    return Ok(StatusCodes.Status201Created);
}

 

자세히 알아보기 :  Model Validation | FluentValidation

 

6. 데이터베이스 직접 액세스


컨트롤러에서 데이터베이스에 직접 액세스하지 마세요. 대신 리포지토리 또는 데이터 액세스 서비스와 같은 추상화 계층을 사용하여 컨트롤러를 특정 데이터 액세스 기술로부터 분리하세요. 이렇게 하면 테스트 가능성과 유지 관리 용이성이 향상됩니다.

 

// Avoid:
[HttpGet]
public IActionResult GetProduct(int productId)
{
    var product = dbContext.Products.Find(productId);
    return Ok(product);
}


// Prefer:
[HttpGet]
public async Task<IActionResult> GetProduct(int productId)
{
    var product = await _productService.GetByIdAsync(productId);
    return Ok(product);
}

자세히 알아보기 :  Repository Pattern or Data Layer

 

8. 인증 및 권한 부여 부족 (Lack of authentication and authorization)


민감한 작업에 대한 인증 및 권한 부여를 구현하세요. 그에 따라 컨트롤러를 보호하세요.

 

// Avoid
[HttpPost]
public async Task<IActionResult> DeleteProduct(int productId)
{
    // No authentication or authorization
    await _productService.DeleteAsync(productId);
    return StatusCode(StatusCodes.Status200OK);
}


// Prefer
[HttpPost]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> DeleteProduct(int productId)
{
    await _productService.DeleteAsync(productId);
    return StatusCode(StatusCodes.Status200OK);
}

자세히 알아보기 :  Authentication and Authorization

 

 

9. 과도한 논리 (Excessive logic)


컨트롤러는 주로 들어오는 요청을 처리하고 응답을 반환하는 역할을 담당해야 합니다. 복잡한 비즈니스 로직을 포함해서는 안 됩니다. 대신 비즈니스 로직은 전용 서비스 클래스나 다른 컴포넌트에 위임하세요.

 

// Avoid:
[HttpGet]
public async Task<IActionResult> GetProducts()
{
    // Complex business logic here
    // ...
    // ...
    return Ok(products);
}


// Prefer:
[HttpGet]
public async Task<IActionResult> GetProducts()
{
    var products = await _productService.GetAllAsync();
    return Ok(products);
}

자세히 알아보기 : Common web application architectures

 

 

10. HTTP verbs  및 RESTful principles 무시


ASP.NET Core의 컨트롤러는 RESTful 아키텍처의 원칙을 준수해야 합니다. 부적절한 HTTP 동사 또는 RESTful 규칙에 맞지 않는 동작을 사용하지 마세요. 리소스에 대해 해당 작업을 수행하려면 적절한 HTTP 동사(GET, POST, PUT, DELETE 등) 를 사용하세요.

 

// Avoid:
public IActionResult DeleteProduct(int productId)
{
    // ...
}


// Prefer:
[HttpDelete("/api/products/{id}")]
public IActionResult DeleteProduct(int productId)
{
    // ...
}

 

자세히 알아보기 : RESTful web API design

 

 

11. 적절한 라우팅 부족 (Lack of proper routing)


컨트롤러가 수신 요청을 처리할 수 있도록 라우팅이 올바르게 설정되어 있는지 확인하세요. 일관되지 않거나 모호한 라우팅 구성을 피하세요. 충돌을 방지하고 라우팅 로직의 명확성을 향상시키기 위해 '[Route]`와 같은 속성을 사용하여 명확하고 명시적인 라우팅 템플릿을 정의하세요.

 

// Avoid:
[HttpGet]
public IActionResult Get()
{
    // ...
}


// Prefer:
[HttpGet("api/products")]
public IActionResult Get()
{
    // ...
}

자세히 알아보기: Routing

 

 

12. 로깅 부족 (Lack of logging)


로깅은 코드 실행 중 중요한 이벤트, 조건 및 오류를 추적하는 데 도움이 되므로 애플리케이션 개발에서 매우 중요한 요소입니다.

 

// Avoid
[HttpPost]
public async Task<IActionResult> CreateProduct(ProductDto productDto)
{
    if (someSimpleCondition)
    {
        // ...
    }

    await _productService.CreateAsync(productDto);
    return Ok();
}


// Prefer
[HttpPost]
public async Task<IActionResult> CreateProduct(ProductDto productDto)
{
     if (someSimpleCondition)
     {
        // ...
        _logger.LogWarning("Warning: Some simple condition is met."); // Log a warning
     }

     await _productService.CreateAsync(productDto);
     return Ok();
}

 

가능한 경우 middleware 또는 action filter 를 사용하여 관련 정보를 캡처하세요.

 

자세히 알아보기 :  Logging | Middleware | Exception filters

 

이러한 일반적인 함정(pitfalls) 을 피함으로써 유지 관리가 가능하고 테스트가 가능하며 API web development 모범 사례를 따르는 컨트롤러를 ASP.NET Core에서 개발할 수 있습니다.

 

읽어주셔서 감사합니다
저는 미디엄 기사를 통해 웹 개발, 커리어 팁, 최신 기술 트렌드에 대한 인사이트를 공유합니다. 저와 함께 흥미로운 주제를 함께 탐구해 보세요. 함께 배우고, 성장하고, 창조합시다!

 


 

번역

 

https://levelup.gitconnected.com/12-bad-practices-to-avoid-in-asp-net-core-api-controllers-3ba52a10954e

 

12 Bad Practices to Avoid in ASP.NET Core API Controllers

Expert Tips for Effective ASP.NET Core API Controller Development

levelup.gitconnected.com

 

 

 

댓글

이 블로그의 인기 게시물

ChatGpt 의 유료결제 영수증 및 청구서 다운로드

ChatGpt 의 유료결제 영수증 및 청구서 다운로드   https://chatgpt.com/  사이트에 접속하며 회원가입을 합니다.   ChatGpt 유료 결제를 위해서는 왼쪽 하단에 있는 " Team 워크스페이스 추가 "를 선택합니다.   https://chatgpt.com/     ChatGPT의 요금제는 세 가지로 나뉩니다:  Free ,  Plus , 그리고  Custom Plan (기업용 요금제). 각 요금제의 특징과 차이점은 다음과 같습니다. 1.  Free Plan (무료 플랜) 사용 모델:  GPT-3.5 제공 기능:  기본적인 질문 응답, 텍스트 생성 접속 가능성:  트래픽이 많을 때는 사용이 제한될 수 있으며, 응답 속도가 느릴 수 있습니다. 제한 사항:  최신 모델이나 고급 기능을 사용할 수 없고, 성능이나 속도 면에서 제한이 있습니다. 2.  Plus Plan (플러스 플랜) 월 요금:  $20 사용 모델:  GPT-4 장점:  더 빠른 응답 속도, 트래픽이 많을 때도 안정적인 접속 가능 차이점:  GPT-4의 향상된 성능으로 더 복잡한 질문이나 고급 작업에도 우수한 결과를 제공합니다. 접속 가능성:  트래픽이 많아도 안정적이며, 더 나은 응답 속도를 제공합니다. 3.  Custom Plan (맞춤형 플랜) 대상:  대규모 기업 또는 특정 요구사항이 있는 고객 요금:  고객의 요구에 따라 맞춤 설정 특징:  기업 맞춤형 기능과 성능을 제공하며, 보안, 데이터 정책, API 액세스와 같은 맞춤형 옵션을 포함할 수 있습니다. 차이점:  대규모 기업에 특화된 기능으로, 추가 지원과 고급 기능 제공이 가능합니다. 주요 차이점 모델 사용:  Free는 GPT-3.5,...

인천국제공항 제1여객터미널에서 일본으로 가는 출국 절차 안내 ✈️

인천공항 제1여객터미널 출국 절차 가이드 (탑승동 이동 및 셔틀트레인 완벽 정리) 공항 도착부터 체크인, 보안검색, 출국심사, 그리고 셔틀트레인을 타고 탑승동으로 이동하는 전체 출국 단계를 빠짐없이 안내합니다. 1. 공항 도착 시간 항공기 출발 3시간 전 제1여객터미널 3층 출국장 도착 권장 2. 탑승구 확인 101~132번 게이트는 셔틀트레인을 타고 탑승동 으로 이동 필수 3. 되돌아오기 불가 셔틀트레인은 편도 이동만 가능하므로 본동 면세품 인도 후 탑승 Step 1. 공항 도착 및 체크인 (3층 일반지역) 항공기 출발 3시간 전 공항 3층 출국장에 도착하는 것을 권장합니다. 셀프 체크인 & 자동 수하물 위탁(Self Bag-Drop): 키오스크에서 모바일·지류 탑승권을 발급받고 전용 카운터를 이용하면 대기시간을 크게 단축할 수 있습니다. 유인 카운터: 여권과 항공권(e-티켓)을 제시하여 좌석 배정 및 위탁 수하물을 처리합니다. Step 2. 출국 전 사전 준비 (환전 및 통신) 환전 수령: 사전 신청한 외화를 3층 또는 지하 1층 환전소·은행 영업점에서 수령합니다. 로밍 및 통신: 통신사 부스에서 데이터 로밍 확인 또는 신청한 USIM/eSIM/와이파이 단말기를 수령합니다. 기타 편의시설: 외투 보관 서비스, 약국, 여행자 보험 창구 이용은 보안검색장 진입 전 일반지역에서 마쳐야 합니다. Step 3. 출국장 진입 및 보안 검색 3층 출국장 게이트(2~5번)로 이동하여 탑승권과 여권을 확인받고 보안검색대로 이동합니다. 주의 (액체류 규정 안내) 기내 반입 액체류는 개별 용기당 100ml 이하, 1인당 총 1L 투명...

엑셀·워드와 호환되는 최신 WYSIWYG 웹 에디터 강추

최신 자료를 기반으로 엑셀과 워드 호환이 잘 되는 상위 10개의 WYSIWYG 웹에디터를 조사하겠습니다. 이 목록은 사용량, 기능, 개발자 선호도를 고려하여 선정되며, 각 웹에디터의 공식 웹사이트 링크도 함께 제공해드리겠습니다.  엑셀·워드와 호환되는 최신 WYSIWYG 웹 에디터 10선 1.  CKEditor 5 오픈 소스 기반의  CKEditor 5 는 높은 완성도의 WYSIWYG 웹 에디터로, Drupal 등 주요 CMS에서 기본 에디터로採용될 정도로 널리 쓰입니다 ( Drupal and CKEditor: a history of advanced content editing | CKEditor | CKEditor ). 풍부한 플러그인과 커스터마이징 기능을 제공하며,  Microsoft Word  문서를 댓글이나 변경 추적 내용까지 포함하여 불러오는 고급 호환 기능도 갖추고 있습니다 ( Wysiwyg Editors Statistics 2025 ). 또한 별도 플러그인을 통해 편집한 내용을 바로  .docx  워드 파일로 내보낼 수 있어 워드 호환성이 뛰어납니다 ( Export to Word | CKEditor 5 Documentation ). 개발자들은 CKEditor 5의 모듈식 설계와 활발한 커뮤니티 지원을 선호하며, 기업용 협업 편집 기능 등의 프리미엄 옵션도 제공됩니다. 2.  TinyMCE TinyMCE 는 오랜 역사와 함께 가장 널리 사용되는 웹 에디터 중 하나로, WordPress에서는 수년간 기본 편집기로採用되어 왔습니다. Joomla, Umbraco, Shopify 등 수많은 CMS에 내장되어 있으며, 전 세계 웹 콘텐츠의 약 40%가 TinyMCE로 작성·출판되고 있다고 합니다 ( Configure TinyMCE for your CMS to rival Wix and WordPress | TinyMCE ). 기본 기능만으로도 강력하지만,...