Skip to content

Conversation

@deveroskp
Copy link
Contributor

  • 로컬 환경에서는 어드민 페이지가 잘 들어가지 지만, 배포 환경에서 어드민 페이지 접속 시 오류가 발생하여 해결하였습니다. 원인을 잘 모르겠어서 제미나이의 도움을 받아 해결했습니다.

제미나이 답변

사용자의 app.py 코드를 보면, 문제의 원인이 된 HttpToHttpsRequestMiddleware는 로컬(local)이나 테스트(test) 환경에서는 아예 등록되지 않도록 설정되어 있습니다.

이 로직 때문에 로컬에서 개발할 때는 해당 미들웨어가 작동하지 않아 아무런 문제가 없었지만, 배포 환경(AWS)에서는 이 미들웨어가 활성화되면서 오류를 유발했습니다.

  1. 근본적인 기술적 원인 (The Root Cause)
    오류 로그(ExceptionGroup: unhandled errors in a TaskGroup)는 BaseHTTPMiddleware와 AnyIO 4.x 버전 간의 호환성 문제 때문에 발생합니다.

배경: FastAPI와 Starlette는 비동기 처리를 위해 AnyIO라는 라이브러리를 사용합니다.
버전 불일치: 현재 프로젝트의 의존성을 보면 AnyIO는 최신 버전인 4.12.0을 사용 중이지만, Starlette는 0.27.0 (FastAPI 0.95.2 의존성)을 사용하고 있습니다.
충돌 내용:
AnyIO 4.0 버전부터는 태스크 그룹 내에서 발생한 예외를 ExceptionGroup이라는 새로운 방식으로 묶어서 처리합니다.
하지만 구버전 Starlette의 BaseHTTPMiddleware 구현체는 내부적으로 요청을 처리하기 위해 비동기 태스크를 생성하는데, 여기서 발생하는 AnyIO 4.x 스타일의 ExceptionGroup 예외를 제대로 포착하거나 처리하지 못합니다.
결과적으로 아주 사소한 연결 종료나 내부 신호조차도 "처리되지 않은 예외 그룹"으로 간주되어 500 Internal Server Error를 터뜨리게 됩니다.
요약 및 해결
BaseHTTPMiddleware는 내부 구현이 복잡하여 이러한 호환성 문제가 잦습니다. 따라서, 이번에 수정한 것처럼 Starlette의 순수 ASGI 인터페이스를 직접 사용하여 미들웨어를 구현하면, 복잡한 내부 태스크 관리 없이 가볍게 동작하므로 해당 오류를
완전히 피할 수 있습니다.

@deveroskp deveroskp requested a review from a team as a code owner January 9, 2026 09:08
@deveroskp deveroskp linked an issue Jan 9, 2026 that may be closed by this pull request
@coderabbitai
Copy link

coderabbitai bot commented Jan 9, 2026

📝 Walkthrough

Walkthrough

Starlette의 클래스 기반 BaseHTTPMiddleware를 제거하고, scope를 직접 변형한 ASGI 호출 가능 미들웨어로 리팩토링했습니다. dispatch에서 __call__으로 시그니처가 변경되었고, HTTP/웹소켓 요청에 대해 scheme을 각각 "https"/"wss"로 설정한 뒤 내부 앱으로 전달합니다.

Changes

코호트 / 파일(들) 변경 요약
미들웨어 구현 변경
wacruit/src/utils/middlewares.py
HttpToHttpsRequestMiddlewareBaseHTTPMiddleware 기반 클래스에서 원시 ASGI 호출 가능 객체로 전환. async def dispatch(request, call_next) -> Response 제거, __init__(self, app: ASGIApp)async def __call__(scope: Scope, receive: Receive, send: Send) -> None 추가.
타입/임포트 조정
wacruit/src/utils/middlewares.py
Request, Response, BaseHTTPMiddleware, RequestResponseEndpoint 임포트 제거 및 ASGIApp, Scope, Receive, Send 등 ASGI 타입으로 교체.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • MunJaeyoung
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 변경 사항과 명확하게 관련되어 있으며, 순수 ASGI 인터페이스로의 전환이라는 주요 변경 사항을 잘 요약하고 있습니다.
Description check ✅ Passed 설명이 배포 환경에서의 문제, 근본 원인(AnyIO 4.x와 BaseHTTPMiddleware의 호환성), 해결 방식을 상세히 담고 있어 변경 사항과 명확하게 관련되어 있습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @wacruit/src/utils/middlewares.py:
- Around line 11-14: The middleware currently sets scope["scheme"] = "https" for
both HTTP and WebSocket in __call__, which is incorrect; change the logic so
that when scope["type"] == "http" set scope["scheme"] = "https" and when
scope["type"] == "websocket" set scope["scheme"] = "wss", preserving the call to
await self.app(scope, receive, send); reference the __call__ method,
scope["type"], scope["scheme"], and self.app to locate and update the code.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a45a89 and a447cf3.

📒 Files selected for processing (1)
  • wacruit/src/utils/middlewares.py
🔇 Additional comments (2)
wacruit/src/utils/middlewares.py (2)

1-4: 순수 ASGI 인터페이스로의 임포트가 올바릅니다.

BaseHTTPMiddleware 의존성을 제거하고 순수 ASGI 타입만 임포트하여 AnyIO 4.x 호환성 문제를 해결하는 접근 방식이 적절합니다.


7-9: 표준 ASGI 미들웨어 패턴을 올바르게 따릅니다.

클래스 정의와 초기화가 ASGI 미들웨어 표준을 따르고 있으며, BaseHTTPMiddleware 제거를 통해 PR에서 언급한 호환성 문제를 해결합니다.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
wacruit/src/utils/middlewares.py (1)

11-16: LGTM! 순수 ASGI 인터페이스 구현이 정확합니다.

__call__ 메서드가 ASGI 사양을 올바르게 따르고 있습니다:

  • HTTP 요청에는 "https" scheme 설정
  • WebSocket 연결에는 "wss" scheme 설정
  • 다른 scope 타입(예: "lifespan")은 자동으로 변경 없이 통과

scope 직접 변경은 ASGI 미들웨어의 표준 패턴이므로 안전합니다.

♻️ 선택적 개선: 명시적인 lifespan 처리

가독성 향상을 위해 lifespan 이벤트를 명시적으로 처리하는 것을 고려해볼 수 있습니다 (현재 동작은 이미 올바릅니다):

 async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
     if scope["type"] == "http":
         scope["scheme"] = "https"
     elif scope["type"] == "websocket":
         scope["scheme"] = "wss"
+    # lifespan 및 기타 scope 타입은 변경 없이 통과
     await self.app(scope, receive, send)
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a447cf3 and 5e87d7b.

📒 Files selected for processing (1)
  • wacruit/src/utils/middlewares.py
🔇 Additional comments (2)
wacruit/src/utils/middlewares.py (2)

1-4: LGTM! 순수 ASGI 타입으로의 전환이 적절합니다.

BaseHTTPMiddleware 의존성을 제거하고 순수 ASGI 타입(ASGIApp, Scope, Receive, Send)으로 변경한 것이 올바릅니다. 이를 통해 AnyIO 4.x와의 호환성 문제를 해결할 수 있습니다.


7-9: LGTM! 핵심 문제 해결을 위한 올바른 변경입니다.

BaseHTTPMiddleware 상속을 제거하고 순수 ASGI 미들웨어 패턴으로 변경한 것이 적절합니다. 이것이 프로덕션 환경에서 발생했던 ExceptionGroup 처리 문제를 해결하는 핵심 변경사항입니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FIX] 배포 환경에서 admin 페이지 접속 오류

2 participants