A-10: 원격 운영
목차 33
안녕하세요, 여러분의 리눅스 길잡이 홍순구 튜터입니다.
지난 시간 우리는 화면도 키보드도 없는 원격 서버의 문을 직접 열었어요. 네트워크가 IP·포트·DNS로 어떻게 동작하는지 기초를 잡고, 마지막엔 손수 만든 열쇠 한 쌍(SSH 키)으로 비밀번호 없이 원격 서버에 쏙 들어갔죠. 그런데 들어가서 끝이 아니에요. 진짜 운영은 그 문 안에서 시작됩니다.
생각해보면 현업에서 서버에 들어가서 하는 일은 늘 비슷해요. 내 컴퓨터에서 만든 파일을 서버로 올리고, 서버에 쌓인 로그를 내 노트북으로 내려받고, "이 서버 웹이 살아는 있나?" 하고 직접 두드려보고, 아무나 못 들어오게 문을 여닫죠. 신입 때 이걸 몰라서 파일 하나 올리겠다고 복사 붙여넣기로 끙끙대거나, 서버가 응답을 안 하는데 어디서부터 봐야 할지 막막했던 경험, 다들 한 번쯤 있어요. 오늘 그 "원격 운영"의 기본 도구 네 가지를 차근차근 배워서, 더는 식은땀 흘리지 않게 만들어 드릴게요.
오늘은 이런 길을 따라갑니다.
오늘의 여정 — "원격 서버를 실제로 운영하기"
① 파일 주고받기 scp·sftp·rsync — SSH 통로 위로 파일을 올리고 내린다
② 웹으로 두드리기 curl·wget — 서버에 HTTP 요청을 던지고 상태 코드를 읽는다
③ 문을 여닫기 ufw — 방화벽으로 포트를 열고 닫는다
④ 컨테이너 한 걸음 "도커가 결국 무엇인지" 개념 한 문단으로 다음 과목 다리 놓기
💡 오늘 수업의 핵심 — "원격 서버에 파일을 올리고 내리고, 웹으로 응답을 확인하고, 방화벽으로 문을 여닫는 운영의 기본기를 손에 익힌다"
지난 시간 SSH로 연 그 통로 하나가 오늘의 모든 일에 그대로 쓰여요. 파일을 보내는 scp도, 동기화하는 rsync도 전부 그 22번 포트·그 키 위에서 돕니다. 새로 설정할 게 없어요. 어렵지 않으니 천천히 따라오세요.
🎯 학습 목표
scp·sftp·rsync세 가지로 원격 서버와 파일을 주고받고, 언제 무엇을 쓸지 구분한다.curl·wget으로 서버에 HTTP 요청을 던지고, 상태 코드(200·404·500)로 응답을 읽는다.ufw로 방화벽 포트를 열고 닫으며, "여는 포트가 곧 서비스 포트"임을 이해한다.
Step 1: "내 파일을 어떻게 저 서버로 보내지?"
지난 시간 SSH로 원격 서버에 들어가는 데까지 성공했어요. 그런데 막상 들어가 보면 바로 부딪히는 게 있어요. 내 노트북에 있는 파일을 어떻게 저 서버로 보낼까요? 반대로 서버에 쌓인 로그 파일을 어떻게 내 컴퓨터로 가져올까요?
좋은 소식부터 말씀드릴게요. 지난 시간 만든 SSH 통로를 그대로 씁니다. 파일 전송 도구들은 별도의 서버를 따로 깔거나 새 포트를 열 필요가 없어요. SSH가 쓰는 그 22번 포트, 그 키 인증 위에서 똑같이 동작하거든요. 그래서 SSH 접속만 되면 파일 전송도 거의 공짜로 따라옵니다.
지난 시간 연 SSH 통로 (22번 포트 · 키 인증)
[ 내 컴퓨터 ] ===== SSH 통로 ===== [ 원격 서버 ]
└─ scp · sftp · rsync 가 이 통로를 그대로 타고 파일을 나른다
리눅스에서 원격 파일 전송은 크게 세 가지 도구가 있어요. scp, sftp, rsync. 하나씩 만나봅시다.
scp — 가장 단순한 "복사 한 방"
scp(secure copy, 보안 복사)는 이름 그대로예요. 지난 시간 로컬에서 파일을 복사하던 cp 기억나시죠? 그 cp에 "원격"이 붙은 버전이라고 보면 됩니다. 한 번 쳐서 파일 하나를 휙 보내고 끝나는, 가장 단순한 방식이에요.
원격 경로를 적는 법만 새로 익히면 돼요. 사용자@서버주소:경로 형태입니다. 콜론(:) 뒤가 서버 안의 경로예요.
# 내 컴퓨터의 파일 하나를 원격 서버로 올리기
scp report.txt deploy@203.0.113.10:/home/deploy/
# 폴더를 통째로 올리기 (-r = 재귀, cp 의 -r 과 똑같다)
scp -r mysite/ deploy@203.0.113.10:/var/www/
# 반대로, 원격 서버의 로그를 내 컴퓨터로 내려받기
scp deploy@203.0.113.10:/var/log/app.log ./
방향은 "보내는 쪽을 먼저, 받는 쪽을 나중에" 적으면 돼요. cp 원본 목적지와 순서가 똑같죠. 올릴 땐 원격 주소가 뒤에, 내려받을 땐 원격 주소가 앞에 옵니다.
⚠️ 한 가지 함정이 있어요. SSH는 포트를 바꿀 때 소문자
-p를 쓰지만,scp는 대문자-P를 씁니다. 서버가 22번이 아닌 다른 포트를 쓴다면scp -P 2222 ...처럼요. 신입 때 이거 때문에 "분명 SSH는 됐는데 scp만 안 돼요" 하고 한참 헤매는 경우가 많아요.
sftp — 원격을 탐색하며 주고받기
scp가 "한 방에 복사"라면, sftp(SSH File Transfer Protocol)는 원격 서버 안을 돌아다니며 대화하듯 파일을 주고받는 방식이에요. sftp 사용자@주소로 접속하면 전용 프롬프트로 들어가는데, 그 안에서 마치 서버 안에 있는 것처럼 ls·cd로 둘러보다가 원하는 파일을 올리고(put) 내려받습니다(get).
sftp deploy@203.0.113.10
# 접속하면 sftp> 프롬프트로 바뀐다. 그 안에서:
# sftp> ls 원격 서버의 현재 폴더 목록 보기
# sftp> cd /var/log 원격 폴더 이동
# sftp> get app.log 원격 파일을 내 컴퓨터로 내려받기
# sftp> put report.txt 내 파일을 원격 서버로 올리기
# sftp> bye 세션 종료
"어디에 뭐가 있는지 모를 때, 둘러보면서 골라 받고 싶을 때" 편해요. 반대로 "뭘 보낼지 이미 정확히 안다"면 굳이 들어갔다 나올 것 없이 scp 한 줄이 빠르고요.
rsync — 바뀐 것만 똑똑하게 동기화
세 번째가 오늘의 주인공 rsync(remote sync, 원격 동기화)예요. scp·sftp가 "통째로 복사"라면, rsync는 양쪽을 비교해서 바뀐 부분만 골라 보냅니다. 폴더에 파일이 100개 있는데 그중 1개만 고쳤다면, rsync는 그 1개만 보내요. 이게 왜 중요하냐면, 매번 전체를 복사하면 느리고 네트워크도 낭비되거든요. 그래서 현업에서 "서버에 코드·정적 파일을 반복 배포"할 때 rsync가 사실상 표준입니다.
# -a 권한·시간 등 속성 보존 · -v 진행 상황 표시 · -z 전송 중 압축
rsync -avz mysite/ deploy@203.0.113.10:/var/www/mysite/
# 진짜 보내기 전에 "무엇이 바뀔지" 미리보기 (실제 전송 안 함)
rsync -avz --dry-run mysite/ deploy@203.0.113.10:/var/www/mysite/
-avz는 거의 항상 같이 붙어 다녀요. -a는 파일의 권한·수정 시간까지 그대로 보존하고(지난 시간 배운 권한 비트 기억나시죠?), -v는 무엇이 전송되는지 보여주고, -z는 보내는 동안 압축해서 더 빠르게요.
특히 --dry-run이 신입을 구해주는 옵션이에요. 운영 서버에 잘못 덮어쓰면 큰일이니, 진짜로 보내기 전에 "이러이러한 파일이 바뀔 예정"이라고 미리 보여줍니다. 위험한 작업일수록 한 번 확인하고 친다 — 지난 시간들에서 계속 강조한 그 습관이에요.
그래서 언제 무엇을 쓸까
세 도구를 한 표로 정리할게요. 처음엔 scp 하나만 손에 익혀도 충분하고, 반복 배포가 잦아지면 rsync로 넘어가면 됩니다.
| 도구 | 성격 | 이럴 때 |
|---|---|---|
scp |
한 방에 통째로 복사 | 파일 한두 개를 빠르게 올리고 내릴 때 |
sftp |
대화형으로 둘러보며 주고받기 | 서버에 뭐가 있는지 모를 때, 골라서 받고 싶을 때 |
rsync |
바뀐 부분만 동기화 | 폴더를 반복 배포할 때, 큰 디렉토리를 효율적으로 보낼 때 |
현업에선 "배포 스크립트"라는 걸 짜는데, 그 안에 십중팔구
rsync한 줄이 들어가요. 빌드한 결과물을 서버로rsync하고, 서버에서 서비스를 재시작하는 흐름이죠. 오늘은 명령 하나하나를 익히지만, 다음 시간(이 과목 마지막)엔 이걸 bash 스크립트로 엮어 자동화하게 됩니다.
💡 한 줄 정리
원격 파일 전송은 지난 시간 연 SSH 통로(22번 포트·키)를 그대로 탄다. scp는 한 방에 통째로 복사, sftp는 둘러보며 대화형으로, rsync -avz는 바뀐 부분만 똑똑하게 동기화한다. 위험할 땐 rsync --dry-run으로 미리보기.
🙋 학생 질문 — "scp 로 폴더를 올렸더니 엄청 오래 걸려요. rsync 면 빨랐을까요?"
상황에 따라 크게 빨라져요. scp는 똑똑하지 않아서, 이미 서버에 똑같이 있는 파일이라도 매번 처음부터 전부 다시 보냅니다. 폴더가 크고 그중 일부만 바뀌었다면 시간 낭비가 크죠.
rsync는 양쪽을 먼저 비교해서 "달라진 부분"만 골라 보내요. 그래서 두 번째 전송부터는 훨씬 빨라집니다. 예를 들어 1GB짜리 폴더에서 파일 하나(1MB)만 고쳤다면, scp는 1GB를 통째로 다시 보내지만 rsync는 그 1MB 근처만 보내요. 처음 한 번은 둘 다 전체를 보내니 비슷하지만, 반복할수록 rsync의 이점이 커집니다. "한 번 보내고 끝"이면 scp, "계속 갱신하며 보낸다"면 rsync라고 기억하세요.
Step 2: "이 서버, 웹이 살아는 있나?"
파일을 주고받는 법을 익혔으니, 이번엔 다른 종류의 일이에요. 서버에 웹 서비스를 띄웠는데, "이게 제대로 응답하고 있나?"를 확인하고 싶어요. 브라우저로 열어볼 수도 있지만, 화면 없는 서버 안에선 브라우저가 없죠. 그래서 터미널에서 직접 웹 요청을 던져보는 도구가 필요합니다. 그게 curl이에요.
먼저, 웹 요청은 어떻게 오가나 (HTTP 한 걸음)
curl을 배우기 전에 그 밑바닥을 잠깐 짚을게요. 우리가 브라우저에서 주소를 치면, 내 컴퓨터는 서버에게 "이 주소의 내용을 줘"라고 요청(request)을 보내고, 서버는 응답(response)을 돌려줍니다. 이 요청과 응답의 약속이 바로 HTTP예요. 지난 시간 배운 80번(HTTP)·443번(HTTPS) 포트가 이 대화가 오가는 문이었죠.
그런데 응답에는 내용(HTML 같은 본문)만 오는 게 아니에요. 맨 앞에 상태 코드(status code)라는 세 자리 숫자가 함께 옵니다. "잘 됐어"인지 "그런 거 없어"인지 "서버가 터졌어"인지를 알려주는 신호등 같은 거예요.
HTTP 상태 코드 — 응답의 신호등
2xx 성공 200 OK 정상 응답 (가장 보고 싶은 숫자)
3xx 다른 곳으로 301 / 302 "주소가 바뀌었어, 저쪽으로 가"
4xx 요청이 잘못 404 Not Found "그런 주소(페이지) 없어"
401 / 403 "로그인 안 됐어 / 권한 없어"
5xx 서버가 잘못 500 / 502 / 503 "서버 안에서 문제가 터졌어"
신입이 현업에서 가장 자주 만나는 게 404와 500이에요. 404는 "내가 주소를 잘못 쳤나?"(요청 쪽 문제), 500은 "서버 코드가 터졌나?"(서버 쪽 문제) 로 책임 소재가 갈려요. 이 숫자만 봐도 어디부터 봐야 할지 방향이 잡힙니다.
curl — 터미널에서 URL 두드리기
curl은 주소 하나를 주면 그 응답을 그대로 터미널에 뿌려줘요. 가장 단순한 형태는 주소만 적는 겁니다.
# 응답 본문(HTML 등)을 그대로 출력
curl https://example.com
그런데 우리가 진짜 알고 싶은 건 본문보다 "상태 코드와 헤더"일 때가 많아요. 서버가 살아있는지, 무슨 응답을 주는지요. 그때 -i(include, 헤더 포함)를 붙입니다.
# 응답 헤더 + 본문 함께 보기 (-i = include headers)
curl -i https://example.com
이렇게 치면 맨 윗줄에 상태 코드가 뜨고, 그 아래로 헤더들이 따라옵니다.
HTTP/2 200
date: Wed, 17 Jun 2026 05:41:04 GMT
content-type: text/html
server: cloudflare
...
(빈 줄 아래로 HTML 본문)
맨 윗줄 HTTP/2 200 — 이 200이 바로 "정상"이라는 신호예요. 만약 없는 주소를 치면 404가, 서버가 터졌으면 500이 거기에 뜹니다. 본문 없이 상태와 헤더만 빠르게 보고 싶으면 -I(대문자, HEAD 요청)를 쓰고요.
자주 쓰는 옵션 두 개만 더 보겠습니다.
# 헤더를 직접 실어 보내기 (-H) — API 를 두드릴 때 인증 토큰 등을 붙인다
curl -H "Authorization: Bearer 토큰값" https://api.example.com/me
# 리다이렉트(3xx)를 자동으로 따라가기 (-L)
curl -L https://example.com
지난 시간들에서 배운 파이프(|)도 여기서 빛을 발해요. 응답이 길면 grep으로 원하는 줄만 거를 수 있죠.
# 응답 헤더에서 상태 줄과 서버 종류만 콕 집어 보기
curl -sI https://example.com | grep -E "HTTP|server"
-s(silent)는 진행률 표시를 숨겨 출력을 깔끔하게 만들어요. A-4에서 배운 "작은 도구를 파이프로 잇는다"는 유닉스 철학이 그대로 이어지죠.
wget — 파일을 받아 저장하는 데 특화
curl과 자주 짝지어 언급되는 게 wget이에요. 둘 다 URL을 다루지만 성격이 조금 달라요. curl이 "응답을 화면에 뿌리는" 데 강하다면, wget은 "파일을 받아 디스크에 저장"하는 데 특화돼 있어요.
# URL 의 내용을 파일로 저장 (-O = 출력 파일 지정)
wget -O ubuntu.iso https://releases.ubuntu.com/26.04/ubuntu-26.04-server.iso
# 그냥 wget URL 만 쳐도 원래 파일 이름 그대로 저장된다
wget https://example.com/data.zip
현업 감각으로 정리하면 이래요. "서버가 무슨 응답을 주는지 확인·디버깅"하려면 curl -i, "설치 파일이나 데이터를 받아 저장"하려면 wget. 둘 다 알아두면 상황에 맞게 골라 쓰면 됩니다. (wget은 우분투에 보통 기본 설치돼 있고, 없으면 지난 시간 배운 sudo apt install wget으로 깔면 돼요.)
💡 한 줄 정리
curl은 터미널에서 URL을 두드려 응답을 확인하는 도구다. curl -i로 상태 코드와 헤더를 보고, 200(성공)·404(주소 없음)·500(서버 오류)으로 어디가 문제인지 가린다. 파일을 받아 저장할 땐 wget -O를 쓴다.
🙋 학생 질문 — "curl 로 우리 서버를 쳤더니 connection refused 가 떠요. 404 와 뭐가 다른가요?"
아주 중요한 차이예요. 둘은 막힌 단계가 완전히 달라요.
404는 일단 서버까지는 잘 도착했다는 뜻이에요. 서버가 받아서 "그런 주소는 없네"라고 404라는 답을 정상적으로 돌려준 거죠. 즉 서버는 살아있어요.
connection refused(연결 거부)는 그보다 앞 단계에서 막힌 거예요. 그 포트에서 받아주는 프로그램이 아예 없거나, 방화벽이 문을 닫아둔 거죠. 비유하면 404는 "건물에 들어가 물어봤더니 그런 사무실 없대"이고, connection refused는 "건물 문 자체가 잠겨 있어 들어가지도 못함"이에요. 이때 의심할 곳은 둘이에요. 서버 프로그램이 안 떠 있거나(지난 시간 ss -ltnp로 포트 확인), 방화벽이 막고 있거나 — 바로 다음 Step에서 배울 ufw죠.
Step 3: "아무나 못 들어오게 문을 여닫자"
방금 질문에서 connection refused 이야기가 나왔죠. 그 원인 중 하나가 방화벽이에요. 이번 Step에서 그 방화벽을 직접 다뤄봅니다.
방화벽이란 — 포트마다 서 있는 문지기
지난 시간 포트를 "건물 안의 호실 번호"에 비유했어요. 그런데 호실이 열려 있으면 아무나 노크할 수 있겠죠. 실제로 인터넷에 연결된 서버에는 하루에도 수천 번씩 "혹시 문 열렸나?" 하고 두드려보는 자동 공격이 들어와요. 그래서 필요한 문만 열고 나머지는 다 잠가두는 장치가 필요한데, 그게 방화벽(firewall)입니다.
방화벽 = 포트마다 서 있는 문지기
바깥 인터넷 ──▶ [ 방화벽 ] ──▶ 내 서버의 포트들
│ 22 (SSH) 허용 → 통과
│ 80 (HTTP) 허용 → 통과
│ 3306 (DB) 차단 → 막힘
└ 정해둔 규칙대로 통과시키거나 막는다
우분투의 표준 방화벽 도구가 ufw(Uncomplicated Firewall, 간단한 방화벽)예요. 이름 그대로, 복잡한 방화벽 설정을 쉬운 명령 몇 개로 다룰 수 있게 만든 도구죠. 방화벽 설정을 바꾸는 일이라 거의 항상 sudo가 필요해요(지난 시간 배운 그 sudo 맞아요).
ufw 기본 사용법
가장 먼저 현재 상태부터 봅니다.
# 현재 방화벽 상태와 규칙 보기
sudo ufw status
처음엔 보통 Status: inactive(꺼짐)로 나와요. 규칙을 먼저 정해두고 켜는 순서로 갑니다. 포트를 여는 명령은 allow예요.
# 22번(SSH) 포트 열기 — 'OpenSSH' 라는 이름으로도 같은 효과
sudo ufw allow 22/tcp
# 80번(HTTP) 열기 — 지난 시간 nginx 가 쓰던 그 포트
sudo ufw allow 80/tcp
규칙을 정했으면 방화벽을 켭니다.
# 방화벽 켜기
sudo ufw enable
켜고 나서 sudo ufw status를 다시 보면 이렇게 나와요.
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
80/tcp ALLOW Anywhere
ufw의 기본 정책은 들어오는 연결은 기본 차단, 나가는 연결은 기본 허용이에요. 그래서 우리가 allow로 열어준 22번·80번만 바깥에서 들어올 수 있고, 나머지는 다 막힙니다. 잘못 연 문을 닫거나 규칙을 지우는 것도 간단해요.
# 특정 포트 차단
sudo ufw deny 23/tcp
# 이전에 만든 규칙 삭제
sudo ufw delete allow 80/tcp
⚠️ 신입이 반드시 한 번은 당하는 사고 — SSH 잠그기
여기서 정말 중요한 안전 수칙 하나. 원격 서버에서 방화벽을 켤 땐, SSH 포트(22번)를 반드시 먼저 열고 나서 enable 해야 해요. 만약 22번을 안 열고 sudo ufw enable을 치면, 들어오는 연결이 전부 차단되면서 지금 내가 접속해 있는 SSH 연결까지 끊겨버립니다. 그러면 다시 들어갈 수도 없어요. 화면도 키보드도 없는 원격 서버라 직접 가서 풀 수도 없죠.
원격 서버에서 방화벽 켜는 순서 — SSH 부터 열어야 안 잠긴다
안전한 순서:
sudo ufw allow 22/tcp ← ① 먼저 SSH(22번) 문을 연다
sudo ufw enable ← ② 그다음 방화벽을 켠다
사고 나는 순서:
sudo ufw enable ← 22번을 안 연 채 켜면…
→ 들어오는 SSH 연결까지 끊겨 서버에 잠긴다
이건 겁주려는 게 아니라, 진짜 현업에서 신입이 한 번씩 겪는 통과의례예요. 그래서 ufw는 enable 직전에 "SSH 연결이 끊길 수 있는데 진행할래?"라고 한 번 물어봐 주기도 해요. 그 경고가 뜨면 "아, 22번 열었나?" 하고 점검하는 신호로 받아들이면 됩니다. 천천히 확인하고 친다 — 리눅스에서 늘 강조하는 그 습관이 방화벽에선 특히 중요해요.
여기서 지난 시간들과의 연결이 보이죠. ufw로 여는 포트가 곧 서비스 포트예요. SSH를 쓰니까 22번을 열고, 웹 서버(nginx)를 띄웠으니 80번을 엽니다. 포트를 잡은 프로세스를 ss -ltnp로 확인하던 것(A-7·A-9), nginx를 80번에 띄우던 것(A-8) — 그 포트들이 그대로 방화벽 규칙이 되는 거예요.
💡 한 줄 정리
방화벽은 포트마다 선 문지기다. 우분투에선 ufw로 allow(열기)·deny(닫기)·status(상태)·enable(켜기)을 다룬다. 기본 정책은 들어오는 연결 차단이라, 여는 포트가 곧 서비스 포트(SSH 22·HTTP 80)다. 원격에서 켤 땐 22번을 먼저 열어야 잠기지 않는다.
🙋 학생 질문 — "방화벽으로 포트를 다 막아두면 그냥 안전한 거 아닌가요? 인증이 왜 또 필요해요?"
좋은 질문이에요. 방화벽은 보안의 한 겹일 뿐, 전부가 아니에요.
생각해보면 서비스를 하려면 어떤 문은 반드시 열어둬야 해요. 웹 서버라면 80·443번을, 원격 관리를 하려면 22번(SSH)을요. 그 열어둔 문으로는 누구나 노크할 수 있어요. 그래서 "문을 여닫는 것(방화벽)"과 "들어온 사람이 진짜 권한이 있는지 확인하는 것(인증)"은 서로 다른 일이에요.
비유하면 방화벽은 건물 정문의 출입 통제이고, 인증(지난 시간 SSH 키)은 각 사무실 문의 열쇠예요. 정문을 통제해도 사무실마다 열쇠가 필요하죠. 그래서 진짜 보안은 한 겹이 아니라 여러 겹이에요. 방화벽으로 불필요한 문을 닫고(노출 면적 줄이기), 열어둔 문은 키 인증으로 지키고(들어온 사람 검증) — 둘을 같이 써야 합니다. 이걸 현업에선 "심층 방어(defense in depth)"라고 불러요.
Step 4: "컨테이너는 결국 무엇일까"
오늘로 리눅스 한 대를 셸로 다루는 여정이 거의 끝나가요. 파일을 주고받고, 웹으로 두드려보고, 방화벽으로 문을 여닫았죠. 마지막으로, 다음 과목으로 넘어가기 전에 요즘 어디서나 들리는 그 단어 — 컨테이너(container) — 가 리눅스 입장에서 결국 무엇인지 한 걸음만 짚고 갈게요. 오늘은 개념만 잡고, 실제로 만들고 띄우는 실습은 다음 과목(인프라)에서 본격적으로 다룹니다.
컨테이너 = 격리된 리눅스 프로세스
흔히 컨테이너를 "가벼운 가상 머신"이라고 오해해요. 그런데 정확히는 달라요. 가상 머신은 운영체제를 통째로 하나 더 돌리는 거지만, 컨테이너는 그냥 리눅스 위에서 도는 평범한 프로세스 하나예요. 지난 시간 배운 그 프로세스(PID를 가진 일하는 직원) 맞아요. 다만 두 가지 리눅스 기능으로 "자기만의 세상에 갇혀 있는 것처럼" 보이게 만든 프로세스죠.
컨테이너 = 프로세스 + 격리(namespace) + 자원 제한(cgroup)
[ 평범한 리눅스 프로세스 ]
+ namespace → "자기만의 파일시스템·네트워크·프로세스 목록이
있는 것처럼" 격리해서 보여준다
+ cgroup → "CPU·메모리를 이만큼만 써라" 자원에 울타리를 친다
─────────────────────────────────────────────
= 한 리눅스 위에서 서로 간섭 없이 도는 격리된 프로세스
두 가지만 기억하면 돼요. namespace(네임스페이스)는 격리예요. 한 프로세스에게 "이 파일시스템, 이 네트워크, 이 프로세스 목록이 네 전부야"라고 자기만의 세상을 보여줘요. 옆 컨테이너는 보이지도 않죠. cgroup(control group, 제어 그룹)은 자원 제한이에요. "너는 CPU 1개, 메모리 512MB만 써"라고 울타리를 칩니다. 이 두 리눅스 커널 기능을 묶어서 "격리되고 자원이 통제된 프로세스"를 만든 게 컨테이너의 본질이에요.
그래서 오늘 배운 게 컨테이너 안에서도 그대로 통해요. 컨테이너 안에서도 포트를 열고(방화벽·ufw의 개념), curl로 두드리고, 파일을 주고받죠. 컨테이너가 결국 리눅스니까요. 여러분이 이 과목에서 익힌 셸·파일·권한·프로세스·네트워크 기본기가 컨테이너를 다룰 때 그대로 바탕이 됩니다.
여기까지가 이 과목, 그다음은 인프라 과목
컨테이너를 만들고(이미지), 여러 개를 묶어 띄우고, 수십 대 서버에 자동 배포하는 본격적인 도구들 — 도커(Docker)·쿠버네티스(Kubernetes) — 는 다음 과목인 인프라에서 다뤄요. 이 과목의 사명은 "그 모든 것이 결국 올라타는 리눅스 한 대를 셸로 자유롭게 다루는 기본기"까지였어요. 그 바탕이 단단하면, 컨테이너도 "아, 결국 격리된 리눅스 프로세스구나" 하고 편하게 받아들일 수 있습니다.
💡 한 줄 정리
컨테이너는 가상 머신이 아니라 리눅스 위에서 도는 격리된 프로세스다. namespace로 자기만의 세상처럼 격리하고, cgroup으로 자원을 제한한다. 도커·쿠버네티스 같은 본격 도구는 다음 인프라 과목의 몫이고, 이 과목은 그 바탕이 되는 리눅스 기본기를 책임진다.
🙋 학생 질문 — "그럼 컨테이너랑 가상 머신은 정확히 뭐가 달라요? 둘 다 격리된 거 아닌가요?"
핵심은 "운영체제를 따로 돌리느냐"예요.
가상 머신은 내 컴퓨터 위에 가짜 컴퓨터를 통째로 하나 더 만들어요. 그 안에 운영체제(우분투든 윈도우든)를 처음부터 끝까지 따로 설치하죠. 그래서 무겁고, 켜는 데도 수십 초가 걸려요. 대신 완전히 분리돼 있어요.
컨테이너는 운영체제를 따로 돌리지 않아요. 바탕이 되는 리눅스 커널 하나를 여러 컨테이너가 공유하면서, 아까 말한 namespace·cgroup으로 "각자 격리된 것처럼" 보일 뿐이에요. 운영체제를 새로 안 켜니까 훨씬 가볍고, 1초도 안 돼서 뜹니다. 그래서 서버 한 대에 컨테이너 수십 개를 띄울 수 있어요. 다만 커널을 공유하니 격리 수준은 가상 머신보다 조금 약하죠. "무겁지만 완전히 분리 = 가상 머신, 가볍고 빠른 격리 = 컨테이너"라고 기억하면 충분해요. 더 깊은 비교는 다음 인프라 과목에서 만나요.
마무리
오늘은 원격 서버에 들어간 뒤 실제로 "운영"하는 도구들을 손에 익혔어요. 지난 시간 연 SSH 통로 위로 파일을 주고받고, 웹으로 서버를 두드려 상태를 확인하고, 방화벽으로 문을 여닫았죠. 그리고 마지막엔 컨테이너가 결국 격리된 리눅스 프로세스라는 걸 짚으며 다음 과목으로 가는 다리를 놓았고요. 핵심을 셋으로 정리할게요.
오늘 배운 핵심 세 가지
💡 하나 — 원격 파일 전송은 지난 시간 연 SSH 통로(22번 포트·키)를 그대로 탄다. scp는 한 방에 통째로 복사, sftp는 둘러보며 대화형으로, rsync -avz는 바뀐 부분만 동기화한다. 위험할 땐 rsync --dry-run으로 미리 확인한다.
💡 둘 — curl로 터미널에서 URL을 두드려 응답을 확인한다. curl -i로 상태 코드와 헤더를 보고, 200(성공)·404(주소 없음)·500(서버 오류)으로 문제의 책임 소재를 가린다. 파일을 받아 저장할 땐 wget -O를 쓴다.
💡 셋 — 방화벽은 포트마다 선 문지기다. ufw로 allow·deny·status·enable을 다루고, 여는 포트가 곧 서비스 포트(SSH 22·HTTP 80)다. 원격에서 켤 땐 22번을 먼저 열어야 스스로를 잠그지 않는다.
다음 시간 예고
자, 이제 여러분은 리눅스 셸로 거의 모든 걸 할 수 있게 됐어요. 파일을 다루고, 권한을 이해하고, 텍스트를 가공하고, 프로세스를 들여다보고, 서비스를 관리하고, 원격 서버에 들어가 파일·웹·방화벽까지 운영하죠. 그런데 여기까지 배운 명령들을 매번 손으로 하나씩 치자니, 같은 일을 반복할 때 번거롭지 않나요?
다음 시간부터는 이 과목을 마무리하는 bash 스크립팅이에요. 분량이 넉넉해서 두 번에 걸쳐 진행해요. 오늘 배운 scp·curl·ufw, 그리고 지금까지 익힌 모든 명령을 스크립트 파일 하나로 엮어 자동으로 실행하는 법을 배우죠. 먼저 스크립트를 짜고 변수에 값을 담는 기본기를 다진 뒤, "매일 밤 서버 로그를 백업하고, 디스크가 꽉 찼는지 점검하고, 서비스가 살아있는지 확인하는" 그런 반복 작업을 사람이 아니라 스크립트가 알아서 하게 만들어요. 지금까지 모은 재료들을 드디어 하나의 요리로 묶는 피날레입니다. 다음 시간에 만나요.
과제
오늘 과제는 전부 여러분 자신의 리눅스 환경(WSL2·VM·맥 터미널·클라우드)에서 직접 쳐보는 실습이에요. 원격 서버가 없어도 괜찮아요 — curl은 인터넷만 되면 어디서나 되고, 파일 전송은 내 컴퓨터 안 두 폴더 사이로도 연습할 수 있습니다. 위험한 명령은 없으니 편하게 해보세요.
[기초] curl 로 웹을 두드려 상태 코드 읽기
내 터미널에서 실제 웹사이트에 요청을 던져 응답을 읽어보세요.
curl -i https://example.com을 쳐서, 맨 윗줄에 뜨는 상태 코드가200인지 확인한다.curl -i https://example.com/없는주소아무거나를 쳐서, 이번엔 어떤 상태 코드가 뜨는지 본다. (404가 나올 거예요.)curl -sI https://example.com | grep server로, 그 사이트가 어떤 종류의 서버를 쓰는지 헤더 한 줄만 뽑아본다.- 마지막으로 평소 자주 가는 사이트 하나를
curl -I로 두드려, 상태 코드가 200인지 3xx(리다이렉트)인지 살펴본다.
[응용] 파일 전송과 rsync 미리보기 연습
원격 서버가 없어도, 내 컴퓨터 안 두 폴더 사이로 rsync를 연습할 수 있어요.
mkdir -p ~/practice/src ~/practice/dst로 연습용 폴더 둘을 만든다.~/practice/src안에 파일 두세 개를 만든다(touch ~/practice/src/a.txt ~/practice/src/b.txt등).rsync -av ~/practice/src/ ~/practice/dst/로 한쪽을 다른 쪽으로 동기화하고, 무엇이 전송됐는지 출력을 읽어본다.- 이번엔
src의 파일 하나만 고친 뒤(또는 새 파일 하나 추가),rsync -av --dry-run ~/practice/src/ ~/practice/dst/를 쳐서 "이번엔 무엇만 전송될 예정인지" 미리보기를 확인한다. 바뀐 파일만 잡히는지 눈으로 보세요.
[심화] 방화벽 설정 시나리오 (서버 상황 상상)
서버 상황을 상상해봅시다. "회사에서 우분투 서버 한 대를 받았다. 여기에 SSH(22번)로 접속하고, 웹 서버(80번)를 띄울 예정이다. 방화벽을 켜서 그 두 문만 열고 나머지는 다 막고 싶다." 실제 서버나 VM이 있다면 해보고, 없다면 명령 순서를 글로 정리해보세요.
- 방화벽을 켜기 전에 어떤 포트부터 열어야 하는지, 그 순서가 왜 중요한지 적는다. (힌트: 22번을 안 열고 켜면?)
ufw로 22번과 80번을 열고, 방화벽을 켜고,status로 규칙을 확인하는 전체 명령을 순서대로 적는다.- 만약 나중에 80번 웹 서버를 내리기로 했다면, 그 규칙을 어떻게 지울지 적는다.
- 마지막으로 "방화벽으로 포트를 다 막아도 왜 SSH 키 인증이 여전히 필요한지"를 두세 문장으로 정리해본다.
생각해볼 주제
1. scp 와 rsync, 매번 무엇을 쓸지 어떻게 정할까
오늘 우리는 scp(한 방에 통째로 복사)와 rsync(바뀐 부분만 동기화)를 둘 다 배웠어요. 둘 다 파일을 보내는 도구인데, 현업에서 배포 작업을 한다면 어느 쪽이 더 자주 쓰일까요? 파일 하나를 딱 한 번 보내는 경우와, 큰 폴더를 하루에도 여러 번 갱신해 보내는 경우를 나눠서 생각해보세요. 그리고 rsync가 "바뀐 부분만 보낸다"는 게 네트워크가 느리거나 파일이 아주 클 때 어떤 차이를 만드는지, "단순함(scp)"과 "효율(rsync)" 사이의 선택이라는 관점에서 정리해보세요.
2. 방화벽으로 막는 것과 인증으로 지키는 것은 어떻게 다를까
어떤 사람은 "방화벽으로 포트를 다 막으면 그걸로 보안 끝 아니냐"고 생각합니다. 그런데 서비스를 하려면 어떤 문(SSH 22·웹 80)은 반드시 열어둬야 하죠. 그 열어둔 문으로는 누구나 노크할 수 있습니다. "문을 여닫는 일(방화벽)"과 "들어온 사람이 진짜 권한이 있는지 확인하는 일(키 인증)"이 어떻게 다른 층의 보안인지 생각해보세요. 그리고 둘 중 하나만으로는 왜 부족한지, "여러 겹으로 지킨다(심층 방어)"는 게 실무에서 왜 기본인지 정리해보세요.
3. 컨테이너가 "가벼운 가상 머신"이 아니라 "격리된 프로세스"라는 구분이 왜 중요할까
컨테이너를 흔히 "가벼운 가상 머신"이라고 부르지만, 오늘 우리는 그게 정확히는 "리눅스 위에서 도는 격리된 프로세스"라는 걸 봤어요. 이 구분이 단순한 용어 정리를 넘어 왜 중요할까요? 컨테이너가 운영체제를 따로 돌리지 않고 리눅스 커널을 공유한다는 사실이, 컨테이너가 왜 그렇게 가볍고 빨리 뜨는지, 또 왜 격리 수준이 가상 머신과는 조금 다른지와 어떻게 연결되는지 생각해보세요. "컨테이너는 결국 리눅스 프로세스"라는 한 줄을 이해하면, 다음 과목에서 만날 도커가 훨씬 덜 낯설 거예요.
✅ 예시 답안정답 보기
과제와 생각해볼 주제의 예시답안입니다. 원격 운영 도구는 글로 보면 간단해 보여도, 직접 파일을 보내보고 curl로 응답을 읽어봐야 손에 익어요. 출력의 숫자(바이트 수·날짜·IP)는 여러분 환경에 따라 다른 게 당연하니, 값보다 흐름이 맞는지를 보면 됩니다. 원격 서버가 없어도 curl은 인터넷만 되면 되고, 파일 전송은 내 컴퓨터 안 두 폴더로도 연습할 수 있어요.
🎯 [과제 1 예시답안] curl 로 웹을 두드려 상태 코드 읽기
채점 포인트
| 확인 항목 | 무엇을 보면 되는가 |
|---|---|
| 정상 응답 | curl -i의 맨 윗줄에서 200을 확인했는가 |
| 404 응답 | 없는 주소를 쳐서 404가 뜨는 걸 봤는가 |
| 헤더 한 줄 뽑기 | curl -sI ... | grep으로 server 헤더만 골라냈는가 |
| 리다이렉트 | curl -I로 200인지 3xx(301/302)인지 구분했는가 |
풀이 예시
$ curl -i https://example.com
HTTP/2 200
date: Wed, 17 Jun 2026 05:41:04 GMT
content-type: text/html
server: cloudflare
...
(빈 줄 아래로 HTML 본문)
$ curl -i https://example.com/없는주소아무거나
HTTP/2 404
content-type: text/html
...
$ curl -sI https://example.com | grep server
server: cloudflare
$ curl -I http://github.com
HTTP/1.1 301 Moved Permanently
location: https://github.com/
맨 윗줄의 세 자리 숫자가 핵심이에요. 200은 정상, 404는 "그런 주소 없음"이죠. curl -sI ... | grep server는 A-4에서 배운 "파이프로 원하는 줄만 거르기"가 그대로 쓰인 거고요. 마지막 github.com은 301(영구 이동)과 함께 location 헤더로 "진짜 주소는 https://github.com/"라고 알려줘요. 여기에 -L을 붙이면 그 주소로 자동으로 따라갑니다.
💡 튜터의 한마디: 현업에서 "서버가 이상해요"라는 말을 들으면 가장 먼저 curl -i로 두드려봐요. 200이면 "서버는 멀쩡한데 다른 문제", 404면 "주소를 잘못 불렀나", 500이면 "서버 코드가 터졌나", 연결 자체가 안 되면 "서버가 죽었거나 방화벽이 막았나". 이 한 줄이 문제를 어디서부터 봐야 할지 방향을 잡아줍니다.
🎯 [과제 2 예시답안] 파일 전송과 rsync 미리보기 연습
채점 포인트
| 확인 항목 | 무엇을 보면 되는가 |
|---|---|
| 연습 폴더 준비 | src·dst 두 폴더와 연습 파일을 만들었는가 |
| 첫 동기화 | rsync -av로 파일이 전송되는 출력을 봤는가 |
| 변경 후 미리보기 | 파일 하나 추가 후 --dry-run에서 그것만 잡히는지 확인했는가 |
| 흐름 이해 | "바뀐 것만 보낸다"를 출력으로 눈으로 확인했는가 |
풀이 예시
$ mkdir -p ~/practice/src ~/practice/dst
$ touch ~/practice/src/a.txt ~/practice/src/b.txt
$ rsync -av ~/practice/src/ ~/practice/dst/
sending incremental file list
./
a.txt
b.txt
sent 213 bytes received 64 bytes 554.00 bytes/sec
total size is 0 speedup is 0.00
$ echo "hello" > ~/practice/src/c.txt
$ rsync -av --dry-run ~/practice/src/ ~/practice/dst/
sending incremental file list
c.txt
sent 165 bytes received 26 bytes 382.00 bytes/sec
total size is 6 speedup is 0.03 (DRY RUN)
핵심은 두 번째 rsync예요. 첫 동기화 땐 a.txt·b.txt가 둘 다 전송됐지만, c.txt 하나만 새로 추가한 뒤 --dry-run을 돌리니 바뀐 c.txt만 목록에 떴죠. 맨 끝의 (DRY RUN) 표시는 "실제로는 안 보냈고 미리보기만 했다"는 뜻이에요. 이게 rsync가 scp와 다른 점이에요 — 이미 같은 파일은 건너뛰고 달라진 것만 골라 보냅니다.
💡 튜터의 한마디: --dry-run은 운영 서버에 배포하기 전 꼭 한 번 거치는 안전벨트예요. 진짜로 덮어쓰기 전에 "무엇이 바뀔 예정인지"를 먼저 보여주니까요. 위험한 명령일수록 치기 전에 한 번 확인한다 — 리눅스를 다루는 내내 강조한 그 습관이 파일 전송에서도 똑같이 통합니다.
🎯 [과제 3 예시답안] 방화벽 설정 시나리오
채점 포인트
| 확인 항목 | 무엇을 보면 되는가 |
|---|---|
| 순서의 이유 | SSH(22번)를 켜기 전에 먼저 열어야 하는 이유를 적었는가 |
| 전체 명령 | 22·80 열기 → enable → status 순서를 바르게 적었는가 |
| 규칙 삭제 | 80번 규칙을 지우는 delete를 적었는가 |
| 보안 정리 | 방화벽과 키 인증이 다른 층의 보안임을 설명했는가 |
풀이 예시
# ① 방화벽을 켜기 '전에' 반드시 SSH(22번)부터 연다
sudo ufw allow 22/tcp
# ② 웹 서버용 80번도 연다
sudo ufw allow 80/tcp
# ③ 이제 방화벽을 켠다 (22번을 열어뒀으니 SSH 연결이 끊기지 않는다)
sudo ufw enable
# ④ 규칙을 확인한다
sudo ufw status
status 출력은 이렇게 나와요.
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
80/tcp ALLOW Anywhere
나중에 웹 서버를 내려 80번을 닫는다면 이렇게 지웁니다.
sudo ufw delete allow 80/tcp
순서가 왜 중요하냐면, ufw의 기본 정책이 "들어오는 연결은 다 차단"이라서예요. 22번을 안 연 채 enable하면 지금 접속해 있는 SSH까지 끊겨 원격 서버에 영영 못 들어가요. 그래서 SSH부터 열고 켜는 순서가 생명줄입니다.
마지막으로, 방화벽으로 포트를 막아도 키 인증이 여전히 필요한 이유 — 서비스를 하려면 22번·80번 같은 문은 반드시 열어둬야 하고, 그 열린 문으로는 누구나 노크할 수 있어요. 방화벽은 "어떤 문을 열지" 정하는 일이고, 키 인증은 "열린 문으로 들어온 사람이 진짜 권한이 있는지" 확인하는 일이에요. 둘은 서로 다른 층의 보안이라 함께 써야 합니다.
💡 튜터의 한마디: "SSH부터 열고 방화벽 켜기"는 신입이 원격 서버에서 한 번씩 잠가먹고 배우는 교훈이에요. 다행히 우분투의 ufw는 enable 직전에 "SSH 연결이 끊길 수 있다"고 경고해줘요. 그 경고가 뜨면 "22번 열었나?" 점검하는 신호로 받아들이면, 잠기는 사고를 피할 수 있습니다.
🤔 [생각해볼 주제 1] scp 와 rsync, 매번 무엇을 쓸지 어떻게 정할까
문제 상황 요약
scp(한 방에 통째로 복사)와 rsync(바뀐 부분만 동기화)는 둘 다 파일을 보내는 도구다. 파일 하나를 딱 한 번 보내는 경우와, 큰 폴더를 하루에도 여러 번 갱신해 보내는 경우에 어느 쪽이 더 알맞은지, "단순함"과 "효율" 사이의 선택으로 따져볼 문제다.
튜터의 가이드 및 해설
기준을 하나로 잡으면 쉬워요. "한 번 보내고 끝이냐, 계속 갱신하며 보내냐."
한 번 보내고 끝이라면 scp가 깔끔해요. 설정 파일 하나, 로그 하나를 휙 가져오거나 보낼 때는 scp가 명령도 짧고 직관적이죠. 굳이 양쪽을 비교하는 rsync의 똑똑함이 필요 없어요.
반대로 같은 폴더를 반복해서 갱신해 보낸다면 rsync가 압도적이에요. 예를 들어 1GB짜리 웹사이트 폴더에서 파일 하나(1MB)만 고쳐 다시 배포한다고 해봐요. scp는 매번 1GB를 통째로 다시 보내지만, rsync는 달라진 그 1MB 근처만 보냅니다. 네트워크가 느리거나 파일이 클수록 이 차이는 어마어마해져요. 몇 분 걸릴 일이 몇 초로 줄죠. 그래서 현업의 배포 작업은 거의 rsync예요 — 코드는 조금씩 바뀌는데 전체를 매번 보내는 건 낭비니까요.
정리하면, 일회성·단순함은 scp, 반복·효율은 rsync예요. 처음엔 scp로 감을 잡고, "어, 이거 매번 전체를 보내니 느리네" 싶을 때 rsync로 넘어가면 자연스럽습니다.
💡 핵심을 한마디로
한 번 보내고 끝이면 단순한 scp, 같은 폴더를 반복 갱신해 보내면 바뀐 부분만 전송하는 rsync다. 파일이 크고 네트워크가 느릴수록 rsync의 "차이만 보내기"가 큰 시간 차이를 만들어, 현업 배포는 대부분 rsync를 쓴다.
🤔 [생각해볼 주제 2] 방화벽으로 막는 것과 인증으로 지키는 것은 어떻게 다를까
문제 상황 요약
"방화벽으로 포트를 다 막으면 보안 끝"이라고 생각하기 쉽다. 그런데 서비스를 하려면 SSH(22번)·웹(80번) 같은 문은 반드시 열어둬야 하고, 그 문으로는 누구나 노크할 수 있다. "문을 여닫는 일(방화벽)"과 "들어온 사람을 검증하는 일(키 인증)"이 어떻게 다른 층의 보안인지 따져볼 문제다.
튜터의 가이드 및 해설
둘은 막는 단계가 완전히 달라요. 비유로 풀어볼게요.
방화벽은 건물 정문의 출입 통제예요. "이 건물엔 22번·80번 출입구만 열어둔다, 나머지는 다 막는다"라고 정하는 일이죠. 노출되는 문(공격당할 수 있는 면적)을 줄여주는 게 방화벽의 역할이에요. 그런데 서비스를 하려면 정문 몇 개는 반드시 열어둬야 하고, 그 열린 문으로는 누구나 일단 들어와 노크할 수 있어요.
키 인증은 각 사무실 문의 열쇠예요. 정문을 통과해 들어온 사람이라도, 진짜 권한이 있는지(올바른 개인키를 가졌는지)를 사무실 문에서 한 번 더 확인하죠. 방화벽이 "어디로 들어올 수 있나"를 정한다면, 키 인증은 "들어온 사람이 진짜 누구인가"를 검증하는 거예요.
그래서 둘 중 하나만으로는 부족해요. 방화벽만 있고 인증이 약하면, 열어둔 문으로 들어온 사람을 거르지 못해요. 인증만 강하고 방화벽이 없으면, 굳이 안 열어도 될 문까지 다 노출돼 공격 면적이 넓어지죠. 그래서 실무에선 둘을 겹쳐 써요 — 방화벽으로 불필요한 문을 닫아 노출을 줄이고, 열어둔 문은 키 인증으로 지키고. 이렇게 여러 겹으로 막는 걸 "심층 방어(defense in depth)"라고 부릅니다.
💡 핵심을 한마디로
방화벽은 "어떤 포트를 열지" 정해 공격 면적을 줄이는 일이고, 키 인증은 "열린 문으로 들어온 사람이 진짜 권한이 있는지" 검증하는 일이다. 서로 다른 층의 보안이라, 둘을 겹쳐 쓰는 심층 방어가 실무의 기본이다.
🤔 [생각해볼 주제 3] 컨테이너가 "가벼운 가상 머신"이 아니라 "격리된 프로세스"라는 구분이 왜 중요할까
문제 상황 요약
컨테이너를 흔히 "가벼운 가상 머신"이라 부르지만, 정확히는 "리눅스 위에서 도는 격리된 프로세스"다. 이 구분이 단순한 용어 정리를 넘어, 컨테이너가 왜 가볍고 빨리 뜨는지, 왜 격리 수준이 가상 머신과는 다른지와 어떻게 연결되는지 따져볼 문제다.
튜터의 가이드 및 해설
이 구분이 중요한 건, 컨테이너의 거의 모든 특성이 거기서 흘러나오기 때문이에요.
가상 머신은 운영체제를 통째로 하나 더 돌려요. 가짜 컴퓨터를 만들고 그 안에 우분투든 윈도우든 처음부터 끝까지 설치하죠. 그래서 무겁고(수 GB), 켜는 데 수십 초가 걸려요. 반면 컨테이너는 운영체제를 새로 안 돌려요. 바탕이 되는 리눅스 커널 하나를 여러 컨테이너가 공유하면서, namespace로 "각자 격리된 것처럼" 보이고 cgroup으로 자원만 제한받는 평범한 프로세스일 뿐이에요.
여기서 컨테이너의 장점이 전부 설명돼요. 운영체제를 새로 안 켜니까 가볍고(수십 MB) 1초도 안 돼 뜹니다. 프로세스 하나 띄우는 거나 다름없으니까요. 그래서 서버 한 대에 컨테이너를 수십, 수백 개 띄울 수 있어요. 가상 머신으로는 상상하기 어려운 밀도죠.
동시에 한계도 같은 이유에서 나와요. 커널을 공유하니, 가상 머신처럼 완전히 분리되진 않아요. 격리 수준이 조금 더 약하죠. 그래서 보안이 아주 민감한 환경에선 이 차이를 신경 써야 해요. "컨테이너는 격리된 프로세스"라는 한 줄을 이해하면, 가볍고 빠른 이유도, 격리가 가상 머신과 다른 이유도 한꺼번에 풀려요. 다음 과목에서 도커를 배울 때 이 토대가 있으면 훨씬 덜 헷갈립니다.
💡 핵심을 한마디로
컨테이너는 운영체제를 따로 돌리는 가상 머신과 달리, 리눅스 커널을 공유하며 namespace·cgroup으로 격리된 프로세스다. 그래서 가볍고 빨리 뜨지만 격리 수준은 가상 머신보다 약하다 — 이 한 줄이 컨테이너의 장점과 한계를 동시에 설명한다.