작성
·
68
·
수정됨
0
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문 전에 다음을 꼭 확인해주세요.
1. 강의 내용과 관련된 질문을 남겨주세요.
2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.
(자주 하는 질문 링크: https://bit.ly/3fX6ygx)
3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.
(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)
질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.
=========================================
[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? 예
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예
3. 질문 잘하기 메뉴얼을 읽어보셨나요?예
[질문 내용]
실무 웹앱의 특정 api 의 연산속도가 너무 느려
ExecutorService 를 활용하여 멀티스레드기법으로 연산속도를 올려볼 계획입니다.
ExecutorService executor = Executors.newFixedThreadPool(5);
위와 같이 스레드풀의 스레드갯수를 5로 설정하려고합니다. 근데 이때 특정 api 에 동시에 5개의 요청이 들어왔다면 executor 객체가 메모리상에 5개가 생성되면서 스레드풀도 자동으로 5개 생성돼 총 25개의 스레드가 생성될것으로 보이는데 이게 서버에 부하를 주지는 않을지 궁금합니다.
아니면 실무에서는 ExecutorService 를 static 싱글톤으로 선언해서 더이상 인스턴스가 생성되지 않게 하고 캐시풀 전략을 사용해야하는건지 궁금하네요.
그리고 ExecutorService 같은건 요청이 몰리는 api 같은데서 사용하는게 아니라 배치작업같은데서 사용해야하는건지도 궁금합니다..
궁금한게 많은 주니어 개발자입니다. 영한님의 답변을 듣고싶네요 ㅠㅠ ai 말고 ㅠㅠ
답변 2
1
안녕하세요. backendman님
지금처럼 요청마다 ExecutorService
를 만드는 것은 좋지 않은 방법입니다.
service() {
ExecutorService executor = Executors.newFixedThreadPool(5);
// 비즈니스 로직 ...
}
위처럼 코드를 매번 API 로직에서 실행한다면, 예를 들어 동시에 5개의 요청이 들어왔을 때 서로 다른 ExecutorService
인스턴스가 5개 만들어지고, 각각이 내부적으로 5개의 스레드를 가지게 됩니다.
즉, 총 25개의 스레드가 (정확히는 5개의 스레드풀 * 5스레드 = 25) 생성되는 셈이죠.
여기서 문제는 풀이 새로 생성되면서 스레드도 각 요청 마다 계속 생성/종료 되므로 성능상 좋지 않습니다.
또, 생성된 ExecutorService
를 요청 처리 후에 명시적으로 shutdown()
또는 shutdownNow()
등을 호출해서 적절히 스레드 풀을 정리해주지 않으면, 계속 리소스가 점유될 수도 있습니다.
결국 API 호출이 있을 때마다 ExecutorService를 새로 만드는 구조는 대부분의 경우 비효율적입니다.
실무에서는 싱글톤으로 사용하거나 또는 스프링을 사용한다면 스레드 풀을 스프링 빈에 등록해서 주입 받는 방식으로 사용하시면 됩니다.
물론 이때 풀은 공용으로 사용하기 때문에 풀의 숫자는 우리 시스템이 받을 수 있는 적절한 숫자로 늘려두셔야 합니다. 예를 들어서 우리 시스템이 해당 요청을 동시에 100개 까지 수용할 수 있어야 한다면 스레드 풀은 500개 정도로 설정해두어야 겠지요? 그리고 여기에 맞는 CPU, 메모리를 사용하셔야 합니다.
감사합니다.
0
안녕하세요, 인프런 AI 인턴입니다.
backendman님께서 질문하신 내용을 기반으로 답변 드리겠습니다.
ExecutorService의 생성 방식과 서버 부하: ExecutorService executor = Executors.newFixedThreadPool(5);
를 사용할 경우, 이 코드는 각 API 요청마다 새로운 ExecutorService
인스턴스를 생성하지 않도록 주의해야 합니다. 일반적으로, 스레드풀은 가능한 한 적은 수의 인스턴스로 유지하는 것이 좋습니다. 따라서, ExecutorService
를 한 번만 생성하고 모든 API 요청이 이를 공유하도록 하는 것이 좋습니다. 이렇게 하면 자원의 효율적인 사용이 보장됩니다.
싱글톤 사용 및 전략: ExecutorService
를 static 싱글톤으로 선언하면 여러 요청 간에 스레드풀을 공유할 수 있습니다. 이렇게 하면 스레드풀이 매번 새로 생성되지 않고, 서버 부하를 줄일 수 있습니다. 필요한 경우 자원을 효율적으로 관리하기 위한 다양한 스레드풀 전략을 고려할 수 있습니다.
ExecutorService의 사용처: ExecutorService
는 배치 작업 뿐만 아니라 많은 수의 동시 요청을 처리해야 하는 경우에도 유용할 수 있습니다. API 요청의 응답 속도를 높이기 위해 멀티스레딩이 필요하다면 사용할 수 있습니다. 다만, 동시성 관련 문제를 예방하고 적절한 리소스 관리를 위해 잘 설계해야 합니다.
추가적으로, 실무에서는 요청량에 기반하여 더 복잡한 로드 밸런싱이나 비동기 처리 기법을 사용할 수도 있습니다. 학습과 실무 환경에 맞게 적절히 대응하여 사용하는 것이 중요합니다.
여기까지 AI 인턴의 답변이었으며, 해당 주제에 대해 더 깊이 있는 답을 원하신다면 영한님의 강의를 참고하시거나 직접 답변을 요청해보시면 더 많은 도움을 받을 수 있을 것입니다.
Spring Boot Task Execution & Scheduling 관련 문서도 참고하시면 도움이 될 수 있으니 확인해보세요.
감사합니다.
영한님 답변 감사합니다! 사랑합니다!