Braze 입문 5편 — REST API 9 카테고리 · Messaging · Currents 깊이

2026-05-17Braze 입문에서 운영까지

Braze 입문 5편. REST API 의 9 카테고리 종합 — User Data · Messaging · Email · Subscription · Data Export · Catalogs · Templates · Schedule · Live Activity. 3 Messaging endpoint 의 분기 (/messages/send vs /campaigns/trigger/send vs /canvas/trigger/send), Catalogs 의 상품 데이터 패턴, Currents 의 이벤트 export (S3 · Snowflake · Kafka · Azure · GCP) 깊이, schema · 비용 · 셋업 단계까지 풀어쓴 학습 노트.

📚 Braze 입문에서 운영까지 · 5편 — REST API 9 카테고리 · Messaging · Currents 깊이

이 글은 Braze 입문에서 운영까지 시리즈 5편이에요. 1편 큰 그림 · 2편 SDK 통합 · 3편 Identity · 4편 4 기능 다음 — 백엔드 엔지니어가 가장 자주 손대는 자리REST API(원격 호출용 웹 API) + Currents(이벤트 실시간 export 채널).

이번 글의 위치

2편의 5분 통합 에서 /users/track 한 endpoint(API 호출 주소) 봤다면, 5편은 REST API 전체 카탈로그 + Currents 이벤트 export 의 깊이. 운영 자동화 · 통합 · 분석 의 자리.

REST API 9 카테고리 — 전체 지도

# 카테고리 대표 endpoint 사용
1 User Data /users/track · /users/identify · /users/merge 사용자 추적 · profile 관리
2 Messaging /messages/send · /campaigns/trigger/send · /canvas/trigger/send 메시지 발송
3 Email /email/status · /email/bounce/remove · /email/unsubscribes 이메일 운영
4 Subscription /subscription/status/set channel 동의 관리
5 Data Export /campaigns/data_series · /users/export/ids · /segments/data_series 분석 데이터 추출
6 Catalogs /catalogs/* 상품 데이터
7 Templates & Content /templates/email/* · /content_blocks/* 콘텐츠 자산
8 Schedule /messages/schedule/create 미래 발송 예약
9 Live Activity & SMS iOS Live Activity 업데이트 · SMS 검증 특수 케이스

9 카테고리 모두 알 필요 X. 우리 운영에 해당하는 것 부터.

카테고리 1: User Data API

2편의 /users/track덜 자주 쓰는 endpoint:

/users/identify

POST /users/identify
{
  "aliases_to_identify": [
    {
      "external_id": "user-123",
      "user_alias": { "alias_name": "legacy-xyz", "alias_label": "legacy_system" }
    }
  ]
}

용도 — Alias(External ID 전 임시 식별자) 만 있던 사용자에게 External ID 할당. 3편의 Identity transition 의 REST 버전.

대표 사용으로는 legacy 시스템에서 마이그레이션 하는 경우, 그리고 anonymous 사용자가 가입할 때 External ID 부여(자동 merge)되는 케이스가 있다.

/users/merge

POST /users/merge
{
  "merge_updates": [
    {
      "identifier_to_merge": { "external_id": "duplicate-456" },
      "identifier_to_keep": { "external_id": "user-123" }
    }
  ]
}

용도중복 사용자 (예: 같은 사람이 email · phone 다른 가입) 통합.

/users/export/ids

POST /users/export/ids
{
  "external_ids": ["user-123", "user-456"],
  "fields_to_export": ["email", "country", "tier", "custom_attributes"]
}

용도사용자 profile 조회 (분석 · 디버그). 한 번에 최대 100명.

/users/delete

POST /users/delete
{
  "external_ids": ["user-to-delete-123"]
}

용도GDPR(EU 개인정보 보호 규정) · KISA(한국인터넷진흥원) 의 "잊혀질 권리" 처리. 사용자가 삭제 요청 시 Braze 데이터도 함께.

/users/alias/new

Anonymous 사용자에게 추가 alias.

POST /users/alias/new
{
  "user_aliases": [
    {
      "external_id": "user-123",
      "alias_name": "salesforce-contact-456",
      "alias_label": "salesforce"
    }
  ]
}

카테고리 2: Messaging API — 3 endpoint 의 분기

여기가 시험 함정 자리 — 세 endpoint 가 비슷해 보이지만 다른 사용.

/messages/send — Ad-hoc 즉시 발송

POST /messages/send
{
  "external_user_ids": ["user-123", "user-456"],
  "messages": {
    "apple_push": {
      "alert": { "title": "긴급 안내", "body": "..." }
    },
    "email": {
      "app_id": "...",
      "subject": "긴급 메시지",
      "from": "noreply@example.com",
      "body": "..."
    }
  }
}

특징:

  • 콘텐츠 모두 API 안 정의
  • 캠페인 · Canvas(다단계 journey 도구) 없이 직접 발송
  • 작은 list (수십 ~ 수백)
  • 일회성 · trigger 즉시

대표 사용으로는 실시간 transaction notification (예: 결제 영수증), 긴급 단발 메시지 (예: 서비스 장애 안내), 그리고 외부 시스템 통합 (예: webhook → Braze 발송) 등이 있다.

/campaigns/trigger/send — Console 캠페인 + API trigger

POST /campaigns/trigger/send
{
  "campaign_id": "campaign-abc",
  "recipients": [
    {
      "external_user_id": "user-123",
      "trigger_properties": {
        "order_id": "ORDER-789",
        "amount": 50000
      }
    }
  ]
}

특징:

  • 콘텐츠는 Console 에서 미리 설계
  • API 호출 시 trigger
  • Liquid template(템플릿용 동적 치환 언어) + trigger_properties 로 개인화
  • 마케터가 콘텐츠 통제

대표 사용 사례를 꼽자면 결제 완료 후 영수증 (콘텐츠는 마케터, trigger 는 백엔드), 비밀번호 재설정 (콘텐츠 통일 + API 호출), 주문 상태 변경 (운영 자동화) 같은 자리다.

/canvas/trigger/send — Canvas 다단계 journey 시작

POST /canvas/trigger/send
{
  "canvas_id": "canvas-xyz",
  "recipients": [
    {
      "external_user_id": "user-123",
      "canvas_entry_properties": {
        "campaign_source": "google_ads",
        "signup_intent": "premium"
      }
    }
  ]
}

특징:

  • Canvas (다단계 journey) 의 entry trigger
  • journey 전체 가 시작 (여러 step 진행)
  • entry properties = 전체 journey 에 Liquid 로 활용

대표 사용 자리는 Onboarding journey 시작, Cart abandonment 시퀀스 trigger, VIP 등급 도달 시 축하 시퀀스 등이다.

3 endpoint 의 결정 가이드

콘텐츠가 API 안 + 일회성  → /messages/send
콘텐츠가 Console + 단일 메시지 → /campaigns/trigger/send
다단계 journey 시작     → /canvas/trigger/send

대부분 운영 = /campaigns/trigger/send/canvas/trigger/send 가 가장 흔함. /messages/send특수 케이스.

핵심 함정 — Re-eligibility 룰

Braze 는 re-eligible 안 된 사용자 에게 API 호출 횟수 무관하게 발송 안 함. — 공식 docs

의미 — Console 에서 "한 사용자 당 한 번" · "24시간 1번" 같은 룰 설정 시, API 가 반복 호출해도 발송 차단. 의도 = 사용자 폭격 자동 방지.

→ API 호출이 모두 발송된다고 가정 X. eligibility 룰 + actual delivery 별도 확인.

카테고리 3: Email Management

Subscription State 관리

POST /email/status
{
  "email": "user@example.com",
  "subscription_state": "subscribed"
}

State 종류 = subscribed · unsubscribed · opted_in (double opt-in 후).

Bounce 관리

POST /email/bounce/remove
{
  "email": "user@example.com"
}

잘못된 emailHard Bounce(영구 반송 처리) 표시되면 영구 발송 차단. 사용자가 email 정정 후 bounce list 에서 제거 필요.

Unsubscribe 조회

GET /email/unsubscribes

unsubscribe 한 사용자 list 추출. 외부 시스템 sync 또는 re-engagement 캠페인 제외 list.

카테고리 4: Subscription Groups

Subscription Group = 마케팅 카테고리 별 동의 그룹.

- Group: "Marketing Newsletter" (이메일)
- Group: "Order Updates" (SMS)
- Group: "Promotional Push" (Push)

사용자가 그룹 별로 선택적 동의/거부세분화된 권한.

Batch Subscription Update

POST /subscription/status/set
{
  "subscription_group_id": "group-abc",
  "subscription_state": "subscribed",
  "external_ids": ["user-123", "user-456", ...]
}

한 번에 최대 50 사용자. 대량 변경 = chunk.

대표 사용 자리는 사용자 설정 페이지channel preference 저장, GDPR 동의 갱신, 그리고 마이그레이션 (기존 시스템의 subscription 을 Braze 로) 등이다.

카테고리 5: Data Export

REST API 로 분석 데이터 추출외부 BI(비즈니스 분석 도구) · dashboard · audit 용.

Campaign 통계

GET /campaigns/data_series
  ?campaign_id=campaign-abc
  &length=7              # 최근 7일
  &ending_at=2026-05-17

Response 예 (예시 — 실제 schema 와 다를 수 있음):

{
  "data": [
    {
      "time": "2026-05-17",
      "sent": 12453,
      "delivered": 12401,
      "opens": 4326,
      "clicks": 1234,
      ...
    },
    ...
  ]
}

5편 Statsig 차트 같은 통계 추출. Braze console 외 우리 BI 에서 분석.

Segment 통계

GET /segments/data_series
  ?segment_id=segment-xyz
  &length=14

세그먼트 멤버 수 추이growth · churn 추적.

User Profile 조회

/users/export/ids — 사용자 데이터 bulk 조회.

카테고리 6: Catalogs — 상품 데이터

Catalogs(상품·콘텐츠 메타 저장소) = 상품 · 콘텐츠 메타데이터 를 Braze 에 저장. 메시지 personalization 의 핵심.

생성

POST /catalogs/{catalog_name}/items
{
  "items": [
    {
      "id": "product-123",
      "name": "여름 원피스",
      "price": 50000,
      "category": "dress",
      "image_url": "https://...",
      "in_stock": true
    },
    ...
  ]
}

사용 — Liquid

{% catalog_items products "${last_viewed_product_id}" %}

{% if items.first %}
{{ items.first.name }} 이 다시 입고됐어요!
가격: {{ items.first.price | times: 0.9 }}원 (10% 할인)
{% endif %}

효과 — 메시지마다 우리 상품 DB 의 최신 정보 자동 반영. 재고 · 가격 · 이미지 항상 최신.

Catalogs 의 운영

운영 자리는 셋이다. daily sync 로 우리 상품 DB → Braze Catalogs 를 매일 맞추고, 변경 시 즉시 sync 로 실시간 갱신을 더하고, 카테고리별 별도 catalog (products · articles · events) 로 데이터 종류를 분리한다.

카테고리 7: Templates & Content Blocks

Email Templates

POST /templates/email/info
GET  /templates/email/list
POST /templates/email/create
POST /templates/email/update

이메일 디자인 재사용 — 한 번 만든 template 을 여러 캠페인.

Content Blocks

HTML/text 조각의 재사용 단위. 예: 사이트 footer · 헤더 · 로고 영역.

[Email 1: 캠페인 A]
  {% content_blocks 'footer' %}    ← 공통 footer

[Email 2: 캠페인 B]
  {% content_blocks 'footer' %}    ← 같은 footer

Footer 한 번 변경 → 모든 이메일 자동 반영.

카테고리 8: Schedule

POST /messages/schedule/create
{
  "campaign_id": "campaign-abc",
  "send_at": "2026-07-01T09:00:00+09:00",
  "recipients": [...]
}

미래 시점 발송 예약. 다음:

  • /messages/schedule/update — 예약 수정
  • /messages/schedule/delete — 예약 취소
  • 비슷한 endpoint = /campaigns/trigger/schedule/* · /canvas/trigger/schedule/*

카테고리 9: Live Activity & SMS

iOS Live Activity

iOS 16+ 의 Dynamic Island · Lock Screen 위젯. 진행 중 작업 실시간 표시 (예: 음식 배달 ETA(도착 예정 시각)).

SMS Phone Validation

/sms/check_phone — 발송 전 phone format 검증.

REST API 운영 패턴

Pattern 1: Idempotent Webhook

@app.post("/webhooks/order-completed")
async def on_order_completed(order: Order):
    # 결제 영수증 이메일 — Console 캠페인 + API trigger
    response = await braze_client.post("/campaigns/trigger/send", json={
        "campaign_id": "receipt-email-campaign",
        "recipients": [{
            "external_user_id": order.user_id,
            "trigger_properties": {
                "order_id": order.id,
                "amount": order.total,
                "items": order.items_summary
            }
        }]
    })

2편 안전망 패턴 의 server-side 응용.

Pattern 2: 대량 사용자 sync

import asyncio

async def bulk_sync_users(users: list, chunk_size: int = 75):
    """대량 사용자 → Braze sync"""
    for i in range(0, len(users), chunk_size):
        chunk = users[i:i + chunk_size]
        payload = {
            "attributes": [
                {
                    "external_id": u.id,
                    "email": u.email,
                    "country": u.country,
                    "tier": u.tier,
                    "signup_year": u.signup_year
                }
                for u in chunk
            ]
        }

        for attempt in range(3):
            try:
                await braze_client.post("/users/track", json=payload)
                break
            except RateLimitError:
                await asyncio.sleep(2 ** attempt)

        await asyncio.sleep(0.1)

2편 패턴 5 그대로.

Pattern 3: GDPR 삭제 처리

async def on_gdpr_deletion_request(user_id: str):
    """사용자 GDPR 삭제 요청 처리"""

    # 1. 우리 DB 삭제
    await db.users.delete(user_id)

    # 2. Braze 에서도 삭제
    await braze_client.post("/users/delete", json={
        "external_ids": [user_id]
    })

    # 3. audit log 기록
    await audit_log.record({
        "type": "gdpr_deletion",
        "user_id": user_id,
        "timestamp": datetime.utcnow().isoformat()
    })

규제 환경 필수.

Pattern 4: Catalogs Daily Sync

# 매일 새벽 실행 (cron)
async def sync_catalog_daily():
    """우리 상품 DB → Braze Catalogs"""

    products = await db.products.find_all()

    # Batch 처리 (예: 50 items per request)
    for i in range(0, len(products), 50):
        chunk = products[i:i + 50]
        await braze_client.post(f"/catalogs/products/items", json={
            "items": [
                {
                    "id": p.id,
                    "name": p.name,
                    "price": p.price,
                    "category": p.category,
                    "image_url": p.image_url,
                    "in_stock": p.stock > 0
                }
                for p in chunk
            ]
        })
        await asyncio.sleep(0.1)

매일 새벽 → Braze 의 최신 상품 정보.

Currents — 이벤트 export 의 깊이

Currents = Braze 의 모든 이벤트 데이터외부 시스템 으로 실시간 stream.

왜 Currents 가 필요한가

Braze 의 closed 시스템 안에 데이터를 가둬두면 곤란한 자리가 여럿이다. 우리 BI 에서 통합 분석이 어렵고, long-term storage 도 불가능하다. machine learning · 추천 모델 학습 데이터도 부족해지고, audit · 컴플라이언스 도 힘들어진다.

→ Currents = Braze 이벤트 → 우리 데이터 인프라. 데이터 통제 회복.

Currents 의 작동

[Braze]
   각 send · open · click · purchase event 발생
   ↓ Currents (실시간 stream)
[우리 시스템]
   - S3 (AWS Data Lake)
   - Snowflake (분석 웨어하우스)
   - Google Cloud Storage
   - Azure Blob Storage
   - Apache Kafka (실시간 처리)
   - Kinesis Data Streams
   - Mixpanel · Amplitude (분석)
   - mParticle (CDP(고객 데이터 통합 플랫폼))

Currents 의 이벤트 종류

Message events (가장 많음):

Event 의미
messages.email.Send 이메일 발송
messages.email.Open 오픈
messages.email.Click 클릭
messages.email.Bounce bounce
messages.pushnotification.Send 푸시 발송
messages.pushnotification.Open 푸시 열기
messages.inappmessage.Impression in-app 표시
messages.inappmessage.Click in-app 클릭
messages.contentcard.Impression content card 노출
... ...

Behavior events:

Event 의미
users.behaviors.CustomEvent Custom Event
users.behaviors.app.FirstSession 첫 세션
users.behaviors.Subscription.GroupStateChange 구독 변경
users.behaviors.PurchaseEvent 결제
... ...

Braze 안 일어나는 모든 일우리 시스템 으로.

Currents 의 schema

각 이벤트의 JSON schema. 예시:

{
  "id": "event-uuid",
  "user_id": "external-user-123",
  "time": 1716000000,         // Unix timestamp
  "timezone": "Asia/Seoul",
  "device": { "model": "...", "os": "...", "platform": "ios" },
  "campaign_id": "campaign-abc",
  "campaign_name": "여름 세일",
  "send_id": "send-xyz",
  "canvas_id": "canvas-789",
  "canvas_name": "Onboarding",
  "canvas_step_id": "step-001",
  "..."
}

핵심 필드user_id (External ID), time, campaign_id 또는 canvas_id, event 특화 필드들.

셋업 단계

1. 우리 destination 인프라 준비
   - S3 bucket + IAM(접근 권한 관리) role
   - Snowflake table + role
   - Kafka topic + ACL(접근 제어 목록)

2. Braze console 의 Currents 설정
   - destination 선택
   - 인증 정보 등록
   - export 할 event 선택
   - schema 매핑

3. Test event 흐름 확인

4. Production 활성 → 실시간 stream 시작

Currents 의 운영 비용

Storage:
  - 일일 이벤트 수 × 평균 크기
  - 예: DAU 100K × 평균 5 event/user × 1KB = 500MB/일 = 15GB/월

Compute (Snowflake · BigQuery 등):
  - 쿼리 시 cost (5편 WHN 과 동일)

Statsig 6편 WHN cost management 와 비슷 — retention · partition · filter 가 비용 핵심.

Currents 활용 패턴

Pattern 1: BI dashboard 통합

-- Snowflake 의 Braze 이벤트로 분석
SELECT
    DATE(time) as date,
    campaign_name,
    COUNT(DISTINCT user_id) as unique_users,
    SUM(CASE WHEN event = 'email.Open' THEN 1 ELSE 0 END) as opens,
    SUM(CASE WHEN event = 'email.Click' THEN 1 ELSE 0 END) as clicks
FROM braze_currents.events
WHERE date >= CURRENT_DATE - 30
GROUP BY 1, 2
ORDER BY 1 DESC, opens DESC;

Braze dashboard 외 우리 BI 에서 커스텀 분석.

Pattern 2: ML(머신러닝) 학습 데이터

# 추천 모델의 학습 데이터
features = spark.sql("""
SELECT
    user_id,
    COUNT(DISTINCT campaign_id) as campaigns_received,
    SUM(CASE WHEN event = 'email.Open' THEN 1 END) as opens_30d,
    SUM(CASE WHEN event = 'PurchaseEvent' THEN 1 END) as purchases_30d
FROM braze_currents.events
WHERE time >= unix_timestamp(date_sub(current_date(), 30))
GROUP BY user_id
""")

Braze 의 user engagement 가 ML 모델의 feature.

Pattern 3: 실시간 처리 (Kafka)

# Kafka consumer
@kafka_consumer("braze_currents")
async def on_braze_event(event):
    if event["event"] == "messages.email.Click":
        await track_click_realtime(
            user_id=event["user_id"],
            campaign=event["campaign_name"],
            link=event["url"]
        )

        # 즉시 follow-up 액션 (다른 시스템)
        await internal_event_bus.publish("email_clicked", event)

실시간 event 흐름 → 즉시 처리. Webhook 보다 신뢰성 ↑.

자주 만나는 사고 — REST API · Currents

사고 1: Rate Limit Hit

원인 — 대량 sync 가 3000 req/3sec 초과.

해결 — exponential backoff + 75 batch + 분산 처리.

사고 2: Re-eligibility 미인지

원인/campaigns/trigger/send 반복 호출 → 발송 안 됨 (사용자 폭격 자동 방지).

해결 — Console 의 eligibility 룰 확인. API 응답에서 실제 발송 수 확인.

사고 3: /messages/send vs /campaigns/trigger/send 혼동

원인Console 캠페인 triggerdirect send endpoint 로 시도.

해결 — 3 endpoint 결정 가이드 (위 표) 참고. 대부분 = /campaigns/trigger/send.

사고 4: Catalogs 의 sync 지연

원인daily sync 만 운영 → 신규 상품이 최대 24시간 지연.

해결실시간 webhook 기반 sync 추가 (상품 추가/변경 시 즉시 catalog update).

사고 5: GDPR 삭제 부분 처리

원인우리 DB 만 삭제 + Braze 안 함 → 사용자에게 여전히 마케팅 메시지.

해결GDPR 삭제 워크플로모든 vendor 삭제 포함 (Braze · Mixpanel · Segment · ...).

사고 6: Currents 비용 폭증

원인모든 이벤트 + 모든 destination + retention 무한.

해결필요 event filter + destination 1~2 만 + retention 90일 등.

사고 7: Currents schema 변경 대응 X

원인 — Braze 가 schema 업데이트 — 새 필드 추가 또는 기존 필드 변경.

해결flexible JSON schema (Snowflake VARIANT · BigQuery JSON) + Currents release notes 모니터링.

사고 8: External ID 형식 불일치

원인 — API 요청의 external_id 가 SDK 의 external_id 와 다른 format (대소문자 · 공백).

해결모든 호출에서 같은 normalization (lowercase · trim).

시험 직전 한 번 더 — REST API · Currents 함정 압축 노트

REST API 9 카테고리

  1. User Data/users/track · /identify · /merge · /delete · /alias/new · /export/ids
  2. Messaging/messages/send · /campaigns/trigger/send · /canvas/trigger/send
  3. Email/email/status · /bounce/remove · /unsubscribes
  4. Subscription/subscription/status/set (최대 50명)
  5. Data Export/campaigns/data_series · /segments/data_series · /users/export/ids
  6. Catalogs/catalogs/{name}/items
  7. Templates & Content/templates/email/* · /content_blocks/*
  8. Schedule/messages/schedule/*
  9. Live Activity & SMS — 특수 케이스

3 Messaging endpoint 결정

  • 콘텐츠 API 안 + 일회성 → /messages/send
  • Console + API trigger → /campaigns/trigger/send
  • 다단계 journey → /canvas/trigger/send
  • 대부분 운영 = trigger send 2종

Re-eligibility 룰

  • Braze 가 re-eligible 안 된 사용자 자동 차단
  • API 호출 횟수 무관
  • 사용자 폭격 자동 방지

User Data 깊이

  • /users/identify — Alias 에 External ID 부여
  • /users/merge — 중복 사용자 통합
  • /users/delete — GDPR 삭제 (필수 워크플로)
  • /users/export/ids — bulk 사용자 조회

Email Management

  • Subscription state — subscribed · unsubscribed · opted_in
  • Hard bounce = 영구 차단 → bounce/remove 로 해제
  • Unsubscribe list 추출 가능

Subscription Groups

  • 마케팅 카테고리 별 동의 그룹
  • Newsletter · Order Updates · Promotional 등 분리
  • batch update 최대 50명

Data Export

  • Console 외 우리 BI 에서 활용
  • Campaign · Segment data_series
  • User profile bulk 조회

Catalogs

  • 상품 · 콘텐츠 메타데이터
  • Liquid 의 {% catalog_items %} 로 메시지 personalization
  • Daily sync + 실시간 webhook 권장

Currents

  • Braze 이벤트 → 외부 destination stream
  • destinations = S3 · Snowflake · GCS · Azure · Kafka · Kinesis · Mixpanel · mParticle
  • 2 event 카테고리 = Message events + Behavior events
  • schema = user_id · time · campaign_id/canvas_id + event-specific 필드
  • 활용 = BI 통합 · ML 학습 · 실시간 처리

운영 함정

  • Rate limit (3000 req/3sec) — backoff + batch
  • Re-eligibility 미인지 → 발송 안 되는 것이 정상
  • /messages/send vs trigger/send 혼동
  • Catalogs sync 지연 (실시간 webhook 보강)
  • GDPR 부분 처리 (모든 vendor 삭제)
  • Currents 비용 (filter · destination 한정 · retention)
  • Currents schema 변경 (flexible JSON · release notes 모니터링)
  • External ID normalization (lowercase · trim 통일)

운영 패턴

  • Idempotent webhook (결제 → trigger send)
  • 대량 sync (75 batch + backoff)
  • GDPR 워크플로 (DB + Braze + audit)
  • Catalogs daily sync
  • BI dashboard 통합 (Currents → Snowflake)
  • ML 학습 데이터 (Currents → Spark)
  • 실시간 처리 (Currents → Kafka)

공식 문서: Braze API Home · Messaging Endpoints 에서 원문을 확인할 수 있어요.

시리즈 다른 편 (앞뒤 글 모음)

이전 글:

다음 글:

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

답글 남기기

error: Content is protected !!