본문으로 건너뛰기

사용자 관리

Connect Base 사용자 관리 심화 가이드입니다.

역할 및 권한

AppMember.role 은 free-form 문자열 컬럼입니다(기본값: 빈 문자열). 아래 4개는 예시 컨벤션일 뿐 시스템이 자동으로 인식하는 값은 아닙니다 — RLS 규칙 / 함수 / 워크플로우에서 auth.role 로 직접 비교해 권한을 구현합니다.

역할 (예시)설명권한 (예시)
owner앱 소유자모든 권한
admin관리자대부분 권한 (앱 삭제 제외)
member일반 멤버기본 CRUD
guest게스트읽기만

📌 콘솔의 owner/admin 은 별개의 콘솔 사용자(User) 권한이며, 앱 멤버(AppMember) 와 다른 개념입니다.

커스텀 역할

콘솔에서 커스텀 역할 생성:

json
{
  "name": "moderator",
  "permissions": [
    "users:read",
    "users:update",
    "content:read",
    "content:update",
    "content:delete"
  ]
}

권한 체크

SDK에서 확인

typescript
const me = await cb.auth.getMe()

// 권한은 custom_data 에 저장합니다
const permissions = (me.custom_data?.permissions ?? []) as string[]

if (permissions.includes('users:delete')) {
  // 삭제 버튼 표시
}

API에서 확인

서버리스 함수에서 권한 확인:

javascript
export async function handler(event, context) {
  const user = context.user

  if (!user.permissions.includes('admin:access')) {
    return {
      statusCode: 403,
      body: JSON.stringify({ error: 'Forbidden' })
    }
  }

  // 관리자 기능 실행
}

세션 관리

토큰 구조

Access Token (1시간)
├── userId
├── appId
├── role
├── permissions
└── exp

Refresh Token (7일)
├── userId
├── appId
└── exp

토큰 갱신 / 세션 만료 처리

📌 토큰 콜백은 SDK 초기화 시 옵션으로 등록합니다. cb.auth.onXxx(...) 같은 메서드는 존재하지 않습니다.

typescript
import ConnectBase from 'connectbase-client'

const cb = new ConnectBase({
  publicKey: 'cb_pk_...',

  // access_token / refresh_token 이 갱신될 때마다 호출
  onTokenRefresh: ({ accessToken, refreshToken }) => {
    localStorage.setItem('cb_access_token', accessToken)
    localStorage.setItem('cb_refresh_token', refreshToken)
  },

  // 401 등 인증 실패 시 호출
  onAuthError: (error) => {
    console.error('인증 실패:', error)
  },

  // refresh_token 까지 만료되어 재로그인이 필요할 때 호출
  onTokenExpired: () => {
    localStorage.removeItem('cb_access_token')
    localStorage.removeItem('cb_refresh_token')
    window.location.href = '/login'
  }
})

소셜 로그인

지원 프로바이더

SDK OAuthProvider 타입 기준 6종:

  • Google
  • Naver
  • Kakao
  • Apple
  • GitHub
  • Discord

소셜 로그인 시 AppMember.email 컬럼에 이메일이 자동 저장됩니다(Apple 의 경우 relay 주소). 콘솔 → 인증 설정에서 사용할 프로바이더만 ON 으로 토글하세요.

설정

콘솔 > 설정 > 인증에서 각 프로바이더 설정:

  1. Client ID 입력
  2. Client Secret 입력
  3. Redirect URL 설정

사용

typescript
// 리다이렉트 방식 로그인 (권장) — 모든 환경에서 안정적
await cb.oauth.signIn('google', 'https://myapp.com/callback')

// 콜백 페이지에서 결과 처리 (3.23.0+: Promise 반환)
const result = await cb.oauth.getCallbackResult()

// 팝업 방식 로그인 (COOP 정책 제한 주의)
const result = await cb.oauth.signInWithPopup('google', 'https://myapp.com/callback')

모범 사례

1. 최소 권한 원칙

필요한 최소한의 권한만 부여:

typescript
// ❌ 나쁜 예: 모든 권한
{ role: 'admin' }

// ✅ 좋은 예: 필요한 권한만
{
  role: 'custom',
  permissions: ['products:read', 'products:update']
}

2. 정기적 세션 검증

typescript
// 주기적으로 세션 유효성 확인
setInterval(async () => {
  try {
    await cb.auth.getMe()
  } catch {
    // 세션 만료, 재로그인 요청
    showLoginModal()
  }
}, 5 * 60 * 1000) // 5분마다

3. 감사 로그

중요 작업은 로깅:

typescript
async function deleteUser(userId: string) {
  await cb.database.createData('tbl_audit_logs', {
    data: {
      action: 'user_deleted',
      targetId: userId,
      performedBy: currentUser.id,
      timestamp: new Date().toISOString()
    }
  })

  await cb.database.deleteData('tbl_users', userId)
}

앱간 / 플랫폼 이슈 큐 (2026-05-10)

사용자 / SDK / MCP 에서 발생한 이슈를 비동기 큐로 발행할 수 있습니다. 워크플로우 / 웹훅과 달리 응답을 기다리지 않고, 운영자가 처리 후 답신을 보내는 비동기 양방향 채널 입니다.

Cross-App Issue Queue

oauth:issue:report scope 를 가진 Consumer 가 Provider 앱 운영자에게 이슈를 발행하는 큐입니다. pull-based 로 운영자가 큐에서 가져가며, AI 가 자동 응답 불가하면 needs_human 으로 escalation 합니다.

typescript
// Consumer 앱이 Provider 운영자에게 이슈 발행
await cb.support.reportToProvider({
  providerAppId: 'provider-app-id',
  accessToken: providerToken,           // OAuth 발급 토큰
  subject: '주문이 결제됐는데 처리 안 됨',
  body: 'order_id=order_xxx 가 30분째 pending 상태입니다.',
  metadata: { order_id: 'order_xxx' }
})

새로운 앱간 비동기 통신은 이 큐를 재사용하는 것을 권장합니다.

Platform Issue Queue

ConnectBase 자체 버그 / 문의를 위한 별도 큐(platform_issues 테이블) 입니다. End-user / SDK / MCP 에서 발행하면 IsSystemAdmin 권한 사용자가 처리합니다.

typescript
// 플랫폼 자체에 문제 보고
await cb.support.reportToPlatform({
  subject: 'SDK 가 404 를 반환',
  body: 'cb.database.queryData 호출이 갑자기 404 가 됩니다.',
  category: 'sdk_bug'
})

두 큐는 entity 가 분리되어 있어, Provider 앱이 자기 앱의 사용자 이슈만 보고 / ConnectBase 플랫폼 이슈는 별도 채널로 운영됩니다.