Guide

SDK Widget 시작하기

설치와 초기화, 운영에서 켜는 조건, 첫 피드백 확인까지 순서대로 진행합니다.

Reader

고객이나 베타 사용자가 제품 안에서 피드백을 남기는 팀

Outcome

SDK Widget을 앱에 초기화하고 첫 피드백을 확인합니다.

다음 단계

이 문서 다음에 이어서 볼 가이드입니다.

SDK Headless 보기

이 문서가 필요한 경우

  • 고객, 베타 테스터, 내부 사용자가 제품 안에서 직접 피드백을 남기는 경우
  • 피드백 도구를 제품 기능에 통합할 필요가 없으며, 스테이징 환경이나 선택된 일부 사용자 등 특정 조건에서만 활성화하는 것으로 충분한 경우

시작하기 전에

관리자 콘솔에서 프로젝트, 허용 도메인, SDK API key를 먼저 준비해야 합니다.

SDK는 워크스페이스에 등록된 도메인과 API key를 기준으로 초기화합니다. 둘 중 하나라도 빠지면 위젯이 나타나지 않습니다. 아직 완료하지 않은 부분이 있다면 시작 준비를 끝내고 오세요.

끝나면 확인할 것

  • 앱에 SDK를 설치하고 API key를 환경 변수로 넣었습니다.
  • 원하는 조건에서만 위젯 버튼이 보이고, 테스트 피드백이 관리자 콘솔에 저장됐습니다.

1. SDK 설치하기

앱에 issue-sticker 패키지를 설치합니다.

npm install issue-sticker

SDK Widget은 현재 React 기반 프로젝트만 지원합니다. 지원 대상 프레임워크는 주기적으로 확대할 예정입니다.

2. 앱에 초기화하기

초기화만 담당하는 컴포넌트를 하나 만들고, 설정은 그 안에서 읽습니다.

'use client';

import { useIssueSticker } from 'issue-sticker/react';

export function IssueStickerWidget() {
  const { user } = useAuth(); // 앱의 사용자 정보

  useIssueSticker({
    apiKey: process.env.NEXT_PUBLIC_ISSUE_STICKER_SDK_KEY!,
    user: user ? { id: user.id, name: user.name } : undefined, // 사용자 식별
  });

  return null;
}

user는 의도에 따라 선택하세요. 넘기면 보고자 이름이 남고 그 사용자가 본인이 만든 이슈를 조회·수정·삭제할 수 있습니다. 비우면 익명 게스트가 되어 이번 세션에서 만든 이슈만 화면에 보이고, 새로 접속하면 본인이 만든 이슈도 다시 확인할 수 없습니다.

user는 앱을 사용하는 외부 사용자를 식별하는 값으로, 위젯 FAB의 "멤버 로그인"과 다릅니다. 멤버 로그인은 이슈스티커 워크스페이스 멤버로 인증해 프로젝트의 모든 이슈를 다루는 기능이고, user는 인증 없이 이슈를 남기는 사용자를 서로 구분하는 필드입니다.

만든 컴포넌트는 앱 최상위에 형제로 한 번만 둡니다.

export function AppShell({ children }) {
  return (
    <AuthProvider>
      <IssueStickerWidget />
      {children}
    </AuthProvider>
  );
}

3. 운영에서 켜는 조건 정하기

모든 사용자에게 항상 보여줄지, 베타 사용자나 관리자에게만 보여줄지 먼저 정하세요. 조건이 필요하면 같은 컴포넌트 안에서 enabled로 분기합니다.

export function IssueStickerWidget() {
  const { user } = useAuth();

  useIssueSticker({
    apiKey: process.env.NEXT_PUBLIC_ISSUE_STICKER_SDK_KEY!,
    enabled: user?.role === 'admin' || user?.flags?.betaFeedback === true,
  });

  return null;
}

enabled가 false면 위젯이 나타나지 않고, 값이 바뀌면 그 시점에 다시 켜지거나 사라집니다.

4. 첫 피드백 확인하기

위젯 FAB를 클릭하면 이슈 생성, 표시 형식 변경, 스티커 on/off 등의 기능을 사용할 수 있습니다.

처음 연결한 뒤에는 실제 고객 화면과 가까운 페이지에서 한 번 남겨보세요. 이슈가 원하는 프로젝트에 생성되는지, 이슈 발생 URL과 콘솔/네트워크 로그 같은 환경 정보, 세션 리플레이 같은 재현 정보가 함께 담기는지 확인해보세요.

5. 민감한 화면 가리기

이슈스티커는 이슈마다 화면 스크린샷과 클릭한 요소 스크린샷을 함께 저장합니다. 카드번호, 주민등록번호, 휴대폰번호, 이메일처럼 형태가 뚜렷한 값은 저장 전에 자동으로 가려집니다.

이름이나 프로필 사진처럼 형태만으로는 판단할 수 없는 정보는 가릴 영역을 직접 지정하세요. 요소에 클래스를 붙이면 됩니다.

<div className="rr-mask">{customer.name} 고객님</div>
<img className="rr-block" src={customer.idScanUrl} alt="신분증" />
  • rr-mask는 그 안의 글자를 전부 가립니다. 글자 수나 길이도 남지 않고, 레이아웃은 원래대로 유지됩니다.
  • rr-block은 영역 전체를 회색 면으로 덮습니다. 이미지처럼 글자가 아닌 정보에 사용하세요.

넓게 걸어 두고 일부만 예외로 빼려면 rr-unmask를 사용하세요.

<section className="rr-mask">
  {customer.name} 고객님
  <span className="rr-unmask">주문번호 {order.id}</span>
</section>

rr-unmask는 rr-mask 안에서만 통합니다. rr-block 영역은 예외를 만들 수 없습니다.

입력창은 autocomplete 값도 함께 봅니다. cc-number, cc-name, street-address처럼 민감한 값이 들어오는 필드라고 표준 속성으로 적어 두었다면 클래스를 따로 붙이지 않아도 가려집니다. 비밀번호 입력창도 마찬가지입니다.

FullStory, Sentry, LogRocket, Microsoft Clarity, Hotjar, PostHog, OpenReplay, Highlight, ContentSquare, Heap, Amplitude, Matomo의 마스킹 표식도 그대로 인식합니다. 이미 붙여 둔 표식이 있다면 추가 작업 없이 함께 적용됩니다.

세 클래스는 세션 리플레이에도 같은 기준으로 적용됩니다.

이미지 안에 글자로 박힌 정보(신분증 스캔, 프로필 사진)는 자동으로 찾지 못합니다. 해당 요소에 rr-block을 붙여주세요.

가리는 방식은 두 가지이고, 무엇을 근거로 가리는지에 따라 달라집니다.

가리는 근거방식결과 이미지에 남는 것
영역 지정 (rr-mask, rr-block, 타사 표식, autocomplete)글자를 보이지 않게 덮습니다영역의 크기만 남습니다
값 형태 탐지 (카드번호, 주민등록번호, 이메일 등)[redacted]로 바꿉니다가려졌다는 표시만 남고 원래 길이는 남지 않습니다

6. 3D 화면을 쓴다면

WebGL로 그린 화면은 브라우저가 화면에 합성한 뒤 내용을 비웁니다. 그래서 별다른 처리가 없으면 스크린샷과 세션 리플레이에서 3D 화면만 빈 칸으로 남습니다.

three.js를 사용한다면 렌더러를 한 번 등록하세요. 이슈스티커가 캡처 순간에 화면을 다시 그려 스크린샷에 넣습니다.

import * as THREE from 'three';
import { IssueSticker } from 'issue-sticker/react';

const unregister = IssueSticker.registerThree({ renderer, scene, camera, three: THREE });

three를 함께 넘기면 3D 화면을 클릭했을 때 어떤 오브젝트를 눌렀는지 이름으로 세션 리플레이 로그에 남습니다. 오브젝트에 name을 붙여 두면 그 이름이 그대로 나오고, 없으면 이름이 붙은 상위 그룹까지 올라가 찾습니다.

화면을 계속 다시 그리는 앱은 등록하지 않아도 스크린샷이 정상으로 찍힙니다. 다만 편집기나 제품 컨피규레이터처럼 변경이 있을 때만 그리는 앱은 등록해야 찍힙니다.

react-three-fiber를 사용한다면 컴포넌트 하나를 <Canvas> 안에 넣으세요.

import { useEffect } from 'react';
import { useThree } from '@react-three/fiber';
import * as THREE from 'three';
import { registerThree } from 'issue-sticker/react';

function IssueStickerThree() {
  const gl = useThree((state) => state.gl);
  const scene = useThree((state) => state.scene);
  const camera = useThree((state) => state.camera);

  useEffect(
    () => registerThree({ renderer: gl, scene, camera, three: THREE }),
    [gl, scene, camera]
  );

  return null;
}

후처리 효과를 쓴다면 EffectComposer를 감싸서 넘기세요. 그러지 않으면 효과가 빠진 화면이 찍힙니다.

IssueSticker.registerThree({
  renderer: { domElement: renderer.domElement, render: () => composer.render() },
  scene,
  camera,
  three: THREE,
});

문제가 생겼을 때 먼저 확인할 것

  • 초기화가 실패하면 현재 페이지의 호스트(window.location.hostname)가 등록한 도메인이거나 그 하위 도메인인지 확인합니다.
  • React hook 오류가 나면 앱에 react와 react-dom이 중복 설치되어 있는지 확인합니다.
  • 특정 사용자에게만 보이게 했다면 enabled 조건이 실제 로그인 상태와 맞는지 확인합니다.
Ready

설정이 끝나면 실제 프로젝트에서 확인하세요

무료 플랜에서도 Extension, SDK, 외부 연동을 실제 프로젝트에 연결해 볼 수 있습니다.

SDK Widget 시작하기 — 이슈스티커 Guide