π©κ°μ
μ¬λ΄ ERP μλΉμ€μ μ¬λ¬ μΌνλͺ° κΈ°λ₯μ μ°λνλ κ°μ μμ
μ μ§ννλ μ€, ν κ°μ§ νΉμ΄ν μ μ λ°κ²¬νμ΅λλ€. μ¬λ¬ μΌνλͺ° κ°μ΄λ°μμλ λ€μ΄λ²μ μ€λ§νΈμ€ν μ΄ μ°λμμλ§ μ λ
μ€ν¨ μλ΅μ΄ λΉλ²νκ² λ°μνκ³ μμμ΅λλ€.
μλ΅ λ©μμ§λ λλΆλΆ λμΌνμ΅λλ€.
“ν λΉλ μκ°λΉ μμ²λμ μ΄κ³Όνμμ΅λλ€.”
μ ν¬ μλΉμ€μμλ μ΄λ¬ν μ€ν¨ 건μ λ¨μ μ€λ₯λ‘ μ²λ¦¬νκ³ , μ¬μ©μμκ² “μ μ ν λ€μ μλν΄ λ¬λΌ”λ μλ΄λ§ μ 곡νκ³ μμμ΅λλ€.
μ λ μ€ν¨ λΉλκ° λ°λ³΅μ μΌλ‘ λ°μνλ μ μ΄ λ¨μν μΌμμ μ₯μ λ‘ λ³΄κΈ°μλ μ΄μνλ€λ μκ°μ΄ λ€μμ΅λλ€.
μμΈμ μΆμ ν΄λ³Έ κ²°κ³Ό, λ¬Έμ λ μλ² μ₯μ κ° μλλΌ νΈμΆ λ°©μ μ체μ μμμ΅λλ€.
λ€μ΄λ²μ μ€λ§νΈμ€ν μ΄λ API νΈμΆ νμ©λμ λμ μΌλ‘ μ ννκ³ μμμ§λ§, μ ν¬ μμ€ν
μ ν΄λΉ μ νμ κ³ λ €νμ§ μμ μ± μμ²μ μ§μμ μΌλ‘ μ μ‘νκ³ μμμ΅λλ€. κ·Έ κ²°κ³Ό μ€λ§νΈμ€ν μ΄ μλ² μΈ‘μμλ μ μμ μΈ λ°©μ΄ λ‘μ§μ λ°λΌ 429(Too Many Requests) μλ΅μ λ°ννκ³ , μ ν¬ μλΉμ€λ μ΄λ₯Ό μ€ν¨λ‘ μ²λ¦¬ν μλ°μ μμλ κ²μ
λλ€.
ν΄κ²° λ°©λ²μ μμΈλ‘ λ¨μνμ΅λλ€.
μ€λ§νΈμ€ν μ΄ API νΈμΆ μ μ 곡λλ νΈμΆ νμ©λ μ 보λ₯Ό κΈ°μ€μΌλ‘, λ¨μ νΈμΆ κ°λ₯ νμκ° μμ κ²½μ° μμ²μ μ μ λκΈ°(sleep)μν¨ λ€ λ€μ μκ° κ΅¬κ°μ λ€μ μμ²νλλ‘ νλ¦μ μ‘°μ νμ΅λλ€. μ΄ κ°μ λ§μΌλ‘λ μ΄μ κΉμ§ λΉλ²νκ² λ°μνλ API νΈμΆ μ€ν¨κ° κ±°μ λͺ¨λ μ¬λΌμ‘κ³ , μ¬μ©μ κ²½ν μμ λμ λκ² μμ νλμμ΅λλ€.
μ΄λ² μμ μ ν΅ν΄ μ λ λ€μ΄λ² μ€λ§νΈμ€ν μ΄κ° 'ν ν° λ²ν· μκ³ λ¦¬μ¦(Token Bucket Rate Limiting Algorithm)' μ κΈ°λ°μΌλ‘ ν λμ API νΈμΆ νμ©λ μ ν λ°©μμ μ£Όλͺ©νκ² λμμ΅λλ€. μ΄λ° κΈ°λ₯μ λ¨μν “μ ν μ μ± ”μ΄ μλλΌ, Open APIλ₯Ό μ 곡νλ νλ«νΌμ΄ λ€μμ ν΄λΌμ΄μΈνΈλ‘λΆν° μλ²λ₯Ό 보νΈνκΈ° μν λ§€μ° νμ€μ μ΄κ³ κ²μ¦λ μ€κ³λΌλ μ μ λκΌμ΅λλ€.
κ·Έλμ μ΄λ² κΈμμλ λ€μ΄λ² μ€λ§νΈμ€ν μ΄μ λμ API νΈμΆ νμ©λ μ ν λ°©μμ μ΄ν΄λ³΄λ©΄μ, ν ν° λ²ν· μκ³ λ¦¬μ¦μ΄ 무μμΈμ§, κ·Έλ¦¬κ³ λ§μ½ λ΄κ° μ΄ κΈ°λ₯μ ꡬννλ μ μ₯μ΄λΌλ©΄ μ΄λ»κ² μ€κ³νκ³ κ΅¬νν κ²μΈμ§λ₯Ό μ€μ¬μΌλ‘ μ 리ν΄λ³΄κ³ μ ν©λλ€.
λμ νΈμΆ νμ©λ μ ν”μ΄ νμν΄μ§ μ΄μ
APIλ₯Ό μ΄μνλ μ μ₯μμ κ°μ₯ 무μμ΄ μκ°μ λ κ°μ§μ λλ€.
- μμ κ°λ₯ν νμ£Ό
μ: μ€μ 10μ μ΄ν μ£Όλ¬Έμ΄ κΈμ¦, λ°μ£Ό λ§κ° μκ°, λκ·λͺ¨ νλ‘λͺ¨μ , λͺ μ μμ¦ λ±. - μμ λΆκ°λ₯ν νμ£Ό
μ: νΉμ μ루μ λ²κ·Έλ‘ 무ν μ¬μλ, μ₯μ μν©μμ μ¬μλ νλ°(thundering herd), λ°°μΉ μμ μ΄ ν μκ°μ λμμ μ€ν.
μ΄λ μλ²λ λ¨μν “CPUκ° λ°μλ€” μμ€μ΄ μλλΌ, DB 컀λ₯μ
ν κ³ κ°, μ€λ λ/μ΄λ²€νΈλ£¨ν μ μ, μΊμ λ―Έμ€ μ¦κ°, ν κ³ΌλΆν, νμμμ μ°μλ‘ μ΄μ΄μ§λλ€. λ μνν 건, νμ£Όκ° ν μ¬μ©μ(λλ ν μ루μ
)μμ μμν΄λ κ²°κ³Όλ νλ«νΌ μ 체 μ¬μ©μμκ² νμ°λλ€λ μ μ
λλ€. κ·Έλμ νλ«νΌμ “μ μ μ¬μ©μ λ³΄νΈ”λ₯Ό μν΄μλΌλ κ°μ μ μΈ μ ν μ₯μΉκ° νμν©λλ€.
λν μ¬κΈ°μ μ€μν νμ€μ΄ νλ μμ΅λλ€. APIλ “νκ· μ²λ¦¬λ”λ§μΌλ‘λ μμ νμ§ μμ΅λλ€. μ€μ μ₯μ λ “μκ° νΌν¬(λ²μ€νΈ)”μ “μ°μλ μ¬μλ”μμ λ°μν©λλ€.
μ¦, νλ«νΌμ νκ· μ μΌλ‘λ μΆ©λΆν μ²λ¦¬ κ°λ₯ν΄λ, “1μ΄ μ¬μ΄μ λͺ°λ¦¬λ μμ²”μ μ μ΄ν΄μΌ ν©λλ€.
μ΄ λ¬Έμ λ₯Ό νκΈ° μν λνμ μΈ λ°©λ²μ΄ ν ν° λ²ν· μκ³ λ¦¬μ¦μ λλ€.
πͺ£ν ν° λ²ν· μκ³ λ¦¬μ¦
ν ν° λ²ν·μ λ€νΈμν¬ νΈλν½ μ μ΄ λΆμΌμμ μμ λ κ° μ¬μ©λΌ μ¨ Rate Limiting μκ³ λ¦¬μ¦μ λλ€.
- λ±μ₯ λ°°κ²½: λ€νΈμν¬ QoS(Quality of Service), νΈλν½ μμ΄ν
- λͺ©μ : νκ· μ²λ¦¬μ¨μ μ ννλ©΄μ, μκ°μ μΈ burstλ νμ©
- μ¬μ© λΆμΌ:λΌμ°ν° / μ€μμΉ νΈλν½ μ μ΄, OS λ€νΈμν¬ μ€ν, API Gateway / Reverse Proxy
ν ν° λ²ν·(Token Bucket)μ μ΄μμ 보면 λ²ν·(bucket)μ ν ν°μ λ΄μλλ μ μ₯ 곡κ°μ΄κ³ , ν ν°(token)μ μμ² 1건μ μ²λ¦¬ν μ μλ κΆνμ λ§ν©λλ€.
λμ μ리λ λ§€μ° λ¨μν©λλ€.
- λ²ν·μ ν ν°μ΄ μΌμ μλλ‘ μ±μμ§ (μ: μ΄λΉ 10κ°)
- μμ² 1κ°λΉ ν ν° 1κ° μλΉ
- ν ν°μ΄ μμΌλ©΄ μμ² κ±°μ (429)
- λ€μ ν ν° μλ§νΌ κ°λΆν΄μ μ¬μ© κ°λ₯ → burst νμ©(λμ μ°μμ μΌλ‘ μ¬μ©μ λΆκ°)
ν ν° λ²ν·(Token Bucket) μκ³ λ¦¬μ¦μ΄ “API νΈμΆ μ ν”μ μ λ§λ μ΄μ λ λ€μκ³Ό κ°μ΅λλ€.
(1) μ΄λΉ μ²λ¦¬λμ λͺ
ννκ² “μ μ”ν μ μλ€.
ν ν°μ΄ μ΄λΉ Nκ° μ±μμ§λ©΄, μμ€ν
μ μ΄λΉ Nκ° μμ€μΌλ‘ μμ²μ μμ μ μΌλ‘ μ²λ¦¬νκ² λ©λλ€. μλ² μ
μ₯μμλ 리μμ€ μ¬μ©λ μνμ μ λ§λ€ μ μμ΅λλ€.
(2) μ§§μ λ²μ€νΈλ₯Ό “μ μ°νκ²” λ°μμ€ μ μλ€.
νμ€ νΈλν½μ μΌμ νμ§ μμ΅λλ€. ν ν°μ΄ μμ¬ μλ€λ©΄ μκ°μ μΌλ‘ λͺ κ° λ μ²λ¦¬ν΄λ μ 체 μμ μ±μ ν° λ¬Έμ κ° μμ΅λλ€. μ΄λ° “μ§§μ κΈμ¦”μ νμ©νλ©΄ ν΄λΌμ΄μΈνΈ μ²΄κ° μ±λ₯λ μ’μμ§λλ€.
(3) κ±°μ (HTTP 429)μ “μ μ±
μ μΌλ‘” μΌκ΄λκ² λ§λ€ μ μλ€.
"μ΄ APIμ λΉμ μ ν ν°μ΄ μμΌλ©΄ κ±°μ ". μ΄μ κ° λͺ
νν©λλ€.
μ΄ μΌκ΄μ±μ΄ ν΄λΌμ΄μΈνΈμκ²λ μ€μν©λλ€. μ λ§€νκ² νμμμμΌλ‘ μ£½λ κ²λ³΄λ€, “λ μ§κΈ λ무 λ§μ΄ 보λλ€(429)”κ° ν¨μ¬ μ€κ³νκΈ° μ½μ΅λλ€.
μ€λ§νΈ μ€ν μ΄μ 컀머μ€API νλ«νΌμ λ°λ‘ μ΄ ν ν° λ²ν· κΈ°λ°μΌλ‘ νΈμΆλμ ν΅μ ν©λλ€.
πμ€λ§νΈ μ€ν μ΄μ λμ API νΈμΆ νμ©λ μ ν λ°©λ²
μ€λ§νΈ μ€ν μ΄ μ»€λ¨Έμ€API νλ«νΌμ μ€λ§νΈμ€ν μ΄ νλ§€μ, 컀머μ€μ루μ
ꡬλ
μ λ± λ€μν μ¬μ©μ λΆλ€κ» μλΉμ€λ₯Ό μ 곡νλ λ²μ© API νλ«νΌμ
λλ€.
μμ μ μλΉμ€ μ 곡μ μν΄ λͺ¨λ API μ¬μ©μμκ² μκ°λΉ μ΅λ API νΈμΆ νμ μ νμ λΉ μ§μμ΄ μ μ©νμ¬ νΉμ μ¬μ©μκ° μμ€ν
μμμ κ³Όμ ν μ μλλ‘ μ€κ³λΌ μλ€κ³ ν©λλ€.
μ€λ§νΈ μ€ν μ΄ μ»€λ¨Έμ€APIλ 'ν ν° λ²ν· μκ³ λ¦¬μ¦Token Bucket Rate Limiting Algorithm'μ μ μ©νμ¬ API νΈμΆλμ μ νν©λλ€.
κ° κ³μΈ΅λ³λ‘ 1μ΄ λμ μ²λ¦¬κ° κ°λ₯ν API νΈμΆ νμλ₯Ό μ νμ¬ ν΄λΉ νμλ₯Ό μ΄κ³Όνλ API μμ²μ μ²λ¦¬ λΆκ° μλ΅μ λ°νν©λλ€. μ΄λ νΉμ κ³μΈ΅μ νΈμΆ νμκ° λ¨μμλλΌλ μμ κ³μΈ΅μ νΈμΆ νμκ° μ΄κ³Όλμλ€λ©΄ μ²λ¦¬ λΆκ° μλ΅μ λ°νν©λλ€.
컀머μ€API νλ«νΌμμ νΈμΆ νμ μ°μ κ³μΈ΅μ μλμ μ°μ μμλ₯Ό κΈ°μ€μΌλ‘ ν©λλ€.
- API μμ©λ
- μ ν리μΌμ΄μ λ³ νΈμΆ νμ©λ – Rate limit
- SELLER ν ν°λ³ νΈμΆ νμ©λ – Quota limit

APIλνμ¬μ λμ νΈμΆ νμ©λ μ€μ μ νΈμΆλ μ°μ μ β μ ν리μΌμ΄μ λ³ μ°μ (Rate limit), β‘ μ€ν μ΄ κ³μ λ³ μ°μ (Quota limit) μ΄μ€μΌλ‘ μ μ©λ©λλ€.
- Rate limit: κΈ°μ‘΄ μ ν리μΌμ΄μ 1κ°λ³ νμ©νλ νΈμΆ μ΄λ
- Quota limit: 'SELLER νμ ' μΈμ¦ ν ν° 1κ°λ³ νμ©νλ νΈμΆ μ΄λ
μ루μ /APIλνμ¬λ§λ€ λ€λ₯Έ νΈμΆ νμ©λμ μ 곡λ°μ΅λλ€.(μ¦, κ°μ APIμ΄λλΌλ μ루μ /APIλνμ¬λ³λ‘ λ€λ₯Έ νΈμΆ νμ©λ(ν ν° μ)μ΄ λ€λ₯Ό μ μμ΅λλ€.)
1οΈβ£API μμ©λ
API μμ©λμ “νΉμ APIκ° μ 체 μ¬μ©μ λμμΌλ‘ 1μ΄μ μ²λ¦¬ν μ μλ μ΄λ”μ
λλ€.
API μμ©λμ κ° APIλ³ κΈ°λ₯ νΉμ±κ³Ό κΈ°μ μ¬μμ λ°λΌ κ°κΈ° λ€λ₯Έ μμ©λμΌλ‘ μ€μ ν©λλ€. API μμ©λμ μλΉμ€ μ΄μ© μν©μ λ°λΌ μ λμ μΌ μ μμ΅λλ€.
API μμ©λμ μ΄κ³Όνλ νΈμΆ μμ²μ λν΄μλ HTTP 429 μλ΅μ λ°νν©λλ€. μ΄λ μ ν리μΌμ΄μ
λ³ νΈμΆ νμ©λ(Rate limit)μ΄ λ¨μμλμ§λ κ³ λ €νμ§ μμ΅λλ€.
νλ«νΌμ΄ μ λ§ μνν μκ°μλ “λλ μμ§ μΏΌν° λ¨μμΌλ μ²λ¦¬ν΄μ€κ²” κ°μ μ¬μ κ° μμ΅λλ€. μλ²κ° λ²ν°λ €λ©΄ μ 체 μνμ μ λ¨Όμ μ§μΌμΌ ν©λλ€.
μ¦, API μμ©λμ “μ 체 μμ‘΄”μ μν μ΅νμ μμ μ₯μΉμ
λλ€.
2οΈβ£μ ν리μΌμ΄μ λ³ νΈμΆ νμ©λ – Rate limit
'μ ν리μΌμ΄μ
'μ 컀머μ€API νλ«νΌμ APIλ₯Ό νΈμΆν λ νμν μ격 μ¦λͺ
μ 보 μΈνΈ(μ ν리μΌμ΄μ
ID/Secret)μ
λλ€.(λ€μ λ§ν΄ νΉμ μ ν리μΌμ΄μ
νλνλλ₯Ό λ»ν©λλ€.) νΉμ APIμ νΈμΆ νμ©λ μ΄κ³Ό μ¬λΆ νλ¨μ λμ APIμ λν μκ° κ΅¬κ°(1μ΄ λ²μ) λ΄ νΈμΆ νμλ₯Ό κΈ°μ€μΌλ‘ νλ©° μ΄λ νμ μ°μ μ μ ν리μΌμ΄μ
λ¨μλ‘ μΈ‘μ ν©λλ€.
μ ν리μΌμ΄μ
λ¨μμμ νΉμ APIμ λν 1μ΄λΉ νΈμΆ κ°λ₯ νμ(νΈμΆ νμ©λ)λ₯Ό "Rate limit" μ΄λΌ λΆλ¦
λλ€.
Rate limitμ μ΄κ³Όνλ νΈμΆ μμ²μ λν΄μλ HTTP 429 μλ΅μ λ°νν©λλ€.
μ΄λ° μ νμ μ ν μ루μ
μ΄ λ²κ·Έλ‘ ν APIλ₯Ό νμ£Ό νΈμΆν΄λ, κ·Έ μ±λ§ μ νμ κ±Έλ¦¬κ³ λ€λ₯Έ μ±μλ μν₯μ΄ μ€μ΄λλλ€.
λν, μ± λ¨μλ‘ κ³΅μ μ±λ ν보λ©λλ€.
3οΈβ£Burst Max
Burst Maxλ λ€μ 1μ΄μ Rate limitμ μλΉκ²¨ λΉλ €μ΅λλ€.
컀머μ€API νλ«νΌμμλ λμ μκ° λ²μ(1μ΄) λ΄ λ¨μ Rate limitμ μ΄κ³Όνλ API μμ²μ΄ λ°μν κ²½μ° μλμΌλ‘ Burst Max κΈ°λ₯μ νμ±ννμ¬ λ€μ 1μ΄ κ΅¬κ°μ Rate limitμ μλΉκ²¨ νΈμΆ νμλ₯Ό μ°μ ν©λλ€.
λ¨, Burst Maxλ μ°μνμ¬ μ¬μ©ν μ μμ΅λλ€.
4οΈβ£SELLER ν ν°λ³ νΈμΆ νμ©λ - Quota limit
Quota limitμ 'SELLER νμ ' μΈμ¦ ν ν° 1κ°λ³ νμ©νλ νΈμΆ μ΄λμ λλ€.(λ¨μ μκ°λΉ[1μ΄] νλ§€μ 리μμ€ μμ² μ μ ν)
Quota limitμ λμ λνμ¬ μμ€ν
μ μ΄μ©νλ νΉμ ν μ΅μ’
μ¬μ©μ(νλ§€μ)κ° ν λΉλ Rate limitμ κ³Όμ νμ¬ λ€λ₯Έ μ΅μ’
μ¬μ©μμ 컀머μ€API νΈμΆμ μ΄λ ΅κ² λ§λλ μΌμ μνν©λλ€.
Quota limitμ Rate limitμ λν μΌμ λΉμ¨λ‘ μ°μ λ©λλ€. λμ SELLER μΈμ¦ ν ν°μΌλ‘λ Quota limitμ μ΄κ³Όνλ API νΈμΆμ΄ λΆκ°λ₯ν©λλ€. Quota limitμ μ μ©μ λ°λ SELLER μΈμ¦ ν ν°λ€μ νΈμΆ νμ©λ μ΄ν©μ Rate limitμ μ΄κ³Όν μ μμ΅λλ€.
πͺ§APIλ³ νΈμΆ νμ©λ νμΈ
κ° APIλ³ νΈμΆ νμ©λμ API νΈμΆμ λν HTTP μλ΅ ν€λ(Response header)λ‘ μ 곡ν©λλ€.
- GNCP-GW-RateLimit-Replenish-Rate: κΈ°λ³Έ μ΄λΉ νΈμΆ νμ©λ μ
- GNCP-GW-RateLimit-Burst-Capacity: λ²μ€νΈ λ§₯μ€(Burst Max)λ‘ μ²λ¦¬ κ°λ₯ν μ΄λΉ νΈμΆ νμ©λ μ
- GNCP-GW-RateLimit-Remaining: λ¨μ νΈμΆ νμ©λ μ
- GNCP-GW-Quota-Period: νΈμΆ νμ©λμ λ¨μ μκ°(λνμ¬ μ ν리μΌμ΄μ : SECONDS κ°μΌλ‘ κ³ μ )
- GNCP-GW-Quota-Limit: λμ SELLER μΈμ¦ ν ν°μ νΈμΆ νμ©λ μ
- GNCP-GW-Quota-Remaining: λμ SELLER μΈμ¦ ν ν°μ λ¨μ νΈμΆ νμ©λ μ
μμ μλ΅
νΈμΆ νμ©λμ μ΄κ³Όνλ API νΈμΆ μν© (μ ν리μΌμ΄μ /SELLER μΈμ¦ ν ν°)
...μ ν리μΌμ΄μ
λ³ νΈμΆ νμ©λμ΄ λ€ λ κ²½μ° Remaining:"0"
GNCP-GW-RateLimit-Burst-Capacity:"4"
GNCP-GW-RateLimit-Replenish-Rate:"2"
GNCP-GW-RateLimit-Remaining:"0"
...SELLER ν ν°λ³ νΈμΆ νμ©λμ΄ λ€ λ κ²½μ° Remaining:"0"
GNCP-GW-Quota-Period:"SECONDS"
GNCP-GW-Quota-Limit:"4"
GNCP-GW-Quota-Remaining:"0"
...
πμμ μΌμ΄μ€

리μμ€ μλ²μμ μ 곡νλ Open API μ€ "/abc/xyz/{id}" λΌλ API κ° μκ³ , μ΄ API κ·Έλ£Ήμ κΆνμ κ°κ³ μλ λνμ¬ μ ν리μΌμ΄μ "A"κ° μμ΅λλ€.
κ·Έλ¦¬κ³ μ΄ A μ ν리μΌμ΄μ μ μ¬μ©νλ νλ§€μλ "μ΄μμ κ³Ό" "μμ€κ·Ό" 2λͺ μ΄ μμ΅λλ€.
κ°κ° API μμ©λμ 10 / μ ν리μΌμ΄μ λ³ νΈμΆ νμ©λ – Rate limitμ 4 / SELLER ν ν°λ³ νΈμΆ νμ©λ – Quota limit μ 2λΌκ³ κ°μ νκ² μ΅λλ€.
1οΈβ£ SELLER ν ν° λ³ νΈμΆ νμ©λμ μ΄κ³Όνλ κ²½μ°
1μ΄λΉ SELLER ν ν° λ³ νΈμΆ νμ©λμ 2μ λλ€. 1μ΄ λ΄μ μμ€κ·Ό μ λ¬κ° μλ νν°μΈ A μ ν리μΌμ΄μ μ ν΅ν΄ /abc/xyz/{id} μμ²μ 3 λ² λ³΄λλ€κ³ κ°μ νκ² μ΅λλ€. (Burst Maxμ 무μ)
- 첫λ²μ§Έ μμ² μ±κ³΅ / RateLimit-Remaining : 3 / Quota-Remaining : 1
- λλ²μ§Έ μμ² μ±κ³΅/ RateLimit-Remaining : 2 / Quota-Remaining :0
- μΈλ²μ§Έ μμ² μ€ν¨ / 429 μλ΅
μ΄λ μ ν리μΌμ΄μ νΈμΆ νμ©λμ΄ λ¨μλ€ νλλΌλ SELLER ν ν° λ³ νΈμΆ νμ©λμ μ΄κ³ΌνμκΈ° λλ¬Έμ μμ²μ μ€ν¨νκ² λ©λλ€.
2οΈβ£ μ ν리μΌμ΄μ λ³ νΈμΆ νμ©λμ μ΄κ³Όνλ κ²½μ°
17μ 03μ΄μ A μ ν리μΌμ΄μ μ¬μ©μ μμ€κ·Όκ³Ό μ΄μμ μ΄ λ§₯μ€ νμ©λμΈ 2νμ© μμ²μ 보λλ€κ³ κ°μ νκ² μ΅λλ€. μ΄λ λ€νΈμν¬ μ§μ°μ΄λ μ¬μλ μ²λ¦¬ λ±μ μ΄μ λ‘ 17μ 02.987 μ΄μ λ³΄λΈ μμ€κ·Ό μμ²μ΄ μλ²μλ 03μ΄μ λμ°©ν μ μμ΅λλ€.
A μ ν리μΌμ΄μ μ νΈμΆ νμ©λμ 4μΈλ° 03μ΄μ μ΄ 5νμ μμ²μ λ°μκΈ° λλ¬Έμ, μ΄ μ€ κ°μ₯ λ§μ§λ§ μμ²μ μ€ν¨ μ²λ¦¬λ©λλ€.
νλ«νΌμ “μκ° μ μ λ” κΈ°μ€μΌλ‘ Rateλ₯Ό κ³μ°νκΈ° λλ¬Έμ λλ€.
μ΄λ API μ΄ νΈμΆ νμ©λμ΄ 10μΌλ‘ μ΄ νΈμΆ νμ©λμ λ¨μλλΌλ μ ν리μΌμ΄μ λ³ νΈμΆ νμ©λμ μ΄κ³Ό νμκΈ° λλ¬Έμ μμ²μ μ€ν¨νκ² λ©λλ€.
3οΈβ£ APIλ³ νΈμΆ νμ©λμ μ΄κ³Όνλ κ²½μ°
"/abc/xyz/{id}" API μ μ΄ νΈμΆ νμ©λμ 10μ λλ€. μ΄λ μλΉμ€ νΌμ‘ μν©μ΄κ³ A μ ν리μΌμ΄μ μ μ¬μ©μ(νλ§€μ)μΈ μμ€κ·Ό, μ΄μμ μ΄ κ°κ° μμ²μ νλ²λ§ λ³΄λΈ λ€κ³ κ°μ νκ² μ΅λλ€.
νμ§λ§ A μ ν리μΌμ΄μ λ§κ³ , B,C,D μ ν리μΌμ΄μ μμ κ°κ° μ΄λ² μ΄ κ΅¬κ°μ 3μ μμ²μ λ³΄λΈ λ€κ³ νκ² μ΅λλ€.
μμ² μ μ μκ° μμλ B → C → D μ ν리μΌμ΄μ μ¬μ©μ → A μ ν리μΌμ΄μ μμ€κ·Ό → A μ ν리μΌμ΄μ μ΄μμ
B,C,D μ ν리μΌμ΄μ μ μμ²μ λͺ¨λ νμ©νμΌλ―λ‘ API μ νμ©λμ 1μ λλ€. A μ ν리μΌμ΄μ μ μμ€κ·Ό μμ²μ νμ© κ°λ₯νλ―λ‘ μ±κ³΅ν©λλ€. κ·Έ λ€μ A μ ν리μΌμ΄μ μ΄μμ μ APIλ³ νΈμΆ νμ©λμ μ΄κ³Όνμ¬ 429 μλ΅μ λ°κ² λ©λλ€.
π€ν ν° λ²ν· μκ³ λ¦¬μ¦μ νμ©νμ¬ μ§μ ꡬνν΄ λ³Έλ€λ©΄?
μ€λ§νΈ μ€ν μ΄μμ νμ©νλ κΈ°λ₯μ μ κ° κ΅¬νν΄λ³Έλ€λ©΄ μ΄λ»κ² ꡬνν΄λ³Όμ§ μμν΄ λ΄€μ΅λλ€. API μμ²μ μ²λ¦¬νλ 리μμ€ μλ²κ° λ¨μΌ μΈμ€ν΄μ€μΈμ§, ν΄λ¬μ€ν°(λΆμ° νκ²½) μΈμ§μ λ°λΌ νΈμΆ νμ©λ(Rate/Quota)μ ꡬννλ λ°©μμ μμ°μ€λ½κ² λ¬λΌμ§λλ€.
νμ§λ§ μ£Όλ ν΅μ¬μ νλμΈλ°μ. λ°λ‘ “μμ²μ΄ λ€μ΄μ¬ λλ§λ€ νμ©λμ μ°¨κ°νλ λ‘μ§μ λ°λμ μμμ (atomic) μ΄μ΄μΌ νλ€.” μ λλ€.
λ¨μΌ μλ²μμλ JVM/λ°νμ λ©λͺ¨λ¦¬ μμμ κ·Έ μμμ±μ ν보νλ©΄ λκ³ , λΆμ° νκ²½μμλ μ¬λ¬ λ Έλκ° λμΌ μνλ₯Ό 곡μ ν΄μΌ νλ―λ‘ Redis κ°μ μ€μ μν μ μ₯μμ μλ² μΈ‘ μμ μ€ν(Lua)μΌλ‘ ꡬμ±ν μ μμ΅λλ€.
1οΈβ£ λ¨μΌ μλ² νκ²½
λ¨μΌ μλ² νκ²½μμλ “νΈμΆ νμ©λ μν”κ° ν νλ‘μΈμ€ λ©λͺ¨λ¦¬ μμλ§ μ‘΄μ¬νλ©΄ λ©λλ€. μ¦, μ μμ μΌλ‘ 곡μ λλ μνλ μ±κΈν€ κ°μ²΄λ‘ λκ³ , ν ν°/μΉ΄μ΄ν° μ‘°μμ AtomicLong, AtomicInteger, νΉμ CAS μκ³ λ¦¬μ¦ κΈ°λ°μΌλ‘ μ§μ ꡬννλ©΄ λμμ± λ¬Έμ λ₯Ό ν΄κ²°ν μ μμ΅λλ€.
λ¨μΌ μλ²μ΄κΈ΄ νμ§λ§ μμ²μ λμλ‘ λ€μ΄μ΅λλ€. synchronized κ°μ λ½λ κ°λ₯νμ§λ§, QPSκ° λμμ§μλ‘ κ²½ν©μ΄ 컀μ§λλ€. ν ν°μ μλ₯Ό λ³νμν€λ 건 κ°λ²Όμ΄ μμ μ΄λ―λ‘ ν ν° λ²ν· μνλ₯Ό νλμ κ΅¬μ‘°λ‘ λ³΄κ³ , λ½μ κ±°λ κ²μ΄ μλ CAS μκ³ λ¦¬μ¦μ μ¬μ©νλ©΄ λ§€μ° κ°λ³κ² ꡬνν μ μμ΅λλ€.
νμ§λ§ μ΄λ° λ°©λ²μ μλ²κ° 2λλ‘ λμ΄λλ μκ°, κ° μλ²κ° λ
립λ ν ν°μ κ°κ² λμ΄ “μ 체 νμ©λ”μ 컨νΈλ‘€ ν μ μκ² λ©λλ€. λν μλ² μ¬μμ μ μνκ° μ΄κΈ°νλλ€λ λ¨μ λ μμ΅λλ€.
μ΄λ° λ°©μμ 리μμ€ μλ²κ° λ¨μΌ μΈμ€ν΄μ€λΌλ μ μ κ° μ μ§λ λλ§ μμ ν λ΅μ
λλ€.
2οΈβ£ λΆμ° νκ²½

λΆμ° νκ²½μμλ Redis + Luaλ‘ “μ μ μμμ±”μ λ§λ€μ΄ ꡬνν μ μμ κ±°λΌ μκ°λ©λλ€.
리μμ€ μλ²κ° μ¬λ¬ λλ‘ νμ₯λλ μκ°, κ°μ₯ λ¨Όμ κΉ¨μ§λ κ²μ΄ “νμ©λ μνμ μΌκ΄μ±”μ λλ€. μλ² Aμ μλ² Bκ° λμμ ν ν°μ μ°¨κ°ν λ, λμ΄ κ°μ μνκ°μ λ°λΌλ³΄μ§ μμΌλ©΄ μ΄λ° μμ²λ μ νμ΄ λ¬΄μλ―Έν΄μ§λλ€. κ·Έλμ λΆμ° νκ²½μμλ “μ μ μν”λ₯Ό ν κ³³μ λͺ¨μμΌ νκ³ , κ·Έ μν κ°±μ μ κ²½μ 쑰건 μμ΄ μμμ μΌλ‘ μ΄λ€μ ΈμΌ ν©λλ€.
μ¬κΈ°μ Redisκ° κ°λ ₯ν μ΄μ λ λ κ°μ§μ λλ€.
- μ€μ μν μ μ₯μλ‘μμ μν : λͺ¨λ λ Έλκ° κ°μ λ²ν· μνλ₯Ό λ³Έλ€.
- μλ² μΈ‘ μμ μ€ν: Lua μ€ν¬λ¦½νΈλ₯Ό Redis λ΄λΆμμ μ€ννλ©΄, μ€ν¬λ¦½νΈκ° λλ λκΉμ§ λ€λ₯Έ λͺ λ Ήμ΄ λΌμ΄λ€μ§ μμ “ν ν° κ° νμΈ + μ°¨κ°”μ νλμ νΈλμμ μ²λΌ μ²λ¦¬ν μ μλ€.
μ²μμλ “λΆμ°λ½μ μ‘κ³ ν ν°μ μ°¨κ°”μ λ μ¬λ¦¬κΈ° μ½μ΅λλ€. νμ§λ§ λ§€ μμ²λ§λ€ λ½μ μ‘λ ꡬ쑰λ λ½ κ²½ν©κ³Ό λ€νΈμν¬ μ볡μΌλ‘ μΈν΄ μ²λ¦¬λμ΄ λ¨μ΄μ§κΈ° μ½μ΅λλ€. λ°λ©΄ Redis Luaλ
- λ²ν· μ‘°ν
- refill κ³μ°
- μ°¨κ°
- μ μ₯
- κ²°κ³Ό λ°ν
μ ν λ²μ νΈμΆλ‘ μ²λ¦¬ν μ μμ΄, λ½ μμ΄λ λμμ± λ¬Έμ κ° μ¬λΌμ§λλ€.
λν, λΆμ° νκ²½μμ μ΄ κ²½κ³λ§λ€ μΉ΄μ΄ν°λ₯Ό μ΄κΈ°ννλ λ°©μμ λ λΉν¨μ¨μ μ΄λΌ μκ°ν©λλ€. μ¬λ¬ μλ²/μ€μΌμ€λ¬κ° κ°μ λλ©΄μ μ½κ°μ μ§μ°μ΄ μκΈ°κ³ , κ²½κ³ μμ μ μ€λ₯κ° μμ μ μμ΅λλ€. κ·Έλμ Redisμμλ λ¨μΌ μλ²μ λμΌνκ² λ§μ§λ§ refill μκ°μ μ μ₯νκ³ κ³μ°μΌλ‘ μ±μ°λ λ°©λ²μ΄ λμ κ² κ°μ΅λλ€.
ν€ μ€κ³λ κ³μΈ΅ ꡬ쑰λ₯Ό λ°μνλ©΄ λ©λλ€.
- μ ν리μΌμ΄μ Rate limit: rl:{app_id}:{api}
- SELLER Quota limit: ql:{seller_token}:{api}
μ€λ§νΈμ€ν μ΄μ²λΌ Rateμ Quotaκ° λμμ μ‘΄μ¬νλ©΄, “λ λ€ ν΅κ³Όν΄μΌ νμ©”μ΄ κΈ°λ³Έ κ·μΉμ
λλ€.
νλμ Lua μ€ν¬λ¦½νΈμμ Rate/Quota λ²ν·μ λμμ refill + 체ν¬νκ³ , λ λ€ μ±κ³΅μΌ λλ§ λ λ€ μ°¨κ°ν΄μΌ ν©λλ€.
μ΄λ κ² νλ©΄ λΆμ° νκ²½μμλ μΌκ΄μ±μ΄ μ μ§λ©λλ€.
κ²°κ΅ λ¨μΌ μλ²μ λΆμ° νκ²½μ μ°¨μ΄λ μμμ±μ 보μ₯νλ μ΅μ μ λ°©λ²μ λ°λΌ λ¬λΌμ§κ² λ©λλ€.
- λ¨μΌ μλ²: μλ‘μ΄ μΈλΆ μ»΄ν¬λνΈ(μΊμ/DB/Redis λ±)μ μ¬μ©νμ§ μκ³ νλ‘μΈμ€ λ©λͺ¨λ¦¬ μμμ Atomic/CASλ‘ ν΄κ²°
- λΆμ° νκ²½: 곡μ μ μ₯μ(Redis)λ‘ μνλ₯Ό λͺ¨μΌκ³ , Lua μ€ν¬λ¦½νΈλ‘ μλ² μΈ‘ μμ μ€ν
πμ°Έκ³
https://github.com/commerce-api-naver/commerce-api/discussions/6
μ¬μ©λ μ ν λλ νΈμΆλ μ νμ΄ μλμ? · commerce-api-naver commerce-api · Discussion #6
Q. μ¬μ©λ μ ν λλ νΈμΆλ μ νμ΄ μλμ? A. APIλ³ μ΄λΉ νΈμΆ νμλ₯Ό μ°μ νμ¬ μ ν΄μ§ νμ μ΄μμ νΈμΆμ μ νν©λλ€. Noteμ΄ κ²μκΈμμλ μ€λ§νΈμ€ν μ΄ νλ§€μκ° μ»€λ¨Έμ€APIμΌν°μμ μμ μ΄ μ΄
github.com
https://github.com/commerce-api-naver/api-agency/discussions/12
[μ€μ] 'λμ νΈμΆ νμ©λ' μ λ©΄ μ μ© μλ΄ · commerce-api-naver api-agency · Discussion #12
λμ νΈμΆ νμ©λ μ λ©΄ μ μ© 'λμ νΈμΆ νμ©λ'μ κ° APIλ³ νΈμΆ νμ©λμ κ°λ³μ μΌλ‘ μ μ©νλ κΈ°λ₯μ λλ€. 컀머μ€API νλ«νΌ μλΉμ€λ₯Ό ꡬμ±νλ μ¬λ¬ μμλ€μ κ³ λ €ν κ° APIλ³ νΈμΆ νμ©λ μ
github.com
https://apicenter.commerce.naver.com/docs/restriction
μ μ½ μ¬ν | 컀머μ€API
μ μ½ μ¬ν 컀머μ€APIμ κ° κΈ°λ₯λ³ μ€λͺ μμμμλ λ€μκ³Ό κ°μ΄ 'μ μ½ μ¬ν'μ λν΄μ μλ΄ν©λλ€. μΉ μλ² μΈμ¦μ(TLS) λ²μ μ μ½β 컀머μ€APIλ μΉ μλ² μΈμ¦μ(TLS) λ²μ 1.2 μ΄μμμλ§ μ μ λμ
apicenter.commerce.naver.com
https://github.com/commerce-api-naver/api-agency/discussions/23
λμ νΈμΆ νμ©λ μ λ©΄ μ μ©μ λ°λ₯Έ λνμ¬ λμ μ¬ν · commerce-api-naver api-agency · Discussion #23
Noteλ³Έ κ²μκΈμμμ λͺ¨λ λ΄μ©μ μ¬μ μ λμ νΈμΆ νμ©λ μ λ©΄ μ μ©κ³Ό κ΄λ ¨ν 곡μ§μ¬ν λ΄μ©μ μ΄ν΄ν κ²μ κ°μ νμ¬ μ€λͺ ν©λλ€. 1. μλΉμ€ νΌμ‘μ λ°λ₯Έ HTTP 429 μλ΅ λμ (4/1) κ° APIλ₯Ό μ²λ¦¬ν
github.com
λκΈ