Task<IActionResult> Task<ActionResult<T>>

냐옹·2024년 2월 13일
0

asp.net core

목록 보기
2/6

ASP.NET core로 컨트롤러 api를 만들면서
반환형으로 이것들을 자꾸 쓰더라.

그런데 메서드에서 Task<ActionResult<T>> 를 그냥 쓰면 되는데 왜 이걸 쓸까.. 생각해보았는데 잘 모르겠는거..

인터페이스 반환형보다 그냥 쌩이 좀 더 크고 쓸데 없는 것도 포함이 되어있더라도, 그냥 쓰면 될텐데 라는 생각을 잠깐 했다. ( 잘못된.. )

Task<IActionResult>

  1. IActionResult를 반환하는 비동기 액션 메서드를 나타낸다.
  2. 이는 다양한 종류의 HTTP 응답을 생성할 때 유연성을 제공한다.
    • 어떤 유연성?
      - NotFound(), Ok(), BadRequest(), 등과 같은 다양한 결과를 비동기적으로 반환할 수 있다.
  3. 이 타입은 특히 메서드가 여러 종류의 결과를 반환할 수 있을 때 유용하다.

Task<ActionResult<T>>

  1. ActionResult<T>의 비동기 버전으로, T타입의 데이터와 함께 http 응답을 반환할 수 있다.
  2. 이것은 IActionResult의 모든 기능을 포함하면서도 특정 타입의 데이터를 반환할 수 있는 장점이 있다.
  3. 이 타입을 사용하면 타입 안정성이 보장되고, 클라이언트에 특정 타입의 데이터를 명확하게 전달할 수 있다.

사용 예시

[HttpGet("{id}")]
public async Task<ActionResult<MyDataType>> GetMyData(int id)
{
    var myData = await _myDataService.FindAsync(id);
    if (myData == null)
    {
        return NotFound();
    }
    return Ok(myData);   
}

이 코드를 보면 어떤 id에 대해서 GET요청을 보내는데,
이 경우에는 반환을 Task<ActionResult<MyDataType>>으로 하고 있다.
그래서 보면 먼저 _myDataService라는 컨텍스트에서 해당 객체를 찾고 없으면 Not Found() 있으면 Ok()를 보내고 있다.

왜 여기에서는 Task<IActionResult>가 아니라 `Task를 반환하는 걸까?

몇가지 예시들을 더 보자 ( 사실 이걸로 이해가 잘 안돼 )


예시 1 (Task<IActionResult>)
[HttpGet("{id}")]
public async Task<IActionResult> GetItem(int id)
{
    var item = await FindItemAsync(id);
    if (item == null)
    {
        return NotFound();
    }
    return Ok(item);
}

예시 2 (Task<IActionResult<T>>)
[HttpGet("{id}")]
public async Task<ActionResult<MyItem>> GetMyItem(int id)
{
    var myItem = await FindMyItemAsync(id);
    if (myItem == null)
    {
        return NotFound();
    }
    return myItem; // 여기서 Ok(myItem)을 사용하지 않아도 됩니다. ActionResult<T> 덕분에 자동으로 처리됩니다.
}

예시를 살펴보았는가?

  • 예시2의 코드 하단을 보면 다음 문구가 눈에 보인다.
    return myItem; // 여기서 Ok(myItem)을 사용하지 않아도 됩니다. ActionResult<T> 덕분에 자동으로 처리됩니다.

Task<ActionResult<T>> 반환 타입을 사용하는 경우에, asp.net core의 mvc 프레임워크는 ActionResult<T>의 특별한 처리를 통해서 개발자가 명시적으로 Ok메서드를 호출하지 않아도 T타입의 객체를 반환할 수 있게 한다. 이것은 ActionResult<T> 타입이 T타입의 결과를 자동으로 HTTP 200 OK 응답으로 래핑하기 때문이다.

따라서 개발자는 데이터를 직접 반환할 수 있으며 이 경우에 프레임워크가 알아서 적절한 응답을 구성한다.

아래 코드를 보면 이해가 쉬울 것

[HttpGet("{id}")]
public async Task<ActionResult<MyItem>> GetMyItem(int id)
{
  var myItem = await FindMyItemAsync(id);
  if (myItem == null)
  {
      return NotFound(); // 직접 HTTP 404 응답을 반환
  }
  return myItem; // HTTP 200 OK 응답에 myItem을 자동으로 포함
}

보면 여기는 또 Ok(myItem) 하고 있지 않고 직접 반환하고 있다.

그래서 으음 싶지만..
장점을 보자면
1. 타입 안정성이 제고되고
ㄴ 반환되는 데이터의 타입이 컴파일 타임에 명확하게 정의되어있음을 의미

  1. 명확한 API 문서 작성이 가능하고
    ㄴ Swagger 같은 api 문서를 사용할때 ActionResult<T>를 반홚 타입으로 사용하면, 생성된 API 문서에서 해당 액션 메서드가 T타입의 데이터를 반환한다고 명시적으로 표시된다.
    ( 아 이건 인정 )

  2. 직관적인 코드가 가능하다.
    ActionResult<T>를 사용하면, 성공적인 경우에는 자동으로 HTTP 200 OK 응답과 함께 T타입의 데이터를 반환하고, 에러가 발생했을 때는 다른 종류의 ActionResult를 반환할 수 있다. (Not Found() 404라던지 ) . 이러한 방식이 코드를 좀 더 읽기 쉽게 만든다고 한다.

    결론!

    그냥 ActionResult<T>쓰자.

0개의 댓글