작은 웹 서비스 실행
110분 안팎
학습 목표
제공된 Python 표준 라이브러리 웹 앱을 서비스 계정으로 실행해 /health와 /items 응답을 확인합니다.
개념
응답까지 확인해야 실행 완료입니다
Python 파일이 존재한다는 사실과 프로세스가 실행 중이라는 사실, 요청이 올바른 데이터를 반환한다는 사실은 서로 다릅니다. 앱 실행 메시지만 보고 완료 처리하면 권한 오류나 잘못된 데이터 경로를 놓칠 수 있습니다. 이번 앱은 /health에서 상태 JSON을, /items에서 실습 데이터 JSON을 반환합니다. 사용자 정의 핸들러를 제공하므로 임의의 디렉터리를 공개하는 파일 서버 명령을 대신 쓰지 않습니다. 결과를 HTTP 상태·본문·실행 주체로 나누어 확인합니다.
프로그램과 실행 인스턴스
app.py는 디스크의 프로그램이고 Python이 이를 실행하면 PID를 가진 프로세스가 생깁니다. 같은 파일을 두 번 실행하면 별개의 PID가 생길 수 있으며 포트 충돌도 가능합니다. PID는 재사용될 수 있으므로 오래된 번호만 저장하지 말고 관측 시각·명령줄·실행 계정도 묶습니다. 부모 PID는 누가 실행을 시작했는지 조사하는 단서입니다. 이번 레슨에서는 서비스 관리자를 붙이지 않은 직접 실행이며 부팅 자동 시작이나 실패 자동 재시작은 아직 제공하지 않습니다.
주소를 제한합니다
앱은 127.0.0.1:18080에 바인딩합니다. 같은 VM 안의 클라이언트만 대상으로 삼는 실습입니다. 호스트 브라우저에서 VM 주소로 접속되지 않는 것을 앱 실패로 단정하지 않습니다. 0.0.0.0으로 바꾸면 외부 인터페이스까지 노출 범위가 달라지므로 접속 편의를 위해 즉흥적으로 바꾸지 않습니다. 포트는 프로세스 번호가 아니고 소켓의 주소 구성요소입니다. 이 앱은 HTTP만 제공하며 실제 인터넷 서비스로 공개할 구성은 아닙니다.
계정과 작업 경로
앞 모듈에서 bcweb는 로그인하지 않는 서비스 계정이며 data 쓰기와 config 읽기만 허용했습니다. 기존 VM 관리자가 sudo -u bcweb로 앱 명령을 직접 실행할 수 있습니다. 서비스 셸을 bash로 바꾸거나 관리자 계정으로 앱을 실행해서 권한 오류를 덮지 않습니다. 앱 코드만 bcops:bcapp 소유의 읽기 가능한 경로로 설치하며 작업자 홈 전체 권한을 넓히지 않습니다. 데이터 경로는 절대경로로 넘겨 실행 위치의 영향을 줄입니다.
표준 라이브러리의 작은 구성
ThreadingHTTPServer는 요청을 스레드로 처리하고 BaseHTTPRequestHandler의 do_GET이 경로를 분기합니다. 응답은 json.dumps로 바이트를 만들고 Content-Type과 Content-Length를 적습니다. /health의 200은 요청 처리 경로가 살아 있다는 좁은 확인입니다. /items는 실제 파일을 읽으므로 이전 권한 설정과 데이터 경로까지 확인합니다. 없는 경로는 404로 분리합니다. 표준 라이브러리 구현을 실습에 쓰지만 인증·TLS·운영용 보안 정책이 갖춰진 서버라고 주장하지 않습니다.
실행 수명을 제한합니다
제공된 CLI는 1~120초 사이 수명을 받고 기본 30초 후 끝납니다. serve_forever는 별도 스레드에서 실행하고 메인 흐름이 시간이 지나면 shutdown으로 요청 루프를 종료합니다. server_close는 소켓을 닫고 join은 스레드 종료를 기다립니다. 같은 요청 루프 스레드에서 shutdown을 호출하는 구조로 바꾸면 진행이 멈출 수 있으므로 종료 담당 흐름을 유지합니다. 프로세스 강제 종료 없이 실습이 자연스럽게 끝나도록 만든 장치입니다.
두 터미널의 역할
터미널 A에서 앱을 전경 실행하고 출력 PID와 UID를 읽습니다. 터미널 B에서 제한 시간 안에 curl로 /health와 /items를 조회하고 ps로 같은 PID의 user·args를 확인합니다. 실행 콘솔을 닫거나 무제한 백그라운드 실행으로 바꾸지 않습니다. 제한 시간이 지나 연결이 거부되면 새 실행의 관측 시간과 비교합니다. URL과 데이터 파일을 어떤 계정으로 읽었는지까지 기록해야 요청 성공을 권한 확인과 연결할 수 있습니다.
상태와 본문을 함께 읽습니다
curl -fsS는 HTTP 오류를 실패로 알리며 정상 응답 본문을 보여 줍니다. 상세 상태는 curl -i 또는 응답 헤더 기록으로 확인합니다. /items의 키가 있다는 것만으로 충분하지 않고 파일 JSON과 파싱한 값을 비교합니다. JSON 공백이나 키 순서는 의미상 동등할 수 있으므로 문자열 전체 비교 대신 객체 비교를 사용합니다. /missing의 404는 예상된 거부이며 /items의 404는 경로 구현 문제입니다. 같은 숫자라도 요청 목적과 함께 판단합니다.
실패 원인을 좁힙니다
Address already in use는 바인딩 주소·포트가 이미 사용 중일 가능성을 뜻합니다. 기존 프로세스를 종료하지 않고 ss -ltnp와 관측 권한을 확인한 뒤 다른 실습 실행이 자연 종료할 때까지 기다립니다. PermissionError는 앱 파일 읽기인지 데이터 읽기인지 traceback의 경로를 확인합니다. Connection refused는 해당 주소에서 연결을 받는 소켓이 없을 가능성부터 조사합니다. 파일 오류를 해결하려고 방화벽을 먼저 변경하는 식으로 진단 계층을 건너뛰지 않습니다.
기능 테스트와 VM 증거
test_web.py는 임시 데이터·자동 배정 포트로 서버를 열고 정상 경로 두 개와 없는 경로를 확인합니다. finally에서 종료와 소켓 닫기를 수행해 테스트 후 서버를 남기지 않습니다. 이 검사는 HTTP 구현이 맞는지 확인하며 실제 bcweb로 18080에 기동한 증거를 대신하지 않습니다. ZIP의 자동 검사와 VM의 실측 관찰을 둘 다 제출합니다. 프로세스 존재와 systemd가 관리하는 상태의 차이는 다음 모듈에서 유닛 상태·로그와 연결합니다.
명령·API 의미의 기준은 공식 문서에서 확인합니다. 상세 원리는 더 읽기의 서재 장으로 연결합니다.
따라하기
응답 비교 연습
JSON은 공백·키 순서 대신 파싱한 값을 비교합니다.
import json
expected=json.loads('{"count":0,"items":["lab-web"]}')
actual=json.loads('{"items":["lab-web"],"count":0}')
print('same='+str(actual==expected))실행 결과
same=True
VM 데이터 준비
Linux VM에서 앞 모듈 완료 뒤 실행합니다. 기존 items.json이 있으면 덮어쓰지 않고 내용을 확인합니다. 서버는 30초 후 자연 종료합니다.
sudo -u bcweb python3 - <<'END'
import json
from pathlib import Path
p=Path('/srv/bootcamp-m02/lab-root/data/items.json')
if not p.exists():
with p.open('x') as f: json.dump({'count':0,'items':['lab-web']},f)
END
sudo install -o bcops -g bcapp -m 0640 app.py /srv/bootcamp-m02/lab-root/app.py
sudo -u bcweb python3 /srv/bootcamp-m02/lab-root/app.py --data /srv/bootcamp-m02/lab-root/data/items.json --seconds 30별도 터미널에서 관측
터미널 B에서 실행합니다. 터미널 A의 출력 PID를 ps -p 명령에 넣고 실행 계정을 확인합니다. 시간 제한 후 연결이 거부되는지도 확인합니다.
curl -fsS http://127.0.0.1:18080/health
curl -fsS http://127.0.0.1:18080/items기능 검사
ZIP 폴더에서 자동 기능 검사를 실행합니다. 임시 포트 검사와 실제 VM 관측을 구분합니다.
bash check.sh확인 문제
실습
app.py의 /items가 실제 파일 내용을 반환하도록 완성합니다. 자동 검사는 임시 포트에서 200·본문·404를 검사하며 실제 bcweb 실행은 VM에서 관측합니다. 소켓 바인딩이 이 맥의 샌드박스에서 차단되어 실제 HTTP 검사는 external입니다.
실행 명령
bash check.sh
기대 결과
PASS web routes
모범 답안
모범 답안 내려받기더 읽기
면접 질문
- 프로세스와 systemd 서비스 상태의 차이를 설명합니다.