"스레드를 많이 쓸수록 항상 성능이 좋아질까요?" 기술 면접에서 물어본다면?
개발을 하다 보면 멀티스레딩(multi-threading)에 대한 이야기를 많이 듣게 된다.
그런데 "스레드를 많이 쓰면 항상 성능이 좋아질까요?" 라는 질문을 받으면 쉽게 답하기 어려울 수도 있다.
이 질문은 기술 면접에서도 자주 등장하는데, 면접관이 이런 질문을 하는 이유는 단순히 "정답"을 원하는 게 아니라,
내가 알고 있는 개념을 논리적으로 설명할 수 있는지, 문제를 여러 관점에서 생각할 수 있는지 확인하기 위해서다.
그래서 이번 글에서는 이 질문에 대해 어떻게 답변할 수 있을지 초보자의 시선에서 하나씩 정리해보자!!!
처음 떠오르는 생각은 이렇다.
"스레드를 많이 쓰면 동시에 더 많은 작업을 실행할 수 있으니까 성능이 좋아지겠지?"
이 말도 일리가 있지만 항상 그런 것은 아니다.
여기에는 암묵적인 전제가 깔려 있다.
예를 들어서
웹 서버에서 여러 사용자의 요청을 동시에 처리하는 경우 → 스레드를 여러 개 사용하면 확실히 성능이 좋아질 가능성이 크다.
하지만 어떤 작업은 반드시 순차적으로 실행되어야 한다면? → 여러 개의 스레드를 써도 효과가 없다.
즉, 어플리케이션의 특성에 따라 스레드를 늘리는 것이 효과적인지 따져봐야 한다는 것!
스레드가 많아지면 또 다른 문제가 생긴다.
바로 컨텍스트 스위칭(context switching) 비용.
👉 하나의 CPU 코어에서 실행되던 스레드가 다른 스레드로 변경될 때 발생하는 작업.
CPU는 한 번에 여러 개의 스레드를 동시에 실행할 수 없기 때문에
한 스레드를 멈추고(Context 저장) 다른 스레드로 전환(Context 로드)하는 과정이 필요하다.
이 과정에서도 CPU 자원이 사용되는데, 이걸 "오버헤드(overhead)" 라고 한다.
즉, 스레드를 무한정 늘리면:
처음에는 여러 작업을 동시에 처리할 수 있어 좋아질 수도 있지만,
너무 많아지면 컨텍스트 스위칭 비용이 커져서 오히려 성능이 떨어질 수도 있다.
그렇다면 언제 스레드를 많이 써도 되는 걸까?
어플리케이션의 특성에 따라 다르다.
정리
✔ 스레드를 많이 쓴다고 무조건 성능이 좋아지지는 않는다!
✔ 어플리케이션의 특성에 따라 효과적인 스레드 개수가 다름
✔ CPU-bound 작업 → 코어 개수와 비슷한 수준으로 설정하는 게 유리
✔ I/O-bound 작업 → 코어 개수보다 더 많은 스레드를 사용하면 성능 향상 가능
✔ 하지만 너무 많은 스레드는 컨텍스트 스위칭 비용 때문에 오히려 성능 저하를 초래할 수 있음
이번에는 context switching 관점에서 생각해보자.
코어에서 실행되던 스레드가 다른 스레드로 바뀔 때마다 context switching을 하게 된다.
이런 스위칭 작업 또한 CPU 코어에서 실행되는 작업이다.
즉, 코어에서 스위칭 작업을 처리하는 동안에는 어플리케이션 코드가 실행되지 않는 것!
이때 스위칭 작업을 위해 소비되는 CPU time은 어플리케이션과 직접적인 관련은 없지만 멀티스레딩으로 동작하기 위해 필요하기 때문에 이런 것을 overhead, 간접 비용이라고 부른다.
이런 지식들을 가지고 생각해보면 CPU의 코어 수는 고정되어 있는데 스레드 수를 계속 늘리면
각 코어에서 경합하는 스레드 수가 점점 많아질 거고, 그러면 overhead도 더 많아질 것 같다, 라는 생각이 든다.
결국 스레드 수를 계속 늘리면 어느 순간에는 overhead 때문에 성능 면에서도 한계에 부딪칠 것 같다, 라는 생각이 들게 된다.
그렇다면 다른 관점에서 생각해보자.
CPU bound 어플리케이션은 CPU를 많이 쓰기 때문에 코어 수와 비슷한 수준 이상으로 스레드 수를 늘려봤자 별 이점이 없다.
오히려 각 코어에서 경합하는 스레드 수가 많아질수록 context switching 때문에 overhead만 더 많아져서 성능에 안좋은 영향을 주게 된다.
반면에 I/O bound 어플리케이션은 I/O 작업이 많기 때문에 CPU가 놀고 있는 상황이 많다.
이런 상황에서는 코어 수보다 두 배, 세 배, 혹은 그 이상으로 스레드 수를 늘려주는 것이 overhead가 좀 더 늘긴 해도 코어들을 더 효율적으로 쓸 수 있기 때문에 성능 면에서는 이점이 더 크다.
하지만 이 경우에도 너무 많은 스레드를 쓰게 되면 오히려 성능에 악영향을 줄 수 있겠죠?
어쨌든 이렇게 어플리케이션을 CPU bound, I/O bound로 구분하고, context switching의overhead와 연결시켜서 스레드 수와 성능의 상관 관계를 종합적으로 설명한다면 관련 지식들이 논리적이고 설득력 있게 정리된 느낌을 주기 때문에 좋은 인상을 줄 수 있다.
이 외에도 여러 관점에서 볼 수 있는데, 결국 핵심은 내가 얼마나 알고 있는지, 알고 있는 지식들을 논리적으로 전개해서 적절한 판단을 할 수 있는지가 중요한 포인트가 된다.
나는 생각을 많이 하지만 이걸 논리정연하게 설명을 하는게 부족하다.
면접을 볼 때는 인상과 더불어 말을 얼마나 조리있게 하느냐도 중요하니 내가 생각한 것들을 말로 내뱉는 연습도 필요할 것 같다.
그리고 어떤 관점에서 보느냐에 따라 내가 생각하는 것들이 달라질 수도 있으니 다양한 관점에서 볼 수 있는 능력도 가져야 하지 않을까?
우선 지식이 더 필요하겠지만...ㅠㅠ