Flask와 FastAPI를 같은 서버에서 동시에 운영

calico·2025년 10월 20일

Computer Science

목록 보기
39/51

컨테이너 없이도 포트만 분리하면 Flask와 FastAPI를 같은 서버에서 동시에 운영 가능


1. 현재 상황


※ 전체 임의 값

  • byproductgas (Flask, port=8000)

  • energy (Flask, port=8001)

  • 신규 기능: FastAPI로 개발 예정 (port=8002)

  • 목표: 기존 Flask 서비스는 그대로 두고, 신규 기능만 FastAPI로 추가



2. 운영 구조


[Client]  --->  [FastAPI JSON API:8002]
                  ↑
                  ├── JSON 생성 및 반환
                  
[Flask:8000]  byproductgas API
[Flask:8001]  energy API
  • 포트 분리로 서비스 간 충돌 없이 병행 운영
  • 클라이언트는 FastAPI의 /data 엔드포인트를 호출하여 JSON 데이터 수신



3. FastAPI JSON API 예시


from fastapi import FastAPI
from datetime import datetime

app = FastAPI(title="JSON Data API")

@app.get("/data")
async def get_data():
    # 예시 데이터
    data = [
        {"id": 1, "value": 10.5, "timestamp": datetime.now().isoformat()},
        {"id": 2, "value": 20.7, "timestamp": datetime.now().isoformat()},
    ]
    return {"status": "success", "count": len(data), "data": data}



실행


uvicorn fastapi_service.main:app --reload --port 8002



4. 운영 시 고려사항


  1. 포트 관리

    • Flask: 8000, 8001
    • FastAPI: 8002
  2. 보안

    • IP 화이트리스트 (허용된 서버만 접근 가능)
    • API Key 또는 토큰 인증
  3. 성능

    • JSON 응답은 직렬화 속도와 크기 최적화 필요
    • 대량 데이터는 페이지네이션(Pagination) 적용
  4. 로그 관리

    • 요청 시간, 요청자, 응답 크기, 처리 시간 기록
  5. API Gateway/Nginx 연동 (선택)

    • /byproductgas → Flask(8000)
    • /energy → Flask(8001)
    • /newfeature → FastAPI(8002)
    • 외부에서는 하나의 도메인으로 접근 가능



5. 폴더 구조 예시


byproductgas/     # Flask, port=8000
energy/           # Flask, port=8001
fastapi_service/  # FastAPI, port=8002
    main.py
    api/
        json_data.py
    config/
    models/



정리


  • 포트 분리만으로 Flask와 FastAPI를 같은 서버에서 안정적으로 운영 가능

  • 신규 기능은 FastAPI로 개발하여 /data 엔드포인트에서 JSON 응답 제공

  • 보안·성능·로그 관리까지 고려하면 운영 안정성이 높아짐



6. 실행 예제


Windows Jupyter 환경 기준

  • Flask: 간단한 JSON 응답 API (/hello)

  • FastAPI: 간단한 JSON 응답 API (/hello)

  • threading을 사용해 두 서버를 동시에 실행

  • Jupyter Notebook에서도 실행 가능

  • 포트: Flask → 8000, FastAPI → 8001


전체 코드


import threading
import time
from flask import Flask, jsonify
from fastapi import FastAPI
import uvicorn
import requests

# ---------------------------
# 1. Flask 앱 정의
# ---------------------------
flask_app = Flask(__name__)

@flask_app.route("/hello", methods=["GET"])
def hello_flask():
    return jsonify({"message": "Hello from Flask!"})

def run_flask():
    # host='127.0.0.1', port=8000
    flask_app.run(host="127.0.0.1", port=8000, debug=False, use_reloader=False)

# ---------------------------
# 2. FastAPI 앱 정의
# ---------------------------
fastapi_app = FastAPI()

@fastapi_app.get("/hello")
def hello_fastapi():
    return {"message": "Hello from FastAPI!"}

def run_fastapi():
    uvicorn.run(fastapi_app, host="127.0.0.1", port=8001, log_level="info")

# ---------------------------
# 3. 서버 실행 (threading)
# ---------------------------
flask_thread = threading.Thread(target=run_flask)
fastapi_thread = threading.Thread(target=run_fastapi)

flask_thread.start()
fastapi_thread.start()

# ---------------------------
# 4. 서버 준비 대기 후 테스트 요청
# ---------------------------
time.sleep(2)  # 서버가 뜰 시간 대기

# Flask API 호출
flask_response = requests.get("http://127.0.0.1:8000/hello")
print("Flask 응답:", flask_response.json())

# FastAPI API 호출
fastapi_response = requests.get("http://127.0.0.1:8001/hello")
print("FastAPI 응답:", fastapi_response.json())



실행 방법


  1. Jupyter Notebook에서 위 코드 셀을 실행

  2. 출력 예시

 * Serving Flask app '__main__'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment.
 * Running on http://127.0.0.1:8000
INFO:     Uvicorn running on http://127.0.0.1:8001
Flask 응답: {'message': 'Hello from Flask!'}
FastAPI 응답: {'message': 'Hello from FastAPI!'}



특징


  • 동시에 두 서버 실행: Flask와 FastAPI를 각각 다른 포트에서 실행

  • Jupyter 호환: threading 사용으로 Notebook에서 실행 가능

  • 간단한 API 테스트 포함: requests로 두 서버 응답 확인



주의사항


  • 현재 구조는 개발용 서버입니다. 운영 환경에서는 WSGI/ASGI 서버와 리버스 프록시(Nginx 등) 사용 권장

  • Jupyter에서 실행 시 커널 중지하면 두 서버가 함께 종료됩니다

  • 포트 충돌이 없도록 8000, 8001 등 서로 다른 포트를 사용해야 합니다



profile
All views expressed here are solely my own and do not represent those of any affiliated organization.

0개의 댓글