
REST API는 현대 웹 애플리케이션의 중추로, 다양한 시스템 간의 원활한 통신을 가능하게 합니다. 오늘은 Python과 Flask를 사용하여 기본적인 CRUD 작업(생성, 읽기, 업데이트, 삭제)을 구현하는 간단하면서도 실용적인 REST API를 만드는 방법을 알아보겠습니다.
우리가 만들 것
각 항목에 다음과 같은 속성을 가진 상품 컬렉션을 관리하는 간단한 API를 만들 것입니다:
- ID
- 이름
- 가격
이 API는 다음과 같은 표준 작업을 지원할 것입니다:
- 모든 항목 조회하기
- ID로 특정 항목 조회하기
- 새 항목 생성하기
- 기존 항목 업데이트하기
- 항목 삭제하기
코드
전체 구현부터 살펴보고 자세히 분석해 보겠습니다:
from flask import Flask, jsonify, request
app = Flask(__name__)
items = [
{"id": 1, "name": "apple", "price": 1000},
{"id": 2, "name": "banana", "price": 1500},
{"id": 3, "name": "orange", "price": 2000}
]
# GET /api/hello
@app.route("/api/hello")
def hello():
return "Hello, World!"
# GET /api/items
@app.route("/api/items")
def get_items():
return jsonify(items)
# GET /api/items/{id}
@app.route("/api/items/<int:item_id>")
def get_item(item_id):
for item in items:
if item["id"] == item_id:
return jsonify(item)
return jsonify({"message": "Item not found"}), 404
# POST /api/items
@app.route("/api/items", methods=["POST"])
def create_item():
item = request.get_json()
items.append(item)
return jsonify(item), 201
# PUT /api/items/{id}
@app.route("/api/items/<int:item_id>", methods=["PUT"])
def update_item(item_id):
item = request.get_json()
for i in range(len(items)):
if items[i]["id"] == item_id:
items[i] = item
return jsonify(item)
return jsonify({"message": "Item not found"}), 404
# DELETE /api/items/{id}
@app.route("/api/items/<int:item_id>", methods=["DELETE"])
def delete_item(item_id):
for i in range(len(items)):
if items[i]["id"] == item_id:
del items[i]
return jsonify({"message": "Item deleted"}), 200
return jsonify({"message": "Item not found"}), 404
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000, debug=True)
코드 이해하기
Flask 설정하기
from flask import Flask, jsonify, request
app = Flask(__name__)
여기서는 필요한 모듈을 가져오고 Flask 애플리케이션 인스턴스를 생성합니다. jsonify
함수는 Python 딕셔너리를 JSON 응답으로 변환하고, request
는 들어오는 데이터를 처리합니다.
데이터 저장소
items = [
{"id": 1, "name": "apple", "price": 1000},
{"id": 2, "name": "banana", "price": 1500},
{"id": 3, "name": "orange", "price": 2000}
]
간단하게 하기 위해 메모리 내 리스트를 사용하여 항목을 저장합니다. 실제 애플리케이션에서는 일반적으로 데이터베이스를 사용할 것입니다.
API 엔드포인트
Hello World 엔드포인트
@app.route("/api/hello")
def hello():
return "Hello, World!"
간단한 인사말을 반환하는 엔드포인트입니다. API가 실행 중인지 테스트하는 데 유용합니다.
모든 항목 가져오기 (Read)
@app.route("/api/items")
def get_items():
return jsonify(items)
이 엔드포인트는 모든 항목을 JSON 배열로 반환합니다.
특정 항목 가져오기 (Read)
@app.route("/api/items/<int:item_id>")
def get_item(item_id):
for item in items:
if item["id"] == item_id:
return jsonify(item)
return jsonify({"message": "Item not found"}), 404
ID로 특정 항목을 검색합니다. 찾지 못한 경우 404 상태 코드와 오류 메시지를 반환합니다.
항목 생성하기 (Create)
@app.route("/api/items", methods=["POST"])
def create_item():
item = request.get_json()
items.append(item)
return jsonify(item), 201
이 엔드포인트는 컬렉션에 새 항목을 추가합니다. 다음과 같은 작업을 수행합니다:
- JSON 요청 본문에서 항목 데이터를 추출
- 해당 항목을 items 리스트에 추가
- 201 상태 코드(Created)와 함께 생성된 항목 반환
항목 업데이트하기 (Update)
@app.route("/api/items/<int:item_id>", methods=["PUT"])
def update_item(item_id):
item = request.get_json()
for i in range(len(items)):
if items[i]["id"] == item_id:
items[i] = item
return jsonify(item)
return jsonify({"message": "Item not found"}), 404
이 엔드포인트는 기존 항목을 새 데이터로 대체하여 업데이트합니다.
항목 삭제하기 (Delete)
@app.route("/api/items/<int:item_id>", methods=["DELETE"])
def delete_item(item_id):
for i in range(len(items)):
if items[i]["id"] == item_id:
del items[i]
return jsonify({"message": "Item deleted"}), 200
return jsonify({"message": "Item not found"}), 404
이 엔드포인트는 컬렉션에서 항목을 제거하고 삭제를 확인합니다.
애플리케이션 실행하기
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000, debug=True)
이 코드는 스크립트가 직접 실행될 때 Flask 개발 서버를 시작합니다.
참고:
host="0.0.0.0"
을 설정하는 것은 Docker 컨테이너에서 실행할 때와 같이 API가 로컬 머신 외부에서 접근 가능하게 하려면 매우 중요합니다. 배포 시나리오에 상관없이 이 매개변수를 항상 포함하는 것이 좋습니다.
API 테스트하기
각 엔드포인트를 테스트하여 API가 어떻게 작동하는지 살펴보겠습니다:
모든 항목 가져오기
GET http://localhost:8000/api/items
이 요청은 초기 항목 리스트를 반환합니다.
특정 항목 가져오기
GET http://localhost:8000/api/items/1
이 요청은 apple 항목만 반환합니다.
새 항목 생성하기
POST http://localhost:8000/api/items
Content-Type: application/json
{"id": 4, "name": "test", "price": 2000}
이 요청은 컬렉션에 새 항목을 추가합니다.
항목 업데이트하기
PUT http://localhost:8000/api/items/4
Content-Type: application/json
{"id": 4, "name": "test1111", "price": 20001111}
이 요청은 방금 생성한 항목을 업데이트합니다.
항목 삭제하기
DELETE http://localhost:8000/api/items/4
이 요청은 방금 업데이트한 항목을 제거합니다.
다음 단계는?
이 API가 기능적이긴 하지만, 프로덕션 환경을 위해 고려해볼 수 있는 몇 가지 개선 사항이 있습니다:
- 입력 유효성 검사: 들어오는 데이터가 적절하게 검증되도록 합니다
- 오류 처리: 더 강력한 오류 처리와 적절한 HTTP 상태 코드를 추가합니다
- 데이터베이스 통합: 메모리 내 리스트를 SQLite, PostgreSQL 또는 MongoDB와 같은 데이터베이스로 대체합니다
- 인증: API를 보호하기 위한 사용자 인증을 추가합니다
- 페이지네이션: 대규모 항목 컬렉션을 위한 페이지네이션을 구현합니다
- 속도 제한: API 남용을 방지하기 위한 속도 제한을 추가합니다
- 문서화: Swagger/OpenAPI와 같은 도구를 사용하여 API를 문서화합니다
결론
Flask를 사용한 REST API 생성은 간단하고 최소한의 코드만 필요합니다. 이 간단한 예제는 RESTful 설계의 핵심 원칙을 보여주며 더 복잡한 애플리케이션의 기초로 활용될 수 있습니다.
Flask의 단순함과 Python의 가독성은 작은 서비스나 대규모 애플리케이션을 구축하든 상관없이 API 개발에 탁월한 선택입니다.