커넥터로 회사 데이터 연결하기

회사가 이미 쓰는 데이터베이스를 앱에서 조회하는 방법이에요. 승인받은 범위만, 안전한 쿼리로 가져와요.

회사에서 쓰는 데이터베이스를 앱에 안전하게 잇는 통로가 커넥터예요.
승인만 받아 두면 앱 코드에서 바로 조회할 수 있어요 — 접속 정보는 AxHub가 맡아서, 코드에는 회사 DB 비밀번호가 전혀 남지 않아요.

준비물

  • 승인받은 커넥터 — 회사 관리자가 연결을 등록하고 내 계정에 접근을 승인(grant)해 둬야 해요. 아직 없다면 관리자에게 요청하세요 (커넥터 등록하고 승인하기)
  • SDK — SDK 설치하기를 먼저 보세요

내가 쓸 수 있는 커넥터 확인

승인이 됐는지, 커넥터 이름과 ID를 먼저 봐요.

axhub connectors mine                      # 내가 조회할 수 있는 커넥터 (이름 · 엔진)
axhub connectors mine --json               # 같은 목록 — .data[].id 가 커넥터 ID(UUID)
axhub connectors resources <connector_id>  # 그 커넥터의 리소스 트리

<connector_id>에는 이름이 아니라 axhub connectors mine --json의 .data[].id(UUID)를 넣어요. 사람이 읽는 axhub connectors mine 출력에는 ID가 나오지 않아요.

목록이 비어 있으면 아직 승인이 안 된 거예요 — grant 없는 커넥터는 목록에조차 나오지 않아요.

앱에서 조회하기

값은 반드시 params로 넘기세요. SQL 문자열에 사용자 입력을 직접 붙이면 값에 명령을 섞어 넣는 공격에 열려요.

PostgreSQL 커넥터는 자리표시자로 $1 · $2를 써요 — ?를 쓰면 백엔드에서 500이 나요. 테이블 이름에는 public. 같은 스키마도 함께 적어요.

템플릿으로 만든 앱이라면

Next.js · Astro 템플릿에는 조회 헬퍼가 이미 들어 있어요. 커넥터 이름만 알면 돼요.

import { queryConnector } from '@/lib/axhub-server';

const { rows } = await queryConnector<{ id: number; name: string }>({
  connector: 'my-db',   // 커넥터 이름 — UUID 아니에요
  sql: 'SELECT id, name FROM public.employees WHERE active = $1 LIMIT $2',
  params: [true, 100],
});

이 한 번의 호출이 커넥터 찾기 → 세션 열기 → 조회 → 세션 닫기를 다 해요. 권한이 없으면 PermissionDeniedError(403), 세션이 만료됐으면 UnauthenticatedError(401)로 던져져요.

직접 조회하기

헬퍼를 안 쓴다면 세 단계를 직접 밟아요. 게이트웨이 세션은 "이 연결로 잠깐 조회하겠다"고 여는 임시 통로예요 — 8시간이 지나면 자동으로 닫혀요.

const gw = sdk.tenant(tenantId).gateway;   // ← 회사 UUID (슬러그 아님)

const session = await gw.sessions.create({ connectorId });   // ← 커넥터 UUID (이름 아님)
try {
  const { rows } = await gw.query.run({
    sessionId: session.id,
    sql: 'SELECT id, name FROM public.employees WHERE active = $1 LIMIT $2',
    params: [true, 10],
  });
} finally {
  await gw.sessions.end(session.id);
}

게이트웨이는 회사를 UUID로만 받아요 — 슬러그를 넣으면 400 invalid_format이 나요. UUID는 sdk.identity.me()의 tenants에서 찾아요.

내가 접근 가능한 커넥터 · 리소스는 gw.me.connectors() · gw.me.connectorResources(connectorId)로 확인해요.

터미널에서는 같은 일을 이렇게 해요.

axhub gateway session start --connector-id <connector_id>   # 커넥터 UUID (이름 아님)
axhub gateway query --session-id <session_id> \
  --sql 'SELECT id, name FROM public.employees LIMIT 10' --execute
axhub gateway session end <session_id>

DB 말고 REST API · 문서 저장소 · Google Drive에 연결한 커넥터는 axhub gateway invoke · document-invoke · file-invoke로 불러요.

승인에는 테이블 범위 말고 행 · 열 단위 정책도 있어요 — 특정 행만 보이거나, 열이 빠지거나 ***로 가려져 올 수 있어요. 정책은 관리자가 정해요 → 커넥터 등록하고 승인하기 › 행·열까지 잠그기.

막혔을 때

상황무슨 뜻인가요
axhub connectors mine이 비어 있어요아직 grant가 없어요 — 관리자에게 승인을 요청하세요
403 scope_requires_target테이블 범위가 지정된 grant예요. 자유 SQL 대신 승인된 리소스를 지정해 조회하세요
403 scope_out_of_range승인 범위 밖의 리소스예요
403 PermissionDeniedErrorpreset이 허용하지 않는 액션이에요. 기본 읽기 전용 preset은 SELECT · WITH · EXPLAIN만 통과시켜요
400 invalid_format회사를 슬러그로, 또는 커넥터를 이름으로 넘겼어요 — 둘 다 UUID여야 해요
404 no_active_grant커넥터 UUID가 틀렸거나 오래됐어요(지워진 커넥터). 그 커넥터에 grant가 없거나 만료돼도 같은 응답이 와요 — axhub connectors mine --json의 .data[].id를 다시 확인하세요
값이 ***로 와요관리자가 그 열에 마스킹 정책을 걸었어요. 가린 열로도 정렬 · 비교는 되지만 값은 안 보여요
있어야 할 열이 응답에 없어요열 allow/deny 정책이에요 — 쿼리가 아니라 권한 문제니 관리자에게 문의하세요
column "..." does not exist — 분명 없는 열인데grant에 행 필터 정책이 걸려 있어요. 조회 SELECT 목록에 그 열을 포함하거나 SELECT *로 조회하세요
LIMIT보다 행이 적게(0건까지) 와요행 필터는 LIMIT 다음에 걸려요 — 잘린 게 아니라 필터를 통과한 행이 그만큼이에요

모든 조회는 허용 · 거부 여부와 함께 감사 기록으로 남아요.

이렇게 보이면 성공

axhub connectors mine에 커넥터가 보이고, 쿼리 결과로 행(rows)이 돌아오면 성공이에요.

다음은 배포 관리에서 배포 상태 · 로그 · 되돌리기를 다뤄요.