콘텐츠로 이동

Ch.8 OS와 네트워크 키워드

< 사례: 같은 문제, 다른 카테고리의 키워드 | DB와 자료구조 키워드 >


앞에서 같은 "API가 느리다"라는 문제를 OS, 네트워크, DB, 자료구조, 아키텍처 다섯 방향으로 진단하는 걸 봤다. 이번에는 그 중 OS와 네트워크 카테고리의 핵심 키워드를 정리한다. 각 키워드가 어떤 상황에서, 어떤 프롬프트에 쓰이는지를 표로 보여준다.

목적은 "사전을 외우는 것"이 아니라 "AI에게 줄 수 있는 키워드의 모양을 익히는 것"이다. Ch.2~6에서 한 번씩 만난 키워드들이 대부분이다. 이번 챕터에서는 같은 키워드를 "프롬프트 도구"로 다시 본다.

OS 키워드

OS 키워드는 "프로그램이 컴퓨터 자원을 어떻게 쓰는가"를 다룬다. 성능, 동시성, 메모리 문제를 진단할 때 필요하다.

실행 단위와 스케줄링

키워드 한 줄 설명 이런 상황에 쓴다 프롬프트 예시
Process OS가 자원을 할당하는 실행 단위, 메모리 공간이 독립적 CPU Bound 작업을 진짜 병렬로 돌리고 싶을 때 "CPU Bound 작업이라 ProcessPoolExecutor로 별도 Process에서 실행해줘"
Thread Process 안에서 실행 흐름을 나눈 단위, 메모리 공유 I/O 대기 시간을 겹쳐 쓰고 싶을 때 "I/O Bound 작업이니까 ThreadPoolExecutor로 Thread Pool 구성해줘"
GIL (Global Interpreter Lock) CPython이 한 번에 하나의 Thread만 Python bytecode를 실행하게 만드는 락 Python에서 멀티스레드가 CPU에서 안 빨라질 때 "Python GIL 때문에 CPU Bound는 Thread로 안 빨라진다. Process로 바꿔줘"
Context Switch 실행 중인 프로세스/스레드를 전환하는 비용 스레드/프로세스를 너무 많이 만들어서 느릴 때 "스레드 500개가 Context Switch 때문에 느리다. Thread Pool로 제한해줘"
Scheduling OS가 어떤 작업을 언제 CPU에 올릴지 결정하는 정책 우선순위 역전, 굶주림(starvation) 의심 시 "OS Scheduling이 의심된다. 백그라운드 작업을 nice로 우선순위 낮춰줘"

I/O와 System Call

키워드 한 줄 설명 이런 상황에 쓴다 프롬프트 예시
System Call 프로그램이 커널에 작업을 요청하는 인터페이스 로그/파일 I/O가 많아서 느릴 때 "write() System Call 횟수가 너무 많다. 라인 단위 말고 버퍼링 후 flush 하게 바꿔줘"
User Mode / Kernel Mode CPU가 권한 분리해 동작하는 두 가지 모드 Mode Switch 비용을 설명할 때 "User → Kernel Mode 전환 비용 줄이려면 System Call을 batch로 묶어야 하지 않나?"
Blocking I/O / Non-blocking I/O I/O 완료를 기다리느냐 안 기다리느냐 외부 호출이 직렬로 연결돼서 느릴 때 "Blocking I/O를 Non-blocking으로 바꿔줘. asyncio + aiohttp 사용"
CPU Bound / I/O Bound 병목이 CPU인지 I/O인지 최적화 방향을 결정할 때 "이 작업이 CPU Bound인지 I/O Bound인지 먼저 판단해줘. 진단 코드도 줘"
epoll / kqueue / IOCP OS의 효율적 I/O 다중화 메커니즘 async/이벤트 루프의 내부를 설명할 때 "asyncio가 내부적으로 epoll을 쓰는 이유와 select 대비 장점 정리해줘"

메모리

키워드 한 줄 설명 이런 상황에 쓴다 프롬프트 예시
Memory Layout (Stack/Heap/Data/Text) 프로세스 메모리가 영역별로 나뉜 구조 메모리 문제 원인 영역을 좁힐 때 "객체 누수가 Heap에 쌓이는 패턴이다. weakref나 명시적 해제 검토해줘"
Virtual Memory 프로세스가 보는 메모리를 물리 메모리와 분리한 추상화 swap, RSS, page 단위 사고가 필요할 때 "RSS는 안정적인데 VSZ만 증가한다. mmap 누수 의심된다"
Page Fault 물리 메모리에 없는 페이지에 접근할 때 발생 대용량 데이터 처리가 갑자기 느려질 때 "Major Page Fault가 많다. 데이터를 chunk로 나누거나 mmap 옵션 조정해줘"
Thrashing 페이지 폴트가 폭발해서 시스템이 IO만 도는 상태 swap만 도느라 CPU/응답 모두 죽었을 때 "Thrashing 같다. 워킹셋이 메모리보다 크다. chunk 처리로 바꿔줘"
OOM (Out of Memory) 가용 메모리가 전부 소진된 상태 서버가 죽거나 OOMKiller에 kill 당할 때 "RSS가 계속 증가하다 OOMKiller에 죽는다. tracemalloc으로 Heap 누수 추적해줘"

동시성과 동기화

키워드 한 줄 설명 이런 상황에 쓴다 프롬프트 예시
Race Condition 공유 자원 동시 접근으로 결과가 비결정적이 되는 현상 동시 요청에서 데이터가 꼬일 때 "Race Condition이다. 카운터 증가 부분에 Lock을 걸어줘"
Critical Section 한 번에 한 스레드만 실행해야 하는 코드 영역 Lock 범위를 줄여 성능을 회복할 때 "Critical Section이 너무 넓다. Lock 범위를 카운터 증가 한 줄로 줄여줘"
Mutex / Semaphore 상호 배제(mutex)와 카운팅 제한(semaphore) 동기화 도구 자원 접근을 N개로 제한하고 싶을 때 "외부 API 동시 호출을 5개로 제한하고 싶다. asyncio.Semaphore로 구현해줘"
Deadlock 둘 이상의 스레드가 서로의 Lock을 기다리며 멈추는 상태 서버가 간헐적으로 멈출 때 "Deadlock이 의심된다. Lock 획득 순서를 통일(Lock Ordering)해줘"
Atomic Operation 중간에 끊기지 않는 단일 연산 Lock 없이 단순 카운터/플래그를 안전하게 다룰 때 "Redis INCR로 Atomic 카운터 만들어줘. Race Condition 없이 동작해야 함"

(Ch.2~5에서 배운 키워드가 대부분이다. "이걸 프롬프트에 어떻게 쓰는가"가 이번 챕터에서 추가되는 관점이다.)

OS 키워드 활용 사례

사례 1: print 빼니까 빨라진 코드를 다시 마주칠 때

[프롬프트]
배치 스크립트가 100만 건 처리에 30분 걸린다. 라인마다 print로 진행상황을 찍는다.
write() System Call이 라인마다 발생해서 stdout이 병목으로 보인다.
1. print 자체를 1000건마다 한 번씩만 찍게 바꿔줘
2. 남기는 것도 sys.stdout.write + 명시적 flush로, 줄 단위 자동 flush 비활성화

Ch.2의 핵심 키워드 write(), System Call, stdout 세 개로 진단을 풀었다.

사례 2: 스레드 풀이 오히려 느려졌을 때

[프롬프트]
이미지 리사이즈를 빠르게 하려고 ThreadPoolExecutor max_workers=500으로 돌렸다.
오히려 단일 스레드보다 느려졌다.
1. 이미지 리사이즈는 CPU Bound라서 GIL 때문에 Thread는 효과 없다고 들었다
2. ProcessPoolExecutor로 바꾸고, max_workers를 CPU 코어 수로 제한해줘
3. Process 생성 비용을 아끼려면 fork 기반 풀이 유리한가, spawn이 유리한가?

CPU Bound, GIL, ProcessPoolExecutor, Context Switch 키워드를 조합했다. Ch.3 내용이 그대로 프롬프트가 된다.

네트워크 키워드

네트워크 키워드는 "프로그램이 다른 시스템과 어떻게 통신하는가"를 다룬다. 서버 간 통신, 외부 API 호출, DB 연결, 보안 관련 문제를 진단할 때 필요하다.

프로토콜과 연결

키워드 한 줄 설명 이런 상황에 쓴다 프롬프트 예시
TCP / IP 안정적인 연결 기반 통신 프로토콜 스택 패킷 손실, 재전송, 순서 보장이 이슈일 때 "TCP 재전송이 많다. tcpdump로 RTT/Window 확인하는 절차 알려줘"
3-way Handshake TCP 연결을 SYN, SYN-ACK, ACK로 수립하는 절차 연결 수립 비용 자체가 병목일 때 "요청마다 3-way Handshake가 새로 일어난다. Keep-Alive로 재사용해줘"
Socket (fd) OS가 네트워크 통신을 다루는 파일 디스크립터 "Too many open files" 류 에러가 날 때 "fd가 폭증하다 EMFILE 에러가 난다. Socket leak 추적하는 코드 보여줘"
Connection Pool 미리 만들어둔 Connection을 재활용하는 구조 DB/외부 서비스 연결 문제에 "Connection Pool이 고갈된다. pool_size를 늘리고 pool_recycle을 설정해줘"
Keep-Alive TCP Connection을 유지해서 재활용하는 기법 HTTP 요청마다 새 Connection이 생기는 문제에 "외부 API 호출에 requests.Session()으로 Keep-Alive 적용해줘"
TIME_WAIT Connection 종료 후 대기 상태 포트 고갈 문제에 "TIME_WAIT가 수천 개 쌓인다. Connection 재사용으로 줄여줘"

성능 지표

키워드 한 줄 설명 이런 상황에 쓴다 프롬프트 예시
Latency 요청에서 응답까지 걸리는 시간 응답이 느린 원인을 정량화할 때 "p99 Latency가 500ms다. OpenTelemetry로 구간별 tracing 넣어줘"
Throughput 단위 시간당 처리 건수 서버의 처리 용량을 측정할 때 "현재 Throughput이 100 req/s인데 500까지 올려야 한다. 병목 후보 정리해줘"
RTT (Round-Trip Time) 패킷 왕복 시간 외부 API 호출이 느릴 때 "RTT 200ms인 외부 API 3개를 직렬 호출 중이다. 병렬로 바꿔줘"
Bandwidth 단위 시간당 전송 가능한 데이터 양 대용량 전송이 한계에 부딪힐 때 "응답이 항상 Bandwidth 한계 근처다. gzip 압축으로 줄여줘"
Tail Latency (p95/p99) 상위 일부 요청의 응답 시간 평균만 좋고 일부 요청만 튀는 문제에 "p50은 50ms인데 p99가 2초다. Tail Latency 원인 후보 정리해줘"

분산 / 라우팅 / 보안

키워드 한 줄 설명 이런 상황에 쓴다 프롬프트 예시
DNS Resolution 도메인 이름을 IP로 변환하는 과정 첫 요청만 유독 느릴 때 "첫 호출만 느리다. DNS Resolution 의심된다. DNS 캐시 TTL 확인 절차 알려줘"
Load Balancing 트래픽을 여러 서버에 분산하는 기법 특정 서버에 요청이 몰릴 때 "Round Robin LB를 Least Connections로 바꿔줘"
CORS 브라우저가 다른 출처 요청을 막는 보안 정책 프론트에서 API 호출이 차단될 때 "CORS 에러가 난다. FastAPI에 CORSMiddleware로 허용 도메인 설정해줘"
TLS / HTTPS 전송 구간 암호화 프로토콜 인증서/암호화 관련 이슈에 "TLS Handshake가 매 요청마다 일어나는 것 같다. Keep-Alive + 세션 재사용 적용해줘"
Reverse Proxy 외부 요청을 내부 서버로 전달해주는 중간 서버 nginx/HAProxy 계층 진단할 때 "Reverse Proxy에서 timeout이 난다. nginx proxy_read_timeout 조정 가이드 줘"

(Ch.6에서 배운 키워드가 대부분이다. CORS, TLS, Reverse Proxy는 이후 Ch.22~23에서 더 자세히 다룬다.)

네트워크 키워드 활용 사례

사례 1: TIME_WAIT가 쌓이는 서버

[프롬프트]
내 서비스가 외부 API를 초당 1000번 호출한다. netstat | grep TIME_WAIT 했더니 2만 개다.
포트 고갈로 가끔 EADDRNOTAVAIL이 난다.
1. 요청마다 Connection을 새로 만드는 게 원인 같다 (Keep-Alive 미사용)
2. requests.Session()으로 Keep-Alive 적용, Connection Pool도 함께 설정
3. HTTPAdapter의 pool_connections / pool_maxsize 값 가이드도 줘

TIME_WAIT, Keep-Alive, Connection Pool 세 키워드로 묶었다. Ch.6 내용의 직접 적용이다.

사례 2: 외부 호출 직렬 → 병렬

[프롬프트]
주문 결제 API에서 결제사 호출(200ms) + 사기탐지(150ms) + 알림(100ms) 순차 호출 중.
세 호출 사이에 의존성이 없다. 직렬 450ms를 max(200,150,100)=200ms로 줄이고 싶다.
1. asyncio.gather로 병렬 호출
2. 단, 알림 실패는 결제 결과에 영향이 없어야 하니 return_exceptions=True로
3. 각 호출에 Connection Pool과 timeout 명시

RTT, asyncio.gather, Connection Pool, timeout 키워드를 조합. 비즈니스 요구사항(알림 실패는 무시)까지 한 프롬프트에 녹였다.

OS + 네트워크 키워드의 조합

실무에서는 하나의 카테고리 키워드만으로 해결되지 않는 경우가 많다. 두 카테고리를 조합해야 하는 사례를 보자.

사례: 외부 API 호출이 느리고, 동시에 메모리도 증가한다

[키워드 조합 프롬프트]
외부 API를 요청당 3번 호출하는데, 각각 Blocking I/O라서 직렬로 300ms 걸린다 (네트워크).
그리고 응답 데이터(평균 5MB)를 전부 메모리에 쌓고 있어서 RSS가 계속 증가한다 (OS/메모리).
1. Blocking I/O → asyncio.gather로 병렬 호출, Connection Pool도 함께 (네트워크)
2. 응답 데이터는 처리 후 즉시 해제하도록 async iterator로 chunk 처리 (OS/메모리)
3. tracemalloc으로 누수 여부 검증하는 코드도 같이 줘 (OS)

Blocking I/O + asyncio.gather + Connection Pool (네트워크) + RSS, tracemalloc (OS) 키워드를 조합했다. 이렇게 프롬프트를 주면 AI는 두 문제를 동시에 해결하는 코드를 생성한다. 키워드를 모르면 "API가 느리고 메모리도 많이 쓴다"라고만 할 수 있고, AI는 두 문제 중 하나만 건드릴 가능성이 높다.

사례: TLS Handshake 비용이 의심될 때

[키워드 조합 프롬프트]
외부 HTTPS API를 호출할 때 첫 요청만 800ms, 이후는 50ms.
1. 첫 요청만 느린 건 DNS Resolution + TCP 3-way Handshake + TLS Handshake 누적 같다 (네트워크)
2. requests.Session() 또는 httpx.Client()로 Keep-Alive + TLS 세션 재사용 (네트워크)
3. 서버 기동 시 warm-up 호출로 첫 요청 비용을 사전에 치르기 (애플리케이션)

DNS Resolution, 3-way Handshake, TLS Handshake, Keep-Alive 키워드를 묶어, AI가 "처음만 느린 이유"를 정확히 짚고 대응 코드를 주게 한다.

카테고리 안에서의 키워드 그래프

OS와 네트워크 키워드는 서로 독립이 아니다. 아래처럼 엮인다.

graph LR
    subgraph OS
        PROC["Process"]
        THR["Thread"]
        GIL["GIL"]
        SC["System Call"]
        BIO["Blocking I/O"]
        MUT["Mutex/Semaphore"]
        DL["Deadlock"]
    end
    subgraph NET[네트워크]
        SOCK["Socket(fd)"]
        TCP["TCP/IP"]
        KA["Keep-Alive"]
        CP["Connection Pool"]
        TW["TIME_WAIT"]
        RTT["RTT/Latency"]
    end
    THR --> GIL
    SC --> BIO
    BIO --> SOCK
    SOCK --> TCP
    TCP --> KA
    KA --> CP
    CP --> TW
    TCP --> RTT
    MUT --> DL

키워드를 묶어서 기억해두면, 프롬프트를 쓸 때 "관련 키워드를 같이 던지는" 게 자연스러워진다. AI는 키워드가 많을수록(노이즈가 아닌 한) 더 정확한 답을 준다.


< 사례: 같은 문제, 다른 카테고리의 키워드 | DB와 자료구조 키워드 >