tech-map

이번 편이 만지는 곳: 개발의 외부 API와 데이터/저장소. 파일 업로드 검증과 외부 API 장애 대비를 붙인다.

기본 서비스가 떴으니 이제 재료를 붙인다. 파일 업로드와 외부 API 연동이다. 둘 다 AI가 잘 될 때만 생각하고 안전장치를 빠뜨리기 쉬운 영역이라, 이번 편은 그 빠진 장치를 우리 손으로 채우는 게 핵심이다. 처음 쓰는 Claude Code 기능은 외부 API를 도구로 잇는 MCP 연결과, 키가 로그에 새지 않게 가리는 시크릿 스크럽 훅이다.

파일 업로드 — 택배를 검사 없이 받지 마라

body-1

사용자가 올리는 파일은 택배와 같다. 검사 없이 받으면 너무 크거나(서버 마비), 이상한 확장자(실행 파일 같은 폭탄)일 수 있다. 그래서 꼭 확인할 세 가지가 있다. 크기 제한, 허용 확장자, 그리고 저장 위치다. 저장은 로컬 개발에선 디스크(또는 MinIO 같은 오브젝트 저장소)에, 운영에선 Supabase Storage에 둔다.

외부 API — 외부 전화는 언젠가 안 받는다

번역이나 결제, 날씨 같은 외부 API는 언젠가 반드시 느려지거나 죽는다. 대비가 없으면 외부 장애가 그대로 우리 서비스 장애가 된다. 그래서 챙길 것이 넷이다. 타임아웃, 재시도, 외부가 죽었을 때도 서비스가 계속 도는 대체 동작(graceful degradation), 그리고 호출 폭주를 막는 비용 방어. 외부 호출을 어떻게 감싸는지 한 장으로 보면 이렇다.

body-2

따라하기 1 — 파일 업로드와 검증

사용자가 문서 파일을 업로드해 오브젝트 저장소(로컬은 디스크/MinIO, 운영은 Supabase Storage)에 저장하는 기능을 붙여 줘.
파일 크기 제한과 허용 확장자 검증(실행 파일 차단), 같은 이름 파일 충돌 처리를 포함해.

큰 파일, 이상한 확장자, 빈 파일을 차례로 올려 본다. "크기 제한이 있나? 확장자를 검증하나? 업로드 실패 시 사용자에게 뭐가 보이나?"

따라하기 2 — 외부 API 연동과 방어

문서 번역 외부 API를 붙여 줘. API 키는 환경 변수로 관리하고, 타임아웃과 재시도,
그리고 외부가 죽었을 때 우리 서비스는 계속 동작하도록 대체 동작을 넣어 줘.

API 키를 일부러 틀리게, 응답을 일부러 느리게 만들어 본다. "키가 코드에 박혔나, 환경 변수에 있나? 타임아웃과 재시도가 있나? 외부가 죽으면 우리도 죽나? 호출 폭주 시 비용 방어는?" 외부 API를 도구로 붙일 땐 Firecrawl(웹 크롤링)이나 Stripe(결제), Composio(여러 SaaS를 한 번에 연결) 같은 플러그인을 마켓플레이스에서 설치해 MCP로 잇는다. 단, 플러그인은 남이 만든 외부 코드이므로 공식 마켓플레이스인지 신뢰 수준을 먼저 확인한다.

따라하기 3 — 시크릿 스크럽 훅

로그와 에러 메시지에 API 키가 절대 안 찍히도록 시크릿을 가리는 훅을 설정해 줘.

일부러 에러를 내도 키가 별표로 가려지는지 확인한다.

따라하기 4 — 함정 (오늘의 시연)

외부 API를 강제로 죽여 본다. 그때 묻는다. "외부 한 곳이 죽었는데 우리 서비스 전체가 멈추지 않나?" 대비가 없으면 번역 API가 점검 중일 때 번역뿐 아니라 서비스 전체가 멈춘다.

외부 실패 시 기능을 일부만 끄고(graceful degradation) 나머지는 계속 돌게 해 줘.

띄워서 확인 — 에이전트가 한 일을 검증한다

업로드와 연동이 "된다"고 안전한 게 아니다. 에이전트는 잘 되는 경우만 짜 두고 검사와 대비를 빼먹기 쉽다. 그러니 정상 입력 말고 망가진 입력을 넣어 본다. 큰 파일과 이상한 확장자를 올리고, 외부 API를 일부러 죽여 서비스 전체가 따라 멈추는지 보고, 에러를 내 키가 로그에 새지 않는지 확인한다.

큰 파일, 이상 확장자, 키 오류, 느린 외부 응답, 네 상황을 각각 만들어
서비스가 어떻게 반응하는지 보여 줘.
  • 업로드에 크기와 확장자 검증이 있는가?
  • 외부 API에 타임아웃과 재시도가 있는가?
  • 외부가 죽어도 서비스 전체는 안 죽는가? (대체 동작)
  • 시크릿이 로그에 안 찍히는가?

한 겹 더 — 비용 방어와 캐시

외부 호출 횟수에 상한을 두고(비용 방어), 같은 입력은 캐시해서 중복 호출을 줄여 줘.

같은 요청이 외부를 다시 부르지 않는지(캐시 활용) 확인한다.

업로드한 문서를 오래 걸려 처리해야 할 때, 사용자를 기다리게 하면 안 된다. 다음 편에서는 백그라운드 작업으로 그 대기를 없애고, 더 많은 사용자를 위한 다국어와 접근성을 다룬다.