성능 튜닝과 OS 면접 주제
파일·TCP·메모리·I/O 커널 파라미터를 측정 근거로 조정하고 운영체제 핵심 질문을 병목 진단 관점에서 정리합니다.
이 절에서는 운영체제 면접에서 자주 다루는 주제와 서버 운영에서 확인하는 커널 파라미터를 함께 정리합니다.
튜닝 항목은 병목 유형, 측정 지표, 변경 전후 검증 기준을 중심으로 봅니다.
커널 파라미터 튜닝
파일 디스크립터 제한
# 프로세스당 최대 열 수 있는 파일 수
ulimit -n # 현재 셸의 값 확인 (환경에 따라 다름)
ulimit -n 65535 # 허용된 hard limit 안에서 현재 셸과 이후 자식에 적용
# PAM의 pam_limits를 거치는 새 세션 설정: /etc/security/limits.conf
# * soft nofile 65535
# * hard nofile 65535
# 시스템 전체 제한
cat /proc/sys/fs/file-max
sysctl -w fs.file-max=2097152웹 서버가 동시에 수천 개의 연결을 처리하려면 파일 디스크립터 제한을 높여야 합니다.
소켓도 파일 디스크립터를 사용하기 때문입니다.
현재 열린 파일 수와 한도 초과 오류를 확인한 뒤 필요한 범위로 정합니다. limits.conf는 PAM 세션에, systemd 서비스는 LimitNOFILE 등에 의해 적용 범위가 달라집니다.
TCP 튜닝
# 현재 값 확인
sysctl -a | grep somaxconn
# accept를 기다리는 연결의 listen backlog 상한
sysctl -w net.core.somaxconn=65535
# 리스너별 미완료 연결 요청 한도 (SYN_RECV)
sysctl -w net.ipv4.tcp_max_syn_backlog=65535
# 프로토콜상 안전한 TIME_WAIT 재사용 허용 (일괄 권장값 아님)
sysctl -w net.ipv4.tcp_tw_reuse=1
# SO_KEEPALIVE가 활성화된 소켓의 기본 keepalive 설정
sysctl -w net.ipv4.tcp_keepalive_time=300 # 300초 후 첫 probe
sysctl -w net.ipv4.tcp_keepalive_intvl=30 # 30초 간격
sysctl -w net.ipv4.tcp_keepalive_probes=5 # 5번 실패 시 연결 종료
# 사용 가능한 로컬 포트 범위 확장
sysctl -w net.ipv4.ip_local_port_range="1024 65535"
# SYN 큐 초과 시 SYN cookies 사용 허용
sysctl -w net.ipv4.tcp_syncookies=1TCP 설정 · 큐와 종료 상태
accept 대기열·SYN 요청·TIME_WAIT 재사용은 서로 다른 설정 대상입니다
설정 이름을 병목 가설과 연결합니다. 특히 tcp_fin_timeout은 고아 FIN_WAIT_2의 대기 한도이며 TIME_WAIT 시간을 줄이는 설정이 아닙니다.
| 대상 | 설정 이름 | 적용 범위 |
|---|---|---|
| accept 대기열 | somaxconn | 애플리케이션 listen backlog의 상한. 처리량이나 연결 성공을 보장하지 않음 |
| 미완료 연결 | tcp_max_syn_backlog | 리스너별 SYN_RECV 요청 한도. 정상 부하 대책과 SYN cookies는 구분 |
| TIME_WAIT 재사용 | tcp_tw_reuse | 프로토콜상 안전한 재사용만 허용. 0: 끔, 1: 전체, 2: 루프백만 |
| 고아 연결 정리 | tcp_fin_timeout | 앱이 더 이상 참조하지 않는 FIN_WAIT_2 연결의 대기 한도. TIME_WAIT 시간이 아님 |
| 임시 로컬 포트 | ip_local_port_range | 자동 할당할 로컬 포트 범위. 예약 포트·목적지와 연결 상태도 고려 |
- accept 대기열
- 설정 이름: somaxconn적용 범위: 애플리케이션 listen backlog의 상한. 처리량이나 연결 성공을 보장하지 않음
- 미완료 연결
- 설정 이름: tcp_max_syn_backlog적용 범위: 리스너별 SYN_RECV 요청 한도. 정상 부하 대책과 SYN cookies는 구분
- TIME_WAIT 재사용
- 설정 이름: tcp_tw_reuse적용 범위: 프로토콜상 안전한 재사용만 허용. 0: 끔, 1: 전체, 2: 루프백만
- 고아 연결 정리
- 설정 이름: tcp_fin_timeout적용 범위: 앱이 더 이상 참조하지 않는 FIN_WAIT_2 연결의 대기 한도. TIME_WAIT 시간이 아님
- 임시 로컬 포트
- 설정 이름: ip_local_port_range적용 범위: 자동 할당할 로컬 포트 범위. 예약 포트·목적지와 연결 상태도 고려
기본값은 커널·배포판에 따라 확인합니다. 예를 들어 somaxconn의 upstream 기본값은 Linux 5.4부터 4096이며, 위 65535는 이 예제의 값입니다.
메모리 튜닝
# 익명 메모리 스왑과 파일 페이지 회수의 상대 비용 (0~200)
sysctl -w vm.swappiness=10
# 10은 설정 형식 예시. 저장장치와 부하를 측정해 선택
# overcommit 정책
sysctl -w vm.overcommit_memory=0 # 0: 휴리스틱으로 과도한 요청 거부
# 1: overcommit 회계 제한을 적용하지 않음
# 2: 계산된 commit 한도 적용
# dirty page 회수·쓰기 임계값과 오래된 페이지 기준
sysctl -w vm.dirty_ratio=20 # free·회수 가능 메모리 기준 dirty 임계 비율
sysctl -w vm.dirty_background_ratio=5 # 5% 초과 시 백그라운드 플러시 시작
sysctl -w vm.dirty_expire_centisecs=3000 # 30초 이상 된 dirty page를 writeback 대상으로 간주
# 영구 설정
echo "vm.swappiness=10" >> /etc/sysctl.conf
sysctl -p # 적용swappiness는 익명 페이지 스왑과 파일 페이지 회수의 상대 비용을 조정합니다. 0도 스왑 완전 금지는 아니며, 100을 넘는 값도 사용할 수 있습니다.
overcommit의 모드 2는 스왑과 설정된 RAM 비율 또는 overcommit_kbytes 등을 바탕으로 commit 한도를 계산합니다. 모드 1도 주소 공간·자원 한도나 실제 메모리 부족에 의한 실패를 없애지 않습니다.
설정 전에 현재 값과 되돌릴 값을 남기고, 병목 가설에 맞는 설정 하나를 바꿔 처리량과 p95·p99 지연을 비교합니다. sysctl -w는 즉시 적용되므로 아래 값을 일괄 추천으로 읽지 않습니다.
I/O 스케줄러
# 현재 I/O 스케줄러 확인
cat /sys/block/sda/queue/scheduler
# [mq-deadline] kyber bfq none
# 변경 (즉시 적용)
echo "none" > /sys/block/nvme0n1/queue/scheduler # NVMe SSD
echo "mq-deadline" > /sys/block/sda/queue/scheduler # HDD/SATA SSD- none: 별도 블록 I/O 스케줄러를 두지 않습니다. 예전 단일 큐의 noop과 같은 이름은 아닙니다.
- mq-deadline: 요청 만료 기준으로 오래 기다린 요청을 우선하되 완료 시각을 보장하지는 않습니다.
- bfq: 대역폭 배분과 공정성을 다룹니다.
- kyber: 지연 시간 목표에 맞춰 요청을 제어합니다.
장치의 scheduler 파일에 나온 지원 항목과 실제 부하를 기준으로 선택합니다. NVMe·HDD라는 이름만으로 최선의 설정을 확정하지 않습니다.
한도를 높이기 전에 필요한 수를 설명하기
하나의 프로세스가 기본 파일 12개와 클라이언트 소켓 100개를 동시에 열고, 열린 fd가 정확히 0~111이며 다음 두 새 소켓이 동시에 필요한 단순 모형을 생각합니다. soft nofile이 113이면 fd 112를 새로 만들 수 있지만 다음 fd 113은 한도 이상입니다. 한도를 114로 바꾸면 이 한도 조건만 해소할 수 있고, 실제 OS 자원 부족·권한·네트워크 오류까지 없앤 것은 아닙니다. 실제 한도는 가장 큰 fd 번호에 관한 조건이므로 단순 열린 개수 계산에는 연속 번호라는 전제도 필요합니다.
독립 확인: 위 연속 fd 모형에서 소켓 120개와 기본 파일 12개, 새 소켓 두 개가 필요합니다. soft nofile 133이면 몇 개까지 추가로 만들 수 있고, 이 조건의 실패를 피할 최소 한도는 얼마인가요? 이어 4KiB 페이지에서 서로 따로 할당하는 4097바이트와 1바이트 영역의 내부 낭비 합을 구하세요. 두 문제에서 용량과 원인을 연결하는 전제를 함께 적으세요.
직접 계산한 뒤 풀이 확인
현재 fd는 0~131이라 첫 새 fd 132는 133 미만으로 만들 수 있지만 다음 133은 한도에 닿습니다. 두 새 fd까지 필요한 최소 한도는 134입니다. 별도 영역은 각각 2페이지·1페이지이고 남는 공간은 4095+4095=8190바이트입니다. fd 번호의 연속성·동시 유지와 별도 페이지 할당이라는 전제를 사용한 계산입니다. 실제 연결 실패나 메모리 부족을 이 한도·단편화 계산 하나로 확정하지 않습니다.
자주 출제되는 OS 면접 질문
프로세스와 스레드
프로세스와 스레드의 차이는?프로세스는 독립된 메모리 공간(코드, 데이터, 힙, 스택)을 가집니다.
스레드는 같은 프로세스의 코드·데이터·힙을 공유하지만 스택, 레지스터 상태, 스레드 로컬 저장소 등은 따로 가집니다.
프로세스 간 통신은 IPC가 필요하지만, 같은 프로세스의 스레드는 공유 메모리로 바로 통신합니다.
프로세스 생성에는 주소 공간 관리 등이, 스레드 생성에는 새 실행 문맥·스택 등의 준비가 필요합니다. 아래의 COW처럼 실제 복사를 줄이는 구현도 있으므로 비용은 방식과 부하에 따라 달라집니다.
컨텍스트 스위칭이란?CPU가 현재 프로세스/스레드의 실행을 중단하고 다른 프로세스나 스레드를 실행하는 과정입니다.
현재의 레지스터 상태, PC, 스택 포인터 등을 PCB에 저장하고, 새 프로세스의 상태를 복원합니다.
상태 저장·복원과 스케줄링에 비용이 들고, 작업 집합이 바뀌면 캐시·TLB 적중률도 떨어질 수 있습니다. 전환마다 모든 캐시와 TLB가 무효화되는 것은 아니며 PCID·ASID 같은 태그로 주소 변환을 유지하기도 합니다. 같은 주소 공간을 쓰는 전환은 일부 비용을 줄일 수 있지만 항상 더 빠르다는 보장은 없습니다.
fork()와 exec()는?fork()는 부모의 메모리를 복사한 자식 프로세스를 생성합니다.
COW(Copy-on-Write)로 실제 물리 메모리는 수정 시에만 복사됩니다.
exec()는 현재 프로세스의 주소 공간을 새 프로그램으로 교체합니다.
셸이 명령을 실행할 때 fork() + exec() 조합을 사용합니다.
메모리
가상 메모리란?프로세스의 주소 공간을 물리 메모리 배치와 분리하는 기법입니다. 가상 주소 범위에는 매핑되지 않은 구간도 있을 수 있습니다.
필요한 페이지를 RAM에 두고 파일·스왑 등에서 가져오거나 처음 접근할 때 0으로 채울 수 있습니다. 모든 비상주 페이지가 디스크에 저장된 것은 아닙니다.
페이지 테이블로 가상 주소를 물리 주소로 변환하며, TLB가 이 변환을 캐시합니다.
페이지 폴트란?주소 변환이나 접근 권한 조건을 만족하지 못할 때 발생하는 예외입니다. 비상주 페이지뿐 아니라 COW 쓰기나 보호 위반도 원인이 됩니다.
OS가 매핑을 준비하거나 페이지를 가져와 재개할 수도 있고, 잘못된 접근이면 시그널을 보낼 수도 있습니다. 디스크 I/O 없는 minor fault도 있으므로 모든 폴트가 수 밀리초의 디스크 읽기를 뜻하지는 않습니다.
빈 프레임이 없으면 페이지 교체 알고리즘(LRU 등)으로 교체할 프레임을 결정합니다.
내부 단편화 vs 외부 단편화?내부 단편화: 할당된 블록 내부의 사용되지 않는 공간 (페이징에서 발생).
외부 단편화: 할당된 블록 사이의 남는 공간 (세그먼테이션에서 발생).
일반 페이지 매핑은 물리적으로 연속된 큰 구간을 요구하지 않습니다. 하지만 커널의 연속 물리 메모리 할당이나 huge page에는 여전히 외부 단편화가 문제가 될 수 있으며, 컴팩션도 비용과 이동 제약이 있습니다.
동기화
데드락의 4가지 조건은?상호 배제, 점유와 대기, 비선점, 순환 대기입니다.
네 조건이 동시에 충족되어야 데드락이 발생합니다.
하나라도 깨뜨리면 예방됩니다.
실무에서는 락 순서 규칙과 타임아웃이 가장 많이 사용됩니다.
뮤텍스와 세마포어의 차이는?일반적인 POSIX 뮤텍스는 소유권을 가지며 잠근 스레드가 해제해야 합니다.
세마포어는 카운터로 N개까지 동시 접근을 허용합니다.
소유권 개념이 없어 다른 스레드가 signal할 수 있습니다.
뮤텍스는 락, 세마포어는 신호라고 기억하면 됩니다.
스핀락은 언제 쓰나?임계 영역이 매우 짧아 컨텍스트 스위칭보다 바쁜 대기가 더 빠른 경우에 씁니다.
대기 중에도 락 소유자가 진행할 수 있어야 하며, 코어 수·선점·인터럽트 조건과 대기 길이를 함께 봅니다. 커널의 잠들 수 없는 문맥 등에서 쓰이지만, 구현과 커널 설정에 따른 제약을 확인해야 합니다.
시스템
사용자 모드와 커널 모드의 차이는?사용자 모드에서는 제한된 명령어만 실행 가능합니다.
특권 명령과 자원 접근은 제한되며, 허용된 장치 매핑처럼 OS가 부여한 접근은 가능합니다.
시스템 콜에서는 커널이 요청과 권한을 검사해 작업합니다. 호출한 애플리케이션이 임의의 커널 권한을 얻는 것은 아닙니다. 전환 비용도 CPU·보안 완화 설정과 호출 내용에 따라 달라집니다.
동기와 비동기, 블로킹과 논블로킹의 차이는?I/O 요청과 완료 대기는 다른 호출일 수 있다
비동기 읽기를 큐에 제출한다. 확인한 완료 요청의 결과를 한 번 얻는다. 각 단계의 값과 전환 이유를 비교합니다.
I/O 인터페이스 · 요청과 완료 대기
비동기 요청을 제출한 뒤에도 완료를 기다리는 호출을 사용할 수 있습니다
블로킹 여부는 개별 호출이 기다리는지를 봅니다. 비동기 I/O는 요청과 완료 확인을 나누며, 논블로킹 read도 성공하면 데이터를 그 호출에서 돌려줍니다.
블로킹 read · 결과를 반환
데이터·EOF·오류 등을 반환할 수 있을 때까지 기다릴 수 있습니다.
확인: 읽은 바이트 수 또는 오류. 요청한 길이보다 적게 읽을 수도 있습니다.
논블로킹 read · 지금 가능한 결과
논블로킹이 지원되는 대상에서는 데이터 대기 없이 반환합니다. 데이터가 없으면 EAGAIN 등의 오류를 확인합니다.
확인: 바이트 수·EOF·오류. 준비 상태를 기다린 뒤 재시도할 수 있습니다.
aio_read · 요청을 제출
비동기 읽기를 큐에 제출합니다. 제출 성공은 읽기 완료나 성공을 뜻하지 않습니다.
확인: aio_error로 상태를 보고, 완료 뒤 aio_return으로 결과를 한 번 회수합니다.
aio_suspend · 별도 호출에서 대기
대상 비동기 요청 중 하나의 완료·시그널·시간 제한까지 기다릴 수 있습니다. 이미 완료된 요청이 있으면 바로 반환합니다.
확인: 각 요청의 상태를 검사해 완료된 작업을 찾습니다.
일반 파일·블록 장치에서 O_NONBLOCK이 I/O 대기 방지를 보장하지는 않습니다. 비동기 완료 확인도 반드시 콜백일 필요는 없습니다. 잘못된 인자나 제출 실패는 각 API의 오류 반환으로 별도 확인합니다.
이 예의 조건
- 본문과 전체 도표의 예를 따라 요청 제출부터 결과 회수까지 진행합니다.
관계도의 보충 설명
| 구분 | 전체 도표의 내용 |
|---|---|
| 제목 | I/O 요청과 완료 대기는 다른 호출일 수 있다 |
| 관계 설명 | 제출에 성공한 뒤 아직 처리 중인 요청 목록의 완료로 aio_suspend가 정상 반환하는 선택 경로다. 시간은 아래로 흐른다. 제출 성공 반환은 비동기 작업의 완료가 아니다. 이미 완료되면 대기는 즉시 반환할 수 있고 시그널·timeout에 의한 다른 반환과 제출 오류는 기존 지원 패널에 남긴다. 목록 중 완료된 요청을 aio_error로 확인한 뒤 그 요청의 aio_return을 한 번 호출해 결과를 회수한다. 점선 화살표는 호출의 반환이며 완료 callback을 뜻하지 않는다. |
| 설명·조건 | 일반 파일·블록 장치에서 O_NONBLOCK이 I/O 대기 방지를 보장하지는 않습니다. 비동기 완료 확인도 반드시 콜백일 필요는 없습니다. 잘못된 인자나 제출 실패는 각 API의 오류 반환으로 별도로 확인합니다. |
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| 요청 제출 비동기 읽기를 큐에 제출한다. |
|
|
| 별도 대기 아직 완료되지 않은 요청을 기다린다. |
|
|
| 완료 확인 정상 완료로 대기 호출이 반환된 경로이다. |
|
|
| 결과 회수 확인한 완료 요청의 결과를 한 번 얻는다. |
|
|
I/O 요청과 완료 대기는 다른 호출일 수 있다
비동기 읽기를 큐에 제출한다. 확인한 완료 요청의 결과를 한 번 얻는다. 각 단계의 값과 전환 이유를 비교합니다.
I/O 인터페이스 · 요청과 완료 대기
비동기 요청을 제출한 뒤에도 완료를 기다리는 호출을 사용할 수 있습니다
블로킹 여부는 개별 호출이 기다리는지를 봅니다. 비동기 I/O는 요청과 완료 확인을 나누며, 논블로킹 read도 성공하면 데이터를 그 호출에서 돌려줍니다.
블로킹 read · 결과를 반환
데이터·EOF·오류 등을 반환할 수 있을 때까지 기다릴 수 있습니다.
확인: 읽은 바이트 수 또는 오류. 요청한 길이보다 적게 읽을 수도 있습니다.
논블로킹 read · 지금 가능한 결과
논블로킹이 지원되는 대상에서는 데이터 대기 없이 반환합니다. 데이터가 없으면 EAGAIN 등의 오류를 확인합니다.
확인: 바이트 수·EOF·오류. 준비 상태를 기다린 뒤 재시도할 수 있습니다.
aio_read · 요청을 제출
비동기 읽기를 큐에 제출합니다. 제출 성공은 읽기 완료나 성공을 뜻하지 않습니다.
확인: aio_error로 상태를 보고, 완료 뒤 aio_return으로 결과를 한 번 회수합니다.
aio_suspend · 별도 호출에서 대기
대상 비동기 요청 중 하나의 완료·시그널·시간 제한까지 기다릴 수 있습니다. 이미 완료된 요청이 있으면 바로 반환합니다.
확인: 각 요청의 상태를 검사해 완료된 작업을 찾습니다.
일반 파일·블록 장치에서 O_NONBLOCK이 I/O 대기 방지를 보장하지는 않습니다. 비동기 완료 확인도 반드시 콜백일 필요는 없습니다. 잘못된 인자나 제출 실패는 각 API의 오류 반환으로 별도 확인합니다.
이 예의 조건
- 본문과 전체 도표의 예를 따라 요청 제출부터 결과 회수까지 진행합니다.
관계도의 보충 설명
| 구분 | 전체 도표의 내용 |
|---|---|
| 제목 | I/O 요청과 완료 대기는 다른 호출일 수 있다 |
| 관계 설명 | 제출에 성공한 뒤 아직 처리 중인 요청 목록의 완료로 aio_suspend가 정상 반환하는 선택 경로다. 시간은 아래로 흐른다. 제출 성공 반환은 비동기 작업의 완료가 아니다. 이미 완료되면 대기는 즉시 반환할 수 있고 시그널·timeout에 의한 다른 반환과 제출 오류는 기존 지원 패널에 남긴다. 목록 중 완료된 요청을 aio_error로 확인한 뒤 그 요청의 aio_return을 한 번 호출해 결과를 회수한다. 점선 화살표는 호출의 반환이며 완료 callback을 뜻하지 않는다. |
| 설명·조건 | 일반 파일·블록 장치에서 O_NONBLOCK이 I/O 대기 방지를 보장하지는 않습니다. 비동기 완료 확인도 반드시 콜백일 필요는 없습니다. 잘못된 인자나 제출 실패는 각 API의 오류 반환으로 별도로 확인합니다. |
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| 요청 제출 비동기 읽기를 큐에 제출한다. |
|
|
| 별도 대기 아직 완료되지 않은 요청을 기다린다. |
|
|
| 완료 확인 정상 완료로 대기 호출이 반환된 경로이다. |
|
|
| 결과 회수 확인한 완료 요청의 결과를 한 번 얻는다. |
|
|
동기·비동기는 요청과 완료의 관계를, 블로킹·논블로킹은 특정 호출이 기다리는지를 나눠 설명합니다.
심화 면접 주제
캐시 친화(Cache-friendly) 코드란?CPU가 메모리에 접근할 때 캐시 라인(보통 64바이트) 단위로 가져옵니다.
연속된 메모리에 순서대로 접근하면 캐시 적중률이 높아집니다.
연속 배열은 포인터로 흩어진 연결 리스트보다 공간 지역성을 활용하기 쉽습니다. 아래처럼 C의 연속된 2차원 배열은 행 우선 배치이므로 행 순회가 연속 주소를 읽습니다.
/* 캐시 친화적: 행 우선 순회 (연속 메모리 접근) */
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
sum += matrix[i][j]; /* 인접 원소의 캐시 라인 재사용 기대 */
/* 캐시 비친화적: 열 우선 순회 (점프 접근) */
for (int j = 0; j < N; j++)
for (int i = 0; i < N; i++)
sum += matrix[i][j]; /* 큰 행 간격이면 캐시 미스가 늘 수 있음 */N이 큰 행렬에서 행 우선 순회가 수배 빠를 수 있습니다.
Zero-Copy란?전통적인 read/write 파일 전송은 데이터를 사용자 버퍼로 읽었다가 다시 커널에 전달합니다.
sendfile()은 파일에서 출력 fd로 전달하는 작업을 커널 안에서 처리해 사용자 버퍼 왕복 복사를 줄입니다. 모든 장치에서 물리적 복사가 전혀 없거나 항상 NIC로 직접 전달된다는 뜻은 아닙니다.
Nginx, Kafka 등 고성능 서버가 활용합니다.
epoll vs select?select는 매번 fd 집합을 전달하고, 반환 뒤 호출자가 준비된 항목을 확인합니다.
epoll은 관심 fd를 등록해 두고 준비된 이벤트 목록을 받습니다. 반환할 이벤트 수와 등록·변경 비용도 있으므로 전체 처리를 무조건 O(1)로 표현하지 않습니다.
큰 연결 집합에서 유용하지만 실제 선택은 준비된 fd 비율과 처리 방식에 달려 있습니다. macOS에는 kqueue가 있고 Windows의 IOCP는 준비 상태가 아닌 I/O 완료 통지를 중심으로 합니다.
정리
운영체제는 컴퓨터 과학의 기초이자, 실무 개발의 근간입니다.
프로세스와 스레드를 이해하면 동시성 버그를 잡을 수 있고, 가상 메모리를 이해하면 메모리 문제를 진단할 수 있습니다.
파일 시스템을 알면 데이터를 안전하게 관리하고, 보안 원리를 알면 견고한 시스템을 설계할 수 있습니다.
이 교재에서 다룬 개념들은 특정 기술이 아니라 원리입니다.
언어와 프레임워크는 바뀌어도, OS의 원리는 수십 년 동안 유효했고 앞으로도 유효할 것입니다.