# v1에서 마이그레이션

import { Badge } from '@astrojs/starlight/components';

이 가이드는 모든 레거시 `/create*Message` 필드를 Messaging API v2에 해당하는 필드로 매핑합니다. 기존 통합을 포팅하는 동안 참조로 사용하세요.

<Aside type="note">
레거시 v1 메서드는 더 이상 사용되지 않지만 완전히 작동합니다. 정해진 서비스 종료일은 없으므로 자신의 속도에 맞춰 마이그레이션할 수 있습니다. 새로운 통합의 경우 Messaging API v2를 사용하세요.
</Aside>

## 상위 수준의 차이점

| 측면 | v1 | v2 |
|---|---|---|
| 채널별 엔드포인트 | 채널별 별도 메서드 (`/createMessage`, `/createEmailMessage`, `/createSMSMessage`, `/createKakaoMessage`, …) | 단일 엔드포인트 — `POST /messaging/v2/notify` |
| 인증 | 요청 본문의 `auth` 필드 | `Authorization: Token <API_TOKEN>` 헤더 |
| 타겟팅 | 혼합: `filter` + `conditions` + `devices` + `users` 동일한 요청에 | 명시적 분리: `NotifySegment` vs `NotifyTransactional` |
| 콘텐츠 | 플랫 `content` + 형제 플랫폼 블록 | 중첩 `payload.content.localized_content.{locale}.{platform}` |
| 응답 | `MessageCode[]` | `message_code` + 선택적 `unknown_identifiers` |

## /createMessage에서 마이그레이션

v1 `notifications[*]` 항목은 개별 `Notify` 요청이 됩니다(각각 메시지 하나). v1 호출에 여러 항목이 있는 경우 항목당 하나의 `Notify`를 발행합니다.

**타겟팅 결정.** v1 항목이 `devices` 또는 `users`(명시적 목록)를 사용하는 경우 `transactional`에 매핑합니다. 그렇지 않으면 `segment`에 매핑합니다.

### 요청 수준 필드

- `application` → `segment.application` 또는 `transactional.application` (동일한 앱 코드 형식).
- `applications_group`: v2에서 지원되지 않습니다. 앱별로 여러 요청을 사용하세요.
- `auth`: `Authorization` 헤더로 이동했으며 더 이상 본문에 없습니다.

### 예약

- `send_date` (`"YYYY-MM-DD HH:mm"` 또는 `"now"`) → `schedule.at` (RFC 3339 UTC 타임스탬프). v1 `"now"`를 재현하려면 `schedule.at`을 현재 시간으로 설정합니다. 과거의 모든 타임스탬프는 즉시 전송됩니다.
- `ignore_user_timezone` → `schedule.follow_user_timezone`. **반전됨:** `ignore_user_timezone: true`는 `follow_user_timezone: false`가 됩니다.
- `timezone`: 지원되지 않습니다. v2는 항상 `at`에 UTC를 사용합니다. 클라이언트 측에서 변환하세요.

### 타겟팅

- `filter` (세그먼트 이름) → `segment.code`.
- `conditions` (`[[tag, op, value], ...]`) → `segment.expression`. [seglang](/ko/developer/api-reference/segmentation-filters-api/segmentation-language/) 표현식으로 다시 작성합니다. seglang에서 `*`는 논리적 AND이며 앱별 태그는 `Tag("<application-code>", "<tag>", <op>, <value>)`로 참조됩니다. 예: `conditions_operator: AND`가 있는 `[["Country","EQ","BR"],["Language","EQ","pt"]]` → `Tag("XXXXX-XXXXX", "Country", EQ, "br") * Tag("XXXXX-XXXXX", "Language", EQ, "pt")`.
- `conditions_operator` (`AND` / `OR`): `segment.expression`에 통합됩니다.
- `devices` (hwid 또는 푸시 토큰) → `transactional.hwids.list` 또는 `transactional.push_tokens.list`. v2는 이 둘을 분리합니다: hwid는 `hwids`로, 원시 푸시 토큰은 `push_tokens`로 들어갑니다.
- `users` → `transactional.users.list`.
- `platforms` (숫자 코드 `[1, 3, …]`) → `segment.platforms` 또는 `transactional.platforms` (문자열 열거형 `["IOS", "ANDROID", …]`). [플랫폼 열거형](/ko/developer/api-reference/messaging-api-v2/notify/#platform-enum)을 참조하세요.

### 콘텐츠

- `content` (문자열) → `payload.content.localized_content.default.{platform}.body`. v2에서는 콘텐츠가 항상 로케일 및 플랫폼별로 지정됩니다. 일반 v1 문자열을 특수 `"default"` 키 아래에 넣습니다(모든 번역을 포괄, [디바이스에 대한 로케일 선택](/ko/developer/api-reference/messaging-api-v2/payload-reference/#locale-selection-for-a-device) 참조).
- `content` (`{locale: text}`) → `payload.content.localized_content.{locale}.{platform}.body`. 본문을 각 대상 플랫폼 블록에 복제합니다.
- `preset` → `payload.preset`.
- `data` → `payload.custom_data`.
- `rich_media` → `payload.open_action.rich_media.code`.
- `link` → `payload.open_action.link.url`.
- `minimize_link` (`0` 또는 `2`) → `payload.open_action.link.shortener` (`NONE` 또는 `BITLY`).
- `inbox_image` → `payload.content.localized_content.{locale}.{platform}.inbox.image_url` (각 플랫폼 블록에는 자체 `inbox`가 있습니다).
- `inbox_date` → `payload.content.localized_content.{locale}.{platform}.inbox.expiration_date`.
- `inbox_days`: 지원되지 않습니다. 클라이언트 측에서 절대적인 `expiration_date`로 변환하세요.

### 전송 제어

- `dynamic_content` / `dynamic_content_placeholders` → `segment` 또는 `transactional`의 `dynamic_content_placeholders`.
- `campaign` → `segment` 또는 `transactional`의 `campaign`.
- `capping_days` → `frequency_capping.days`.
- `capping_count` → `frequency_capping.count`.
- `send_rate` (int) → `send_rate.value` (send_rate.bucket: "1s" 포함).
- `message_type` (`"marketing"` / `"transactional"`) → `message_type` (`MESSAGE_TYPE_MARKETING` / `MESSAGE_TYPE_TRANSACTIONAL`).

### v2에서 지원되지 않음

- `transactionId`: 직접적인 등가물이 없습니다. 사용자 측에서 상관 관계를 추적하세요.
- `template_bindings`: Liquid 템플릿 바인딩은 v2에서 사용할 수 없습니다. 이에 의존하는 경우 v1을 계속 사용하세요.

### 플랫폼별 블록

v1은 각 `notifications[*]` 항목(ios, android, safari, chrome, …)의 최상위 수준에서 플랫폼별 매개변수를 허용합니다. v2에서는 로케일 내부로 이동합니다:

```
// v1
"notifications": [{
  "content": "Hello",
  "ios":     { "title": "Hi",    "sound": "default.caf" },
  "android": { "header": "Hi",   "led": "#ff0000" }
}]

// v2
"payload": {
  "content": {
    "localized_content": {
      "en": {
        "ios":     { "title": "Hi", "body": "Hello", "sound": "default.caf" },
        "android": { "title": "Hi", "body": "Hello", "led_color": "#ff0000" }
      }
    }
  }
}
```

플랫폼 블록 내의 필드 이름은 일부 다릅니다. 정확한 v2 이름은 [페이로드 참조](/ko/developer/api-reference/messaging-api-v2/payload-reference/)를 참조하세요.

### 예시: 이전과 이후

**v1 `/createMessage`** (세그먼트로 푸시):

```json
{
  "request": {
    "application": "XXXXX-XXXXX",
    "auth":        "YOUR_API_TOKEN",
    "notifications": [{
      "send_date":  "2026-05-01 12:00",
      "content":    "Hello!",
      "platforms":  [1, 3],
      "filter":     "active_users",
      "campaign":   "YYYYY-YYYYY",
      "capping_days":  7,
      "capping_count": 3,
      "message_type":  "marketing"
    }]
  }
}
```

**v2 `/messaging/v2/notify`**:

```json
{
  "segment": {
    "application": "XXXXX-XXXXX",
    "platforms":   ["IOS", "ANDROID"],
    "code":        "active_users",
    "payload": {
      "content": {
        "localized_content": {
          "en": {
            "ios":     { "body": "Hello!" },
            "android": { "body": "Hello!" }
          }
        }
      }
    },
    "schedule":          { "at": "2026-05-01T12:00:00Z" },
    "frequency_capping": { "days": 7, "count": 3 },
    "campaign":          "YYYYY-YYYYY",
    "message_type":      "MESSAGE_TYPE_MARKETING"
  }
}
```

## /createTargetedMessage에서 마이그레이션

`/createTargetedMessage`는 대부분의 경우 `transactional`에 매핑되거나, 명시적 식별자 없이 교차 앱 `devices_filter`로만 사용하던 경우에는 `segment`에 매핑됩니다.

- `devices_filter` → `segment.expression` (seglang) 또는 `segment.filter_expression` (구조화됨).
- `content` → `payload.content.localized_content.{locale}.{platform}.body`.
- 다른 모든 필드는 위의 `/createMessage`와 동일합니다.

## /createEmailMessage에서 마이그레이션

`platforms: ["EMAIL"]` 및 `email_payload` 블록과 함께 `Notify`로 이동합니다. 전체 참조: [이메일 페이로드 참조](/ko/developer/api-reference/messaging-api-v2/email-payload-reference/).

- `subject` → `email_payload.subject` (로케일별로 키가 지정된 맵. 단일 로케일 값은 `{"en": "..."}`으로 래핑).
- `content` (HTML) → `email_payload.body`.
- `email_template` → `email_payload.email_template`.
- `from` / `from_name` → `email_payload.from` (`{ "name": "...", "email": "..." }`).
- `reply_to` / `reply_to_name` → `email_payload.reply_to`.
- `list_unsubscribe` → `email_payload.list_unsubscribe`.
- `attachments` → `email_payload.attachments` (`[{ "name": "...", "content": "<base64>" }]`).
- 타겟팅, 예약, 캠페인 등은 `/createMessage`와 동일합니다.

## /createSMSMessage에서 마이그레이션

`platforms: ["SMS"]`와 함께 `Notify`로 이동합니다. SMS 본문은 앱에 구성된 SMS 제공업체를 통해 전송됩니다. 채워진 플랫폼 블록의 `payload.content.localized_content.{locale}.{platform}.body`에 콘텐츠를 넣습니다.

SMS 관련 제공업체 옵션(발신자 ID 등)은 요청 본문이 아닌 앱의 SMS 구성에서 계속 가져옵니다.

## /createKakaoMessage에서 마이그레이션

`platforms: ["KAKAO"]`와 함께 `Notify`로 이동하고 `payload.content.localized_content.{locale}.kakao`를 사용합니다:

- `template_id` → `kakao.template`.
- `content` → `kakao.content`.
- `variables` → `kakao.content_variables` (JSON 문자열화).

## /createWhatsAppMessage에서 마이그레이션

`platforms: ["WHATS_APP"]`와 함께 `Notify`로 이동하고 `payload.content.localized_content.{locale}.whatsapp`을 사용합니다:

- `content` (자유 형식 텍스트) → `whatsapp.content`. 24시간 고객 서비스 창 내에서만 Meta에서 전송됩니다.
- `content_id` → `whatsapp.content_id`. 사전 승인된 Meta 템플릿의 이름입니다.
- `language` → `whatsapp.language`. Meta 템플릿 로케일(예: `"en_US"`). 외부 `LocalizedContent` 로케일 키와는 독립적입니다.
- `content_variables` (v1의 객체) → `whatsapp.content_variables` (JSON 문자열화된 객체). 예시 v1 `{"1": "John"}`은 v2 `"{\"1\":\"John\"}"`이 됩니다.
- `button_url_variables` (객체) → `whatsapp.button_url_variables` (JSON 문자열화).
- `header_variables` (객체) → `whatsapp.header_variables` (JSON 문자열화).
- `preset` → `payload.preset` (페이로드 수준의 일반 프리셋).
- 타겟팅: v1에서 `devices`로 들어간 WhatsApp 전화번호(예: `"whatsapp:+1234567890"`)는 사용자에 대해 [`/registerDevice`](/ko/developer/api-reference/device-api#registerdevice)를 통해 등록해야 합니다. v2에서는 결과 사용자를 `transactional.users.list` (또는 hwid를 통해 `transactional.hwids.list`)로 타겟팅합니다.
- `use_auto_registration`: 지원되지 않습니다. 전송하기 전에 WhatsApp 번호를 등록하세요.

## /createLineMessage에서 마이그레이션

`platforms: ["LINE"]`과 함께 `Notify`로 이동하고 `payload.content.localized_content.{locale}.line`을 사용합니다:

- `content` (일반 텍스트) → `line.content`.
- `preset` (LINE 프리셋 코드) → `line.template`. v2 필드는 Pushwoosh Control Panel에서 구성된 LINE 템플릿을 참조하는 코드를 저장합니다.
- 인라인 `template` (v1 이미지, 캐러셀 또는 플렉스 메시지 구조): v2에서 직접 지원되지 않습니다. 리치 메시지를 Control Panel에서 LINE 프리셋으로 사전 구성하고 `line.template`를 통해 참조하세요.
- 타겟팅: v1 `devices` 목록(SDK / `/registerDevice`를 통해 등록된 LINE 사용자 ID)은 v2에서 `transactional.users.list` (또는 hwid를 통해 `transactional.hwids.list`)가 됩니다.

## 응답 차이점

v1 `/createMessage`는 다음을 반환합니다:

```json
{
  "status_code": 200,
  "status_message": "OK",
  "response": { "Messages": ["XXXXX-XXXXX-AAAAA"] }
}
```

v2 `Notify`는 다음을 반환합니다:

```json
{
  "result": {
    "message_code": "XXXXX-XXXXX-AAAAA",
    "unknown_identifiers": []
  }
}
```

200이 아닌 응답은 v1 `status_code` / `status_message` 쌍 대신 표준 gRPC-Gateway 오류 봉투(`{ "code": ..., "message": ..., "details": [...] }`)를 따릅니다.