> ## 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.

# GraphQL 설정

> VPMS GraphQL API 공통 설정 및 인증

## GraphQL Endpoint

모든 VPMS 서비스는 Apollo Federation을 통해 통합된 단일 GraphQL endpoint를 제공합니다.

```
POST https://development.vpms.io/graphql
```

<Info>
  개발 환경 endpoint입니다. 프로덕션 환경에서는 다른 URL을 사용합니다.
</Info>

## 공통 Headers

모든 GraphQL 요청에는 다음 헤더가 필요합니다.

### Content-Type

```http theme={null}
Content-Type: application/json
```

GraphQL 요청은 JSON 형식으로 전송됩니다.

### Authorization (선택적)

인증이 필요한 API의 경우 JWT 토큰을 포함해야 합니다.

```http theme={null}
Authorization: Bearer YOUR_JWT_TOKEN
```

<ParamField header="Authorization" type="String">
  Bearer 방식의 JWT 토큰

  * 형식: `Bearer {token}`
  * SMS 인증을 통해 획득한 authHash 사용
  * 일부 공개 API는 토큰 없이 호출 가능
</ParamField>

### 전체 헤더 예제

```http theme={null}
POST /graphql HTTP/1.1
Host: development.vpms.io
Content-Type: application/json
Authorization: Bearer 01HQKS9V8X2N3P4Q5R6S7T8U9V
```

## 요청 형식

GraphQL 요청은 JSON 객체로 구성되며, 다음 필드를 포함합니다.

### Query/Mutation

```json theme={null}
{
  "query": "query GetReservations($id: ID!) { ... }",
  "variables": {
    "id": "01HQKS9V8X"
  },
  "operationName": "GetReservations"
}
```

<ParamField body="query" type="String" required>
  GraphQL 쿼리 또는 뮤테이션 문자열
</ParamField>

<ParamField body="variables" type="Object">
  쿼리 변수 (key-value 형식)
</ParamField>

<ParamField body="operationName" type="String">
  실행할 작업 이름 (여러 작업이 있을 때 사용)
</ParamField>

## 응답 형식

### 성공 응답

```json theme={null}
{
  "data": {
    "getReservations": [
      {
        "id": "01HQKS9V8X",
        "status": "CONFIRMED"
      }
    ]
  }
}
```

### 에러 응답

```json theme={null}
{
  "errors": [
    {
      "message": "인증 토큰이 유효하지 않습니다",
      "locations": [{"line": 2, "column": 3}],
      "path": ["getReservations"],
      "extensions": {
        "code": "UNAUTHENTICATED",
        "errorCode": "AUTH_TOKEN_INVALID"
      }
    }
  ],
  "data": null
}
```

## 클라이언트 설정 예제

### TypeScript (Apollo Client)

```typescript theme={null}
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client';
import { setContext } from '@apollo/client/link/context';

// HTTP 링크 설정
const httpLink = createHttpLink({
  uri: 'https://development.vpms.io/graphql',
});

// 인증 헤더 설정
const authLink = setContext((_, { headers }) => {
  // 로컬 스토리지에서 토큰 가져오기
  const token = localStorage.getItem('authToken');

  return {
    headers: {
      ...headers,
      'Content-Type': 'application/json',
      ...(token && { authorization: `Bearer ${token}` }),
    }
  };
});

// Apollo Client 생성
const client = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache(),
});

export default client;
```

### JavaScript (Fetch API)

```javascript theme={null}
async function graphqlRequest(query, variables = {}) {
  const token = localStorage.getItem('authToken');

  const response = await fetch('https://development.vpms.io/graphql', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      ...(token && { 'Authorization': `Bearer ${token}` }),
    },
    body: JSON.stringify({
      query,
      variables,
    }),
  });

  const { data, errors } = await response.json();

  if (errors) {
    throw new Error(errors[0].message);
  }

  return data;
}

// 사용 예제
const data = await graphqlRequest(`
  query GetReservations($accommodationId: ID!) {
    getReservations(accommodationId: $accommodationId) {
      id
      status
    }
  }
`, {
  accommodationId: '01HQKS9V8X'
});
```

### cURL

```bash theme={null}
curl -X POST https://development.vpms.io/graphql \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "query": "query GetReservations($id: ID!) { getReservations(accommodationId: $id) { id status } }",
    "variables": { "id": "01HQKS9V8X" }
  }'
```

## Rate Limiting

API 요청에는 다음과 같은 제한이 적용됩니다.

<ResponseField name="일반 API">
  * 제한: 분당 60회
  * 초과 시: 429 Too Many Requests
</ResponseField>

<ResponseField name="인증 API">
  * SMS 발송: 10분당 5회 (번호당)
  * 인증 확인: 1분당 10회 (번호당)
</ResponseField>

## GraphQL Playground

개발 환경에서는 GraphQL Playground를 통해 API를 탐색할 수 있습니다.

```
https://development.vpms.io/graphql
```

브라우저에서 접속하면 인터랙티브한 쿼리 도구를 사용할 수 있습니다.

<Tip>
  Playground에서 우측 상단의 "HTTP HEADERS" 탭에서 Authorization 헤더를 설정할 수 있습니다.
</Tip>

## 에러 코드

VPMS API에서 사용하는 공통 에러 코드입니다.

| 코드                      | 설명           | HTTP Status |
| ----------------------- | ------------ | ----------- |
| `UNAUTHENTICATED`       | 인증되지 않은 요청   | 401         |
| `FORBIDDEN`             | 권한 없음        | 403         |
| `NOT_FOUND`             | 리소스를 찾을 수 없음 | 404         |
| `BAD_REQUEST`           | 잘못된 요청       | 400         |
| `INTERNAL_SERVER_ERROR` | 서버 오류        | 500         |
| `RATE_LIMITED`          | 요청 제한 초과     | 429         |

## Federation & Subgraphs

VPMS는 Apollo Federation을 사용하여 여러 서비스를 하나의 GraphQL 스키마로 통합합니다.

### 서비스 구성

* **Core Service**: 예약, 객실, 인증, 요금 관리
* **Booking Service**: 공개 구매, 결제 처리
* **User Service**: 사용자, 인증, 검색
* **Subscription Service**: 구독, 알림

모든 서비스는 단일 endpoint를 통해 접근 가능하며, Federation이 자동으로 쿼리를 적절한 서비스로 라우팅합니다.

### 크로스 서비스 쿼리

Federation을 통해 여러 서비스의 데이터를 한 번의 쿼리로 가져올 수 있습니다.

```graphql theme={null}
query GetReservationWithUser {
  # Core Service에서 예약 조회
  getReservation(id: "01HQKS9V8X") {
    id
    status
    # User Service로 확장하여 사용자 정보 조회
    user {
      id
      name
      email
    }
  }
}
```

## 관련 문서

* [Core Service API](/api-reference/core-svc/introduction) - 예약 및 객실 관리
* [Booking Service API](/api-reference/booking-svc/introduction) - 공개 구매 및 결제
* [User Service API](/api-reference/user-svc/introduction) - 사용자 관리

## 지원

GraphQL API 관련 문의사항은 [support@vendit.io](mailto:support@vendit.io)로 연락주세요.
