> For the complete documentation index, see [llms.txt](https://docs.hackle.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hackle.io/user-view/csv-import.md).

# 사용자 업로드 (CSV Import)

## 소개

CSV 파일을 업로드하여 여러 사용자와 사용자의 `커스텀 속성`, `CRM 속성` 을 한 번에 생성하거나 업데이트할 수 있습니다.

`$userId` 를 기준으로 기존 사용자는 갱신되고, 존재하지 않는 사용자는 새로 생성됩니다. (upsert)

대량의 사용자를 개별 입력 없이 일괄로 반영할 때 유용합니다. (이벤트 데이터는 대상이 아니며, 사용자 속성만 지원합니다.)

## **단계**

CSV Import는 다음과 같은 단계로 이루어집니다.

### 1. 파일 업로드 단계

CSV 파일을 업로드하는 단계입니다.

**CSV의 첫 행은 헤더입니다.**

* 헤더의 각 값은 컬럼 key입니다.
* 아래 CSV 예시에서 컬럼 key는 `$userId`, `$phoneNumber`, `$kakaoMarketingSubscribe`, `username` 입니다.

<figure><img src="/files/TDwJVaJZVVyqqHhqAdU0" alt=""><figcaption></figcaption></figure>

컬럼 key가 어떤 필드에 매핑 될지는 2단계(컬럼 매핑 단계)에서 커스텀할 수 있기 때문에 헤더는 사용자가 알아보기 쉽게 작성하셔도 좋습니다.

또는 예약어를 사용하여 예약어에 맞는 필드에 저절로 매핑되게 할 수 있습니다. ([예약된 필드 규칙](#undefined-4))

#### 주의 사항

* 파일 업로드는 최대 **100만 행**까지 지원합니다. 100만행이 넘는 경우 업로드하실 수 없습니다.
* 파일 크기는 최대 **100MB**까지 지원합니다.
* **모든 값은 문자열(String)로 저장됩니다.**
  * 날짜를 다루려면 `20260708`처럼 문자열/숫자 비교가 가능한 형태로 입력하는 것을 권장합니다.
  * CRM속성을 업데이트 하려면 적절한 값을 입력해주셔야 합니다. ([예약된 필드 규칙](#undefined-4))
* **배열·객체 형식은 지원하지 않습니다.**
  * 값은 항상 단일 문자열이어야 합니다.
* **모든 속성은 덮어쓰기($set)로 반영됩니다.**
  * 빈 값은 무시되어 기존 값을 덮어쓰지 않습니다.
* **인코딩은 UTF-8**을 사용하며, **RFC 4180 규칙**(쉼표·따옴표·줄바꿈 처리)을 따릅니다.

{% hint style="info" %}
대시보드 내 샘플 템플릿(`$userId, <key1>, <key2> ...`)을 다운로드하여 형식에 맞게 작성할 수 있습니다.
{% endhint %}

### 2. 컬럼 매핑 단계

업로드한 CSV의 컬럼들을 실제 어떤 사용자의 필드에 매핑시킬지 정하는 단계입니다.

매핑시킬 수 있는 필드는 `IDENTIFIER`, `CRM`, `CUSTOM` 이 있습니다.

만약 CSV 컬럼에 예약어가 입력되어 있다면 기본적으로 예약된 필드에 매핑되며, 예약어가 아닌 경우 `CUSTOM` 필드에 매핑됩니다. ([예약된 필드 규칙](#undefined-4))

#### 주의 사항

* `IDENTIFIER` **필드는 필수로 매핑시켜주어야 합니다.**
* `CRM` **속성은 각 속성에 맞는 value 값이 정해져 있으니 (예약된 속성 규칙)을 확인하여 CSV파일을 작성해주셔야 합니다.**

### 3-1. 사전 검증 단계

업로드한 CSV와 컬럼 매핑정보를 통해 유효하지 않은 row들을 확인할 수 있는 단계입니다.

유효하지 않은 row는 다음과 같습니다.

* CRM 속성인 경우 속성에 맞지 않은 value가 들어가 있는 경우
* IDENTIFIER 속성 중 $userId 속성인 경우 값이 공백으로만 이루어진 경우

### 3-2. 임포트 시작 단계

모든 준비가 끝나면 임포트를 시작할 수 있습니다.

임포트 시작 시점에는 "대기중"으로만 기록되고, 실제 반영은 10분 주기로 도는 배치가 처리합니다.

따라서 업로드 직후 바로 반영되지 않으며, 대기 시간(최대 10분) + 처리 시간이 걸립니다.

## 예약된 필드 규칙

예약어는 `$` 로 시작하는 컬럼명입니다. CSV 헤더에 예약어를 쓰면 **컬럼 매핑 단계에서 해당 필드에 자동으로 매핑**됩니다.

예약어가 아닌 컬럼명은 모두 `CUSTOM` 필드로 매핑되며, 컬럼명이 그대로 커스텀 속성의 key가 됩니다.

#### 예약어 목록

<table><thead><tr><th>컬럼명(예약어)</th><th width="214.4296875">매핑되는 필드</th><th>허용하는 값</th></tr></thead><tbody><tr><td><code>$userId</code></td><td>IDENTIFIER</td><td>사용자를 식별할 값 (필수)</td></tr><tr><td><code>$phoneNumber</code></td><td>CRM</td><td>휴대폰 번호</td></tr><tr><td><code>$pushMarketingSubscribe</code></td><td>CRM</td><td><code>subscribe</code> / <code>unsubscribe</code></td></tr><tr><td><code>$pushInformationSubscribe</code></td><td>CRM</td><td><code>subscribe</code> / <code>unsubscribe</code></td></tr><tr><td><code>$kakaoMarketingSubscribe</code></td><td>CRM</td><td><code>subscribe</code> / <code>unsubscribe</code></td></tr><tr><td><code>$kakaoInformationSubscribe</code></td><td>CRM</td><td><code>subscribe</code> / <code>unsubscribe</code></td></tr><tr><td><code>$textMarketingSubscribe</code></td><td>CRM</td><td><code>subscribe</code> / <code>unsubscribe</code></td></tr><tr><td><code>$textInformationSubscribe</code></td><td>CRM</td><td><code>subscribe</code> / <code>unsubscribe</code></td></tr></tbody></table>

`push` 는 앱 푸시, `kakao` 는 카카오 알림톡/친구톡 등, `text` 는 문자(SMS/LMS/MMS) 수신동의입니다.\
`Marketing` 은 광고성, `Information` 은 정보성 메시지에 대한 동의입니다.

#### 값 규칙

**수신동의 (`$~~Subscribe`)**

`subscribe`(동의) 또는 `unsubscribe`(거부)만 입력할 수 있습니다.

* 대소문자는 구분하지 않습니다. `Subscribe`, `SUBSCRIBE`, `UnSubscribe` 모두 인정됩니다.
* `Y`, `N`, `동의`, `1`, `0`, `true` 등은 인정되지 않으며 해당 행 전체가 반영되지 않습니다.

**휴대폰 번호 (`$phoneNumber`)**

**휴대폰 번호만** 입력할 수 있습니다. 표기 형식은 자유롭게 쓸 수 있으며, 저장 시 국제 표준(E.164)으로 변환됩니다.

| 입력              | 결과                      |
| --------------- | ----------------------- |
| `01012345678`   | ✅                       |
| `010-1234-5678` | ✅ 하이픈·공백 등 구분자 사용 가능    |
| `+821012345678` | ✅ 국가번호를 붙여 입력 가능        |
| `+14155552671`  | ✅ 해외 번호도 국가번호를 붙이면 가능   |
| `0212345678`    | ❌ 유선번호(지역번호)는 지원하지 않습니다 |

* 국가번호가 없으면 **국내(대한민국) 번호로 판단**합니다. 해외 번호는 반드시 `+` 와 국가번호를 붙여주세요.
* 유선번호, 대표번호(15xx·16xx 등)는 지원하지 않습니다.

**식별자 (`$userId`)**

* 필수 항목이며, 값이 없거나 공백으로만 이루어진 행은 반영되지 않습니다.
* 앞뒤 공백과 줄바꿈은 자동으로 제거됩니다.

#### 예약어를 잘못 입력한 경우

예약어와 **한 글자라도 다르면 커스텀 속성으로 처리**됩니다. 값 검증도 이루어지지 않습니다.

| 컬럼명                       | 결과                                                  |
| ------------------------- | --------------------------------------------------- |
| `$textMarketingSubscribe` | CRM · 문자 광고성 수신동의                                   |
| `$txtMarketingSubscribe`  | ⚠️ CUSTOM · key 가 `$txtMarketingSubscribe` 인 커스텀 속성 |

의도한 필드에 매핑되었는지 **컬럼 매핑 단계에서 반드시 확인**해주세요. 예약어를 쓰지 않고 컬럼 매핑 단계에서 직접 지정하셔도 됩니다.

#### 길이 제한

| 항목               | 제한        |
| ---------------- | --------- |
| 커스텀 속성의 key(컬럼명) | 최대 128자   |
| 값                | 최대 1,024자 |

초과하면 해당 행 전체가 반영되지 않습니다.

#### 작성 예시

```
$userId,$phoneNumber,$textMarketingSubscribe,회원등급,가입일
user_001,010-1234-5678,subscribe,GOLD,20260708
user_002,01098765432,unsubscribe,SILVER,20260715
```

`회원등급`, `가입일` 은 예약어가 아니므로 각각 `회원등급`, `가입일` key의 커스텀 속성으로 저장됩니다.

***

## Q\&A

* Q) 동시에 여러 CSV 업로드 요청을 하면 순서가 보장되나요?
  * A) 보장되지 않습니다. 요청 간 순서가 중요하다면 하나의 요청이 처리완료되면 다음 요청을 하기를 권장드립니다.
* Q) 한 CSV 파일 안에서 같은 userId를 갖고 있는 row는 순서가 보장되나요?
  * A) 보장되지 않습니다. 순서가 중요하다면 한 파일 안에서 같은 userId를 여러개 넣지 않는 것을 권장드립니다.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.hackle.io/user-view/csv-import.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
