μ΄λ² ν¬μ€ν μμλ μ μ§μ₯μμ μ§ννλ DB Function λ‘μ§μ Java ApplicationμΌλ‘ μ΄κ΄νλ μμ μ λν΄ μ 리νκ³ μ ν©λλ€. μκ°μ΄ λ€μ νλ μ§λ§, μ΄ μμ κ³Όμ μ λλμλ³΄κ³ μ νλ λͺ©μ λ μκ³ , μ μ¬ν μμ μ μ§νν λ μ°Έκ³ ν μ μλλ‘ νΈλ¬λΈμν λ° κ³ λ € μ¬ν λ±μ μ λ¦¬ν΄ λ³΄λ € ν©λλ€.
ν¬μ€ν μ κ°μ - κ³Όμ - κ²°κ³Ό(μ±κ³Ό) - νκ³ μμΌλ‘ ꡬμ±νμμ΅λλ€.
κ°μ
κΈ°μ‘΄μ DB Functionμ μΏ ν° λ°κΈ APIλ₯Ό μ²λ¦¬νλ ν¨μλ‘, μΈλΆ μ ν΄μ¬κ° λ°κΈ μμ²μ νλ©΄ λ΄λΆμ μΌλ‘ μ¬λ¬ νλ‘μμ λ€μ μμ°¨μ μΌλ‘ νΈμΆνμ¬ κ²μ¦, λ‘κΉ , INSERT, UPDATE λ± μΏ ν° λ°κΈμ μ²λ¦¬νλ λ‘μ§μ΄μμ΅λλ€. νμ§λ§ μ΄ λ‘μ§μλ μ¬λ¬ λ¬Έμ κ° μμκ³ , μ΄λ₯Ό κ°μ νκΈ° μν΄ μ΄λ² μμ μ μ§ννκ² λμμ΅λλ€.
DB Functionμ΄ κ°μ§κ³ μλ μ£Όμ λ¬Έμ μ μ λ€μκ³Ό κ°μ΅λλ€.
- λλ²κΉ μ μ΄λ €μ: DB ν¨μλ‘ μμ±λ λ‘μ§μ΄λΌ λλ²κΉ μ΄ κ±°μ λΆκ°λ₯ν μν©μ΄μμ΅λλ€.
- μ¬λ‘μ° μΏΌλ¦¬ λ°μ: κ°νμ μΌλ‘ μ¬λ‘μ° μΏΌλ¦¬κ° λ°μνκ³ μμΌλ μ νν μ΄λ μ§μ μμ λ³λͺ©μ΄ λ°μνλμ§ νμ νκΈ°κ° μ΄λ €μ μ΅λλ€.
- μ μ§ λ³΄μμ μ΄λ €μ: λΆνμν 쿼리문μ΄λ 무μλ―Έν λ‘κ·Έ ν μ΄λΈ μ μ₯, λΆνμν μΆκ° μ‘°ν 쿼리, νλ‘μμ λ΄μ ꡬνλ μ¬μλ(retry) λ‘μ§ λ± λΉν¨μ¨μ μΈ λΆλΆμ΄ λ€μ μ‘΄μ¬νμ΅λλ€.
- μ€λ κΈ°κ° λ°©μΉλ μ½λ: μ€λ«λμ μ½λκ° κ°μ λμ§ μμκΈ°μ νμ€ν 리 κ΄λ¦¬κ° λμ§ μκ³ , μ£Όμκ³Ό μ€μ λ‘μ§μ΄ λΆμΌμΉνλ λ±μ λ¬Έμ μ μ΄ μ‘΄μ¬νμ΅λλ€.
μ΄μ κ°μ λ¬Έμ λ€λ‘ μΈν΄ DB Function λ‘μ§μ Java ApplicationμΌλ‘ κ°μ νλ μμ μ μ§ννκ² λμμ΅λλ€.
κ³Όμ
κ°μ μμ μ κ³Όμ μ λ€μκ³Ό κ°μ΅λλ€.
- κΈ°μ‘΄ λ‘μ§ λΆμ
- μ΄κ΄ μΌμ μ립
- μ μ§μ μ΄κ΄ (νλ‘μμ λ¨μ)
- κ°μ
- ν μ€νΈ
- λ°°ν¬, λ‘€λ°±, λͺ¨λν°λ§
- νΈλ¬λΈ μν
λν Javaλ‘ μ΄κ΄ μμ μ μ§ννλ©΄μ κ³ λ €ν΄μΌ νλ μ¬νλ€μ λ€μκ³Ό κ°μ΅λλ€:
- κΈ°μ‘΄μ λ‘μ§κ³Ό μ κ· λ‘μ§μ κ²°κ³Όκ° λμΌνμ§ μ΄λ»κ² κ²μ¦ν κ²μΈκ°? (ν μ€νΈ)
- μ΄μ νκ²½μλ μ΄λ»κ² λ°°ν¬λ₯Ό ν κ²μΈκ°? (λ°°ν¬ μ λ΅)
- λ°°ν¬ ν μ₯μ κ° λ°μνμ λ νμ²λ¦¬ λ°©μμ μ΄λ»κ² ν΄μΌ νλκ°? (λ°μ΄ν° μ ν©μ±, λ‘€λ°± μ λ΅ λ±)
μ λͺ©λ‘λ€μ λ°νμΌλ‘ ꡬ체μ μΌλ‘ μ 리ν΄λ³΄κ² μ΅λλ€.
κΈ°μ‘΄ λ‘μ§ λΆμ
κΈ°μ‘΄ DB FunctionμΌλ‘ μμ±λ λ‘μ§μ λ€μκ³Ό κ°μ΅λλ€.
(νλ‘μμ λͺ , νλλͺ λ± μ£Όμ λ΄μ©λ€μ λΈλΌμΈλ μ²λ¦¬νμμ΅λλ€ ^^;)
λλ΅μ μΌλ‘ μμ² μ 보 μ μ₯, μ ν¨μ± κ²μ¦, λ²νΈ μ‘°ν λ° λ°κΈ μ²λ¦¬, μνμ€ μ‘°ν, μΏ ν° λ°ν μ²λ¦¬ λ±μ κ³Όμ μ μμ°¨μ μΌλ‘ μ²λ¦¬ν©λλ€.
μ΄λ―Έμ§λ₯Ό ν΅ν΄ ν° νλ¦μ νμ ν μ μμμΌλ, μμ λ§μλλ¦° κ²μ²λΌ νμ€ν 리 κ΄λ¦¬κ° μ λλ‘ μ΄λ£¨μ΄μ§μ§ μμμ΅λλ€. μ΄λ‘ μΈν΄, νλ‘μμ 쿼리 μ²λ¦¬ κ³Όμ μμ μ΄ν΄λμ§ μλ λΆλΆμ λν΄μλ ν μ€νΈ μΌμ΄μ€λ₯Ό μΆκ°νμ¬ μ΄ν΄λλ₯Ό λμ¬κ°μ΅λλ€.
(μ€μ ν μ€νΈ κ³Όμ μμ, νλ‘μμ λ‘μ§μ΄ λ³λμ νΈλμμ μμ μ²λ¦¬λμ΄ μ€νλ§ ν μ€νΈμμ μ¬μ©νλ @Transactionalμ΄ λ‘€λ°± λμ§ μλ μ΄μκ° λ°μνκΈ°λ νμ΅λλ€.)
μ΄λ¬ν κ³Όμ μμ κΈ°μ‘΄ νλ‘μμ λ‘μ§μ λΆμν΄ λ³΄λ μ£Όμκ³Ό μ€μ λ‘μ§μ΄ λ€λ₯Έ κ²½μ°λ λ§μκ³ , μμ μΈκΈν κ²μ²λΌ μ¬μ©λμ§ μλ μ½λλ λΉν¨μ¨μ μΈ λ‘μ§λ€μ΄ λ€μ μ‘΄μ¬νμ΅λλ€. μ΄λ‘ μΈν΄ κ°μ μμ μ λμ± λΉ λ₯΄κ² μ§νν νμμ±μ λλΌκ² λ κ² κ°μ΅λλ€.
μ΄κ΄ μΌμ μ립
μ΄κ΄ μΌμ μ κ° νλ‘μμ μ κ·λͺ¨μ λ°λΌ μ‘°κΈμ© λ€λ₯΄κ² μ‘μκ³ , λ€λ₯Έ μ 무λ λ°μν μ μλ μ¬μ΄λ μ΄ννΈλ μ¬μ μλ μΌμ μ μ€μ νκ³ μμ μ μ§ννμ΅λλ€.
μ μ§μ μ΄κ΄ (νλ‘μμ λ¨μ)
μ΄κ΄μ μ μΌμ μ²λΌ νλ‘μμ λ¨μλ‘ νλμ© μ΄κ΄νμμ΅λλ€.
As-Is) κΈ°μ‘΄μλ μ ν리μΌμ΄μ μ΄ DB Functionμ νΈμΆνκ³ , κ·Έ μμμ μ¬λ¬ νλ‘μμ λ€μ λ΄λΆμ μΌλ‘ νΈμΆνλ ꡬ쑰μμ΅λλ€.
To-Be) μ΄λ₯Ό μ ν리μΌμ΄μ μ΄ κ°κ°μ νλ‘μμ λ€μ μμ°¨μ μΌλ‘ μ§μ νΈμΆνλλ‘ μμ νλλ°, μ΄ κ³Όμ μμ μμμΉ μκ² μ¬λ‘μ° μΏΌλ¦¬μ μμΈμ λ°λ‘ νμ ν μ μμμ΅λλ€.
κΈ°μ‘΄ λ‘μ§μλ DB Function νΈμΆλ§ λͺ¨λν°λ§μ μ‘νκΈ°μ SQL 쿼리 건μκ° 1νλ‘λ§ κΈ°λ‘λμκΈ°μ μ 체 쿼리 κ²°κ³Όλ§ νμΈν μ μμμ§λ§, λ‘μ§ λ³κ²½ νμλ κ° νλ‘μμ μ μΏΌλ¦¬κ° κ°λ³μ μΌλ‘ λͺ¨λν°λ§λμκΈ° λλ¬Έμ, μ΄λ νλ‘μμ μμ λ³λͺ©μ΄ λ°μνλμ§ μ νν νμ ν μ μμμ΅λλ€.
κ°μ
μ¬λ‘μ° μΏΌλ¦¬μ μμΈμ MAX() ν¨μ μ¬μ©κ³Ό λΉν¨μ¨μ μΈ retry λ‘μ§ κ΅¬ν λ±μΌλ‘ μΈν΄ λ°μνκ³ μμμ΅λλ€.
# νλ‘μμ λ‘μ§
SELECT MAX(SEQ) FROM ... WHERE μν_ID = ? AND ...
INSERT ...
# μμΈ λ°μ μ (retry = 1)
SELECT MAX(SEQ) FROM ... WHERE μν_ID = ? AND ...
INSERT ...
# μμΈ λ°μ μ (retry = 2, SEQ = SEQ + 1)
SELECT MAX(SEQ) FROM ... WHERE μν_ID = ? AND ...
INSERT ...
# μμΈ λ°μ μ (retry = 3, SEQ = SEQ + 1)
SELECT MAX(SEQ) FROM ... WHERE μν_ID = ? AND ...
INSERT ...
...
μ λ κ² κ΅¬νλ νμ€ν 리κΉμ§λ μ μ μμ§λ§, μ‘°ν 쑰건μμ μ¬μ©λ WHERE μ μ 컬λΌμ λ³΅ν© μΈλ±μ€λ‘ μ€μ λμ΄ μμμ΅λλ€. νμ§λ§ SEQκ° μΈλ±μ€μ ν¬ν¨λμ§ μμκΈ° λλ¬Έμ λ°μ΄ν°κ° μ¦κ°ν μλ‘ μ±λ₯μ΄ μ νλλ λ¬Έμ κ° λ°μν©λλ€. μ΄λ λ°κΈμ΄ μ΄λ£¨μ΄μ§ λλ§λ€ ν΄λΉ ν μ΄λΈμ λμ ν΄μ μμ΄κΈ° λλ¬Έμ, λ°κΈλμ΄ λ§μ μνμΌμλ‘ λ λ§μ λ°μ΄ν°κ° μμ΄λ μν©μ΄μμ΅λλ€.
μμμ μ€νλλ `μν_ID`μ ν΄λΉνλ μνλ€μ μ΄ν΄λ³΄λ, λ°κΈλμ΄ μλμ μΌλ‘ λ§μ μνλ€μ λͺ¨λ λμΌν SEQ κ°μ λ°ννκ³ μμμ΅λλ€. SEQ κ°μ μλ₯Ό λ€μ΄ A01λΆν° Z99κΉμ§(A02, A03 ... Z99) 1μ© μ¦κ°νλ©΄μ λ§λ€μ΄μ§κΈ° λλ¬Έμ, λ°κΈμ΄ μμ£Ό λ°μνλ κ²½μ° ν΄λΉ μνμ SEQ κ°μ λͺ¨λ 'Z99'λ‘ λμΌν κ²°κ³Όλ₯Ό λ°νν©λλ€.
μ μ¬λ‘μ° μΏΌλ¦¬λ₯Ό κ°μ νκΈ° μν΄ 1) 쿼리 κ°μ , 2) μΊμ± μ μ©, 3) μΈλ±μ€ μΆκ° μΈ κ°μ§ λ°©λ²μΌλ‘ μ κ·Όνμμ΅λλ€.
μ¬μ€ κ·Όλ³Έμ μΈ ν΄κ²°μ± μ μΈλ±μ€λ₯Ό μΆκ°νλ κ²μ΄μ§λ§, μΈλ±μ€ μμ μ DBA λΆμ΄ μ§νν΄μΌ νκΈ°μ μ΅μ 1~2μ£Όκ° μμλλ μμ μ λλ€. λν ν΄λΉ ν μ΄λΈμ λ°μ΄ν°λ μλ ~μμ λ κ° λμ λμκΈ°μ μΈλ±μ€ μΆκ°λ₯Ό μν΄μλ κ³Όκ±° λ°μ΄ν° μμ κ° λ¨Όμ νμνμ΅λλ€. μ΄ μμ λν 2~3μ£Όλ μμλλ μν©μ΄μκΈ°μ, λ°μ΄ν° μμ λ° μΈλ±μ€ μμ μ΄ μ²λ¦¬λλ λμ, μΊμ±μ μ μ©νμ¬ κ°μ νκ³ μ νμ΅λλ€.
1) 쿼리 κ°μ
쿼리 κ°μ μ μ΄μ μ μ½μλ μΉμ ν SQL νλ λ΄μ©μμ 'Top N' 쿼리λ₯Ό μ μ©ν μ μμ κ² κ°μμ΅λλ€.
μ λ΄μ©μ κΈ°λ°μΌλ‘ κΈ°μ‘΄ 쿼리μ κ³ λ―Όνλ 쿼리λ λ€μκ³Ό κ°μ΅λλ€.
# κΈ°μ‘΄
SELECT NVL(MAX(SEQ), '0')
FROM ...
WHERE μν_ID = ? AND ...
SORT AGGREGATEλ μ 체 λ‘μ°λ₯Ό λμμΌλ‘ μ§κ³λ₯Ό μνν λ λνλλ νλμ
λλ€.
λλ΅μ μΌλ‘ μμ κ°μ΄ μνμ΄ λλλ°μ, λ°λΌμ κΈ°μ‘΄μ MAX(SEQ) 쿼리λ μ 체 λ‘μ°λ₯Ό λμμΌλ‘ μννλ κ² κ°μ΅λλ€.
# Top N
SELECT SEQ
FROM (
SELECT SEQ
FROM ...
WHERE μν_ID = ? AND ...
ORDER BY SEQ DESC
)
WHERE ROWNUM = 1;
COUNT(STOPKEY)μμ ROWNUMμΌλ‘ μ§μ λ 건μλ§νΌ λ μ½λλ₯Ό μ»μΌλ©΄ λ°λ‘ λ©μΆ κ²μΌλ‘ μμμ νμ§λ§, κ·Έ μλ λΆλΆμSORT(ORDER BY STOPKEY)κ° μ‘΄μ¬νλ κ²μΌλ‘ 보μ μ 쿼리μμλ λ°μ΄ν° μ λ ¬μ΄ νμν©λλ€. κ·Έλ¬λ SEQκ° μΈλ±μ€λ‘ μ€μ μ΄ λμ΄ μμ§ μκΈ° λλ¬Έμ κ²°κ΅ SEQ κΈ°μ€μΌλ‘ λ°μ΄ν° μ λ ¬μ΄ νμνκ³ , μ΄λ‘ μΈν΄ κ°μ ν¨κ³Όλ₯Ό λ³΄μ§ λͺ»νμ΅λλ€.
κΈ°μ‘΄ 쿼리λ μ΅λκ°μ κ³μ°νμ§λ§, λ λ²μ§Έ 쿼리λ μ λ ¬λ λ°μ΄ν° μ€ μ²« λ²μ§Έ κ°μ κ°μ Έμ€λ λ°©μμ΄λΌκ³ μ΄ν΄νκ³ , κ·Έλ‘ μΈν΄ SEQκ° κΈ°μ‘΄ μΈλ±μ€μ ν¨κ» λ³΅ν© μΈλ±μ€λ‘ μ€μ λλ€λ©΄ μ λ ¬ μμ΄ λΉ λ₯΄κ² κ°μ Έμ¬ μ μκΈ°μ, κ²°κ΅ μΈλ±μ€κ° νμν μν©κ³Ό λμΌνλ€κ³ νλ¨νμ΅λλ€.
2) μΊμ± μ μ©
μν μ€ λ°κΈμ΄ μμ£Ό λ°μνκ³ SEQ κ°μ΄ λμΌν μνμ λν΄μλ μΊμ±μ μ μ©νμ¬ μμ μ¬λ‘μ° μΏΌλ¦¬κ° λ°μνλ νλ‘μμ λ‘μ§μ νΈμΆνμ§ μλλΌλ μ ν리μΌμ΄μ λ¨μμ λΉ λ₯΄κ² μ²λ¦¬λ μ μλλ‘ νμ΅λλ€.
ν΄λΉ λ°μ΄ν°(SEQ)λ ν λ² μ΅λκ°μ λλ¬νλ©΄ κ° μμ²΄κ° κ°±μ λμ§ μκ³ , μν λν μΆκ°λμ§ μλ μν©μ΄κΈ° λλ¬Έμ μΆκ°μ μΈ μμ
λ° μ΄μμ΄ νμν κΈλ‘λ² μΊμ±μ ν¬κ² κ³ λ €νμ§ μμμ΅λλ€.
λΆμ° μλ²λ₯Ό μ΄μ μ€μ΄μ§λ§ λ°μ΄ν°μ κ°±μ μ΄λ μμ μμ
λ μμκΈ°μ λ‘컬 μΊμ(EhCache, Caffeine) λ±λ λμ
νμ§λ μμμ΅λλ€.
3) μΈλ±μ€ μΆκ°
μΈλ±μ€ μΆκ°λ₯Ό μν΄μλ λ¨Όμ λ°μ΄ν° μμ κ° νμν μν©μ΄μμ΅λλ€. λ°λΌμ κ³Όκ±° nλ μΉμ λ°μ΄ν°λ₯Ό λ¨Όμ μμ ν ν, μ΄νμ SEQ κ°μ λν΄ μΆκ°μ μΈ λ³΅ν© μΈλ±μ€λ₯Ό μ€μ νμμ΅λλ€.
κ°μ κ²°κ³Ό
μ μμ λ€μ μ²λ¦¬ν κ²°κ³Ό, μ 체 νΈλν½ μ€ μΌλΆλ§ μ κ· λ‘μ§μΌλ‘ μ μ λκ³ μμ΄ κΈ°μ‘΄ λ‘μ§κ³Ό μ κ· λ‘μ§μ μλ μ°¨μ΄κ° νμ°νκ² μ‘΄μ¬ν©λλ€.
ν μ€νΈ
ν μ€νΈλ λμΌν μμ²κ°μΌλ‘ κΈ°μ‘΄ λ‘μ§κ³Ό μ κ· λ‘μ§μ κ°κ° νΈμΆν ν, κ²°κ³Όμ λ°μ΄ν° μ ν©μ±μ΄ λμΌνμ§λ₯Ό λΉκ΅νλ μλμ λ°©μμΌλ‘ κ²μ¦μ νμ΅λλ€.
μλμ(shadowing)μ, λμΌν μμ²μ λν΄ κΈ°μ‘΄ μλΉμ€μ μλ‘μ΄ μλΉμ€μ μλ΅μ΄ μΌμΉνλμ§ λΉκ΅νλ λ°©λ²μ μλ―Έν©λλ€.
λ°μ΄ν°κ° Insertλ Update λλ ν μ΄λΈμ΄ λ§μ§λ μμκΈ°μ μ§μ λ°μ΄ν°λ₯Ό νμΈν μ μλλ‘ SQL ν νλ¦Ώμ λ§λ€κ³ κ° νΈμΆλ§λ€ λΉκ΅νλ©° μμ μ μ§ννμλλ°μ, ν μ€νΈλ₯Ό μ§νν λλ§λ€ λ§€λ² μΏΌλ¦¬λ₯Ό μ§μ μ€νν΄μ λΉκ΅νλ μμ μ΄ λ²κ±°λ‘μ κΈ°μ, μ΄λ₯Ό κ°μννκΈ° μν΄ μ ν리μΌμ΄μ λ΄μμ λΉκ΅νλ λ©μλλ₯Ό ꡬννμ΅λλ€. μ΄λ₯Ό ν΅ν΄ APIκ° νΈμΆλ λλ§λ€ κ³Όκ±° λ‘μ§κ³Ό μ κ· λ‘μ§μ λμμ νΈμΆνκ³ , λ°μ΄ν° μ ν©μ±μ μλμΌλ‘ λΉκ΅νμ¬ μ’ λ νΈλ¦¬νκ² λΉκ΅ν μ μμμ΅λλ€.
μμ μ μ§ννλ©° λ± ν¬μλ¬λλ μ΄λ»κ² λ κ±°μ μλΉμ€λ₯Ό λ°μ΄ λ΄λκ° λΌλ ν¬μ€ν μ μ°Έκ³ νλλ°, ν΄λΉ λΈλ‘κ·Έμμλ κΈ°μ‘΄ μλΉμ€μ μ κ· μλΉμ€ μλ΅μ λν μ€ν―(statsd)μ κΈ°λ‘νκ³ , μ€μ κ°μ μ°¨μ΄λ ν€λ°λ(Kibana)μ λ‘κΉ νμ¬ λͺ¨λν°λ§ ν λΆλΆμ΄ μΈμμ μ΄μμ΅λλ€.
μ ν¬κ° κ°μ₯ λ¨Όμ μλνλ 건 λ¬Έμ λ₯Ό λ¨μνκ² λ°κΎΈμ΄ νλ‘μ νΈμ κ°μμ±μ ν보νλ μΌμ΄μμ΅λλ€. μ΄λ₯Ό μν΄ μ ν¬λ μλμshadowingμ λμ νμ΅λλ€. μλμμ λ§ κ·Έλλ‘ κ°μ μμ²μ λν΄ κΈ°μ‘΄ μλΉμ€μ μλ‘μ΄ μλΉμ€μ μλ΅μ΄ μΌμΉνλμ§ λΉκ΅νλ λ°©λ²μ λ»ν©λλ€.
λ κ±°μ μλΉμ€κ° κΈ°μ‘΄κ³Ό λμΌνκ² λͺ¨λ HTTP μμ²μ μ²λ¦¬νμ¬ μ μ ν μλ΅μ λ°ννλ, μ΄λ ν΄λΉ HTTP μμ²μ μ κ· μλΉμ€λ‘λ λμΌνκ² μμ²μ 보λ΄λλ‘ νμ΅λλ€. μ΄ν μ κ· μλΉμ€μ μλ΅κ³Ό κΈ°μ‘΄ μλΉμ€μ μλ΅μ΄ μΌμΉνλμ§ μ¬λΆλ₯Ό νλ¨ν΄ μ΄λ₯Ό μ€ν―statsdμ μ°λλ‘ μ²λ¦¬νκ³ , μ€μ λ‘ μ΄λ€ κ°μ΄ μ΄λ»κ² λ€λ₯Έμ§λ ν€λ°λKibanaλ₯Ό ν΅ν΄ κ²μν΄λ³Ό μ μλλ‘ λ‘κΉ νμ΅λλ€.
https://blog.banksalad.com/tech/how-banksalald-decomposes-legacy-services/
μ₯μ μ λ―Όκ°ν APIμ΄κ±°λ νΈλν½μ΄ λ§μ APIλΌλ©΄ μμ κ°μ΄ μμ μλνμ λ°©λ²λ κ³ λ €ν΄λ³Ό μ μμ κ² κ°μ΅λλ€.
(2024.10.28)
μΆκ°μ μΌλ‘ ν μ€ SLASH 24μ μΈμ μμ "ν μ€λ± ν¬κ° μ°¨μΈλλ₯Ό νμ§ μλ μ΄μ : μ§μ κ°λ₯ν λ§μ΄κ·Έλ μ΄μ μ λ΅" μμμ νλ° κ²μ¦ λΆλΆμμ, 볡μ‘ν μμ€ν μ λ€λ£° λ λ§μ΄κ·Έλ μ΄μ μ νλ κ³Όμ μ λν΄ μ¬λ μκ² κ³΅μ μ£Όμ λΆλΆμ΄ μλλ° λ§μ΄κ·Έλ μ΄μ κ³νμ΄ μμΌμλ€λ©΄ κΌ! μμ μ°Έκ³ ν΄λ³΄μλ©΄ κ΅μ₯ν λ§μ λμμ΄ λ κ² κ°μ΅λλ€!!
λ°°ν¬, λ‘€λ°±, λͺ¨λν°λ§
λ°°ν¬λ μΌλΆ νΈλν½λ§ μ κ· APIλ‘ μ μ νκ³ , μ μ§μ μΌλ‘ νΈλν½μ λΉμ€μ λμ΄λ μΉ΄λ리 λ°°ν¬μ λΉμ·ν μ λ΅μ μ¬μ©νμ΅λλ€.
μ μ¬μμ μ¬μ© μ€μΈ λ°°ν¬ λꡬλ 컀μ€ν μ€μ μ΄ λΆκ°λ₯νκΈ°μ μ ν리μΌμ΄μ λ 벨μμ λλ€μΌλ‘ μΌλΆ μμ²(5%)λ§ μ κ· APIλ‘ μ μ λλλ‘ κ΅¬ννκ³ , μ΄ν μ κ· λ‘μ§μ΄ νΈμΆλλ λΉμ¨μ μ μ§μ μΌλ‘ λλ Έμ΅λλ€.
μ΄κΈ° 5%μ νΈλν½λ§ μ κ· λ‘μ§μ ν λΉλμκΈ°μ, μ κ· λ‘μ§μ΄ μΈμ νΈμΆλλμ§ κ³μ λͺ¨λν°λ§μ ν΄μΌ νλλ°μ, μ§κΈ λμ΄μΌλ³΄λ©΄ μ κ· λ‘μ§μ΄ νΈμΆλ λ μ¬λ λ©μμ§μ κ°μ μλ¦Όμ μ€μ νλλΌλ©΄ μ΄λ¬ν λΉν¨μ¨μ μΈ λͺ¨λν°λ§μ νΌν μ μμμ κ² κ°λ€μ. π
λ‘€λ°± λν κΈ°μ‘΄μ μ μ¬μμ μ¬μ© μ€μΈ λ°°ν¬ λꡬλ₯Ό κ·Έλλ‘ νμ©νμ΅λλ€. λ¬Έμ λ°μ μ λ‘€λ°±μλ μ΅λ 2~3λΆ μ λ μμλ μ μμμ§λ§, ν΄λΉ APIκ° κ·Έ μ λλ‘ λ―Όκ°νμ§λ μμκ³ , ν΄λΌμ΄μΈνΈ μΈ‘μμ 3νμ μ¬μλ(Retry) λ‘μ§μ΄ μ‘΄μ¬νκΈ° λλ¬Έμ μ κ· λ‘μ§μμ μ€ν¨νλλΌλ μ΄ν κΈ°μ‘΄ λ‘μ§μ΄ νΈμΆλ κ°λ₯μ±μ΄ λμμ΅λλ€. λ°λΌμ μ₯μ λ°μ μ μ¦κ°μ μΈ λ‘€λ°±μ΄ λ°λμ νμν μν©μ μλμμ΅λλ€.
λ‘€λ°± μ λ΅μ λν΄μλ 6λ 묡μ λ κ±°μ, RootController 리ν©ν λ§νκΈ° ν¬μ€ν μ μ°Έκ³ νλλ°, λΉ λ₯Έ νΈλ¬λΈ μν μ΄ νμν μν©μ΄λΌλ©΄ Feature Flag λ±μ νμ©νμ¬ λΉ λ₯΄κ² λμν μ μλ λ°©λ²μ κ³ λ €ν΄ λ³Ό μ μμ κ² κ°μ΅λλ€.
μ΄λ κ² ν° μμ μ μ§νν λ μμμΉ λͺ»ν λ³μκ° μκΈ° λ§λ ¨μ λλ€. 29CM μ±μ μ¬λ¬ νλ«νΌμ΄ ν¨κ» λ§λ€κ³ λ€μν μλΉμ€λ₯Ό μ 곡νκ³ μκΈ° λλ¬Έμ λͺ¨λ μΌμ΄μ€λ₯Ό μλ²½νκ² μ»€λ²νκΈ° μ½μ§ μμ΅λλ€. RootController νΉμ±μ μ± μ¬μ©μ΄ λΆκ°λ₯ν κ²½μ°κ° μκΈΈ μλ μκΈ° λλ¬Έμ λΉ λ₯Έ νΈλ¬λΈ μν μ΄ νμνμ΅λλ€. νμ§λ§ λͺ¨λ°μΌ μ΄ν리μΌμ΄μ λ°°ν¬ νλ‘μΈμ€ νΉμ±μ FE λ BE μ²λΌ λΉ λ₯΄κ² λμν μ μμ£ .
μ΄λ₯Ό ν΄κ²°νκΈ° μν΄ μ격μΌλ‘ μ½λλ₯Ό λΆκΈ°ν μ μλ Remote Flag κΈ°λ₯μ μ¬μ©νμ΅λλ€. μ μ ν λΆκΈ° λ‘μ§μ ꡬννκ³ μ격μΌλ‘ ON/OFF λ₯Ό ν μ μλ€λ©΄ μ΄μκ° λ°μνμ λ μλ‘μ΄ λ°°ν¬μμ΄ λΉ λ₯΄κ² λμν μ μμ£ .
μ΄ μμ μ ν΅μ¬ μ λ΅μ λ§ κ·Έλλ‘ λ‘€λ°±μ μ¬μ§λ₯Ό λκ³ κ°λ°νλ κ²μ μμ΅λλ€. μ ν¬λ Amplitude μ Flag κΈ°λ₯μ ν΅ν΄ μ€μκ°μΌλ‘ κΈ°λ₯μ ON/OFF μ¬λΆλ₯Ό κ²°μ ν μ μκ² κ°λ°ν©λλ€. κ°λ°μ μμ μ±μ μν΄, λ°μ΄ν°μ μ ν©μ±μ μν΄, μ€ν κ²°κ³Όλ₯Ό μ¦μ λ°μνκΈ° μν΄ μ μ ν λΆκΈ° λ‘μ§μ κ°λ°νλλ° μ κ²½μλλ€.
νΈλ¬λΈ μν
ν΄λΉ μμ μ μ§ννλ©° λ°μν λ¬Έμ λ ν¬κ² λ κ°μ§ μ λκ° μμλλ°μ, 1. λμμ± λ¬Έμ μ 2. μμμΉ λͺ»ν νΈλν½ μ μ μ λλ€.
λ κ°μ§ λ¬Έμ μ λν΄ μ΄ν΄λ³΄κ² μ΅λλ€.
1. λμμ± λ¬Έμ
νΉμ νλ‘μμ λ₯Ό Java ApplicationμΌλ‘ μ΄κ΄νλ κ³Όμ μμ λμμ± λ¬Έμ κ° λ°μνμ΅λλ€.
λ‘컬 λ° κ°λ° μλ²μμ μΆ©λΆν ν μ€νΈλ₯Ό μ§ννλ€κ³ μκ°νμ§λ§, μ΄μ νκ²½μμ λ°μν μμμΉ λͺ»ν μ΄μμμλλ°μ,
ν΄λΉ νλ‘μμ μ λ‘μ§μ λ€μκ³Ό κ°μ΅λλ€.
- μμ² λ°μ΄ν°λ₯Ό κΈ°λ°μΌλ‘ λ°κΈ κ°λ₯ν μνμ μΏ ν° λ²νΈ μ‘°ν
- μ‘°νν μΏ ν° λ²νΈκ° μ€λ³΅λ μΏ ν°μΈμ§ μ²΄ν¬ (μΏ ν° λ²νΈλ₯Ό PKλ‘ μ¬μ©νλ κ°μ§λ ν μ΄λΈμ INSERT) --> λμμ± λ¬Έμ λ°μ
- λ°κΈ κ°λ₯ν μΏ ν° λ²νΈλΌλ©΄, μΏ ν° ν μ΄λΈμμ λ°κΈ μ²λ¦¬ (Update)
λμμ±μ΄ λ°μνλ κ²½μ°λ 2λ² λ¨κ³μμ λΉμ·ν μκ°μ λμΌν μνμ λν λ°κΈ μμ²μ΄ λ€μ΄μ¬ λ λ°μν©λλ€.
ν΄λΉ νλ‘μμ κ° μ²λ¦¬λκ³ λ ν μ¬λ‘μ° μΏΌλ¦¬κ° λ°μνμ¬ νΈλμμ μ΄ κ³μ λκΈ°νλ μν©μ΄κ³ , κ·Έλ‘ μΈν΄ μμ² Aμ Bκ° λμΌν μνμ λν΄ μμ²μ ν κ²½μ°, λμΌν 쿼리 쑰건μΌλ‘ μΈν΄ λμΌ μΏ ν° λ²νΈλ₯Ό μ‘°ννκ³ , λ μμ² λͺ¨λ 컀λ°μ΄ λμ§ μμ μ± μ¬λ‘μ° μΏΌλ¦¬λ‘ μΈν΄ μ¨μ΄ν μ΄ λ°μνμ¬ μ΅μ’ μ μΌλ‘ λ¦κ² μμ² μ¨ Bμ κ²½μ° μ»€λ° μμ μμ PK μμΈκ° λ°μν©λλ€.
μ μ΄λ―Έμ§κ° λ°μν μ΄μ μ λν μ€λͺ μΈλ°μ, λλ΅μ μΌλ‘λ λ€μκ³Ό κ°μ΅λλ€.
- μμ² Aκ° νλ‘μμ λ₯Ό νΈμΆνμ¬ μΏ ν° λ²νΈ(1234)λ₯Ό μ‘°ννκ³ , INSERT μ±κ³΅ (Commit μ )
- μ΄ν Aλ μ¬λ‘μ° μΏΌλ¦¬λ‘ μΈν΄ Waiting
- μμ² Bκ° λμΌν μνμΌλ‘ νλ‘μμ λ₯Ό νΈμΆ ν λμΌν μΏ ν° λ²νΈ(1234)μ‘°ν, INSERT μ±κ³΅ (Commit μ )
- Bλ λ§μ°¬κ°μ§λ‘ μ¬λ‘μ° μΏΌλ¦¬λ‘ μΈν΄ Waiting
- λ¨Όμ νΈμΆν Aμ μ¬λ‘μ° μΏΌλ¦¬κ° μ’ λ£λ ν Commitμ μ±κ³΅
- λ€λ¦κ² νΈμΆν Bμ κ²½μ° μ¬λ‘μ° μΏΌλ¦¬ μ’ λ£ ν Commitμ μλνμ§λ§, μ΄ μμ μμ PK μμΈ λ°μ
μ λ¬Έμ λ₯Ό ν΅ν΄ κΈ°μ‘΄ νλ‘μμ λ‘μ§μμ μ΄ν΄νμ§ λͺ»νλ λΆλΆμ΄ νλ ν΄κ²°λμμ΅λλ€.
ν΄λΉ νλ‘μμ μ λ‘μ§μ μμ λμΌνκ² μΏ ν° λ²νΈ μ‘°ν -> INSERT -> PK Exception λ°μ μ λμΌνκ² μΏ ν° λ²νΈ μ‘°ν -> INSERT ... μ λ‘μ§μΌλ‘ μ ν리μΌμ΄μ μ Retry λ‘μ§μ΄ νλ‘μμ λ΄μ ꡬνλμ΄ μμμ΅λλ€.
μ΄ λμμ± λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ κ°μ₯ λ¨Όμ μ κ·Όν λ°©λ²μ νΈλμμ μ λΆλ¦¬νλ λ°©λ²μΈλ°μ, (SELECT-INSERT-UPDATE) λ‘μ§κ³Ό μ¬λ‘μ° μΏΌλ¦¬κ° λ°μνλ λ‘μ§μ λν΄ νΈλμμ μ λΆλ¦¬νμ¬ INSERT λ‘μ§μ μνν ν μ¦μ Commitμ μ²λ¦¬νλ©΄ ν΄κ²°λμ§ μμκΉ μκ°νμ΅λλ€.
μμ κ°μ΄ μ ν μμ±μ REQUIRES_NEW λ‘ μ€μ νμ¬, μ¬λ‘μ° μΏΌλ¦¬κ° λ°μνκΈ° μ Commitμ΄ λ¨Όμ μ²λ¦¬λλ©΄, λ€λ₯Έ νΈλμμ μμ μΏ ν° λ²νΈλ₯Ό μ‘°νν λ λ€λ₯Έ μΏ ν° λ²νΈλ₯Ό μ‘°νν κ²μ΄λΌκ³ μκ°νμ΅λλ€.
Spring Transaction Propagation
νμ§λ§ νΈλμμ μ λΆλ¦¬νλλΌλ λμΌν λ¬Έμ κ° λ°μνμ΅λλ€. μμ² A(λΉ¨κ°μ), μμ² B(νλμ)μ μκ°λλ³λ‘ μ 리ν΄λ³΄λ©΄ λ€μκ³Ό κ°μ΅λλ€.
- [11:00:15.707, exec-50] λ°κΈμμ²
- [11:00:15.710, exec-51] λ°κΈ μμ²
- [11:00:15.790, exec-50] μΏ ν° λ°κΈ μ±κ³΅
- [11:00:15.843, exec-51] μΏ ν° λ°κΈ μ€ν¨ (PK μμΈ λ°μ)
νΈλμμ μ λΆλ¦¬νμμλ λ μμ²μ΄ 0.003μ΄λΌλ λ§€μ° μ§§μ μκ° μ°¨μ΄λ‘ μκΈ°μ μ»€λ° μμ²΄κ° 0.003μ΄ μμ μλ£λμ§ λͺ»νλ©΄μ λμΌν λ¬Έμ κ° λ°μνμ΅λλ€.
λ€μμΌλ‘λ κΈ°μ‘΄ νλ‘μμ λ‘μ§κ³Ό λΉμ·νκ² μΏ ν° λ²νΈ μ‘°ν μ Nκ°λ₯Ό μ‘°ν νκ³ , λμΌν λ‘μ§μ μννλ PK μλ¬κ° λ°μνλ©΄ try-catchλ‘ μμΈλ₯Ό μ‘κ³ , λ€μ μΏ ν° λ²νΈλ‘ μ²λ¦¬νλλ‘ μμ μ νμ΅λλ€.
μ λ°©μμ μ μ©ν μ΄νλ‘ λμΌν λ¬Έμ λ λ°μνμ§ μμμ΅λλ€.
(μ°Έκ³ λ‘ νΈλμμ μ μ ν μμ±μ REQUIRES_NEWλ‘ μ€μ νμ§ μμΌλ©΄, try-catchλ‘ μμΈλ₯Ό μ²λ¦¬νλλΌλ rollback-only markedλ‘ μΈν΄ λ‘€λ°±μ΄ λ°μνμ¬, μμνλ λ‘μ§κ³Ό λ€λ₯΄κ² μλν μ μμ΅λλ€. μ΄μ κ΄λ ¨νμλ μ? μ΄κ² μ λ‘€λ°±λλκ±°μ§? λ₯Ό μ°Έκ³ ν΄μ£ΌμΈμ!)
μ ν리μΌμ΄μ μ΄λ λ°μ΄ν°λ² μ΄μ€μ μ 곡νλ Lockμ μ΄μ©νλ©΄ λ κΉλνκ² ν΄κ²°ν μ μμμ κ² κ°μλ°, μ΄μ κ°μ΄ μ²λ¦¬ν μ΄μ λ λ€μκ³Ό κ°μ΅λλ€.
- λͺ¨λ μΌμ΄μ€μμ λμμ± λ¬Έμ κ° λ°μνλ κ²μ΄ μλ, νΉμ μ ν΄μ¬λ μνμ λν΄μλ§ λ°μν©λλ€.
- κ³Όκ±° νμ€ν 리λ₯Ό μ΄ν΄λ³Έ κ²°κ³Ό, νΉμ μ ν΄μ¬μμ λ°κΈ μ²λ¦¬λμ λ리기 μν΄ λ³λ ¬λ‘ λ°κΈ APIλ₯Ό νΈμΆνλ μν©μ΄ μμκ³ , λ³λ ¬λ‘ μ²λ¦¬νλ μ€λ λ μλ μ΅λ 3κ°μκΈ° λλ¬Έμ μ΄ μλ μΆκ° μμ²μ΄ μμΌλ©΄ μ¦κ°νμ§ μμ΅λλ€.
λ§μ½ Lockμ μ μ©νλ€λ©΄, νΉμ μνμ λν΄μλ λμμ±μ΄ λΉλ²νκ² λ°μνλ μν©μ΄κΈ°μ νΉμ μνμ λν΄μλ§ λΆλΆμ μΌλ‘(νΉμ μν, μ ν΄μ¬ λ±) λΉκ΄μ λ½μ μ μ©ν΄ λ³Ό μ μμ κ² κ°μ΅λλ€.
2. μμμΉ λͺ»ν νΈλν½ μ μ
μ λ¬Έμ λ μΏ ν° λ°κΈ μ λ°μνλ μ¬λ‘μ° μΏΌλ¦¬κ° κ°μ λ¨μ λ°λΌ μΏ ν°μ μμ± μλκ° λ°κΈ μλλ₯Ό λ°λΌκ°μ§ λͺ»νμ¬ λ°μν μ΄μμΈλ°μ, ν΄λΌμ΄μΈνΈμ μ‘΄μ¬νλ 리νΈλΌμ΄(μ΅λ 3ν) λ‘μ§μΌλ‘ μΈν΄ 3λ°°μ νΈλν½μ΄ μ μ λμμ΅λλ€.
νμ¬ κ΅¬μ‘°λ λλ΅μ μΌλ‘ μμ κ°μλ°μ,
μΈλΆ μ ν΄μ¬κ° λ°κΈ μμ²μ μν΄ λ΄λΆ μλ²μ μμ²νκ³ , λ΄λΆ μλ²μμ λ€μ λ°κΈ μλ²λ‘ API μμ²μ 보λ΄λ ꡬ쑰μ λλ€.
(λ΄λΆ μλ² μμ΄ μΈλΆ μ ν΄μ¬μμ λ°λ‘ λ°κΈ μλ²μ μμ²νλ κ² κ°μ₯ λ¨μνμ§λ§, μ νν νμ€ν 리λ₯Ό μ μλ μμ§λ§ κ³Όκ±° μ¬μ κ³μ½μΌλ‘ μΈν΄ λ΄λΆ μλ²λ₯Ό κ²½μ νλ κ΅¬μ‘°κ° λμκ³ , B2Bμ B2Cμ λ°λΌ μ²λ¦¬ λ°©μμ΄ λ€λ₯΄κ² λμ΄μλ κ²μΌλ‘ λ€μλ κ² κ°μ΅λλ€..;)
μΈλΆ μ ν΄μ¬μμλ μμ²ν μλλ§νΌ μΏ ν°μ λ°μ§ λͺ»νλ©΄ 무νν μμ²μ λ°λ³΅νλ νλ‘μΈμ€λ‘ ꡬνλμ΄ μμ΅λλ€. κ³Όκ±°μλ μ¬λ‘μ° μΏΌλ¦¬λ‘ μΈν΄(?) μΏ ν°μ΄ μμ±λλ μκ°μ μ΄λ μ λ ν보ν μ μμμ§λ§, νμ¬λ API μλ΅μ΄ μ¦μ μ΄λ£¨μ΄μ§κΈ° λλ¬Έμ μμ² λΉλκ° λμ± μ¦κ°νκ² λ μν©μ λλ€.
λ°λΌμ μμ λ¬Έμ λ₯Ό κ°μ νκΈ° μν΄ μ μ©ν(μ μ©ν μ μλ) λ°©λ²μ λ€μκ³Ό κ°μ΅λλ€.
- μΈλΆ μ ν΄μ¬μμ λ°κΈ μμ² μ μλ¬κ° λ°μνλ©΄ μΆ©λΆν κ°κ²©μ λκ³ μ¬μλνλλ‘ λ³κ²½
- μΏ ν° μμ¬λμ΄ λΆμ‘±ν κ²½μ° λ΄λΆ νμμλ Retry λ‘μ§μ μ κ±°νλ€.
- Rate Limiter λ±μ ꡬννκ³ , λ§μ νΈμΆλμ λν΄ μ μ νκ² μ μ΄νλ€.
- λλ λ°κΈμ΄ νμν κ²½μ°, μΏ ν° νμ μ¬μ μ μΆ©λΆν ν보νκ³ μ체 λͺ¨λν°λ§μ κ°ννλ€.
μ¬μ€ κ·Όλ³Έμ μΈ ν΄κ²°μ± μ μΏ ν° μμ± λ‘μ§μ κ°νΈν΄μΌ νμ§λ§, λΉμμλ μ¬λ¬ μ μ½μ΄ μ‘΄μ¬νκ³ λ―Έλμλ μμ€ν ν΅ν© λ±μ κ³νλ μμκΈ°μ ν΄λΉ μμ μ μ§ννμ§λ λͺ»νμ΅λλ€.
κ²°κ³Ό(μ±κ³Ό)
κΈ°μ‘΄ APIμ νΈλμμ κ³Ό μ κ· APIμ νΈλμμ μ±λ₯ λΉκ΅ μ λλ€.
νκ· μ²λ¦¬ μκ°μ΄ μ½ 1,500msμμ 25msλ‘ κ°μ λμμ΅λλ€. (μΊμ±μ μ©, κ³Όκ±° λ°μ΄ν° μμ , μΈλ±μ€ μ μ©)
μ΅λ μ²λ¦¬ μκ°λ 60,000msμμ 1,400msλ‘ κ°μ λμμ΅λλ€. (μ¬λ‘μ° μΏΌλ¦¬ κ°μ λ° νλ‘μμ λ΄ λΉν¨μ¨μ μΈ Retry λ‘μ§ μ κ±° λ±)
νκ³
μμ μ νκ³ λμ κ½€λ μκ°μ΄ μ§λμ μμ±νκ² λμ΄μ, μ νν κΈ°μ΅λμ§ μκ±°λ μλ£κ° μλ λΆλΆλ μ‘΄μ¬ν©λλ€.
μμ νλ©΄μ κΉ¨λ«κ³ , μ»κ²λ κ΅νμ λ€μκ³Ό κ°μ΅λλ€.
- ν¬κ³ 볡μ‘ν λ¬Έμ λ (νμ) κ°λ₯ν μμ λ¨μλ‘ λΆν νκ³ μ κ·Όνμ.
- μ½λ λ΄ (μ€λλ) μ£Όμμ μ λ’°νμ§ λ§κ³ κ²½κ³νμ..
- λ―Έλμ μ 3μ (νΉμ λ³ΈμΈ)λ₯Ό μν΄ μ½λ κ°λ μ±μ μΆ©λΆν μ κ²½ μ°μ.
- μ΄μ νκ²½μμλ νμ μ¬μ΄λ μ΄ννΈκ° λ°μν μ μμμ μΌλμ λκ³ μμ νμ.
'νκ³ ' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
μ κ· μμ€ν ꡬμΆνκΈ° (feat. MSA, λ°±μ€νΌμ€) (3) | 2024.01.19 |
---|---|
무λνλ 2022λ , μλ‘μ΄ μμ 2023λ (17) | 2023.01.02 |
λ»κΉμ 2021λ νκ³ (10) | 2022.01.02 |
μ¬λ¦μ΄ λ λκ°λ 8μμ νκ³ (4) | 2021.08.29 |
λ―ΈμΉλλ‘ λμ λ 7μμ νκ³ (0) | 2021.07.31 |
λκΈ