쓰레드란?

2026. 1. 29. 16:16·Java

 

멀티스레드를 공부하다 보면 항상 막히는 지점이 있다.
프로그램 / 프로세스 / 스레드가 각각 뭔지 “말로는 아는 것 같은데”, 막상 코드나 그림으로 나오면 갑자기 섞여버린다.

그래서 이번에는 개념을 실행 흐름 기준으로 정리해보려고 한다.

핵심은 이거다.

프로그램(디스크) → 실행하면 프로세스(메모리) → 그 안에서 일하는 흐름이 스레드(실행 단위)

 

 

출발점: 프로세스(Process)와 쓰레드(Thread)

프로세스란?

실행 중인 프로그램을 프로세스라고 부른다.

프로그램 파일(.exe, .jar)은 디스크에 “저장된 상태”일 뿐이고,
그걸 실행해서 메모리에 올라가고 CPU를 할당받아 돌아가는 상태가 되면 프로세스가 된다.

여기서 중요한 성질이 하나 있다.

  • 프로세스는 보통 자기만의 메모리 공간(주소 공간)을 가진다.
  • 그래서 프로세스끼리는 기본적으로 서로 간섭이 어렵다.
  • 다른 프로세스의 메모리를 마음대로 만질 수 없고, 뭔가 주고받으려면 IPC 같은 별도 수단이 필요하다.

한마디로,

프로세스는 “실행 단위”이면서 “자원(메모리) 단위”다.

 

쓰레드란?

쓰레드는 프로세스 안에서 일을 수행하는 실행 흐름(flow) 단위다.

  • 한 프로세스 안에 쓰레드가 1개면 싱글 쓰레드
  • 여러 개면 멀티 쓰레드

비유로 정리하면 이게 가장 깔끔하다.

  • 프로세스 = 공장(자원 묶음, 큰 틀)
  • 쓰레드 = 공장 안의 작업 라인(실행 흐름)

 

 

멀티태스킹 / 멀티프로세싱 / 멀티쓰레딩

여기서 헷갈리는 이유는 “멀티”라는 말이 다 비슷하게 들리기 때문이다.
근데 실제로는 기준이 다르다.

멀티태스킹

운영체제가 여러 작업을 동시에 하는 것처럼 보이게 만드는 능력이다.

CPU 코어가 1개여도, OS가 아주 빠르게 번갈아 실행시키면 사람 눈에는 동시에처럼 느껴진다.

멀티프로세싱

프로세스가 여러 개 떠서 각각 작업을 수행하는 것.

예: 크롬, 카톡, IDE, 음악 플레이어를 동시에 실행하면
각각이 별개의 프로세스로 돌아간다.

멀티쓰레딩

하나의 프로세스 내부에서 쓰레드를 여러 개 만들어 일을 나누는 것.

예: 한 프로그램(한 프로세스) 안에서

  • UI 쓰레드(화면/입력)
  • 작업 쓰레드(다운로드/연산)
  • 로그 쓰레드

처럼 역할을 나누는 방식이다.

 

 

멀티쓰레드의 장점 — “왜 쓰레드로 나누냐”에 대한 설득

멀티쓰레드의 장점은 결국 “프로그램이 현실에서 겪는 문제”를 해결하기 위해 나온다.

1) 응답성(Responsiveness)

오래 걸리는 작업을 메인 흐름(UI 처리)에서 같이 해버리면
프로그램이 멈춘 것처럼 보인다.

그래서 무거운 작업은 작업 쓰레드로 빼고,
메인 쓰레드는 사용자 입력/화면 갱신을 계속 담당하게 만든다.

UI가 멈추는 문제를 막기 위해 “일을 분리”하는 것.

2) 자원 공유가 쉽다

같은 프로세스 안의 쓰레드는 힙(Heap) 같은 메모리를 공유한다.

즉 같은 데이터 구조를 같이 보고 같이 업데이트할 수 있어 협업이 쉽다.
다만 이 장점이 그대로 단점(동기화 문제)로 이어진다.

3) 비용이 상대적으로 싸다

프로세스를 여러 개 만들면 자원이 독립적으로 잡히고 관리 부담이 크다.

쓰레드는 프로세스 자원을 공유하기 때문에, 일반적으로 생성/전환 비용이 프로세스보다 낮다.

 

 

멀티쓰레드의 단점 — “좋은데 어려운 이유”

멀티쓰레드는 좋다. 근데 어려운 이유가 명확하다.

1) 동기화(Synchronization) 문제

여러 쓰레드가 같은 데이터(공유 자원)를 동시에 만지면

  • 값이 꼬이거나
  • 업데이트가 사라지거나(lost update)
  • 중간 상태를 다른 쓰레드가 읽어버리는

상황이 생긴다.

그래서 lock, synchronized, atomic, concurrent collection 같은 개념이 필요해진다.

2) 디버깅/재현이 어렵다

단일 쓰레드는 실행 순서가 비교적 예측 가능하지만,
멀티쓰레드는 스케줄러가 실행 순서를 매번 다르게 만들 수 있다.

그래서:

  • 어제 되던 게 오늘 안 됨
  • 가끔만 터짐

같은 문제가 나온다.

3) 교착상태(Deadlock)

서로 락을 잡고 기다리면 영원히 진행이 안 되는 상황이 생길 수 있다.

멀티쓰레드를 “설계”로 다뤄야 하는 이유가 여기서 확 드러난다.

 

 

자바에서 쓰레드를 만드는 2가지 방식

(1) Thread 클래스를 상속해서 만들기

  • Thread를 상속한 클래스를 만들고 run()을 오버라이딩한다.
  • 객체 생성 후 start() 호출

핵심은 이거다.

  • run() = “쓰레드가 할 일”
  • start() = “그 일을 새 실행 흐름으로 출발시키는 트리거”

(2) Runnable 인터페이스를 구현해서 만들기

  • Runnable은 run() 하나만 가진 작업 단위 인터페이스
  • new Thread(runnable).start()로 실행

Runnable을 많이 쓰는 이유는

  • 자바는 단일 상속이라 Thread 상속을 써버리면 다른 상속이 막힘
  • 그래서 “작업 내용은 Runnable로 분리”하고 “실행은 Thread가 담당”하는 구조가 더 유연함

 

 

start()와 run()의 차이 — 멀티쓰레드 이해의 핵심

run()을 직접 호출하면?

그냥 일반 메서드 호출이다.

  • 현재 쓰레드(보통 main)가 run 내용을 그대로 실행
  • 새 쓰레드가 생기지 않음
  • 새 실행 흐름이 생기지 않음

start()를 호출하면?

JVM/OS가 새 실행 흐름(새 쓰레드)을 준비한다.

  • 새 쓰레드 생성
  • 새 호출스택 생성
  • 그 새 쓰레드에서 run()이 실행됨

즉,

  • start() = 새 쓰레드를 출발시킨다
  • run() = 쓰레드가 할 일(작업 본문)

 

 

main 쓰레드와 콜스택 관점 — “실행 흐름”이 왜 흐트러져 보이나

자바 프로그램이 시작되면 JVM은 기본적으로 main 쓰레드를 만들고,
그 쓰레드가 main()을 실행한다.

그리고 아주 중요한 사실:

쓰레드마다 자기만의 호출스택(call stack)을 갖는다.

 

그래서 쓰레드가 여러 개면 “스택도 여러 개”가 된다.

이게 왜 중요하냐면,
멀티쓰레드에서는 서로 다른 스택에서 동시에 메서드가 쌓이고 빠지기 때문에

  • 출력 순서가 매번 바뀌고
  • 실행이 섞여 보이는 현상이

너무 자연스럽게 발생한다.

 

 

8) 싱글 쓰레드 vs 멀티 쓰레드 출력 결과가 달라지는 이유

이걸 체감시키는 방식이 보통 “출력 예시”다.

싱글 쓰레드라면

A 작업이 끝나야 B 작업이 시작된다.
그래서 출력 순서가 거의 항상 동일하다.

멀티 쓰레드라면

스케줄러가 A와 B를 번갈아 실행시키면서 출력이 섞인다.
실행할 때마다 순서가 달라질 수 있다.

여기서 중요한 포인트는:

  • 1코어면 “진짜 동시에”라기보다는 아주 짧은 시간 단위로 번갈아 실행(동시성)
  • 멀티코어면 실제 병렬성도 가능

 

 

왜 멀티쓰레드가 웹/서버에서 특히 중요해지나

EC2 배포/서버 실습(요청-응답, 여러 사용자가 동시에 접속)을 생각해보았을때,

서버는 한 순간에 요청이 1개만 오지 않는다.

여러 클라이언트가 동시에 들어오면:

  • 요청을 순차 처리만 하면 대기 시간이 폭증한다.

그래서 웹서버/서블릿 컨테이너/스프링 서버는 내부적으로

  • 쓰레드 풀(Thread Pool)로 요청을 분산 처리하는 구조를 가진다.

 

 

정리

  • 프로세스: 실행 중인 프로그램(자원 단위)
  • 쓰레드: 프로세스 내부의 실행 흐름(작업 단위)
  • 멀티쓰레드의 장점: 응답성 / 공유 / 비용
  • 단점: 동기화 / 디버깅 / 데드락
  • start()는 새 쓰레드 생성, run()은 그냥 메서드 호출
  • 쓰레드마다 콜스택이 따로 생겨서 실행/출력이 섞이는 게 정상

 

'Java' 카테고리의 다른 글

왜 new Integer()를 사용하면 안 될까?  (0) 2026.02.13
static  (0) 2026.02.05
enum: 사용이유와 예시  (0) 2026.02.04
'Java' 카테고리의 다른 글
  • 왜 new Integer()를 사용하면 안 될까?
  • static
  • enum: 사용이유와 예시
sqaxe1
sqaxe1
woojoo-devlog 님의 블로그 입니다.
  • sqaxe1
    Woojoo's Devlog
    sqaxe1
  • 전체
    오늘
    어제
    • 분류 전체보기 (148)
      • Backend (9)
        • Servlet (7)
        • Spring (2)
      • Frontend (1)
      • CS (0)
      • Book (33)
        • 자바 웹 프로그래밍 Next Step (30)
        • 테스트 주도 개발: 고품질 쾌속개발을 위한 TDD.. (1)
        • 성공과 실패를 결정하는 1%의 네트워크 원리 (2)
      • Engineering (0)
        • Testing (0)
      • Infra (6)
        • AWS (6)
      • Java (4)
      • Network (1)
      • 김영한 (28)
        • 자바 입문 (8)
        • 실전 자바 - 기본편 (6)
        • 실전 자바 - 중급편 (10)
        • 실전 자바 - 고급편 (4)
      • Web (39)
        • Web Basics (39)
      • Project (24)
        • NeoSquare (0)
        • Memo Evolution (24)
      • 정보처리기사 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    개발서적
    java
    aws
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
sqaxe1
쓰레드란?
상단으로

티스토리툴바