Python 미드레벨 프레임워크 기술면접
새 면접Q. Django의 미들웨어(Middleware) 실행 순서와 process_request, process_view, process_response의 호출 순서를 설명하고, 미들웨어에서 예외가 발생했을 때 process_exception이 어떻게 동작하는지 설명해주세요. 또한 실무에서 커스텀 미들웨어를 작성할 때 주의해야 할 점을 설명해주세요.
Django 미들웨어는 설정 순서대로 process_request와 process_view가 실행되고, 역순으로 process_response가 실행됩니다. 예외 발생 시 process_exception은 미들웨어 역순으로 호출되며, 하나의 미들웨어가 HttpResponse를 반환하면 다음 미들웨어로 전파되지 않습니다. 커스텀 미들웨어 작성 시에는 반드시 get_response를 호출하여 체인을 유지해야 하며, 성능에 영향을 주지 않도록 무거운 작업은 피해야 합니다. 또한 미들웨어 순서가 중요하므로 인증, 세션 등 의존성이 있는 미들웨어의 위치를 신중히 결정해야 합니다.
- • 미들웨어는 요청 시 순방향, 응답 시 역방향으로 실행됨
- • process_exception은 역순으로 호출되며 HttpResponse 반환 시 전파 중단
- • get_response 호출을 통한 체인 유지 필수
- • 미들웨어 순서와 성능 고려 필요
미들웨어와 데코레이터를 사용한 권한 체크 중 어느 것을 선택해야 하는지, 그리고 그 판단 기준은 무엇인지 설명해주세요.
Q. FastAPI의 Depends() 시스템이 내부적으로 어떻게 의존성 주입을 구현하는지 설명하고, 의존성이 중첩되어 있을 때 캐싱 메커니즘이 어떻게 동작하는지 설명해주세요. 또한 use_cache=False를 사용해야 하는 실무 시나리오를 제시해주세요.
FastAPI의 Depends()는 함수 시그니처를 검사하여 타입 힌트와 기본값을 분석한 후, 요청마다 의존성 트리를 구성하고 실행합니다. 동일한 요청 내에서 같은 의존성이 여러 번 호출되면 기본적으로 결과를 캐싱하여 재사용하므로, 데이터베이스 세션처럼 요청당 하나만 생성되어야 하는 리소스를 효율적으로 관리할 수 있습니다. 하지만 매번 다른 값을 반환해야 하는 타임스탬프 생성이나, 외부 API 호출 시 최신 데이터를 가져와야 하는 경우에는 use_cache=False를 사용해야 합니다. 의존성 주입 시스템은 비동기 함수도 자동으로 감지하여 await 처리를 수행합니다.
- • 타입 힌트 기반으로 의존성 트리를 자동 구성
- • 요청 단위로 의존성 결과를 캐싱하여 재사용
- • use_cache=False로 매번 새로운 값 생성 가능
- • 비동기/동기 함수 자동 감지 및 처리
FastAPI의 BackgroundTasks와 Celery를 비교했을 때, 각각 어떤 작업에 적합한지 설명해주세요.
Q. Flask의 Blueprint를 사용하는 이유와 애플리케이션 팩토리 패턴(Application Factory Pattern)과의 관계를 설명하고, 대규모 프로젝트에서 Blueprint를 구조화할 때의 베스트 프랙티스를 설명해주세요.
Flask Blueprint는 애플리케이션을 모듈화하여 라우트, 템플릿, 정적 파일을 논리적 단위로 그룹화하고, 재사용 가능한 컴포넌트로 만들 수 있게 합니다. 애플리케이션 팩토리 패턴과 함께 사용하면 순환 참조를 방지하고, 테스트용 앱과 프로덕션 앱을 다르게 구성할 수 있어 유연성이 높아집니다. 대규모 프로젝트에서는 기능별로 Blueprint를 분리하고, 각 Blueprint마다 독립적인 url_prefix를 부여하며, before_request나 errorhandler를 Blueprint 레벨에서 관리하여 관심사를 분리합니다. 또한 Blueprint 간 의존성을 최소화하고, 공통 기능은 별도의 유틸리티 모듈로 분리하는 것이 좋습니다.
- • 모듈화를 통한 코드 구조화와 재사용성 향상
- • 애플리케이션 팩토리 패턴으로 순환 참조 방지 및 유연한 설정
- • 기능별 Blueprint 분리와 독립적인 url_prefix 사용
- • Blueprint 레벨에서 훅과 에러 핸들러 관리
Flask의 before_request, before_app_request, before_app_first_request의 차이점과 각각의 사용 시나리오를 설명해주세요.
Q. Django의 시그널(Signals) 시스템이 어떻게 동작하는지 설명하고, post_save 시그널을 사용할 때 발생할 수 있는 문제점들(트랜잭션, 성능, 순환 참조)과 이를 해결하기 위한 방법을 설명해주세요. 또한 시그널 대신 다른 패턴을 사용하는 것이 더 나은 경우를 제시해주세요.
Django 시그널은 발행-구독 패턴으로 구현되어 있으며, 특정 이벤트 발생 시 등록된 모든 리시버 함수를 동기적으로 순차 실행합니다. post_save 시그널은 트랜잭션 커밋 전에 실행되므로 롤백 시 시그널 내 작업이 이미 수행되어 데이터 불일치가 발생할 수 있으며, 이는 transaction.on_commit()으로 해결할 수 있습니다. 또한 여러 리시버가 등록되면 성능 저하가 발생하고, 시그널 내에서 모델 저장 시 무한 루프가 발생할 수 있으므로 update_fields 체크나 플래그 변수로 방지해야 합니다. 명확한 비즈니스 로직이 있다면 시그널보다 서비스 레이어나 모델 메서드의 오버라이딩(save() 메서드)을 사용하는 것이 코드 추적과 유지보수에 유리합니다.
- • 동기적 순차 실행으로 성능 영향 가능
- • 트랜잭션 커밋 전 실행으로 데이터 불일치 위험, transaction.on_commit() 사용
- • 순환 참조 방지를 위한 조건 체크 필요
- • 명확한 로직은 서비스 레이어나 모델 메서드 오버라이딩 선호
Django에서 대량의 모델 인스턴스를 생성할 때 bulk_create를 사용하면 시그널이 발생하지 않는데, 이를 해결하기 위한 방법은 무엇인가요?
Q. Pydantic의 데이터 검증이 런타임에 어떻게 수행되는지 설명하고, validator와 root_validator의 차이점을 설명해주세요. 또한 FastAPI에서 Pydantic 모델을 사용할 때 성능 최적화를 위해 고려해야 할 사항들을 설명해주세요.
Pydantic은 타입 힌트를 기반으로 런타임에 데이터를 파싱하고 검증하며, 내부적으로 각 필드의 타입 변환과 제약조건을 체크합니다. validator는 개별 필드에 대한 검증을 수행하며 pre=True 옵션으로 타입 변환 전후 시점을 선택할 수 있고, root_validator는 모든 필드 검증 후 전체 데이터를 대상으로 교차 검증을 수행합니다. FastAPI에서는 요청마다 Pydantic 검증이 수행되므로, 복잡한 중첩 모델은 성능에 영향을 줄 수 있어 필요한 필드만 포함하고, Config.extra = 'forbid'로 불필요한 필드를 조기에 차단하며, 재사용 가능한 모델을 캐싱하는 것이 좋습니다.
- • 타입 힌트 기반 런타임 검증 및 타입 변환
- • validator는 필드별, root_validator는 전체 데이터 교차 검증
- • pre=True/False로 검증 시점 제어
- • 불필요한 필드 제거와 모델 재사용으로 성능 최적화
Pydantic V2에서 도입된 성능 개선 사항과 V1과의 주요 차이점을 설명해주세요.
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!