
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
slsberry는 AWS Lambda 기반의 Serverless 개발을 효율적으로 도와주는 프레임워크입니다. 소스 코드 내의 파일에 정의된 스펙 문서를 기반으로 자동으로 Serverless Framework yml파일 내에 Lambda 함수를 생성해주고 OpenAPI 3.0, Notion 등으로 문서화도 수행합니다.
npm install slsberry
또는
yarn add slsberry
slsberry build
serverless deploy --aws-profile [awsprofile 이름]
# OpenAPI 문서 생성
slsberry --openapi
# Notion 문서 생성
slsberry -n {notion_api_key}
공통 리소스(기본 설정, IAM 역할, CloudFormation 기반 리소스 등)를 정의한 템플릿 파일을 기반으로 apiSpec이 정의된 함수가 포함된 새로운 serverless.yml 파일을 생성해줍니다.
Lambda 함수를 제외한 나머지 내용을 정의하는 템플릿 파일입니다. 기본 이름은 serverless_template.yml입니다. -t 플래그로 템플릿 파일을 지정할 수 있습니다.
slsberry -t serverless_template.yml
이 템플릿에서 정의되어 있는 app 이름이 함수명에 포함됩니다.
Serverless.yml 및 함수명 등에서 사용하는 stage와 각 스테이지별 버전을 지정할 수 있습니다.
slsberry --stage test --ver 1
최상위 디렉토리에 .env 파일에 STAGE와 VER을 설정하면 해당 스테이지와 버전에 맞게 serverless.yml 파일을 생성합니다.
# .env 파일
STAGE=test
VER=3
이 경우 스테이지와 버전을 명시할 필요가 없습니다.
slsberry # 위와 같은 .env가 정의되어 있을 경우 slsberry --stage test --ver 3과 같음
./src/lambda (또는 TypeScript 프로젝트의 경우 ./trc/lambda) 경로 안에 정의된 함수들을 대상으로 합니다. REST 타입의 (HTTP로 트리거되는) Lambda 함수의 경우 경로가 곧 API Path가 됩니다.
예시: ./src/lambda/user/data/get.js 또는 ./trc/lambda/user/data/get.ts라면, API 경로는 다음과 같습니다:
https://{api_gateway_id}.execute-api.{region}.amazonaws.com/{stage}/user/data/get (Method: GET)
TypeScript 프로젝트의 경우:
trc/ 디렉토리에 TypeScript 소스 코드를 작성npx tsc 명령으로 src/ 디렉토리로 컴파일slsberry 명령으로 serverless.yml 생성# TypeScript 빌드 및 배포 예시
npx tsc && npx slsberry && npx sls deploy
각 Lambda 함수에 다음 형식으로 apiSpec을 선언하여 export 합니다.
JavaScript:
const apiSpec = {
"category": "test",
"desc": "테스트 함수",
"event": [
// 이벤트 설정
]
};
exports.apiSpec = apiSpec;
exports.handler = async (event, context) => {
// 함수 구현
};
TypeScript:
export const apiSpec = {
category: "User",
event: [
{
type: "REST",
method: "GET",
authorizer: "AppAuthorizer",
},
],
summary: "Get user information",
desc: "사용자 정보를 조회합니다",
requestQuery: querySchemaToParameters(querySchema),
errors: {},
responses: {
200: {
description: "User retrieved successfully",
content: { "application/json": { schema: responseSchema } },
},
400: { $ref: "#/components/responses/Validation" },
401: { $ref: "#/components/responses/Unauthorized" },
500: { $ref: "#/components/responses/InternalServerError" },
},
};
export async function lambdaHandler(
event: FromSchema<typeof eventSchema> & { v3TestProfile: AwsCredentialIdentityProvider },
context: ApiKeyVerifiedContext,
): Promise<APIGatewayProxyResult> {
// 함수 구현
}
export const handler = middy()
.use(authGuard())
.use(userFriendlyValidator({ eventSchema }))
.handler(lambdaHandler);
함수의 카테고리입니다. 문서화 및 분류를 위해 사용합니다.
OpenAPI 문서 생성 시 사용되는 API의 간단한 요약입니다.
export const apiSpec = {
summary: "Get user information",
// ...
};
true로 설정할 경우 OpenAPI 문서에서 제외됩니다.
export const apiSpec = {
hide: true,
// ...
};
REST API의 쿼리 파라미터를 정의합니다. querySchemaToParameters 유틸리티 함수를 사용하여 JSON Schema로부터 자동 생성할 수 있습니다.
export const apiSpec = {
requestQuery: querySchemaToParameters(querySchema),
// ...
};
REST API의 요청 본문을 정의합니다.
export const apiSpec = {
requestBody: {
required: true,
content: { "application/json": { schema: bodySchema } },
},
// ...
};
API의 응답을 정의합니다. OpenAPI 3.0 스펙에 따라 구성됩니다.
export const apiSpec = {
responses: {
200: {
description: "Success",
content: { "application/json": { schema: responseSchema } },
},
400: { $ref: "#/components/responses/Validation" },
401: { $ref: "#/components/responses/Unauthorized" },
500: { $ref: "#/components/responses/InternalServerError" },
},
// ...
};
Lambda 함수의 메모리 크기를 지정합니다 (MB 단위).
export const apiSpec = {
memorySize: 512,
// ...
};
Lambda 함수의 타임아웃을 지정합니다 (초 단위).
export const apiSpec = {
timeout: 30,
// ...
};
true로 설정할 경우 배포하지 않습니다.(serverless.yml에 포함되지 않습니다.)
const apiSpec = {
"category": "test",
"desc": "테스트 함수",
"disabled": true,
"event": []
};
각 함수의 트리거 이벤트를 설정할 수 있습니다. 현재 사용 가능한 트리거는 다음과 같습니다.
const apiSpec = {
"category": "test",
"event": [{
"type": "REST",
"method": "GET",
"authorizer": "AppAuthorizer" // 선택사항
}]
...
};
const apiSpec = {
"category": "websocket",
"event": [{
"type": "websocket",
"route": "$connect"
}]
...
};
$connect: 연결 시$disconnect: 연결 해제 시$default: 기본 라우트const apiSpec = {
"category": "test",
"event": [
{
"type": "s3",
"existing": true,
"bucket": `my-test-bucket`,
"event": "s3:ObjectCreated:put"
},
{
"type": "s3",
"existing": false,
"bucket": `\${ssm:/\${self:app}/\${opt:stage, "dev"}/filebucket}`,
"event": "s3:ObjectCreated:post"
}
],
...
};
(Serverless Framework s3 Event 참고)
const apiSpec = {
"category": "sqs",
"event": [
{
"type": "sqs",
"sqsARN": `arn:aws:sqs:ap-northeast-2:207637378596:test-queue-1`,
},
{
"type": "sqs",
"sqs": `MySQSQueue`,
"batchSize": 9,
"maximumBatchingWindow": 1,
}
]
...
}
(Serverless Framework SQS Event 참고)
const apiSpec = {
"category": "cognito",
"event": [
{
"type": "cognito",
"pool": "MyUserPool",
"trigger": "PreSignUp"
}
]
...
}
(Serverless Framework Cognito Event 참고)
const apiSpec = {
"category": "stepfunctions",
"event": [
{
"type": "sfn"
}
]
...
}
Step Functions에서 호출되는 Lambda 함수입니다. 별도의 이벤트 설정이 필요하지 않습니다.
const apiSpec = {
"category": "iot",
"event": [
{
"type": "iot",
"sql": "SELECT * FROM 'topic/+/data'"
}
]
...
}
(Serverless Framework IoT Event 참고)
const apiSpec = {
"category": "test",
"event": [
{
"type": "pure",
}
]
...
}
다른 트리거 혹은 Cron Job 등에서 사용되어 별도의 Trigger가 필요 없는 함수입니다. 주로 다른 Lambda 함수에서 직접 호출되거나 Step Functions에서 사용됩니다.
Lambda 함수의 이름을 정의합니다.
const apiSpec = {
"category": "test",
"event": [
{
"type": "pure",
}
],
"functionName":"my_test_function"
...
}
Default 값은
${self:service}_${stage}_${version}_{lambda 경로}
입니다.
예: ./src/lambda/user/data/get.js 라면, 함수명은
${self:service}_${stage}_${version}_user_data_get
입니다.
slsberry는 다양한 CLI 옵션을 제공합니다:
# 기본 빌드 (현재 디렉토리의 .env 파일 또는 기본값 사용)
slsberry
# 또는
slsberry build
# 스테이지와 버전 지정
slsberry --stage production --ver 2
# 템플릿 파일 지정
slsberry -t custom_template.yml
# 운영체제 타입 지정 (Windows에서 실행 시)
slsberry -os windows
# OpenAPI 문서 생성
slsberry --openapi
# Notion 문서 생성
slsberry -n {notion_api_key}
# 도움말 보기
slsberry --help
.env 파일에서 다음 환경 변수를 설정할 수 있습니다:
STAGE=development
VER=1
TEMPLATE=serverless_template.yml
# 1. TypeScript 컴파일 (TypeScript 프로젝트인 경우)
npx tsc
# 2. serverless.yml 생성
npx slsberry
# 3. 로컬 테스트 (serverless-offline 사용시)
npx sls offline
# 4. 배포
npx sls deploy --aws-profile [profile-name]
{
"scripts": {
"build": "npx slsberry",
"build:windows": "rimraf src/lambda/* && npx tsc && npx slsberry -os windows",
"deploy": "rimraf src/lambda/* && npx tsc && npx slsberry -os windows && npx sls deploy --verbose",
"doc": "npx tsc && npx slsberry"
}
}
apiSpec을 기반으로 최상위 info.yml에 정의된 정보로 notion 혹은 OpenAPI에 export 할 수 있는 api 문서를 생성합니다.
프로젝트의 정보를 담습니다.
title: demo-slsberry
description: demo project
version: 0.0.1
contact:
name: spark
email: spark@rubywave.io
url: rubywave.io
host: https://rubywave.io
database_id: 4803f792302e4c7bbd2124a55b117465
slsberry -n {notion_api_key}
notion_api_key의 경우 링크 를 참고해주세요. info.yml에 database_id가 정의되어 있어야 합니다. notion database_id의 경우 Stack Overflow 를 참고해주세요.
Notion 데이터베이스는 경우 Name Description Stage(Select) Version 컬럼이 있어야 합니다.

slsberry --openapi
REST API 이벤트가 포함된 함수들을 기반으로 OpenAPI 3.0 스펙의 JSON 파일을 생성합니다. 생성된 파일은 Swagger UI나 다른 OpenAPI 도구에서 사용할 수 있습니다.
TypeScript 프로젝트에서 slsberry를 사용할 때의 권장 구조:
project/
├── trc/ # TypeScript 소스 코드
│ └── lambda/
│ ├── user/
│ │ ├── get.ts
│ │ └── put.ts
│ └── auth/
│ └── authorizer.ts
├── src/ # 컴파일된 JavaScript (자동 생성)
├── serverless_template.yml
├── tsconfig.json
├── package.json
└── .env
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "node",
"outDir": "./src",
"rootDir": "./trc",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true
},
"include": ["trc/**/*.ts"],
"exclude": ["**/*.test.ts"]
}
middy와 함께 사용하는 현대적인 패턴을 권장합니다.
import middy from "@middy/core";
import { ioLogger } from "../libs/middlewares/io-logger.js";
import { globalErrorHandler } from "../libs/middlewares/global-error-handler.js";
import { userFriendlyValidator } from "../libs/middlewares/user-friendly.validator.js";
import { authGuard } from "../libs/middlewares/auth.guard.js";
export const apiSpec = {
category: "User",
event: [{ type: "REST", method: "GET", authorizer: "AppAuthorizer" }],
summary: "Get user information",
// ...
};
export async function lambdaHandler(event, context) {
// 비즈니스 로직
}
export const handler = middy()
.use(ioLogger())
.use(globalErrorHandler({
name: apiSpec.summary,
path: process.env.PATH,
fallbackMessage: JSON.stringify({
message: "Internal Server Error",
code: "internal_server_error",
}),
}))
.use(authGuard())
.use(userFriendlyValidator({ eventSchema }))
.handler(lambdaHandler);
JSON Schema to TypeScript를 활용한 타입 안전한 개발:
import { FromSchema } from "json-schema-to-ts";
const querySchema = {
type: "object",
properties: {
userId: { type: "string" },
limit: { type: "number", minimum: 1, maximum: 100 }
},
required: ["userId"],
additionalProperties: false,
} as const;
const eventSchema = {
type: "object",
properties: {
queryStringParameters: querySchema,
},
required: ["queryStringParameters"],
} as const;
export async function lambdaHandler(
event: FromSchema<typeof eventSchema> & { v3TestProfile: AwsCredentialIdentityProvider },
context: ApiKeyVerifiedContext,
): Promise<APIGatewayProxyResult> {
// event.queryStringParameters는 타입 안전함
const { userId, limit } = event.queryStringParameters;
// ...
}
export const apiSpec = {
// ...
memorySize: 512, // MB
timeout: 30, // seconds
};
export const apiSpec = {
category: "Queue",
event: [{
type: "sqs",
sqs: "UserProcessingQueue",
batchSize: 10, // 최대 배치 크기
maximumBatchingWindow: 5, // 배치 수집 대기 시간(초)
}],
memorySize: 1024, // 배치 처리를 위한 높은 메모리
};
함수에서 hide: true를 사용하여 내부 함수를 OpenAPI 문서에서 제외:
export const apiSpec = {
hide: true, // OpenAPI 문서에서 제외
category: "Internal",
event: [{ type: "pure" }],
desc: "내부 유틸리티 함수",
};
Windows 환경에서는 -os windows 플래그를 사용하세요:
npx slsberry -os windows
tsconfig.json에서 outDir이 ./src로 설정되어 있는지 확인rootDir이 ./trc로 설정되어 있는지 확인rimraf src/lambda/*serverless_template.yml 파일이 루트 디렉토리에 있는지 확인src/lambda/ 또는 trc/lambda/ 경로에 있는지 확인disabled: true로 설정되어 있지 않은지 확인현재 버전: ^0.0.69
주요 기능:
FAQs
A CLI tool to generate serverless.yml
We found that slsberry demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.