๐Ÿš€ AWS CDK์™€ LocalStack์„ ์‚ฌ์šฉํ•œ ์™„์ „ํ•œ API REST ๋งŒ๋“ค๊ธฐ: ์ฒ˜์Œ๋ถ€ํ„ฐ ๋กœ์ปฌ ํ”„๋กœ๋•์…˜๊นŒ์ง€

๋ฐœํ–‰: (2025๋…„ 12์›” 13์ผ ์˜ค์ „ 04:59 GMT+9)
6 min read
์›๋ฌธ: Dev.to

Source: Dev.to

๐Ÿ“‹ ์†Œ๊ฐœ

์ด ์ „์ฒด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” AWS CDK, TypeScript, LocalStack์„ ์‚ฌ์šฉํ•ด ์ฃผ๋ฌธ ๊ด€๋ฆฌ์šฉ ๊ฐ•๋ ฅํ•œ REST API๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. AWS๋ฅผ ์™„๋ฒฝํžˆ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•˜๋Š” ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์„ ์„ค์ •ํ•˜๊ณ , ์ „์ฒด CRUD๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉฐ, ์ฒ ์ €ํžˆ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ณผ์ •์„ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐ŸŽฏ ๋ฌด์—‡์„ ๋งŒ๋“ค ๊ฑด๊ฐ€์š”?

  • 5๊ฐœ์˜ CRUD ์—”๋“œํฌ์ธํŠธ๋ฅผ ๊ฐ–์ถ˜ ์™„์ „ํ•œ REST API
  • ๊ฐ ์ž‘์—…์„ ๋‹ด๋‹นํ•˜๋Š” TypeScript Lambda ํ•จ์ˆ˜
  • ์˜์†์„ฑ์„ ์œ„ํ•œ DynamoDB ํ…Œ์ด๋ธ”
  • ์ง„์ž…์  ์—ญํ• ์„ ํ•˜๋Š” API Gateway
  • ๋น„์šฉ ์—†์ด ๋กœ์ปฌ์—์„œ AWS๋ฅผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•˜๋Š” LocalStack
  • ์ž๋™ํ™” ๋ฐ ์ˆ˜๋™ ํ…Œ์ŠคํŠธ

๐Ÿ› ๏ธ ๊ธฐ์ˆ  ์Šคํƒ

  • AWS CDK v2.170.0 โ€“ ์ธํ”„๋ผ์ŠคํŠธ๋Ÿญ์ฒ˜ ์ฝ”๋“œ(IaC)
  • TypeScript 5.x โ€“ ์ฃผ์š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด
  • Node.js 20+ โ€“ ๋Ÿฐํƒ€์ž„
  • LocalStack โ€“ ๋กœ์ปฌ AWS ์‹œ๋ฎฌ๋ ˆ์ด์…˜
  • DynamoDB โ€“ NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
  • API Gateway โ€“ API ๊ด€๋ฆฌ
  • Lambda โ€“ ์„œ๋ฒ„๋ฆฌ์Šค ํ•จ์ˆ˜

๐Ÿ”ง ์ดˆ๊ธฐ ์„ค์ •

1. VS Code์—์„œ LocalStack ์„ค์น˜

๐Ÿ“ฆ LocalStack ํ™•์žฅ ์„ค์น˜

๋ฐฉ๋ฒ• 1: VS Code Marketplace์—์„œ

  1. VS Code๋ฅผ ์—ฝ๋‹ˆ๋‹ค.
  2. ํ™•์žฅ ํƒญ(Ctrl+Shift+X ๋˜๋Š” Cmd+Shift+X)์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
  3. **โ€œLocalStackโ€**์„ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.
  4. LocalStack ๊ณต์‹ ํ™•์žฅ์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
  5. VS Code๋ฅผ ์žฌ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

๋ฐฉ๋ฒ• 2: ๋ช…๋ น์ค„์—์„œ

code --install-extension localstack.localstack

๋ฐฉ๋ฒ• 3: ์ˆ˜๋™ ์„ค์น˜
VS Code Marketplace - LocalStack ํŽ˜์ด์ง€์— ์ ‘์†ํ•ด โ€œInstallโ€ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

โš™๏ธ ํ™•์žฅ ์„ค์ •

์„ค์ •(Ctrl+, Windows, Cmd+, macOS)์„ ์—ด๊ณ  **โ€œLocalStackโ€**์„ ๊ฒ€์ƒ‰ํ•œ ๋’ค ์•„๋ž˜ ์˜ต์…˜์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค:

{
  "localstack.endpoint": "http://localhost:4566",
  "localstack.profile": "default",
  "localstack.region": "us-east-1",
  "localstack.autoStart": true,
  "localstack.dockerFlags": "-d"
}

๐ŸŽฏ ํ™•์žฅ ๊ธฐ๋Šฅ

  • LocalStack ํŒจ๋„: ์„œ๋น„์Šค ์ƒํƒœ, ์‹ค์‹œ๊ฐ„ ๋กœ๊ทธ, ์„œ๋น„์Šค ๊ด€๋ฆฌ, ๋ฆฌ์†Œ์Šค ํƒ์ƒ‰๊ธฐ.
  • ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ช…๋ น (๋ช…๋ น ํŒ”๋ ˆํŠธ Ctrl+Shift+P):
    • LocalStack: Start โ€“ LocalStack ์‹œ์ž‘
    • LocalStack: Stop โ€“ LocalStack ์ค‘์ง€
    • LocalStack: Restart โ€“ LocalStack ์žฌ์‹œ์ž‘
    • LocalStack: Show Logs โ€“ ๋กœ๊ทธ ๋ณด๊ธฐ
    • LocalStack: Open Web UI โ€“ ์›น UI ์—ด๊ธฐ
  • AWS CLI์™€ ํ†ตํ•ฉ: ์—”๋“œํฌ์ธํŠธ ์ž๋™ ์„ค์ •, ๋กœ์ปฌ ํ”„๋กœํŒŒ์ผ, AWS ๋ช…๋ น์„ LocalStack์œผ๋กœ ๋ผ์šฐํŒ….

๐Ÿ” ํ™•์žฅ ์„ค์น˜ ํ™•์ธ

  • ์‚ฌ์ด๋“œ ํŒจ๋„: ์‚ฌ์ด๋“œ๋ฐ”์— LocalStack ์•„์ด์ฝ˜์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
  • ๋ช…๋ น ํŒ”๋ ˆํŠธ: Ctrl+Shift+P โ†’ โ€œLocalStackโ€ ๊ฒ€์ƒ‰.
  • ์ƒํƒœ ํ‘œ์‹œ์ค„: ํ•˜๋‹จ์— ์ƒํƒœ ํ‘œ์‹œ๊ธฐ๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

๐Ÿš€ ์ฒซ ์‚ฌ์šฉ

  1. LocalStack ํŒจ๋„์„ ์—ฝ๋‹ˆ๋‹ค(์•„์ด์ฝ˜ ํด๋ฆญ).
  2. Start LocalStack ๋ฒ„ํŠผ์ด๋‚˜ ๋ช…๋ น์„ ์‚ฌ์šฉํ•ด LocalStack์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
  3. ํŒจ๋„์— Running์ด ํ‘œ์‹œ๋˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  4. Logs ํƒญ์—์„œ ๋กœ๊ทธ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

2. CDK ํ”„๋กœ์ ํŠธ๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋งŒ๋“ค๊ธฐ

๐Ÿ“‹ ์‚ฌ์ „ ์š”๊ตฌ์‚ฌํ•ญ

๋‹ค์Œ์ด ์„ค์น˜๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค:

# Node.js (๋ฒ„์ „ 20 ์ด์ƒ)
node --version

# npm
npm --version

# AWS CDK CLI (์ „์—ญ)
npm install -g aws-cdk

# CDK ์„ค์น˜ ํ™•์ธ
cdk --version

๐Ÿ—๏ธ CDK ํ”„๋กœ์ ํŠธ ์ดˆ๊ธฐํ™”

# ํ”„๋กœ์ ํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ ์ƒ์„ฑ
mkdir cdk-api-localstask
cd cdk-api-localstask

# TypeScript๋กœ CDK ํ”„๋กœ์ ํŠธ ์ดˆ๊ธฐํ™”
cdk init app --language typescript

์ดˆ๊ธฐ ๊ตฌ์กฐ ํ™•์ธ

ls -la
# ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŒŒ์ผ/๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ๋ณด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค:
# bin/           # ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ง„์ž…์ 
# lib/           # ์Šคํƒ ์ •์˜
# test/          # ๋‹จ์œ„ ํ…Œ์ŠคํŠธ
# package.json   # ํ”„๋กœ์ ํŠธ ์˜์กด์„ฑ
# tsconfig.json  # TypeScript ์„ค์ •
# cdk.json       # CDK ์„ค์ •

์ถ”๊ฐ€ ์˜์กด์„ฑ ์„ค์น˜

# LocalStack ๊ด€๋ จ ์˜์กด์„ฑ
npm install aws-cdk-local

# Lambda์™€ DynamoDB์šฉ ์˜์กด์„ฑ
npm install @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodb

# TypeScript์šฉ ์˜์กด์„ฑ
npm install @types/aws-lambda @types/uuid uuid

# ๊ฐœ๋ฐœ์šฉ ์˜์กด์„ฑ
npm install --save-dev @types/node typescript

โš™๏ธ LocalStack ์Šคํฌ๋ฆฝํŠธ ์„ค์ •

package.json์„ ์—ด์–ด ๋‹ค์Œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค:

{
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "test": "jest",
    "synth": "cdk synth",
    "deploy": "cdk deploy",
    "local:synth": "npx cdklocal synth",
    "local:deploy": "npx cdklocal deploy",
    "local:destroy": "npx cdklocal destroy",
    "local:diff": "npx cdklocal diff",
    "local:bootstrap": "npx cdklocal bootstrap"
  }
}

๐Ÿ”ง CDK๋ฅผ LocalStack์— ๋งž๊ฒŒ ์„ค์ •

cdk.json (CDK ์„ค์ • ํŒŒ์ผ):

{
  "app": "npx ts-node --prefer-ts-exts bin/app.ts",
  "watch": {
    "include": ["**"],
    "exclude": [
      "README.md",
      "cdk*.json",
      "**/*.d.ts",
      "**/*.js",
      "tsconfig.json",
      "package*.json",
      "yarn.lock",
      "node_modules",
      "test"
    ]
  },
  "context": {
    "@aws-cdk/aws-lambda:recognizeLayerVersion": true,
    "@aws-cdk/core:checkSecretUsage": true,
    "@aws-cdk/core:target-partitions": ["aws", "aws-cn"],
    "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
    "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
    "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
    "@aws-cdk/core:validateSnapshotRemovalPolicy": true,
    "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
    "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
    "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
    "@aws-cdk/aws-apigateway:disableCloudWatchRole": false,
    "@aws-cdk/core:enablePartitionLiterals": true,
    "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
    "@aws-cdk/aws-iam:minimizePolicies": true,
    "@aws-cdk/core:disableStackTrace": false
  }
}

๐Ÿ“ ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ตฌ์กฐ ๋งŒ๋“ค๊ธฐ

# ์ฝ”๋“œ ์ •๋ฆฌ๋ฅผ ์œ„ํ•œ ๋””๋ ‰ํ„ฐ๋ฆฌ ์ƒ์„ฑ
mkdir -p lib/lambdas
mkdir -p lib/types

# ๊ธฐ๋ณธ ํŒŒ์ผ ์ƒ์„ฑ
touch lib/types/order.ts
touch lib/lambdas/create-order.ts
touch lib/lambdas/get-order.ts
touch lib/lambdas/list-orders.ts
touch lib/lambdas/update-order.ts
touch lib/lambdas/delete-order.ts

๐ŸŽฏ ๋ฉ”์ธ ์Šคํƒ ์„ค์ •

bin/app.ts (์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ง„์ž…์ ):

#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { CdkApiLocalstackStack } from '../lib/cdk-api-localstask-stack';

const app = new cdk.App();
new CdkApiLocalstackStack(app, 'CdkApiLocalstackStack', {
  env: {
    account: process.env.CDK_DEFAULT_ACCOUNT || '000000000000', // LocalStack ๊ธฐ๋ณธ๊ฐ’
    region: process.env.CDK_DEFAULT_REGION || 'us-east-1',
  },
});
Back to Blog

๊ด€๋ จ ๊ธ€

๋” ๋ณด๊ธฐ ยป

๋ฐ”์ด๋ธŒ ์ฝ”๋”ฉ ํŒจ๋Ÿฌ๋…์Šค

๋‚ด๊ฐ€ Nudges์— ๋ณด๋‚ธ ๋งˆ์ง€๋ง‰ PR์€ +96 โˆ’312์˜€๊ณ , 38๊ฐœ์˜ ํŒŒ์ผ์„ ๊ฑด๋“œ๋ ธ์œผ๋ฉฐ, ์•ฝ 90 %๊ฐ€ vibeโ€‘coded์˜€๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์— ์ž์‹  ์žˆ๋‹ค. ๋‚ด๊ฐ€ Hyrule์„ ํ™œ๊ณตํ•˜๊ณ  ์žˆ์„ ๋•Œ, ๋‘ ๊ฐœ์˜ ๋‹ค๋ฅธ AIโ€ฆ

Rust/WASM์œผ๋กœ ์„œ๋ธŒ๋ฐ€๋ฆฌ์ดˆ ๋ฒกํ„ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ตฌ์ถ•

EdgeVec๋Š” WebAssembly๋ฅผ ์‚ฌ์šฉํ•ด ๋ธŒ๋ผ์šฐ์ €์—์„œ ์™„์ „ํžˆ ์‹คํ–‰๋˜๋Š” ๊ณ ์„ฑ๋Šฅ ๋ฒกํ„ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ž…๋‹ˆ๋‹ค. ์„œ๋ธŒ๋ฐ€๋ฆฌ์ดˆ ์ˆ˜์ค€์˜ ๊ฒ€์ƒ‰ ์‹œ๊ฐ„์„ ๋‹ฌ์„ฑํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธโ€‘์‚ฌ์ด๋“œโ€ฆ

์ธ์‡„ ๊ฐ€๋Šฅํ•œ ํ”Œ๋ž˜์‹œ์นด๋“œ ์ƒ์„ฑ๊ธฐ

์†Œ๊ฐœ ์‹œ๊ฐ ํ•™์Šต์ž์ด์‹ ๊ฐ€์š”? ์ด๋ฏธ์ง€ ๊ธฐ๋ฐ˜ ํ”Œ๋ž˜์‹œ์นด๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ์–ด๋‚˜ ๊ฐœ๋…์„ ๋” ํšจ๊ณผ์ ์œผ๋กœ ์•”๊ธฐํ•œ ์ ์ด ์žˆ๋‚˜์š”? ๊ทธ๋ ‡๋‹ค๋ฉด, ์ด ํ”„๋กœ...

Cursor + MCP's | Docker | Strapi v5 | Next JS | Render

Overview ๐Ÿš€ ์˜ค๋Š˜ ๋‚˜์˜ ์ž„๋ฌด๋Š” ํฌํŠธํด๋ฆฌ์˜ค ์›น์‚ฌ์ดํŠธ์˜ ์ฝ˜ํ…์ธ ๋ฅผ ๊ตฌ๋™ํ•  Strapi CMS๋ฅผ ๋ฐฐํฌํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€์žฅ ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์ธโ€ฆ