Files
sundol/docs/troubleshooting.md
joungmin 4cde775809 Switch to user Chrome CDP for YouTube transcript, fix auth and ads
- Replace Playwright standalone browser with CDP connection to user Chrome
  (bypasses YouTube bot detection by using logged-in Chrome session)
- Add video playback, ad detection/skip, and play confirmation before transcript extraction
- Extract transcript JS to separate resource files (fix SyntaxError in evaluate)
- Add ytInitialPlayerResponse-based transcript extraction as primary method
- Fix token refresh: retry on network error during backend restart
- Fix null userId logout, CLOB type hint for structured_content
- Disable XFCE screen lock/screensaver
- Add troubleshooting entries (#10-12) and YouTube transcript guide

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 21:01:49 +00:00

310 lines
9.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 트러블슈팅 가이드
## 1. 프론트엔드 502 Bad Gateway
### 증상
- 브라우저에서 `502 Bad Gateway nginx/1.20.1` 표시
### 원인
Next.js standalone 빌드 시 `server.js``sundol-frontend/` 서브디렉토리에 생성되는 경우가 있음.
PM2가 `.next/standalone/server.js`를 찾지만 실제 파일은 `.next/standalone/sundol-frontend/server.js`에 위치.
### 확인 방법
```bash
pm2 list # sundol-frontend 상태 확인 (errored 여부)
pm2 logs sundol-frontend --err --lines 20 # 에러 로그 확인
# "Cannot find module .../standalone/server.js" 에러가 나면 이 문제
```
### 해결
```bash
# server.js 심볼릭 링크 생성
ln -sf /home/opc/sundol/sundol-frontend/.next/standalone/sundol-frontend/server.js \
/home/opc/sundol/sundol-frontend/.next/standalone/server.js
pm2 restart sundol-frontend
```
> `build.sh`에 이미 자동 처리 로직 포함되어 있음. 문제가 반복되면 build.sh 확인.
---
## 2. 프론트엔드 static 파일 404
### 증상
- 페이지는 로드되지만 CSS/JS가 404
- 브라우저 콘솔에 `_next/static/chunks/...js net::ERR_ABORTED 404` 다수 표시
### 원인
standalone 빌드에서 `.next/static` 심볼릭 링크가 올바른 위치에 걸리지 않음.
`server.js``standalone/sundol-frontend/` 안에서 실행되므로 static도 그 안에 있어야 함.
### 해결
```bash
# 중첩 디렉토리에도 static 링크 생성
ln -sf /home/opc/sundol/sundol-frontend/.next/static \
/home/opc/sundol/sundol-frontend/.next/standalone/sundol-frontend/.next/static
pm2 restart sundol-frontend
```
> `build.sh`에 자동 처리 로직 포함되어 있음.
---
## 3. 브라우저 로그인 모달 (HTTP Basic Auth 팝업)
### 증상
- 페이지 리프레시 시 브라우저 기본 로그인 팝업(username/password)이 뜸
- 특히 JWT 토큰이 만료되었거나 없을 때 발생
### 원인
Spring Security가 401 응답에 `WWW-Authenticate: Basic` 헤더를 포함.
브라우저가 이 헤더를 감지하면 자동으로 Basic Auth 로그인 다이얼로그를 표시.
### 해결
`SecurityConfig.java`에 커스텀 `authenticationEntryPoint` 설정:
```java
.exceptionHandling(exceptions -> exceptions
.authenticationEntryPoint((exchange, ex) -> {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
})
)
```
이렇게 하면 `WWW-Authenticate` 헤더 없이 401만 반환되어 브라우저 팝업이 뜨지 않음.
프론트엔드의 axios 인터셉터가 401을 감지하여 자동으로 토큰 갱신 처리.
---
## 4. YouTube 자막 가져오기 실패 (Caption XML 0 chars)
### 증상
- YouTube 트랜스크립트 가져오기 시 "자막 텍스트를 파싱할 수 없습니다" 에러
- 로그에 `Caption XML fetched: 0 chars` 표시
### 원인
YouTube timedtext API의 caption URL이 서명 기반으로, 브라우저 세션 외부에서 요청하면 빈 응답 반환.
`HttpURLConnection`이나 `context.request().get()`으로는 쿠키/세션이 유지되지 않음.
### 해결
두 가지 방법으로 fallback 처리:
1. **방법 A (우선)**: YouTube 페이지에서 '스크립트 표시' 패널을 열어 DOM에서 직접 텍스트 추출
2. **방법 B**: caption URL에 `&fmt=json3` 추가 후 `page.evaluate(fetch())`로 브라우저 내에서 요청
자세한 내용은 [crawling-guide.md](crawling-guide.md) 참조.
---
## 5. Playwright 브라우저 창이 사라짐
### 증상
- VNC에서 Playwright Chromium 창이 보이다가 사라짐
### 원인
`page.close()` 호출 시 마지막 탭이 닫히면 브라우저 창이 빈 상태가 됨.
### 해결
`page.close()` 대신 `page.navigate("about:blank")`으로 변경하여 탭을 유지:
```java
try {
page.navigate("about:blank");
} catch (Exception ignored) {
page.close();
}
```
---
## 6. Playwright 의존 라이브러리 누락 경고
### 증상
- 백엔드 로그에 `Host system is missing dependencies to run browsers` 경고
- `libicudata.so.66`, `libwoff2dec.so.1.0.2` 등 누락 표시
### 원인
Playwright가 WebKit 브라우저용 의존성까지 검사함. Chromium만 사용하면 대부분 문제없음.
### 확인
```bash
# Chromium 실행 가능 여부 직접 테스트
/home/opc/.cache/ms-playwright/chromium-1161/chrome-linux/chrome --version
```
### 해결 (경고 제거하려면)
```bash
sudo dnf install -y libicu woff2 harfbuzz-icu libjpeg-turbo libwebp enchant2 hyphen libffi
```
> `libx264`는 WebKit 전용이므로 Chromium만 사용 시 불필요.
---
## 7. Git Push 인증 실패
### 증상
- `git push origin main``could not read Username` 에러
### 원인
`.netrc`이나 `.git-credentials`에 인증 정보가 없음.
### 해결
`.env``GIT_USER`, `GIT_PASSWORD` 사용 (비밀번호에 특수문자 포함 시 URL 인코딩 필요):
```bash
set -a && source /home/opc/sundol/.env && set +a
ENCODED_PW=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$GIT_PASSWORD', safe=''))")
git push "https://${GIT_USER}:${ENCODED_PW}@gittea.cloud-handson.com/joungmin/sundol.git" main
```
---
## 8. LLM 구조화 내용이 잘림
### 증상
- 지식 정리(구조화) 결과가 중간에 끊김
### 원인
OCI GenAI의 `maxTokens`가 4096으로 제한되어 있어 긴 콘텐츠 정리 시 응답이 잘림.
### 해결
한 번에 전체를 정리하지 않고, 나눠서 요청하는 방식으로 변경:
1. **1차 호출**: Abstract + 목차만 생성
2. **2차~ 호출**: 목차 항목별로 상세 정리 요청 (각각 maxTokens 4096 내에서 충분)
3. **최종 조합**: 모든 결과를 합침
각 섹션 완료 시 DB에 중간 저장하여 프론트엔드에서 실시간 확인 가능.
---
## 9. VNC 접속 안 됨
### 증상
- VNC 클라이언트에서 접속 불가
### 확인
```bash
# VNC 서버 실행 확인
vncserver -list
# 방화벽 확인
sudo firewall-cmd --list-ports
# OCI 보안 목록에서 TCP 5901 인바운드 허용 여부 확인
```
### 해결
```bash
# VNC 서버 재시작
vncserver -kill :1
vncserver :1 -geometry 1920x1080 -depth 24
# 방화벽 포트 열기
sudo firewall-cmd --permanent --add-port=5901/tcp
sudo firewall-cmd --reload
```
자세한 내용은 [setup-xwindow.md](setup-xwindow.md) 참조.
---
## 10. VNC 접속 시 스크린 락(화면 잠금) 걸림
### 증상
- VNC로 접속하면 검은 화면에 로그인 다이얼로그가 뜸
- 잠시 자리를 비운 뒤 접속하면 사용자 비밀번호를 요구
### 원인
XFCE 스크린세이버가 기본 활성화되어 있어, 일정 시간 비활성 후 화면을 잠금.
### 해결
```bash
export DISPLAY=:1
# 스크린세이버 비활성화
xfconf-query -c xfce4-screensaver -p /saver/enabled --create -t bool -s false
# 화면 잠금 비활성화
xfconf-query -c xfce4-screensaver -p /lock/enabled --create -t bool -s false
xfconf-query -c xfce4-screensaver -p /lock/saver-activation/enabled --create -t bool -s false
# 모니터 절전(DPMS) 비활성화
xfconf-query -c xfce4-power-manager -p /xfce4-power-manager/dpms-enabled --create -t bool -s false
xfconf-query -c xfce4-power-manager -p /xfce4-power-manager/lock-screen-suspend-hibernate --create -t bool -s false
# 잠금 명령 제거
xfconf-query -c xfce4-session -p /general/LockCommand --create -t string -s ""
# 실행 중인 screensaver 프로세스 종료
ps aux | grep -E 'xfce4-screensaver|screensaver-dialog' | grep -v grep | awk '{print $2}' | xargs kill 2>/dev/null
```
---
## 11. YouTube 자막 추출 시 광고 때문에 실패
### 증상
- Playwright로 YouTube 페이지 로드 후 자막 패널이 열리지 않음
- VNC에서 보면 광고가 재생 중
### 원인
YouTube 동영상 앞에 프리롤 광고가 삽입되면 본 영상 UI(자막 패널 등)가 활성화되지 않음.
### 해결
코드에 `waitForAdsToFinish()` 로직이 포함되어 있음:
- 최대 60초간 2초 간격으로 광고 상태 확인
- 스킵 버튼(`.ytp-skip-ad-button` 등)이 나타나면 자동 클릭
- 광고가 끝나면 자막 추출 진행
수동으로 확인하려면 VNC에서 Playwright 브라우저 창을 직접 관찰.
---
## 12. 백엔드 재시작 시 로그인이 풀림
### 증상
- 백엔드(`pm2 restart sundol-backend`) 후 프론트엔드에서 로그인 화면으로 튕김
- 로그에 `User logged out: null` 표시
### 원인
1. 백엔드 재시작 중 프론트엔드가 API 호출 → 연결 실패(네트워크 에러)
2. axios 인터셉터가 401로 인식 → refresh 시도 → 서버 아직 안 떠서 실패
3. `onRefreshFailed` 콜백 → 자동 로그아웃 실행
### 해결
프론트엔드 axios 인터셉터에서 refresh 실패 시 네트워크 에러이면 3초 후 최대 2회 재시도:
```typescript
const attemptRefresh = async (retryCount: number): Promise<string> => {
try {
const res = await api.post<LoginResponse>("/api/auth/refresh");
return res.data.accessToken;
} catch (err) {
const isNetworkError = !((err as AxiosError).response);
if (isNetworkError && retryCount < 2) {
await new Promise((r) => setTimeout(r, 3000));
return attemptRefresh(retryCount + 1);
}
throw err;
}
};
```
백엔드 logout에도 userId null 체크 추가:
```java
if (userId == null) {
log.warn("Logout called with null userId, ignoring");
return;
}
```
### 예방
- 백엔드 재시작 시 기동 완료까지 약 10~25초 소요
- 프론트엔드는 네트워크 에러 시 최대 9초(3초 × 3회) 대기 후 재시도