docs: Gateway 필드 변환 및 보안 문제 트러블슈팅

- 헬스체크 엔드포인트 표준화 (/healthz)
- UUID vs username 처리 문제 해결
- nginx 직접 프록시 vs Gateway 라우팅 분석
- 사용자 인증 검증 부재 보안 위험 지적
- 현업 패턴 및 실용적 해결책 정리
This commit is contained in:
happybell80 2025-08-11 11:03:35 +09:00
parent 1a8ab73ca9
commit d71e0ff81e

View File

@ -0,0 +1,137 @@
# Gateway 필드 변환 및 보안 문제 해결
## 오전 10:58
### 문제 1: 헬스체크 엔드포인트 표준화
**상황**:
- 각 서비스마다 다른 헬스체크 엔드포인트
- nginx/k8s 표준인 `/healthz` 필요
**해결**:
```python
# rb10508_micro/app/main.py
@app.get("/healthz")
async def healthz():
"""단순 헬스체크 - 서비스 생존 확인만"""
return {"status": "ok"}
```
- 루트 레벨에 `/healthz` 추가
- API 프리픽스 없이 접근 가능
- 빠른 응답 (< 100ms)
### 문제 2: UUID 형식 오류
**원인**:
- Frontend가 username(`happybell80`) 전송
- Gateway가 UUID 형식 기대
- `invalid UUID 'happybell80': length must be between 32..36 characters`
**해결**:
```python
# robeing-gateway/app/database.py
async def get_robing_info(username: str):
"""username으로 직접 조회"""
query = text("""
SELECT ...
FROM workspace_members wm
JOIN users u ON wm.user_id = u.id
WHERE u.username = :username
""")
```
- users 테이블 JOIN으로 username → UUID 변환
- UUID 체크 로직 제거 (Frontend는 항상 username 사용)
### 문제 3: nginx 직접 프록시 vs Gateway 라우팅
**현재 구조 분석**:
```
# 원래 설계 (문서)
Frontend → nginx(/gateway/) → Gateway(8100) → rb10508_micro
# 실제 nginx 설정
location ^~ /rb10508/ {
proxy_pass http://192.168.219.52:10508/; # 직접 프록시
}
location ^~ /gateway/ {
proxy_pass http://localhost:8100/; # Gateway 서비스
}
```
**문제점**:
- `/rb10508/`는 Gateway 우회
- `message``text` 필드 변환 안됨
- 422 Unprocessable Entity 에러
**해결 방안 검토**:
1. nginx 모든 요청을 Gateway로 → **Gateway 부하 문제**
2. rb10508_micro가 두 필드 모두 지원 → **실용적**
### 문제 4: 사용자 인증 검증 부재 (보안 위험)
**현재 상황**:
```javascript
// 누구나 헤더 조작 가능
fetch('/gateway/api/chat', {
headers: {'X-User-Id': 'admin'} // 위장 가능!
})
```
**위험**:
- 사용자 위장 가능
- 로빙 접근 권한 우회
- 데이터 유출 위험
**필요한 조치**:
- JWT 토큰 검증 로직 추가
- auth-server와 연동
- 실제 사용자 확인 필수
## 교훈
### 1. **헬스체크 설계**
- 표준 엔드포인트 사용 (`/healthz`)
- 빠른 응답 우선 (복잡한 체크는 별도 엔드포인트)
- 루트 레벨 배치로 프리픽스 문제 회피
### 2. **식별자 설계**
- Frontend는 사용자가 이해하는 값 사용 (username)
- Backend에서 내부 ID 변환
- UUID는 내부용으로만 사용
### 3. **Gateway 아키텍처**
- 모든 요청을 Gateway로 보내면 병목 발생
- 실용적 접근: 서비스가 유연하게 처리
- 점진적 마이그레이션 전략 필요
### 4. **보안 최우선**
- 헤더 기반 인증은 위험
- JWT 토큰 검증 필수
- 신뢰 경계 명확히 설정
## 현업 패턴
### Gateway 부하 해결:
1. **Service Mesh**: 각 서비스에 Sidecar 프록시
2. **Gateway 클러스터링**: 여러 Gateway 인스턴스
3. **하이브리드**: 중요 요청만 Gateway, 나머지 직접
### 실용적 해결:
```python
class MessageRequest(BaseModel):
text: Optional[str] = None
message: Optional[str] = None
def get_text(self):
return self.text or self.message
```
- 두 경로 모두 지원
- Gateway 유무와 관계없이 작동
- 마이그레이션 유연성 확보
## 다음 작업
1. **즉시**: rb10508_micro에 message 필드 지원 추가
2. **긴급**: JWT 토큰 검증 구현
3. **계획**: Gateway 스케일링 전략 수립
4. **장기**: Service Mesh 도입 검토