Files
AutonetSellCar/TROUBLESHOOTING.md
AutonetSellCar Deploy b1afea79d9 Add SOLD OUT badge and improve deployment docs
- Add SOLD OUT overlay on car detail page image
- Add SOLD OUT badge next to car name
- Add Sold Out status in Admin Cars detail view
- Add soldout field to Car TypeScript interface
- Create PRODUCTION_VALUES.md for deployment reference
- Update CLAUDE.md with CRITICAL deployment section
- Update TROUBLESHOOTING.md with recurring errors

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-03 09:05:16 +09:00

11 KiB

AutonetSellCar 트러블슈팅 가이드

이 문서는 배포 및 운영 중 발생한 문제와 해결 방법을 정리합니다.


2024-12-30: 운영서버 이미지 표시 문제

증상

  • 개발서버(192.168.0.204)에서는 이미지가 정상 표시
  • 운영서버(192.168.0.202)에서 외부 PC로 접속 시 이미지가 표시되지 않음
  • 브라우저 개발자 도구에서 이미지 요청 URL이 http://localhost:8000/...으로 되어 있음

원인 분석

1차 원인: 서버2 소스 코드 미동기화

문제: 서버2의 프론트엔드 소스 코드가 개발서버와 동기화되지 않아 오래된 코드가 배포됨

위치 코드
서버4 (개발) process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000'
서버2 (운영) 'http://localhost:8000' (하드코딩)

영향받은 파일:

  • /admin/hero-banners/page.tsx
  • /admin/cars/page.tsx
  • 기타 관리자 페이지

2차 원인: 차량 상세 페이지 특수 패턴

문제: /cars/[id]/page.tsx에서 다른 방식으로 localhost가 하드코딩됨

// 문제 코드
const getImageUrl = (url: string | undefined): string => {
  if (!url) return '';
  if (url.startsWith('http://') || url.startsWith('https://')) {
    return url;
  }
  // 포트만 동적으로 추출하고 localhost는 하드코딩
  const backendPort = process.env.NEXT_PUBLIC_API_URL?.includes('8001') ? 8001 : 8000;
  return `http://localhost:${backendPort}${url}`;
};

해결 방법

Step 1: 소스 코드 동기화

# 서버4 (Windows)에서 실행
scp -r D:/Workspace/claudeCode/AutonetSellCar.com/frontend/src damon@192.168.0.202:/opt/autonet/production/frontend/

Step 2: 차량 상세 페이지 수정

// 수정된 코드 (/cars/[id]/page.tsx)
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000';

const getImageUrl = (url: string | undefined): string => {
  if (!url) return '';
  if (url.startsWith('http://') || url.startsWith('https://')) {
    return url;
  }
  return `${API_BASE_URL}${url}`;
};

Step 3: Docker 이미지 재빌드

# 서버2에서 실행
cd /opt/autonet/production/frontend

# 캐시 없이 재빌드 (중요!)
docker build --no-cache -t autonet-frontend-v2 .

# 컨테이너 교체
docker stop autonet-frontend
docker rm autonet-frontend
docker run -d --name autonet-frontend -p 3000:3000 autonet-frontend-v2

Step 4: 확인

# localhost:8000이 없는지 확인
docker exec autonet-frontend sh -c "grep -l 'localhost:8000' /app/.next/static/chunks/app/**/*.js 2>/dev/null || echo 'No localhost:8000 found'"

# 올바른 URL이 있는지 확인
docker exec autonet-frontend sh -c "grep -o '192.168.0.202:8000' /app/.next/static/chunks/app/**/*.js 2>/dev/null | wc -l"

핵심 개념: Next.js 환경변수

중요: Next.js의 NEXT_PUBLIC_* 환경변수는 빌드 시점에 JavaScript 번들에 포함됩니다.

시점 설명
빌드 시점 NEXT_PUBLIC_* 변수 값이 JS 코드에 직접 삽입됨
런타임 이미 삽입된 값이 사용됨 (변경 불가)

따라서:

  • .env.production 수정 후 반드시 재빌드 필요
  • Docker 환경에서는 Dockerfile에 ARG/ENV 설정 필요
# Dockerfile 예시 (builder 단계)
ARG NEXT_PUBLIC_API_URL=http://192.168.0.202:8000
ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
RUN npm run build

올바른 이미지 URL 패턴

모든 프론트엔드 파일에서 이미지 URL을 생성할 때 다음 패턴을 사용해야 합니다:

// 올바른 패턴
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000';

const getImageUrl = (url: string): string => {
  if (!url) return '';
  if (url.startsWith('http://') || url.startsWith('https://')) {
    return url;
  }
  return `${API_BASE_URL}${url}`;
};

잘못된 패턴 (사용 금지):

// 하드코딩 - 절대 사용 금지!
return `http://localhost:8000${url}`;

// 포트만 추출 - 사용 금지!
const port = process.env.NEXT_PUBLIC_API_URL?.includes('8001') ? 8001 : 8000;
return `http://localhost:${port}${url}`;

디버깅 명령어 모음

프론트엔드 환경변수 확인

# 컨테이너 환경변수
docker exec autonet-frontend printenv | grep API

# .env.production 파일
cat /opt/autonet/production/frontend/.env.production

# Dockerfile ARG/ENV 확인
grep -E "(ARG|ENV).*NEXT_PUBLIC" /opt/autonet/production/frontend/Dockerfile

빌드된 JS 파일 검사

# localhost:8000 검색
docker exec autonet-frontend sh -c "grep -r 'localhost:8000' /app/.next/static/chunks/ | head -5"

# 올바른 URL 검색
docker exec autonet-frontend sh -c "grep -r '192.168.0.202:8000' /app/.next/static/chunks/ | head -5"

이미지 직접 접근 테스트

# 백엔드에서 이미지 직접 접근
curl -I http://192.168.0.202:8000/uploads/cars/1/image_0.jpg

# API 응답에서 이미지 URL 확인
curl -s http://192.168.0.202:8000/api/cars/1 | jq '.images'

컨테이너 상태 확인

docker ps -a | grep autonet
docker logs autonet-frontend --tail 20
docker logs autonet-backend --tail 20

예방 조치

1. 코드 동기화 자동화

개발 완료 후 운영 서버 배포 시 항상 최신 코드를 동기화:

# 배포 전 동기화 스크립트
scp -r frontend/src damon@192.168.0.202:/opt/autonet/production/frontend/

2. 빌드 전 환경변수 확인

# 빌드 전 확인 사항
echo "=== .env.production ==="
cat /opt/autonet/production/frontend/.env.production

echo "=== Dockerfile ENV ==="
grep "NEXT_PUBLIC" /opt/autonet/production/frontend/Dockerfile

3. 빌드 후 검증

# 빌드 후 localhost 하드코딩 검사
docker exec autonet-frontend sh -c "grep -r 'localhost:8000' /app/.next/static/chunks/ && echo 'ERROR: localhost found!' || echo 'OK: No localhost hardcoding'"

체크리스트

배포 시 확인해야 할 항목:

  • 서버2 소스 코드가 최신인가?
  • .env.production에 올바른 URL이 설정되어 있는가?
  • Dockerfile에 ARG/ENV가 설정되어 있는가?
  • --no-cache 옵션으로 빌드했는가?
  • 빌드된 JS에 localhost:8000이 없는가?
  • 외부 PC에서 이미지가 정상 표시되는가?


2026-01-02: 반복되는 배포 오류 종합 (CRITICAL)

문제 1: DB_NAME 오류 (mongolcar vs autonet)

증상:

  • 사이트에 차량/배너 없음
  • API가 빈 배열 [] 반환
  • 로그인은 되지만 데이터 없음

원인:

  • 수동 docker run 시 DB_NAME을 mongolcar로 잘못 입력
  • PostgreSQL에 mongolcarautonet 두 DB가 존재
  • mongolcar는 비어있고, 실제 데이터는 autonet에 있음

확인 방법:

# 현재 연결된 DB 확인
ssh server2 "docker exec autonet-backend python -c \"from app.config import get_settings; print('DB_NAME:', get_settings().DB_NAME)\""

# DB별 데이터 확인
ssh server1 "docker exec postgres-primary psql -U admin -d autonet -c 'SELECT COUNT(*) FROM cars;'"
ssh server1 "docker exec postgres-primary psql -U admin -d mongolcar -c 'SELECT COUNT(*) FROM cars;'"

해결:

  • DB_NAME=autonet 확인 후 컨테이너 재시작
  • CLAUDE.md의 표준 명령어 복사해서 사용

문제 2: 비밀번호 @ 파싱 오류

증상:

  • could not translate host name "1122@192.168.0.201"
  • 백엔드 컨테이너 계속 재시작

원인:

  • DB_PASSWORD=roskfl@1122@가 URL에서 호스트 구분자로 인식됨
  • config.pyquote_plus() URL 인코딩이 없거나, Docker 이미지가 오래됨

확인 방법:

# config.py에 quote_plus 있는지 확인
ssh server2 "docker exec autonet-backend cat /app/app/config.py | grep quote_plus"

해결:

  1. config.pyquote_plus() 적용 확인
  2. Docker 이미지 재빌드: docker build --no-cache -t production-backend ./backend

문제 3: 이미지 404 (잘못된 uploads 경로)

증상:

  • /uploads/cars/40/image_0.jpg → 404
  • Hero 배너에 기본 이미지만 표시

원인:

  • Production 컨테이너가 잘못된 경로 마운트: /home/damon/mongolcar/data/uploads (비어있음!)
  • 실제 이미지는 /opt/autonet/production/backend/uploads에 있음

확인 방법:

# 올바른 경로 (파일 있어야 함)
ssh server2 "ls /opt/autonet/production/backend/uploads/cars/ | head -5"

# 잘못된 경로 (비어있음!)
ssh server2 "ls /home/damon/mongolcar/data/uploads/cars/ 2>/dev/null || echo 'Empty or not exists'"

해결:

  • 볼륨 마운트를 -v /opt/autonet/production/backend/uploads:/app/uploads로 변경
  • CLAUDE.md의 표준 명령어 사용

문제 4: Mixed Content (HTTPS/HTTP)

증상:

  • 브라우저 콘솔에 Mixed Content 오류
  • API 요청 실패
  • 사이트에 기본 이미지만 표시

원인:

  • Frontend가 NEXT_PUBLIC_API_URL=http://192.168.0.202:8000으로 빌드됨
  • HTTPS 페이지에서 HTTP API 호출 시 브라우저가 차단

확인 방법:

# 빌드된 JS에서 API URL 확인
ssh server2 "docker exec autonet-frontend grep -r '192.168.0.202:8000' /app/.next/static/chunks/ | head -1"

해결:

# Frontend 빌드 전 필수!
ssh server2 "echo 'NEXT_PUBLIC_API_URL=https://autonetsellcar.com' > /home/damon/mongolcar/frontend/.env.production"
ssh server2 "cd /home/damon/mongolcar/frontend && docker build --no-cache -t production-frontend ."

문제 5: .env 파일이 디렉토리로 생성됨

증상:

  • 로그인 실패
  • (sqlite3.OperationalError) no such column 에러
  • 환경변수 로드 실패

원인:

  • docker-compose 볼륨 마운트 시 .env 파일이 없으면 디렉토리로 생성됨

확인 방법:

ssh server2 "ls -la /opt/autonet/production/backend/.env"
# 'd'로 시작하면 디렉토리 (문제!)

해결:

# 디렉토리면 삭제 후 파일로 재생성
ssh server2 "rm -rf /opt/autonet/production/backend/.env"
ssh server2 "cat > /opt/autonet/production/backend/.env << 'EOF'
USE_SQLITE=False
DB_HOST=192.168.0.201
DB_PORT=5432
DB_NAME=autonet
DB_USER=admin
DB_PASSWORD=roskfl@1122
EOF"

재발 방지 체크리스트

배포 시 반드시 확인:

  • DB_NAME이 autonet인가? (절대 mongolcar 아님!)
  • Uploads 경로가 /opt/autonet/production/backend/uploads인가?
  • Frontend .env.productionhttps://autonetsellcar.com이 설정되어 있는가?
  • --no-cache로 이미지를 빌드했는가?
  • 배포 후 curl https://autonetsellcar.com/api/hero-banners/로 데이터 확인했는가?

변경 이력

날짜 문제 해결
2026-01-02 DB_NAME 오류 (mongolcar vs autonet) DB_NAME=autonet 확인, 표준 명령어 사용
2026-01-02 비밀번호 @ 파싱 오류 quote_plus() URL 인코딩 적용
2026-01-02 이미지 404 (잘못된 uploads 경로) /opt/autonet/production/backend/uploads 사용
2026-01-02 Mixed Content 오류 NEXT_PUBLIC_API_URL=https://autonetsellcar.com
2024-12-30 운영서버 이미지 미표시 (배너) 소스 코드 동기화 + Docker 재빌드
2024-12-30 차량 상세 이미지 미표시 getImageUrl() 함수 수정