Python과 Flask로 간단한 REST API 만들기

Python

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가 기능적이긴 하지만, 프로덕션 환경을 위해 고려해볼 수 있는 몇 가지 개선 사항이 있습니다:

  1. 입력 유효성 검사: 들어오는 데이터가 적절하게 검증되도록 합니다
  2. 오류 처리: 더 강력한 오류 처리와 적절한 HTTP 상태 코드를 추가합니다
  3. 데이터베이스 통합: 메모리 내 리스트를 SQLite, PostgreSQL 또는 MongoDB와 같은 데이터베이스로 대체합니다
  4. 인증: API를 보호하기 위한 사용자 인증을 추가합니다
  5. 페이지네이션: 대규모 항목 컬렉션을 위한 페이지네이션을 구현합니다
  6. 속도 제한: API 남용을 방지하기 위한 속도 제한을 추가합니다
  7. 문서화: Swagger/OpenAPI와 같은 도구를 사용하여 API를 문서화합니다

결론

Flask를 사용한 REST API 생성은 간단하고 최소한의 코드만 필요합니다. 이 간단한 예제는 RESTful 설계의 핵심 원칙을 보여주며 더 복잡한 애플리케이션의 기초로 활용될 수 있습니다.

Flask의 단순함과 Python의 가독성은 작은 서비스나 대규모 애플리케이션을 구축하든 상관없이 API 개발에 탁월한 선택입니다.

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤