Guide

클라이언트 메서드

createIssueStickerHeadless가 돌려주는 클라이언트가 제공하는 모든 메서드 레퍼런스입니다.

createIssueStickerHeadless(config)가 돌려주는 클라이언트가 가진 메서드 전체입니다.

생명주기와 상태 구독

initialize()

initialize(): Promise<void>

클라이언트를 준비 상태(idle)로 만듭니다. API key를 검증하고 프로젝트 정보를 불러옵니다. 다른 메서드들도 필요하면 내부에서 먼저 초기화하므로, 보통 앱을 켤 때 한 번만 명시적으로 호출하면 됩니다.

subscribe(listener)

subscribe(listener: (snapshot: HeadlessSnapshot) => void): () => void

상태가 바뀔 때마다 listener를 호출합니다. 반환된 함수를 호출하면 구독이 해제됩니다. UI는 이 콜백 안에서 다시 그리면 됩니다.

getSnapshot()

getSnapshot(): HeadlessSnapshot

현재 상태를 한 번 동기적으로 읽습니다. 구독 없이 즉시 값이 필요할 때 사용합니다.

phase

readonly phase: HeadlessPhase

현재 phase를 읽는 읽기 전용 속성입니다. getSnapshot().phase의 단축입니다.

destroy()

destroy(): void

클라이언트를 정리합니다. 구독·리스너를 해제하고 진행 중인 녹화·세션 리플레이를 중단하며 내부 상태를 초기화합니다. 컴포넌트를 언마운트하거나 위젯을 내릴 때 호출하세요.

이슈 불러오기

refreshIssues(filters?)

refreshIssues(filters?: HeadlessIssueFilters): Promise<void>

조건에 맞는 이슈 목록을 불러와 snapshot.issues에 채웁니다. idle 또는 viewingIssue에서 호출할 수 있습니다.

// 현재 페이지의 내 이슈만
await client.refreshIssues({
  url: window.location.href,
  externalUserId: currentUser.id,
});

// 전체 페이지에서 검색·필터
await client.refreshIssues({
  url: 'all',
  search: 'checkout',
  customFieldValues: { [fieldDefinitionId]: ['high'] },
});

식별된 사용자(user 또는 externalUserId)가 없으면 public 모드에서는 목록이 비어 있습니다. 멤버로 로그인하면 프로젝트 전체 이슈를 불러올 수 있습니다.

openIssue(issueId)

openIssue(issueId: string): Promise<void>

이슈 상세를 불러와 snapshot.activeIssue에 담고 phase를 viewingIssue로 바꿉니다.

closeIssue()

closeIssue(): void

상세 보기를 닫고 idle로 돌아갑니다.

refreshFilterSchema()

refreshFilterSchema(): Promise<void>

필터 UI를 그릴 정의(snapshot.filterSchema.groups)를 불러옵니다. 필터는 멤버 모드에서만 제공됩니다.

이슈 만들기

startIssueCapture(options?)

startIssueCapture(options?: HeadlessIssueCaptureOptions): Promise<void>

스크린샷 이슈 만들기를 시작합니다. phase가 selectingTarget이 되고, 사용자가 페이지 요소를 클릭하면 즉시 초안(snapshot.draft)이 만들어지고 draftingIssue로 전환됩니다. 스크린샷은 백그라운드에서 캡처되어 완료되는 대로 snapshot.draft.screenshotPreviewUrls에 채워지므로, 폼을 바로 그리되 프리뷰 영역은 빈 배열일 때 로딩으로 표시하면 됩니다.

제목·설명·동적 필드 값은 앱이 직접 상태로 관리하고, 제출할 때 submitDraft에 넘깁니다.

await client.startIssueCapture();

const form = { title: '', description: '', fields: {} as Record<string, unknown> };

client.subscribe((snapshot) => {
  if (snapshot.phase !== 'draftingIssue' || !snapshot.draft) return;

  renderIssueForm({
    screenshots: snapshot.draft.screenshotPreviewUrls, // []이면 캡처 진행 중
    fields: snapshot.formSchema?.fields ?? [], // null이면 스키마 로딩 중
    onTitleChange: (title) => (form.title = title),
    onFieldChange: (id, value) => (form.fields[id] = value),
    onSubmit: () =>
      client.submitDraft({
        title: form.title,
        description: form.description,
        dynamicFields: form.fields,
      }),
    onCancel: () => client.cancelIssueCapture(),
  });
});

startVideoCapture()

startVideoCapture(): Promise<void>

화면 녹화를 시작합니다(phase recordingVideo). 브라우저의 화면 공유 권한을 사용합니다.

stopVideoCapture()

stopVideoCapture(): Promise<void>

녹화를 끝냅니다. 녹화 파일이 있으면 요소 선택 단계(selectingTarget)로 이어지고, 사용자가 요소를 클릭하면 녹화 영상이 초안에 연결됩니다. 사용자가 브라우저 공유 UI에서 직접 녹화를 멈춰도 동일하게 처리됩니다.

setSessionReplayEnabled(enabled)

setSessionReplayEnabled(enabled: boolean): void

이슈를 제출할 때 세션 리플레이(직전 조작 다시보기)를 함께 첨부할지 토글합니다. snapshot.sessionReplayavailable·canAttach로 사용 가능 여부를 확인해 스위치를 그리세요.

client.subscribe((snapshot) => {
  renderReplayToggle({
    available: snapshot.sessionReplay.available,
    checked: snapshot.sessionReplay.enabled,
    onChange: (on) => client.setSessionReplayEnabled(on),
  });
});

cancelIssueCapture()

cancelIssueCapture(): void

진행 중인 캡처·녹화·초안 작성을 취소하고 idle로 되돌립니다.

submitDraft(input)

submitDraft(input: {
  title: string;
  description: string;
  dynamicFields?: Record<string, unknown>;
}): Promise<Issue>

앱이 관리하던 제목·설명·동적 필드 값을 받아 이슈를 생성하고, 생성된 Issue를 반환합니다. 동적 필드의 키는 snapshot.formSchema.fieldsid입니다(DynamicFieldDescriptor 참고). 스크린샷·영상·콘솔/네트워크 로그·세션 리플레이는 자동으로 함께 업로드됩니다.

  • 제목·설명이 비어 있으면 VALIDATION_ERROR로 거부됩니다.
  • 호출 시점에 스크린샷 캡처가 아직 진행 중이면 phase가 submittingIssue로 전환된 채 캡처 완료를 기다렸다가 업로드합니다. submittingIssue 동안 제출 버튼 비활성화·스피너 같은 진행 피드백을 phase 기준으로 그리세요.

멤버 로그인

loginAsMember()

loginAsMember(): Promise<void>

워크스페이스 멤버로 로그인합니다. 가능한 경우 조용히 로그인하고, 아니면 로그인 창을 띄웁니다. 멤버로 로그인하면 프로젝트 전체 이슈 조회와 동적 필드·필터를 사용할 수 있습니다. 멤버 자격 증명은 SDK 메모리에만 보관되며 앱이 직접 저장하지 않습니다.

logoutMember()

logoutMember(): Promise<void>

멤버 로그아웃하고 public 모드로 돌아갑니다.

클라이언트 메서드 — 이슈스티커 Guide