Files
superport_v2/doc/backup/backend_change_requests.md

98 lines
6.2 KiB
Markdown

# 백엔드 수정 요청서 (2025-10-20 갱신)
## 1. 배경
- 프런트엔드는 `.env.development`에서 `API_BASE_URL=http://43.201.34.104:8080`을 사용해 실서버 로그인 API를 호출한다.
- 동일 API를 사용하는 운영 환경에서는 CORS 문제가 없지만, 로컬 웹 개발 시 브라우저가 `http://localhost:<port>` 오리진으로 사전 요청(preflight)을 보내면서 403 대신 CORS 차단이 발생한다.
- 프런트(`superport_v2`)와 백엔드(`superport_api_v2`) 양쪽 구현을 재검토한 결과, 로그인 계약은 일치하나 실서버에서 CORS 응답 헤더가 전혀 내려오지 않는 것으로 확인되었다.
- 로컬 개발 및 QA가 모두 실서버를 바라보고 있어, 백엔드에서 CORS 허용 정책을 명시적으로 정비해야 한다.
## 2. 현상 및 재현 절차
- 브라우저 콘솔 오류:
```
Access to XMLHttpRequest at 'http://43.201.34.104:8080/api/v1/auth/login' from origin 'http://localhost:50408'
has been blocked by CORS policy: Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
```
- curl 재현(사전 요청):
```bash
curl -i -X OPTIONS \
http://43.201.34.104:8080/api/v1/auth/login \
-H 'Origin: http://localhost:50408' \
-H 'Access-Control-Request-Method: POST'
```
실제 응답: `HTTP/1.1 404 Not Found` + 헤더 없음 → CORS 미적용.
- 실제 요청도 동일하게 헤더가 비어 있음:
```bash
curl -i -X POST \
http://43.201.34.104:8080/api/v1/auth/login \
-H 'Origin: http://localhost:50408' \
-H 'Content-Type: application/json' \
-d '{"identifier":"test","password":"test"}'
```
응답: `401 Unauthorized` 본문은 내려오지만 `Access-Control-Allow-Origin` 헤더가 없음.
## 3. 프런트/백엔드 로그인 계약 점검
- **프런트 요청 구조**
- 경로: `POST ${ApiRoutes.apiV1}/auth/login` → `/api/v1/auth/login`
- 페이로드: `{ identifier, password, remember_me }` (`lib/features/auth/data/repositories/auth_repository_remote.dart:18`)
- 응답 파싱: `{ data: { access_token, refresh_token, expires_at, user, permissions[] } }`
(`lib/features/auth/data/dtos/auth_session_dto.dart`)
- **백엔드 구현**
- 라우트: `#[post("/login")]` (`backend/src/api/v1/auth.rs:17`) → `web::scope("/api/v1")`
- 요청 모델: `LoginRequest { identifier: String, password: String, remember_me: bool }`
(`backend/src/domain/auth.rs:9`)
- 응답 모델: `AuthSessionResponse { data: AuthSessionData { ... } }`
- **계약 비교 결론**
- 필드 명/자료형 모두 일치, remember_me 기본값 및 데이터 매핑도 호환.
- 로그인 자체는 401/403 흐름이 정상이나, 브라우저 오리진이 차단되어 요청이 전달되지 못함.
## 4. 근본 원인 분석
- 백엔드 `App::new()` 정의는 `build_cors(&config.cors)` 미들웨어를 `wrap`하고
`default_service`에서 `OPTIONS` 가드를 204로 처리하도록 구현되어 있음 (`backend/src/app/mod.rs:36-132`).
- `config/default.toml`의 `[cors]` 설정은 `allowed_origins = []`로 전체 허용이 기본이지만,
실제 운영 환경에서는 `APP_ENV`에 대응하는 설정 또는 환경 변수로 제한된 오리진만 등록한 것으로 추정된다.
- 하지만 허용 목록에서 로컬 호스트가 빠진 경우라면 CORS 미들웨어가 `403`을 반환해야 하는데,
현재는 단순 404/401 응답으로 보아 **미들웨어가 동작하지 않거나, 리버스 프록시/로드밸런서 구간에서 CORS 헤더가 삭제**되고 있다.
- 결과적으로 브라우저는 `Access-Control-Allow-Origin`을 받지 못하고 사전 요청 단계에서 차단된다.
## 5. 요청 사항
1. **백엔드 Actix CORS 설정 재점검**
- `build_cors`가 실제 배포 바이너리에도 적용되는지 확인하고, 필요한 경우 `Cors::default()` 대신
`Cors::permissive()` 또는 `allowed_origin_fn` 로깅을 추가해 런타임에서 허용 여부를 추적한다.
- `supports_credentials()`를 유지하면서도 최소 `http://localhost` 기반 개발 포트 전체를 허용하도록
`allowed_origin_fn`에서 와일드카드 검사를 추가하거나, 설정 파일에 와일드카드 표기를 허용하도록 개선한다.
```rust
.allowed_origin_fn(move |origin, _| {
if allow_all {
return true;
}
if origin.as_bytes().starts_with(b"http://localhost") {
return true;
}
allowed_list.iter().any(|allowed| allowed == origin)
})
```
- 운영 배포용 설정(`APP_ENV=production`)에도 `cors.allowed_origins`에
`https://{prod-domain}` + `http://localhost` (또는 사내 VPN 도메인)을 명시한다.
2. **리버스 프록시/로드밸런서 검증**
- Nginx/ALB 등 중간 계층이 `OPTIONS` 메서드를 백엔드로 전달하는지 확인하고, 차단 시 `proxy_set_header Access-Control-Allow-Origin` 등을 설정한다.
- 모든 사전 요청이 최소 `204` 혹은 `200`과 함께 `Access-Control-Allow-Origin`, `Access-Control-Allow-Methods`, `Access-Control-Allow-Headers`를 반환하도록 보장한다.
3. **로그인 핸들러 응답 헤더 확인**
- 인증 성공/실패 여부와 관계없이 `Access-Control-Allow-Origin`이 반드시 포함되도록 통합 테스트를 추가한다.
- 예시: `cargo test cors_allows_login_origin` 형태의 통합 테스트에서 `Origin: http://localhost:50408` 헤더를 넣고 응답 헤더를 검증.
## 6. 검증 및 수용 기준
- `curl -X OPTIONS` 및 `curl -X POST` 재현 시 `Access-Control-Allow-Origin: http://localhost:50408` 헤더가 내려오고 브라우저 CORS 에러가 사라질 것.
- `flutter run -d chrome --web-port 50408`에서 로그인 성공/실패 흐름이 정상 동작.
- 백엔드 `cargo fmt`, `cargo test` 모두 통과.
- `stock_approval_system_api_v4.md` 또는 운영 문서에 허용 오리진 정책 및 설정 방법을 명시.
## 7. 후속 조치
- 백엔드 담당자가 실제 배포 서버의 환경 변수/리버스 프록시 설정을 확인 후 조치 내용을 공유.
- 수정 배포 이후 프런트 팀이 실서버 연결 테스트를 수행하고, 필요한 경우 추가 허용 오리진 목록을 요청.