> For the complete documentation index, see [llms.txt](https://tech.x2bee.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tech.x2bee.com/dev-guide/pjt-prepare/publish-your-docs/bo.md).

# BO 개발 가이드

X2BEE 솔루션 3.0의 일관된 개발 스타일을 위해 사용되는 프로그래밍 표준을 설명합니다. 일관된 코드 스타일을 유지하며, 솔루션을 활용한 개발의 효율성과 가독성을 위해 가이드라인을 준수 해야합니다.

Next.js 15 기반의 애플리케이션 개발을 위한 코드 재사용성, 타입 안정성, 성능 최적화 원칙과 함께 프로젝트의 구조와 개발 표준을 설명합니다.

***

## Route 생성 가이드

* NEXT15 - [App Router](https://nextjs.org/docs/app) 사용
* URL은 폴더 계층대로 [약어집](/dev-guide/pjt-prepare/publish-your-docs.md#undefined-3)을 기반으로 조합하여 생성
* 1차분류 : *<mark style="color:red;">모듈</mark>* , 2차분류 : *<mark style="color:green;">업무</mark>*
  * 예) /src/app/\[pageType]/*<mark style="color:red;">**display**</mark>*/*<mark style="color:green;">**standard-category-mgmt**</mark>*/page.tsx → /display/standard-category-mgmt
* 페이지 컴포넌트(page.tsx) → use client 사용을 최소화

표준 구조 예시:

<table data-header-hidden><thead><tr><th width="95"></th><th width="133"></th><th width="85"></th><th width="80"></th><th></th></tr></thead><tbody><tr><td>app</td><td>(multi-lang)</td><td>모듈</td><td>업무</td><td>다국어 적용을 위한 <a href="https://nextjs.org/docs/app/building-your-application/routing/route-groups">그룹</a></td></tr><tr><td></td><td>(task-popup)</td><td></td><td></td><td>업무팝업 <a href="https://nextjs.org/docs/app/building-your-application/routing/route-groups">그룹</a> ex) 전시연결세트 팝업</td></tr><tr><td></td><td>[pageType]</td><td></td><td></td><td><p>pageType: 'page' | 'tab' | 'pagepopup'</p><p>default 값을 넣지 않으면 layout에서 page로 기본 설정</p></td></tr><tr><td></td><td>popup</td><td></td><td></td><td>공통 및 일반 팝업</td></tr><tr><td></td><td>auth</td><td></td><td></td><td>권한관련 (로그인 페이지)</td></tr><tr><td></td><td>error</td><td></td><td></td><td>에러페이지</td></tr></tbody></table>

***

## Component 생성 가이드

* 1차분류 : *<mark style="color:red;">**모듈**</mark>* , 2차분류 : *<mark style="color:green;">**업무**</mark>*
  * 예) /src/components/*<mark style="color:red;">**display**</mark>*/*<mark style="color:green;">**display-category-mgmt**</mark>* /display-category-tree.tsx
* 업무별 필수 type, schema 별도 파일로 정의

{% code title="standard-category-schema.ts" lineNumbers="true" %}

```typescript
export const StandardCategoryGoodsAttrSchema = z.object({
  stdCtgNo: StringSchema({ key: 'display.standardCategory.field.stdCtgNo' })
});
export type StandardCategoryGoodsAttrSchemaType = z.infer<typeof StandardCategoryGoodsAttrSchema>;
```

{% endcode %}

* 컴포넌트 내부에서만 사용될 것으로 판단되는 타입은 컴포넌트 내부에 선언

{% code title="StandardCategoryGoodsAttrGrid.tsx" lineNumbers="true" %}

```typescript
type Props = {stdCtgNo: string };
export default function StandardCategoryGoodsAttrGrid({ stdCtgNo }: Props) { 
... }
```

{% endcode %}

* 업무 및 state 기준으로 컴포넌트를 세밀하게 구성하여 리렌더링(Re-render) 이슈 최소화
* key 설정으로 컴포넌트의 life-cycle을 명시적으로 관리 가능
  * key는 상세하게 남겨 주는 것을 권장 (단순 ID만 사용할 경우 키 중복 가능)

예시:

{% code title="usage-example.tsx" lineNumbers="true" %}

```jsx
<CommonSectionBox>
  <StandardCategoryForm
    standardCategory={standardCategory}
    key={`standard_category_form_${standardCategory.stdCtgNo}`}
  />
</CommonSectionBox>
```

{% endcode %}

컴포넌트 내부 예시:

{% code title="StandardCategoryForm.tsx" lineNumbers="true" %}

```tsx
const StandardCategoryForm = ({ standardCategory }: Props) => {
  const { data: formData, success } = useSafeParse(
    StandardCategorySchema.safeParse(standardCategory)
  );
  ...
}
```

{% endcode %}

***

## API 호출 가이드

* REST API 사용
* Zod 스키마에서 추출된 타입 사용
* Promise 형식 반환을 기본으로 함

**GET 예시:**

{% code title="api-get.ts" lineNumbers="true" %}

```ts
export const fetchDisplaySubCategoryList = async (
  params: DisplayCategorySearchSchemaType
) => 
  (await restApi.get(
    `${API_PATH}/getSubCategoryList`, 
    { 
      params 
    }
  )) as GridResponse<DisplayCategorySchemaType[]>;
```

{% endcode %}

**POST/PUT/DELETE 예시:**

{% code title="api-post.ts" lineNumbers="true" %}

```ts
export const fetchRegistDisplayCategory = async (
  body: DisplayCategorySchemaType
) => 
  (await restApi.post(
    API_PATH, 
    {
     body 
    }
  )) as ResponseEntity<DisplayCategorySchemaType>;
```

{% endcode %}

**핸들러 및 클라이언트 API 사용 규칙:**

* handleResponse, handleGridResponse : getData 내부에서 isSuccess로 기본 데이터 출력
  * isSuccess: boolean
  * code: string
  * message: string
  * getData: () => T
* clientRestApi : clientRequest 시 사용, 기본 옵션으로 로딩 enabled
  * api: Promise
  * options(optional) → loading: true

사용 예시:

{% code title="useClientRestApi-example.tsx" lineNumbers="true" %}

```ts
const clientRestApi = useClientRestApi();

const fetchGridData = useCallback(async () => {
  const api = async () => {
    const response = await fetchDisplaySubCategoryList({ dispCtgNo: displayCategory.dispCtgNo });
    const { getData } = handleGridResponse(response as GridResponse<DisplayCategorySchemaType[]>);
    const payload = getData() as X2beeSimplePaginationDataType<DisplayCategorySchemaType>;
    setGridPayload(payload.rows);
  };

  await clientRestApi({
    api,
    // options: { loading: true } // 옵션 생략 가능
  });
}, [displayCategory.dispCtgNo]);
```

{% endcode %}

***

## Custom Hooks 생성 가이드

* 재사용이 필요하고 hooks 사용이 필요할 경우 생성
* 로직 복잡도로 인해 별도로 관리를 해야할 경우 (Utils 선고려, 내부에서 Hooks 사용 여부 고려)

***

## Utils 생성 가이드

* 재사용이 필요한 경우
* 내부에서 hooks 사용이 되지 않는 경우
* 구문이 복잡하여 별도로 관리가 필요한 경우
* 서버 영역에서 사용이 필요할 경우

***

##


---

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

```
GET https://tech.x2bee.com/dev-guide/pjt-prepare/publish-your-docs/bo.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
