멀티스레딩이란?
하나의 프로세스 안에서 여러 스레드가 동시에 작업을 수행하는 것
CPU는 실제로 한 번에 하나의 일만 하더라도, “매우 빠른 속도로 스레드들을 번갈아가며 실행”해서 동시에 여러 일이 일어나는 것처럼 보이게 함
하지만 CPU가 1코어일 때 설명에 가깝고
요즘 서버는
CPU 8코어
CPU 16코어
CPU 32코어
이다
그래서 스프링 서버는
멀티스레드
+
멀티코어 CPU
그래서 일부 스레드는 진짜 동시에 실행되고
나머지는 대기하거나 스케줄링됨
즉 자바의 경우 멀티스레딩과 병렬구조가 같이 이루어지는 것
다만
멀티스레드 = 소프트웨어 개념
병렬처리 = 하드웨어(CPU 코어) 개념
스프링 서버는
Tomcat Thread Pool
+
CPU Multi Core
이므로
멀티스레드
+
병렬처리
가 동시에 이루어짐
병렬처리란?
여러 CPU나 코어가 동시에 각각의 작업을 “진짜로 동시에 처리하는 것”
진짜 여러 CPU나 코어가 동시에 일하는 것, 속도가 훨씬 빨라짐
JavaScript의 async/await는 동기가 아니라 “비동기 코드를 동기식 문법으로 작성하는 것”
Spring의 @Async는 실제로 다른 스레드에서 실행되는 멀티스레딩
Spring 구조 자체가 스레딩 구조다.
아래 코드만 써도 이미 멀티 스레드 환경
@GetMapping
public String test() {
...
}
왜냐하면 내부에 이런 구조가 있기 때문
Tomcat
├─ thread-1
├─ thread-2
├─ thread-3
└─ ...
위 구조 덕분에 여러 사용자가 각자의 할일을 해도 대기 없이 진행 됨
사용자 A → 상품조회
사용자 B → 로그인
사용자 C → 주문조회
톰캣 내부에서는
Tomcat Thread Pool
thread-1 → 사용자 A 처리
thread-2 → 사용자 B 처리
thread-3 → 사용자 C 처리
만약 스레드가 한개 뿐이라면
A 처리
↓
B 대기
↓
C 대기
JVM
├─ Main Thread
├─ Tomcat Thread Pool
└─ Async Thread Pool
[JVM]
│
└── [Spring Boot]
│
├── [Tomcat]
│ ├ thread-1
│ ├ thread-2
│ └ thread-3
│
└── [Async Executor]
├ thread-1
├ thread-2
└ thread-3
“Spring Boot는 JVM 위에서 실행되는 하나의 애플리케이션이고, Tomcat과 @Async 스레드도 결국 JVM이 관리한다”
실무에서는
* @Async = 작업 위임 표시
* Executor = 작업자 관리소(스레드풀)
* Thread = 실제 일하는 작업자
Tomcat
↓
Thread Pool 보유
사용자 요청
↓
Tomcat Thread 처리
@Async 발견
↓
Executor(Thread Pool)에 작업 위임
별도 Thread가 실행
@Async는 Spring이 제공하는 멀티스레드 실행 기능이다.
주 목적은 무거운 작업을 별도 스레드로 분리하여 Tomcat 요청 처리 스레드를 빨리 반환하는 것이다.
실무에서는 특히
* 이메일 발송
* SMS 발송
* 대용량 엑셀 생성
* 파일 업로드 후 후처리
* 외부 API 호출
* 로그/통계 적재
같은 작업에 많이 사용합니다.
반대로 DB 저장 한 건, 단순 조회 한 건 같은 짧은 작업에는 @Async를 잘 쓰지 않음, 오히려 스레드 전환 비용 때문에 손해일 수도 있음
————— @Async 의 예시
컨트롤러
@PostMapping("/signup")
public String signup() {
userService.save();
emailService.sendAsync();
smsService.sendAsync();
return "OK";
}
EmailService
@Service
public class EmailService {
@Async
public void sendAsync() {
// 이메일 발송
}
}
SmsService
@Service
public class SmsService {
@Async
public void sendAsync() {
// 문자 발송
}
}
여기서 핵심은 @Async
public void sendAsync()
원래는
emailService.sendAsync();
하면
Tomcat Thread-1
↓
sendAsync 실행
스프링에서 @Async해주면
Tomcat Thread-1
↓
Executor에게 전달
↓
즉시 리턴
그리고
Async Thread-1
↓
sendAsync 실행
예를 들어 회원가입시
user 저장
↓
응답
이 로직은 꼭 필요
환영 이메일
가입 축하 문자
로그 적재
이런건 사용자에게 바로 안 보여도 됨
그래서
saveUser();
sendWelcomeMail(); // @Async
sendSms(); // @Async
return OK;
이런식으로 처리
즉 @Async의 목적
✅ 현재 스레드를 빨리 반환
✅ 오래 걸리는 작업을 별도 스레드에서 수행
✅ Tomcat Thread Pool 고갈 방지
그래서 @Async는 “성능 최적화 도구”라기보다는 “작업 분리 도구”에 가깝다고 이해하는 게 가장 정확
Cf.
프론트 async/await
= "전화 올 때까지 기다릴게"
백엔드 @Async
= "이 업무는 다른 직원에게 맡길게"
자바스크립트는 기본적으로 한 줄씩 실행하는 싱글 스레드
JavaScript의 async/await는 동기가 아니라 “비동기 코드를 동기식 문법으로 작성하는 것”
자바스크립트 실행 순서
A
1
B
(응답 대기)
2
async function test() {
console.log("1");
const result = await fetch("/api");
console.log("2");
}
console.log("A");
test();
console.log("B");
* 현재 함수(test)만 잠시 멈춤
* 브라우저는 다른 작업 계속 수행
* 응답이 오면 다시 실행
cf2.
스레드 풀(Thread Pool)은 작업 처리에 사용되는 스레드의 개수를 제한하고, 미리 생성된 스레드들을 관리하는 소프트웨어 디자인 패턴입니다. 작업 요청이 발생하면 대기 중인 스레드를 할당해 처리하고, 완료된 스레드는 소멸하지 않고 다시 풀(Pool)로 돌아가 다른 작업을 대기합니다.
비싼 자원을 미리 생성해두고 재사용한다라는 철학은 같은 두개의 구분

cf3. JVM은
메모리 관리
스레드 관리
GC(가비지 컬렉션)
클래스 로딩
JIT 컴파일
을 담당하는 엄청 큰 존재
실제로 Spring보다 JVM이 더 아래 계층이고 더 큰 개념
'개인공부' 카테고리의 다른 글
| webClient&feignClient with HTTP (0) | 2026.07.08 |
|---|---|
| Claude code의 init과 git init (0) | 2026.06.23 |
| AWS Summit 2026 (0) | 2026.06.17 |
| Aws 인공지능 파트 맛보기… (0) | 2026.05.20 |
| MyBatis, iBatis, JPA 같은 기술들을 무엇이라고 부르는가? (1) | 2025.02.04 |