> ## Documentation Index
> Fetch the complete documentation index at: https://api-docs.vpms.io/llms.txt
> Use this file to discover all available pages before exploring further.

# 검색 (Elasticsearch)

> Elasticsearch 로그 저장 API

## 개요

Search 도메인은 Elasticsearch 기반의 로그 저장 기능을 제공합니다. 시스템 로그, 사용자 활동 로그 등을 Elasticsearch에 저장하여 빠른 검색과 분석을 가능하게 합니다.

## Types

### JSON / JSONObject

JSON 데이터를 나타내는 스칼라 타입입니다.

<ResponseField name="JSON" type="Scalar">
  모든 JSON 타입 (객체, 배열, 문자열, 숫자, 불리언, null)
</ResponseField>

<ResponseField name="JSONObject" type="Scalar">
  JSON 객체 타입만 허용
</ResponseField>

***

### ElasticResult (Enum)

Elasticsearch 작업 결과를 나타냅니다.

* `created`: 새로운 문서가 생성됨
* `updated`: 기존 문서가 업데이트됨
* `deleted`: 문서가 삭제됨
* `not_found`: 문서를 찾을 수 없음
* `noop`: 변경 사항 없음

***

### ErrorCause

Elasticsearch 에러 원인 정보를 나타냅니다.

<ResponseField name="type" type="String">
  에러 타입
</ResponseField>

<ResponseField name="reason" type="String">
  에러 원인
</ResponseField>

<ResponseField name="stack_trace" type="String">
  스택 트레이스
</ResponseField>

<ResponseField name="caused_by" type="ErrorCause">
  직접적인 원인
</ResponseField>

<ResponseField name="root_cause" type="[ErrorCause]">
  근본 원인 목록
</ResponseField>

<ResponseField name="suppressed" type="[ErrorCause]">
  억제된 에러 목록
</ResponseField>

***

### ShardFailure

샤드 실패 정보를 나타냅니다.

<ResponseField name="index" type="String">
  인덱스 이름
</ResponseField>

<ResponseField name="node" type="String">
  노드 ID
</ResponseField>

<ResponseField name="reason" type="ErrorCause">
  실패 원인
</ResponseField>

<ResponseField name="shard" type="Int">
  샤드 번호
</ResponseField>

<ResponseField name="status" type="String">
  HTTP 상태 코드
</ResponseField>

***

### ShardStatistics

샤드 통계 정보를 나타냅니다.

<ResponseField name="failed" type="Int">
  실패한 샤드 수
</ResponseField>

<ResponseField name="successful" type="Int">
  성공한 샤드 수
</ResponseField>

<ResponseField name="total" type="Int">
  전체 샤드 수
</ResponseField>

<ResponseField name="failures" type="[ShardFailure]">
  실패 상세 정보
</ResponseField>

<ResponseField name="skipped" type="Int">
  건너뛴 샤드 수
</ResponseField>

***

## Mutations

### addElasticSearchLog

Elasticsearch에 로그 문서를 저장합니다.

#### GraphQL Signature

```graphql theme={null}
mutation AddElasticSearchLog($index: String!, $doc: JSON!) {
  addElasticSearchLog(index: $index, doc: $doc)
}
```

#### 파라미터

<ParamField path="index" type="String!" required>
  Elasticsearch 인덱스 이름

  인덱스 명명 규칙:

  * 소문자만 사용
  * 하이픈(-)으로 단어 구분
  * 날짜 기반 인덱스: `logs-YYYY-MM-DD`
  * 기능별 인덱스: `user-activity`, `system-events` 등
</ParamField>

<ParamField path="doc" type="JSON!" required>
  저장할 JSON 문서

  문서에는 다음 필드를 포함하는 것을 권장:

  * `timestamp`: 로그 발생 시각 (ISO 8601 형식)
  * `level`: 로그 레벨 (info, warn, error 등)
  * `message`: 로그 메시지
  * `userId`: 관련 사용자 ID (있는 경우)
  * `accommodationId`: 관련 숙박 시설 ID (있는 경우)
</ParamField>

#### 응답

<ResponseField name="result" type="Boolean">
  저장 성공 여부
</ResponseField>

#### 예제

<CodeGroup>
  ```graphql Request - 사용자 활동 로그 theme={null}
  mutation {
    addElasticSearchLog(
      index: "user-activity"
      doc: {
        timestamp: "2025-01-10T15:30:00Z"
        level: "info"
        action: "user_login"
        userId: "01HQKS9V8X2N3P4Q5R6S7T8U9V"
        ip: "192.168.1.100"
        userAgent: "Mozilla/5.0..."
        message: "User logged in successfully"
      }
    )
  }
  ```

  ```graphql Request - 예약 이벤트 로그 theme={null}
  mutation {
    addElasticSearchLog(
      index: "reservation-events"
      doc: {
        timestamp: "2025-01-10T15:35:00Z"
        level: "info"
        event: "reservation_created"
        reservationId: "01HQKS9V8X2N3P4Q5R6S7T8U9V"
        accommodationId: "01HQKS9V8X"
        userId: "01HQKS9V8X2N3P4Q5R6S7T8U9V"
        guestName: "홍길동"
        checkIn: "2025-01-20"
        checkOut: "2025-01-22"
        message: "New reservation created"
      }
    )
  }
  ```

  ```graphql Request - 에러 로그 theme={null}
  mutation {
    addElasticSearchLog(
      index: "error-logs"
      doc: {
        timestamp: "2025-01-10T15:40:00Z"
        level: "error"
        error: "DatabaseConnectionError"
        message: "Failed to connect to database"
        stack: "Error: Connection timeout\n  at Database.connect..."
        userId: "01HQKS9V8X2N3P4Q5R6S7T8U9V"
        endpoint: "/api/reservations"
        method: "POST"
      }
    )
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "addElasticSearchLog": true
    }
  }
  ```
</CodeGroup>

***

## 사용 사례

### 사용자 활동 추적

사용자의 로그인, 로그아웃, 페이지 방문 등을 기록합니다.

```graphql theme={null}
mutation {
  addElasticSearchLog(
    index: "user-activity"
    doc: {
      timestamp: "2025-01-10T15:30:00Z"
      level: "info"
      action: "page_view"
      userId: "01HQKS9V8X"
      page: "/reservations"
      referrer: "/dashboard"
      duration: 1234
    }
  )
}
```

### 시스템 이벤트 로깅

예약 생성, 수정, 취소 등의 중요 이벤트를 기록합니다.

```graphql theme={null}
mutation {
  addElasticSearchLog(
    index: "system-events"
    doc: {
      timestamp: "2025-01-10T15:35:00Z"
      level: "info"
      event: "payment_completed"
      paymentId: "01HQKS9V8X"
      amount: 150000
      currency: "KRW"
      method: "card"
      userId: "01HQKS9V8X"
    }
  )
}
```

### 에러 및 예외 추적

시스템 에러와 예외 상황을 상세히 기록합니다.

```graphql theme={null}
mutation {
  addElasticSearchLog(
    index: "error-logs"
    doc: {
      timestamp: "2025-01-10T15:40:00Z"
      level: "error"
      error: "ValidationError"
      message: "Invalid email format"
      field: "email"
      value: "invalid-email"
      userId: "01HQKS9V8X"
      endpoint: "/api/users/signup"
    }
  )
}
```

### 성능 모니터링

API 응답 시간 및 성능 지표를 기록합니다.

```graphql theme={null}
mutation {
  addElasticSearchLog(
    index: "performance-metrics"
    doc: {
      timestamp: "2025-01-10T15:45:00Z"
      level: "info"
      metric: "api_response_time"
      endpoint: "/graphql"
      operation: "getReservations"
      duration: 234
      userId: "01HQKS9V8X"
      status: 200
    }
  )
}
```

***

## 인덱스 명명 규칙

### 기능별 인덱스

* `user-activity`: 사용자 활동 로그
* `reservation-events`: 예약 관련 이벤트
* `payment-events`: 결제 관련 이벤트
* `system-events`: 시스템 이벤트
* `error-logs`: 에러 및 예외 로그
* `performance-metrics`: 성능 지표
* `audit-logs`: 감사 로그

### 날짜 기반 인덱스

대량의 로그를 관리하는 경우 날짜별로 인덱스를 분리합니다.

* `logs-2025-01-10`: 2025년 1월 10일 로그
* `user-activity-2025-01`: 2025년 1월 사용자 활동 로그

***

## 권장 필드

모든 로그 문서에 다음 필드를 포함하는 것을 권장합니다:

### 필수 필드

<ParamField path="timestamp" type="String" required>
  로그 발생 시각 (ISO 8601 형식)

  예: `"2025-01-10T15:30:00Z"`
</ParamField>

<ParamField path="level" type="String" required>
  로그 레벨

  * `debug`: 디버깅 정보
  * `info`: 일반 정보
  * `warn`: 경고
  * `error`: 에러
  * `fatal`: 치명적 에러
</ParamField>

<ParamField path="message" type="String" required>
  로그 메시지 (사람이 읽을 수 있는 형태)
</ParamField>

### 선택 필드

<ParamField path="userId" type="String">
  관련 사용자 ID
</ParamField>

<ParamField path="accommodationId" type="String">
  관련 숙박 시설 ID
</ParamField>

<ParamField path="requestId" type="String">
  요청 추적 ID (분산 추적용)
</ParamField>

<ParamField path="ip" type="String">
  클라이언트 IP 주소
</ParamField>

<ParamField path="userAgent" type="String">
  클라이언트 User-Agent
</ParamField>

***

## 에러 처리

### 인덱스 생성 실패

존재하지 않는 인덱스에 문서를 추가하면 Elasticsearch가 자동으로 인덱스를 생성합니다. 단, 인덱스 이름이 유효해야 합니다.

**유효하지 않은 인덱스 이름:**

* 대문자 포함: `UserActivity` (❌)
* 특수문자 포함: `user_activity*` (❌)
* 공백 포함: `user activity` (❌)

**유효한 인덱스 이름:**

* `user-activity` (✅)
* `logs-2025-01-10` (✅)
* `reservation.events` (✅)

### 문서 크기 제한

Elasticsearch는 기본적으로 100MB까지의 문서를 지원하지만, 대부분의 로그는 1MB 이하로 유지하는 것을 권장합니다.

### 타임아웃

대량의 데이터를 한 번에 저장하는 경우 타임아웃이 발생할 수 있습니다. 이 경우 벌크 API 사용을 고려하세요.

***

## 베스트 프랙티스

### 1. 구조화된 로그

JSON 형식으로 구조화된 로그를 사용하여 검색 및 분석을 용이하게 합니다.

```json theme={null}
{
  "timestamp": "2025-01-10T15:30:00Z",
  "level": "info",
  "service": "user-svc",
  "action": "user_login",
  "userId": "01HQKS9V8X",
  "ip": "192.168.1.100",
  "success": true
}
```

### 2. 일관된 필드명

동일한 타입의 데이터는 일관된 필드명을 사용합니다.

* `userId` (✅), `user_id` (❌), `uid` (❌)
* `timestamp` (✅), `time` (❌), `createdAt` (❌)

### 3. 적절한 로그 레벨

* `debug`: 개발 및 디버깅용
* `info`: 정상적인 동작 기록
* `warn`: 잠재적 문제
* `error`: 에러 발생 (복구 가능)
* `fatal`: 치명적 에러 (복구 불가능)

### 4. 민감 정보 제외

비밀번호, 개인정보, API 키 등 민감한 정보는 로그에 포함하지 않습니다.

```json theme={null}
// ❌ 나쁜 예
{
  "password": "mysecretpassword",
  "creditCard": "1234-5678-9012-3456"
}

// ✅ 좋은 예
{
  "passwordChanged": true,
  "paymentMethodLast4": "3456"
}
```

### 5. 인덱스 라이프사이클 관리

오래된 로그는 정기적으로 삭제하거나 아카이브하여 스토리지를 관리합니다.

***

## 관련 API

* [사용자 API](/api-reference/user-svc/user) - 사용자 활동 로그 저장
* [Core Service](/api-reference/core-svc/introduction) - 예약 이벤트 로그 저장
* [Audit Service](/api-reference/audit-svc/introduction) - 감사 로그 관리
