흔한 에러 & 해결책
Connect Base를 처음 연동할 때 자주 마주치는 에러와 해결 방법입니다.
막혔을 때 가장 먼저 확인해야 할 6가지 시나리오를 모았습니다.
1. 401 Unauthorized — Public Key가 필요합니다
Public Key가 누락되었거나 형식이 잘못된 경우입니다.
실제 응답 예:
{"error": "Public Key가 필요합니다"}(또는"유효하지 않은 Secret Key입니다","Public Key는 사용할 수 없습니다. 유저 레벨 Secret Key(cb_sk_)를 사용하세요"등)
원인
.env파일을 만들었지만 dev 서버를 재시작하지 않음- 환경 변수 접두사가 빌드 도구와 맞지 않음 (Vite=
VITE_, Next.js=NEXT_PUBLIC_, Expo=EXPO_PUBLIC_) cb_pk_앞뒤로 공백·따옴표가 들어감- 콘솔에서 키를 폐기했는데 코드에 옛날 키가 남아있음
해결
// 디버깅: 키가 실제로 로드되었는지 먼저 확인
console.log('Public Key:', import.meta.env.VITE_CONNECT_BASE_PUBLIC_KEY?.slice(0, 8))
// 출력: "Public Key: cb_pk_ab" 가 나와야 함. undefined면 환경 변수 누락체크리스트:
-
.env파일이 프로젝트 루트에 있는가? - 환경 변수 이름에 빌드 도구 접두사가 있는가? (
VITE_,NEXT_PUBLIC_,EXPO_PUBLIC_) - dev 서버를
.env변경 후 재시작했는가? - 키 값에 따옴표나 공백이 없는가?
- 콘솔에서 해당 키가 활성 상태인가?
2. 브라우저 CORS 차단
브라우저에서 호출했는데 CORS 정책에 막힌 경우입니다. 콘솔(브라우저 개발자 도구)에는
Access to fetch at ... has been blocked by CORS policy 같은 메시지가 표시되며,
이는 백엔드 응답 본문이 아니라 브라우저가 직접 출력하는 메시지입니다.
원인
- 콘솔의 CORS 허용 도메인에 현재 도메인(예:
http://localhost:5173)이 등록되지 않음 - 잘못된
baseUrl사용 (예:api.connectbase.world대신connectbase.world)
해결
- 콘솔 → 사용 중인 앱 → 설정 → CORS 메뉴로 이동
- 허용 도메인 추가에 다음을 등록:
- 개발:
http://localhost:5173,http://localhost:3000 - 프로덕션:
https://yourdomain.com
- 개발:
- SDK 초기화 시
baseUrl은 기본값(https://api.connectbase.world)을 그대로 사용
서버(Node.js)에서 호출할 때는 CORS 정책이 적용되지 않습니다. 브라우저 호출에서만 발생합니다.
3. 429 Too Many Requests — Rate limit exceeded
플랜 한도를 초과해서 API 호출이 제한된 경우입니다.
실제 응답 예:
{"error": "Rate limit exceeded", "level": "app", "retry_after": "60", "message": "Your application has exceeded its rate limit. Please wait before making more requests."}—level은global/app/table/endpoint중 하나입니다.retry_after는 문자열 형태의 초 값("30"/"60"/"120")이며Retry-AfterHTTP 헤더에도 동일하게 실려옵니다.
원인
useEffect안에서 의존성을 잘못 설정해 무한 루프- 페이지 새로고침 시마다 매번 전체 데이터 재조회
- 여러 컴포넌트가 같은 데이터를 동시에 조회
해결: Exponential Backoff 재시도
import { ApiError } from 'connectbase-client'
async function withRetry<T>(fn: () => Promise<T>, maxAttempts = 3): Promise<T> {
for (let i = 0; i < maxAttempts; i++) {
try {
return await fn()
} catch (e) {
if (e instanceof ApiError && e.statusCode === 429 && i < maxAttempts - 1) {
// 1초, 2초, 4초 대기
await new Promise((r) => setTimeout(r, Math.pow(2, i) * 1000))
continue
}
throw e
}
}
throw new Error('재시도 한도 초과')
}
// 사용
const result = await withRetry(() => cb.database.getData('tbl_xxx'))근본 원인 해결:
- React Query / SWR 같은 캐시 레이어 사용
useEffect의존성 배열 점검- 무한 루프가 아닌지 Network 탭에서 호출 빈도 확인
- 한도가 너무 빡빡하면 콘솔에서 요금제 업그레이드
4. TypeError: Cannot read property 'files' of null
파일 업로드에서 <input type="file"> 요소가 DOM에 없거나 ref가 잘못 연결된 경우입니다.
원인
// ❌ 잘못된 예: input 요소가 없는데 querySelector로 찾음
const file = document.querySelector('input[type="file"]')!.files[0]해결: HTML과 JS를 함께 작성
<!-- index.html 또는 컴포넌트 JSX 안에 input 요소를 명시 -->
<input type="file" id="avatar" accept="image/*" />
<button id="upload-btn">업로드</button>import { cb } from './lib/connectbase'
const input = document.getElementById('avatar') as HTMLInputElement | null
const button = document.getElementById('upload-btn')
button?.addEventListener('click', async () => {
const file = input?.files?.[0]
if (!file) {
alert('파일을 먼저 선택해주세요')
return
}
try {
const result = await cb.storage.uploadFile('stg_your_storage_id', file)
console.log('업로드 완료:', result.url)
} catch (e) {
console.error('업로드 실패:', e)
}
})React를 사용한다면 useRef 가 더 안전합니다:
const fileRef = useRef<HTMLInputElement>(null)
const handleUpload = async () => {
const file = fileRef.current?.files?.[0]
if (!file) return
await cb.storage.uploadFile('stg_xxx', file)
}
return (
<>
<input ref={fileRef} type="file" accept="image/*" />
<button onClick={handleUpload}>업로드</button>
</>
)5. ReferenceError: cb is not defined / Cannot read properties of undefined (reading 'database')
SDK 초기화 순서 문제거나 import가 누락된 경우입니다.
원인
new ConnectBase(...)를 호출하기 전에cb.database.xxx를 사용- import 누락 (
import ConnectBase from 'connectbase-client') publicKey가undefined라서 SDK가 정상 초기화되지 않음
해결
// ✅ 모듈 최상단에서 한 번만 초기화하고 export
// src/lib/connectbase.ts
import ConnectBase from 'connectbase-client'
const publicKey = import.meta.env.VITE_CONNECT_BASE_PUBLIC_KEY
if (!publicKey) {
throw new Error('VITE_CONNECT_BASE_PUBLIC_KEY가 설정되지 않았습니다 (.env 파일 확인)')
}
export const cb = new ConnectBase({ publicKey })// ✅ 사용처에서 import
import { cb } from './lib/connectbase'
const result = await cb.database.getData('tbl_xxx')환경 변수가
undefined일 때 즉시 에러를 던지면 디버깅이 쉬워집니다.
6. Module not found: connectbase-client / Cannot find module 'connectbase-client'
패키지 설치/import 경로 문제입니다.
원인
npm install실행을 잊음pnpm-workspace.yaml등 모노레포 설정으로 다른 워크스페이스에 설치됨- 잘못된 패키지 이름 (
connect-base-client,@connectbase/client등은 존재하지 않음) - TypeScript path mapping 충돌
해결
# 1. 패키지 설치 확인
npm list connectbase-client
# 출력: [email protected] /path/to/project
# └── [email protected]
# 만약 비어있다면 설치
npm install connectbase-client
# 2. 캐시 / lock 파일 정리 후 재설치
rm -rf node_modules package-lock.json
npm install
# 3. import 경로 확인 (정확한 패키지 이름)// ✅ 올바른 import
import ConnectBase from 'connectbase-client'
// ❌ 존재하지 않는 패키지
import ConnectBase from 'connect-base-client' // 하이픈 위치 다름
import ConnectBase from '@connectbase/client' // 스코프 패키지 아님TypeScript에서 타입을 함께 import 할 때:
import ConnectBase, { ApiError, AuthError } from 'connectbase-client'그래도 안 되면
- SDK 레퍼런스 에서 사용 중인 메서드의 정확한 시그니처 확인
- REST API 문서 에서 응답 코드/필드명 직접 확인
- 콘솔의 로그(Logs) 메뉴에서 실시간 요청/응답 추적
- GitHub Issues 에 재현 코드와 함께 문의