서버리스란?
서버리스를 한 마디로 표현하면 "서버는 있는데, 개발자가 신경 안 써도 되는 구조" 다.
"서버가 없다"는 게 아니라, 클라우드 제공업체가 서버 인프라를 대신 관리해주는 모델이다.
개발자는 그냥 코드(함수)만 작성하면 된다.
동작 방식을 간단하게 보면 이렇다.
1. 개발자가 함수(Function) 형태로 코드를 작성해서 클라우드에 올린다.
2. 특정 이벤트(HTTP 요청, DB 변경, 파일 업로드 등)가 발생하면 함수가 자동으로 트리거된다.
3. 클라우드가 필요한 컴퓨팅 리소스를 동적으로 할당해서 함수를 실행한다.
4. 실행이 끝나면 리소스를 해제하고, 사용한 만큼만 비용이 청구된다.
EC2 같은 VM 방식과 비교하면 차이가 명확하다.
구분 기존 VM 방식 서버리스
| 서버 관리 | 개발자가 직접 | 클라우드가 알아서 |
| 비용 | 서버 켜놓은 시간만큼 | 실제 실행된 시간만큼 |
| 스케일링 | 수동 또는 별도 설정 | 자동 |
| 배포 단위 | 애플리케이션 전체 | 함수 단위 |
서버리스 아키텍처의 주요 구성 요소
함수 (Functions)
서버리스의 핵심 단위다. 특정 작업을 수행하는 작은 코드 조각이다.
Spring Boot로 치면 하나의 Controller 메서드 수준이라고 생각하면 이해하기 쉽다.
이벤트 소스 (Event Sources)
함수를 실행시키는 트리거다. 대표적인 이벤트 소스는 다음과 같다.
- HTTP 요청 — API 호출
- 데이터베이스 변경 — DB에 새 데이터 삽입/수정
- 파일 업로드 — Storage에 파일이 올라옴
- 타이머 — 정해진 시간에 주기적으로 실행
- 메시지 큐 — 큐에 메시지가 들어오면 실행
서비스형 백엔드 (BaaS)
데이터베이스, 인증, 파일 스토리지 같은 백엔드 기능을 API 형태로 제공하는 것이다.
직접 DB 서버를 운영하는 대신, 클라우드에서 제공하는 관리형 서비스를 API로 연결해서 쓰는 방식이다.
API 게이트웨이
클라이언트 요청을 적절한 함수로 라우팅하고 관리하는 역할을 한다.
Spring의 Gateway나 Nginx 역할을 클라우드가 대신 해주는 것이다.
서버리스의 장단점
장점
- 비용 효율성
실제로 함수가 실행된 시간만큼만 돈을 낸다. 트래픽이 없으면 비용도 없다. - 자동 스케일링
트래픽이 갑자기 몰려도 클라우드가 알아서 리소스를 늘려준다. - 유지보수 간소화
서버 패치, OS 업데이트, 서버 모니터링 같은 인프라 작업을 클라우드가 처리해준다.
개발자는 비즈니스 로직에만 집중할 수 있다. - 빠른 개발 및 배포
인프라 세팅 없이 함수만 작성하면 바로 배포 가능하다.
단점
- 콜드 스타트 (Cold Start)
함수가 처음 실행될 때 컨테이너를 새로 띄워야 해서 지연이 발생한다.
간헐적으로 호출되는 함수는 응답 속도가 들쭉날쭉할 수 있다. - 벤더 종속성
AWS Lambda에서 작성한 코드를 Azure Functions로 옮기려면 수정이 필요하다.
특정 클라우드에 종속되는 문제가 있다. - 장기 실행 작업에 부적합
대부분의 서버리스 플랫폼은 함수 실행 시간에 제한이 있다.
오래 걸리는 작업에는 적합하지 않다. - 디버깅과 모니터링의 어려움
함수가 분산되어 있고 실행 환경이 일시적이라 로그 추적이 복잡하다.
주요 서버리스 서비스 제공업체
제공업체 서비스명 특징
| AWS | Lambda | S3, DynamoDB 등 AWS 생태계와 통합이 용이 |
| Microsoft Azure | Azure Functions | Azure 생태계 통합, 다양한 호스팅 옵션 제공 |
| Google Cloud | Cloud Functions | GCS, Pub/Sub 등 GCP 서비스와 연동 |
Azure Functions 깊게 살펴보기
Azure Functions는 Microsoft Azure의 서버리스 컴퓨팅 플랫폼이다.
인프라 관리 없이 이벤트 기반 애플리케이션을 구축할 수 있게 해주는 서비스다.
주요 호스팅 옵션
Azure Functions는 어떤 플랜에서 실행하느냐에 따라 특성이 달라진다.
플랜 특징
| Consumption Plan | 실행 시간에만 비용 발생, 자동 확장 지원, 기본 서버리스 방식 |
| Premium Plan | 콜드 스타트 없음, 강력한 리소스, 가상 네트워크 지원 |
| App Service Plan | App Service 리소스 공유, 항상 활성 상태 유지 가능 |
| Flex Consumption Plan | 사전 인스턴스 프로비전 + 빠른 확장, 비용 효율적 |
콜드 스타트가 치명적인 서비스라면 Premium Plan을 선택하고, 비용을 최소화하고 싶다면 Consumption Plan이 기본 선택지다.
SLA
Azure Functions는 99.95% 의 SLA(Service Level Agreement)를 보장한다.
SLA는 서비스 제공자와 고객 간에 가용성, 성능 목표 등을 명시한 계약이다.
99.95%라는 건 한 달 기준으로 약 21.6분의 다운타임만 허용된다는 의미다.
Azure Functions의 트리거와 바인딩
트리거 (Trigger)
함수를 실행시키는 이벤트다. 함수 하나당 트리거는 딱 하나만 지정할 수 있다.
- HTTP 트리거 : API 요청이 들어올 때 실행
- Timer 트리거 : 정해진 시간 간격으로 실행 (Cron 표현식 사용)
- Blob 트리거 : Storage에 파일이 업로드될 때 실행
- Queue 트리거 : 큐에 메시지가 들어올 때 실행
- Event Hub 트리거 : 이벤트 스트림이 발생할 때 실행
- Service Bus 트리거 : Service Bus 큐/토픽 메시지 발생 시 실행
바인딩 (Binding)
함수와 외부 리소스를 연결하는 방법이다. 트리거와 달리 여러 개를 붙일 수 있다.
- 입력 바인딩 (Input Binding) — 함수 실행 시 외부에서 데이터를 가져온다.
예: Azure SQL에서 데이터를 읽어와서 함수 파라미터로 전달 - 출력 바인딩 (Output Binding) — 함수 실행 결과를 외부로 내보낸다.
예: 함수 반환값을 Azure SQL에 자동으로 저장
코드에서 직접 SDK를 호출하지 않아도, 바인딩 설정만으로 외부 서비스와 연결할 수 있다는 게 핵심이다.
실습: Blob Storage 위협 파일 감지 및 삭제
서버리스가 어디에 유용한지 직접 보여주는 예시다.
시나리오
1. Blob Storage에 파일이 업로드된다.
2. Blob 트리거가 발생해 Azure Function이 실행된다.
3. 파일 확장자를 분석해 위협 파일이면 자동으로 삭제한다.
위협 파일로 분류되는 대표적인 확장자들은 다음과 같다.
DANGEROUS_EXTENSIONS = [
# 실행 파일
'.exe', '.bat', '.cmd', '.com', '.msi', '.vbs', '.ps1',
# 스크립트
'.js', '.jse', '.sh', '.py',
# 매크로 포함 Office 파일
'.docm', '.xlsm', '.pptm',
# 기타
'.scr', '.dll', '.lnk', '.reg'
]
이중 확장자(.pdf.exe 같은 것)나 위장된 확장자도 체크해야 한다.
Blob 트리거로 구현하면 이런 구조가 된다
import azure.functions as func
app = func.FunctionApp()
@app.blob_trigger(arg_name="myblob", path="uploads/{name}",
connection="AzureWebJobsStorage")
def blob_trigger(myblob: func.InputStream):
file_name = myblob.name
extension = file_name.split('.')[-1].lower()
if f".{extension}" in DANGEROUS_EXTENSIONS:
# 파일 삭제 로직
delete_blob(file_name)
logging.warning(f"위협 파일 감지 및 삭제: {file_name}")
else:
logging.info(f"정상 파일: {file_name}")
기존 방식이었다면 서버를 항상 켜놓고 Storage를 폴링해야 했는데,
서버리스로 구현하면 파일이 올라올 때만 함수가 실행된다. 비용도 줄고 코드도 훨씬 간결하다.
실습: HTTP Trigger로 번역 API 만들기
Azure Translator API를 연결해서 간단한 번역 서비스를 만들어봤다.
시나리오
1. 클라이언트에서 한국어 텍스트를 HTTP POST로 보낸다.
2. Azure Function이 요청을 받아 Azure Translator API를 호출한다.
3. 번역된 결과를 응답으로 돌려준다.
@app.route(route="translate", methods=["POST"])
def translate(req: func.HttpRequest) -> func.HttpResponse:
body = req.get_json()
text = body.get("text")
# Azure Translator API 호출
result = call_translator_api(text, target_language="en")
return func.HttpResponse(
json.dumps({"translated": result}),
mimetype="application/json"
)
로컬에서 테스트할 때는 이렇게 호출한다.
curl -X POST "http://localhost:7071/api/translate" \
-H "Content-Type: application/json" \
-d '{"text": "안녕하세요"}'
이 함수를 클라우드에 배포하면 다른 웹이나 앱에서도 호출해서 사용할 수 있는 백엔드 역할을 한다.
Streamlit 같은 프론트엔드와 연결하면 간단한 번역 웹앱도 뚝딱 만들 수 있다.
Azure Functions 개발 환경
로컬에서 개발하는 방법은 크게 두 가지다.
Azure Portal에서 직접 개발
브라우저에서 코드를 작성하고 바로 테스트할 수 있다.
빠르게 확인하기엔 편하지만, 사용할 수 있는 기능에 제약이 있다.
Visual Studio Code + Azure Functions Extension
로컬에서 개발하고 디버깅까지 가능하다.
Azure Functions Core Tools를 함께 설치하면 로컬 환경에서 실제 클라우드와 거의 동일하게 테스트할 수 있다.
다양한 기능을 모두 사용하려면 이 방법을 권장한다.
서버리스 서비스들을 레고처럼 조합하면?
서버리스의 진가는 여러 서비스를 조합했을 때 나온다.
예를 들어 차량 번호판 인식 시스템을 서버리스로 구현하면 이런 구조가 된다.
차량 사진 업로드
→ Azure Storage Blobs (사진 저장)
→ Azure Event Grid (이벤트 발생)
→ Azure Functions (사진 처리, Computer Vision API 호출)
→ Cosmos DB (번호판 데이터 저장)
→ Logic Apps (CSV 내보내기 + 이메일 알림)
→ Power BI (데이터 시각화)
각 서비스가 레고 블록처럼 역할을 나눠 담당하고, 이벤트로 연결된다.
서버를 직접 운영하지 않아도 이런 복잡한 파이프라인을 구성할 수 있다는 게 서버리스의 강점이다.
정리
서버리스는 "서버 관리를 클라우드에게 맡기고, 코드에만 집중하는 방식" 이다.
- 비용 효율적이고, 자동 스케일링이 되며, 인프라 관리 부담이 없다.
- 콜드 스타트, 벤더 종속성, 장기 실행 작업의 한계는 여전히 존재한다.
- Azure Functions는 Trigger와 Binding 개념으로 외부 서비스와 쉽게 연결된다.
- 여러 서버리스 서비스를 레고처럼 조합하면 강력한 아키텍처를 낮은 운영 비용으로 구성할 수 있다.
서버리스가 모든 상황의 정답은 아니지만, 이벤트 기반 처리나 간헐적 워크로드에서는 확실히 강점을 발휘한다.
특성을 제대로 이해하고 적재적소에 활용하는 게 핵심이다.
'Cloud > 클라우드 응용 SW 개발' 카테고리의 다른 글
| [클라우드 응용 SW 개발] 13, 14주차 (1) | 2026.06.15 |
|---|---|
| [클라우드 응용 SW 개발] 11, 12주차 (0) | 2026.06.15 |
| [클라우드 응용 SW 개발] 6,7주차 (0) | 2026.05.10 |
| [클라우드 응용 SW 개발] 4,5주차 (0) | 2026.04.02 |
| [클라우드 응용 SW 개발] 2,3주차 (0) | 2026.03.22 |