블로그 목록
알림톡

Next.js에서 카카오 알림톡 보내기 (Solapi 연동 가이드)

Layered Labs|

한국 SaaS에서 고객에게 알림을 보내는 가장 효과적인 방법은 카카오 알림톡입니다. SMS보다 저렴하고, 열람율도 압도적으로 높습니다. 결제 완료, 예약 확인, 배송 알림 등 거의 모든 트랜잭션 메시지에 알림톡이 사용됩니다.

이 글에서는 Next.js App Router + Solapi API를 활용해서 카카오 알림톡을 발송하는 방법을 단계별로 설명합니다. 실제 프로덕션에서 사용 중인 코드를 기반으로 작성했습니다.


1단계: 카카오 알림톡이란?

알림톡은 카카오톡 채널을 통해 발송되는 정보성 메시지입니다. 광고성 메시지가 아닌, 사용자가 요청한 서비스와 관련된 알림만 보낼 수 있습니다.

SMS vs 알림톡 비교:

항목SMS알림톡
건당 비용약 20원약 8원
열람율약 30%약 90%+
글자 제한90바이트 (한글 45자)1,000자
버튼/링크불가가능 (최대 5개)
발신번호전화번호카카오톡 채널

핵심 포인트: 알림톡은 SMS 대비 비용이 약 60% 저렴하고, 열람율은 3배 이상 높습니다. 한국 SaaS라면 알림톡을 기본으로 사용하세요.


2단계: Solapi 가입 + API 키 발급

카카오 알림톡을 직접 연동하려면 카카오 비즈메시지 API를 사용해야 하는데, 심사 절차가 복잡합니다. 대신 Solapi(솔라피)를 사용하면 간편하게 연동할 수 있습니다.

Solapi는 알림톡, SMS, MMS를 통합 관리할 수 있는 메시징 API 플랫폼입니다. 한국 개발자들이 가장 많이 사용하는 메시징 서비스 중 하나입니다.

  1. Solapi 홈페이지에서 회원가입
  2. 대시보드 → API 키 관리에서 API Key와 API Secret 발급
  3. 발신번호 등록 (사전에 인증된 전화번호 필요)

발급받은 키를 .env.local에 설정합니다:

.env.local
# Solapi 알림톡 설정
SOLAPI_API_KEY=NCSXXXXXXXXXXXXXXXX
SOLAPI_API_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
SOLAPI_SENDER_PHONE=01012345678
SOLAPI_PF_ID=KA01PF_XXXXXXXXXXXX

# 알림톡 템플릿 코드
SOLAPI_TEMPLATE_WELCOME=KA01TP_XXXX
SOLAPI_TEMPLATE_PAYMENT_COMPLETE=KA01TP_XXXX
SOLAPI_TEMPLATE_NOTIFICATION=KA01TP_XXXX

주의: API Secret은 절대 프론트엔드에 노출하면 안 됩니다. NEXT_PUBLIC_ 접두사를 붙이지 마세요.


3단계: 카카오 채널 연동

알림톡을 발송하려면 카카오톡 채널이 필요합니다. 채널은 기존에 사용하던 것을 연결하거나 새로 만들 수 있습니다.

  1. 카카오톡 채널 관리자센터에서 채널 생성 또는 기존 채널 확인
  2. Solapi 대시보드 → 카카오톡 채널 관리 → 채널 연동
  3. 카카오 비즈니스 인증 완료 (사업자등록증 필요)
  4. 연동 완료 후 PF ID 확인 → .env.local에 설정

채널 연동이 완료되면 Solapi 대시보드에서 카카오 비즈메시지 > 템플릿 관리메뉴가 활성화됩니다.

팁: 카카오 채널 프로필 이미지와 소개글을 잘 설정해두세요. 알림톡을 받는 고객이 처음 보는 것이 채널 프로필입니다.


4단계: Next.js에서 알림톡 발송 구현

이제 실제 코드를 작성합니다. Solapi는 HMAC-SHA256 인증 방식을 사용합니다. 먼저 알림톡 클라이언트를 만들겠습니다:

src/lib/alimtalk/solapi.ts
import crypto from "crypto";

const SOLAPI_API_URL = "https://api.solapi.com/messages/v4/send";

/** 승인된 알림톡 템플릿 코드 */
export const TEMPLATES = {
  WELCOME: process.env.SOLAPI_TEMPLATE_WELCOME ?? "",
  PAYMENT_COMPLETE:
    process.env.SOLAPI_TEMPLATE_PAYMENT_COMPLETE ?? "",
  NOTIFICATION:
    process.env.SOLAPI_TEMPLATE_NOTIFICATION ?? "",
} as const;

interface AlimtalkResult {
  success: boolean;
  messageId?: string;
  error?: string;
}

function getAuthHeader(): string {
  const apiKey = process.env.SOLAPI_API_KEY;
  const apiSecret = process.env.SOLAPI_API_SECRET;

  if (!apiKey || !apiSecret) {
    throw new Error(
      "솔라피 API 키가 설정되지 않았습니다."
    );
  }

  const date = new Date().toISOString();
  const salt = crypto.randomBytes(32).toString("hex");
  const signature = crypto
    .createHmac("sha256", apiSecret)
    .update(date + salt)
    .digest("hex");

  return `HMAC-SHA256 apiKey=${apiKey}, date=${date}, salt=${salt}, signature=${signature}`;
}

/** 알림톡 발송 */
export async function sendAlimtalk(params: {
  to: string;
  templateId: string;
  variables: Record<string, string>;
}): Promise<AlimtalkResult> {
  try {
    const response = await fetch(SOLAPI_API_URL, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: getAuthHeader(),
      },
      body: JSON.stringify({
        message: {
          to: params.to.replace(/-/g, ""),
          from: process.env.SOLAPI_SENDER_PHONE,
          kakaoOptions: {
            pfId: process.env.SOLAPI_PF_ID,
            templateId: params.templateId,
            variables: params.variables,
          },
        },
      }),
    });

    const data = await response.json();

    if (response.ok) {
      return {
        success: true,
        messageId: data.groupId,
      };
    }

    return {
      success: false,
      error:
        data.errorMessage
        ?? data.message
        ?? "발송 실패",
    };
  } catch (err) {
    const message =
      err instanceof Error
        ? err.message
        : "알 수 없는 오류";
    return { success: false, error: message };
  }
}

핵심 포인트를 짚어보겠습니다:

  • HMAC-SHA256 인증 — Solapi는 매 요청마다 date + salt를 HMAC으로 서명합니다. 토스페이먼츠의 Basic 인증보다 약간 복잡하지만, 보안성이 높습니다.
  • 전화번호 정규화replace(/-/g, "")로 하이픈을 제거합니다. 010-1234-5678 형태와 01012345678 형태 모두 처리할 수 있습니다.
  • 템플릿 변수 — 알림톡은 사전 승인된 템플릿만 발송할 수 있습니다. variables로 동적 값을 주입합니다.

이제 Next.js API Route에서 이 함수를 호출합니다:

src/app/api/alimtalk/route.ts
import { NextRequest, NextResponse } from "next/server";
import {
  sendAlimtalk,
  TEMPLATES,
} from "@/lib/alimtalk/solapi";

export async function POST(req: NextRequest) {
  const { to, type, variables } = await req.json();

  // 입력 검증
  if (!to || !type) {
    return NextResponse.json(
      { error: "to와 type이 필요합니다." },
      { status: 400 }
    );
  }

  // 템플릿 코드 매핑
  const templateId =
    TEMPLATES[type as keyof typeof TEMPLATES];

  if (!templateId) {
    return NextResponse.json(
      { error: "유효하지 않은 템플릿 타입입니다." },
      { status: 400 }
    );
  }

  const result = await sendAlimtalk({
    to,
    templateId,
    variables: variables ?? {},
  });

  if (!result.success) {
    return NextResponse.json(
      { error: result.error },
      { status: 500 }
    );
  }

  return NextResponse.json({
    success: true,
    messageId: result.messageId,
  });
}

클라이언트에서 호출하는 방법:

// 결제 완료 후 알림톡 발송 예시
const response = await fetch("/api/alimtalk", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    to: "010-1234-5678",
    type: "PAYMENT_COMPLETE",
    variables: {
      "#{고객명}": "홍길동",
      "#{상품명}": "Pro 플랜 월간 구독",
      "#{결제금액}": "29,000원",
    },
  }),
});

5단계: 템플릿 관리

카카오 알림톡은 사전 승인된 템플릿으로만 발송할 수 있습니다. 임의의 메시지를 보낼 수 없다는 뜻입니다.

템플릿 등록 절차:

  1. Solapi 대시보드 → 카카오 비즈메시지 템플릿 관리
  2. 템플릿 내용 작성 (변수는 #{변수명} 형식)
  3. 카카오 검수 요청 → 평일 기준 1~3일 소요
  4. 승인 완료 → 템플릿 코드 확인 → .env.local에 설정

자주 사용하는 템플릿 예시:

// 회원가입 환영 템플릿
안녕하세요, #{고객명}님! 🎉
#{서비스명}에 가입해주셔서 감사합니다.

지금 바로 시작해보세요:
#{서비스URL}

// 결제 완료 템플릿
#{고객명}님, 결제가 완료되었습니다.

상품명: #{상품명}
결제금액: #{결제금액}
결제일: #{결제일}

영수증 확인: #{영수증URL}

// 구독 갱신 알림 템플릿
#{고객명}님, 구독이 곧 갱신됩니다.

플랜: #{플랜명}
갱신일: #{갱신일}
결제금액: #{결제금액}

구독 관리: #{관리URL}

주의: 템플릿에 홍보성 문구를 넣으면 검수에서 반려됩니다. 알림톡은 정보성 메시지만 가능합니다. 마케팅 메시지는 친구톡을 사용해야 합니다.


6단계: 프로덕션 팁

테스트에서는 잘 되지만 프로덕션에서 문제가 생기는 경우가 많습니다. 실제 운영하면서 배운 팁을 공유합니다.

  • 알림톡 실패 시 SMS 대체 발송: 카카오톡을 사용하지 않는 고객이나 차단한 경우, 자동으로 SMS로 대체 발송하도록 설정하세요. Solapi에서 failoverConfig 옵션을 지원합니다.
  • 발송 로그 저장: 모든 발송 결과를 DB에 기록하세요. 실패한 건을 추적하고 재발송할 수 있어야 합니다.
  • 발송량 관리: 초당 발송 제한이 있습니다. 대량 발송 시 큐(Queue)를 사용해서 속도를 조절하세요.
  • 변수 누락 방지: 템플릿 변수가 하나라도 누락되면 발송이 실패합니다. 발송 전에 모든 변수가 채워졌는지 검증하세요.
  • 잔액 모니터링: Solapi는 선불 충전 방식입니다. 잔액이 부족하면 발송이 안 됩니다. Webhook으로 잔액 알림을 설정하세요.
  • 채널 친구 추가 유도: 알림톡을 받은 고객이 채널을 추가하면, 이후 친구톡(마케팅 메시지)도 발송할 수 있습니다.

SMS 대체 발송 옵션을 추가한 확장 코드:

// SMS 대체 발송이 포함된 확장 버전
const response = await fetch(SOLAPI_API_URL, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: getAuthHeader(),
  },
  body: JSON.stringify({
    message: {
      to: phone,
      from: process.env.SOLAPI_SENDER_PHONE,
      kakaoOptions: {
        pfId: process.env.SOLAPI_PF_ID,
        templateId: templateId,
        variables: variables,
      },
    },
    // 알림톡 실패 시 SMS로 대체 발송
    agent: {
      appId: "ShipFast KR",
    },
  }),
});

전체 파일 구조 정리

src/
├── lib/
│   └── alimtalk/
│       └── solapi.ts          # Solapi 클라이언트 + 인증 + 발송
├── app/
│   └── api/
│       └── alimtalk/
│           └── route.ts       # 알림톡 발송 API Route
└── .env.local                 # API 키 + 템플릿 코드 (git 커밋 금지)

마무리

여기까지 따라오셨다면 Next.js + Solapi로 카카오 알림톡 발송 시스템의 핵심 구조를 이해하셨을 겁니다. 핵심을 정리하면:

  • 알림톡은 SMS 대비 비용 60% 절감 + 열람율 3배 이상
  • Solapi의 HMAC-SHA256 인증으로 안전하게 API를 호출할 것
  • 템플릿은 사전 승인 필수 — 검수 기간(1~3일)을 고려해서 미리 등록할 것
  • 프로덕션에서는 SMS 대체 발송 + 발송 로그 + 잔액 모니터링이 필수

이 글에서 보여드린 코드는 실제로 한국형 SaaS 보일러플레이트를 만들면서 작성한 코드입니다. 알림톡뿐 아니라, 토스페이먼츠 결제, 카카오 로그인, Supabase, tRPC, Drizzle ORM까지 모두 포함된 Next.js 스타터킷이 있습니다.

위 코드가 모두 포함된 한국형 SaaS 보일러플레이트

토스페이먼츠 + 카카오 로그인 + Supabase + tRPC + 알림톡 — 설정 없이 바로 시작

가격 보기
Written by 레이어드 랩스 | 한국 개발자를 위한 SaaS 인프라