- 스레드 개념과 기초 사용법2026년 06월 23일
- 소쩍소쩍이
- 작성자
- 2026.06.23.:39
스레드란?
스레드는 프로그램 안의 작은 실행 흐름이다.
스레드 = 하나의 프로그램 안에서 실행되는 별도의 작업 흐름
스레드를 사용하면 서버 프로그램이 여러 개 생기는 것이 아니라, 하나의 서버 프로그램 안에서 여러 작업 흐름이 동시에 움직이게 된다.
하나의 서버 프로그램 ├── 메인 흐름: 새 클라이언트 접속을 기다림 ├── 스레드 1: 클라이언트 A의 메시지 처리 ├── 스레드 2: 클라이언트 B의 메시지 처리 └── 스레드 3: 클라이언트 C의 메시지 처리용어 쉬운 설명 프로세스 실행 중인 프로그램 하나 스레드 프로그램 안에서 움직이는 작업 흐름 메인 스레드 프로그램이 처음 시작될 때 기본으로 실행되는 흐름 작업 스레드 특정 작업을 따로 처리하기 위해 추가로 만든 흐름 채팅 서버에 스레드가 필요한 이유
스레드를 사용하는 것은 단순히 속도를 높이기 위해서가 아니다. 핵심은 기다리는 작업을 분리하는 것이다.
각 클라이언트가 언제 메시지를 보낼지 알 수 없기 때문에, 클라이언트마다 별도 스레드를 두어 각자 기다리게 만드는 것이 중요하다.
역할 하는 일 메인 스레드 새 클라이언트 접속을 계속 받음 (accept() 반복) 클라이언트 처리 스레드 특정 클라이언트의 메시지를 기다리며 처리 핵심
스레드는 여러 클라이언트를 동시에 처리하기 위해 사용한다.
특히 recv()처럼 기다리는 작업을 클라이언트마다 분리할 수 있다는 점이 중요하다.비유와 기본 형태
요리사로 비유하기
순차 실행은 요리사 한 명이 A 요리를 끝낸 뒤에 B 요리를 시작하는 것과 같다.
스레드 실행은 A 요리와 B 요리를 동시에 진행하는 것과 비슷하다. A 냄비에 불을 올리고 기다리는 시간 동안 B 재료를 손질하는 느낌으로 이해할 수 있다.
주방 비유 서버 역할 요리사 한 명이 순서대로 요리 순차 실행 — 한 클라이언트가 끝날 때까지 대기 여러 냄비를 동시에 올림 스레드 실행 — 각 클라이언트를 독립 흐름으로 처리 불 올리고 기다리는 시간 recv() 대기 — 이 시간에 다른 클라이언트 처리 가능 냄비마다 다른 요리 진행 클라이언트마다 다른 스레드가 처리 기본 형태
파이썬에서 스레드를 사용할 때는 threading 모듈을 사용한다.
import threading def work(): print("스레드에서 실행할 작업입니다.") thread = threading.Thread(target=work) # 스레드 객체 생성 — 아직 실행 안 됨 thread.start() # 스레드 실제 시작코드 의미 threading.Thread(target=work) 새 스레드 객체를 만든다. work 함수를 실행할 준비를 한다 target=work 스레드가 실행할 함수 이름을 지정한다 thread.start() 스레드를 실제로 시작한다. 이 줄 이후 함수가 별도 흐름에서 실행된다 자주 하는 실수 - target에 괄호 붙이기
자주 하는 실수는 target에 함수 이름 뒤 괄호를 붙이는 것이다.
# 잘못된 형태 — work()가 바로 호출되고, 그 반환값(None)이 target에 전달됨 threading.Thread(target=work()) # 올바른 형태 — work 함수 자체를 스레드에 넘기고, 스레드가 나중에 실행 threading.Thread(target=work)target=work()로 작성하면 스레드를 만드는 그 줄에서 work()가 바로 실행되어 버린다. 에러 메시지가 바로 나오지 않는 경우도 있어서 왜 스레드가 예상대로 동작하지 않는지 헷갈릴 수 있다.
target 뒤에는 항상 괄호 없이 함수 이름만 작성한다. 나중에 handle_client(client_socket)처럼 인자가 있는 함수를 넘길 때도 같은 원리로 생각하면 된다.
중요
target=work()는 함수를 바로 실행하는 형태이다.
스레드에 함수 자체를 넘기려면 target=work처럼 괄호 없이 작성해야 한다.스레드 실행 순서
① threading.Thread(target=함수) — 스레드 객체 생성 (아직 실행 안 됨) ↓ ② thread.start() — 스레드 실제 시작 ↓ ③ 메인 흐름과 스레드 흐름이 동시에 진행됨 ↓ ④ thread.join() (선택) — 스레드가 끝날 때까지 메인 흐름이 기다림join()은 "이 스레드가 완전히 끝날 때까지 기다려라"라는 의미이다.
다중 접속 채팅 서버에서는 스레드가 클라이언트 연결이 끊길 때까지 계속 실행되므로 join()을 쓰지 않는 경우도 많다.
순차 실행과 스레드 실행 비교
순차 실행의 경우
import time def work(name): for i in range(3): print(f"{name} 작업 중: {i + 1}") time.sleep(1) # 1초 기다림 — 클라이언트가 메시지를 보낼 때까지 기다리는 상황과 비슷 work("A") work("B") print("모든 작업이 끝났습니다.")순차 실행에서는 A의 작업이 모두 끝난 뒤 B의 작업이 시작된다.
스레드로 바꿔서 실행하기
import threading import time def work(name): for i in range(3): print(f"{name} 작업 중: {i + 1}") time.sleep(1) thread_a = threading.Thread(target=work, args=("A",)) # 스레드 생성 — 아직 실행되지 않음 thread_b = threading.Thread(target=work, args=("B",)) # 스레드 생성 — 아직 실행되지 않음 thread_a.start() # A 스레드 시작 — 독립 흐름으로 실행 시작 thread_b.start() # B 스레드 시작 — 독립 흐름으로 실행 시작 thread_a.join() # A 스레드가 끝날 때까지 메인 흐름이 기다림 thread_b.join() # B 스레드가 끝날 때까지 메인 흐름이 기다림 print("모든 작업이 끝났습니다.")스레드를 사용하면 A가 모두 끝난 뒤 B가 시작되는 것이 아니라 두 작업의 출력이 섞여 나타난다.
args로 스레드 함수에 값 전달하기
work(name) 함수는 name이라는 인자가 필요하다. 스레드에서 이 값을 전달하려면 args를 사용한다.
args는 반드시 튜플 형태여야 한다.
# 잘못된 형태 — 튜플이 아니라 문자열로 전달됨, 예상치 못한 동작 가능 args=("A") # 올바른 형태 — 값이 하나여도 쉼표를 붙여 튜플로 만듦 args=("A",) # 인자가 두 개인 경우 — 쉼표 없어도 튜플 args=(client_socket, client_address) # 인자가 하나인 경우 — 쉼표 필수 args=(client_socket,)주의
args에 값이 하나만 들어갈 때는 반드시 쉼표를 붙여야 한다.
args=("A",)처럼 작성해야 튜플로 인식된다.join() - 스레드가 끝날 때까지 기다리기
import threading import time def work(name): for i in range(3): print(f"{name} 작업 중: {i + 1}") time.sleep(1) thread_a = threading.Thread(target=work, args=("A",)) thread_b = threading.Thread(target=work, args=("B",)) thread_a.start() thread_b.start() work("메인 스레드") # 추가 thread_a.join() # join 제거 후 테스트 thread_b.join() # join 제거 후 테스트 print("모든 작업이 끝났습니다.")join()은 해당 스레드가 완전히 끝날 때까지 메인 흐름이 그 자리에서 기다리게 한다.
정리
스레드는 하나의 프로그램 안에서 실행되는 별도의 작업 흐름이다.
채팅 서버에서는 클라이언트마다 독립적인 스레드를 만들어 메시지를 기다리게 할 수 있다.
target에는 함수 이름만 전달하고, 인자가 필요한 경우 args를 사용한다.
스레드가 끝날 때까지 기다려야 하는 경우에는 join()을 사용할 수 있다.'Server - Client' 카테고리의 다른 글
접속자 목록 관리 (0) 2026.06.23 스레드로 클라이언트 처리 (0) 2026.06.23 여러 클라이언트 접속 구조 (0) 2026.06.23 1:1 터미널 채팅 완성하기 (0) 2026.06.22 반복 송수신과 종료 처리 (0) 2026.06.22 다음글이전글이전 글이 없습니다.댓글