Microsoft MVP성태의 닷넷 이야기
.NET Framework: 346. 닷넷 개발자에게 Node.js의 의미 [링크 복사], [링크+제목 복사]
조회: 30285
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

닷넷 개발자에게 Node.js의 의미

최근 들어, Nginx 웹 서버와 Node.js 등의 소개로 인해 ‘비동기 처리’에 대한 관심이 뜨거워지고 있습니다. 이런 분위기 속에서 마이크로소프트 플랫폼에는 어떤 변화들이 있을까요? 인식하지 못하는 사이에 ‘비동기 처리’는 이미 마이크로소프트 기술 전반에 퍼져있고, 또한 지속적으로 적용되고 있습니다. 과연 어떤 기술들에 ‘비동기 처리’가 관련되어 있는지 살펴보고, C# 5.0에 추가된 비동기 처리의 백미인 async/await 기능을 설명해 보겠습니다.


비동기 처리의 장점

비동기 처리의 장점은 클라이언트와 서버의 응용 프로그램 유형에 따라 달라집니다.

우선, 서버에 비동기를 도입하면 어떤 장점이 있을까요? 기존의 웹 서버들은 대체로 일정 수의 스레드를 가진 ‘스레드 풀’을 만들고 클라이언트의 요청을 받아 처리하는 구조였습니다. 가령, [그림 1]에서는 3개의 스레드 수로 제한된 스레드 풀을 가정한 웹 서버를 보여주는데요.

[그림 1: 스레드 풀만큼의 요청이 온 경우]
async_net_1.png

웹 서버로 동시에 3개의 요청을 받고 있는데, 만약 요청 받은 test.aspx가 5초의 처리 시간을 요구하면 어떻게 될까요? 그다음 접속한 사용자는 이전에 요청된 test.aspx에 할당된 스레드가 자유로워질 때까지 대기하게 되고 이런 현상은 사용자 접속이 몰리는 시간에 심각한 서비스 장애로 나타날 수 있습니다.

그렇다면, 이 문제를 어떻게 해결할 수 있을까요? 여기서 주목해야 할 것은 과연 “test.aspx”라는 웹 페이지가 왜 ‘5초’의 처리 시간을 필요로 하게 되었느냐...라는 점입니다. 이 원인에는 대표적으로 다음과 같은 2가지 시나리오를 생각해 볼 수 있습니다.

  1. CPU를 5초 동안 사용
  2. 외부 호출을 하는 데 4.8초를 사용하고 실제 작업에는 0.2초를 사용

1번의 상황에서는 해당 요청을 처리하는 코드가 잘못 작성되지 않았다면 개선의 여지가 거의 없는 반면, 2번의 상황은 ‘비동기 처리’로 변환하면 처리량(Throughput)을 극적으로 높일 수 있습니다. 그렇다면 현실적으로 웹 서버들이 1번과 2번 문제 중에서 어디에 더 많은 비중으로 문제가 발생하고 있을까요? 필자 개인적으로도 그동안 APM(Application Performance Monitoring) 도구를 개발하고 적용하면서 고객 사이트에서 접해 본 경험으로 볼 때, 대부분의 시나리오는 1번이 아닌 2번에 속했습니다. (어쩌면 Nginx, Node.js가 인기를 끌고 있다는 점이 2번과 같은 사례가 많다는 반증일 것입니다.)

서버는 그렇다 치고, 클라이언트 측에는 비동기가 어떤 의미가 있을까요? 클라이언트 프로그램은 대체로 사용자와의 interactive한 UI를 갖게 되는 것이 보통인데, UI에 관련된 스레드에서 test.aspx에서와 같은 식의 시간이 걸리는 작업을 하게 되면 사용자는 UI 요소와 상호작용을 할 수 없게 되는 문제가 발생합니다. 따라서, 이런 부분을 비동기로 처리한다면 응용 프로그램이 매우 매끄럽게 동작하는 듯한 효과를 갖게 되는 것입니다. (출처가 기억나지 않는데) 실제로 윈도우 8의 스토어 앱은 내부적으로 사용되는 API들 중에 500ms 이상의 시간이 걸리는 것들은 모조리 비동기 버전을 제공하도록 바뀌었다고 합니다. 반응성 향상을 위한 특단의 조치였지요. ^^





닷넷과 비동기 처리

닷넷은 초기부터 필요한 부분의 메소드들은 모두 동기 버전과 비동기 버전을 함께 제공했습니다. ASP.NET 역시 페이지 처리에 대한 비동기 버전을 제공하고 있고, WCF도 마찬가지입니다.

그런 준비가 있었기 때문에 가능했던 것이 하나 있다면, 동기 호출을 완전히 제거한 Silverlight의 출현입니다. 윈도우 폰의 반응성이 타 폰들보다 저 사양에서도 밀리지 않는 성능을 보여줄 수 있었던 주요 요인에는 명시적으로 동기 호출을 제거한 Silverlight의 힘이 컸을 것입니다.

마이크로소프트는 계속해서 닷넷 프레임워크 자체의 병렬 프로그래밍 라이브러리도 발전시키다가, 급기야 C# 5.0에서는 획기적인 비동기 처리 메커니즘을 발표합니다. 바로 async/await 키워드의 도입이 그것입니다. 이것이 왜 획기적인지... node.js와 비교해서 한번 설명해 볼까요? ^^


ASP.NET 에 내장된 기존 방식의 비동기 처리와 node.js의 비교

ASP.NET에서는 1.0부터 이미 IHttpAsyncHandler를 통해서 비동기 처리를 지원하고 있지만, 대부분의 개발자가 해당 인터페이스를 상속받아서 개발하기 보다는 System.Web.UI.Page를 상속하기 때문에 특별한 경우를 제외하고는 사용하지 않게 되었습니다. 이에 마이크로소프트는 ASP.NET 2.0에서 “Asynchronous Page”를 도입하여 기존 System.Web.UI.Page에서도 비동기 처리를 할 수 있는 기반을 추가하게 되는데요.

비동기를 지원하는 웹 페이지는 [코드 1]에서 보는 것처럼 aspx 웹 페이지의 Page 지시자에 Async속성을 true로 지정하고 Being/EndAsyncOperation 메소드를 등록하는 것으로 간단하게 작성할 수 있습니다.

[코드 1: 비동기 처리를 지원하는 ASP.NET 페이지]
<%@ Page Async="true" ... %>

public partial class AsyncPage : System.Web.UI.Page
{
    void Page_Load(object sender, EventArgs e)
    {
        AddOnPreRenderCompleteAsync(BeginAsyncOperation, EndAsyncOperation);
    }

    IAsyncResult BeginAsyncOperation(
       object sender, EventArgs e, AsyncCallback cb, object state)
    {
        return [...].BeginGetResponse(cb, state);
    }
 
    void EndAsyncOperation (IAsyncResult ar)
    {
            [...].EndGetResponse(ar);
    }
}

실제로 이를 사용해서 node.js와 비교하는 것도 괜찮겠지요. ^^ [코드 2]와 [코드 3]은 간단한 파일 읽기에 대한 그 비교 사례입니다.

[코드 2: node.js 로 구현한 비동기 처리 - 파일 읽기]
var http = require('http');
var fs = require('fs');

var server = http.createServer(function(req, res) {

  fs.readFile('./asyncpage.html', encoding='utf-8', function(err, data)
  {
      res.writeHead(200, {
        "Content-Type": "text/html; charset=utf-8"
      });
      res.end(data);
      return;
  });
});

[코드 3: C#으로 구현한 비동기 처리 - 파일 읽기]
FileStream _fs;
byte[] _buffer;

IAsyncResult BeginAsyncOperation(object sender, EventArgs e, AsyncCallback cb, object state)
{
    string currentPath = Server.MapPath("~");
    string path = Path.Combine(currentPath, "AsyncPage.aspx");
    _fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
    _buffer = new byte[_fs.Length];
    return _fs.BeginRead(_buffer, 0, (int)_fs.Length, cb, state);
}

void EndAsyncOperation(IAsyncResult ar)
{
    _fs.EndRead(ar);

    string txt = Encoding.UTF8.GetString(_buffer);
}

각각 readFile 또는 BeginRead와 같은 비동기 I/O 호출을 했던 스레드는 해당 작업들이 완료되었다고 통보해 주는 사이에 다른 작업을 할 수 있는 여유를 갖게 됩니다. node.js/ASP.NET은 그렇게 풀려난 스레드로 "다음 요청"을 처리할 수도 있고, 아니면 비동기 I/O 호출이 완료된 통지가 있는 경우 해당 작업 이후에 할당된 코드, 즉 node.js에서는 readFile에 전달된 function 함수를 부르거나 ASP.NET의 경우에는 EndAsyncOperation을 호출할 수 있습니다.

물론, 보는 바와 같이 비동기에 특화된 node.js가 훨씬 더 간결한 코드를 제공하고 있습니다. 실제로 ASP.NET의 비동기 페이지를 활용하는 사례도 국내에서는 거의 찾아보기 힘들 정도였고... 이 상태라면 닷넷 개발자가 node.js에 관심을 안 가질 수 없었을 것입니다.


남부럽지 않은 .NET의 비동기 처리 - async/await

비동기 처리를 위해 태어난 node.js임에도 불구하고 극복할 수 없는 단점이 하나 있습니다. node.js는 자바스크립트의 익명(anonymous)함수나 클로져(closure)를 사용해서 비동기를 구현하는데, 콜백 함수의 중첩 구조가 복잡해지면 'sequential'한 처리에 익숙한 개발자의 뇌가 받아들이기 힘들 수 있다는 것이지요.

이러한 문제를 마이크로소프트는 컴파일러의 노력으로 극복하게 됩니다. C# 5.0에 추가된 async/await이 바로 오늘의 주인공입니다.

[코드 4: async/await으로 구현한 비동기 처리]
01: public async void Test();
02: {
03:     WebClient wc = new WebClient();
04: 
05:     var htmlText = await
06:         wc.DownloadStringTaskAsync("http://www.microsoft.com");
07: 
08:     htmlText += await wc.DownloadStringTaskAsync("http://www.oracle.com");
09: }

이것이 왜 비동기일까? 하고 의아해 하는 개발자가 있을 것입니다. C# 5.0의 async/await 키워드는 마치 "동기"처럼 개발자에게 코드를 만들도록 허용하고 나머지는 컴파일러가 자동으로 처리해 줍니다.

어떻게 처리하냐고요? C# 컴파일러는 5번째 라인의 await 키워드를 인식하면서 5번째 라인 이후의 코드를 별도로 분리해 냅니다. 바로 그 분리된 코드를 예전의 콜백처럼 자동으로 호출해주는 코드로 만들어 준다는 것이 숨겨진 비밀의 전부입니다.

이렇게 콜백 함수 처리가 없어짐으로써 비동기 처리 개발을 위한 코드의 가독성이 매우 향상됩니다.

async/await의 또 다른 장점은 그 확장이 매우 쉽다는 것입니다. 예를 들어, [코드 4]에서는 WebClient 개체가 명시적으로 DownloadStringTaskAsync라는 비동기 버전의 메소드를 제공해주고 있지만, 이렇게 제공되지 않는 경우까지도 개발자 임의대로 비동기로 처리하도록 확장하는 것이 가능합니다.

예를 들어 볼까요? ^^ 이전에 살펴본 [코드 2]에서 node.js의 readFile 메소드는 비동기 기능을 제공하지요. 닷넷에서는 이와 동일한 기능의 System.IO.File.ReadAllText라는 메소드가 제공되고 있지만 이 메소드는 아쉽게도 비동기 버전이 없습니다. 하지만, async/await에서는 [코드 5]에서와 같이 쉽게 이를 감싸서 비동기 호출을 가능케 하는데, 이러한 확장성에 힘입어 기존에 개발된 닷넷 내/외부 라이브러리들이 모두 비동기 호출로 쉽게 노출될 수 있는 기반이 제공됩니다.

[코드 5: async/await으로 구현한 비동기 처리]

// File.ReadAllText를 이렇게 감싸주면,
Task<string> ReadFile(string filePath)
{
    return Task.Factory.StartNew(() =>
        {
            return File.ReadAllText(filePath);
        });
}

// 사용 시에 이렇게 비동기로 호출하는 것이 가능하다.
var fileText = await ReadFile(filePath);
Console.WriteLine(fileText);  // 이 코드는 컴파일러가 자동으로 비동기 작업이 끝난 후 호출되도록 변경됨

이 외에도 async/await의 장점은 또 있습니다. 바로 비동기 호출의 콜백을 묶을 수 있다는 점입니다. 흔한 예를 한번 들어볼까요? 보통, 인트라넷 웹 사이트의 경우 첫 번째 화면을 보여주기 위해 엄청난 호출들이 발생할 것입니다. 그 사용자의 일정, 메일, 결제 서류 등의 것들이 있는지 첫 화면에서 하나의 결과로 보여주는 것이 보통인데요. 일반적으로 이 작업을 서버 페이지에서 처리하게 되면 순차적으로 각각의 데이터를 조회하는 웹 서비스, DB 호출을 거쳐야만 했습니다. 만약 그 각각의 호출에 3, 5, 2초의 시간이 걸렸다면 그 시간들이 더해져서 사용자에게 보여지기까지는 10초의 시간이 걸렸던 것이지요.

이를 async/awiat으로 해결하면 어떻게 될까요? main.aspx.cs에서 일정, 메일, 결제 서류에 데이터를 비동기로 한꺼번에 결과를 요청하면 가장 오래 걸린 5초에 기준해서 사용자에게 응답을 보여줄 수 있습니다.

이러한 매력적인 코드가 다음의 글에 쉽게 설명되어 있습니다. ^^

Awaiting multiple Tasks with different results
; https://stackoverflow.com/questions/17197699/awaiting-multiple-tasks-with-different-results

어떠세요? 이 정도면 훌륭하지 않나요? ^^




간단하게 정리를 해볼까요?

제가 알기로는 (혹시 틀리면 덧글 부탁드립니다.) 자바에는 비동기 API에 대한 배려가 거의 없습니다. 이런 분위기 속에서 Nginx나 node.js는 획기적인 변화였을 것입니다.

하지만, 닷넷 개발자들에게는 그와 비교해서 더 나은 무기를 손에 들었기 때문에 별다른 의미로 다가오지는 않습니다.




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 6/22/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2012-11-28 01시38분
[Lyn] 자바엔 비동기 API에 대한 배려가 없는것 맞습니다.
컨소시엄에서 치고박고 싸우느라 막상 언어 발전이 기어가고있죠.... 델리게이트 언제추가해줄건데 ㅡ.ㅡ;

Native 서버 개발자인 제 입장에서도 node.js는 원래 당연하게 하던걸 더럽게 느린 방법으로 쬐금 편하게(? 편하긴 한가?) 작업할 수 있다는 것 이상의 의미를 가지진 않습니다

C#의 언어 발전속도는 정말 상상 초월이네요 ㅡㅜ
궂이 await 비스무리한걸 찾아면 Cilk+의 spawn 정도인가 ..
[guest]
2012-11-28 01시48분
Cilk+의 spawn도 await에 비교하기에는 좀 그렇죠. ^^ Cilk+가 예약어로 처리한다는 점을 제외하고는 기능 자체는 System.Threading.Tasks.Task와 비교되어야 할 것 같습니다. ^^
정성태
2012-11-28 02시25분
[psycoder] 좋은정보 감사합니다.^^
[guest]
2012-11-28 04시58분
[steelleg@gmail.com] 정리를 잘해주셔서 쉽게 잘 읽었습니다.
제가 잘 몰라서 질문 좀 드릴려고요.
마지막 예제에서
var fileText = await ReadFile(filePath);
Console.WriteLine(fileText); // 이 코드는 컴파일러가 자동으로 비동기 작업이 끝난 후 호출되도록 변경됨
이렇게 되면...결국 동기처리랑 같은 것이 아닌지요?
이런 경우에도 어떤 다른 이 점이 있을까요?
[guest]
2012-11-28 06시27분
[Lyn] steelleg@gmail.com // 동기처럼 코드를 짜지만 그 중간에 블록이 되지 않고 다른 일을 맘껏 할수 있다는게 장점이죠.

await의 장점은 위에 정성태님이 말씀하신대로 비동기 코드를 동기코드처럼 만들 수 있단겁니다
[guest]
2012-11-28 06시52분
steelleg 님, 그 코드는 다음과 같은 식으로 동작하게 됩니다.

ReadFile(filePath, (fileText) => { Console.WriteLine(fileText); } );

ReadFile은 별도의 스레드에서 동작하게 되고, 그 스레드의 결과물을 2번째 인자로 전달된 콜백 메소드로 전달하면서 후처리가 됩니다. (물론, async/await이 정확히 위와 같이 번역되지는 않습니다.)
정성태
2012-11-29 09시51분
[이성환] APM(IAsyncResult)나 EAP, TAP를 비롯해 직접 스레드를 이용하는 작업까지 굉장히 다양한 비동기 방식이 존재하는데
await 키워드를 만난 컴파일러가 이러한 비동기 패턴을 어떻게 일반화 했는지 궁금해지네요.
제 단순한 수준으로 간단히 생각해보면,
비동기 작업의 최종 리턴 타입을 검사해서 이 결과를 사용하는 변수를 모두 검색한 다음 그와 엮인 코드를 모두 콜백으로 만드는 정도로밖에 떠오르지 않는데
정말 대단합니다.
[guest]
2012-11-29 09시55분
[이성환] 그런데 저같은 초보 개발자들한테는 나중에 이런한 문법이 독이 될 가능성도 살짝 있을 듯 하네요.(특히 디버깅 할 때...)
이미 wc.DownloadStringTaskAsync("http://www.microsoft.com"); 나 Task<string> ReadFile(string filePath) 자체도
닷넷에서 제공해주는 비동기 기법을 사용한 건데 여기에 습관처럼 쓰던 콜백을 생략하고 동기처럼 코딩하다가
await 키워드를 놓치면 리턴없는 루프 속으로 돌진하는 일이 발생할 지도...

근데 Task<string> ReadFile(string filePath) 요 메서드 앞에 async 키워드가 원래 없어도 되는 건가요?
[guest]
2012-11-29 10시28분
첫 번째 질문에 대해서는, await으로 인해 C#은 가벼운 상태 머신으로써 동작하는 타입으로 구현합니다. 이에 대한 자세한 사항은 다음의 글을 보면,

Async/Await FAQ
; https://devblogs.microsoft.com/pfxteam/asyncawait-faq/

아래의 주제에 예제 코드와 함께 자세하게 설명하고 있습니다.

The “Await” Keyword - What does the “await” keyword do?

글쎄요. 얼만큼 독이 될지는 처음 시도이다 보니 두고 봐야겠지요. ^^ 단지 await으로 사용될 수 있는 메소드가 동기 함수와는 완전히 구분되기 때문에 걱정하시는 그런 정도의 문제는 희귀한 사례가 되지 않을까 싶은데요.

그리고, 2번째 질문의 답을 드리면. C# 5.0에서 await는 문맥 키워드의 하나입니다. 원래 키워드는 변수 등의 식별자로 사용하는 것이 불가능하죠. 만약 기존 4.0의 코드에 다음과 같은 코드가 있다고 가정해 보세요.

int await = 5;

만약 C# 5.0의 await가 문맥 키워드가 아니었다면 위의 코드는 5.0으로 컴파일 시에 오류가 발생합니다.

그렇다면 await가 언제 키워드로서 인정되어지느냐 하면 async가 붙은 메소드 내에서만 C#은 키워드로서 await을 인식합니다.

사실 async 키워드는 그 자체로 아무런 효력이 없습니다. 단지 async를 사용함으로써 그 함수 내부에서 사용되는 await 토큰을 키워드로 인식시키는 역활만을 합니다. ReadFile의 정의에 async가 필요 없는 이유는 그 메소드 내부에 await 키워드가 사용되지 않았기 때문입니다.
정성태
2012-11-30 12시59분
[steelleg@gmail.com] https://docs.microsoft.com/en-us/archive/msdn-magazine/2011/october/asynchronous-programming-async-performance-understanding-the-costs-of-async-and-await

비동기가 항상 좋은 것은 아니군요.
참고해 보시면 좋겠네요.
[guest]
2012-11-30 02시12분
IT 업계에서 항상 좋은 기술이 있으면... 혹시 소개해 주시겠어요? ^^
정성태
2012-12-04 04시50분
물론,,, 편파적일 수 있음을 감안하면서.

The Fastest Webserver?
; http://www.webperformance.com/load-testing/blog/2011/11/what-is-the-fastest-webserver/

Node.js vs .Net performance
; http://stackoverflow.com/questions/9290160/node-js-vs-net-performance
정성태
2012-12-22 02시03분
[lancers] 요즘 node.js를 열심히 가지고 놀고 있는데.. ㅎㅎ
근데 차이는 있어요.
node.js는 기본적으로 single-threaded 형태로 context switching을 줄이고 비동기와 이벤트 루프로 바른 형태입니다.
그러다보니 생기는 장점은 동기화 문제 신경 안써도 되고, 사실상 무조건 비동기 형태로 짜게 강제화가 되지요.
하지만, ASP.NET 혹은 WCF 서비스는 기본적으로 멀티쓰레드를 사용한다고 봐야 하고, 비동기를 선택적으로 사용하게 되는 형태입니다.

뭐, 그게 딱히 어느 것이 낫다고 보기 어려워서.. 서로 장단점이 있지요.
용도에 따라 다르지만, 특히 web api 제공 정도로는 node가 확실히 간편하긴 합니다. 워낙 가벼운데다, NPM들 덕도 있고, 개발자 구하기도 쉽고.
[guest]
2012-12-25 03시27분
물론, node.js와 .NET 구현의 세세한 측면을 보면 많은 차이점이 있겠지요. ^^ 단일 스레드를 사용하는 것이나, 제가 알기로는 node.js가 쓸데 없는 API 호출도 많이 없앴다고 어느 표에서 본 것 같습니다.

그냥 이 글에서 다룬 것은 순수하게 "비동기 호출 방식" 면에서 살펴본 것입니다. 사실 동기화 같은 것은 ASP.NET에서조차도 전역 static 변수를 사용하지 않으면 크게 신경 쓴 적은 없으니까요. ^^
정성태
2013-06-20 03시51분
.NET and Node.JS - Performance Comparison (Updated)
; https://www.salmanq.com/blog/net-and-node-js-performance-comparison/
정성태
2013-07-02 12시20분
Visual Studio 2013부터는 async/await에 대한 call stack도 마치 동기 호출을 한 것처럼 보여줍니다. ^^

Debugging Asynchronous Code in Visual Studio 2013- Call Stack enhancements
; https://devblogs.microsoft.com/devops/debugging-asynchronous-code-in-visual-studio-2013-call-stack-enhancements/
정성태
2014-03-13 12시20분
정성태

[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13600정성태4/18/2024250닷넷: 2242. C# - 관리 스레드와 비관리 스레드
13599정성태4/17/2024272닷넷: 2241. C# - WAV 파일의 PCM 사운드 재생(Windows Multimedia)파일 다운로드1
13598정성태4/16/2024286닷넷: 2240. C# - WAV 파일 포맷 + LIST 헤더파일 다운로드1
13597정성태4/15/2024361닷넷: 2239. C# - WAV 파일의 PCM 데이터 생성 및 출력파일 다운로드1
13596정성태4/14/2024719닷넷: 2238. C# - WAV 기본 파일 포맷파일 다운로드1
13595정성태4/13/2024841닷넷: 2237. C# - Audio 장치 열기 (Windows Multimedia, NAudio)파일 다운로드1
13594정성태4/12/20241001닷넷: 2236. C# - Audio 장치 열람 (Windows Multimedia, NAudio)파일 다운로드1
13593정성태4/8/20241049닷넷: 2235. MSBuild - AccelerateBuildsInVisualStudio 옵션
13592정성태4/2/20241202C/C++: 165. CLion으로 만든 Rust Win32 DLL을 C#과 연동
13591정성태4/2/20241165닷넷: 2234. C# - WPF 응용 프로그램에 Blazor App 통합파일 다운로드1
13590정성태3/31/20241071Linux: 70. Python - uwsgi 응용 프로그램이 k8s 환경에서 OOM 발생하는 문제
13589정성태3/29/20241140닷넷: 2233. C# - 프로세스 CPU 사용량을 나타내는 성능 카운터와 Win32 API파일 다운로드1
13588정성태3/28/20241191닷넷: 2232. C# - Unity + 닷넷 App(WinForms/WPF) 간의 Named Pipe 통신파일 다운로드1
13587정성태3/27/20241149오류 유형: 900. Windows Update 오류 - 8024402C, 80070643
13586정성태3/27/20241293Windows: 263. Windows - 복구 파티션(Recovery Partition) 용량을 늘리는 방법
13585정성태3/26/20241094Windows: 262. PerformanceCounter의 InstanceName에 pid를 추가한 "Process V2"
13584정성태3/26/20241046개발 환경 구성: 708. Unity3D - C# Windows Forms / WPF Application에 통합하는 방법파일 다운로드1
13583정성태3/25/20241150Windows: 261. CPU Utilization이 100% 넘는 경우를 성능 카운터로 확인하는 방법
13582정성태3/19/20241408Windows: 260. CPU 사용률을 나타내는 2가지 수치 - 사용량(Usage)과 활용률(Utilization)파일 다운로드1
13581정성태3/18/20241585개발 환경 구성: 707. 빌드한 Unity3D 프로그램을 C++ Windows Application에 통합하는 방법
13580정성태3/15/20241136닷넷: 2231. C# - ReceiveTimeout, SendTimeout이 적용되지 않는 Socket await 비동기 호출파일 다운로드1
13579정성태3/13/20241493오류 유형: 899. HTTP Error 500.32 - ANCM Failed to Load dll
13578정성태3/11/20241628닷넷: 2230. C# - 덮어쓰기 가능한 환형 큐 (Circular queue)파일 다운로드1
13577정성태3/9/20241870닷넷: 2229. C# - 닷넷을 위한 난독화 도구 소개 (예: ConfuserEx)
13576정성태3/8/20241543닷넷: 2228. .NET Profiler - IMetaDataEmit2::DefineMethodSpec 사용법
[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...