개인화 변수 가이드

알마니는 트리거 이벤트(주문완료, 배송시작 등)가 발생할 때 수신자별 데이터를 템플릿에 치환해 발송합니다. 이 가이드는 그 치환이 어떤 구조로 동작하는지(세 층위), 템플릿 신청 시 mappingData를 어떻게 작성하는지, 사용 가능한 변수를 GET /variables로 어떻게 조회하는지, 그리고 매핑 실수를 막아 주는 검증 규칙 3가지를 설명합니다.

시작 전에 Base URL은 https://docs.almani-center.com/open/v1 입니다. 모든 요청에는 인증에서 발급한 API 키(Authorization: Bearer ak_live_xxxx — 예시는 더미 키)와 대상 사이트를 지정하는 X-Site-Id 헤더가 필요합니다. 템플릿 API 전체 규격은 템플릿 API 레퍼런스를 참고하세요.

세 층위 구조

개인화 발송에는 세 층위가 관여합니다. 트리거가 발생하면 ① 트리거 데이터에서 ② 개인화 변수 값을 추출하고, 매핑을 따라 ③ 템플릿 변수를 치환한 뒤 발송합니다.

개인화 3층 구조 도해: 트리거 발생 → ① 트리거 데이터(이벤트 원본 값) → 개인화 변수 값 추출 → ② 개인화 변수(한글 표준명) → mappingData 매핑에 따라 치환 → ③ 템플릿 변수(#{변수명}) → 빈 값 보호 검사 후 발송 트리거 발생 — 주문완료(orderComplete) · 배송시작(deliveryStart) 등 ① 트리거 데이터 — 이벤트 원본 값 주문·배송·쿠폰 이벤트가 실어오는 수신자별 실제 값 (사이트 플랫폼에 따라 제공 범위가 다름) 개인화 변수 값 추출 ② 개인화 변수 — 한글 표준명 알마니가 표준화한 변수 — 고객명, 주문번호, 결제금액, 송장번호, 쿠폰명 등 트리거별 사용 가능 목록은 GET /variables로 조회 mappingData 매핑에 따라 치환 ③ 템플릿 변수 — #{변수명} 템플릿 본문·버튼 URL에 쓰는 치환 자리 #{고객명}, #{주문번호} 빈 값 보호 검사 후 발송
층위 표현 형태 설명
① 트리거 데이터 이벤트 원본 값 주문·배송·쿠폰 이벤트가 실어오는 수신자별 실제 값 (사이트 플랫폼에 따라 제공 범위가 다름)
② 개인화 변수 한글 표준명 알마니가 표준화한 변수 — 고객명, 주문번호, 결제금액, 송장번호, 쿠폰명 등. 트리거별 사용 가능 목록은 GET /variables로 조회
③ 템플릿 변수 #{변수명} 템플릿 본문·버튼 URL에 쓰는 치환 자리 — 예: #{고객명}, #{주문번호}

mappingData 작성법

Open API에서 매핑은 템플릿 신청 (POST /templates) 시 mappingData 객체로 지정합니다. 이 템플릿을 발송에 연결하는 작업(캠페인 설정)은 알마니 콘솔에서 수행하며, 그때 이 매핑이 기본값으로 상속됩니다.

  1. 에는 템플릿 본문·버튼 URL에 쓴 템플릿 변수명(#{ } 안의 이름)을 적습니다.
  2. 에는 개인화 변수명(한글 표준명)을 적습니다. 사용 가능한 이름은 GET /variables로 조회합니다.
  3. 템플릿 변수명과 개인화 변수명이 같으면 그 항목은 생략할 수 있습니다(자동 매핑). 이름이 다를 때만 명시합니다.
mappingData 형식
"mappingData": {
  "고객명":   "고객명",          // #{고객명} ← 개인화 변수 '고객명'
  "주문번호": "주문번호",
  "상품명":   "첫번째상품명"     // #{상품명} ← 개인화 변수 '첫번째상품명' (이름이 다른 케이스)
}

아래는 mappingData를 포함한 템플릿 신청 전체 예시입니다. 본문의 #{고객명}, #{주문번호}, #{결제금액}과 버튼 URL의 #{주문번호}가 모두 매핑 대상입니다.

예시 — 템플릿 신청에 매핑 지정
curl -X POST "https://docs.almani-center.com/open/v1/templates" \
  -H "Authorization: Bearer ak_live_xxxx" \
  -H "X-Site-Id: 1024" \
  -H "Content-Type: application/json" \
  -d '{
    "templateName": "주문완료 안내 v3",
    "templateType": "BA",
    "category": "004001",
    "content": "#{고객명}님, 주문이 완료되었습니다.\n\n▶ 주문번호: #{주문번호}\n▶ 결제금액: #{결제금액}원\n\n배송이 시작되면 다시 알려드릴게요.",
    "buttons": [
      {
        "name": "주문 상세 보기",
        "type": "WL",
        "urlMobile": "https://shop.example.com/orders/#{주문번호}"
      }
    ],
    "mappingData": {
      "고객명": "고객명",
      "주문번호": "주문번호",
      "결제금액": "결제금액"
    }
  }'
// Java 17 + Spring Framework 6 RestClient
RestClient restClient = RestClient.builder()
        .baseUrl("https://docs.almani-center.com/open/v1")
        .defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer ak_live_xxxx")
        .defaultHeader("X-Site-Id", "1024")
        .build();

record TemplateButton(String name, String type, String urlMobile) {}
record CreateTemplateRequest(
        String templateName, String templateType, String category,
        String content, List<TemplateButton> buttons,
        Map<String, String> mappingData) {}

var request = new CreateTemplateRequest(
        "주문완료 안내 v3", "BA", "004001",
        "#{고객명}님, 주문이 완료되었습니다.\n\n▶ 주문번호: #{주문번호}\n"
                + "▶ 결제금액: #{결제금액}원\n\n배송이 시작되면 다시 알려드릴게요.",
        List.of(new TemplateButton("주문 상세 보기", "WL",
                "https://shop.example.com/orders/#{주문번호}")),
        Map.of("고객명", "고객명", "주문번호", "주문번호", "결제금액", "결제금액"));

String response = restClient.post()
        .uri("/templates")
        .contentType(MediaType.APPLICATION_JSON)
        .body(request)
        .retrieve()
        .body(String.class);
참고 위 예시는 템플릿 변수명과 개인화 변수명이 모두 같아 자동 매핑이 적용되므로 mappingData를 통째로 생략해도 동일하게 동작합니다. 이름이 다른 변수(예: #{상품명}첫번째상품명)가 하나라도 있으면 그 항목만 명시하면 됩니다.

개인화 변수 카탈로그 조회

GET /variables

필요 스코프: template:read

템플릿 매핑에 사용할 수 있는 개인화 변수 목록을 반환합니다. 사이트 플랫폼 기준으로 필터되어 반환되며, triggerEvent를 지정하면 해당 트리거가 제공하는 변수만 반환합니다.

Query Parameters

triggerEvent 선택 string

트리거 값입니다 (예: orderComplete, deliveryStart). 미지정 시 전체 변수를 반환합니다.

Response

variables[] array of object

사용 가능한 개인화 변수 목록입니다.

variables[].name string

개인화 변수명(한글 표준명)입니다. mappingData의 값과 #{변수명}에 이 이름을 사용합니다.

variables[].group string

변수 그룹입니다 (예: 고객, 주문, 배송).

variables[].description string

변수 설명입니다.

variables[].triggers array of string

이 변수를 제공하는 트리거 목록입니다.

활용 팁 템플릿을 신청하기 전에 대상 트리거로 이 API를 먼저 호출해, 그 트리거가 제공하는 변수만으로 본문을 설계하면 신청 시점 검사(4000)를 한 번에 통과할 수 있습니다.
요청 예시
# 트리거별 필터: /variables?triggerEvent=deliveryStart
curl "https://docs.almani-center.com/open/v1/variables" \
  -H "Authorization: Bearer ak_live_xxxx" \
  -H "X-Site-Id: 1024"
// Java 17 + Spring Framework 6 RestClient
RestClient restClient = RestClient.builder()
        .baseUrl("https://docs.almani-center.com/open/v1")
        .defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer ak_live_xxxx")
        .defaultHeader("X-Site-Id", "1024")
        .build();

String response = restClient.get()
        .uri("/variables")
        // 트리거별 필터:
        // .uri(b -> b.path("/variables")
        //         .queryParam("triggerEvent", "deliveryStart").build())
        .retrieve()
        .body(String.class);
응답 예시
HTTP/1.1 200 OK

{
  "code": "0000",
  "message": "OK",
  "data": {
    "variables": [
      { "name": "고객명",   "group": "고객",
        "description": "주문자 이름",
        "triggers": ["orderComplete", "deliveryStart"] },
      { "name": "주문번호", "group": "주문",
        "description": "플랫폼 주문번호",
        "triggers": ["orderComplete", "deliveryStart"] },
      { "name": "송장번호", "group": "배송",
        "description": "택배 송장번호",
        "triggers": ["deliveryStart"] }
    ]
  },
  "meta": {
    "requestId": "req_7c20d9b4",
    "quota": {
      "rateLimit": {
        "limit": 120,
        "remaining": 119,
        "resetAt": "2026-07-25T14:31:00+09:00"
      }
    }
  }
}

검증 규칙 3가지

매핑 실수로 변수가 빈 채 발송되는 사고를 막기 위해, 알마니는 신청 시점부터 발송 시점까지 세 단계에서 매핑을 검사합니다.

1. 신청 시점 검사

템플릿 신청 (POST /templates)에서 매핑 대상 개인화 변수가 표준 카탈로그 (GET /variables)에 없으면 4000 에러와 함께 사용 가능한 변수 목록을 반환합니다. usedFor(대상 트리거)를 함께 보내면 해당 트리거가 제공하는 변수 기준으로 더 엄격히 검사합니다.

2. 매핑 미지정 변수 경고

본문의 #{변수} 중 매핑(자동 매핑 포함)이 해석되지 않는 것이 있으면 응답의 data.unmappedVariables: ["송장번호"] 형태로 알려줍니다. 발송 연결 전까지 매핑을 완성해야 합니다.

3. 발송 시점 빈 값 보호

수신자 데이터에 매핑 값이 비어 있으면 해당 수신자는 발송을 건너뜁니다. 변수가 빈 채로 발송되는 사고를 방지하기 위한 보호 장치입니다.

검사 시점 무엇을 검사하나 결과
템플릿 신청 시
(POST /templates)
매핑 대상 개인화 변수가 표준 카탈로그에 있는지 (usedFor 지정 시 해당 트리거 제공 변수 기준) 4000 에러 + 사용 가능한 변수 목록 반환
템플릿 신청 응답 본문 #{변수} 중 매핑(자동 매핑 포함)이 해석되지 않는 변수 data.unmappedVariables로 경고 — 발송 연결 전까지 매핑 완성 필요
발송 시점 수신자별 매핑 값이 비어 있는지 해당 수신자는 발송 건너뜀 (빈 변수 발송 방지)
주의 매핑 미지정 경고(unmappedVariables)를 해소하지 않은 채 발송에 연결하면, 발송 시점 빈 값 보호에 의해 해당 변수 값이 비는 수신자들이 조용히 제외될 수 있습니다. 경고 목록이 비어 있는 상태로 만든 뒤 연결하세요.

다음 단계