login register Sysop! about ME  
qrcode
    최초 작성일 :    2012년 06월 27일
  최종 수정일 :    2012년 06월 27일
  작성자 :    whosnail
  편집자 :    whosnail (최 원재)
  읽음수 :    23,523

강좌 목록으로 돌아가기

필자의 잡담~

이번 컬럼은 최원재님이 번역해 주셨으며, ASP.NET MVC에서 비동기 프로그래밍을 하는 방법에 대해 설명하고 있습니다. 컬럼의 원문은 http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4입니다.

본문은 ASP.net의 공식 MVC 관련 자습서인 http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4의 글을 편역한 내용입니다. 마이크로소프트의 공식 번역 문서가 아니며 태오 사이트 MS 컬럼 번역팀에서 번역한 내용입니다. 그렇기에, 일부 오역이나 오타가 존재할 수 있는 점 미리 양해를 구합니다. 원문에 대한 모든 저작권은 마이크로소프트에 있으며, 컬럼 내용과 관련한 질의 문답 역시 원문 사이트에 문의하시는 것을 추천드립니다.

ASP.NET MVC 4에서 비동기 액션 메서드 사용하기

이번 컬럼에서는 무료 도구인 Visual Studio Express 2012 RC for Web을 사용하여 비동기 ASP.NET MVC 웹 어플레이케이션을 만들기 위한 기본 사항을 배우게 될 것입니다. 또한, 원한다면 Visual Studio 2012 RC를 사용해도 무방합니다. 이번 컬럼에서 다루는 내용은 다음과 같습니다.

이번 컬럼에 대한 완전한 예제는 github에서 제공되고 있습니다.

https://github.com/RickAndMSFT/Async-ASP.NET/

ASP.NET MVC 4 Controller 클래스를 .NET 4.5 상에서 사용한다면, Task<ActionResult> 형식의 객체를 반환하는 비동기 액션 메서드를 구현할 수 있습니다. Task로 대변되는 비동기 프로그래밍 개념은 .NET Framework 4에서 소개되었으며, 그렇기에 ASP.NET MVC 4도 Task를 지원합니다. Task라는 것은 Task 형식과 System.Threading.Tasks 네임스페이스 안에 있는 관련 형식들을 말합니다. 또한, .NET Framework 4.5에 들어서는 awaitasync 키워드들을 사용하여 이러한 비동기 지원을 제공하고 있는데요. await와 async 키워드를 사용하면 이전의 비동기 방식보다 훨씬 덜 복잡하게 Task 객체들을 다룰 수 있습니다. await 키워드는 코드의 어떤 부분이 다른 어떤 부분을 비동기로 기다려야 함을 나타내는 문법적 약칭입니다. async 키워드는 Task 기반의 비동기 메서드로 메서드들을 표시할 수 있도록 하기 위한 (컴파일러에게 제공하는) 힌트입니다. await, async 그리고 Task 객체를 조합하여 사용한다면, .NET 4.5 기반에서는 비동기 구현을 훨씬 더 쉽게 할 수 있습니다. 이러한 비동기 메서드들에 대한 새로운 설계 모델을 Task 기반 비동기 패턴 (Task-based Asynchronous Pattern, TAP)이라고 합니다. 이번 컬럼은 여러분이 awaitasync 키워드, 그리고 Task 네임스페이스를 사용한 비동기 프로그래밍에 어느 정도 익숙하다고 가정하고 진행하고 있습니다.

awaitasync 키워드 및 Task 네임스페이스를 사용하는 방법에 대한 더 많은 정보를 얻기 위해서는, 다음 참조들을 확인하십시오.

요청은 스레드 풀에 의해 어떻게 처리되는가

웹 서버 상에서, .NET Framework은 ASP.NET 요청들을 처리하기 위해 스레드 풀을 관리합니다. 어떤 요청이 도착하게 되면, 그 요청을 처리하기 위해서 스레드 풀로부터 하나의 스레드를 얻어내게 됩니다. 동기 방식으로 요청을 처리한다면, 요청을 처리하는 그 스레드는 요청을 처리하는 동안 busy 상태가 되며, 다른 요청을 처리할 수 없습니다.

이러한 동작이 문제가 되지 않는 것은 스레드 풀에서 많은 busy 스레드들을 수용할 수 있도록 충분히 크게 설정할 수 있기 때문입니다. 하지만, 스레드 풀 내의 스레드의 숫자는 제한되어 있습니다(.NET 4.5에서 스레드 숫자의 기본 최대치는 5,000개입니다). 그렇기에, 요청 처리 시간이 오래 걸리고 높은 동시 실행성을 띈 대형 응용 프로그램들에서는 모든 스레드가 busy 상태에 있게 될 수도 있습니다. 이러한 상태를 스레드 기아(thread starvation) 상태라고 부릅니다. 그리고, 이 상태에 도달하면, 웹 서버는 요청을 대기열에 쌓기 시작합니다. 그리고, 대기열이 가득 차게 되면, 웹 서버는 HTTP 503 상태(Server Too Busy)를 반환하며 요청들을 거부합니다. CLR 스레드 풀에 새로운 스레드를 추가하는 작업은 제약적입니다. 그렇기에, 동시성이 집중적이면서(즉, 웹 사이트가 갑자기 수많은 요청을 받는 경우) 처리에 오랜 시간이 걸리는 호출들 때문에 요청을 처리할 수 있는 모든 스레드가 busy 상태라면, 스레드를 추가 삽입하는 비용으로 인하여 응용 프로그램은 더욱 느려질 수 있습니다. 거기에 더해서, 스레드 풀에 추가된 각각의 새 스레드들은 또 다른 부담 요소(1MB의 스택 메모리 같은)도 가지고 있습니다. 그렇기 때문에, 웹 응용 프로그램이 동기적 메서드를 사용하여 높은 대기 시간을 가지는 요청을 처리할 경우 스레드 풀이 .NET 4.5의 기본 최대치인 5,000개의 스레드 개수에 도달하게 되면 약 5GB이상의 메모리를 사용하게 된다고 볼 수 있는데요. 이는 비동기 메서드와 대략 50개의 스레드 만으로 동일한 요청을 처리하는 경우에 비해 대략 5 GB의 추가 메모리를 소모한다고 볼 수 있습니다. 여러분이 비동기 작업을 수행할 경우, 항상 하나의 스레드를 사용하는 것은 아닙니다. 예를 들어, 비동기로 웹 서비스 요청을 수행할 경우, ASP.NET은 async 메서드 호출과 await 사이에 어떠한 스레드도 사용하지 않을 수 있습니다. 매우 높은 대기 시간을 필요로 하는 요청을 처리하기 위해 스레드 풀을 사용하게 되면 높은 메모리 사용량과 서버 장비의 비효율적 사용을 야기할 수 있습니다.

비동기 요청 처리하기

초기화 시에 동시에 대량의 요청을 받거나 (갑자기 동시 사용성이 증가하는) 집중적 부하가 있는 웹 응용 프로그램에서는, 이러한 웹 서비스 호출을 비동기로 처리하여 응용 프로그램의 반응성을 높일 수 있을 것입니다. 하나의 비동기 요청은 동기적 요청과 마찬가지의 처리 시간이 걸립니다. 예를 들어, 어떤 요청이 완료되는데 2초가 걸리는 웹 서비스를 호출한다면, 그 요청이 동기적으로 처리되든 비동기로 처리되든 2초가 걸립니다. 하지만, 비동기 요청의 경우, 스레드는 첫 번째 요청이 종료되기를 기다리면서 다른 요청을 처리할 수 있습니다. 따라서, 비동기 요청은 오랜 시간이 걸리는 호출을 하는 많은 동시적 요청이 요구되는 상황에서 요청이 대기열에 쌓이고 스레드 풀이 증가하는 현상을 완화합니다.

동기적 혹은 비동기 액션 메서드 선택하기

이번 절에서는 동기적 메서드 혹은 비동기 메서드를 언제 사용하는 것이 좋은 지에 대한 가이드라인을 제시할 것입니다. 물론, 이는 단지 가이드라인일 뿐입니다. 비동기 메서드가 성능 향상에 도움이 될 지 여부는 각각의 응용 프로그램에 대해 개별적으로 확인해봐야 합니다.

일반적으로, 다음과 같은 상황에서는 동기적 메서드를 사용하십시오.

  • 메서드가 단순하거나 짧은 시간 안에 완료됩니다.
  • 단순성이 효율성보다 중요합니다.
  • 동작들이 기본적으로 광범위한 디스크나 네트워크 부하를 포함하는 동작이 아닌 CPU 집약적인 동작인 경우. CPU 위주의 동작에 대해 비동기 액션 메서드를 사용하는 경우에는 이득이 없으며 더 많은 부하를 야기할 수 있습니다.

일반적으로 다음과 같은 상황에서 비동기 메서드를 사용하십시오.

  • .NET 4.5 이상의 버전을 사용하고 있으며, 비동기 메서드를 통해 처리할 수 있는 서비스를 호출하고 있습니다.
  • 요청들이 CPU 보다는 네트워크 혹은 I/O에 더 밀접한 관련이 있습니다.
  • 병렬성이 코드의 단순성보다 중요합니다.
  • 사용자들이 오래 걸리는 요청을 취소할 수 있도록 하는 기능을 제공하고자 합니다.
  • 스레드 간의 전환으로 얻는 이득이 스레드 컨텍스트 전환으로 인한 부하보다 더 큰 경우입니다. 일반적으로, 동기적 메서드가 ASP.NET 요청 스레드에 대해 아무 것도 하지 않고 기다리기만 한다면 메서드를 비동기로 만드는 것이 좋습니다. 호출을 비동기로 처리하게 되면, ASP.NET 요청 스레드는 웹 서비스 요청이 완료될 때까지 마냥 기다리면서 시간을 허비하지 않을 것입니다.
  • 테스트에 따르면, 동기적 동작들은 사이트 성능에 있어서 병목지점이 되며 IIS는 이러한 동기적 호출을 비동기로 처리함으로써 더 많은 요청을 처리할 수 있는 것으로 확인되고 있습니다.

다운로드 가능한 예제에서는 어떻게 비동기 액션 메서드들을 효과적으로 이용할 수 있는 지에 대해 배울 수 있습니다. 제공되는 예제에서는 .NET 4.5를 사용하여 ASP.NET MVC 4에서 비동기 프로그래밍을 하는 방법을 간략하게 설명하고 있습니다. 이는 가벼운 데모일 뿐, ASP.NET MVC 비동기 프로그래밍에 대해 참조할만한 아키텍처를 제시할 목적으로 작성된 것은 아닙니다. 예제 프로그램에서는 ASP.NET Web API 메서드들을 호출하고 있는데, 오래 걸리는 웹 서비스 호출로 보이도록 하기 위해서 내부적으로 Task.Delay를 호출하고 있습니다. 대부분의 운영 환경 응용 프로그램들은 비동기 액션 메서드를 사용한다고 해서 확연한 이점이 나타나지는 않을 것입니다.

모든 액션 메서드가 비동기이기를 요구하는 응용 프로그램은 거의 없습니다. 주로, 일부 동기적 액션 메서드들을 비동기 액션 메서드로 변환함으로써 요구되는 업무량 대비 최대의 효율 증가를 얻을 수 있습니다.

예제 응용 프로그램

예제 응용 프로그램은 GitHub 사이트 상의 https://github.com/RickAndMSFT/Async-ASP.NET/ 에서 받을 수 있습니다. 저장소는 3가지 프로젝트로 구성되어 있습니다:

  • Mvc4Async : ASP.NET MVC 4 프로젝트로서 이번 강좌에서 사용된 코드들을 포함하고 있습니다. WebAPIpgw 서비스에 대해 Web API 호출을 하고 있습니다.
  • WebAPIpgw : ASP.NET MVC 4 Web API 프로젝트로서 Products, Gizmos 그리고 Widgets 컨트롤러들을 구현하고 있습니다. WebAppAsync 프로젝트와 Mvc4Async 프로젝트를 위한 데이터를 제공하고 있습니다.
  • WebAppAsync : ASP.NET Web Forms 프로젝트로 다른 강좌에서 사용됩니다.

Gizmos 동기 액션 메서드

다음 코드는 Gizmos의 목록을 보여주는데 사용되는 Gizmos 동기적 액션 메서드를 보여주고 있습니다(이 글에서 gizmo란 가상의 기계적 장치를 말합니다.)

public ActionResult Gizmos()
{
    ViewBag.SyncOrAsync = "Synchronous";
    var gizmoService = new GizmoService();
    return View("Gizmos", gizmoService.GetGizmos());
}

다음의 코드는 gizmo 서비스의 GetGizmos 메서드를 보여주고 있습니다.

public class GizmoService
{
    public async Task<List<Gizmo>> GetGizmosAsync()
    {
        // 구현은 잠시 후에
    }
       
    public List<Gizmo> GetGizmos()
    {
        var uri = Util.getServiceUri("Gizmos");
        using (WebClient webClient = new WebClient())
        {
            return JsonConvert.DeserializeObject<List<Gizmo>>(
                webClient.DownloadString(uri)
            );
        }
    }
}

GizmoService 클래스의 GetGizmos 메서드는 ASP.NET Web API HTTP 서비스에 URI를 넘기고 gizmo 목록 데이터를 반환합니다. Web API인 gizmos, widget 그리고 product 컨트롤러들의 구현부는 WebAPIpgw 프로젝트에 포함되어 있습니다.

다음 이미지는 예제 프로젝트의 gizmos 뷰를 보여주고 있습니다.


출처 : http://i1.asp.net/umbraco-beta-media/39004/Gizmos.PNG

비동기 Gizmos 액션 메서드 작성하기

예제에서는 새로운 async와 await 키워드들(.NET 4.5와 Visual Studio 2012에서 사용 가능합니다)을 사용하여 컴파일러가 비동기 프로그래밍에 필요한 복잡한 변환을 대신 수행하도록 합니다. 즉, 여러분이 C#의 동기적 제어 흐름 구조를 사용하여 코드를 작성하더라도, 컴파일러가 자동으로 스레드들이 대기하지 않도록 하는 callback을 사용하도록 변환을 수행합니다.

다음의 코드에서 Gizmos 동기적 메서드와 GizmosAsync 비동기 메서드를 확인할 수 있습니다. 기존 코드에서 변경된 부분은 노란색으로 강조된 것을 볼 수 있을 것입니다.

public ActionResult Gizmos()
{
    ViewBag.SyncOrAsync = "Synchronous";
    var gizmoService = new GizmoService();
    return View("Gizmos", gizmoService.GetGizmos());
}

public async Task<ActionResult> GizmosAsync()
{
    ViewBag.SyncOrAsync = "Asynchronous";
    var gizmoService = new GizmoService();
    return View("Gizmos", await gizmoService.GetGizmosAsync());
}

GizmosAsync를 비동기로 만들기 위해서 적용된 변경사항은 다음과 같습니다.

  • 메서드가 async 키워드로 표시되어 있습니다. 이는 컴파일러가 메서드 본문 중 일부에 대해 callback을 생성하도록 하고, 반환되는 Task<ActionResult>를 자동으로 생성하도록 합니다.
  • 메서드 이름 뒤에 "Async"를 붙여 넣었습니다. "Async"를 붙여 넣는 것이 필수적이지는 않지만, 비동기 메서드 작성 시 관례입니다.
  • 반환 형식을 ActionResult에서 Task<ActionResult>로 변경하였습니다. Task<ActionResult> 반환 형식은 진행 중인 작업을 표현하고, 메서드의 호출자에게 비동기 작업의 완료를 기다릴 대상 핸들을 제공합니다. 예제의 경우, 호출자는 웹 서비스입니다. Task<ActionResult>는 ActionResult 결과와 관련된 진행 중인 작업을 의미합니다.
  • await 키워드가 웹 서비스 호출에 적용되었습니다.
  • 비동기 웹 서비스 API(GetGizmosAsync)가 호출되었습니다.

GetGizmosAsync 메서드 본문 안에서는 다른 비동기 메서드인 GetGizmosAsync를 호출하고 있습니다. GetGizmosAsync는 Task<List<Gizmo>>를 곧바로 반환하고 있지만, Task<List<Gizmo>>는 데이터가 사용 가능해졌을 때에야 완료될 것입니다. 여러분은 gizmo 데이터를 얻기 전까지는 다른 어떤 작업도 원하지 않기 때문에, 코드는 Task를 (await 키워드를 사용하여) 기다리게 됩니다. await 키워드는 async 키워드로 표시된 메서드 안에서만 사용할 수 있습니다.

await 키워드는 Task가 완료될 때까지 스레드를 대기 상태에 두지 않습니다. 즉, 메서드의 나머지 부분을 Task의 callback으로서 예약해두고, 즉시 반환합니다. await의 대상인 Task가 완료되면, Task는 callback을 호출하고 결국 남겨두었던 메서드의 나머지 부분에 대한 실행을 재개합니다. await와 async 키워드와 Task 네임스페이스를 사용하는 것에 대한 더 많은 정보를 얻기 위해서는 async 참조 부분을 확인하십시오.

다음 코드에서 GetGizmos와 GetGizmosAsync 메서드를 확인할 수 있습니다.

public List<Gizmo> GetGizmos()
{
    var uri = Util.getServiceUri("Gizmos");
    using (WebClient webClient = new WebClient())
    {
        return JsonConvert.DeserializeObject<List<Gizmo>>(
            webClient.DownloadString(uri)
        );
    }
}

public async Task<ListGizmo>>> GetGizmosAsync()
{
    var uri = Util.getServiceUri("Gizmos");
    using (HttpClient httpClient = new HttpClient())
    {
        var response = await httpClient.GetAsync(uri);
        return (await response.Content.ReadAsAsync<List<Gizmo>>());
    }

}

비동기로의 변환은 위의 GizmosAsync에서 이루어진 것과 비슷합니다.

  • 메서드 시그니처를 async 키워드로 표시하였으며, 반환 형식을 Task<List<Gizmo>>로 바꾸었고, Async를 메서드 명에 덧붙였습니다.
  • WebClient 대신 비동기 클래스인 HttpClient 클래스를 사용합니다.
  • await 키워드가 HttpClient 비동기 메서드에 적용되었습니다.

다음 이미지는 비동기 gizmo 뷰를 보여주고 있습니다.


출처 : http://i1.asp.net/umbraco-beta-media/39002/AsyncGizmos.PNG

gizmo 데이터가 브라우저에 보이는 모습은 동기 호출의 결과와 동일합니다. 유일한 차이점은 심한 부하가 있을 때 좀더 나은 성능을 낼 수 있다는 점입니다.

병렬로 여러 동작 실행하기

비동기 액션 메서드가 동기 메서드에 비해 유리한 상황은 여러가지 독립적인 동작들을 실행해야 하는 상황입니다. 밑의 예제의 경우, 동기 메서드인 PWG(Products, Widgets 그리고 Gizmos를 위한 메서드)는 products와 widgets, gizmos의 목록을 얻기 위한 세 가지 웹 서비스 호출의 결과를 보여주는 view를 반환합니다. ASP.NET Web API 프로젝트는 이러한 서비스들을 제공하고 있는데, 지연 상황이나 느린 네트워크를 재연하기 위해 Task.Delay를 사용하고 있습니다. 지연 시간이 500 ms로 설정된 경우, 비동기 메서드인 PWGasync는 완료하기까지 500 ms 조금 넘는 시간이 걸리는데 비해, 동기 메서드인 PWG는 1500 ms 이상의 시간이 걸립니다. 동기 메서드인 PWG는 다음과 같습니다.

public ActionResult PWG()
{
    ViewBag.SyncType = "Synchronous";
    var widgetService = new WidgetService();
    var prodService = new ProductService();
    var gizmoService = new GizmoService();

    var pwgVM = new ProdGizWidgetVM(
        widgetService.GetWidgets(),
        prodService.GetProducts(),
        gizmoService.GetGizmos()
       );

    return View("PWG", pwgVM);
}

비동기 메서드인 PWGasync는 다음과 같습니다.

public async Task<ActionResult> PWGasync()
{
    ViewBag.SyncType = "Asynchronous";
    var widgetService = new WidgetService();
    var prodService = new ProductService();
    var gizmoService = new GizmoService();

    var widgetTask = widgetService.GetWidgetsAsync();
    var prodTask = prodService.GetProductsAsync();
    var gizmoTask = gizmoService.GetGizmosAsync();

    await Task.WhenAll(widgetTask, prodTask, gizmoTask);

    var pwgVM = new ProdGizWidgetVM(
       widgetTask.Result,
       prodTask.Result,
       gizmoTask.Result
       );

    return View("PWG", pwgVM);
}

다음의 이미지는 PWGasync 메서드가 반환하는 view를 보여주고 있습니다.


출처 : http://i1.asp.net/umbraco-beta-media/39007/PWGasync.PNG

취소 토큰 이용하기

Task<ActionResult>를 반환하는 비동기 액션 메서드는 취소가 가능합니다. 메서드는 AsyncTimeout 어트리뷰트를 가질 수 있으며, CancellationToken 매개변수를 부여하면 됩니다. 다음의 코드에서는 GizmosCancelAsync 메서드에 150 ms의 타임아웃을 설정하고 있는 것을 볼 수 있습니다.

[AsyncTimeout(150)]
[HandleError(ExceptionType = typeof(TimeoutException),
                                    View = "TimeoutError")]

public async Task<ActionResult> GizmosCancelAsync(
                       CancellationToken cancellationToken )
{
    ViewBag.SyncOrAsync = "Asynchronous";
    var gizmoService = new GizmoService();
    return View("Gizmos",
        await gizmoService.GetGizmosAsync(cancellationToken));
}

그리고, 다음 코드는 GetGizmoAsync 매서드의 오버로드 버전이며 CancellationToken 매개변수를 부여하고 있습니다.

public async Task<List<Gizmo>> GetGizmosAsync(string uri,
        CancellationToken cancelToken = default(CancellationToken))
{
    using (HttpClient httpClient = new HttpClient())
    {
        var response = await httpClient.GetAsync(uri, cancelToken);
        return (await response.Content.ReadAsAsync<List<Gizmo>>());
    }
}

제공되는 예제 응용 프로그램에서 Cancellation Token Demo 링크를 선택하면, GizmosCancelAsync 메서드를 호출하고 비동기 호출에 대한 취소를 시연할 것입니다.

높은 동시 실행성과 높은 지연이 발생하는 웹 서비스 호출에 대비한 서버 설정

비동기 웹 응용 프로그램의 이점을 극대화 하기 위해서는 기본 서버 설정에 약간의 변화를 줘야 할 수 있습니다. 비동기 웹 응용 프로그램을 설정하고 스트레스 테스트를 수행할 경우, 다음의 사항들을 염두에 두십시오.

  • 윈도우 7, 윈도우 Vista 그리고 모든 윈도우 클라이언트 운영 체제는 동시 요청을 최대 10개로 제한하고 있습니다. 그렇기에, 높은 부하 상태에서 비동기 메서드의 이점을 확인하려면 윈도우 서버 운영 체제가 필요합니다.
  • 권한이 상승된 명령줄 프롬프트에서 IIS에 .NET 4.5를 등록하십시오.

    %windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis -i

    자세한 사항은 ASP.NET IIS 등록 도구 (Aspnet_regiis.exe)[ http://msdn.microsoft.com/en-us/library/k6h9cz8h.aspx]를 참고하십시오.

  • HTTP.sys 큐 대기열의 제한을 기본 값인 1,000에서 5,000으로 증가시킬 필요가 있습니다. 설정이 너무 낮다면, HTTP.sys가 HTTP 503 상태와 함께 요청을 거부하는 모습을 보게 될 것입니다. HTTP.sys의 큐 대기열 제한을 변경하기 위해서는 다음과 같이 하면 됩니다.

  • 여러분의 응용 프로그램이 웹 서비스나 System.NET을 사용하여 HTTP를 통해 뒷 단(backend)의 장치와 통신하고 있다면, connetionManagement/maxconnection 요소를 증가시킬 필요가 있습니다. ASP.NET 응용 프로그램에서, 이 항목은 autoConfig 기능에 의해 CPU 개수의 12배로 제한되어 있습니다. 즉, 이는 4개의 프로세서의 경우 하나의 IP 접점에 대해 최대 12 * 4 = 48개의 동시 연결을 처리할 수 있다는 것입니다. 이 요소는 autoConfig에 종속되어 있기 때문에, ASP.NET 응용 프로그램에서 maxconnection을 증가시키는 가장 쉬운 방법은 global.asax 파일 안에 있는 Application_Start 메서드에서 System.Net.ServicePointManager.DefaultConnectionLimit을 프로그램적으로 설정하는 것입니다. 예제를 보고 싶다면 샘플 예제를 다운로드 하십시오.
  • .NET 4.5에서는 MaxConcurrentRequestsPerCPU의 기본 값인 5,000으로도 충분할 것입니다.


원본 컬럼의 저자는 Rick Anderson입니다. Rick Anderson은 마이크로 소프트의 프로그래머이자 저자로서, ASP.NET MVC, jQuery , Entity Framework에 관심을 가지고 있습니다. 그는 또한 ASP.NET MVC 포럼에서 뛰어난 활동가들과 함께 하는 것을 좋아합니다.

역자 최원재는 현재 CJ E&M에서 근무하고 있습니다. .NET, Silverlight, iOS, Android, Hadoop 등 다양한 분야에 관심을 가지고 있습니다. 최근에는 Diablo 3에 빠져있으며 다른 대부분의 시간은 육아로 정신이 없습니다. 기회가 되면 번역서를 출간하고 싶은 욕심도 가지고 있습니다.

authored by

  taeyo
  2014-03-06(19:39)
캐릭 이미지
이 내용은 ASP.NET 4.5에서도 동일하게 적용됩니다.

더불어, 원래의 강좌도 훌륭하지만 번역 또한 아주 훌륭합니다.
테크데이즈 세미나 이후에 많은 분들이 읽어보시길 희망합니다.
왜냐면, 세미나 때 이 강좌를 홍보할 거라서요 ㅎㅎ

  julboy2
  2015-04-17(13:55)
찾던 자료가 여기에 있었네요..
참..태오사이트 강의만 하나씩 봐도 고수가 될텐데...
흑흑..지금부터라도 열심히 봐야겠네요
좋은강좌 써주셔서 감사합니당


 
 
.NET과 Java 동영상 기반의 교육사이트

로딩 중입니다...

서버 프레임워크 지원 : NeoDEEX
based on ASP.NET 3.5
Creative Commons License
{5}
{2} 읽음   :{3} ({4})