인프런 커뮤니티 질문&답변

유영재님의 프로필 이미지
유영재

작성한 질문수

[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버

컴파일러 최적화

안녕하세요 선생님 Task에 대해서 질문 드립니다.,

작성

·

209

0

전 강의 TASK에 대한 설명

TASK는 워커 쓰레드를 소모하는 것이 아닌 별도의 쓰레드 이다.

쓰레드 풀에 들어가긴 하지만, 애당초 별도의 특이한 쓰레드여서 오래 걸리는 작업일 때, 그때 만들어 주어서 맡기는 것이라고 보면된다.

즉, 워커 쓰레드 풀에서 뽑아서 실행하는 게 아니라 별도 처리를 해주는 것

즉, 쓰레드랑 쓰레드 풀의 양쪽 장점만을 이용하는 것

--------------------

애당초 쓰레드 풀을 사용하는 이유가 쓰레드를 생성하고

소멸하는데 많은 성능을 잡아먹기  때문에 쓰레드를 이용하고

나서 소멸시키지 않고 쓰레드 풀에 넣어놓는 재활용 개념이

이라고 알고 있는데요 

질문 1, 여기서 앞선 강의에서 쓰레드를 최소 1개 최대 5개를

생성해주고 오래 걸리는 작업이 있을 때 그때 테스크를 생성해

서 걔한테 맡기면 워커 쓰레드를 사용하지 않는다.

워커 쓰레드가 아닌 별도의 쓰레드 이다 까진 이해가 가는데

쓰레드 풀 공간을 1 ~ 5까지 할당을 명시적으로 해두었는데

쓰레드 풀에 TASK가 들어가나요? 쓰레드 풀에 별도의

TASK가 들어갈 공간이 동적으로 생성이 되나요?

질문 2. 쓰레드 풀에 TASK가 들어간다면

이 강의의 예제 코드를 보면 쓰레드 풀을 생성하시지 않으셨는

데, 이해가 잘 안갑니다. 어느때 TASK를 써야하고

어느 떄 쓰레드 풀을 사용해야 하는지 ㅠ.ㅠ 

비유를 하자면 한 나라의 군인들 중  관군들이 있고 (쓰레드 풀),

 의병 ( TASK ) 가 있는데,  외적이 쳐들어 왔습니다.

관군들을 소모 시키고 싶지 않아서 그때 마다 외적이 좀 빡셀거

같으면 그때마다 의병( TASK)를 이용하고

관군들을 채용하고 훈련시키는 비용이 꽤 많이 들고

이들을 소모 시키기엔 재정적으로 문제가 있으니까

빡센 일이 닥쳤을 때는 의병(TASK)를 세운다

얘가 죽건 말건 상관없이 버리는 카드 

즉, 의병(TASK)의 소속은  A라는 나라(쓰레드 풀) 이지만

정식 군인 (쓰레드)가 아니다.

이런 개념인거 같은데 

질문이 좀 길어졌는데,  쓰레드 풀을 생성하지 않고

별도로 TASK를 사용을 하는지 

그럼 TASK는 쓰레드 풀에 소속된 것이 아니라는 얘기인데

언제 쓰레드풀을 사용하고 언제 TASK를 사용하는지 여쭤봅니다 

답변 1

2

Rookiss님의 프로필 이미지
Rookiss
지식공유자

TASK는 워커 쓰레드를 소모하는 것이 아닌 별도의 쓰레드 이다
쓰레드 풀에 들어가긴 하지만, 애당초 별도의 특이한 쓰레드여서 오래 걸리는 작업일 때,
그때 만들어 주어서 맡기는 것이라고 보면된다.
즉, 워커 쓰레드 풀에서 뽑아서 실행하는 게 아니라 별도 처리를 해주는 것
즉, 쓰레드랑 쓰레드 풀의 양쪽 장점만을 이용하는 것

->
살짝 오해를 하셨는데 이 부분은 일반 Task가 아니라
옵션을 LongRunning으로 준 특이한 경우에 대한 얘기입니다.


LongRunning을 준 Task는 아주 오래 실행된다는 힌트를 붙여줬기 때문에,
단기 알바 인력 사무소인 ThreadPool에서 꺼내가지 않고
별도의 전담 마크맨이 붙은 셈입니다.
대부분의 경우 LongRunning으로 사용하진 않으니 이 부분은 헷갈리시면 잊으셔도 됩니다.

전체 비유에서 Task랑 Thread를 동일 선상으로 생각하고 계시는데
Task는 '일감', Thread는 '일꾼'으로 생각을 하셔야 합니다.
ThreadPool은 '인력 사무소'의 개념이죠.

MMO 서버에서는 굉장히 연산할 것이 많은데
이걸 단일 쓰레드로 처리하긴 벅차기 때문에
이것을 적당히 분배해서 처리해야 합니다.

첫번째 방법은 일꾼 (Thread)를 직접 고용해서
각자 전담하는 일을 지정하는 (GameLogic, DB, Network 등) 것이고,
실제 강의에선 그렇게 진행됩니다.

그런데 일손이 조금 부족한데 굳이 새로운 일꾼을 채용해서 굴리기 싫다면,
이를 인력 사무소(ThreadPool)에 의뢰를 하는 것도 가능한데요.
의뢰를 할 일감을 Task로 만든다고 볼 수 있겠습니다.

Task이지만 LongRunning 상태로 세팅된 경우라면
뭔가 인력 사무소를 통한 장기 인력 고용? 정도라고 비유할 수 있겠네요.

즉, 의병(TASK)의 소속은  A라는 나라(쓰레드 풀) 이지만 정식 군인 (쓰레드)가 아니다.
이런 개념인거 같은데  질문이 좀 길어졌는데,  쓰레드 풀을 생성하지 않고 별도로 TASK를 사용을 하는지 
그럼 TASK는 쓰레드 풀에 소속된 것이 아니라는 얘기인데
언제 쓰레드풀을 사용하고 언제 TASK를 사용하는지 여쭤봅니다 

->
의병 / 정식 군인 비유는 Task를 [A라는 나라에 주는 의뢰서] 정도로 바꾸면 

적절한 비유입니다.
마지막으로 Task vs Thread 에 관해서는
보통 혼용해서 사용하진 않고 한쪽을 정해서 가는 경우가 많은데
Task가 말이 좋아 외주지 어차피 결국 우리 컴퓨터 CPU (-_-)를 갉아먹는 것이기 때문에
사실상 Thread를 사용하면서 Task를 사용한다고 딱히 성능이 엄청 좋아지진 않습니다.

양쪽 방법의 장단점이 있는데 Thread를 사용하게 되면
직접 일꾼을 고용하는 부담은 있지만,
그래도 정직원으로 영구 고용하다보니 
이런 저런 일을 시키고 데이터를 저장하기에 편리합니다.
단점이라면, Thread를 10개를 사용중이라면 그 모든 쓰레드가 균일하게
일을 하게 유도를 해야 하는데 한쪽으로 일감이 몰리면
최대 성능을 발휘하지 못할 수도 있습니다.

Task는 단순한 일감 단위로 일을 쪼개서 (특정 쓰레드한테 의뢰하는게 아니라)
상시 대기중인 인력들중 아무나 실행을 하게 되니
일감 분배 차원에서 많은 장점이 있습니다.
단점이라면 일감 자체가 엄청 오래 걸리고 힘든 작업이라거나,
애당초 일감 단위로 쪼개기가 애매한 경우 (MMO 서버의 게임 로직 전체 Update 루프 등)
Task로 만드는 것 자체가 애매한 경우가 생길 수도 있습니다.

사실 모던 프로그래밍에서는
Task기반 (+async/await) 방식이 정석적인 방법이지만,
MMO 게임만 놓고 보면 오히려 일감 단위로 분배하는게 애매한 상황이 많아
Thread 기반을 아직까지는 훨씬 더 많이 사용합니다.

유영재님의 프로필 이미지
유영재

작성한 질문수

질문하기