테마
트러블슈팅
이 플랫폼의 실패는 대부분 예외가 아니라 침묵으로 나타난다. 어느 단계에서 걸려도 포탈은 정상적으로 뜨고, 그 BP만 없다. 그래서 "오류가 안 나는데 안 된다"가 기본값이라고 생각하는 편이 빠르다.
가장 먼저 볼 것은 포탈 부팅 로그다. 건너뛴 BP와 그 이유가 남는다.
BP가 아예 나타나지 않는다
부팅 스캔의 어느 단계에서 걸렸는지 순서대로 좁힌다(install-to-portal.md §3).
| 증상 | 원인 | 확인 |
|---|---|---|
| 로그에 BP 이름조차 없다 | 설치 디렉터리 배치가 틀렸다 | <설치 디렉터리>/<id>/bp-manifest.yaml이 실재하는지 |
| "unknown apiVersion" | 포탈이 이 서술자 포맷을 모른다 | 포탈 버전 확인 |
| 호스트 계약 불일치 | runtime.hostContract 범위 밖 | 포탈의 HOST_CONTRACT_VERSION과 대조 |
| DB 방언 불일치 | backend.database.providers에 운영 방언이 없다 | 방언 추가 후 재빌드 |
| "register not found" | 번들이 register를 export하지 않는다 | node -e "import('./backend/index.mjs').then(m=>console.log(typeof m.register))" |
ENOENT 후 스킵 | 번들의 자산 상대경로가 어긋났다 | build-and-package.md §2 "런타임 자산 경로" |
컨트롤러가 등록되지 않는다 (404인데 오류는 없다)
거의 항상 호스트 제공 모듈의 사본이 둘인 경우다.
@nestjs/common사본이 둘 → DI 토큰이 서로 다른 객체가 되어 주입이 안 붙는다reflect-metadata사본이 둘 → 데코레이터 메타데이터가 다른 저장소에 쌓인다
확인: 번들에 그 모듈 코드가 들어갔는지 본다. external에 HOST_PROVIDED_MODULES를 넘겼는지 다시 확인한다.
bash
grep -c "class BadRequestException" dist/backend/index.mjs # 0이어야 한다DI 주입이 undefined다
emitDecoratorMetadata 없이 번들했다. esbuild 단독으로는 이 옵션이 지원되지 않으므로 .ts를 ts.transpileModule로 먼저 변환해야 한다 — build-and-package.md §2.
컴파일은 통과하고 런타임에만 드러나므로 빌드 성공을 신호로 삼으면 안 된다.
DB 접속은 되는데 쿼리가 실패한다
Missing field 'format' 같은 프로토콜 오류라면, BP가 빌드 시점에 본 Prisma 버전과 포탈이 제공하는 버전이 다른 것이다. 실제로 겪은 사례다 — 양쪽 다 ^7.8.0이었는데 BP는 7.9.1로, 포탈은 7.8.0으로 해석됐다.
bash
node -e "import('@starj-portal/bp-backend-sdk').then(m=>console.log(m.HOST_PROVIDED_VERSIONS))"이 값으로 캐럿 없이 고정하고 다시 빌드한다.
마이그레이션이 적용되지 않는다
backend.database.schemaDir을 선언했는지 확인한다. 생략하면 포탈은 이 BP의 마이그레이션에 손대지 않는다.schema.prisma와migrations/가 같은 폴더에 있는지 확인한다. Prisma CLI가 스키마 파일과 같은 디렉터리에서 마이그레이션을 찾기 때문이다.bp-manifest.yaml의version을 올렸는지 확인한다. 같은 버전이면 다시 돌지 않는다.
화면이 안 뜬다 / "위젯이 등록되지 않았습니다"
window.__BP_WIDGETS__의 키가bp-manifest.yaml의id와 정확히 같은지.- 번들 포맷이
iife인지.esm으로 만들면 전역 등록 코드가 실행되지 않는다. - 브라우저 콘솔에서 번들 스크립트가 404가 아닌지.
화면은 뜨는데 API가 403이다
domainId를 쿼리 파라미터로 안 넘겼다. 가장 자주 밟는 함정이다.
ts
fetch(`${host.apiBasePath}/items?domainId=${encodeURIComponent(host.domainId)}`)셸의 상단 메뉴가 사라진다 / 위젯 스타일이 깨진다
위젯 CSS가 셸과 같은 캐스케이드에서 충돌했다. Shadow DOM 경계를 만들어야 한다 — frontend-guide.md §3.
위젯 안의 모달만 스타일을 잃는다면 document.body로 포탈을 만든 것이다. shadow root 안에서 렌더링한다.
설치는 됐는데 사용자에게 화면이 안 보인다
설치·활성화·권한 부여는 별개다.
- 그 도메인에서 활성화됐는지 (관리자)
- 사용자에게 권한이 부여됐는지 (관리자) —
defaultAuthorities가 만드는 것은 권한의 정의까지다 apps[].dispYn을false로 두지 않았는지
업그레이드했는데 화면·권한이 새로 생겼다
apps[].id 또는 menu[].id를 바꿨다. 이 값들은 upsert 기준이라 바꾸면 기존 레코드와 이어지지 않는다. 이전 id로 되돌린다.