파이썬 Sanic 프레임워크란?

Sanic은 파이썬으로 작성된 비동기 웹 프레임워크로, 고성능비동기 처리에 최적화되어 있습니다. 특히 비동기/병렬 처리를 지원하므로, 네트워크 요청이 많은 실시간 API, 웹소켓, 비동기 작업 처리 등의 작업에 매우 적합합니다. Python의 asyncio를 사용하여 비동기 I/O 작업을 수행하며, 대규모의 비동기 API 또는 서비스에 적합합니다.

Sanic의 가장 큰 특징은 비동기적으로 작성된다는 점입니다. 이를 통해 네트워크 요청을 비동기적으로 처리하며, 성능을 최대로 끌어올릴 수 있습니다.

주요 특징

  1. 비동기 처리: async/await 구문을 통해 비동기 처리와 병렬 작업이 가능합니다.
  2. 고성능: 요청-응답 처리가 매우 빠르며, 초당 수천 개의 요청을 처리할 수 있습니다.
  3. WSGI 미지원: Sanic은 WSGI를 사용하지 않으며, 직접 이벤트 루프를 관리합니다.
  4. 웹소켓 지원: 웹소켓을 쉽게 사용할 수 있으며, 실시간 통신에 적합합니다.
  5. 자동화된 JSON 응답: 편리한 JSON 처리 기능을 제공합니다.

Sanic 설치

Sanic은 pip를 사용하여 쉽게 설치할 수 있습니다.

pip install sanic

1. 기본 Sanic 예제

Sanic의 가장 간단한 "Hello World" 예제입니다.

from sanic import Sanic
from sanic.response import json

# 애플리케이션 인스턴스 생성
app = Sanic("HelloWorldApp")

# GET 요청에 대한 라우팅 설정
@app.route("/")
async def hello_world(request):
    return json({"message": "Hello, world!"})

# 서버 실행
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)

설명

  • Sanic("HelloWorldApp"): Sanic 애플리케이션을 생성합니다. Sanic의 애플리케이션은 비동기적으로 동작하므로, 함수에 async 키워드를 사용합니다.
  • @app.route("/"): 라우팅을 설정하여, / 경로에 대한 GET 요청을 처리합니다.
  • return json(...): JSON 응답을 반환합니다. Sanic은 JSON 응답을 매우 쉽게 처리할 수 있습니다.
  • app.run(): 서버를 실행하며, 기본적으로 0.0.0.0에서 8000번 포트로 실행됩니다.

2. 비동기 작업 처리 예제

Sanic의 비동기 기능을 활용하면 비동기 I/O 작업을 매우 간단하게 처리할 수 있습니다. 예를 들어, 비동기적으로 데이터를 가져오고 처리하는 API를 만들어보겠습니다.

from sanic import Sanic
from sanic.response import json
import asyncio

app = Sanic("AsyncApp")

# 비동기 GET 요청 처리
@app.route("/async")
async def async_example(request):
    await asyncio.sleep(1)  # 1초 대기
    return json({"message": "This was an async request!"})

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)

설명

  • await asyncio.sleep(1): 비동기적으로 1초 대기합니다. 다른 작업을 블로킹하지 않고 대기 상태를 유지할 수 있습니다.
  • 비동기 작업을 통해 I/O 바운드 작업을 효율적으로 처리할 수 있습니다.

3. POST 요청 처리 예제

Sanic을 사용하여 POST 요청을 처리하고, 클라이언트로부터 데이터를 받아 처리할 수 있습니다.

from sanic import Sanic
from sanic.response import json

app = Sanic("PostExampleApp")

# POST 요청 처리
@app.route("/post", methods=["POST"])
async def handle_post(request):
    data = request.json  # 요청의 JSON 데이터 가져오기
    return json({"received_data": data})

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)

설명

  • request.json: 클라이언트가 보낸 POST 요청에서 JSON 데이터를 가져옵니다.
  • POST 요청을 처리할 때는 methods=["POST"]를 통해 HTTP 메서드를 지정합니다.

4. URL 매개변수 처리 예제

Sanic은 URL에서 매개변수를 쉽게 받아 처리할 수 있습니다.

from sanic import Sanic
from sanic.response import json

app = Sanic("ParamsExampleApp")

# URL 매개변수 처리
@app.route("/hello/<name>")
async def greet_user(request, name):
    return json({"message": f"Hello, {name}!"})

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)

설명

  • @app.route("/hello/<name>"): URL에서 <name>이라는 매개변수를 받아서 해당 값을 처리합니다.
  • greet_user(request, name): 함수의 두 번째 인자로 URL에서 추출된 name 값을 받습니다.

5. 미들웨어 사용 예제

Sanic에서 미들웨어를 사용하여 요청이나 응답 전에 공통 작업을 처리할 수 있습니다.

from sanic import Sanic
from sanic.response import json

app = Sanic("MiddlewareExampleApp")

# 요청 전 미들웨어
@app.middleware("request")
async def add_request_header(request):
    request.headers["X-Custom-Header"] = "CustomValue"

# 응답 전 미들웨어
@app.middleware("response")
async def add_response_header(request, response):
    response.headers["X-Processed-Time"] = "Processed in Sanic"

# 기본 GET 요청 처리
@app.route("/")
async def index(request):
    return json({"message": "Check the headers!"})

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)

설명

  • @app.middleware("request"): 요청이 들어오기 전에 실행되는 미들웨어를 정의합니다. 예제에서는 요청 헤더에 X-Custom-Header를 추가합니다.
  • @app.middleware("response"): 응답을 반환하기 전에 실행되는 미들웨어를 정의합니다. 응답 헤더에 X-Processed-Time 값을 추가합니다.

6. Sanic의 웹소켓 지원 예제

Sanic은 웹소켓을 지원하여 실시간 통신을 구현할 수 있습니다. 다음 예제는 간단한 웹소켓 서버입니다.

from sanic import Sanic
from sanic.response import json
from sanic.websocket import WebSocketProtocol

app = Sanic("WebSocketExampleApp")

# 웹소켓 연결 처리
@app.websocket("/ws")
async def websocket_handler(request, ws):
    while True:
        data = await ws.recv()  # 클라이언트로부터 메시지 수신
        await ws.send(f"Echo: {data}")  # 받은 메시지를 그대로 다시 보냄

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000, protocol=WebSocketProtocol)

설명

  • @app.websocket("/ws"): 웹소켓 경로를 정의합니다.
  • ws.recv(): 클라이언트로부터 메시지를 수신합니다.
  • ws.send(): 수신된 메시지를 클라이언트로 다시 전송합니다(에코 서버).

7. 파일 업로드 처리 예제

Sanic에서 파일 업로드를 처리하는 방법입니다.

from sanic import Sanic
from sanic.response import json

app = Sanic("FileUploadExampleApp")

@app.route("/upload", methods=["POST"])
async def upload_file(request):
    file = request.files.get('file')  # 업로드된 파일 가져오기
    file_content = file.body  # 파일의 내용
    file_name = file.name  # 파일명

    return json({"file_name": file_name, "file_size": len(file_content)})

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)

설명

  • request.files.get('file'): 업로드된 파일을 가져옵니다.
  • file.body: 파일의 내용을 가져옵니다.
  • 업로드된 파일의 이름과 크기를 JSON으로 반환합니다.

결론

Sanic은 비동기 I/O 처리와 고성능 웹 애플리케이션을 구축하는 데 매우 적합한 프레임워크입니다. 비동기 처리, 웹소켓 지원, 미들웨어와 같은 강력한 기능을 제공하여 실시간 처리나 대규모 네트워크 요청이 필요한 환경에서 뛰어난 성능을 발휘합니다.

더 복잡한 응용 프로그램이나 다른 기능에 대해 궁금한 점이 있다면 언제든지 질문해 주세요!

+ Recent posts