소개
운영 업무에서는 웹 서비스의 가용성을 확인하는 일이 자주 필요합니다. requests와 같은 서드 파티 라이브러리가 널리 사용되지만, 제한된 환경에서는 Python 표준 라이브러리만 사용해야 할 수 있습니다.
이 실습에서는 Python 표준 라이브러리 모듈인 urllib를 사용해 간단한 연결 확인기를 만듭니다. 추가 의존성을 설치하지 않고도 유용한 운영 도구를 만들 수 있다는 점을 확인합니다.
이 실습을 마치면 다음 방법을 이해하게 됩니다.
urllib.request모듈을 가져옵니다.- URL 을 확인하는 함수를 정의합니다.
- HTTP 상태 코드 (예: 200 OK) 를 가져옵니다.
- 서버 오류나 연결할 수 없는 호스트와 같은 예외를 처리합니다.
- 사용자가 이해하기 쉬운 상태 메시지를 표시합니다.
모듈 가져오기
이 단계에서는 먼저 Python 스크립트를 만들고 필요한 모듈을 가져옵니다. urllib.request 모듈은 URL 을 여는 데 사용하는 Python 내장 도구입니다. 마우스 대신 코드로 제어하는 Chrome 이나 Firefox 같은 웹 브라우저라고 생각하면 됩니다. 이 모듈을 사용하면 스크립트에서 인터넷의 데이터를 가져올 수 있습니다.
운영 환경에서는 많은 시스템이 HTTP 기반 API 나 상태 확인 엔드포인트를 제공합니다. 나중에 서드 파티 라이브러리를 사용하더라도 표준 라이브러리 도구를 이해하면 요청과 응답이 동작하는 기본 원리를 더 명확하게 파악할 수 있습니다.
먼저 올바른 디렉터리에 있는지 확인합니다. 터미널을 열고 프로젝트 폴더로 이동합니다.
cd ~/project
이제 nano 텍스트 편집기 (또는 원하는 편집기) 를 사용해 connectivity_check.py라는 새 Python 파일을 만듭니다.
nano connectivity_check.py
Python 에서 라이브러리를 사용하려면 먼저 가져와야 합니다. 파일 맨 위에 다음 줄을 추가합니다. 요청을 처리하기 위해 urllib.request를 가져오고, 나중에 발생할 수 있는 오류를 처리하기 위해 urllib.error를 가져옵니다.
import urllib.request
import urllib.error
Ctrl+O를 누른 다음 Enter를 눌러 파일을 저장하고, Ctrl+X를 눌러 nano를 종료합니다.
cat 명령으로 파일 내용을 확인할 수 있습니다.
cat connectivity_check.py
함수 정의
필요한 import 가 준비되었으므로 이제 코드를 구조화해야 합니다. 일반적으로 로직은 함수 안에 캡슐화하는 것이 좋습니다. 이렇게 하면 코드를 재사용하고 테스트하기 쉬워집니다.
운영 스크립트에서는 같은 작업을 여러 대상에 반복해서 실행해야 하는 경우가 많으므로 함수가 특히 유용합니다. 네트워크 확인 작업을 함수로 묶으면 코드를 복사하지 않고 여러 URL 에 대해 호출할 수 있습니다.
이 단계에서는 URL 문자열을 인수로 받는 check_url 함수를 정의합니다.
connectivity_check.py 파일을 다시 엽니다.
nano connectivity_check.py
import 문 아래에 다음 함수 정의를 추가합니다. 지금은 Python 에서 "아무 작업도 하지 않음"을 나타내는 자리 표시자인 pass 문만 넣습니다. 다음 단계에서 실제 로직을 추가합니다.
import urllib.request
import urllib.error
def check_url(url):
print(f"Checking connectivity for: {url}")
## Logic will go here
pass
편집기를 저장하고 종료합니다 (Ctrl+O, Enter, Ctrl+X).
이 구조가 기본 틀을 마련합니다. check_url 함수는 하나의 매개변수인 url을 받으며, 이 값은 확인할 웹 사이트 주소가 됩니다 (예: "https://www.google.com").
요청 보내기
이 단계에서는 요청을 보내고 HTTP 상태 코드를 가져오는 핵심 로직을 구현합니다. HTTP 상태 코드 200은 일반적으로 "OK" 또는 성공을 의미합니다.
간단히 말하면 HTTP 요청은 클라이언트와 서버 사이의 대화입니다. 여기서 스크립트가 클라이언트입니다. 스크립트는 URL 로 요청을 보내고 서버의 응답을 기다린 다음, 상태 코드와 같은 메타데이터를 확인해 다음 작업을 결정합니다.
URL 을 열 때 urllib.request.urlopen()을 사용합니다. 이 함수는 응답 객체를 반환하며, 응답 객체의 .getcode() 메서드로 상태 코드를 가져올 수 있습니다.
connectivity_check.py를 엽니다.
nano connectivity_check.py
check_url 함수를 다음과 같이 수정합니다. 서버가 응답하지 않을 때 스크립트가 멈추지 않도록 5 초의 타임아웃을 설정합니다.
import urllib.request
import urllib.error
def check_url(url):
print(f"Checking connectivity for: {url}")
## Open the URL with a 5-second timeout
response = urllib.request.urlopen(url, timeout=5)
## Get the status code
status_code = response.getcode()
print(f"Status Code: {status_code}")
참고: 아직 오류 처리를 추가하지 않았으므로 이 단계에서는 URL 이 잘못되었거나 서버가 중단된 경우 스크립트가 오류와 함께 종료됩니다. 다음 단계에서 이 문제를 해결합니다.
편집기를 저장하고 종료합니다.
오류 처리
네트워크 프로그래밍의 결과는 예측하기 어렵습니다. 서버가 중단되거나 DNS 조회가 실패하거나 인터넷 연결이 끊길 수 있습니다. urlopen이 실패하면 예외가 발생합니다. 스크립트를 안정적으로 만들려면 try...except 블록으로 이러한 예외를 처리해야 합니다.
실제 모니터링에서는 서로 다른 장애 유형을 구분하는 것이 중요합니다. 서버가 500을 반환했다면 서버에 도달했고 서버가 내부 문제를 보고한 것입니다. 반면 URLError는 요청이 사용 가능한 HTTP 엔드포인트에 도달하지 못했음을 의미하는 경우가 많습니다. 운영자는 이러한 상황을 서로 다른 유형의 장애로 처리해야 합니다.
다음 두 가지 오류를 처리합니다.
urllib.error.HTTPError: 서버가 응답했지만 오류 코드 (예: 404 Not Found, 500 Server Error) 를 반환한 경우입니다.urllib.error.URLError: 서버에 전혀 연결할 수 없는 경우입니다 (예: 인터넷 연결 없음, 잘못된 도메인).
try...except 블록을 안전망이라고 생각하면 됩니다. 인터넷 연결이 끊기는 것처럼 문제가 발생해도 코드가 비정상 종료되지 않습니다. 대신 except 블록으로 이동하고, 여기서 오류를 처리해 이해하기 쉬운 메시지를 표시할 수 있습니다.
connectivity_check.py를 엽니다.
nano connectivity_check.py
요청 로직을 try 블록으로 감싸도록 함수를 수정합니다.
import urllib.request
import urllib.error
def check_url(url):
print(f"Checking connectivity for: {url}")
try:
## Attempt to open the URL
response = urllib.request.urlopen(url, timeout=5)
status_code = response.getcode()
print(f"Success! Status Code: {status_code}")
except urllib.error.HTTPError as e:
## Server responded with an error (e.g., 404, 500)
print(f"HTTP Error: {e.code}")
except urllib.error.URLError as e:
## Failed to reach the server
print(f"URL Error: {e.reason}")
이 코드는 먼저 try 블록 안의 줄을 실행합니다. 오류가 발생하면 Python 은 try 블록의 실행을 중단하고 일치하는 except 블록으로 이동합니다.
편집기를 저장하고 종료합니다.
스크립트 테스트
마지막 단계에서는 함수를 호출하는 main 블록을 추가해 스크립트를 실행할 수 있도록 합니다. 이렇게 하면 터미널에서 스크립트를 직접 실행할 수 있습니다.
if __name__ == "__main__": 패턴은 재사용 가능한 함수와 직접 실행할 때 동작해야 하는 코드를 구분하는 Python 관례입니다. 이 구조를 사용하면 다른 스크립트에서 check_url을 가져와도 테스트 호출이 자동으로 실행되지 않으므로 나중에 재사용하기 쉽습니다.
정상적으로 작동하는 URL(예: https://www.example.com) 로 테스트합니다. 오류 처리가 실제로 동작하는지 확인하기 위해 존재하지 않는 URL 도 시도할 수 있습니다.
connectivity_check.py를 엽니다.
nano connectivity_check.py
파일 마지막에 다음 코드를 추가합니다.
if __name__ == "__main__":
## Test with a valid URL
target_url = "https://www.example.com"
check_url(target_url)
print("-" * 20)
## Test with an invalid URL to see error handling
invalid_url = "https://www.this-domain-does-not-exist-12345.com"
check_url(invalid_url)
if __name__ == "__main__": 블록을 사용하면 이 코드는 스크립트를 직접 실행할 때만 실행됩니다. 다른 스크립트에서 모듈로 가져올 때는 실행되지 않습니다.
편집기를 저장하고 종료합니다.
이제 스크립트를 실행해 결과를 확인합니다.
python3 connectivity_check.py
다음과 비슷한 출력이 표시됩니다.
Checking connectivity for: https://www.example.com
Success! Status Code: 200
--------------------
Checking connectivity for: https://www.this-domain-does-not-exist-12345.com
URL Error: [Errno -2] Name or service not known
(참고: 잘못된 URL 에 대한 정확한 오류 메시지는 네트워크 환경에 따라 조금 다를 수 있습니다.)
요약
이 실습에서는 Python 표준 라이브러리를 사용해 네트워크 연결 확인기를 성공적으로 만들었습니다. 다음 내용을 배웠습니다.
- 모듈 가져오기:
urllib.request와urllib.error를 사용했습니다. - HTTP 요청 보내기:
urlopen을 사용해 웹 서버에 연결했습니다. - 응답 처리: HTTP 상태 코드를 가져와 서비스 가용성을 확인했습니다.
- 오류 관리:
try...except블록으로HTTPError와URLError를 처리해 네트워크 장애에 강한 스크립트를 만들었습니다.
이 기술은 외부 의존성을 설치할 수 없는 환경에서 모니터링 스크립트, 상태 확인 도구, 간단한 웹 스크래퍼를 만드는 데 기본이 됩니다.



