목차
json-server
JSON을 정보 전달의 순단으로 사용하기 위해서는
웹 서비스를 제공하는 서버가 필요하고, 서비스와 통신할 수있는 socket모듈 보다 더 간단한 도구가 필요하다.
socket 모듈의 경우 너무 까다롭고 또 강력하다.
socket 모듈은 TCP 수준에서 네트워크 문제를 이해하고 OS가 인터넷 연결을 설정, 유지, 종료를 할 때 사용하기 좋은 모듈이다.
하지만, 웹 서비스와 간단하게 대화하기 위한 용도의 사용으로는 socket이 복잡성을 가지고, 너무 크다.
이러한 니즈를 충족하기 위해 우리는 RESTful API 기반으로 수행하는 HTTP 서버가 필요하다.
Node.js 환경으로 구현된 무료이고, 오픈 패키지로 json-server를 사용한다.
브라우저 외부에서 JavaScript 코드를 실행하는 오픈 소스 플랫폼 Node.js.의 환경으로 JavaScript를 접하게 되지만,
코드를 작성하지 않아도 된다.
너무 걱정할 필요 없이 시작해보도록 하자.
먼저 Node.js가 설치되어야 한다. 설치단계는 사용하는 OS에 따라 다르다.
Node.js — Download Node.js®
Node.js® is a free, open-source, cross-platform JavaScript runtime environment that lets developers create servers, web apps, command line tools and scripts.
nodejs.org
Windows 사용자라면 cmd를 , linux나 macOS 사용자라면 선호하는 터미널 에뮬레이터를 실행한다.
참고로 관리자 권한이 필요할 수 있다.
npm
Node.js 구성요소를 설치하고 업데이트하기 위해 자체 도구를 사용하는데 모든 플랫폼에서 이름이 동일하므로
해당 명령어를 실행한다.
해당 명령어를 실행시에 짧은 도움말 화면이 표시되는 것을 볼 수 있다.
npm install -g json-server
npm을 통해 json-server 패키지를 설치한다.
패키지를 실행하는 데 필요한 모든 패키지들을 함께 다운로드 해야하므로 약간의 지연이 발생할 수 있다.
json 샘플 파일을 하나 만들고, 홈 디렉토리나 쓰기 권한이 있는 다른 디렉토리에 저장한다.
https://microsoftedge.github.io/Demos/json-dummy-data/
JSON dummy data
Web pages and apps used to demo various DevTools, PWA, WebView, Extensions, and Web Platform features of Microsoft Edge
microsoftedge.github.io
(JSON 샘플 파일)
import json,os
# Python 딕셔너리 및 리스트로 데이터 구성
cars_data = {
"cars": [
{
"id": 1,
"brand": "Ford",
"model": "Mustang",
"production_year": 1972,
"price": {
"currency": "USD",
"value": 35900
}
},
{
"id": 2,
"brand": "Aston Martin",
"model": "Rapide",
"production_year": 2010,
"price": {
"currency": "GBP",
"value": 32000
}
},
{
"id": 3,
"brand": "Audi",
"model": "A4",
"production_year": 2018,
"price": {
"currency": "EUR",
"value": 45000
}
},
{
"id": 4,
"brand": "Tesla",
"model": "Model S",
"production_year": 2020,
"price": {
"currency": "USD",
"value": 70000
}
},
{
"id": 5,
"brand": "BMW",
"model": "M3",
"production_year": 2022,
"price": {
"currency": "EUR",
"value": 80000
}
}
]
}
# JSON 파일로 저장
# 저장할 디렉토리 경로 정의
output_dir = 'resources'
output_file_path = os.path.join(output_dir, 'cars.json')
# indent=4는 가독성을 위해 들여쓰기를 4칸으로 설정
with open(output_file_path, 'w', encoding='utf-8') as f:
json.dump(cars_data, f, indent=4, ensure_ascii=False)
print("cars.json 파일이 성공적으로 생성되었습니다.")
# 생성된 JSON 파일 내용 확인
try:
with open(output_file_path, 'r', encoding='utf-8') as f:
print("\n--- cars.json 내용 ---")
print(f.read())
print("--------------------")
except FileNotFoundError:
print(f"오류: '{output_file_path}' 파일을 찾을 수 없습니다. 경로를 다시 확인해주세요.")
except Exception as e:
print(f"파일을 읽는 중 오류 발생: {e}")
json-server --watch resources/cars.json
뒤에 json 파일 경로를 지정한다.
모든 것이 바르게 지정되었다면
Watching...
이라는 문구가 뜨며 이는 서버가 작동중이고 수신 연결을 처리할 준비가 되었다는 의미다.
이제 http://localhost:3000 을 열어보면 JSON Server 페이지가 열리고, 이는 서버가 정상적으로 작동한 것이다.
만약 터미널에서 실행했다면 서버를 종료하기 위해서는 Ctrl + C 를 눌러 종료할 수 있다.
터미널 실행이 아닌, 다른 노트북환경에서 실행한 경우 터미널 창을 열어 3000포트의 프로세스를 찾아 종료한다.
>netstat -ano | findstr :3000
TCP 0.0.0.0:3000 0.0.0.0:0 LISTENING 17292
TCP [::]:3000 [::]:0 LISTENING 17292
>taskkill /PID 17292 /F
성공: 프로세스(PID 17292)가 종료되었습니다.
requests 모듈
첫번째로 살펴볼 requests 모듈은 아주 기본적으로 활용한다.
import requests
reponse = requests.get('https://www.google.com')
print(reponse.status_code)
200
HTTP 프로토콜은 메소드를 이용하여 작동한다.
HTTP 메소드는 클라이언트와 서버간의 양방양 상호작용(물론 클라이언트가 전송을 시작.)으로 특정 동작을 실행하는데 사용한다.
GET 메소드는 이러한 상호작용중 하나로, 클라이언트가 요청한 리소스를 서버에게 전송하도록 유도하는 데 사용된다.
requests의get()이라는 함수가 HTTP GET 메서드를 실행하여 서버의 응답을 받는다.
보다시피 코드는 간단하고 간결하다.
socket처럼 복잡한 상수, 기호, 함수, 개념을 다룰 필요가 없다.
브라우저 주소창을 사용할 때와 마찬가지로 서버주소와 서비스 포트번호만 제공하면된다.
포트번호의 경우 HTTP 기본 포트인 80 일 경우 생략이 가능하다.
get()을 통해 응답결과를 반환한다. 해당 객체는 HTTP GET 메서드 실행에 대한 모든 정보를 가지고 있다.
물론 가장 중요한 것은 성공여부이다.
성공여부를 알기 위해 status_code를 통해 확인할 수 있다.
import requests
# 응답 코드 확인
print(requests.codes.__dict__)
https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status
HTTP response status codes - HTTP | MDN
HTTP response status codes indicate whether a specific HTTP request has been successfully completed. Responses are grouped in five classes:
developer.mozilla.org
code 상태 코드를 정수값과 비교하는 것 보다 아래와 같이 변경하면 더욱 더 이해를 도울 수 있다.
import requests
reponse = requests.get('https://www.google.com')
if response.status_code == requests.codes.ok:
print('정상입니다.')
else:
print('문제가 생겼습니다.', response.status_code)
숫자 200 으로 표현되는 것 보다 훨씬 나아보인다.
이제 응답(response) 객체에 대해 살펴보도록 하자.
- response.headers
import requests
reponse = requests.get('https://www.google.com')
print(response.headers)
보기 어려운 관계로
import requests
reponse = requests.get('https://www.google.com')
headers = response.headers
for key, value in headers.items():
print(f"-- {key} : {value}")
보다 시피 응답 헤더는 연관된 값을 여러 필드로 구성되어 있고,
대부분은 중요하지 않지만 Content-Type의 경우 중요하다.
딕셔너리형태의 검색을 통해 직접 액세스 할 수 있다.
import requests
reponse = requests.get('https://www.google.com')
content_type = response.headers['Content-Type']
print(content_type)
text/html; charset=ISO-8859-1
- response.text
import requests
reponse = requests.get('https://www.google.com')
text = response.text
print(text)
text 속성은 데이터 스트림에서 그대로 가져온 텍스트를 포함하는 문자열로 변환은 적용되지 않는다.
참고로 클라이언트와 서버 모두 컨텐츠에 JSON 메세지가 포함되어 있다는 사실을 알 경우
딕셔너리 형태를 반환하는 json() 이라는 메서드를 사용할 수도 있다.
HTTP method
GET
GET은 서버에 정보를 가져오는 것을 목적으로 한다.
물론 간단한 서버는 두 개 이상의 리소스를 제공하므로 GET 방법은
클라이언트가 요구사항을 정확하게 지정할 수 있는 수단을 제공한다.
클라이언트에 요구사항이 없고, 리소스 식별 없이 시작하면 서버에 응답은 루트 문서가 포함된다.
이는 위의 예제에서 response.text를 확인했던 것과 같다.
즉, 서버에게 "뭔가를 줘 !"라고 요청하는 방법이다.
POST
POST도 GET과 같이 리소스를 전송하는 데 사용되지만,
목표를 반대로 클라이언트에서 서버로 전송하는 것을 한다.
GET과 마찬가지로 리소스의 식별 정보를 제공해야한다.
또한 클라이언트가 보내는 리소스는 서버에 새로운 리소스라고 가정하고, 이전에 수집된 데이터를 대체하거나 덮어 쓰지 않는다.
즉, 서버에 새로운 것을 주고 싶다면 POST 요청을 한다.
PUT
POST와 유사하게 클라이언트에서 서버로 리소스를 전송하지만 의도가 다르다.
전송되는 리소스는 이전에 저장된 데이터를 대체하기 위한것이다.
즉, 서버가 현재 가지고 있는 것을 업데이트 하고 싶다면 PUT 요청을 한다.
DELETE
메서드 이름에 목적이 담겨있따.
서버에서 지정된 식별자에서 리소스를 제거하도록 명령하는데 사용하고,
이후 해당 리소스를 더이상 사용할 수 없다.
requests의 예외
만약 서버에 장애가 발생하거나, 전송 매체가 다운되는 등 여러가지 일이 일어날 수 있다.
requests 모듈은 통신 문제가 발생하면 예외를 발생시키려는 경향이 있지만,
일부 문제는 또 다른 형태로 나타난다.
- request.exceptions.Timeout
서버가 즉시 응답하지 않는 일은 정상이다.
연결 -> 데이터전송 -> 리소스 검색 등 모든 단계에서 시간이 걸린다.
하지만, 우리 인내심의 한계가 있다.
보통 얼마나 기다릴지, 더이상 기다리고 싶지 않을지 알수 있다.
이에 대한 시간 값을 넣어, 요청에 대한 timeout을 지정할 수 있다.
#timeout= 1
import requests
try:
response = requests.get('https://www.google.com', timeout=1)
except requests.exceptions.Timeout:
print('timeout')
else:
print(response.status_code)
200
#timeout= 0.00001
import requests
try:
response = requests.get('https://www.google.com', timeout=0.00001)
except requests.exceptions.Timeout:
print('timeout')
else:
print(response.status_code)
timeout
해당 시간에 응답을 못받을 경우 위의 처럼 exception이 일어나면서
그에 대한 대응을 마련한다.
- requests.exceptions.ConnectionError
import requests
try:
response = requests.get('https://www.google.com:4000', timeout=5)
except requests.exceptions.ConnectionError:
print('ConnectionError')
else:
print(response.status_code)
ConnectionError
또한 서버가 기다리는 포트가 아닌 다른 포트로 접근을 시도하려고 할 경우
클라이언트와 서버가 만나지 못해 request.exceptions.ConnectionError의 이름으로 예외가 발생한다.
- reqests.exceptions.InvalidURL
import requests
try:
response = requests.get('https://///')
except requests.exceptions.InvalidURL:
print('InvalidURL')
else:
print(response.status_code)
invalidURL
리소스 URL을 다소 잘못된 형태로 기입하는 경우 다음과 같은 예외가 발생한다.
'Developer > Python' 카테고리의 다른 글
[python] SQLite, sqlite3을 활용한 CRUD (1) | 2025.07.14 |
---|---|
[python] requests CRUD (3) | 2025.07.14 |
[python] XML , XML 모듈 (0) | 2025.07.13 |
[python] JSON, JSON 모듈 (6) | 2025.07.12 |
[python] socket (1) | 2025.07.12 |