"μ¬μ΄λ νλ‘μ νΈμ λ°±μλκ° νμν΄μ AWS EC2λ₯Ό λμ λλ°, μ무λ μ μ μ νλ μλ²½μλ λ§€λ¬ 2λ§ μμ© μκΈμ΄ λκ°κ³ μμ΅λλ€. μ΄κ±° μ μμΈκ°μ?"
μλ νμΈμ! ν΄λΌμ°λ μΈνλΌ μκΈ λ€μ΄μ΄νΈμ ν¨μ¨μ μΈ μν€ν μ² μ€κ³μ μ§μ¬μΈ κ°λ°μμ λλ€.
μ£Όλμ΄ κ°λ°μλ νλ‘ νΈμλ κ°λ°μκ° κ°μΈ νλ‘μ νΈλ₯Ό μ§νν λ κ°μ₯ ν° μ₯λ²½μ 'λ°±μλ μλ² μ μ§λΉ'μ λλ€. 24μκ° λ΄λ΄ μΌλμ΄μΌ νλ κΈ°μ‘΄μ μλ² νΈμ€ν (EC2 λ±) λ°©μμ νΈλν½μ΄ μλ μκ°λμλ λΆνμν λΉμ©μ λ°μμν΅λλ€.
μ΄λ¬ν μκΈ ννμ 곡ν¬μ μλ² κ΄λ¦¬μ 볡μ‘ν¨μ ν λ²μ ν΄κ²°ν΄ μ£Όλ νλ ν΄λΌμ°λμ λ§λ²μ΄ λ°λ‘ 'μλ²λ¦¬μ€(Serverless)'μ λλ€. κ·Έμ€μμλ κ°μ₯ λμ€μ μ΄κ³ κ°λ ₯ν μ‘°ν©μΈ AWS Lambdaμ API Gatewayλ₯Ό μ¬μ©νλ©΄, μ½λκ° μ€νλ λ± κ·Έ 0.1μ΄μ μ°°λμλ§ λΉμ©μ μ§λΆνλ νμμ μΈ λ°±μλλ₯Ό ꡬμΆν μ μμ΅λλ€.
μ΄λ² κΈμμλ μλ²λ¦¬μ€κ° λλ체 무μμΈμ§ μ§κ΄μ μΈ λΉμ λ‘ μμλ³΄κ³ , νμ μμ μ΄ λ κ°μ§ μλΉμ€λ₯Ό μ΄λ»κ² κ²°ν©νμ¬ μμ© APIλ₯Ό λ§λλμ§, κ·Έλ¦¬κ³ λ°λμ λ§μ£ΌμΉκ² λλ 'μ½λ μ€ννΈ(Cold Start)' μλ¬ ν΄κ²°λ²κΉμ§ κΉμ΄ μκ² νν€μ³ λ³΄κ² μ΅λλ€.
1. μλ²λ¦¬μ€(Serverless)λ? μ§μ§ μλ²κ° μλ κ±ΈκΉ?
μλ²λ¦¬μ€λΌλ λ¨μ΄λ₯Ό μ²μ λ€μΌλ©΄ "μλ²κ° μλλ° μ½λκ° μ΄λμ λμκ°μ§?"λΌλ μλ¬Έμ΄ μκΉλλ€. κ²°λ‘ λΆν° λ§νμλ©΄ μλ²λ μ‘΄μ¬νμ§λ§, κ°λ°μμΈ λ΄κ° μ§μ μλ²λ₯Ό κ΄λ¦¬ν νμκ° μλ€λ λ»μ λλ€.
μ΄λ₯Ό 'μκ°μ©(EC2)'κ³Ό 'νμ(Lambda)'μ λΉμ ν΄ λ³΄κ² μ΅λλ€.
- κΈ°μ‘΄ μλ² (AWS EC2) = μκ°μ©:
- μ°¨λ₯Ό μ¬λ©΄(μλ² μλ), λ΄κ° μ΄μ μ μ νκ³ μ£Όμ°¨μ₯μ μΈμλ§ λμ΄λ λ§€λ¬ λ³΄νλ£μ μ£Όμ°¨λΉ(κ³ μ μκΈ)κ° λκ°λλ€. μμ§ μ€μΌλ μ§μ κ°μμΌ νκ³ (OS μ λ°μ΄νΈ), μλμ΄ λ§μμ§λ©΄ λ ν° μ°¨λ‘ μ§μ λ°κΏμΌ ν©λλ€(μ€μΌμΌ μ ).
- μλ²λ¦¬μ€ (AWS Lambda) = νμ:
- νμλ μ°¨λ₯Ό μμ νμ§ μμ΅λλ€. λ΄κ° μ΄λνκ³ μΆμ λ(API μμ²μ΄ λ€μ΄μ¬ λ) νμλ₯Ό λΆλ₯΄κ³ , λ± λͺ©μ μ§κΉμ§ λ¬λ¦° 거리(μ½λ μ€ν μκ°)λ§νΌλ§ λ―Έν°κΈ° μκΈμ μ§λΆν©λλ€. νμμλ μκΈμ΄ 0μμ΄λ©°, μ°¨λ¨κΈ° κ³ μ₯μ΄λ μ λΉλ νμ νμ¬(AWS)κ° μμμ λ€ ν΄μ€λλ€.
2. API Gatewayμ Lambdaμ νμμ μΈ μ½€λΉ (λμ μ리)
νμ(Lambda)κ° μ€λΉλμλ€λ©΄, μλ(ν΄λΌμ΄μΈνΈ)μ νΈμΆμ λ°μ νμλ₯Ό λ°°μ°¨ν΄ μ€ 'μ½νμ μΌν°'κ° νμν©λλ€. μ΄ μν μ νλ κ²μ΄ λ°λ‘ Amazon API Gatewayμ λλ€.
μΉμ΄λ μ±μμ [https://api.my-domain.com/users](https://api.my-domain.com/users) λΌλ μ£Όμλ‘ μ¬μ©μ μ 보λ₯Ό λ¬λΌκ³ GET μμ²μ 보λ΄λ©΄, κ·Έ μμ²μ μ§μ Lambdaλ‘ κ°μ§ μκ³ API Gatewayλ₯Ό κ±°μΉκ² λ©λλ€.
[ν΄λΌμ΄μΈνΈ λΈλΌμ°μ / μ±]
β
(HTTP GET /users μμ²)
βΌ
[Amazon API Gateway (μ½μΌν° μ§μ)]
β "μ΄? /users κ²½λ‘λ€? μ¬μ©μ μ‘°ν λ΄λΉ Lambdaλ₯Ό κΉ¨μλΌ!"
βΌ
[AWS Lambda (μλ¦¬μ¬ / ν¨μ)]
β DB μ‘°ν λ° JSON λ°μ΄ν° μμ± ν λ°ν
βΌ
[ν΄λΌμ΄μΈνΈ λΈλΌμ°μ / μ±] (κ²°κ³Ό μμ )
π API Gatewayμ Lambda μν λΉκ΅
| μλΉμ€ | μν€ν μ² μν | λΉμ μ μν | μ£Όμ κΈ°λ₯ λ° νΉμ§ |
| API Gateway | λ¬Έμ§κΈ° & λΌμ°ν° | λ μ€ν λ ν λ§€λμ | URL κ²½λ‘ λ§€ν, νΈλν½ μ ν(Rate Limit), μΈμ¦ μΈκ°(CORS, JWT), νλΌλ―Έν° κ²μ¦ |
| AWS Lambda | μ»΄ν¨ν μ°μ° μ²λ¦¬ | μ£Όλ°© μλ¦¬μ¬ | λΉμ¦λμ€ λ‘μ§ μ€ν, λ°μ΄ν°λ² μ΄μ€ μ°λ, μΈλΆ API ν΅μ (μ΅λ μ€ν μκ° 15λΆ) |
API Gatewayκ° μ μ± νΈλν½μ λ§μμ£Όκ³ κΆνμ κ²μ¬ν λ€, μμ ν μμ²λ§ Lambdaλ‘ λ겨주기 λλ¬Έμ λ°±μλ μμ€ν μ΄ λ§€μ° κ²¬κ³ ν΄μ§λλ€.
3. νμ μ€λ¬΄ μλ리μ€: 'μ’μμ' μΉ΄μ΄νΈ API λ§λ€κΈ°
μ€μ μ κ° νλ‘ νΈμλ μμ£Όμ ν¬νΈν΄λ¦¬μ€ μ¬μ΄νΈλ₯Ό λ§λ€ λ, λ°±μλ μλ² μμ΄ κ²μκΈμ 'μ’μμ' λ²νΌ κΈ°λ₯μ ꡬννλ μλ리μ€μ λλ€.
Lambda ν¨μλ Node.js, Python, Java λ± λ€μν μΈμ΄λ₯Ό μ§μν©λλ€. μλλ Node.jsλ₯Ό κΈ°λ°μΌλ‘ ν Lambdaμ κΈ°λ³Έμ μΈ μ½λ λΌλ(Handler)μ λλ€.
// index.mjs (AWS Lambda νΈλ€λ¬ ν¨μ)
export const handler = async (event, context) => {
// 1. API Gatewayκ° λκ²¨μ€ μμ²(event)μμ νλΌλ―Έν°λ₯Ό κΊΌλ
λλ€.
// μ: /likes?postId=123
const postId = event.queryStringParameters?.postId;
if (!postId) {
return {
statusCode: 400,
body: JSON.stringify({ message: 'postIdκ° νμν©λλ€.' }),
};
}
try {
// 2. λ°μ΄ν°λ² μ΄μ€(μ: DynamoDB)μμ μ’μμ μλ₯Ό +1 μ¦κ°μν΅λλ€.
const currentLikes = await updateLikesInDatabase(postId);
// 3. API Gatewayλ₯Ό ν΅ν΄ νλ‘ νΈμλλ‘ μλ΅μ 보λ
λλ€.
return {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin": "*", // CORS νμ© νμ!
},
body: JSON.stringify({
message: 'μ’μμ μ±κ³΅!',
likes: currentLikes
}),
};
} catch (error) {
console.error("DB μ
λ°μ΄νΈ μ€ μλ¬ λ°μ:", error);
return {
statusCode: 500,
body: JSON.stringify({ message: 'μλ² λ΄λΆ μ€λ₯κ° λ°μνμ΅λλ€.' }),
};
}
};
π‘ μ€λ¬΄ ν΅μ¬ ν¬μΈνΈ:
νλ‘ νΈμλμμ APIλ₯Ό νΈμΆν λ λΈλΌμ°μ μ CORS μλ¬λ₯Ό λ§μΌλ €λ©΄, Lambdaμ λ°νκ°(Return) headers κ°μ²΄μ λ°λμ "Access-Control-Allow-Origin": "*" λ₯Ό ν¬ν¨ν΄μ λ΄λ €μ£Όμ΄μΌ ν©λλ€. μ΄κ²μ λλ½ν΄μ ν루 μ’ μΌ μ½μ§νλ μ£Όλμ΄ λΆλ€μ΄ μ λ§ λ§μ΅λλ€!
4. μ£Όλμ΄κ° κ²ͺλ μλ²λ¦¬μ€ μ΅λ λμ : 'μ½λ μ€ννΈ(Cold Start)'
μλ²λ¦¬μ€λ₯Ό μ€λ¬΄μ λμ νλ©΄ 첫 ν μ€νΈμμ λ¬ν μ΄μ§κ°μ λλΌκ² λ©λλ€.
"μ΄? λ°©κΈ μ²« λ²μ§Έ ν΄λ¦ λλ λ‘λ©μ΄ 3μ΄λ κ±Έλ Έλλ°, λ λ²μ§Έ ν΄λ¦λΆν°λ 0.1μ΄ λ§μ λλ€μ?"
μ΄ νμμ΄ λ°λ‘ μλ²λ¦¬μ€μ νμμ νκ³μΈ 'μ½λ μ€ννΈ(Cold Start)'μ λλ€.
Lambdaλ νμμ λΉμ©μ μλΌκΈ° μν΄ μΏ¨μΏ¨ μ μ μκ³ μμ΅λλ€(컨ν μ΄λ μ’ λ£ μν). κ·Έλ°λ° κ°μκΈ° μμ²μ΄ λ€μ΄μ€λ©΄, AWSκ° λΆλ΄λΆλ΄ 1) κ°μ νκ²½μ λμ°κ³ 2) μ½λλ₯Ό λ€μ΄λ‘λνκ³ 3) μ΄κΈ°ννλ κ³Όμ μ κ±°μΉκ² λ©λλ€. μ΄ κ³Όμ μμ λ°μνλ λͺ μ΄κ°μ μ§μ° μκ°μ μ½λ μ€ννΈλΌκ³ λΆλ¦ λλ€. λ°λ©΄, ν λ² κΉ¨μ΄λ Lambdaλ λΉλΆκ°(μ½ 10~15λΆ) μ λ€μ§ μκ³ λκΈ°νλλ°, μ΄λ μμ²μ΄ λ€μ΄μ€λ©΄ μ§μ° μμ΄ μ¦μ μ²λ¦¬νλ κ²μ μ μ€ννΈ(Warm Start)λΌκ³ ν©λλ€.
β μ€λ¬΄μμμ μ½λ μ€ννΈ ν΄κ²°μ±
- κ°λ²Όμ΄ μΈμ΄ μ ν: Javaλ C#μ²λΌ μ΄κΈ°νκ° λ¬΄κ±°μ΄ μΈμ΄λ³΄λ€λ, Node.jsλ Python, Go μΈμ΄λ₯Ό μ¬μ©νλ κ²μ΄ μ½λ μ€ννΈλ₯Ό νκΈ°μ μΌλ‘ μ€μ¬μ€λλ€.
- EventBridge(CloudWatch Events)λ‘ ν(Ping) λ 리기: 10λΆλ§λ€ λλ€λ₯Ό μ°λ¬μ£Όλ(νΈμΆνλ) λΉ μ΄λ²€νΈλ₯Ό μμ½ν΄ λμ΄ λλ€κ° μ λ€μ§ μκ² κ΄΄λ‘νλ(?) κΌΌμμ λλ€.
- Provisioned Concurrency (μμ½λ λμμ±): νΈλν½μ΄ λ§κ³ μ§μ° μκ°μ΄ μΉλͺ μ μΈ μμ© μλΉμ€λΌλ©΄, AWSμ λμ μ‘°κΈ λ λ΄κ³ "νμ λλ€ 5λλ κΉ¨μλ¬!"λΌκ³ μμ½ν μ μλ κΈ°λ₯μ λλ€.
5. μ€λ¬΄ κ²½νμμ μ»μ μλ²λ¦¬μ€ μ€κ³ ν 3κ°μ§
μλ²λ¦¬μ€ μν€ν μ²λ₯Ό νλ‘λμ νκ²½μ λ°°ν¬νλ©° 체λν νΌμ λμ΄ μμΈ νμ 곡μ ν©λλ€.
- ν 1: API Gatewayμ 29μ΄ νμμμμ λͺ μ¬νμΈμ.
- Lambda μ체λ μ΅λ 15λΆκΉμ§ μ½λλ₯Ό μ€νν μ μμ΅λλ€. νμ§λ§ κ·Έ μλ¨μ μ μλ API Gatewayλ 무쑰건 29μ΄ μμ μλ΅μ μ£Όμ§ μμΌλ©΄ ν΄λΌμ΄μΈνΈμκ² 504 Gateway Timeout μλ¬λ₯Ό λ±μ΄λ²λ¦½λλ€. λ₯λ¬λ λͺ¨λΈ μΆλ‘ μ΄λ λμ©λ μμ λ€μ΄λ‘λμ²λΌ 30μ΄ μ΄μ 걸리λ λ¬΄κ±°μ΄ μμ μ API Gatewayλ₯Ό κ±°μΉλ λκΈ°μμΌλ‘ μ€κ³νλ©΄ μ λ μ λ©λλ€. (μ΄ κ²½μ° λΉλκΈ°μ μ€κ³κ° νμν©λλ€.)
- ν 2: λͺ¨λ κΈ°λ₯μ νλμ Lambdaμ λλ € λ£μ§ λ§μΈμ (Fat Lambda μ§μ).
- Express.jsλ Spring Bootλ‘ λΌμ°ν μ μ§λ― νλμ Lambda νμΌ μμ μ μ μ‘°ν, μν λ±λ‘, κ²°μ λ‘μ§μ λ€ λ£μΌλ©΄ (μ΄λ₯Έλ° λ±λ±ν λλ€), νμΌ μ©λμ΄ μ»€μ Έ μ½λ μ€ννΈκ° μ¬ν΄μ§κ³ μ μ§λ³΄μκ° μ§μ₯μ΄ λ©λλ€. κΈ°λ₯ λ¨μ(λ§μ΄ν¬λ‘μλΉμ€)λ‘ λλ€λ₯Ό μͺΌκ°μ API Gatewayμμ URLλ³λ‘ μ°κ²°ν΄ μ£Όλ κ²μ΄ μ μμ λλ€.
- ν 3: νκ²½ λ³μ(Environment Variables)λ‘ DB λΉλ°λ²νΈλ₯Ό νλμ½λ©νμ§ λ§μΈμ.
- μ½λ λ΄λΆμ DB λΉλ°λ²νΈλ₯Ό μ μ΄λλ κ²μ κΈλ¬Όμ λλ€. Lambdaμ κ΅¬μ± νμμ νκ²½ λ³μλ‘ λΆλ¦¬νμ¬ μ£Όμ νκ³ , λ λμ 보μμ΄ νμνλ€λ©΄ AWS Secrets Managerλ Parameter Storeλ₯Ό κ²°ν©ν΄ λ°νμμ μμ νκ² λΉλ°λ²νΈλ₯Ό κ°μ Έμ€λλ‘ μ€κ³νμΈμ.
ν΄λΌμ°λμ λ°μ μΌλ‘ μ΄μ κ°λ°μλ 'μλ² μΈνλΌ κ΅¬μΆ'μ΄λΌλ λ¬΄κ±°μ΄ μ§μ λ΄λ €λκ³ , μ€μ§ 'λΉμ¦λμ€ λ‘μ§(μ½λ)'μλ§ μ§μ€ν μ μλ μλκ° λμμ΅λλ€. νΉν μ¬μ΄λ νλ‘μ νΈλ ν¬νΈν΄λ¦¬μ€λ₯Ό μ€λΉνλ μ£Όλμ΄ κ°λ°μμκ² λ§€λ¬ 0μμ μλ ΄νλ λΉμ©μΌλ‘ 무νν νμ₯μ΄ κ°λ₯ν μλ²λ¦¬μ€ μν€ν μ²λ μ νμ΄ μλ νμ 무기μ λλ€. μ€λ λ°°μ΄ λ΄μ©μ λ°νμΌλ‘ λλ§μ 첫 λ²μ§Έ μλ²λ¦¬μ€ APIλ₯Ό λμ보μκΈΈ λ°λλλ€!