본문으로 건너뛰기
Didit, 신원·사기 방지 인프라 구축 위해 750만 달러 투자 유치
Didit
블로그로 돌아가기
블로그 · 2026년 3월 6일

Fastify와 PostgreSQL을 활용한 Didit 웹훅 리스너 구축 (KO)

Node.js, Fastify, PostgreSQL을 사용하여 Didit의 실시간 신원 확인 알림을 위한 강력하고 안전한 웹훅 리스너를 구축하는 방법을 알아보세요.

작성자: Didit업데이트됨
building-a-didit-webhook-listener-with-fastify-postgresql.png

안전한 웹훅 통합HMAC-SHA256 서명 검증을 구현하는 것은 Didit 웹훅 페이로드의 신뢰성과 무결성을 보장하고, 위조된 요청으로부터 애플리케이션을 보호하며, 데이터 보안을 유지하는 데 중요합니다.

실시간 데이터 처리웹훅을 활용하여 신원 확인 세션 상태 변경에 대한 즉각적인 알림을 받아 애플리케이션이 즉시 반응하고 사용자 온보딩 또는 위험 관리 워크플로우를 자동화할 수 있도록 합니다.

확장 가능한 데이터 저장PostgreSQL을 활용하여 웹훅 데이터를 효율적으로 저장 및 관리함으로써 강력한 쿼리, 감사, 기존 사용자 관리 시스템과의 통합을 가능하게 하여 데이터 지속성과 신뢰성을 보장합니다.

Didit의 모듈식 이점Didit의 모듈식 신원 플랫폼과 포괄적인 웹훅 시스템은 통합을 간소화하여 개발자에게 깔끔한 API와 실시간 데이터 흐름을 제공하여 무료 코어 KYC 및 설정 비용 없이 유연한 AI 기반 KYC 솔루션을 구축할 수 있도록 합니다.

Didit 웹훅 및 그 중요성 이해

신원 확인의 세계에서는 실시간 피드백이 무엇보다 중요합니다. 새로운 사용자를 온보딩하든, 사기를 방지하든, 규정 준수를 보장하든, 확인 세션의 상태를 실시간으로 아는 것이 중요합니다. 여기에 웹훅이 등장합니다. Didit의 웹훅은 세션 완료, 실패 또는 추가 조치 필요와 같이 신원 확인 워크플로우 내에서 발생하는 이벤트에 대한 알림을 받는 자동화된 방법을 제공합니다.

비효율적이고 지연을 초래할 수 있는 Didit API를 지속적으로 폴링하는 대신, 웹훅은 구성된 엔드포인트로 데이터를 직접 푸시합니다. 이 이벤트 기반 아키텍처는 애플리케이션이 항상 최신 정보를 가지고 있음을 보장하여 즉각적인 처리와 원활한 사용자 경험을 가능하게 합니다. 예를 들어, 사용자가 Didit의 ID 확인수동 및 능동 생체 인식 검사를 성공적으로 완료하면 웹훅은 온보딩 흐름에서 다음 단계를 즉시 트리거할 수 있습니다.

Didit은 구성 가능한 웹훅 버전을 제공하며, v3는 포괄적인 페이로드 구조로 인해 권장되는 표준입니다. Didit 비즈니스 콘솔을 통해 또는 API를 통해 웹훅 URL, 버전, 심지어 데이터 보존 정책을 직접 설정할 수 있어 데이터 흐름 및 규정 준수 의무에 대한 완전한 제어가 가능합니다.

Fastify 웹훅 리스너 설정하기

Fastify는 Node.js를 위한 빠르고 오버헤드가 적은 웹 프레임워크로, 고성능 웹훅 리스너를 구축하는 데 탁월한 선택입니다. 시작하는 방법은 다음과 같습니다.

1. 프로젝트 설정 및 종속성

먼저, Node.js 프로젝트를 초기화하고 필요한 패키지를 설치합니다.

mkdir didit-webhook-listener
cd didit-webhook-listener
npm init -y
npm install fastify dotenv pg crypto

Didit 웹훅 비밀 키와 PostgreSQL 연결 세부 정보를 저장할 .env 파일을 생성합니다.

DIDIT_WEBHOOK_SECRET=your_didit_webhook_secret_key
DATABASE_URL=postgresql://user:password@host:port/database

DIDIT_WEBHOOK_SECRET은 Didit 비즈니스 콘솔의 앱 설정에서 또는 Didit APIGET /v3/webhook/ 엔드포인트를 통해 검색할 수 있습니다.

2. Fastify 서버 구성

app.js 파일을 생성합니다. Fastify는 서명 확인을 위해 원시 본문이 필요하므로, 웹훅 경로에 대해 JSON을 자동으로 구문 분석하지 않도록 구성할 것입니다.

require('dotenv').config();
const fastify = require('fastify')({ logger: true });
const crypto = require('crypto');
const { Client } = require('pg');

const DIDIT_WEBHOOK_SECRET = process.env.DIDIT_WEBHOOK_SECRET;
const DATABASE_URL = process.env.DATABASE_URL;

const pgClient = new Client({ connectionString: DATABASE_URL });

// 특정 경로에 대해 본문을 원시 상태로 유지하기 위해 'application/json'에 대한 콘텐츠 파서 등록
fastify.addContentTypeParser('application/json', { parseAs: 'buffer' }, function (req, body, done) {
  if (req.raw.url === '/webhooks/didit') {
    done(null, body); // 웹훅 엔드포인트의 경우 원시 상태로 유지
  } else {
    try {
      const json = JSON.parse(body.toString());
      done(null, json);
    } catch (error) {
      error.statusCode = 400;
      done(error, undefined);
    }
  }
});

fastify.post('/webhooks/didit', async (request, reply) => {
  const signature = request.headers['x-signature'];
  const timestamp = request.headers['x-timestamp'];
  const rawBody = request.body;

  if (!signature || !timestamp || !rawBody) {
    reply.code(400).send({ message: 'Missing signature, timestamp, or body' });
    return;
  }

  // 1. HMAC-SHA256 서명 확인
  const expectedSignature = crypto
    .createHmac('sha256', DIDIT_WEBHOOK_SECRET)
    .update(`${timestamp}.${rawBody.toString()}`)
    .digest('hex');

  if (expectedSignature !== signature) {
    reply.code(403).send({ message: 'Invalid signature' });
    return;
  }

  // 2. 타임스탬프 유효성 검사 (예: 재전송 공격 방지를 위해 5분 이내)
  const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);
  if (parseInt(timestamp) < fiveMinutesAgo) {
    reply.code(403).send({ message: 'Timestamp too old' });
    return;
  }

  // 3. 확인 후 JSON 본문 구문 분석
  let payload;
  try {
    payload = JSON.parse(rawBody.toString());
  } catch (error) {
    reply.code(400).send({ message: 'Invalid JSON payload' });
    return;
  }

  fastify.log.info('Received Didit webhook:', payload);

  // 4. 웹훅 페이로드 처리 (예: DB에 저장, 사용자 상태 업데이트)
  try {
    await pgClient.query(
      'INSERT INTO webhooks (event_id, event_type, payload, received_at) VALUES ($1, $2, $3, NOW())',
      [payload.id, payload.event, JSON.stringify(payload)]
    );
    // 예시: payload.status를 기반으로 사용자 상태 업데이트
    // await pgClient.query(
    //   'UPDATE users SET verification_status = $1 WHERE didit_session_id = $2',
    //   [payload.status, payload.session_id]
    // );
    reply.code(200).send({ message: 'Webhook received and processed' });
  } catch (dbError) {
    fastify.log.error('Database error:', dbError);
    reply.code(500).send({ message: 'Internal server error' });
  }
});

const start = async () => {
  try {
    await pgClient.connect();
    fastify.log.info('Connected to PostgreSQL');
    await fastify.listen({ port: 3000, host: '0.0.0.0' });
  } catch (err) {
    fastify.log.error(err);
    process.exit(1);
  }
};

start();

PostgreSQL에 웹훅 데이터 저장하기

웹훅 데이터를 지속적으로 유지하는 것은 감사, 디버깅 및 데이터 무결성 보장을 위해 중요합니다. PostgreSQL은 이 작업에 이상적인 강력한 관계형 데이터베이스입니다.

1. 데이터베이스 스키마

먼저, 웹훅 이벤트를 저장할 테이블을 생성합니다. 이 스키마는 좋은 시작점을 제공합니다.

CREATE TABLE webhooks (
    id SERIAL PRIMARY KEY,
    event_id VARCHAR(255) UNIQUE NOT NULL, -- Didit의 고유 이벤트 ID
    event_type VARCHAR(255) NOT NULL,
    payload JSONB NOT NULL, -- 전체 JSON 페이로드 저장
    received_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

2. Fastify와 통합

app.js 예제에서 볼 수 있듯이, PostgreSQL 데이터베이스에 연결하고 들어오는 웹훅 페이로드를 삽입하기 위해 pg 클라이언트를 통합합니다. payload JSONB NOT NULL 컬럼은 전체 JSON 객체를 저장하기에 완벽하며, Didit이 도입할 수 있는 모든 새로운 필드에 대해 미리 정의된 스키마 변경 없이 나중에 유연한 쿼리를 허용합니다.

잠재적인 데이터베이스 오류를 적절하게 처리하는 것을 잊지 마십시오. 위 예제에는 데이터베이스 작업에 대한 기본 try-catch 블록이 포함되어 있습니다.

웹훅 엔드포인트 보안

민감한 신원 확인 데이터를 다룰 때는 보안이 가장 중요합니다. Didit은 HMAC-SHA256 서명을 사용하여 들어오는 웹훅이 합법적이고 변조되지 않았음을 보장합니다.

1. HMAC 서명 확인

모든 Didit 웹훅 요청에는 X-SignatureX-Timestamp라는 두 가지 중요한 헤더가 포함됩니다. X-Signature 헤더에는 고유한 웹훅 비밀과 타임스탬프와 연결된 원시 요청 본문을 사용하여 생성된 HMAC-SHA256 서명이 포함됩니다. 리스너는 다음을 수행해야 합니다.

  1. DIDIT_WEBHOOK_SECRET을 검색합니다.
  2. X-SignatureX-Timestamp 헤더를 추출합니다.
  3. 서명된 페이로드 재구성: `${timestamp}.${rawBody}`.
  4. 비밀과 재구성된 페이로드를 사용하여 자체 HMAC-SHA256 서명을 생성합니다.
  5. 생성된 서명을 요청의 X-Signature와 비교합니다. 일치하지 않으면 요청을 거부합니다.

제공된 Fastify 예제는 이 정확한 프로세스를 보여주며, 진정한 Didit 웹훅만 처리되도록 보장합니다.

2. 타임스탬프 유효성 검사

X-Timestamp 헤더는 재전송 공격을 방지하는 데 필수적입니다. 재전송 공격은 공격자가 합법적인 웹훅을 가로채 나중에 다시 보내는 경우 발생합니다. 타임스탬프가 최근(예: 현재 시간으로부터 5분 이내)인지 확인하여 이 위험을 완화할 수 있습니다. Fastify 코드 스니펫에는 타임스탬프가 너무 오래되지 않았는지 확인하는 검사가 포함되어 있습니다.

Didit이 도움이 되는 방법

Didit의 플랫폼은 신원 확인 통합을 원활하고 안전하게 설계되었습니다. 당사의 모듈식 아키텍처를 통해 견고한 문서 분석을 위한 ID 확인부터 고보안 전자여권/전자ID 확인을 위한 NFC 확인, 규정 준수를 위한 AML 심사 및 모니터링에 이르기까지 다양한 신원 확인 기능을 플러그 앤 플레이 방식으로 사용할 수 있습니다. 웹훅 시스템은 이러한 모듈성의 핵심 구성 요소로서, 지속적인 폴링 없이 복잡한 KYC 워크플로우를 조정할 수 있도록 실시간 업데이트를 제공합니다.

Didit의 AI 기반 접근 방식은 당사 시스템이 지속적으로 학습하고 적응하여 뛰어난 정확성과 사기 탐지를 제공함을 의미합니다. 명확한 API 문서와 개발자 중심 사고방식은 무료 코어 KYC 및 설정 비용과 같은 기능과 결합되어 쉽게 시작할 수 있도록 합니다. 당사의 웹훅은 구조화된 신원 데이터를 제공하여 애플리케이션이 확인 결과에 지능적으로 반응하고 전 세계적으로 신뢰를 대규모로 자동화할 수 있도록 합니다. Didit의 연령 추정을 사용하여 연령을 확인해야 하거나 수동 및 능동 생체 인식을 사용하여 사용자가 실제 사람인지 확인해야 하는 경우, Didit은 강력한 신원 솔루션에 필요한 도구와 실시간 피드백을 제공합니다.

시작할 준비가 되셨습니까?

Didit이 작동하는 것을 볼 준비가 되셨습니까? 오늘 무료 데모를 받으세요.

Didit의 무료 등급으로 무료로 신원 확인을 시작하세요.

신원 및 사기 방지 인프라.

KYC, KYB, 거래 모니터링, 지갑 심사를 위한 단일 API. 5분 만에 통합하세요.

AI에게 이 페이지 요약 요청
Fastify 및 PostgreSQL을 이용한 Didit 웹훅 리스너 구축.