> For the complete documentation index, see [llms.txt](https://toktokhan.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://toktokhan.gitbook.io/docs/basic-guides/convention/apis/code-style.md).

# Code Style

apis 폴더 내에 각 항목별 설명입니다.

## 1. type

### 1-1. DTO (Data Transfer Object)

**data transfer object** 의 줄임말로, **데이터 교환하기 위한 객체**들을 뜻합니다.

저희 컨벤션에서는 **api `request` 시 전달하는 `parameter` 의 타입**을 정의하기 위해 사용됩니다.

**DTO**는 **객체 형태로 선언한 타입**을 사용합니다.\
이를 사용하는 **`React Query`**  에서  **`parameter` 가 1개 이하여아 올바른 타입 정의가 가능합니다.**

**각 파일 별로 하나의 타입만 정의**하며, 추가로 필요한 타입은 `import` 하여 사용합니다.

<figure><img src="https://1168173052-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9A2Jt7XcUkiyMXRHBecz%2Fuploads%2FwWTJgYDmmD5qRNEtwLFR%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202023-07-03%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2012.37.22.png?alt=media&amp;token=9dc142db-5d15-486d-b850-d9d7c033800f" alt="" width="439"><figcaption></figcaption></figure>

### 1-2. Model

**model** 은 보통 서버에서 관리하는 데이터들을 의미합니다.

&#x20;저희 컨벤션에서는 **api `response` 시 전달받는 타입**을 정의하기 위해 사용됩니다.

**model** 역시 **파일 별로 하나의 타입만 정의**해야 합니다.

<figure><img src="https://1168173052-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9A2Jt7XcUkiyMXRHBecz%2Fuploads%2F6OPDGvWSV5B4Te3A5F2U%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202023-07-03%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2012.36.47.png?alt=media&amp;token=52c437d2-9df0-49fd-a20c-d03d7d547bf2" alt="" width="517"><figcaption></figcaption></figure>

**DTO**와 **Model** 타입 모두 얼마든지 선언 해도 좋지만 **`pagination`**, **`Promise`** 같은 공통적으로 사용하는 타입은 **api 파일 안**에서 **`generic`** 과 같은 형식으로 확장해서 사용하는걸 권장합니다.

좀 더 자세한 사용법은 **아래 api** 에서 확인해주세요.

## 2. Api

api 파일은 아래와 같은 code style을 갖고 있습니다.

**`gen:api`** 로 생성된 파일 또한 같은 규칙이니 컨벤션을 안다면 코드 해석이 더 쉬워집니다.

* **api** 파일은 **하나의** **`Class`** 로 만듭니다.
* 다른 추가 설정이 없다면 **`config`에 설정된 `axios instance` 코드를 사용**하며\
  다른 설정이 필요할 경우 파일 하단의 api 인스턴스 생성시, 새로운 **`axios instance`**&#xB97C; 주입하여 사용합니다.
* **`.env`** 파일이나 배포시 **환경변수로** **base url** 을 설정하기 때문에 **url 에는 end point** 만 적어주며,\
  &#x20;**method 는 전부 대문자**로 작성합니다.
* **`parameter`** 와 **`return`** 타입은 **`dto`** / **`model`** 에서 선언한 타입들을 활용하여 **꼭 명시해주세요.**

  **호출한 데이터 사용 및 문제 파악에 용이합니다.**
* 각 **`method`**&#xC758; 명칭은 꼭 **의미를 이해하기 쉽게** 작성해주세요.\
  아래는 주로 사용하는 관행적인 규칙입니다.

> - **GET** -> `get`
> - **POST** -> `create` 등
> - **PATCH**, **PUT** -> `update`
> - **DELETE** -> `delete`

<figure><img src="https://1168173052-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9A2Jt7XcUkiyMXRHBecz%2Fuploads%2Fn3T45B6ZhYBSjgaI4Bux%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202023-06-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.37.57.png?alt=media&amp;token=8277e296-8d07-4cd0-ae66-3ce9e8dedde5" alt=""><figcaption></figcaption></figure>

## 3. React Query

현재 **`axios`**&#xC640; 더불어 편리한 데이터 관리를 위해 주로 **`React Query`**&#xB97C; 사용합니다.

각 **`~api.ts`** 에서 생성한 method를 두 파일에 미리 **custom hooks** 형태로 작성한 후 사용합니다.

### 3-1. api.query.ts

**api**의 **`GET` 메소드**는 이 파일에 작성합니다. 미리 작성한 api 파일 뒤에 **`.query.ts`** 를 붙여 파일을 생성해주세요.

{% tabs %}
{% tab title="선언하기" %}

#### Query Key 선언

<figure><img src="https://1168173052-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9A2Jt7XcUkiyMXRHBecz%2Fuploads%2F57CqgF1DK0brjKBT1vWl%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202023-06-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.11.08.png?alt=media&amp;token=6b420b8f-3eab-4abd-a58c-30055b200342" alt=""><figcaption><p>Query Key </p></figcaption></figure>

* 객체와 객체의 **`key`** 는 **상수와 동일한 스타일**로 작성해주세요.
* **`query-key`** 함수의 인자는 api method 와 동일한 인자를 작성합니다.\
  예제와 같은 방법으로 유틸리티 함수인 **`Parameter`** 를 사용하면 **api method 의 파라미터 타입을** 반환합니다.
* return 문은 **배열로 작성**하며 **첫 번째는 `query-key` 문자열,** 두번째는 인자로 넘긴 **`params`** **를 그대로 전달**합니다.\
  인자가 없을 경우에는 **`.filter(isNotNull)`** 메서드가 **`params`** 를 제거합니다.

\
**Custom Hooks 선언**\
\
이제 각 api method 별로 **`useQuery`** 를 생성합니다.

우측의 **태그별**로 하나씩 설명하겠습니다.

<figure><img src="https://1168173052-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9A2Jt7XcUkiyMXRHBecz%2Fuploads%2FHQA5UBV5C0A8m5NEbFDI%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202023-06-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2012.31.20.png?alt=media&amp;token=cb4d5a7a-95b9-4ea8-a9df-393da3f4de21" alt=""><figcaption><p>Custom Query</p></figcaption></figure>

<mark style="color:orange;">**Naming**</mark>

아래와 같은 규칙으로 네이밍을 붙여줍니다. 사용하는 api method의 의미를 표현하도록 작성합니다.

<figure><img src="https://1168173052-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9A2Jt7XcUkiyMXRHBecz%2Fuploads%2Fs6pbFgJ8HUoxPA5GxE2u%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202023-06-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2012.17.54.png?alt=media&amp;token=ae163784-ee36-4624-b097-e239083ae1b6" alt="" width="312"><figcaption></figcaption></figure>

<mark style="color:green;">**Params**</mark>

생성할 api method의 parameter 타입을 정의합니다.

미리 생성된 유틸리티 타입 **`UseQueryParams`** 을 사용하여 **generic** 형태로 **`typeof api.method`** 를 전달하면 **`variables`**&#xACFC; **`options`** 타입을 정의해줍니다.

{% hint style="info" %}
**`variables` 와** **`options`** 은 뭔가요?\
\
추후 React Query를 사용하기 위한 parameter 라고 보면 됩니다.\
**`variables`** 은 앞서 **`dto`** 에서 선언한 **request 인자들을 전달**하면 되고\
**`options`** 는 React `Query` hooks의 **이벤트나 상태를 제어**할 수 있습니다.
{% endhint %}

\ <mark style="color:blue;">**Query Key**</mark>

상단에서 선언한 **`QUERY_KEY`** 함수에 **`params?.variables`** 을 인자로 넣어 생성합니다.

\ <mark style="color:red;">**useQuery**</mark>

사용하는 api method에 맞게 <mark style="color:red;">**`useQuery`**</mark> <mark style="color:red;">**`useInfiniteQuery`**</mark> 둘 중 하나를 반환합니다.\
반환한 hooks 모두 query key를 비롯한 3개의 인자를 전달해야 합니다.

\ <mark style="color:purple;">**Query Fn**</mark>

api method를 **callback 함수 형태로 전달**합니다.

\ <mark style="color:green;">**options**</mark>

해당 hooks를 **사용하는 시점에서 options를 자유롭게 제어**하기 위해 **`params?.options`** 을 그대로 전달합니다.<br>

> &#x20;<mark style="color:red;">**`useInfiniteQuery`**</mark> 사용하기
>
> <mark style="color:red;">**`useInfiniteQuery`**</mark> 를 사용하기 위해선 <mark style="color:purple;">**Query Fn**</mark> 과 <mark style="color:green;">**options**</mark> 에서 추가적인 설정이 필요합니다.
>
> <mark style="color:purple;">**Query Fn**</mark>
>
> **`queryFn`** 에서 인자로 제공하는 **`pageParam`** 을 **다음 page를 받아오기 위한 인자로 전달**합니다. **default 값**은 **`null`** 로 설정하면 첫 API 호출이 문제없이 작동합니다.
>
> <mark style="color:green;">**options**</mark>
>
> **현재 페이지가 마지막인지 검사**하는 기능인 **`getNextPageParam`** **이벤트를 `params?.options`  와 함께 전달합니다.**<br>
> {% endtab %}

{% tab title="사용하기" %}

#### Query Key 사용

<figure><img src="https://1168173052-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9A2Jt7XcUkiyMXRHBecz%2Fuploads%2FSbcsk685tq4LGxSZ0Gsa%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202023-06-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.31.27.png?alt=media&amp;token=9e5ac67a-6bc3-436d-90d5-2872f9b4802a" alt=""><figcaption><p>Query Key </p></figcaption></figure>

* **`query-key`** 를 **함수 형태**로 작성했기 때문에 **함수를 호출하는 방식으로 사용**합니다.
* 사용한 인자를 전달하여 특정 **`query-key`**&#xB97C; 가져올 수 있습니다.
* 자세한 **`query-key`** 의 활용법은 [React Query 공식문서](https://tanstack.com/query/v4/docs/react/guides/query-keys) 를 참고해주세요.<br>

#### Custom Hooks 사용

<figure><img src="https://1168173052-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9A2Jt7XcUkiyMXRHBecz%2Fuploads%2FQEBd1JKXkEww65z6W2k1%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202023-06-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2012.42.30.png?alt=media&amp;token=f0edc70c-a66e-4acc-808e-545a37dcc8fa" alt=""><figcaption></figcaption></figure>

사용법은 어렵지 않습니다. 앞서 선언만 잘 해주었다면 **원하는 상황에 맞게 `variables` 와 `options` 를 사용**하면 됩니다.

웬만하면 React Query 에서 **반환하는 상태와 함수의 이름을 변경하여 사용**합니다. **어떤 데이터인지 명확하게 파악**하기 위함입니다.

**`InfiniteQuery`** 는 추가적인 설정이 필요합니다.

* React Query 에서 관리하는 **`InfiniteQuery`**&#xB294; **2차원 배열의 형태로 관리**됩니다. 때문에 보통 2차원 배열을 flatMap 메서드로 풀어 **1차원 배열로 가공 후 사용**합니다.
* 다음 페이지를 받아올 때는 **`InfiniteQuery`** 에서 반환하는 **`fetchNextPage`** 함수를 사용합니다.
* api 호출시 **불필요한 요청을 막기** 위해  **`hasNextPage`** **`isFetchingNextPage`** 두 상태를 활용하여 **무한스크를의 조건**을 걸어 사용합니다.
  {% endtab %}
  {% endtabs %}

### 3-2. api.mutation.ts

**api**의 **`GET` 을 제외한 메소드는** 이 파일에 작성합니다.\
미리 작성한 api 파일 뒤에 **`.mutation.ts`** 를 붙여 파일을 생성해주세요.

{% tabs %}
{% tab title="선언하기" %}

<figure><img src="https://1168173052-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9A2Jt7XcUkiyMXRHBecz%2Fuploads%2FHdkHrxF3rtOSIujYN5Bi%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202023-06-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.20.53.png?alt=media&amp;token=9c010791-e1dc-4632-83c2-f6cd96d6b79c" alt=""><figcaption></figcaption></figure>

**`mutate.ts`** 의 선언은 위 **`query.ts`** 와 **거의 동일**합니다. 오히려 api method 에 관계 없이 **`useMutation`** 만 사용하기 때문에 더 쉽게 느껴질 수도 있습니다.

**`UseMutationParams`** 사용 등 일부만 다르니 천천히 비교하며 확인해보세요.
{% endtab %}

{% tab title="사용하기" %}

<figure><img src="https://1168173052-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9A2Jt7XcUkiyMXRHBecz%2Fuploads%2FfQVdPZzPMUZavCX4imbd%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202023-06-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.28.50.png?alt=media&amp;token=d6723bf8-29af-4bfb-b13f-7a1afb599a0e" alt=""><figcaption></figcaption></figure>

사용 부분 또한 간단합니다.

* **custom mutation** 을 할당할 때 필요한 **`options`** 를 전달합니다.
* api를 호출하기 위한 함수는 **반환하는 `mutate` 함수**를 사용합니다. 필요한 인자가 있다면 **`mutate` 안에서 전달**합니다.

이 외에 필요한 [useMutation 공식문서](https://tanstack.com/query/v4/docs/react/guides/mutations) 를 참고해주세요.
{% endtab %}
{% endtabs %}

{% hint style="info" %}
tokplate에서 Custom Hooks를 사용할 때 제네릭 타입을 선언하여 사용하고 있습니다.

```typescript
- UseQueryParams
- UseInfiniteQueryParams
- UseMutationParams

해당 타입에 관한 설명은 
Convention/Types/modules/3.react-query 섹션에서 살펴봐주세요.
```

{% endhint %}

###
