Modal Functions (서버리스 함수)

Modal Functions는 고도로 확장 가능한 서버리스 클라우드 컴퓨팅으로 Python 코드를 실행해 주는 핵심 단위예요. 함수를 Modal에서 돌리도록 준비하는 건 정말 간단한데, App을 정의하고 @app.function() 데코레이터로 함수를 등록하면 끝이에요. 이렇게 감싸진 함수는 modal.Function이 되어 로컬 스크립트에서 부르거나, 배포한 뒤 다른 애플리케이션에서 마치 자기 코드인 것처럼 호출할 수 있죠.

출처: https://modal.com/docs/guide/functions

함수를 호출하면 무슨 일이 벌어질까

함수를 호출하면 Modal이 컨테이너 부팅, 입력 라우팅, 예외 전파 같은 모든 운영 작업을 처리해요. 입력이 더 없으면 함수는 자동으로 0개로 스케일 다운되니 계속 들고 있는 비용이 발생하지 않아요. 호출 정보, 로그, 컨테이너 메트릭은 자동으로 캡처되어 여러 관측 표면에서 확인할 수 있죠.

함수 런타임@app.function() 데코레이터의 인자로 구성해요. 컨테이너 환경과 리소스는 모두 Python 코드베이스 안에서 정의되기 때문에 별도 설정 파일이 필요 없어요.

  • 함수는 기본적으로 일정량의 CPU와 메모리를 받아요. 필요하면 이 기준선 위로 순간적으로 버스트(burst)할 수 있고, 무거운 잡은 추가 리소스를 예약해 가용성을 보장할 수 있죠.
  • 함수에는 GPU 하나 이상을 배정할 수 있어요. GPU를 쓰면 CUDA 드라이버가 자동으로 포함돼요.
  • 함수는 임의의 컨테이너 환경(Image) 안에서 실행돼요. PyPI·비공개 저장소의 Python 라이브러리, FFmpeg·OpenCV 같은 바이너리 의존성, 로컬 데이터까지 담을 수 있죠.
  • 모델 가중치 같은 큰 데이터는 Volume이나 CloudBucketMount로 컨테이너에 마운트해요.
  • 환경 변수는 안전한 Secrets로 넘기거나 직접 설정할 수 있어요.

함수 호출 방식

Modal Functions는 호출 방법(invocation methods)으로 부르는데, f.remote()f.spawn()이 대표적이에요. 같은 App 안의 다른 Function이나 로컬 엔트리포인트에서 참조하면 직접 호출할 수 있고, 다른 App이나 Modal 밖에서는 App·Function 이름으로 lookup 후 호출해요. 원격 조회와 호출은 JavaScript·Go SDK로도 가능해서, Python의 AI 생태계를 다른 언어에서도 쓸 수 있어요.

Web Function 데코레이터를 적용하면 함수에 URL이 붙어 어디서든 HTTP로 호출할 수 있어요. Web Function은 기본적으로 인터넷에 열려 있고, 원하면 Proxy Tokens로 인증을 요구하게 만들 수도 있어요. 간단한 Python 함수를 웹 서비스로 노출하기에 좋지만, 고동시성이나 지연에 민감한 앱이라면 Server 원시 요소를 쓰는 게 나아요. 함수는 크론 잡처럼 스케줄로도 자동 호출할 수 있어요.

실행 의미론과 오토스케일링

함수 호출은 Modal 토큰으로 자동 인증되고, RBAC 설정에 따라 권한이 부여돼요. 함수 구현 자체가 접근 제어를 신경 쓸 필요가 없다는 뜻이죠.

Modal이 컨테이너를 스케줄링하고 입력을 라우팅해요. 기본적으로 컨테이너는 전 세계 어디에서나 시작돼서 가용성은 최대화되고 스케줄링 지연은 최소화되죠. 규정 준수 같은 이유로 특정 지역에 제한하려면 compute/routing region을 구성할 수 있는데, 컴퓨트 지역 선택은 가격 승수(pricing multiplier)가 붙고 재고도 제한된다는 점을 기억해 둬요.

컨테이너 스케줄링은 입력 부하에 반응하기 때문에 호출 시점에 컨테이너가 없을 수도 있어요. 입력은 Modal의 I/O 시스템에서 대기열에 쌓였다가 가용한 컨테이너로 분배되죠. 너무 빨리 쌓이면 ResourceExhaustedError로 거부돼요. 배치 워크로드에서는 더 깊은 입력 대기열을 지원하는 내구성 있는 f.spawn()을 쓰는 걸 권장해요.

동시성과 배치

기본적으로 함수 컨테이너는 한 번에 하나의 입력만 처리해요. Modal은 여러 입력을 처리하는 두 가지 패턴을 지원하죠.

  • 입력 동시성(Input concurrency): @modal.concurrent() 데코레이터로 스레드나 asyncio 작업으로 여러 입력을 동시에 실행해요. I/O 바운드 워크로드(네트워크 요청·DB 쿼리)나 연속 배치를 쓰는 GPU 프레임워크에 유용해요.
  • 동적 배치(Dynamic batching): @modal.batched() 데코레이터로 입력 리스트를 받아 출력 리스트를 반환하는 함수를 만드는데, Modal이 배치 크기가 차거나 대기 시간이 지나면 입력을 모아 한 번에 처리해요. torch·numpy 같은 텐서/배열 벡터화를 활용할 때 특히 유용해요.

더 알아보기