> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.onesignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 시간 연산자

> 시간 연산자를 사용하면 특정 시점에 상대적인 메시지를 보낼 수 있습니다—액션이 일어난 후나 다가오는 날짜 전에.

## 개요

시간 연산자를 사용하면 특정 시점에 상대적인 메시지를 보낼 수 있습니다—**액션이 일어난 후**나 **다가오는 날짜 전에**.

해당 시점을 **태그**를 사용하여 사용자에게 \*\*Unix 타임스탬프(초 단위)\*\*로 저장합니다. OneSignal은 현재 시간을 해당 타임스탬프와 비교하여 경과한 시간(또는 남은 시간)을 기준으로 사용자를 타겟팅할 수 있게 해줍니다.

이를 통해 메시지를 수동으로 스케줄링하지 않고도 알림, 후속 조치, 데드라인 메시지를 쉽게 자동화할 수 있습니다.

**일반적인 사용 사례:**

* **[장바구니 포기](./abandoned-cart)**: 특정 시간 후 체크아웃하지 않은 사용자에게 알림
* **이벤트 알림**: 예약된 약속이나 갱신 날짜 전에 사용자에게 메시지 전송
* **마일스톤**: 사용자가 데드라인까지 액션을 완료하지 않았을 때 후속 조치
* **생일**: 사용자의 생일(또는 생일 즈음)에 자동 메시지 전송

<Note>
  시간 연산자는 유료 플랜에서만 사용할 수 있습니다. 무료 플랜에서도 첫 번째 세션과 마지막 세션 같은 기본 시간 기반 세그먼트 필터를 사용할 수 있습니다.
</Note>

### 언제 사용해야 하나요?

다음과 같은 경우 시간 연산자를 사용하세요:

* 고정된 달력 시간이 아닌 **이벤트에 상대적인** 메시지 전송
* **움직이는 시간 윈도우** 생성 (예: "24-48시간 후")
* 다른 날짜를 가진 많은 사용자에 대해 동일한 로직 재사용
* 시간이 지남에 따라 자격을 지속적으로 평가

이벤트가 발생할 때 즉시 메시징을 트리거해야 하는 경우 대신 \*\*[사용자 정의 이벤트](./custom-events)\*\*를 고려하세요.

### 태그 vs 사용자 정의 이벤트

**태그** 또는 **사용자 정의 이벤트** 중 하나로 많은 "알림" 사용 사례를 해결할 수 있습니다. 최선의 선택은 저장해야 하는 것과 자동화를 트리거하는 방법에 따라 다릅니다.

* 사용자에게 **마지막으로 알려진 타임스탬프**(예: `cart_updated_at` 또는 `subscription_expires_at`)를 저장하고 시간이 지남에 따라 해당 값을 기준으로 세그먼트를 나누려는 경우 **태그**를 사용합니다.
* **각 이벤트 발생**(속성 포함)을 기록하고 실시간 행동을 기반으로 여정을 트리거하려는 경우 **사용자 정의 이벤트**를 사용합니다.

<Info>
  실제로 많은 구현에서 둘 다 사용할 수 있습니다: 실시간 추적을 위한 사용자 정의 이벤트와 나중에 세그먼트하려는 사용자 상태를 위한 태그.
</Info>

[Tags](/docs/en/add-user-data-tags) and [Custom Events](/docs/en/custom-events) are both ways to add data to your users. However, there are some key differences:

| Feature        |                      Tags                     |                                          Custom Events                                         |
| -------------- | :-------------------------------------------: | :--------------------------------------------------------------------------------------------: |
| Data usage     |        Segmentation and personalization       | Trigger Journeys without a Segment, Wait Until steps, personalization directly within Journeys |
| Data retention |                    Lifetime                   |        30+ days ([lifetime storage is available](/docs/en/billing-faq#streaming-events))       |
| Data format    |          Key-value strings or numbers         |                                              JSON                                              |
| Data source    | OneSignal SDK, API, or integrations (limited) |                               OneSignal SDK, API, or integrations                              |
| Data access    |    Segmentation and message personalization   |        Journeys and Journey-message-template personalization, Segmentation (Coming soon)       |

The key distinction between Tags and Custom Events is in their depth and use cases. Tags are properties of a user, such as Name, Account Status, or Location. Events are thing that the user has done, such as Purchasing an Item, Completing a Level, or Inviting a Friend. Both tags and events can be used for segmentation and personalization.

In practice, you will likely use both:

* Tags for user properties that are static and don't change often
* Custom Events for real-time scenarios, complex segmentation, and more sophisticated journey workflows

***

## 빠른 참조

1. 이벤트 날짜를 **초 단위** Unix 타임스탬프로 변환합니다.
2. 키가 이벤트 이름이고 값이 타임스탬프를 **문자열**로 하는 [태그](./add-user-data-tags)를 설정합니다 (예: `'event_date': '1739145600'`).
3. **Time Elapsed Greater Than** 연산자를 사용하여 세그먼트를 생성합니다:
   * 과거 날짜 이후의 경우 **Time Elapsed Greater Than** 연산자와 양수 값 사용
   * 미래 날짜 이전의 경우 **Time Elapsed Greater Than** 연산자와 음수 값 사용

<Warning>
  일반적인 실수는 타임스탬프를 **초**(10자리) 대신 **밀리초**(13자리)로 설정하는 것입니다. 시간 연산자는 **초**가 필요합니다.
</Warning>

***

## 과거 이벤트 후 메시지 전송

무언가가 일어난 후 **일정 시간이 경과한 후** 사용자에게 메시지를 보내고 싶을 때 이 패턴을 사용합니다.

**예: 사용자가 장바구니를 업데이트한 후 24시간 후 장바구니 포기 알림 전송**

<Steps>
  <Step title="이벤트 발생 시 타임스탬프 저장">
    사용자가 장바구니를 업데이트할 때 현재 시간을 Unix 타임스탬프(초 단위)로 저장합니다:

    ```javascript theme={null}
    // SDK 예제
    const timestampSeconds = String(Math.floor(Date.now() / 1000));
    OneSignal.User.addTag("cart_updated_at", timestampSeconds);
    ```

    <Warning>
      초(10자리)를 사용하고 밀리초(13자리)는 사용하지 마세요.
    </Warning>
  </Step>

  <Step title="세그먼트 생성">
    1. **Audience** > **Segments**로 이동
    2. **User Tag** 필터 추가
    3. **Key**를 `cart_updated_at`로 설정
    4. **Time Elapsed Greater Than** 선택
    5. **Value**를 `1`일 (또는 `24`시간 또는 `86400`초)로 설정

    <Frame caption="24시간 전에 장바구니를 포기한 사용자를 위한 세그먼트">
      <img src="https://mintcdn.com/onesignal/BIUS_wdfwITxcuxQ/images/segments/time-elapsed-greater-than.png?fit=max&auto=format&n=BIUS_wdfwITxcuxQ&q=85&s=fd95aaf5b4ff3d4ebf594af867a594c8" alt="Time Elapsed Greater Than을 사용하는 세그먼트" width="1311" height="617" data-path="images/segments/time-elapsed-greater-than.png" />
    </Frame>
  </Step>

  <Step title="상한선 추가 (권장)">
    상한선이 없으면 사용자는 영구적으로 세그먼트에 남아 있습니다. 윈도우를 만들기 위해 두 번째 필터를 추가합니다:

    * **Time Elapsed Greater Than** `24`시간
    * **Time Elapsed Less Than** `48`시간

    이제 사용자는 이벤트 후 24-48시간 사이에만 세그먼트에 있습니다.

    <Frame caption="24-48시간 윈도우가 있는 세그먼트">
      <img src="https://mintcdn.com/onesignal/BIUS_wdfwITxcuxQ/images/segments/time-elapsed-greater-less-than.png?fit=max&auto=format&n=BIUS_wdfwITxcuxQ&q=85&s=3cb973d5b0252683e9f804e4b04a37b4" alt="Time Elapsed Greater Than과 Less Than을 모두 사용하는 세그먼트" width="1292" height="715" data-path="images/segments/time-elapsed-greater-less-than.png" />
    </Frame>
  </Step>

  <Step title="여정에서 세그먼트 사용">
    메시징을 자동화하기 위해 세그먼트를 타겟팅하는 [여정](./journeys-overview)을 생성합니다.
  </Step>
</Steps>

***

## 미래 이벤트 전 메시지 전송

약속이나 갱신과 같은 **미래 날짜 전**에 사용자에게 메시지를 보내기 위해 이 패턴을 사용합니다.

1. 미래 날짜를 Unix 타임스탬프 태그로 저장합니다 (예: `'future_date': '1739145600'`)
2. **Time Elapsed Greater Than**과 원하는 진입 시간을 음수 값으로 하여 세그먼트를 생성합니다
   * 예: `-2`일 (또는 `-172800`초)

<Frame caption="다가오는 이벤트가 있는 사용자를 위한 세그먼트">
  <img src="https://mintcdn.com/onesignal/BIUS_wdfwITxcuxQ/images/segments/time-elapsed-greater-than-negative-value.png?fit=max&auto=format&n=BIUS_wdfwITxcuxQ&q=85&s=bea6fe1e5d4a2d3349fe05674946b910" alt="음수 값을 사용하는 Time Elapsed Greater Than 세그먼트" width="1291" height="618" data-path="images/segments/time-elapsed-greater-than-negative-value.png" />
</Frame>

3. 동일한 **Time Elapsed Greater Than** 연산자를 사용하여 더 가까운 시간의 음수 값으로 상한선을 추가합니다
   * 예: `-1`일 (또는 `-86400`초)

<Frame caption="상한선이 있는 세그먼트">
  <img src="https://mintcdn.com/onesignal/BIUS_wdfwITxcuxQ/images/segments/time-elapsed-greater-than-negative-value-upper-limit.png?fit=max&auto=format&n=BIUS_wdfwITxcuxQ&q=85&s=406246bb0136f1997ababc06a638408f" alt="음수 값과 상한선을 사용하는 Time Elapsed Greater Than 세그먼트" width="1286" height="703" data-path="images/segments/time-elapsed-greater-than-negative-value-upper-limit.png" />
</Frame>

### 예: 생일 메시지

각 사용자의 **다음 다가오는 생일**을 타임스탬프로 저장하여 생일 메시지를 전송합니다.

<Steps>
  <Step title="다음 생일 타임스탬프 저장">
    사용자의 다음 다가오는 생일을 계산하고 저장합니다:

    ```javascript theme={null}
    function getNextBirthday(month, day) {
      // month: 0-11 (Jan=0), day: 1-31
      const now = new Date();
      let birthday = new Date(now.getFullYear(), month, day);

      if (birthday <= now) {
        birthday = new Date(now.getFullYear() + 1, month, day);
      }

      return String(Math.floor(birthday.getTime() / 1000));
    }

    // 예: 1월 15일 생일
    OneSignal.User.addTag("birthday", getNextBirthday(0, 15));
    ```
  </Step>

  <Step title="생일 세그먼트 생성">
    * **User Tag**: `birthday`
    * **Time Elapsed Greater Than**: `0`초

    생일 타임스탬프가 지나면 사용자가 세그먼트에 들어갑니다.

    <Frame caption="생일 세그먼트">
      <img src="https://mintcdn.com/onesignal/BIUS_wdfwITxcuxQ/images/segments/birthday-segment.png?fit=max&auto=format&n=BIUS_wdfwITxcuxQ&q=85&s=6f431d2f592779f74a5b4e27045ad984" alt="Time Elapsed Greater Than 0을 사용하는 생일 세그먼트" width="1287" height="602" data-path="images/segments/birthday-segment.png" />
    </Frame>
  </Step>

  <Step title="반복 여정 설정">
    1. 생일 세그먼트를 타겟팅하는 [여정](./journeys-overview) 생성
    2. 사용자가 내년에 재진입할 수 있도록 재진입을 **52주**로 설정
    3. 전송 후 `birthday` 태그를 내년 날짜로 업데이트 (백엔드 또는 여정에서)
  </Step>
</Steps>

<Note>
  가능한 경우 사용자의 현지 시간대를 사용하여 생일 타임스탬프를 계산하세요. 서버 시간만 사용하면 메시지가 예상보다 일찍 또는 늦게 전송될 수 있습니다.
</Note>

<Warning>
  메시지가 해마다 정확하게 유지되기를 원한다면 메시지 전송 후 사용자의 `birthday` 태그를 다음 다가오는 생일로 업데이트하세요 (예: 백엔드 또는 여정 단계에서). 이렇게 하는 경우 대신 [사용자 정의 이벤트](./custom-events)를 사용하는 것이 더 쉬울 수 있습니다.
</Warning>

<Check>
  생일 메시지는 사용자의 `birthday` 태그 날짜 즈음에 사용자에게 전송됩니다.
</Check>

***

## FAQ

### 수학은 어떻게 작동하나요? (기술적 세부사항)

시간 연산자는 고정 날짜 대신 **상대적이고 움직이는 윈도우**를 만들 수 있도록 존재합니다.

OneSignal은 다음 공식을 사용하여 경과 시간을 계산합니다:

```
time_elapsed = current_time - tag_timestamp
```

* **과거 타임스탬프** → 양수 값
* **미래 타임스탬프** → 음수 값

**연산자:**

* `Time Elapsed Greater Than X`: `elapsed > X`일 때 매치
* `Time Elapsed Less Than X`: `elapsed < X`일 때 매치

**미래 타임스탬프가 `Less Than`으로 즉시 매치하는 이유:**

음수는 양수보다 작습니다. 따라서 `time_elapsed_lt 2 days` (172,800초)는 미래 30일의 타임스탬프와 매치합니다:

```
-2,592,000 < 172,800  →  true (매치)
```

미래 타임스탬프는 항상 음수 경과 시간을 생성하므로, 다가오는 이벤트 전에 사용자가 세그먼트에 들어가고 나가야 하는 시기를 정의하려면 **음수 값을 사용해야 합니다**. 양수 값으로는 미래 날짜 \_이전\_의 시간을 나타낼 수 없습니다.

### 어떻게 테스트할 수 있나요?

1. 외부 ID, 구독 ID, 이메일 또는 전화번호로 사용자를 찾으세요. 사용자 찾기에 대한 자세한 내용은 [테스트 구독 찾기 및 설정](./test-users)을 참조하세요.
2. 현재 날짜와 미래 날짜(지금부터 5분 후)의 초 단위 타임스탬프를 구하세요.
3. 키가 'current\_time'과 'future\_time'이고 값이 초 단위 타임스탬프인 두 개의 태그를 설정하세요.
4. 다음 필터로 `current_time` 세그먼트를 생성하세요:
   * **User Tag**: `current_time` **Time Elapsed Greater Than**: `2`분
   * 그리고 **User Tag**: `current_time` **Time Elapsed Less Than**: `5`분
5. 다음 필터로 `future_time` 세그먼트를 생성하세요:
   * **User Tag**: `future_time` **Time Elapsed Greater Than**: `-5`분
   * 그리고 **User Tag**: `future_time` **Time Elapsed Less Than**: `-2`분

사용자가 다음과 같이 보이는 것을 확인해야 합니다:

* 현재 시간 날짜 후 2분에 `current_time` 세그먼트에 들어가고 현재 시간 날짜 후 5분에 세그먼트에서 나간다.
* 미래 시간 날짜 5분 전에 `future_time` 세그먼트에 들어가고 미래 시간 날짜 2분 전에 세그먼트에서 나간다.

***
