Web App 개발 — FastAPI를 Spring Boot 멘탈 모델로 매핑하기 · 퀴즈

7 문항 · Bloom: Understand:1, Apply:3, Analyze:2, Evaluate:1

Q1 Understand mcq_single

Spring Boot 컨트롤러의 어노테이션 세트와 FastAPI의 대응 요소를 1:1로 가장 정확하게 매핑한 것은 무엇인가?

정답: A
FastAPI에서는 APIRouter가 컨트롤러 모듈화(@RestController + @RequestMapping prefix)를, path operation 데코레이터(@app.get/post)가 라우팅+@ResponseBody+OpenAPI 등록을, Depends()가 명시적 함수형 DI(@Autowired)를, BackgroundTasks가 가벼운 응답 후 후처리(@Async)를 담당합니다.
오답 해설:
  • B. path operation 데코레이터는 메서드 매핑이지 컨트롤러 자체가 아니며, APIRouter는 @GetMapping이 아닌 prefix 모듈화 도구입니다.
  • C. Pydantic BaseModel은 DTO/검증 계층(@Valid 대상)이지 컨트롤러가 아니고, Depends()는 라우트 매핑이 아니라 DI입니다.
  • D. BackgroundTasks는 후처리 도구이지 컨트롤러 정의가 아니며, path operation 데코레이터를 @Async로 보는 것은 역할 혼동입니다.
Q2 Apply mcq_single

FastAPI의 Depends()를 처음 쓰는 Spring 베테랑이 자주 빠지는 함정으로 가장 정확한 설명은?

정답: C
FastAPI는 Spring 같은 전역 DI 컨테이너가 없습니다. Depends()는 함수 호출 시점에 시그니처를 읽어 의존성 그래프를 해석하므로 반드시 시그니처에 명시해야 합니다. scope는 별도 어노테이션이 아니라 callable의 형태(매 호출 새 인스턴스 vs 모듈 레벨 객체 vs yield 패턴)로 결정됩니다.
오답 해설:
  • A. Spring Boot 멘탈 모델로 가장 흔한 오해입니다. Depends() 자체는 application-scope 싱글턴 보장이 없으며, 싱글턴이 필요하면 모듈 레벨 객체를 반환하도록 callable을 직접 작성해야 합니다.
  • B. 이름이 비슷해 자동 주입을 기대하지만, FastAPI는 명시적으로 시그니처에 Depends를 적어야 합니다 — 함수 시그니처가 곧 의존성 선언입니다.
  • D. yield는 enter/exit 훅(트랜잭션·세션 정리)이지 별도 스레드 실행이 아닙니다. @Async에 가까운 것은 BackgroundTasks이며 그것도 같은 프로세스에서 응답 직후에 실행됩니다.
Q3 Apply mcq_single

Pydantic v2 BaseModel을 FastAPI 라우트의 body 파라미터로 두었을 때 검증이 실패하면 어떤 일이 벌어지는가?

정답: C
Pydantic v2가 시그니처의 BaseModel을 보고 요청 body를 자동 파싱·검증하며, 실패 시 FastAPI가 ValidationError를 가로채 422 Unprocessable Entity와 함께 어떤 필드가 어떤 제약을 위반했는지 상세 JSON을 만들어 줍니다. Spring의 GlobalExceptionHandler + MethodArgumentNotValidException 보일러플레이트가 필요 없습니다.
오답 해설:
  • A. Spring 멘탈 모델 그대로의 오해입니다. FastAPI는 422 응답 핸들러가 기본 내장이라 커스터마이징이 필요할 때만 exception_handler를 등록합니다.
  • B. ValidationError는 핸들러 진입 전에 가로채지므로 500이 아니라 422가 나갑니다. 직접 직렬화할 필요가 없습니다.
  • D. 검증은 핸들러 실행 전(요청 바인딩 시점)에 일어납니다. 핸들러 본문은 검증을 통과한 모델만 보게 됩니다.
Q4 Apply mcq_single

JPA 베테랑이 SQLAlchemy 2.0 async 세션으로 옮길 때 가장 주의해야 할 동작 차이는 무엇인가?

정답: B
비동기 세계에서는 lazy loading이 동기 가정에 의존하므로 명시적 eager loading(selectinload/joinedload)이 안전합니다. 그리고 expire_on_commit=False는 commit 후에도 ORM 객체가 살아 있게 해 JPA의 LazyInitializationException 류 트랩을 회피하는 핵심 설정입니다.
오답 해설:
  • A. JPA 멘탈 모델로 자주 발생하는 오해입니다. SQLAlchemy도 dirty tracking이 있지만 commit 시점이나 flush 시점은 JPA만큼 '알아서' 도는 인상이 약하고, async에서는 명시적 commit이 권장됩니다 — 무엇보다 '필드 수정만으로 UPDATE 보장'을 신뢰해선 안 됩니다.
  • C. SQLAlchemy 자체에는 @Transactional 데코레이터가 없습니다. FastAPI Depends + yield 패턴으로 직접 enter/exit를 작성하는 명시적 모델입니다.
  • D. AsyncSession에도 identity map(1차 캐시)이 있어 동일 키 조회는 캐시 히트할 수 있습니다. JPA persistence context와 비슷한 역할을 합니다.
Q5 Analyze mcq_multi

Alembic autogenerate 마이그레이션을 운영에 적용할 때 주의해야 할 사항으로 옳은 것 2개를 고르시오.

정답: A, C
Alembic autogenerate는 모델 메타데이터 diff에 의존하므로 의미가 같은 변경(rename)을 구조적으로는 'drop + add'로 잘못 해석할 수 있고, 데이터 보존이 필요한 변경은 사람이 직접 보강해야 안전합니다. 운영 정책으로는 forward-only + 작은 단위 + 코드 리뷰가 정석이며, Flyway 운영 노하우가 그대로 재활용됩니다.
오답 해설:
  • B. Alembic downgrade 스크립트는 Python으로 직접 작성해야 하며, autogenerate가 만들어 주는 downgrade는 구조적 역연산이지 데이터 복원 보장이 없습니다. 운영에서는 보통 forward-only 정책으로 가는 편이 안전합니다.
  • D. Alembic은 별도 CLI 명령(alembic upgrade head)으로 실행하며 부팅 시 자동 실행되지 않습니다. Hibernate ddl-auto=update 같은 자동 적용을 기대하면 안 됩니다.
  • E. autogenerate가 생성하는 것은 op.create_table() 같은 Alembic 연산 코드이지 raw DDL이 아닙니다. 실제 DDL은 SQL 로그(echo=True)나 alembic upgrade --sql로 확인합니다.
Q6 Analyze mcq_single

FastAPI 통합 테스트에서 dependency_overrides + httpx AsyncClient를 사용할 때, Spring의 @MockBean·@TestConfiguration과 비교해 가장 정확한 분석은?

정답: B
dependency_overrides는 Depends()로 들어오는 의존성에만 작동합니다. 모듈 import 시점에 일어나는 사이드이펙트나 라우트 함수 외부에서 직접 인스턴스화한 객체는 교체할 수 없어 별도 패턴(monkeypatch, env 분리 등)이 필요합니다. 또한 DB 격리는 savepoint/rollback과 schema 재생성 중 선택해야 하는 명확한 트레이드오프가 있습니다.
오답 해설:
  • A. Spring ApplicationContext 캐시 모델을 그대로 옮긴 오해입니다. dependency_overrides는 app 객체의 dict이며 테스트 후 명시적으로 clear()해야 다른 테스트에 영향이 없습니다.
  • C. AsyncClient(app=app)는 ASGI를 in-process로 호출하므로 실제 포트를 열지 않습니다. Spring 컨텍스트 부팅(수 초)에 비해 매우 가볍습니다.
  • D. pytest-asyncio 픽스처 기본 scope는 function이 맞지만, scope를 'session'으로 두면 픽스처가 재사용되고 의존성 그래프가 자동 리셋되지 않습니다 — 격리는 명시적 정리가 필요합니다.
Q7 Evaluate short_answer

신규 LLM 챗봇 마이크로서비스를 만들어야 하는데, 사내 표준은 Spring Boot이고 운영팀은 JVM APM·GC 튜닝 노하우가 풍부하다. 팀에는 Spring 시니어 5명, Python 시니어 1명이 있다. FastAPI vs Spring Boot 중 어느 스택을 추천할지, 본문에서 다룬 평가 축(런타임 모델·콜드스타트·메모리·도구 성숙도·팀 학습 곡선·에코시스템) 중 최소 3가지를 근거로 2~4문장으로 결정 근거를 작성하시오. 단일 정답 대신 근거의 일관성을 평가합니다.

채점 기준:
  • 추천 스택을 명확히 선택하고 결론을 한 문장으로 제시 (1pt)
  • 최소 3개 평가 축을 인용 — 예: 런타임 모델(asyncio coloring vs Loom·thread pool), 콜드스타트(FastAPI 수백 ms vs Spring Boot 수 초), 메모리 풋프린트(Python 50~200MB vs JVM 200~600MB), 도구 성숙도(JVM APM·profiling 우세), 팀 학습 곡선(Spring 시니어 5 vs Python 시니어 1의 채용·온보딩 비용), 에코시스템(AI/LLM은 Python 우세) 중 3개 이상 (3pt)
  • 트레이드오프를 양면으로 인정 — '~는 우세하지만 ~ 비용이 든다' 식의 균형 잡힌 서술 (1pt)
  • 혼용 전략(예: '신규 LLM 마이크로서비스만 FastAPI로 잘라내고 인터페이스로 격리') 또는 결정 트리 적용 흔적 언급 시 가산 (1pt 보너스)
  • Spring Boot 동작을 잘못 일반화하거나(예: 'Loom 없으면 동기는 절대 비동기가 안 된다') FastAPI 한계를 무시하면(예: '도구 성숙도가 JVM과 동일하다') 감점