๐ ALPACO ์ปค๋ฎค๋ํฐ API: ๊ธฐ๋ฅ ๋ฐ ๊ธฐ์ ๊ฐ์ด๋
1. ๊ฐ์
ALPACO ์ปค๋ฎค๋ํฐ API๋ ๊ฒ์๋ฌผ, ๋๊ธ, ์ข์์ ์์ฑ ๋ฐ ๊ด๋ฆฌ๋ฅผ ํฌํจํ ์ปค๋ฎค๋ํฐ ๊ธฐ๋ฐ ๊ธฐ๋ฅ์ ์ํ ๋ฐฑ์๋ ์๋น์ค๋ฅผ ์ ๊ณตํฉ๋๋ค. AWS ์๋ฒ๋ฆฌ์ค ๊ธฐ์ ์ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌ์ถ๋ ๊ฒฌ๊ณ ํ๊ณ ํ์ฅ ๊ฐ๋ฅํ๋ฉฐ ์์ ํ API๋ฅผ ๋ชฉํ๋ก ํฉ๋๋ค. ์ด ๊ฐ์ด๋์์๋ ๊ธฐ๋ฅ, ๊ธฐ๋ณธ ๊ธฐ์ , ๋ฐ์ดํฐ ๊ตฌ์กฐ ๋ฐ ๋ฐฐํฌ ์ ์ฐจ๋ฅผ ์์ธํ ์ค๋ช ํฉ๋๋ค.
ํ๋ก์ ํธ ๊ฒฝ๋ก: capstone-2025-04
API ์ธํ๋ผ ๊ฒฝ๋ก: infrastructure/api
Lambda ์์ค ๊ฒฝ๋ก: backend/lambdas/community-lambda-functions/
2. ์ฃผ์ ๊ธฐ๋ฅ
- ๊ฒ์๋ฌผ ๊ด๋ฆฌ:
- ์ ๊ฒ์๋ฌผ ์์ฑ (ํ ์คํธ ๊ธฐ๋ฐ, Markdown ์ง์).
- ์ ํ์ ์ผ๋ก ๊ฒ์๋ฌผ์ ํน์ ํ๋ก๊ทธ๋๋ฐ ๋ฌธ์ ์ ์ฐ๊ฒฐ.
- ๋ชจ๋ ๊ฒ์๋ฌผ ๋ชฉ๋ก ๊ฒ์ (ํ์ด์ง๋ค์ด์ ).
- ํน์ ๊ฒ์๋ฌผ์ ์์ธ ์ ๋ณด ๊ฒ์.
- ๊ธฐ์กด ๊ฒ์๋ฌผ ์ ๋ฐ์ดํธ (์ ๋ชฉ, ๋ด์ฉ).
- ๊ฒ์๋ฌผ ์ญ์ (๊ด๋ จ ๋๊ธ๋ ํจ๊ป ์ญ์ ).
- ๋๊ธ ๊ด๋ฆฌ:
- ํน์ ๊ฒ์๋ฌผ์ ๋๊ธ ์์ฑ.
- ๊ฒ์๋ฌผ์ ๋ชจ๋ ๋๊ธ ๊ฒ์ (ํ์ด์ง๋ค์ด์ , ์์ฑ ๋ ์ง ๊ธฐ์ค ์ ๋ ฌ).
- ๋๊ธ ์ญ์ .
- ์ข์์ ๊ด๋ฆฌ:
- ๊ฒ์๋ฌผ ์ข์์/์ข์์ ์ทจ์.
- ๊ฒ์๋ฌผ์ ์ข์์ ์ ์ถ์ .
- ์ฌ์ฉ์ ์ธ์ฆ:
- Amazon Cognito๋ฅผ ์ฌ์ฉํ์ฌ ์ค์ ์์ (์์ฑ, ์ ๋ฐ์ดํธ, ์ญ์ , ์ข์์) ๋ณด์.
- ์ฝ๊ธฐ ์์ (๊ฒ์๋ฌผ ๊ฐ์ ธ์ค๊ธฐ, ๋๊ธ ๊ฐ์ ธ์ค๊ธฐ)์ ๊ณต๊ฐ ์ก์ธ์ค.
- ๋ฐ์ดํฐ ์์์ฑ:
- Amazon DynamoDB๋ฅผ ํ์ฉํ์ฌ ๊ฒ์๋ฌผ๊ณผ ๋๊ธ์ ์ ์ฅํ๊ณ ํจ์จ์ ์ธ ์ฟผ๋ฆฌ ํจํด ์ฌ์ฉ.
3. ๊ธฐ์ ์คํ
- ๋ฐฑ์๋ ๋ก์ง:
- AWS Lambda: ๊ฐ API ์์ ์ ์ํ ๋น์ฆ๋์ค ๋ก์ง์ ์คํํ๋ ์๋ฒ๋ฆฌ์ค ํจ์ (Node.js 20.x ๋ฐํ์).
- AWS Lambda Layer: Lambda ํจ์์์ ๊ณตํต์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํด ๊ณต์ Node.js ์์กด์ฑ(์:
uuid
)์ ํจํค์งํ ๋ ์ด์ด.
- API ๋
ธ์ถ:
- Amazon API Gateway: Lambda ํจ์๋ฅผ HTTP ์๋ํฌ์ธํธ๋ก ๋ ธ์ถํ๋ RESTful API. ์์ฒญ ๋ผ์ฐํ , ๊ถํ ๋ถ์ฌ, CORS ์ฒ๋ฆฌ.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค:
- Amazon DynamoDB: ์ปค๋ฎค๋ํฐ ๋ฐ์ดํฐ(๊ฒ์๋ฌผ, ๋๊ธ) ์ ์ฅ์ ์ํ NoSQL ๋ฐ์ดํฐ๋ฒ ์ด์ค. ํจ์จ์ ์ธ ์ฟผ๋ฆฌ๋ฅผ ์ํด ๊ธ๋ก๋ฒ ๋ณด์กฐ ์ธ๋ฑ์ค(GSI)๋ก ์ค๊ณ.
- ์ธ์ฆ ๋ฐ ๊ถํ ๋ถ์ฌ:
- Amazon Cognito: ์ฌ์ฉ์ ํ์ ํตํด ์ฌ์ฉ์ ID๋ฅผ ๊ด๋ฆฌํ๊ณ ๋ณดํธ๋ API ์๋ํฌ์ธํธ์ JWT ๊ธฐ๋ฐ ์ธ์ฆ ์ ๊ณต.
- ์ฝ๋ํ ์ธํ๋ผ (IaC):
- Terraform: ๋ชจ๋ AWS ๋ฆฌ์์ค๋ฅผ ์ ์ธ์ ์ผ๋ก ์ ์ํ๊ณ ํ๋ก๋น์ ๋.
- ์ํ ๊ด๋ฆฌ: AWS S3 (Terraform ์ํ ํ์ผ์ฉ) ๋ฐ DynamoDB (์ํ ์ ๊ธ์ฉ).
- Terraform: ๋ชจ๋ AWS ๋ฆฌ์์ค๋ฅผ ์ ์ธ์ ์ผ๋ก ์ ์ํ๊ณ ํ๋ก๋น์ ๋.
- CI/CD:
- GitHub Actions:
main
๋ธ๋์น์ ํธ์ ์ ์ธํ๋ผ ๋ฐ Lambda ์ ๋ฐ์ดํธ๋ฅผ ์ํ ์๋ํ๋ ์ํฌํ๋ก์ฐ. ์์ ํ AWS ์ธ์ฆ์ ์ํด OIDC ํ์ฉ.
- GitHub Actions:
- ํ๋ก ํธ์๋ (์ฐ๋ ์ง์ ):
- Next.js ์ ํ๋ฆฌ์ผ์ด์ .
- ํ๋ก ํธ์๋ ์ธ์ฆ ๋ฐ Cognito์์ ์ํธ์์ฉ์ ์ํ AWS Amplify.
- API Gateway๋ก ์์ฒญ์ ๋ณด๋ด๊ธฐ ์ํ ์ปค์คํ
API ํด๋ผ์ด์ธํธ (
communityApi.ts
- ๊ฐ๋ ์ ).
4. API ์๋ํฌ์ธํธ
API๋ /community
๊ธฐ๋ณธ ๊ฒฝ๋ก ํ์์ ๋ฐฐํฌ๋ฉ๋๋ค. ์ ์ฒด ํธ์ถ URL์ Terraform ๋ฐฐํฌ์ ์ถ๋ ฅ ๊ฐ์
๋๋ค (์: https://{api_id}.execute-api.{region}.amazonaws.com/{stage}/community
).
๋ฉ์๋ | ๊ฒฝ๋ก | ์ธ์ฆ ํ์ | Lambda ํจ์ | ์ค๋ช |
---|---|---|---|---|
POST | /community | โ ์ | createPost | ์ ์ปค๋ฎค๋ํฐ ๊ฒ์๋ฌผ์ ์์ฑํฉ๋๋ค. |
GET | /community | โฌ ์๋์ | getAllPosts | ๋ชจ๋ ๊ฒ์๋ฌผ์ ํ์ด์ง๋ค์ด์ ๋ ๋ชฉ๋ก์ ๊ฒ์ํฉ๋๋ค. |
GET | /community/{postId} | โฌ ์๋์ | getPost | ํน์ ๊ฒ์๋ฌผ์ ์์ธ ์ ๋ณด๋ฅผ ๊ฒ์ํฉ๋๋ค. |
PATCH | /community/{postId} | โ ์ | updatePost | ๊ธฐ์กด ๊ฒ์๋ฌผ์ ์ ๋ฐ์ดํธํฉ๋๋ค. |
DELETE | /community/{postId} | โ ์ | deletePost | ๊ฒ์๋ฌผ๊ณผ ๊ด๋ จ ๋๊ธ์ ์ญ์ ํฉ๋๋ค. |
POST | /community/{postId}/like | โ ์ | likePost | ๊ฒ์๋ฌผ์ ์ข์์๋ฅผ ๋๋ฅด๊ฑฐ๋ ์ทจ์ํฉ๋๋ค. |
POST | /community/{postId}/comments | โ ์ | createComment | ๊ฒ์๋ฌผ์ ์ ๋๊ธ์ ์์ฑํฉ๋๋ค. |
GET | /community/{postId}/comments | โฌ ์๋์ | getComments | ๊ฒ์๋ฌผ์ ํ์ด์ง๋ค์ด์ ๋ ๋๊ธ ๋ชฉ๋ก์ ๊ฒ์ํฉ๋๋ค. |
DELETE | /community/{postId}/comments/{commentId} | โ ์ | deleteComment | ํน์ ๋๊ธ์ ์ญ์ ํฉ๋๋ค. |
OPTIONS | ์์ ๋ชจ๋ ๊ฒฝ๋ก | โฌ ์๋์ | API Gateway MOCK | CORS ์ฌ์ ์์ฒญ(preflight request)์ ์ฒ๋ฆฌํฉ๋๋ค. |
์ธ์ฆ: โโ
์โ๋ก ํ์๋ ์๋ํฌ์ธํธ๋ Amazon Cognito์์ ์ป์ JWT ID ํ ํฐ์ ํฌํจํ๋ Authorization
ํค๋๊ฐ ํ์ํฉ๋๋ค. ์: Authorization: Bearer <your_cognito_id_token>
.
์์ฒญ/์๋ต ์์ (๊ฒ์๋ฌผ ์์ฑ):
- ์์ฒญ:
POST /community
// ํค๋: // Content-Type: application/json // Authorization: Bearer <token> { "title": "๋ฌธ์ X์ ๋ํ ๋์ ์ฒซ ๊ฒ์๋ฌผ", "content": "์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ด๋ ์ต๋๋ค...\n\n```python\nprint('hello')\n```", "problemId": "optional-problem-uuid", // ์ ํ ์ฌํญ "author": "์ฌ์ฉ์๋๋ค์" // ์ฌ์ฉ์ ํ์ ์ด๋ฆ }
- ์๋ต (201 Created):
{ "message": "๊ฒ์๊ธ์ด ์ฑ๊ณต์ ์ผ๋ก ์์ฑ๋์์ต๋๋ค.", "postId": "generated-uuid-for-post", "author": "์ฌ์ฉ์๋๋ค์", "title": "๋ฌธ์ X์ ๋ํ ๋์ ์ฒซ ๊ฒ์๋ฌผ", "content": "์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ด๋ ์ต๋๋ค...\n\n```python\nprint('hello')\n```", "createdAt": "iso-timestamp", "problemId": "optional-problem-uuid" // ๋๋ null }
5. ๋ฐ์ดํฐ ๋ชจ๋ธ (DynamoDB)
๋จ์ผ DynamoDB ํ
์ด๋ธ(๊ธฐ๋ณธ๊ฐ: alpaco-Community-production
)์ ๋ชจ๋ ์ปค๋ฎค๋ํฐ ๋ฐ์ดํฐ๊ฐ ์ ์ฅ๋ฉ๋๋ค.
- ํ
์ด๋ธ ์ด๋ฆ:
${var.project_name}-Community-${var.environment}
- ๊ธฐ๋ณธ ํค:
PK
: ํํฐ์ ํคSK
: ์ ๋ ฌ ํค
- ์์ฑ (ํต์ฌ):
PK
(๋ฌธ์์ด): ๊ฒ์๋ฌผ ํญ๋ชฉ๊ณผ ๋๊ธ ํญ๋ชฉ ๋ชจ๋์ ๋ํดpostId
.SK
(๋ฌธ์์ด):- ๊ฒ์๋ฌผ ํญ๋ชฉ:
"POST"
- ๋๊ธ ํญ๋ชฉ:
"COMMENT#{commentId}"
- ๊ฒ์๋ฌผ ํญ๋ชฉ:
userId
(๋ฌธ์์ด): ์์ฑ์/๋๊ธ ์์ฑ์์ Cognito ์ฌ์ฉ์ ID.author
(๋ฌธ์์ด): ์์ฑ์/๋๊ธ ์์ฑ์์ ํ์ ์ด๋ฆ.title
(๋ฌธ์์ด): ๊ฒ์๋ฌผ ์ ๋ชฉ (๊ฒ์๋ฌผ ํญ๋ชฉ์๋ง ํด๋น).content
(๋ฌธ์์ด): ๊ฒ์๋ฌผ ๋๋ ๋๊ธ ๋ด์ฉ (Markdown).createdAt
(๋ฌธ์์ด): ISO 8601 ํ์์คํฌํ.updatedAt
(๋ฌธ์์ด): ISO 8601 ํ์์คํฌํ (๊ฒ์๋ฌผ ํญ๋ชฉ์ฉ).likesCount
(์ซ์): ์ข์์ ์ (๊ฒ์๋ฌผ ํญ๋ชฉ์ฉ).likedUsers
(๋ฌธ์์ด ์งํฉ): ๊ฒ์๋ฌผ์ ์ข์ํuserId
์งํฉ (๊ฒ์๋ฌผ ํญ๋ชฉ์ฉ).commentCount
(์ซ์): ๊ฒ์๋ฌผ์ ๋๊ธ ์ (๊ฒ์๋ฌผ ํญ๋ชฉ์ฉ).problemId
(๋ฌธ์์ด): ์ฐ๊ด๋ ํ๋ก๊ทธ๋๋ฐ ๋ฌธ์ ์ ์ ํ์ ID (๊ฒ์๋ฌผ ํญ๋ชฉ์ฉ).commentId
(๋ฌธ์์ด): ๋๊ธ์ ๊ณ ์ ID (๋๊ธ ํญ๋ชฉ์ฉ, SK์ ์ผ๋ถ์ด๊ธฐ๋ ํจ).
- ๊ธ๋ก๋ฒ ๋ณด์กฐ ์ธ๋ฑ์ค (GSI):
postOnlyIndex
:- ๋ชฉ์ : ๋ชจ๋ ๊ฒ์๋ฌผ์ ์์ฑ ์๊ฐ์์ผ๋ก ํจ์จ์ ์ผ๋ก ๋์ด.
getAllPosts
Lambda์์ ์ฌ์ฉ. GSI1PK
(๋ฌธ์์ด):"POST"
(๋ชจ๋ ๊ฒ์๋ฌผ ํญ๋ชฉ์ ๋ํ ์์).GSI1SK
(๋ฌธ์์ด):createdAt
ํ์์คํฌํ.- ํ๋ก์ ์
: ๊ฒ์๋ฌผ ๋ชฉ๋ก ๋ณด๊ธฐ์ ํ์ํ ์์ฑ ํฌํจ (
PK
,title
,author
,createdAt
,likesCount
,commentCount
,problemId
,userId
). - ์ฐธ๊ณ :
createPost
Lambda๋ ์ ๊ฒ์๋ฌผ์ ๋ํดGSI1PK
์GSI1SK
๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค.
- ๋ชฉ์ : ๋ชจ๋ ๊ฒ์๋ฌผ์ ์์ฑ ์๊ฐ์์ผ๋ก ํจ์จ์ ์ผ๋ก ๋์ด.
commentSortIndex
:- ๋ชฉ์ : ํน์ ๊ฒ์๋ฌผ์ ๋ชจ๋ ๋๊ธ์ ์์ฑ ์๊ฐ์์ผ๋ก ํจ์จ์ ์ผ๋ก ๋์ด.
getComments
Lambda์์ ์ฌ์ฉ. PK
(๋ฌธ์์ด):postId
(๊ธฐ๋ณธ ํ ์ด๋ธ PK๋ฅผ GSI ํด์ ํค๋ก ์ฌ์ฌ์ฉ).createdAt
(๋ฌธ์์ด): ๋๊ธ์createdAt
ํ์์คํฌํ (๊ธฐ์กด ์์ฑ์ GSI ๋ฒ์ ํค๋ก ์ฌ์ฌ์ฉ).- ํํฐ: Lambda๋ ์ด GSI๋ฅผ ์ฟผ๋ฆฌํ ๋
SK
๊ฐCOMMENT#
๋ก ์์ํ๋์ง ์ถ๊ฐ๋ก ํํฐ๋งํฉ๋๋ค. - ํ๋ก์ ์
: ๋๊ธ ๋ชฉ๋ก ๋ณด๊ธฐ์ ํ์ํ ์์ฑ ํฌํจ (
content
,author
,commentId
,userId
,SK
).
- ๋ชฉ์ : ํน์ ๊ฒ์๋ฌผ์ ๋ชจ๋ ๋๊ธ์ ์์ฑ ์๊ฐ์์ผ๋ก ํจ์จ์ ์ผ๋ก ๋์ด.
6. Lambda ํจ์
backend/lambdas/community-lambda-functions/
์ ์์นํฉ๋๋ค. ๋ชจ๋ ํจ์๋ Node.js 20.x ๋ฐํ์์ ์ฌ์ฉํ๊ณ , ๊ณตํต IAM ์คํ ์ญํ ์ ๊ณต์ ํ๋ฉฐ, common-deps
Lambda ๋ ์ด์ด๋ฅผ ํ์ฉํฉ๋๋ค. COMMUNITY_TABLE_NAME
ํ๊ฒฝ ๋ณ์๋ฅผ ์์ํฉ๋๋ค. _modified.mjs
์ ๋ฏธ์ฌ๋ ํ์ฌ ์ธํ๋ผ์ ๋ง๊ฒ ์์ ๋ ๋ฒ์ ์์ ๋ํ๋
๋๋ค (์: AWS SDK v3 ์ฌ์ฉ, ํน์ DynamoDB ์ํธ์์ฉ).
- ๊ฒ์๋ฌผ ํจ์:
createPost_modified.mjs
: GSI ํค ์์ฑ์ ํฌํจํ์ฌ ๊ฒ์๋ฌผ ์์ฑ์ ์ฒ๋ฆฌํฉ๋๋ค.deletePost_modified.mjs
: ๊ฒ์๋ฌผ๊ณผ ๊ด๋ จ๋ ๋ชจ๋ ๋๊ธ์ ํธ๋์ญ์ ๋ด์์ ์ญ์ ํฉ๋๋ค. ์์ ๊ถ์ ํ์ธํฉ๋๋ค.getAllPosts_modified.mjs
:postOnlyIndex
๋ฅผ ์ฌ์ฉํ์ฌ ํ์ด์ง๋ค์ด์ ๋ ๊ฒฐ๊ณผ๋ก ๊ฒ์๋ฌผ์ ๊ฐ์ ธ์ต๋๋ค.getPost_modified.mjs
: ID๋ก ๋จ์ผ ๊ฒ์๋ฌผ์ ๊ฐ์ ธ์ต๋๋ค.likePost_modified.mjs
: ๊ฒ์๋ฌผ์likedUsers
์งํฉ์ ์ฌ์ฉ์๋ฅผ ์ถ๊ฐ/์ ๊ฑฐํ๊ณlikesCount
๋ฅผ ์ ๋ฐ์ดํธํฉ๋๋ค.updatePost_modified.mjs
: ๊ฒ์๋ฌผ ์ ๋ชฉ/๋ด์ฉ์ ์ ๋ฐ์ดํธํฉ๋๋ค. ์์ ๊ถ์ ํ์ธํฉ๋๋ค.
- ๋๊ธ ํจ์:
comment/createComment_modified.mjs
: ๋๊ธ์ ์์ฑํ๊ณ ๋ถ๋ชจ ๊ฒ์๋ฌผ์commentCount
๋ฅผ ํธ๋์ญ์ ๋ด์์ ์ฆ๊ฐ์ํต๋๋ค.comment/deleteComment_modified.mjs
: ๋๊ธ์ ์ญ์ ํ๊ณ ๋ถ๋ชจ ๊ฒ์๋ฌผ์commentCount
๋ฅผ ํธ๋์ญ์ ๋ด์์ ๊ฐ์์ํต๋๋ค. ์์ ๊ถ์ ํ์ธํฉ๋๋ค.comment/getComments_modified.mjs
:commentSortIndex
๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์๋ฌผ์ ๋๊ธ์ ํ์ด์ง๋ค์ด์ ํ๊ณ ์ ๋ ฌํ์ฌ ๊ฐ์ ธ์ต๋๋ค.
7. ์ฝ๋ํ ์ธํ๋ผ (Terraform)
์ธํ๋ผ๋ infrastructure/api/
์ ์์นํ Terraform์ผ๋ก ๊ด๋ฆฌ๋ฉ๋๋ค.
- ์ฃผ์ ํ์ผ:
providers.tf
: AWS ํ๋ก๋ฐ์ด๋๋ฅผ ์ ์ํฉ๋๋ค.backend.tf
: S3 ์๊ฒฉ ์ํ ๋ฐฑ์๋๋ฅผ ์ค์ ํฉ๋๋ค (key = "api/community/terraform.tfstate"
).variables.tf
: ์ ๋ ฅ ๋ณ์ (๋ฆฌ์ , ํ๋ก์ ํธ ์ด๋ฆ, ํ๊ฒฝ)๋ฅผ ์ ์ํฉ๋๋ค.outputs.tf
: API Gateway ํธ์ถ URL๊ณผ ๊ฐ์ ์ถ๋ ฅ ๊ฐ์ ์ ์ํฉ๋๋ค.iam.tf
: IAM ์ญํ (Lambda ์คํ, API Gateway CloudWatch ๋ก๊น ) ๋ฐ ์ ์ฑ (DynamoDB ์ ๊ทผ)์ ์ ์ํฉ๋๋ค.dynamodb.tf
:Community
DynamoDB ํ ์ด๋ธ ๋ฐ GSI๋ฅผ ์ ์ํฉ๋๋ค.layer.tf
:layers/common-deps/nodejs/
์common-deps
Lambda ๋ ์ด์ด๋ฅผ ์ ์ํฉ๋๋ค.lambdas.tf
: ๋ชจ๋aws_lambda_function
๋ฆฌ์์ค๋ฅผ ์ ์ํ๋ฉฐ,../../backend/lambdas/community-lambda-functions/
์์ ์์ค ์ฝ๋๋ฅผ ์์ถํฉ๋๋ค.apigateway.tf
: API Gateway (REST API, ๋ฆฌ์์ค, ๋ฉ์๋, ํตํฉ, Cognito Authorizer, ๋ฐฐํฌ, ์คํ ์ด์ง)๋ฅผ ์ ์ํฉ๋๋ค.
- ์๊ฒฉ ์ํ:
infrastructure/backend-setup
๋ชจ๋์์ ์์ฑ๋ S3 ๋ฒํท(alpaco-tfstate-bucket-kmu
)๊ณผ DynamoDB ํ ์ด๋ธ(alpaco-tfstate-lock-table
)์ ์ฌ์ฉํฉ๋๋ค. - Cognito ์์กด์ฑ:
cognito/terraform.tfstate
์๊ฒฉ ์ํ์์ Cognito ์ฌ์ฉ์ ํ ARN์ ์ฝ์ด API Gateway Authorizer๋ฅผ ์ค์ ํฉ๋๋ค. - ์ด๊ธฐํ ๋ฐ ๋ฐฐํฌ:
# infrastructure/api๋ก ์ด๋ cd infrastructure/api # ์ด๊ธฐํ (ํ๋ ์ด์คํ๋๋ฅผ ์ค์ ๊ฐ์ผ๋ก ๊ต์ฒด) terraform init \ -backend-config="bucket=<YOUR_TFSTATE_BUCKET_NAME>" \ -backend-config="key=api/community/terraform.tfstate" \ -backend-config="region=<YOUR_AWS_REGION>" \ -backend-config="dynamodb_table=<YOUR_TFSTATE_LOCK_TABLE_NAME>" # ๋ณ๊ฒฝ ๊ณํ ๊ฒํ terraform plan # ๋ณ๊ฒฝ ์ฌํญ ์ ์ฉ terraform apply
8. CI/CD (GitHub Actions)
์๋ํ๋ .github/workflows/deploy-api.yml
์ ์ ์๋ GitHub Actions ์ํฌํ๋ก์ฐ์ ์ํด ์ฒ๋ฆฌ๋ฉ๋๋ค (PLAN.md
์ฐธ์กฐ).
- ํธ๋ฆฌ๊ฑฐ:
backend/lambdas/community/**
๋๋infrastructure/api/**
์ ์ํฅ์ ๋ฏธ์น๋main
๋ธ๋์น๋ก์ ํธ์. - ์ธ์ฆ: OpenID Connect (OIDC)๋ฅผ ์ฌ์ฉํ์ฌ AWS์์ IAM ์ญํ ์ ์์ ํ๊ฒ ์์ํ์ฌ ์ฅ๊ธฐ ์๊ฒฉ ์ฆ๋ช ์ ์ฌ์ฉํ์ง ์์ต๋๋ค.
- ๋จ๊ณ:
- ์ฝ๋ ์ฒดํฌ์์.
- Node.js ์ค์ .
- Lambda ๋ ์ด์ด ์์กด์ฑ์ ์ค๋นํ๊ธฐ ์ํด
infrastructure/api/layers/common-deps/nodejs/
์์npm install
์คํ. secrets.AWS_IAM_ROLE_ARN_API
์ ์ญํ ARN์ ์ฌ์ฉํ์ฌ OIDC๋ฅผ ํตํด AWS ์๊ฒฉ ์ฆ๋ช ์ค์ .infrastructure/api
๋๋ ํ ๋ฆฌ ๋ด์์terraform init
(secrets์ ๋ฐฑ์๋ ์ค์ ์ฌ์ฉ),terraform plan
,terraform apply
์คํ.
- ํ์ Secrets:
AWS_IAM_ROLE_ARN_API
: GitHub Actions๊ฐ ์์ํ IAM ์ญํ ์ ARN.AWS_REGION
: ๋์ AWS ๋ฆฌ์ .TF_STATE_BUCKET
: Terraform ์ํ์ฉ S3 ๋ฒํท.TF_STATE_LOCK_TABLE
: Terraform ์ํ ์ ๊ธ์ฉ DynamoDB ํ ์ด๋ธ.
9. ํ๋ก ํธ์๋ ์ฐ๋
ํ๋ก ํธ์๋(Next.js ์ ํ๋ฆฌ์ผ์ด์ )๋ ์ด API์ ์ํธ์์ฉํฉ๋๋ค.
- API ํด๋ผ์ด์ธํธ: API ํธ์ถ์ ์บก์ํํ๊ธฐ ์ํด ๊ฐ๋
์ ์ธ
communityApi.ts
(๋๋ ์ ์ฌํ ์๋น์ค ๋ชจ๋)๊ฐ ์ฌ์ฉ๋ฉ๋๋ค. - ์๋ํฌ์ธํธ ์ค์ : API Gateway ํธ์ถ URL์ ์ผ๋ฐ์ ์ผ๋ก ํ๊ฒฝ ๋ณ์(์:
NEXT_PUBLIC_API_ENDPOINT
)๋ฅผ ํตํด ํ๋ก ํธ์๋์ ์ ๊ณต๋ฉ๋๋ค. - ์ธ์ฆ:
- AWS Amplify์
useAuthenticator
ํ ์ด ์ฌ์ฉ์ ์ธ์ฆ ์ํ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค. - Amplify Auth์
fetchAuthSession
์ ์ฌ์ฉํ์ฌ ํ์ฌ ์ฌ์ฉ์์ JWT ID ํ ํฐ์ ๊ฒ์ํฉ๋๋ค. - ๋ณดํธ๋ API ํธ์ถ(์์ฑ, ์
๋ฐ์ดํธ, ์ญ์ , ์ข์์)์ ๊ฒฝ์ฐ ์ด JWT ํ ํฐ์ด
Authorization
ํค๋์ ํฌํจ๋ฉ๋๋ค:Authorization: Bearer <id_token>
. - ์ฌ์ฉ์ ์์ฑ(์: ํ์ด๋ก๋ ๋๋ UI์ ์ฌ์ฉํ
nickname
๋๋sub
(userId์ฉ))์fetchUserAttributes
๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ ธ์ต๋๋ค.
- AWS Amplify์
- ์ค๋ฅ ์ฒ๋ฆฌ: ํ๋ก ํธ์๋ ์ปดํฌ๋ํธ๋ API ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ๋ฉฐ, ์ข
์ข
ํ ์คํธ ์๋ฆผ(์:
sonner
์ฌ์ฉ)์ ํ์ํฉ๋๋ค. - ์์ ํ์ด์ง:
frontend/src/app/community/page.tsx
: ๊ฒ์๋ฌผ ๋ชฉ๋ก ํ์ ๋ฐ ๊ฒ์๋ฌผ ์์ธ ์ ๋ณด ํ์๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค.frontend/src/app/community/create/page.tsx
: ์ ๊ฒ์๋ฌผ ์์ฑ์ ์ํ ํผ์ ๋๋ค.frontend/src/app/community/edit/page.tsx
: ๊ธฐ์กด ๊ฒ์๋ฌผ ์์ ์ ์ํ ํผ์ ๋๋ค.
10. CORS ์ค์
CORS(Cross-Origin Resource Sharing)๋ API Gateway์์ ์ฒ๋ฆฌ๋ฉ๋๋ค.
- ๊ฐ ๋ฆฌ์์ค ๊ฒฝ๋ก์ ๋ํด
OPTIONS
๋ฉ์๋๊ฐ MOCK ํตํฉ์ผ๋ก ์ ์๋ฉ๋๋ค. - ์ด๋ฌํ
OPTIONS
๋ฉ์๋ ๋ฐ ์ค์ ์๋ํฌ์ธํธ ๋ฉ์๋์๋ ๋ค์๊ณผ ๊ฐ์ ์๋ต ํค๋๊ฐ ํฌํจ๋ฉ๋๋ค:Access-Control-Allow-Origin: '*'
(ํ๋ก๋์ ํ๊ฒฝ์์๋ ํน์ ํ๋ก ํธ์๋ URL)Access-Control-Allow-Methods: 'POST,GET,PATCH,DELETE,OPTIONS'
(๋ฆฌ์์ค๋ง๋ค ๋ค๋ฆ)Access-Control-Allow-Headers: 'Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'
- Lambda ํจ์๋ ์๋ต์ CORS ํค๋๋ฅผ ํฌํจํ์ฌ ๊ฒฌ๊ณ ์ฑ์ ๋์ด์ง๋ง, API Gateway๊ฐ ๊ธฐ๋ณธ ์ฒ๋ฆฌ๊ธฐ์ ๋๋ค.
์ด ๊ฐ์ด๋๋ ALPACO ์ปค๋ฎค๋ํฐ API ์์คํ ์ ๋ํ ํฌ๊ด์ ์ธ ์ดํด๋ฅผ ์ ๊ณตํด์ผ ํฉ๋๋ค. ๊ฐ๋ณ Terraform ํ์ผ ๋ฐ Lambda ์์ค ์ฝ๋๋ ๊ตฌ์ฒด์ ์ธ ๊ตฌํ ์ฌํญ์ ์ฐธ์กฐํ์ญ์์ค.