# 커스터마이징 방법

{% 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;
    }
}
```
