# Gmail OAuth 404 에러 및 Return URL 구현

## 작성일: 2025-09-01
## 작성자: happybell80
## 관련 서비스: auth-server, frontend-customer

---

## 18시 30분 - 문제 발견

### 문제 상황
1. **Frontend 404 오류**
   - Gmail OAuth 성공 후 `/settings/items` 페이지로 리다이렉트
   - 해당 라우트가 Frontend에 존재하지 않아 404 에러 발생
   - 실제 아이템 관리 페이지는 `/inventory`

2. **UX 문제**
   - OAuth 인증 후 `/inventory` 페이지로 이동
   - 사용자가 원래 있던 페이지로 돌아가려면 수동 이동 필요

### 원인 분석
```typescript
// frontend-customer/src/App.tsx
<Route path="/inventory" component={InventoryPage} />  // 존재
<Route path="/settings/items" ... />  // 존재하지 않음

// auth-server/app/providers/gmail_passport.py:223
return RedirectResponse(f"https://ro-being.com/settings/items?gmail=success&email={email}")
// 잘못된 경로로 리다이렉트
```

---

## 18시 45분 - 1차 수정: 404 에러 해결

### 수정 내용
```python
# auth-server/app/providers/gmail_passport.py:223
# 변경 전
return RedirectResponse(f"https://ro-being.com/settings/items?gmail=success&email={email}")

# 변경 후
return RedirectResponse(f"https://ro-being.com/inventory?gmail=success&email={email}")
```

### 결과
- 404 에러 해결 ✅
- `/inventory` 페이지로 정상 리다이렉트
- 하지만 여전히 원래 페이지로 돌아가지 못함

---

## 19시 00분 - 2차 수정: Return URL 구현

### 구현 전략
1. OAuth 요청 시 현재 페이지 URL을 `return_url` 파라미터로 전달
2. auth-server에서 state에 return_url 저장
3. OAuth 콜백 처리 시 return_url로 리다이렉트
4. return_url이 없으면 기본값 `/game` 사용

### 수정 내용

#### 1. Frontend - OAuth 요청에 return_url 추가
```typescript
// frontend-customer/src/components/skills-items-panel.tsx:359-364
// 변경 전
const authUrl = `https://auth.ro-being.com/auth/gmail/passport?user_id=${userId}`;
sessionStorage.setItem('gmail_oauth_return_url', window.location.href);
window.location.href = authUrl;

// 변경 후
const currentUrl = window.location.href;
const authUrl = `https://auth.ro-being.com/auth/gmail/passport?user_id=${userId}&return_url=${encodeURIComponent(currentUrl)}`;
window.location.href = authUrl;
```

#### 2. auth-server - return_url 처리 추가
```python
# app/providers/gmail_passport.py

# 1) 발급 엔드포인트 수정 (line 58)
@router.get("/")
async def issue_passport(user_id: str = Query(...), return_url: str = Query(default=None)):
    # state에 return_url 포함
    state_data = {"user_id": user_id, "timestamp": time.time()}
    if return_url:
        state_data["return_url"] = return_url
    state = json.dumps(state_data)
    
# 2) 콜백 처리 수정 (line 225-235)
# return_url이 있으면 해당 페이지로, 없으면 기본 페이지로
return_url = state_data.get("return_url")
if return_url:
    separator = "&" if "?" in return_url else "?"
    redirect_url = f"{return_url}{separator}gmail=success&email={email}"
else:
    redirect_url = f"https://ro-being.com/game?gmail=success&email={email}"

return RedirectResponse(redirect_url)
```

---

## 19시 15분 - 배포 및 검증

### Git 커밋
```bash
# auth-server
git commit -m "feat: OAuth 인증 후 이전 페이지로 자동 복귀 구현"

# frontend-customer  
git commit -m "feat: Gmail OAuth 요청 시 return_url 파라미터 추가"
```

### 테스트 시나리오
1. `/game` 페이지에서 Gmail 연결 → OAuth 완료 → `/game` 복귀 ✅
2. `/game001` 페이지에서 Gmail 연결 → OAuth 완료 → `/game001` 복귀 ✅
3. return_url 없이 직접 접근 → OAuth 완료 → `/game` (기본값) ✅

---

## 교훈

### 개발 원칙
1. **라우트 변경 시 양쪽 확인**: Frontend 라우트 변경 시 Backend 리다이렉트 경로도 함께 확인
2. **UX 우선**: OAuth 같은 외부 플로우는 원래 페이지로 복귀가 기본
3. **파라미터 전달**: state 파라미터를 활용한 컨텍스트 유지

### 기술적 포인트
1. **URL 인코딩**: return_url은 반드시 `encodeURIComponent()` 처리
2. **쿼리 파라미터 처리**: 기존 쿼리 있는 URL에 파라미터 추가 시 `?` vs `&` 구분
3. **기본값 설정**: return_url 없을 때 합리적인 기본값 제공

### 문서 업데이트
- `300_architecture/sequences/email_sequences.md`: Gmail Passport 플로우 추가
- `300_architecture/380_authentication_system.md`: Gmail Passport 엔드포인트 문서화

---

## 참고 자료
- 관련 PR: auth-server #fc94303, frontend-customer #26e7f70
- 영향받는 파일:
  - auth-server/app/providers/gmail_passport.py
  - frontend-customer/src/components/skills-items-panel.tsx