# 커스터마이징 방법

{% hint style="danger" %} <mark style="color:red;">**개발 가이드를 준수하지 않아 발생하는 모든 문제는 전적으로 이용자에게 책임이 있습니다!**</mark>
{% endhint %}

## 📌 테이블 생성 <a href="#dbtablefield" id="dbtablefield"></a>

### Engine 타입 <a href="#ed-85-8c-ec-9d-b4-eb-b8-94-ec-83-9d-ec-84-b1-ec-8b-9c-engine-ed-83-80-ec-9e-85-ec-9d-80-innodb-ec-82" id="ed-85-8c-ec-9d-b4-eb-b8-94-ec-83-9d-ec-84-b1-ec-8b-9c-engine-ed-83-80-ec-9e-85-ec-9d-80-innodb-ec-82"></a>

* 테이블 생성 시, Engine 타입은 솔루션의 기본값인 **InnoDB** 를 사용해야 합니다.
* 다른 타입의 Engine을 사용할 경우 테이블의 깨짐 등의 문제 발생

### Character set, Collation <a href="#character-set-ec-9d-80-utf8mb4-collation-ec-9d-80-utf8mb4_general_ci-ec-82-ac-ec-9a-a9" id="character-set-ec-9d-80-utf8mb4-collation-ec-9d-80-utf8mb4_general_ci-ec-82-ac-ec-9a-a9"></a>

* Character set: utf8mb4
* Collation: utf8mb4\_general\_ci
* Character set 과 Collation 는 위에 명시된 솔루션 기본값을 사용해야 합니다.
* 솔루션 기본값과 다르게 사용할 경우 테이블 간 조인(Join) 시 에러가 발생합니다.
  * Error Code : 1267. Illegal mix of collations

### Primary key <a href="#primary-key-ed-95-84-ec-88-98-ec-83-9d-ec-84-b1" id="primary-key-ed-95-84-ec-88-98-ec-83-9d-ec-84-b1"></a>

* Primary Key는 필수로 생성해야 합니다.
* InnoDB 엔진의 테이블은 Primary key 기반으로 정렬 및 저장되기에 필수적으로 필요합니다.

### Comment <a href="#ed-85-8c-ec-9d-b4-eb-b8-94-ec-83-9d-ec-84-b1-eb-b0-8f-ec-bb-ac-eb-9f-bc-ec-b6-94-ea-b0-80-ec-8b-9c-c" id="ed-85-8c-ec-9d-b4-eb-b8-94-ec-83-9d-ec-84-b1-eb-b0-8f-ec-bb-ac-eb-9f-bc-ec-b6-94-ea-b0-80-ec-8b-9c-c"></a>

* 테이블 생성 및 컬럼 추가 시 Comment를 작성해야 합니다.
* Comment을 작성해야만 해당 테이블이나 컬럼의 용도를 정확하게 확인할 수 있습니다.

### Prefix <a href="#ed-85-8c-ec-9d-b4-eb-b8-94-ec-83-9d-ec-84-b1-eb-b0-8f-ec-bb-ac-eb-9f-bc-ec-b6-94-ea-b0-80-ec-8b-9c-e" id="ed-85-8c-ec-9d-b4-eb-b8-94-ec-83-9d-ec-84-b1-eb-b0-8f-ec-bb-ac-eb-9f-bc-ec-b6-94-ea-b0-80-ec-8b-9c-e"></a>

* 테이블 생성 및 컬럼 추가 시 접두사(prefix)를 사용해야 합니다.
* 솔루션 자동 패치에서 동일한 테이블이나 컬럼이 추가될 경우 오류가 발생하기 때문에 \
  업체만의 접두사를 만들어 사용해야 합니다.
* **`es_` , `zz_`** 는 솔루션에서 사용하는 접두사로, 커스터마이징 시 사용 금지합니다.

### 솔루션 제공 기본 데이터 <a href="#ec-86-94-eb-a3-a8-ec-85-98-ec-97-90-ec-84-9c-ea-b8-b0-eb-b3-b8-ec-a0-9c-ea-b3-b5-ed-95-98-eb-8a-94-e" id="ec-86-94-eb-a3-a8-ec-85-98-ec-97-90-ec-84-9c-ea-b8-b0-eb-b3-b8-ec-a0-9c-ea-b3-b5-ed-95-98-eb-8a-94-e"></a>

#### Table, Column

* 솔루션에서 기본적으로 제공하는 테이블 및 컬럼명은 수정/삭제를 금지합니다.
* 솔루션에서 사용하는 부분이기 때문에 수정이나 삭제 시 사이트 오류가 발생합니다.

#### Column Data Type <a href="#ec-86-94-eb-a3-a8-ec-85-98-ec-97-90-ec-84-9c-ea-b8-b0-eb-b3-b8-ec-a0-9c-ea-b3-b5-ed-95-98-eb-8a-94-e" id="ec-86-94-eb-a3-a8-ec-85-98-ec-97-90-ec-84-9c-ea-b8-b0-eb-b3-b8-ec-a0-9c-ea-b3-b5-ed-95-98-eb-8a-94-e"></a>

* 솔루션에서 기본 제공하는 컬럼의 데이터타입 수정을 금지합니다.
* 솔루션 자동 패치 시 원복 또는 다른 형태로 변경되기에 필요한 경우 컬럼을 추가적으로 만들어 사용해야 합니다.

## 📌 컬럼 생성 <a href="#dbtablefield" id="dbtablefield"></a>

### Default Value <a href="#primary-key-ed-95-84-ec-88-98-ec-83-9d-ec-84-b1" id="primary-key-ed-95-84-ec-88-98-ec-83-9d-ec-84-b1"></a>

* NotNull 컬럼인 경우 기본값을 지정 하셔야 합니다.
* NotNull 컬럼일 경우 기본값을 설정하지 않으면 데이터 무결성 오류가 발생할 수 있습니다.

### Comment <a href="#ed-85-8c-ec-9d-b4-eb-b8-94-ec-83-9d-ec-84-b1-eb-b0-8f-ec-bb-ac-eb-9f-bc-ec-b6-94-ea-b0-80-ec-8b-9c-c" id="ed-85-8c-ec-9d-b4-eb-b8-94-ec-83-9d-ec-84-b1-eb-b0-8f-ec-bb-ac-eb-9f-bc-ec-b6-94-ea-b0-80-ec-8b-9c-c"></a>

* 컬럼 추가 시 Comment를 작성해야 합니다.
* Comment을 작성해야만 해당 컬럼의 용도를 정확하게 확인할 수 있습니다.

## 📌 쿼리 작성

### 문자형, 숫자형 데이터 타입 주의 <a href="#eb-ac-b8-ec-9e-90-ed-98-95-ec-88-ab-ec-9e-90-ed-98-95-eb-8d-b0-ec-9d-b4-ed-84-b0-ed-83-80-ec-9e-85-e" id="eb-ac-b8-ec-9e-90-ed-98-95-ec-88-ab-ec-9e-90-ed-98-95-eb-8d-b0-ec-9d-b4-ed-84-b0-ed-83-80-ec-9e-85-e"></a>

* 문자형, 숫자형 데이터 타입에 주의하여 사용해야 합니다.
* 문자형일 경우 `''` 사용 필수입니다.
* 인덱스에 포함된 컬럼인 경우 인덱스를 사용할 수 없습니다.

  ```sql
  # 숫자형
  WHERE goodsNo = 123456

  # 문자형
  WHERE orderNo = '123456'
  ```

### SELECT 절 '\*' 사용 자제 <a href="#select-ec-a0-88-ec-9d-98-ec-9d-80-ec-82-ac-ec-9a-a9-ec-9e-90-ec-a0-9c-ed-95-98-ea-b3-a0-eb-90-98-eb" id="select-ec-a0-88-ec-9d-98-ec-9d-80-ec-82-ac-ec-9a-a9-ec-9e-90-ec-a0-9c-ed-95-98-ea-b3-a0-eb-90-98-eb"></a>

* SELECT 절의 '\*' 사용은 자제하고 가능한 필요한 컬럼만 사용해야 합니다.
* 사용되지 않을 불필요한 데이터를 반환하거나 자원을 사용할 경우 쿼리 실행 속도에 영향을 줍니다.

  ```sql
  SELECT orderNo, mallSno, memNo ...
  ```

### WHERE 절 조회 조건 추가 <a href="#where-ec-a0-88-ec-97-90-ed-95-84-ec-88-98-eb-a1-9c-ec-a1-b0-ed-9a-8c-ec-a1-b0-ea-b1-b4-ec-9e-91-ec-8" id="where-ec-a0-88-ec-97-90-ed-95-84-ec-88-98-eb-a1-9c-ec-a1-b0-ed-9a-8c-ec-a1-b0-ea-b1-b4-ec-9e-91-ec-8"></a>

* WHERE 절에 필수로 조회 조건 작성해야 합니다.
* 조회 조건이 없을 경우 테이블 전체 조회 발생하여 쿼리 실행 속도에 영향을 줍니다.

  ```sql
  WHERE orderNo = '20240415001010'
  ```

### JOIN, GROUP BY, ORDER BY <a href="#eb-b6-88-ed-95-84-ec-9a-94-ed-95-9c-join-group-by-order-by-ec-82-ac-ec-9a-a9-ec-9e-90-ec-a0-9c" id="eb-b6-88-ed-95-84-ec-9a-94-ed-95-9c-join-group-by-order-by-ec-82-ac-ec-9a-a9-ec-9e-90-ec-a0-9c"></a>

* 불필요한 JOIN, GROUP BY, ORDER BY 사용은 지양합니다.
* 불필요한 JOIN 사용 예

  ```sql
  # es_orderGoods 테이블의 컬럼을 사용하지 않음
  SELECT a.orderNo, a.mallSno, a.memNo  
  FROM es_order AS a 
  LEFT JOIN es_orderGoods AS b 
      ON b.sno = a.sno
  WHERE a.order_no = '20240415001010'
  ```
* 불필요한 GROUP BY 사용 예

  ```sql
  # 집계 함수 (COUNT, SUM, MAX 등) 없이 GROUP BY 사용
  SELECT orderNo, mallSno 
  FROM es_order
  WHERE orderStatus = 'o1'
  GROUP BY orderNo, mallSno
  ```

### 조건 컬럼(좌변) 가공 대신 상수 부분을 가공하여 사용 <a href="#ec-a1-b0-ea-b1-b4-ec-bb-ac-eb-9f-bc-ec-a2-8c-eb-b3-80-ea-b0-80-ea-b3-b5-eb-8c-80-ec-8b-a0-ec-83-81-e" id="ec-a1-b0-ea-b1-b4-ec-bb-ac-eb-9f-bc-ec-a2-8c-eb-b3-80-ea-b0-80-ea-b3-b5-eb-8c-80-ec-8b-a0-ec-83-81-e"></a>

* 인덱스 컬럼이 비교되기 전에 변형이 일어나는 경우 인덱스를 사용할 수 없습니다.

  ```sql
  # 인덱스 사용 불가
  WHERE SUBSTR(orderStatus, 1, 1) = 'o'

  # 인덱스 사용 가능
  WHERE orderStatus like 'o%'
  ```

## 📌 솔루션 수정

### DBTableField <a href="#dbtablefield" id="dbtablefield"></a>

#### DBTableField 란 <a href="#dbtablefield" id="dbtablefield"></a>

고도몰 솔루션에서 사용하는 모든 Table 과 Column을 정의해 둔 Class 이며 \
자동으로 Table 과 Column을 불러와서 사용할수 있게 해주는 기능을 합니다.

#### DBTableField 위치 <a href="#component" id="component"></a>

고도몰 원본 소스의 `Bundle/Component/Database` 에 있으며 파일명은 `DBTableField.php` 입니다.

### Table, Column 추가 방법 <a href="#table-column" id="table-column"></a>

* 사용자 소스의 `module/Component/Database` 폴더 하위에 `DBTableField.php` 파일을 생성을 합니다.
* 원본 소스의 Component 를 상속하여 확장 개발을 합니다.

```php
<?php
namespace Component\Database;
class DBTableField extends \Bundle\Component\Database\DBTableField
{
    public static function methodName()
    {
        // some code ...
    }
}
```

### Table 추가 <a href="#table" id="table"></a>

* `es_testTable` 라는 Table 추가시\
  Methods명은 `table` + `es_를 뺀 첫문자 대문자인 table 이름` 입니다.
* `val` 은 Column 명, `typ` 은 Column Type 로서 숫자형은 `i` 문자형은 `s`, `def` 은 기본값 입니다.

```php
<?php
namespace Component\Database;
class DBTableField extends \Bundle\Component\Database\DBTableField
{
    public static function tableTestTable()
    {
        $arrField = [
            ['val' => 'sno', 'typ' => 'i', 'def' => null], // 일련번호
            ['val' => 'testNo', 'typ' => 'i', 'def' => '1'], // 테스트 번호
            ['val' => 'testId', 'typ' => 's', 'def' => null], // 테스트 아이디
        ];
        return $arrField;
    }
}
```

### Column 추가 <a href="#column" id="column"></a>

* 기존의 Methods 를 그대로 사용을 하고 원래 Methods 의 것을 가지고 와서 처리합니다.
* 아래는 상품 Table에 Column을 추가하는 예제입니다.

```php
<?php
namespace Component\Database;
class DBTableField extends \Bundle\Component\Database\DBTableField
{
    public static function tableGoods($conf = null)
    {
        // 부모 method 상속
        $arrField = parent::tableGoods($conf);
        
        // 추가 필드
        $arrField[] = ['val' => 'testNo', 'typ' => 'i', 'def' => '1']; // 테스트 번호
        $arrField[] = ['val' => 'testId', 'typ' => 's', 'def' => null]; // 테스트 아이디
        
        // 필드값 리턴
        return $arrField;
    }
}
```


---

# Agent Instructions: 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://devcenter-help.nhn-commerce.com/guide/tuning/database/how-to.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.
