주소에서 응답까지
65분 안팎
학습 목표
DNS·IP·TCP·TLS·HTTP의 역할을 연결합니다.
개념
통신을 나누어 보는 이유
앞 모듈에서는 JSON을 읽고 SQL 공개 보고서를 만들었습니다. 파일을 열어 내용을 확인하는 방식은 같은 컴퓨터 안에서는 충분하지만, 브라우저가 보고서를 요청할 때는 주소와 통신 규칙도 필요합니다. 화면이 비어 있다는 사실만으로 보고서 계산이 틀렸다고 판단하면 조사 위치를 놓칩니다. 주소를 해석하지 못한 경우, 서버에 연결하지 못한 경우, 서버가 오류 응답을 보낸 경우를 순서대로 분리하는 것이 이번 목표입니다.
이 모듈은 Python 3 표준 라이브러리만 사용합니다. 로컬 실습과 미션은 같은 foundations-m08-http-observation-mission 압축 파일을 이용합니다. 압축을 푼 폴더에서 README의 명령을 실행합니다. 예제의 책과 소유자는 가상 자료입니다. 서버 관찰은 본인 컴퓨터의 127.0.0.1에서만 하고 외부 사이트에 요청하지 않습니다. 브라우저를 쓰는 단계의 출력은 환경에 따라 달라져 비워 두며, 표시된 항목을 직접 문서에 적습니다.
주소 예시는 http://127.0.0.1:PORT/report.json입니다. PORT는 문자 그대로 입력하는 값이 아니라 실행 도구가 출력한 실제 숫자입니다. http는 통신 방식, 127.0.0.1은 목적지 호스트, 포트는 그 컴퓨터에서 요청을 받을 프로그램의 입구, /report.json은 HTTP 요청 대상 경로입니다. 경로 끝이 json이라고 해서 디스크에 같은 이름의 파일이 있어야 하는 것은 아닙니다. 이 서버는 경로를 비교해 메모리에서 계산한 보고서를 반환합니다.
이름·주소·연결의 책임
DNS는 도메인 이름을 주소 정보로 해석하는 데 사용됩니다. IP 주소는 네트워크에서 목적지를 지정하는 데 쓰입니다. 이름 해석에 로컬 설정과 캐시도 관여하므로 주소창에 이름을 넣었다고 매번 외부 DNS 서버를 조회했다고 말할 수는 없습니다. 예제의 숫자 IP에는 도메인을 IP로 바꾸는 작업이 필요하지 않습니다. localhost는 보통 로컬 이름 해석으로 루프백 주소를 가리키지만 IPv4와 IPv6 선택이 환경마다 다를 수 있어 실습은 숫자 IPv4 주소로 조건을 맞춥니다.
127.0.0.1은 이 요청을 보내는 컴퓨터 자신을 가리키는 IPv4 루프백 주소입니다. 친구에게 이 주소를 보내면 친구 컴퓨터의 서버를 찾게 됩니다. 로컬 서버가 실행 중이라는 사실은 외부 사람도 접근할 수 있다는 뜻이 아닙니다. 특히 실습 서버는 모든 인터페이스가 아닌 127.0.0.1에 바인딩합니다. 브라우저와 서버가 같은 컴퓨터에 있는지, 도구가 출력한 포트와 주소창의 포트가 같은지 먼저 대조합니다.
이번 서버의 HTTP 연결은 TCP를 이용합니다. TCP는 연결과 바이트 전달을 제공하지만 그 바이트가 독서 보고서인지 판단하지 않습니다. HTTP는 GET 같은 메서드와 경로를 담은 요청, 상태·헤더·본문을 담은 응답의 의미를 정합니다. TCP 연결에 성공해도 HTTP의 결과는 404 또는 500일 수 있습니다. 주소 찾기, 연결, 업무 결과를 한 번의 성공 여부로 묶지 않는 이유입니다.
HTTPS를 설명하는 범위
가상 주소 https://reading.example/report.json을 설명할 때는 이름 해석, 연결, TLS, HTTP의 책임을 구분합니다. TLS는 통신을 보호하고 인증서 기반 서버 인증에서 기대한 이름과 신뢰 경로 등을 확인합니다. 이 레슨의 로컬 http 서버에는 TLS와 인증서 검사가 없습니다. 따라서 로컬 관찰 성공을 HTTPS 인증서 검증 성공의 증거로 쓰지 않습니다. 실제 외부 접속 대신 가상 주소의 논리 흐름을 종이에 적습니다.
여기서 TCP 다음 TLS라는 흐름은 전통적인 HTTPS 연결을 설명하는 모델입니다. 모든 웹 통신이 같은 전송 방식을 쓰는 것은 아니며 HTTP/3는 QUIC을 이용합니다. 캐시된 응답이나 재사용한 연결도 있으므로 브라우저의 한 번의 화면 갱신이 모든 단계를 새로 수행했다고 단정하지 않습니다. 이번 목표는 프로토콜 전체 구현이 아니라 실패가 어떤 책임의 경계에서 관찰됐는지를 설명하는 것입니다.
인증서 이름 불일치를 만났을 때 주소를 숫자 IP로 바꾸거나 검증을 끄는 것은 같은 조건의 해결이 아닙니다. 연결 이름과 인증서의 관계가 달라지기 때문입니다. DNS 결과가 나왔다면 이름 해석에 관한 증거를 얻었을 뿐, 원하는 상대의 인증이나 HTTP 보고서 성공까지 확인한 것은 아닙니다. 더 읽기에서는 이름 해석 캐시와 TLS 신뢰 경로를 자세히 다룹니다.
실패 위치를 기록하기
Connection refused는 연결 대상에서 접속을 거절한 상황을 조사하게 합니다. 서버가 아직 시작되지 않았거나 이미 정리된 경우, 포트 오타 등이 후보입니다. Name or service not known과 같은 이름 해석 오류는 호스트 이름과 해석 환경을 먼저 확인합니다. 정확한 표현은 운영체제마다 다르므로 오류 문구를 그대로 보존하고 추측한 원인을 별도 칸에 씁니다. 한 메시지만으로 방화벽이나 DNS 장애를 확정하지 않습니다.
따라하기의 URL 파서는 문자열을 나눌 뿐 DNS 질의나 서버 연결을 수행하지 않습니다. hostname 값이 출력되는 것은 입력된 호스트 부분을 읽었다는 뜻입니다. 이 결과를 실제 접속 성공이라고 기록하는 실수를 피합니다. 설계 제출물에는 숫자 IP 경로와 가상 HTTPS 이름 경로를 나란히 그리고, 각 단계에 입력·출력·실패 가능성을 적습니다. HTTP 상태가 있는지 없는지를 판단하는 준비가 됩니다.
최종 점검에서는 주소의 통신 방식, 호스트, 포트, 경로를 각각 짚고 누가 해석하는지 말해 봅니다. 주소의 /report.json을 내 작업 폴더 경로로 바꾸거나 포트를 책 ID로 해석하면 역할이 섞인 것입니다. 설명을 들은 동료가 서버 미실행과 없는 보고서 경로를 다른 후보로 조사할 수 있어야 합니다. 흐름도에 연결 재사용과 로컬 이름 해석이라는 조건도 덧붙여 과도한 일반화를 줄입니다.
따라하기
주소 구성 요소 읽기
이 코드는 주소 문자열만 분리하며 접속하지 않습니다.
from urllib.parse import urlsplit
u = urlsplit("http://127.0.0.1:8123/report.json")
print(u.scheme, u.hostname, u.port, u.path)실행 결과
http 127.0.0.1 8123 /report.json
이름 주소와 기본 포트
명시하지 않은 포트는 파서에서 None입니다. HTTPS 기본 포트 443을 의미하는 연결 규칙과 파서 반환값을 구분합니다.
from urllib.parse import urlsplit
u = urlsplit("https://reading.example/report.json")
print(u.hostname, u.port, u.path)실행 결과
reading.example None /report.json
흐름도 작성
숫자 IP의 HTTP 요청과 가상 HTTPS 이름 요청을 두 줄로 그립니다. 이름 해석·TCP·TLS·HTTP의 필요 여부를 각 줄에 표시하고 DNS 결과만으로 HTTP 성공을 보장할 수 없는 이유를 적습니다.
확인 문제
실습
숫자 IP의 로컬 HTTP와 가상 HTTPS 이름 주소 흐름도를 제출합니다. DNS·IP·TCP·TLS·HTTP의 역할, 외부 DNS가 필요 없는 조건, 응답 없는 실패와 HTTP 오류의 차이를 각각 표시합니다. 실제 외부 접속은 필요하지 않습니다.
더 읽기
면접 질문
- 주소 입력부터 HTTP 응답까지의 흐름을 설명합니다.