- ShoppingFourU
- π₯ Team Member
- π Architecture
- π Convention
- π‘ API Documentation
- π₯ Troubleshooting
- [λΆνμν 쿼리 μμ± λ¬Έμ ]
- [JWT νν° μμΈ μ²λ¦¬ λ¬Έμ ]
- π κΈ°λ³Έ νλ‘μ νΈ μ΄ν 보μμ
- [Git Β· Slack μλ¦Ό & Bot μλ¬ μ°λ]
- [API μ κ·Ό μ ν (Rate Limiting)]
- [Domain Refactoring]
- [ν μΈ Β· λ©€λ²μ μ μ± λͺ¨λν]
- [μ£Όλ¬Έ μ λ°°μ‘μ§ κ²μ¦ κ°ν]
- [μ£Όλ¬Έβκ²°μ νλ‘μΈμ€ 리ν©ν λ§ & λμμ± μ μ΄]
- [λκ΄μ λ½ (Optimistic Lock) λμ ]
- [μ¬κ³ μμ½ μμ€ν λμ ]
- [μ° (Wishlist) λλ©μΈ μΆκ°]
- π μλ‘μ΄ κΈ°μ λμ
μ¬ν λ° μ μ μ΄μ
- [μν ν μΈ μ μ΄λ©μΌ μλ¦Ό μμ€ν λμ ]
- [OpenAI κΈ°λ° FAQ μ±λ΄ λμ ]
- [ELK + λͺ¨λν°λ§ μμ€ν λμ ]
ShoppingFourU λ μ¨λΌμΈ μΌνλͺ° μ΄μμ νμν κΈ°λ₯λ€μ μμ νκ² κ΅¬νν E-commerce νλ«νΌμ
λλ€.
νμ κ΄λ¦¬λΆν° μν λ±λ‘, μ₯λ°κ΅¬λ, μ£Όλ¬Έ/κ²°μ κΉμ§ μ€μ μλΉμ€μ λμΌν νλ¦μ μ 곡νλ©°
μ¬μ©μ κ²½νκ³Ό κ΄λ¦¬μ μ΄μ κ²½νμ λͺ¨λ λ΄μλΈ μΌν μλΉμ€μ
λλ€.
| μ΄λ¦ | GITHUB | μν |
|---|---|---|
| π¦ μμ μ | https://github.com/jungyoyang | νμ |
| π€ μ΄λμ | https://github.com/DaveLee-b | νμ |
| π€ μ μ§λ―Ό | https://github.com/jeemin65-pixel | νμ |
| π¨ μ λ¬Έμ | https://github.com/munyeong0103 | νμ₯ |
| π« μ μ’ ν | https://github.com/jong15325/ | νμ |
μμΈν 컨벀μ μ¬νμ λ Έμ μ ν΅ν΄ νμΈ ν΄μ£ΌμΈμ! https://vivid-thyme-ac6.notion.site/Commit-Convention-2e19e3e335cc80d7bf16c7377e4ddeac?source=copy_link
μ 체 API λͺ μΈ λ° μμΈ μ€νμ μλ λ§ν¬μμ νμΈν μ μμ΅λλ€.
π Full API Documentation (Notion)
π Swagger Documentation
λ¬Έμ μν©
- ν μΈ μ 보 μ‘°ν μ λ©€λ²μ μ 보λ νμν¨
- Lazy LoadingμΌλ‘ μΈν΄ 2λ²μ 쿼리 λ°μ (ν μΈ μ‘°ν β λ©€λ²μ μ‘°ν)
- λͺ©λ‘ μ‘°νμμλ N+1 λ¬Έμ λ‘ μ΄μ΄μ§ μ μλ ꡬ쑰
ν΄κ²° λ°©λ²
- @EntityGraph λ‘ Fetch Join μ μ©
- 1λ²μ μΏΌλ¦¬λ‘ ν΅ν©νμ¬ μ±λ₯ κ°μ
- 쿼리 νμ 50% κ°μ (2ν β 1ν)
λ¬Έμ μν©
- ν ν°μ΄ νμ μλ μμ²μμλ ν ν° κ²μ¦ μμΈ λ°μ
- Authorization ν€λκ° μλ κ²½μ°μλ μμΈλ₯Ό λμ Έ Controller λ‘μ§κΉμ§ μ λ¬λμ§ λͺ»ν¨
κΈ°μ‘΄ λ¬Έμ μ½λ
private String resolveToken(HttpServletRequest request) {
String header = request.getHeader(AUTH_HEADER);
if (!StringUtils.hasText(header) || !header.startsWith(BEARER_PREFIX)) {
throw new CustomException(ErrorCode.INVALID_JWT_TOKEN);
}
return header.substring(BEARER_PREFIX.length());
}
ν΄κ²°λ°©λ²
if (!StringUtils.hasText(header) || !header.startsWith(BEARER_PREFIX)) {
return null;
}
return header.substring(BEARER_PREFIX.length());- Authorization ν€λκ° μκ±°λ Bearer λ‘ μμνμ§ μμΌλ©΄ μμΈλ₯Ό λμ§μ§ μκ³ null λ°ν
- μ΄λ κ² νλ©΄ Securityμμ μΈμ¦μμ΄ ν΅κ³Όμν€κ³ Controller λ‘μ§κΉμ§ μ μμ μΌλ‘ μ λ¬λ¨
κΈ°λ³Έ νλ‘μ νΈ κ΅¬ν μ΄ν,
μ€μ μ΄μ νκ²½μμ λ°μν μ μλ λ¬Έμ λ€μ κ°μ νκ³ μμ μ±κ³Ό νμ₯μ±μ μ€μ¬μΌλ‘ ꡬ쑰λ₯Ό 보μνμ΅λλ€.
λ¨μ κΈ°λ₯ ꡬνμ λμ΄μ μ΄μ κ΄μ μ νμ§ κ°μ μ μ΄μ μ λ§μ·μ΅λλ€.
1μ°¨ λ°©μ΄
- Global Filter κΈ°λ° IP λ¨μ μ ν
- μ΄λΉ 100ν / μ΅λ 10,000 IP κΈ°μ€
2μ°¨ λ°©μ΄
- AOP κΈ°λ° Controller λ¨μ μ κ·Ό μ μ΄
- API νΉμ±μ λ°λΌ IP / μ¬μ©μλ³ μ ν μ μ± λΆλ¦¬ μ μ©
- λ©μλλ³λ‘ μλ‘ λ€λ₯Έ μ ν μ μ± μ μ© κ°λ₯
- Redis μ¬μ©μ΄ μ νμ μΈ νκ²½ κ³ λ €
- Caffeine κΈ°λ° μΊμλ‘ κ²½λ Β· κ³ μ±λ₯ Β· λμμ± μμ μ± ν보
μ£Όλ¬Έ μμ± API
- μν ꡬ맀 κ°λ₯ μ¬λΆ νμΈ
- μ£Όλ¬Έ μ 보 μ μ₯
π μν:PENDING_PAYMENT
κ²°μ μμ± API
- μΈλΆ κ²°μ λͺ¨λ νΈμΆ
- (Transaction)
- κ²°μ μ 보 μ μ₯
- μν μ¬κ³ μ°¨κ°
- μ£Όλ¬Έ μν λ³κ²½ β
PAID
π‘
μΈλΆ κ²°μ API νΈμΆμ νΈλμμ μ ν¬ν¨νμ§ μκ³ ,
DB λ³κ²½ λ‘μ§λ§ μμμ μΌλ‘ λ¬Άμ΄ λ½ μ μ λ° μ±λ₯ μ νλ₯Ό λ°©μ§
- μν μν°ν°μ
@Versionνλ μΆκ° - λμ μ¬κ³ μ°¨κ° μ μ»€λ° μμ μ μΆ©λ κ°μ§
- μΆ©λ λ°μ μ μμΈ μ²λ¦¬ ν μ¬μλ μ λ΅ μ μ©
- λμ μ£Όλ¬Έ νκ²½μμ μ΄κ³Ό νλ§€ λ°©μ§
- κ²°μ μλ£ μ ꡬ맀 κΆν μ μ νμ
μ£Όλ¬Έ μμ± μ
- μ¬κ³ μ°¨κ°
- μ¬κ³ μμ½ μ 보 μ μ₯
- μ£Όλ¬Έ μν:
PENDING_PAYMENT
κ²°μ μ±κ³΅ μ
- μ¬κ³ μμ½ ν΄μ
- μ£Όλ¬Έ μν λ³κ²½:
PAID
κ²°μ μ€ν¨ / μμ½ λ§λ£ μ
- μμ½ μ 보 μμ
- μ¬κ³ 볡ꡬ
- λλΆλΆμ μ¬μ©μκ° μ΄λ©μΌμ 보μ νκ³ μμ΄ μ κ·Όμ±μ΄ λμ
- νμκ°μ
μ μ΄λ―Έ μ΄λ©μΌ μ 보λ₯Ό μμ§νλ―λ‘
μΆκ° μ 보 μ λ ₯μ΄λ μΈλΆ μλΉμ€ μ°Έμ¬λ₯Ό μꡬνμ§ μμλ λ¨ - Slack, Discord λ±μ λ³λμ νλ‘κ·Έλ¨ μ¬μ© λ° κ³΅κ° μ°Έμ¬κ° νμνμ¬
μ¬μ©μ μλ¦Ό λͺ©μ κ³Ό λ§μ§ μμ μ μΈ - μΉ΄μΉ΄μ€ν‘ μ±λμ κ²½μ°
- μ¬μ μ λ±λ‘ νμ
- μ λ£ λ©μμ§ λ°μ‘
- μΉ΄μΉ΄μ€ κ³μ κ΄λ ¨ μ 보 μΆκ° κ΄λ¦¬ νμ
β μ΄μ λΉμ© λ° λ³΅μ‘μ± μ¦κ°λ‘ μΈν΄ μ μΈ
- λλ©μΈλ³ μμ£Ό 묻λ μ§λ¬Έκ³Ό λ΅λ³μ JSON νμΌλ‘ μ 리
- ν΄λΉ λ°μ΄ν°λ₯Ό κΈ°λ°μΌλ‘ λ²‘ν° μ€ν μ΄(Vector Store) μ°λ
- FAQ JSON λ°μ΄ν° κΈ°λ° μ§μμλ΅ μ 곡
- μλΉμ€ λ΄λΉ λλ©μΈ μΈ μ§λ¬Έμ λν΄μλ
μλ΅μ μ ννμ¬ λΉμλμ λ΅λ³ λ°©μ§
ELK Stack
- μλ¬ λ‘κ·Έ μμ§
- μμ² νλ¦ λ° μ₯μ μμΈ μΆμ
Prometheus + Grafana
- EC2 λ° Docker 컨ν μ΄λ 리μμ€ λͺ¨λν°λ§
- CPU / λ©λͺ¨λ¦¬ / μλΉμ€ λΆν μν μ€μκ° μκ°ν
- λ‘κ·Έμ λ©νΈλ¦μ λΆλ¦¬νμ¬ λΆμ κ°λ₯
- μλΉμ€ μ₯μ λ°μ μ μμΈ νμ μλ ν₯μ
- μ΄μ κ΄μ μμ μμ€ν μνλ₯Ό νλμ νμ κ°λ₯
