API
API 세션 인증이 로컬에서는 되는데 배포 후 안 될 때
로컬 개발 환경과 운영 환경의 인증 설정 차이를 추적하고 해결하기.
API 개발을 하다 보면 로컬에서는 잘 동작하던 인증 로직이 운영 환경에서 갑자기 안 되는 경험을 한다. 대부분 환경 설정 차이에서 비롯된다.
먼저 인증 상태를 확인하자
curl -i -H 'Authorization: Bearer token' 'https://api.example.com/me'
응답 코드를 보자.
- 200: 정상
- 401: 토큰 없거나 만료됨
- 403: 권한 부족
- 500: 서버 에러
상태 코드에 따라 원인이 달라진다.
로컬과 운영의 인증 차이
토큰 생성 방식
로컬에서는 테스트 토큰을 하드코딩할 수 있지만, 운영에서는 자동 갱신되는 토큰을 써야 한다.
// ❌ 로컬 개발용
const token = 'test-token-abc123';
// ✅ 운영
const token = await getAuthToken(); // API에서 동적으로 받기
쿠키 vs 헤더
로컬에서는 Authorization 헤더로 토큰을 전달하지만, 운영에서는 쿠키를 쓸 수 있다.
# 로컬: 헤더로 전달
curl -H 'Authorization: Bearer token' https://localhost:3000
# 운영: 쿠키로 전달
curl -b 'session=abc' https://api.example.com
이게 다르면 withCredentials 설정도 달라진다.
요청 파라미터 확인
curl -i 'https://api.example.com/api/items?page=1' \
-H 'Authorization: Bearer token' \
-H 'Content-Type: application/json'
확인할 것:
- 쿠키가 제대로 첨부되었는가?
- CORS 헤더가 있는가?
- 요청 바디 형식이 맞는가?
응답 Body 확인
단순히 상태 코드만 보지 말고, 실제 응답 메시지를 봐야 한다.
{
"error": "invalid_token",
"error_description": "Token expired at 2024-06-30 14:30:00"
}
이 정보가 원인을 알려주는 경우가 많다.
환경 변수 체크리스트
로컬과 운영에서 다를 수 있는 것들:
# .env 파일 확인
echo $API_SECRET
echo $API_BASE_URL
echo $SESSION_TIMEOUT
echo $CORS_ORIGIN
로컬에서는 http://localhost:3000이지만 운영에서는 https://api.example.com일 수 있다.
상태 코드별 대응
401 (Unauthorized)
if (response.status === 401) {
// 토큰 갱신 시도
const newToken = await refreshToken();
// 원래 요청 재시도
}
403 (Forbidden)
사용자는 인증되었지만 이 리소스에 접근할 권한이 없다. 권한 설정을 확인해야 한다.
500 (Server Error)
서버 로그를 확인한다.
sudo journalctl -u api-service -n 50
실제로 재현되는지 확인
# 로컬
flutter run # 또는 npm start
# 운영
curl -H 'Authorization: Bearer $(cat ~/.tokens/api-token)' \
https://api.example.com/api/user/me
같은 요청인데 결과가 다르면, 확실히 환경 차이다.
체크리스트
- 토큰이 실제로 유효한가? (갱신되었는가?)
- 요청이 올바른 엔드포인트로 가고 있는가?
- 헤더와 쿠키 설정이 일치하는가?
- CORS 설정이 올바른가?
- 타임존이 다르지는 않는가? (토큰 만료 시간)
마지막으로, 로그를 자세히 보면 대부분의 인증 문제는 해결된다. 작은 환경 차이가 큰 장애로 이어지는 게 API 인증의 특징이니까.