일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- React
- JavaSpring
- designpatterns
- 티스토리챌린지
- Spring
- typescript
- springboot
- javascript
- 오블완
- component
- css
- Gin
- hook
- react-hook-form
- go
- satisfiles
- ReactHooks
- tanstackquery
- Redux
- 웹애플리케이션서버
- RTK
- backend
- golang
- JPA
- java
- Chakra
- storybook
- test
- frontend
- Today
- Total
bkdragon's log
스레드 본문
스레드는 프로세스 내에서 실행되는 가장 작은 단위의 작업이다. 프로세스는 운영체제에서 실행 중인 프로그램을 의미하며, 각 프로세스는 최소 하나 이상의 스레드를 포함한다. 스레드는 같은 프로세스 내에서 자원을 공유하며, 독립적으로 실행될 수 있다. 프로세스가 하나의 스레드를 가지면 싱글 스레드 프로세스이고, 여러 개의 스레드를 가지면 멀티 스레드 프로세스이다.
메인 스레드
메인 스레드는 프로그램이 시작될 때 자동으로 생성되는 스레드로, 프로그램의 기본 작업을 수행한다. 메인 스레드는 프로그램의 주요 작업을 수행하며, 프로그램의 종료와 함께 종료된다.
스레드의 사용이유
스레드는 주로 병렬 처리를 위해 사용된다. 예를 들어, 대규모 데이터 처리를 할 때 여러 스레드를 사용하여 작업을 분할하고 동시에 처리함으로써 처리 속도를 높일 수 있다. 또한, 사용자 인터페이스(UI)와 백그라운드 작업을 분리하여 UI의 응답성을 유지할 수 있다.
스레드와 비동기의 관계
스레드는 비동기와도 밀접한 연관이 있다. 비동기란 특정 작업이 끝나지 않고 다른 작업을 수행할 수 있는 것을 의미하는데, 멀티스레딩은 이 비동기를 구현하는 수단중 하나라고 볼 수 있다.
자바스크립트: 자바스크립트는 싱글 스레드 언어로, 한 번에 하나의 작업만 수행할 수 있다. 이벤트 루프와 콜백 큐를 사용하여 비동기 처리를 통해 마치 여러 작업을 동시에 수행하는 것처럼 보이게 할 수 있다. 자바스크립트는 비동기를 구현한 수단이 멀티스레딩이 아닌 것이다.
자바: 자바는 멀티스레드 언어이다. 자바에서는
Thread
클래스나Runnable
인터페이스를 사용하여 스레드를 생성하고 관리할 수 있다. 자바는 비동기를 멀티스레딩으로 구현한다.
Spring의 요청 처리 방식
스프링은 기본적으로 요청 당 하나의 스레드를 사용하여 처리한다. 이는 스프링 프레임워크의 기본 설정이다. 스프링은 톰캣의 스레드 풀에서 스레드를 할당받아 사용하며, 이를 통해 여러 요청을 동시에 처리할 수 있다.
스레드 풀은 미리 생성해둔 스레드들을 재사용하는 방식으로 톰캣이 이를 관리한다. (application.yml 혹은 application.properties에 설정)
# 적절한 스레드 풀 크기 설정이 중요
server.tomcat.threads.max=200 # 최대 동시 처리 가능 요청 수
server.tomcat.accept-count=100 # 대기 큐 크기
하나의 HTTP 요청은 하나의 스레드가 처리하며, 톰캣의 스레드 풀에서 스레드를 할당받아 사용한다.
[클라이언트 요청] → [톰캷 스레드 풀] → [스레드 할당] → [요청 처리] → [스레드 반환]
사용자 A의 요청 → 스레드 1이 처리
사용자 B의 요청 → 스레드 2가 처리
사용자 C의 요청 → 스레드 3이 처리
동시 요청이 스레드 풀 크기를 초과하면 대기 큐에서 대기한다. 대기 큐마저 가득 차면 connection refused 에러 발생한다. 요청 처리 중 블로킹 작업이 있으면 해당 스레드는 다른 요청을 처리할 수 없다.
Spring 비동기 처리
앞서 설명했듯 스프링은 기본적으로 요청 당 하나의 스레드를 사용하여 처리한다. 비동기 처리를 위해서는 별도의 스레드를 사용해야 한다.
특정 유저에게 메일을 보내는 작업을 예시로 들어보자.
@Service
public class UserService {
// 기본적으로 톰캣 스레드풀의 스레드가 처리
public void processUser(Long userId) {
// 1. 사용자 정보 조회
User user = findUser(userId);
// 2. 이메일 발송 (별도 스레드가 처리)
emailService.sendEmailAsync(user);
// 3. 즉시 응답 반환 (이메일 발송 완료 대기 없음)
return;
}
}
@Service
public class EmailService {
@Async
public CompletableFuture<Void> sendEmailAsync(User user) {
// 별도 스레드에서 이메일 발송 처리
return CompletableFuture.runAsync(() -> {
sendEmail(user);
});
}
}
[요청] → [톰캣 스레드 풀에서 스레드 할당] → [해당 스레드가 주요 로직 처리] → [응답]
↓
[@Async]
↓
[비동기 스레드 풀에서 새로운 스레드 할당] → [해당 스레드가 비동기 로직 처리]
@Async가 붙은 메서드는 비동기 스레드 풀에서 스레드가 할당되어 처리된다. 원래 스레드는 비동기 적업을 수행하는 새로운 스레드의 작업 완료를 기다리지 않고 응답을 반환한다.
동시성 문제
멀티스레드 환경에서 동시성 문제는 여러 스레드가 동시에 공유 자원에 접근하는 경우 발생할 수 있다. 이를 해결하기 위해서는 동시성 제어 기법을 사용해야 한다.
자바에서는 synchronized
키워드, Lock
인터페이스, Semaphore
등을 사용하여 동시성을 제어할 수 있다. 이 부분은 다음 글에서 다뤄보겠다.
정리
스레드가 무엇인지, 그리고 내가 자주 사용하는 언어에서 어떻게 사용되는지 살펴보았다. 자바스크립트는 크게 신경 쓸 필요가 없고 스프링에서는 잘 추상화가 되어있어서 어렵지 않게 활용할 수 있을 것 같다.
'concept' 카테고리의 다른 글
ws와 was (0) | 2024.10.26 |
---|---|
에러 헨들링에 관하여 (0) | 2024.06.14 |
변신하는 Form (1) | 2023.10.18 |
CSS 프레임워크로 atomic design pattern 적용하기 (0) | 2023.09.02 |
[Redux-toolkit] 비동기 처리하기 (0) | 2023.09.01 |