# 커스터마이징 가이드

고도몰을 더 잘 알고, 더 잘 하기 위해서!

반드시 알아야하는 커스터마이징가이드를 알려 드립니다!

{% hint style="warning" %}
잘못된 커스터마이징은 쇼핑몰 운영에 큰 문제가 발생할 수 있습니다!

커스터마이징 가이드 내용을 반드시 숙지하셔서, 쇼핑몰 운영에 문제가 발생하지 않도록 개발 부탁 드립니다.
{% endhint %}

## 영상으로 알려드리는 필수! 커스터마이징 가이드

* 고도몰의 핵심 서비스, 커스터마이징이란?
* 고도몰은 어떤 구조로 되어 있을까?
* ⚠️고도몰을 개발하는 방법과 유의사항은?
* 커스터마이징 시 알아두면 유용한 기능, 디버깅?
* 고도몰 패치 배포는 어떻게 확인하고 적용할까?

{% embed url="<https://youtu.be/-lglkxxrKfA?utm_campaign=tuningguide&utm_medium=devcenter&utm_source=youtube>" %}
커스터마이징 필수 가이드
{% endembed %}

***

## \[목차] 꼭 봐야하는 커스터마이징 가이드&#x20;

커스터마이징 개발 전! 반드시 봐야하는 커스터마이징 가이드를 알려 드립니다.\
중요한 내용을 놓치지 않도록, 모든 내용을 확인해주세요!

* [시작하기 전에](/guide/intro)
* [이해하기](/guide/base-information)
* [준비하기](/guide/preparation)
* [커스터마이징 하기](/guide/tuning)
* [커스터마이징 따라하기](/guide/tuning-example)
* [잘못된 커스터마이징 사례](/guide/wrong-example)
* [기타 개발 가이드](/other-guide)


# 시작하기 전에

본 가이드는 총 3개의 파트로 구성되어있습니다.

***

\* **이해하기**&#x20;

커스터마이징에 대한 기초적인 내용(용어, 구조, 규칙 등)과 커스터마이징 가이드를 활용하는 방법을 확인할 수 있습니다.&#x20;

\* **준비하기**&#x20;

고도몰을 커스터마이징하기에 앞서, 준비해야하는 내용을 확인할 수 있습니다.

\* **커스터마이징 하기**&#x20;

커스터마이징을 실제 진행할 경우 등에 대한 내용을 확인할 수 있습니다&#x20;

***

본 가이드는 고도몰을 사용해주신 분들이 해당 가이드를 참고하여 커스터마이징함으로써, 고도몰을 보다 더 편리하고 효율적으로 사용할 수 있도록 안내하는 것을 목표로 하며,  가이드의 내용에 대해 궁금하신 사항이나 의견은 NHN커머스 고객센터(1:1문의) 로 언제든 문의하여 주시기 바랍니다.

해당 문서의 모든 내용은 법적 효력을 가지고 있지 않으며, 법적 논쟁의 근거로 활용 될 수 없습니다.&#x20;


# 이해하기

본 메뉴에서는 고도몰의 '커스터마이징'과 관련 된 기본 내용을 이해하는 단계입니다.

커스터마이징에서 자주 사용 되는 '용어' 에 대한 정의를 시작으로 커스터마이징 구조를 확인할 수 있습니다.

커스터마이징을 시작하기 앞서, 고도몰의 커스터마이징과 관련 된 기본 개념을 이해하신 후 진행하여 주세요!

더 좋은 고도몰을 만들고 이용하는데 도움이 됩니다. 🥳

{% content-ref url="/pages/2uKeVpeaJbR7gHM3WVuh" %}
[용어](/guide/base-information/terms)
{% endcontent-ref %}

{% content-ref url="/pages/sjoQptHWl1EwdLC5jlXk" %}
[구조](/guide/base-information/structure)
{% endcontent-ref %}


# 용어

본 내용에서는 커스터마이징 시 사용 되는 기본적인 용어들에 대해 설명합니다.

## 📌 커스터마이징이란?

커스터마이징이란 허용 된 범위 내에서 고도몰의 기능을 직접 개발하는 것을 의미합니다.&#x20;

예를 들어 고도몰에서 제공하지 않는 기능을 사용하고 싶을 경우 상점에서는 직접 개발 혹은 에이전시를 통하여 해당 기능을 개발하여 사용할 수 있습니다.

{% hint style="info" %}
커스터마이징이 가능한 상세 범위는 구조> [커스터마이징 가능 범위](/guide/base-information/structure/tunable-range) 내용을 참고하여주세요.&#x20;
{% endhint %}

> Q. 커스터마이징이 가능한 범위 내에서는 마음대로 개발해도 되나요?
>
> A. 커스터마이징 가능 범위를 개발하더라도, 고도몰의 가이드를 준수하여 개발하셔야 합니다.\
> 고도몰은 모든 범위가 서로 연계 되어있습니다. 따라서 고도몰에서 제시하는 규칙을 준수하지 않았을 경우 커스터마이징한 기능으로 인해 기본 기능이 동작하지 않거나, 추후 업데이트를 통해 새로운 기능이 적용 되는 경우 충돌이 발생하여 기존 기능 및 커스터마이징 기능이 정상 동작하지 않을 수 있습니다. 그러므로 고도몰이 제시하는 가이드를 반드시 참고하시어 개발해주셔야 합니다.

## 📌 패치란?

패치란 고도몰 솔루션의 업데이트를 의미하며 다음과 같은 이유에 따라 진행 되고 있습니다.

1. 법적 및 보안 이슈에 대응해야하는 경우
2. 신규 기능을 추가하거나 기존 기능(성능)을 업그레이드 하는 경우
3. 현재 제공되고 있는 기능에 버그/오류가 있어 수정이 필요한 경우
4. 그외 NHN커머스에 필요에 따라 진행해야하는 경우

고도몰 패치에는 총 세 가지 유형의 패치(프로그램 패치, DB패치, 스킨패치)가 존재합니다.&#x20;

* 프로그램 패치
* DB(Database) 패치
* 스킨패치

프로그램 패치란,  고도몰의 기능(프로그램)이 패치 되는 것을 의미하며 패치 시 자동으로 적용 됩니다.&#x20;

DB패치란, 고도몰의 DB(Database)가 패치 되는 것을 의미하며 패치 시 자동으로 적용됩니다. 테이블이 추가 되거나 테이블의 컬럼(항목)이 추가/삭제/변경 되는 경우 진행 되며, 기존 데이터를 보정하거나 새로운 데이터로 변경하는 경우에도 DB 패치가 진행 됩니다.

스킨패치란, 사용자에게 보이는 영역(스킨)에 패치가 진행 되는 것을 의미하며 관리자 스킨패치와 쇼핑몰 스킨패치로 나뉘어 집니다.

> Q. 관리자 스킨패치란? 쇼핑몰 스킨패치? 스킨패치도 자동으로 적용 되는 건가요?
>
> 관리자 스킨패치란, 고도몰 관리자 화면단이 업데이트 되어 패치가 진행 되는 것을 의미하며,  쇼핑몰 스킨패치란, 쇼핑몰 화면에 패치가 진행 되는 것을 의미합니다.<br>
>
> 관리자와 쇼핑몰 스킨패치는 모두 자동 패치 적용 대상이 되지 않습니다.\
> 관리자 화면을 커스터마이징한 경우에는 고도몰 원본소스의 관리자 스킨 소스를 확인하여 업데이트 된 부분을 반영해주셔야 합니다.   \
> 쇼핑몰 화면을 커스터마이징한 경우에는 제공 되는 리드미를 참고하여 패치 된 부분을 직접 반영해주셔야 합니다.  리드미의 상세 내용은 "리드미(ReadMe)란?" 영역의 내용을 참고하여주세요.

{% hint style="info" %}
패치 시 자동으로 적용 되는 패치(프로그램 패치, DB패치)의 경우 커스터마이징된 기능이 고도몰이 제시하는 커스터마이징 가이드에 준수 되어있지 않다면, 쇼핑몰이 출력 되지 않거나 기능이 정상 동작하지 않을 수 있습니다.
{% endhint %}

대부분의 패치는 상점에서 직접 적용하지 않아도 자동으로 적용 됩니다.\
다만 이로 인해 기존에 커스터마이징하여 사용 중인 기능에 영향이 있을 수도 있습니다. 해당 부분을 최소화 하기 위해 고도몰에서는 패치 진행 전 사전 안내를 진행하고 있습니다. [사전안내 게시글 확인하러가기 >](https://www.nhn-commerce.com/customer/board-list.gd?type=notice)\
따라서, **패치 사전 안내 게시글이나 메일을 확인하셨다면 커스터마이징한 범위가 패치 범위내에 포함되어 있는지 반드시 확인하시고,&#x20;**<mark style="color:red;">**고도몰 개발가이드와 원본소스를 참고하시어 수정**</mark>**하여 주시기 바랍니다.**&#x20;

## 📌 리드미(ReadMe)란?

고도몰 쇼핑몰 스킨이 패치 되는 경우, 해당 패치 내용은 자동으로 적용 되지 않습니다. 이에, 패치가 된 부분을 직접 확인하고 적용할 수 있는 스킨패치 가이드 즉, 리드미를 제공해드리고 있습니다.

리드미에서는 고도몰이 제공하는 무료 스킨(스토리지, 모먼트 등)을 기반으로 어떤 페이지의 어떤 구역이 어떻게 수정 되어있는지를 확인하실 수 있습니다.

{% hint style="info" %}
쇼핑몰 스킨패치 리드미는 [고객지원 > 소식 > 업데이트](https://www.nhn-commerce.com/support/board?secondaryCategoryNo=39\&primaryCategoryNo=35\&page=1\&searchValue=)에서 패치 건 별로 확인하실 수 있습니다.
{% endhint %}

> Q. 왜 쇼핑몰 스킨은 패치가 자동으로 적용 되지 않나요?
>
> A. 쇼핑몰 스킨의 경우 다양한 형태로 운영 될 수 있기 때문입니다. 예를 들어, 고도몰이  제공하는 무료 스킨을 동일하게 사용하고 있거나, 고도몰 무료 스킨을 사용하고 있지만 일부 영역을 커스터마이징(수정)하여 사용하고 있을 수도 있으며 에이전시에서 제작한 스킨을 구매하여 사용할 수도 있습니다. 이때 고도몰 스킨패치의 내용이 상점에서 사용 중인 스킨의 구조와 맞지 않는 형태라고 한다면, 패치 자동 적용으로 인해 쇼핑몰 화면의 기능이 동작하지 않거나, 일부 내용이 출력 되지 않는 등의 오류가 발생할 수 있습니다. 즉, 몰 운영의 안정성을 위해 쇼핑몰 스킨 패치는 자동 적용이 아닌 상점의 수동 적용이 필요한 부분이므로 스킨패치가 필요한 패치는 반드시 적용을 해주셔야 합니다.&#x20;

***


# 구조

고도몰 진행방법과 커스터마이징 가능 범위, 아키텍쳐 등 고도몰의 구조를 이해할 수 있는 내용을 정리하였습니다.

해당 문서의 내용을 커스터마이징 진행 전 반드시 숙지하고 진행하여주세요!\
이를 통해 고도몰 패치 시 커스터마이징에 의한 이슈 발생율을 최소화할 수 있습니다. 👍🏻

{% content-ref url="/pages/yDtgQIv3m8wwg3WwTDBS" %}
[커스터마이징 진행 방법](/guide/base-information/structure/how-to-tuning)
{% endcontent-ref %}

{% content-ref url="/pages/kxNFbPA5GqoYyhQhOQdL" %}
[커스터마이징 가능 범위](/guide/base-information/structure/tunable-range)
{% endcontent-ref %}

{% content-ref url="/pages/Se5DPyMV7aUadYRQiEnr" %}
[고도몰 아키텍쳐(Architecture)](/guide/base-information/structure/godomall-architecture)
{% endcontent-ref %}

{% content-ref url="/pages/lLjqT9okzKFQSGspcusL" %}
[코딩 규칙](/guide/base-information/structure/coding-rules)
{% endcontent-ref %}

{% content-ref url="/pages/uVBcvvATOuWNl6zrXTqg" %}
[네이밍 규칙](/guide/base-information/structure/naming-rules)
{% endcontent-ref %}


# 커스터마이징 진행 방법

커스터마이징을 진행하는 방법에 대한 내용입니다.

고도몰의 커스터마이징 진행은 다음과 같이 원본소스 확인 > 소스 커스터마이징 > 운영환경 적용의 단계로 진행 됩니다.

#### 1. 원본소스 확인

고도몰의 원본 소스를 확인하는 단계입니다. 원본소스 확인을 권장 드리는 이유는 커스터마이징이 가능한 범위를 직접 확인할 수 있을 뿐더러, 해당 소스 기반으로 한 커스터마이징을 진행하시는 것을 권장 드리기 때문입니다. \
고도몰 원본소스는  고도몰 상점 관리자의 '개발소스 관리'에서 확인할 수 있습니다.&#x20;

> 고도몰 원본소스에서 제공 되고 있는 내용을 기반으로 기능을 추가하는 커스터마이징 예시
>
> : 상품리스트 검색어 키워드에 '상품상태' 조건을 추가하는 커스터마이징

#### 2. 소스 커스터마이징

고도몰 원본소스를 기반으로 개발하는 내용으로 소스를 커스터마이징하는 단계, 즉 개발을 직접 진행하는 단계 입니다. 통상 소스 커스터마이징의 경우 각 개발자(혹은 에이전시)의 로컬 환경에서 진행 됩니다.

#### 3. 운영환경 적용

개발(커스터마이징)한 소스를 운영환경에 적용하는 단계를 의미하며, 이는 곧 사용자들이 보는 쇼핑몰에 개발 된 내용이 적용 되는 것을 의미합니다.&#x20;

#### 📌 고도몰 커스터마이징 관련 제공 기능 '개발소스 관리' 소개

고도몰의 기본 개발 방법은 원본소스를 확인하고, 커스터마이징하고자 하는 파일의 소스를 디렉토리로 복사하여 해당 파일에서 작업한 뒤 운영소스에 적용하는 것 입니다.

앞서 말씀 드린 것 처럼 쇼핑몰 스킨패치를 제외한 모든 고도몰 패치는 자동으로 적용 되는데요. 이를 위해서는 반드시 커스터마이징 시 하기 두 가지 사항을 반드시 준수해주셔야 합니다.

{% hint style="danger" %} <mark style="color:red;">**자동패치 지원 대상이 되기 위한 필수 준수 사항 ‼️**</mark>

1. 원본 소스의 class를 상속 받을 것.
2. 원본 소스의 메소드 확장 개발 시, 반드시 원본 소스의 부모 메서드를 상속 받을 것
3. 다른 클래스를 사용하는 경우에는 namespace와 class 사이에 use를 이용하여 사용하려는 class를 추가할 것
   {% endhint %}

고도몰이 제안하는 기본 개발방법대로 진행할 수 있도록 커스터마이징 관련 기능을 제공하고 있으며, 이는 상점 관리자를 통해 접속 가능한 '개발소스 관리' 기능을 통해 사용하실 수 있습니다. \
해당 기능은 커스터마이징이 가능한 고도몰을 사용하시는 경우에만 노출 되는 메뉴로, 해당 기능이 확인 되지 않은 고도몰은 커스터마이징이 불가한 상점이오니 이용에 참고하여주시기 바랍니다.&#x20;

<figure><img src="/files/C3Wld56tr2B6uTpTnUq2" alt=""><figcaption><p>고도몰 원본 소스 확인 화면</p></figcaption></figure>

<div align="center"><figure><img src="/files/SwYym76d5rNV7OyMJJnj" alt=""><figcaption><p>작업 중인 개발소스 확인 화면</p></figcaption></figure></div>

<figure><img src="/files/PRA7CiIs76HBtI1qvIom" alt=""><figcaption><p>운영환경에 적용 된 소스 확인 화면</p></figcaption></figure>


# 커스터마이징 가능 범위

고도몰의 커스터마이징이 가능한 범위 입니다. 커스터마이징 하시고자 하는 기능을 페이지 단위로 확인하여주세요.

## 커스터마이징 가능 범위/영역

* module/Controller : 컨트롤러 영역으로 사용자 URI 요청에 1:1 대응합니다.
* module/Controller/API : api 영역으로 URL 요청에 1:1대응합니다.
* module/Component : 컴포넌트 영역으로 비즈니스로직과 데이터 핸들링을 처리합니다.&#x20;
* module/Widget : 화면 부분요소로 추가할 수 있는 기능을 제공합니다.
* module/Asset/Admin : 관리자 스킨소스 보기 영역으로 관리자 내의 메뉴 및 페이지를 제공합니다.

{% hint style="info" %}
관리자 스킨소스 보기 영역은 상속개념의 영역으로 포함 되지 않습니다.\
이로 인해 자동패치 적용 시 커스터마이징에 의한 오류가 발생할 수 있어 자동패치를 지원하지 않습니다. \
관리자 스킨소스 보기 영역이 패치 된 경우, 패치 된 부분의 고도몰 원본소스를  직접 반영하여주셔야 합니다.&#x20;
{% endhint %}

## <mark style="background-color:yellow;">⚠️ 반드시 확인해주세요</mark>

* 패치의 내용이 정상적으로 적용 되지 않을 경우, 고도몰 기능이 정상 동작하지 않을 수 있습니다.  자동패치를 적용 받기위한 조건을 한번 더 확인해주세요!  [자동패치 적용 조건 확인하러 가기 >](/guide/base-information/structure/how-to-tuning)
* 커스텀 개발 시 다른 클래스를 사용하는 경우에는 `namespace 와 class 사이에 use 를 이용하여 사용하려는 class 를 추가`해야 합니다.
* module 폴더 이외에서의 개발 관련 작업은 운영정책상 삭제될 수 있습니다.


# 고도몰 아키텍쳐(Architecture)

Request의 처리순서 Controller 등의 동작 방법과 디렉토리 구조 등 고도몰의 전반적인 아키텍쳐에 대한 내용입니다.

## 📌 Request 처리 순서

<figure><img src="/files/nECMFTfM4qmyJVpry8Cl" alt=""><figcaption></figcaption></figure>

1. 사용자의 요청은 `route`로 전달 되어 고도몰에서 처리할 준비를 합니다.
2. `Application`은 솔루션 구동에 필요한 리소스를 준비하고 요청을 처리할 `Controller`를 찾아서 실행 시킵니다.
3. `Controller`는 사용자의 `Request`를 처리하고 템플릿을 찾아 화면에 보여질 데이터를 전달합니다.
4. 템플릿은 `Controller`로 부터 데이터를 전달 받아서 데이터를 설정한 뒤 `Controller`로 HTML 스트링을 반환합니다.
5. `Controller`는 템플릿과 데이터가 처리된 HTML 스트링을 화면에 출력합니다.

## 📌 Route의 동작

<figure><img src="/files/FaN29gesfmziwUGwIoYK" alt=""><figcaption></figcaption></figure>

* 사용자의 요청은 모두 `사용자 소스 디렉토리(User Source Directory)` 내 `route.php` 에서 받은 뒤 처리됩니다.
* `autoload.php`는 ClassLoader를 이용하여 `원본 소스 디렉토리(Base Source Directory)` 및 `사용자 소스 디렉토리(User Source Directory)` 아래의 클래스를 생성하여 로드합니다.
* `bootstrap.php`는 Application 생성 후 필요한 리소스를 로드합니다.

## 📌 Application의 동작

<figure><img src="/files/CNgRgsN9KkYnw6paa9kz" alt=""><figcaption></figcaption></figure>

* `bootstrap.php`에서 `Application` 객체를 생성합니다.
* `Application` 객체가 생성되면 `AbstractBootstrap`을 상속받은 클래스를 로드하여 객체를 모두 실행합니다.
* `Bootstrap`에 필요한 클래스의 객체 생성 후 `Application` 컨테이너에 주입시킵니다.
* `Application`의 실행 준비가 완료되면 사용자 요청을 처리한 `Controller`를 찾아서 요청을 처리하도록 합니다.

## 📌Controller의 동작

<figure><img src="/files/GeV94wQ6nuzNAfk62kRy" alt=""><figcaption></figcaption></figure>

* `Interceptor`에서 템플릿 레이아웃 설정, 글로벌 변수 설정, 통계 데이터 측정, 보안 및 인증과 같은 전역에서 이루어져야 하는 작업을 처리합니다.
* 사용자가 작성한 `MyController::pre()` 메소드가 실행됩니다.
* 사용자가 작성한 `MyController::index()` 메소드가 실행됩니다.
* 사용자가 작성한 `MyController::postHandle()` 메소드가 실행됩니다.

## 📌 View의 동작

<figure><img src="/files/4Y9pQXvsufbvTgG9ODLS" alt=""><figcaption></figcaption></figure>

* 컨트롤러에서 호출한 View 엔진인 Template\_를 토대로 템플릿 엔진을 구성합니다.
* 템플릿 엔진의 종류
  1. Template\_ 엔진 : `사용자` 스킨 처리
  2. Include 엔진 : `관리자` 스킨 처리

## 📌 Class Loader

#### Class Loader 소개

* 고도몰은 클래스의 `FQN(Fully Qualified Name)`을 이용하여 `class` 파일을 자동으로 `include` 하는 `autoload` 시스템을 사용합니다.
* `Classloader`는 `사용자 소스 디렉토리(User Source Directory)` 내 `route.php` 에서 정의된 `Class`를 사용할 수 있도록 설정합니다.
* `PHP`에서는 `Classloader`를 `Loader Stack`에 여러개 등록할 수 있고, `Stack`의 순서대로 `Classloader`가 동작하여 `Class`를 찾습니다. 하지만, `고도몰` 에서는 하나의 `Classloader`를 사용하며, 내부에서 여러개의 `ClassPathResolver`를 등록하여 `Loader Stack`을 구현하고 있습니다.

{% hint style="info" %}
Fully Qualified Name란?&#x20;

네임스페이스의 완전한 이름으로 아래의 예에서 볼 때 `Framework\ClassLoader\ClassLoader`, `Framework\Http\Request`을 의미합니다. 또한 반드시 네임스페이스와 물리적인 디렉토리의 경로가 동일해야 `Classloader`가 정상 실행됩니다.
{% endhint %}

#### Class Loader 동작

1. `Classloader`가 `사용자 소스 디렉토리(User Source Directory)`의 `module`에서 `class`를 먼저 검색하고, 없으면 `원본 소스 디렉토리(Base Source Directory)`에서 검색을 합니다.
2. `class`가 `사용자 소스 디렉토리(User Source Directory)`의 `module`에서 검색되면 `원본 소스 디렉토리(Base Source Directory)`의 `class`는 무시됩니다.
3. 원본 소스 중 확장 가능한 `class`는 `사용자 소스 디렉토리(User Source Directory)`의 `module`에 원본 소스의 `class`를 확장한 `Wrapping class`를 만들어 사용할 수 있습니다.

## 📌 사용자 소스 디렉토리(User Sourc Directory) 구조

* 최상위 경로에서 동작하는 파일은 `route.php`, `blank.php`만 해당됩니다.
* 신규 파일을 생성하시려면 `data`, `skin` 을 이용해 주시기 바랍니다.
* `tmp` 에서 이미지 및 신규파일의 작업을 진행하시면 파일의 소실이 우려가 있으니 지양해 주시기 바랍니다.

## 📌 사용자 소스 디렉토리(User Source Directory) 권한

* `data`, `skin` 디렉토리(하위 경로 포함)는 `0707` 이상의 권한이 필요합니다.<br>


# 코딩 규칙

커스터마이징 시 사용하는 '코딩'은 아래의 내용을 준수하여 작성해주세요.

## 📍 PHP Code Tags

* 반드시 `<?php` 와 `<?=` 만을 사용한다.

> php 파일을 template 처럼 사용하는 경우, `echo` 태그는 가급적 `<?=` 를 사용한다.

#### Closing Tag

* PHP 소스 코드만 포함된 경우, `?>` 를 생략 한다.

## 📍Indenting

* `TAB`을 사용하지 않으며, 4자리의 `SPACE`를 사용한다.
* namespace, php open tag 레벨의 인덴트를 하지 않는다.

## 📍Control Structures

**Alternative syntax**

* Alternative syntax 를 사용하지 않는다.

**Curly brackets**

* `{`, `}` 사용시 줄바꿈 하지 않는다.

**Indenting**

* `{`, `}` 내부는 반드시 들여쓰기 한다.

**Control Statements**

* Control Keyword와 조건문 사이에는 반드시 1개의 `SPACE`가 포함되어야 한다.
* `else if` 대신 `elseif` 를 사용한다.

## 📍Forbidden Functions

* `sizeof` 대신 `count`를 사용한다.
* `delete` 대신 `unset`을 사용한다.
* `print` 대신 `echo`를 사용한다.
* `is_null` 대신 `if ($var === null);` 을 사용한다.
* `create_function` 대신 `anonymous function`을 사용한다.

## 📍Function Calls

* 메서드 또는 함수 호출시 `->`,`(`,`)`,`;` 사이에 `SPACE`가 포함되면 안된다.
* 각 Arguments 사이에 `SPACE`를 삽입한다.

## 📍Class Definitions

* 하나의 파일에는 하나의 클래스를 생성해야 한다.
* `{` 를 줄바꿈 한다.
* classloader 에서 클래스 경로를 찾을 수 있도록 namespace 를 정의한다.

#### Filenames

* 클래스명과 파일명이 일치해야 한다.
* classloader에서 클래스를 찾을 수 있도록 namespace 를 sub-directory 로 간주한 위치에 파일을 저장한다.

## 📍Function Definitions

* 함수명과 `(`, `)` 사이에 `SPACE`가 포함되면 안된다.
* 클래스와 마찬가지로 `{` 를 줄바꿈 한다.

#### Arguments

* 각 Argument 사이에 `SPACE`를 넣어 가독성을 높인다.

## 📍Comments

#### Inline Comment

* `//`만 사용한다.
* `#`을 사용하지 않는다.

**Block Comment**

* 2줄 이상의 inline comment 를 사용하지 않는다.

**Document Comments**

* 파일, 함수, 메소드, 프로퍼티, 클래스, 인터페이스에는 [phpDocumentor](https://www.phpdoc.org)형식의 Document Comments를 작성해야 한다.
* 구현 메소드의 Document Comments 는 {@inheritDoc} 태그를 사용한다.

#### Task Tags

* @todo 키워드를 주석에 사용하여 추가 작업에 대한 내용을 기록해 둘 수 있다.

> TODO, FIXME, XXX 는 사용하지 않는다.

## 📍File Formats

* BOM 이 없는 UTF-8 인코딩을 사용한다.
* 파일 인코딩을 혼용하지 않는다. (ex: EUC-KR 환경에서 AJAX 처리를 위해 일부 파일을 UTF-8로 저장하는 행위)
* 줄바꿈 문자는 Unix 타입의 `LF` 만을 사용한다.
* 줄끝 공백 제거 처리한다.
* 파일의 맨 마지막 라인에 빈 공백 라인을 추가한다.

## 📍 Etc

#### Operators

* 모든 연산자 앞, 뒤로 1개의 공백을 삽입한다.
* `Ternary Operator`는 중첩 사용하지 않고, 중간 구문을 생략 사용하지 않는다.
* `Error Control Operators`(@) 를 사용하지 않는다.

#### Strings

* `"` 대신 `'` 를 사용한다.
* SQL문 과 같이 내부에 `'` 가 쓰일 수 있는 경우 `"` 사용을 허용한다.
* [Heredoc syntax](http://php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc)를 사용하지 않는다.

#### Arrays

* 배열을 여러줄로 정의할 경우 마지막 원소의 끝에 `,`를 추가한다.
* 배열 선언시 가급적 축약형 구문을 사용한다.<br>


# 네이밍 규칙

커스터마이징 시 '네이밍'이 필요한 경우에는 하기 규칙을 준수하여주세요.

## 📍Capitalization

**Casing Styles**

* 아래의 표기 형식을 사용하며, 식별자별로 구분하여 사용한다.

| Style                                 | Decription                                     |
| ------------------------------------- | ---------------------------------------------- |
| lowercase                             | 모든 단어를 띄어쓰기 하지 않은 소문자로 표기한다.                   |
| lower\_case\_with\_underscores        | 모든 단어를 소문자로 표기하고, 단어와 단어는 `_` 를 삽입하여 구분한다.     |
| UPPERCASE                             | 모든 단어를 띄어쓰기 하지 않은 대문자로 표기한다.                   |
| UPPER\_CASE\_WITH\_UNDERSCORES        | 모든 단어를 대문자로 표기하고, 단어와 단어는 `_` 를 삽입하여 구분한다.     |
| lowerCamelCase                        | 첫글자를 소문자로 표기하고, 나머지 단어의 첫글자는 대문자로 표기한다.        |
| UpperCamelCase                        | 첫글자를 대문자로 표기하고, 나머지 단어의 첫글자는 대문자로 표기한다.        |
| Capitalized\_Words\_With\_Underscores | 각 단어의 첫글자를 대문자로 표기하고, 단어와 단어는 `_` 를 삽입하여 구분한다. |

#### Style for Identifiers

* 추가적인 세부규칙은 각 항목에서 다루며, 기본 규칙은 아래와 같다.

| Indenfidier       | Style                                                          | Example                              |
| ----------------- | -------------------------------------------------------------- | ------------------------------------ |
| Variable          | lowerCamelCase, lowercase                                      | $fooBar, $i                          |
| Class             | UpperCamelCase                                                 | FooBar                               |
| Namespace         | UpperCamelCase                                                 | FooBar                               |
| Property          | lowerCamelCase                                                 | $fooBar                              |
| Method            | lowerCamelCase                                                 | fooBar                               |
| Constant          | UPPER\_CASE\_WITH\_UNDERSCORES                                 | FOO\_BAR                             |
| Internal Function | lower\_case\_with\_underscore                                  | mysql\_query                         |
| Database          | lower\_case\_with\_underscores, UPPER\_CASE\_WITH\_UNDERSCORES | gd\_goods, USP\_GET\_GD\_GOODS\_LIST |
| Column            | lower\_case\_with\_underscores                                 | goods\_name                          |

## 📍Filenames

#### PHP

* 클래스명과 파일명이 같아야 한다.

#### Resources

* Image : lower\_case\_with\_underscores 를 사용하되, 구분자는 \_ 대신 . 을 사용해도 된다.
* CSS : lower\_case\_with\_underscores 를 사용하되, 구분자는 \_ 대신 . 을 사용해도 된다.
* JS : lower\_case\_with\_underscores 를 사용하되, 구분자는 \_ 대신 . 을 사용해도 된다.

## 📍General

#### Word Choice

* 의미가 전달 될 수 있도록, 쉽고 간단한 단어를 사용하여 작명한다.
* 흔히 쓰이는 용어(ex: email, XML, file, error 등)를 사용할 경우, 반드시 1개 이상의 수식어를 함께 사용한다.
* [헝가리안 표기](http://en.wikipedia.org/wiki/Hungarian_notation)를 사용하지 않는다.
* Control Structures 에 i, j, k, v 등의 네이밍을 사용하는 것은 복잡한 중첩 구조가 아닌 경우에는 허용된다.

#### Abbreviations

* 약속된 약어 외에는 단어를 모두 풀어쓰도록 한다.

## 📍Namespaces & Classes

* UpperCamelCase 형태로 표기한다.
* Interface 는 접미사로 Interface 를 붙인다.
* Trait 는 접미사로 Trait 를 붙인다.
* Abstract 클래스는 접두사로 Abstract 를 붙인다.
* Exception 클래스는 접두사로 Exception 을 붙인다.

## 📍Methods

* lowerCamelCase 형태로 표기한다.
* 동사로 시작한다.
* Visibility를 반드시 지정한다.
* private method일 경우에만 \_ 로 시작한다.

## 📍Properties

* lowerCamelCase 형태로 표기한다.
* 명사로 시작한다.
* Visibility를 반드시 지정한다.
* private method일 경우에만 \_ 로 시작한다.

## 📍Constants

* UPPER\_CASE\_WITH\_UNDERSCORES 형태로 표기한다.
* true, false, null 은 소문자를 유지한다.

## 📍Internal Functions

* 내장 함수는 모두 소문자와 \_로 표기한다.
* PHP코드와 프로젝트 코드를 구분하기 위해 반드시 `gd_`를 prefix로 붙힌다.

## 📍Databases

**Table Name Prefix**

* 프로젝트별 구분을 위해 Table Name Prefix 를 사용할 수 있다.
* 고도몰의 Table Name Prefix 는 `es_` 이다.

**Tables**

* lower\_case\_with\_underscores 형태로 표기한다.
* DBMS 내장 키워드명, 함수명을 사용하지 않는다.
* 의미 없는 단어나, 약속되지 않은 약어를 사용하지 않는다.

**Columns**

* lower\_case\_with\_underscores 형태로 표기한다.
* DBMS 내장 키워드명, 함수명을 사용하지 않는다.
* 의미 없는 단어나, 약속되지 않은 약어를 사용하지 않는다.

**Indexes**

* lower\_case\_with\_underscores 형태로 표기한다.
* 인덱스에 포함된 모든 컬럼명을 모두 입력한다.
* 인덱스 형태별로 아래의 prefix 를 사용한다.
  * Unique : uidx
  * Index : idx

#### Tiggers / Stored Procedures / User Defined Functions / Views

* 사용금지<br>


# 준비하기


# 심화 구조 이해

본 메뉴에서는 고도몰의 '커스터마이징'을 본격적으로 시작하기 전, 고도몰 구조에 대해 심도 있게 이해하는 단계입니다.


# Routing 소개

고도몰의 Routing 을 소개하는 내용입니다.

## 📌 라우팅 소개

* 고도몰에는 요청한 `URI`에 해당하는 `PHP` 파일이 존재하지 않습니다.
* `Application` 객체에서 적절한 `Controller`를 찾아 실행한 결과를 되돌려 주는 형태로 동작합니다.
* `Application` 객체에서는 `Request`(사용자 요청 정보)를 근거로, 실행해야 할 `Controller`를 찾기 위해 `ControllerNameResolver`가 구동되도록 구성되어 있습니다.

## 📌 Rewrite Module 스펙 <a href="#rewrite-module" id="rewrite-module"></a>

* 어떤 Request 주소가 와도 `사용자 소스 디렉토리(User Source Directory)` 내 `route.php`가 실행됩니다.
* 단, 확장자가 gif, jp(e)g, png, js, css, swf, ico, eot, woff, ttf 인 파일과 `사용자 소스 디렉토리(User Source Directory)` 내 `route.php`는 제외됩니다.

**Document Root 설정**

* `사용자 소스 디렉토리(User Source Directory)` 내 `route.php`가 위치한 root의 `.htaccess` 설정 내용입니다.

```xml
DirectoryIndex route.php
RewriteEngine on

RewriteCond %{REQUEST_URI} \.(gif|jpe?g|png|js|css|swf|ico|eot|woff|ttf)$ [NC,OR]
RewriteCond %{REQUEST_URI} ^/?blank\.php$
RewriteRule ^ - [L]

RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^\/])$ $1/

RewriteRule ^ route.php [L]
```

**Data 디렉토리 설정**

* `사용자 소스 디렉토리(User Source Directory)` 내 `data` 디렉토리는 이미지 및 게시판 스킨등 사용자 정의 파일 및 웹리소스를 저장하거나 호출할 수 있습니다.
* 필요한 확장자가 있는 경우 반드시 이곳에 추가해야 웹에서 접근이 가능합니다.

```xml
RewriteCond %{REQUEST_URI} \.(php?|htm?|log|cgi|inc|xml|json|exe|bat|sh|bash|dll)$ [NC]
RewriteRule ^ - [F]
```

**기타 디렉토리 설정**

* `사용자 소스 디렉토리(User Source Directory)` 내 `data` 디렉토리을 제외한 모든 디렉토리는 웹에서 접근을 제한하기 위해 다음과 같이 설정되어 있습니다.

```xml
<IfModule mod_authz_core.c>
    Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
    Order deny,allow
    Deny from all
</IfModule>
```


# Controller 소개

고도몰의 Controller 를 소개하는 내용입니다.

{% hint style="info" %}
`Controller`는 Framework의 구동을 제외한 \
솔루션의 기본 공통 작업부터 화면 출력까지의 업무를 담당합니다.
{% endhint %}

## 📌 Controller 실행 순서 <a href="#controller" id="controller"></a>

1. `view (템플릿 엔진)` 설정
2. `Setup()`
   * 해당 화면에서 사용될 interceptor 설정 (인증, 레이아웃 설정, 공통변수 설정 등)
   * 사용자 정의 데이터 설정 (추후 지원)
3. `pre()` 실행 (사용자 정의 전처리)
4. interceptor 실행 (시스템 전처리)
   * 설정된 `interceptor` 의 `preHandle` 메소드 실행
   * 환경설정에 등록된 순서에 따라서 순차적으로 `interceptor` 실행
5. `index()`
   * 해당 Controller에서 실행되는 구문 (사용자 정의 가능 영역)
6. interceptor 실행 (시스템 후처리)
   * 설정된 `interceptor` 의 `postHandle` 메소드 실행
   * 실행 순서는 `interceptor` 등록 역순
7. `post()` 실행 (사용자 정의 후처리)
8. `fetch()`
   * 구성된 view를 html로 수신
9. `render()`
   * `header`를 설정한 후 수신된 html 데이터를 화면에 출력

## 📌 Controller 상속 구조 <a href="#controller" id="controller"></a>

![](http://localhost:63343/markdownPreview/1494396028/fileSchemeResource/e54cbd0178fd58e50c34316e5dd4a489-Controller5.png?_ijt=r8qjcqaepapne9qdf7cmkjqnbl)

* `AbstractController`는 추상화를 목적으로 `index()`, `setup()`, `pre()`, `post()`의 추상 메서드가 설정되어 있으며 최종적으로 화면 출력을 담당합니다.
* `ActionController`는 컨트롤러가 할 수 있는 `action`에 대해 정의되어 있습니다.
* `Controller`는 위젯, 플러스샵, 헤더설정 및 `Controller`에서 사용하는 절대상수를 정의합니다.
* `Widget`은 넓게 보면 컨트롤러 개념이지만 현 컨트롤러에 종속되어 부분적으로 프로그램+템플릿을 표현할 수 있습니다.

## 📌 Controller Implement <a href="#controller-implement" id="controller-implement"></a>

### 사용자(PC) 영역

```php
<?php
namespace Bundle\Controller\Front\Test;

class MyController extends \Controller\Front\Controller {
    public function index() {
        something();
    }
}
```

### 사용자(Mobile) 영역

```php
<?php
namespace Bundle\Controller\Mobile\Test;

class MyController extends \Controller\Mobile\Controller {
    public function index() {
        something();
    }
}
```

### 관리자 영역

```php
<?php
namespace Bundle\Controller\Admin\Test;

class MyController extends \Controller\Admin\Controller {
    public function index() {
        something();
    }
}
```

### 위젯 영역

```php
<?php
namespace Bundle\Widget\Front\Test;

class MyWidget extends \Widget\Front\Widget {
    public function index() {
        something();
    }
}
```

### API 영역

```php
<?php
namespace Bundle\Controller\Api\Test;

class MyController extends \Controller\Api\Controller {
    public function index() {
        something();
    }
}
```

## 📌 Controller Extends <a href="#controller-extends" id="controller-extends"></a>

### **User Source Directory**

* `module/Controller/Front/Test/MyController.php`

  ```php
  <?php

  namespace Bundle\Controller\Front\Test;

  class MyController extends \Controller\Front\Test\Controller {
      protected function func() {
          return '456';
      }
  }
  ```
* result

  ```
  [ 'test' => '456' ]
  ```

### **API**

* `module/Controller/api/Test/MyController.php`

  ```php
  <?php

  namespace Bundle\Controller\Api\Test;

  class MyController extends \Controller\Api\Test\Controller {
      protected function func() {
          // some code ...
      }
  }
  ```

## 📌 Data Handling <a href="#data-handling" id="data-handling"></a>

{% hint style="info" %}
`Controller` 의 `index()` 실행 후 `interceptor` 후처리를 통해 `DataHandler interceptor`가 실행 되면서 uri에 대응하는 위치에 있는 파일이 실행됩니다. 파일 안에서는 `$data` 변수를 통해 `data`를 가공할 수 있습니다.
{% endhint %}

ex) `사용자 소스 디렉토리(User Source Directory)` 내 `goods/goods_list.php`에 파일을 생성하고 다음과 같이 작성합니다.

* `Bundle/Controller/Front/Goods/GoodsListController.php`

  ```php
  <?php
  namespace Bundle\Controller\Front\Goods;

  class GoodsListController extends \Controller\Front\Controller {
      public function index() {
          $this->setData('data', 'original');
      }
  }
  ```
* `goods/goods_list.php`

  ```php
  <?php

  $data['data'] = 'not original';
  $data['data2'] = 'new data';
  ```
* result \[ 'data' => 'not original', 'data2' => 'new data' ]

## 📌 View Rendering <a href="#view-rendering" id="view-rendering"></a>

### View 출력 예제

```php
<?php
namespace Bundle\Controller\[Front|Admin|Mobile]\Test;

class MyController extends \Controller\[Front|Admin|Mobile]\Controller {
    public function index() {
        // somecode or data handling				
    }
}
```

### JSON 출력 예제

```php
<?php
namespace Bundle\Controller\[Front|Admin|Mobile]\Test;

class MyController extends \Controller\[Front|Admin|Mobile]\Controller {
    public function index() {
        // case 1
        $this->setData('wrapper', [
            'test1' => 1,
            'test2' => 2,
            'test3' => 3,
        ]);
        $this->json();
        
        // case 2
        $data = [
            'wrapper' => [
                'test1' => 1,
                'test2' => 2,
                'test3' => 3,
            ]
        ]);
        $this->json($data);
    }
}
```

### 파일 다운로드 예제

```php
<?php
namespace Bundle\Controller\[Front|Admin|Mobile]\Test;

class MyController extends \Controller\[Front|Admin|Mobile]\Controller {
    public function index() {
        // 파일경로와 파일명을 인자로 넘기면 즉시 다운로드가 실행됩니다
        $this->download(UserFilePath::frontSkin('mera_ws','img','btn_19out.gif'), 'sample_test.gif');
    }
}
```

### 스트림 파일 다운로드 예제

```php
<?php
namespace Bundle\Controller\[Front|Admin|Mobile]\Test;

class MyController extends \Controller\[Front|Admin|Mobile]\Controller {
    /**
     * index() 함수내 echo를 이용해 화면에 출력하면
     * 출력 버퍼를 이용해 파일로 저장합니다.
     */
    public function index() {
        // case 1
        echo '인덱스내에 스트링을 출력하면 해당 내용이 결과로 저장되며, 파일 확장자에 따라서 자동으로 Mime-Type이 설정됩니다.';
        $this->streamedDownload('sample_test.txt');
        
        // case 2
        echo '<table><tr><td>엑셀</td></tr></table>';
        $this->streamedDownload('sample_test.xls');
    }
}
```

### 리다이렉트 예제

```php
<?php
namespace Bundle\Controller\[Front|Admin|Mobile]\Test;

class MyController extends \Controller\[Front|Admin|Mobile]\Controller {
    public function index() {
        $this->redirect('../order/cart');
    }
}
```


# HTTP 소개

고도몰의 HTTP 관련 메서드를 소개하는 내용입니다.

## 📌 Request <a href="#request" id="request"></a>

`Form`을 작성하거나, `File`을 업로드 하는 등의 사용자 요청과 관련된 제어를 수행합니다. 일반적으로 `$_GET`, `$_POST`, `$_FILES`, `$_SERVER`, `$_REQUEST`의 내용에 접근할 수 있으며, 아래 명시된 편의 메서드를 제공합니다.

```php
Request::get()->get('someKey'); // $_GET['someKey']
Request::post()->get('someKey'); // $_POST['someKey']
Request::server()->get('REQUEST_URI'); // $_SERVER['REQUEST_URI']
Request::files()->get('someKey'); // $_FILES['someKey']
Request::request()->get('someKey'); // $_REQUEST['someKey']
```

> 단, `$_ENV` 는 지원하지 않습니다. 다차원 키의 접근 방법으로 `dot notation` 을 지원합니다.

### **값 설정하기**

```php
Request::get()->set('name', 'value');
Request::post()->set('name', 'value');
Request::files()->set('file.name', 'value');
Request::request()->set('sampel.name', 'value');
Request::server()->set('REQUEST_URI', 'value');
```

### **값 가져오기**

```php
$name = Request::get()->get('name');
$name = Request::post()->get('name.first');
$name = Request::files()->get('name.first');
$name = Request::request()->get('name.first');
$name = Request::server()->get('REQUEST_URI');
```

요청값이 없는 경우 다음과 같이 2번째 인자로, 기본값을 설정할 수 있습니다.

```php
$name = Request::get()->get('name', '기본값');
$name = Request::post()->get('name.first', '기본값');
```

### **모든 값 가져오기**

해당 `get()`이 가지고 있는 모든 변수를 배열로 반환합니다.

```php
$allGet = Request::get()->all();
$allGet = Request::get()->toArray();
```

### **값 지우기**

```php
Request::get()->del('name');
Request::get()->del('name.first');
```

### **모든 값 지우기**

```php
Request::get()->clear();
```

### **값의 존재유무 체크하기**

```php
if (Request::get()->has('name')) {
    // some code...
}

if (Request::get()->has('name.first')) {
    // some code...
}
```

### **주요 Method**

#### **getServerAddress()**

서버의 `IP주소`를 반환하며, `cli`에서도 정상적으로 가져올 수 있도록 처리되었습니다.

#### **getRemoteAddress()**

클라이언트의 `ip주소`를 반환하며, `Proxy` 혹은 `nginx`와 같은 구조에서 정상적으로 반환할 수 있도록 처리되었습니다.

#### **isCli()**

`cli`접근 여부를 체크하여 `boolean`을 반환합니다.

```php
if (Request::isCli()) {
    // background process
}
```

#### **isAjax()**

`Request` 가 `ajax`인지 체크 후 `boolean` 값을 반환합니다.

```php
if (Request::isAjax()) {
    // ajax code
}
```

#### **isMethod($method)**

주어진 `$method` 인자와 현재 `REQUEST_METHOD` 비교 후 `boolean` 값을 반환하며, 파라미터가 `get`, `post`, `head`, `options`, `put`, `delete`, `trace`, `connect`이 아닌 경우 예외 처리됩니다.

```php
if (Request::isMethod('get')) {
    // get인 경우만 실행
}

if (Request::isMethod('post')) {
    // get인 경우만 실행
}
```

#### **isMobile()**

`도메인`의 `m`이 있는지 여부를 통해 모바일 여부를 `boolean` 형태로 반환합니다.

```php
if (Request::isMobile()) {
    // 도메인이 m.domain.com 인 경우
}
```

#### **isMobileDevice()**

접속한 기기가 `모바일` or `태블릿`인지 `UserAgent`를 통해 체크 후 `boolean`을 반환합니다.

```php
if (Request::isMobileDevice()) {
    // 접속기기가 모바일/태블릿인 경우
}
```

#### **isRefresh()**

브라우저에서 `새로고침`을 했는지에 대해 체크 후 `boolean`을 반환합니다.

```php
if (Request::isRefresh()) {
    // 페이지 새로고침을 한 경우
}
```

## 📌 Response <a href="#response" id="response"></a>

`Json`, `Redirect`, `Streamed`, `BinaryFile` 의 4가지 형태로 응답 객체를 생성할 수 있습니다. Chaining method를 제공합니다.

### **Create Instance**

```php
$response = Response::create($content, $statusCode, $headers);
```

## 📌 Session <a href="#session" id="session"></a>

파일 세션만 지원합니다.

> 다차원 키의 접근 방법으로 `dot notation` 을 지원합니다.

### **Setting a value**

```php
Session::set('name', 'value');
Session::set('name.first', 'value');
```

### **Getting a value**

```php
$name = Session::get('name');
$name = Session::get('name.first');
```

> 2번째 인자로, 기본값을 설정할 수 없습니다. 미설정시 `null` 로 설정됩니다.

### **Getting all values**

```php
$session = Session::all();
```

### **Removing a value**

```php
Session::del('name');
Session::del('name.first');
```

### **Removing all values**

```php
Session::clear();
```

### **Determining if an given key exists**

```php
if (Session::has('name')) {
    // some code...
}

if (Session::has('name.first')) {
    // some code...
}
```

## 📌 Cookie <a href="#cookie" id="cookie"></a>

> 쿠키는 다차원 키를 사용할 수 없습니다.

### **Setting a value**

```php
Cookie::set('name', 'value'); // 세션 쿠키 생성
Cookie::set('name', 'value', 3600, '/', true, true); // 1시간 만료 쿠키 생성
```

### **Getting a value**

```php
$name = Cookie::get('name');
```

### **Getting all values**

```php
$session = Cookie::all();
```

### **Removing a value**

```php
Cookie::del('name');
```

### **Determining if an given key exists**

```php
if (Cookie::has('name')) {
    // some code...
}
```


# Database 소개

고도몰의 Database 관련 메서드 및 사용법을 를 소개하는 내용입니다.

## 📌 주요 function <a href="#function" id="function"></a>

### **bind\_param\_push**

```php
bind_param_push($bindParam, $type, $value)
```

* binding처리를 위한 파라미터를 정의하고 배열형태로 저장합니다.
* WHERE 절에 저장될 파라미터 정보 타입인 `$type`과 파라미터 값인 `$value` 를 배열형태의 `$bindParam`값으로 저장하여 반환합니다.

### **query\_complete**

```php
query_complete($isReset)
```

* 멤버 변수에 저장했던 쿼리문의 각 요소`(field, join, where, group, order. limit)`값에 조건절에 맞는 쿼리문을 추가하여 값을 생성합니다.
* `bool`타입의 `$isReset` 파라미터로 사용한 멤버 변수의 리셋 여부를 설정할 수 있습니다.

### **query\_fetch**

```php
query_fetch($strSQL, array $arrBind, bool $dataArray)
```

* `$strSQL`에 쿼리문을 저장하고, binding처리된 파라미터가 저장된 `$arrBind`로 쿼리 결과를 출력합니다.
* `$arrBind`는 반드시 배열타입으로 지정해야 합니다.
* `bool`타입의 `$dataArray` 파라미터로 결과 데이터의 배열 타입 출력 여부를 결정합니다.

### **get\_binding**

```php
get_binding($defaultSetting, $arrData, $dbType, $arrInclude, $arrExclude)
```

* binding 데이터를 배열처리하여 결과를 반환합니다.
* `$defaultSetting`에는 처리할 테이블의 기본값 배열을 저장하고 `$arrInclude`에는 `$defaultSetting`에 저장된 기본값 배열에서 사용할 필드명을, `$arrExclude`에는 제외할 필드명을 저장합니다. `$arrData`에는 처리할 데이터, `$dbType`에는 처리 방식`(insert|update|select|delete)`을 저장하여 기본값 데이터에서 처리할 데이터를 추출하여 배열형태로 결과를 반환합니다.

### **set\_insert\_db**

```php
set_insert_db($dbTable, $arrTableField, $arrTableValue, $bindChk, $debug)
```

* `$dbTable`에 저장할 테이블 명을 넣고 해당 테이블 데이터 필드 정보가 담긴 `$arrTableField`와 값 정보가 담긴 `$arrTableValue`로 insert 쿼리를 실행합니다.
* `$bindChk` 파라미터에 `‘y’` 값을 저장하면 쿼리에 저장되어있는 파라미터를 binding 처리하여 쿼리를 실행합니다.

### **set\_update\_db**

```php
set_update_db($dbTable, $arrTableParam, $strWhere, $arrBindParam, $debug)
```

* `$dbTable`에 수정할 테이블 명을 넣고 수정할 테이블의 필드 및 값 정보가 담긴 `$arrTableParam`과 WHERE 절이 담긴 `$strWhere`, binding처리된 파라미터 배열 값인 `$arrBindParam`을 받아 update 쿼리를 실행합니다.
* 실행 후 update가 적용된 레코드 개수를 반환합니다.

### **set\_delete\_db**

```php
set_delete_db($dbTable, $strWhere, $arrBindParam, $debug)
```

* `$dbTable`에 내용을 삭제할 테이블 명을 넣고 WHERE 절이 담긴 `$strWhere`, binding처리된 파라미터 배열 값인 `$arrBindParam`을 받아 delete 쿼리를 실행합니다.
* 실행 후 delete가 적용된 레코드 개수를 반환합니다.

### **bind\_query**

```php
bind_query($strSQL, $arrBind)
```

* 쿼리문이 담긴 `$strSQL` 값과 binding 처리할 파라미터가 담긴 `$arrBind` 값을 받아 쿼리를 실행합니다.

### **getCount**

```php
getCount($tableName, $column, $appendQuery)
```

* 해당 테이블의 쿼리 결과에 대한 row count를 반환합니다.

## 📌 Usage <a href="#usage" id="usage"></a>

### **선언**

#### 생성자에서 선언

```php
class MyComponent
{
    protected $db = null;

    /**
     * 생성자
     */
    public function __construct()
    {
         $this->db = \App::load('DB');
    }

    public function updateData($arrData)
    {
        $arrBind = $this->db->get_binding(DBTableField::tableTestInfo(), $arrData, 'update');
        $this->db->bind_param_push($arrBind['bind'], 'i', $ arrData ['sno']);
        $this->db->set_update_db('es_testTable', $arrBind['param'], 'sno = ?', $arrBind['bind']);
    }
}
```

#### 메소드 내에서 선언

```php
public function selectData($bdId, $bdSno)
{
    $db = \App::load('DB');
    $arrBind = [];
    $query = sprintf("SELECT MIN(sno) FROM %s WHERE field1 = ? AND field2 = ? ", 'es_testTable');
    $db->bind_param_push($arrBind, 's', $field1);
    $db->bind_param_push($arrBind, 'i', $field2);
    $result = $db->query_fetch($query, $arrBind, false);

    return $result;
}
```

### **SELECT**

#### **예제 코드 1**

```php
$this->db->strField = 'field1, field2';
$this->db->strJoin = ' LEFT JOIN es_testTable AS t1 ON t2.testSno = t1.sno';
$this->db->strWhere = 't1.field3 = ?';
$this->db->strOrder = 't1.field DESC';
$this->db->strLimit = '0, 10';

$this->db->bind_param_push($bindParam, $type, $value);

$query = $this->db->query_complete();
$strSQL = sprintf('SELECT %s FROM es_testTable1 %s', array_shift($query), implode(' ', $query));

return $this->db->query_fetch($strSQL, $bindParam, false);
```

* 위와 같이 필드와 조인, WHERE 절, GROUP BY 절, ORDER BY 절, LIMIT 값을 멤버 변수에 설정 한 후에 `query_complete()` 메소드로 설정한 조건들을 적용시킵니다.
* WHERE 절이 있다면 `bind_param_push()` 메소드로 해당 파라미터를 binding 처리해줍니다.
* 쿼리문 설정 후, `query_fetch()` 메소드를 통해 실행 결과를 출력합니다.

#### **예제 코드 2**

```php
$strSQL = sprintf("SELECT * FROM es_testTable WHERE field = '%s'", $field);
$data = $this->db->query_fetch($strSQL, null);
```

* 쿼리문 내에 조건절까지 포함하여 쿼리문 변수를 선언한 후에 `query_fetch()` 메소드로 결과를 반환합니다.

### **INSERT**

#### **예제 코드 1**

```php
$arrBind = $this->db->get_binding($defaultSetting, $arrData, 'insert');
$this->db->set_insert_db('es_testTable', $arrBind['param'], $arrBind['bind'], 'y');
```

* `get_binding()` 메소드를 통해 INSERT할 테이블 데이터 배열을 가져옵니다.
* `set_insert_db()` 메소드를 통해 `get_binding()` 메소드로 변환된 배열 값을 해당 테이블에 INSERT 해줍니다.

#### **예제 코드 2**

```php
$strSQL = "INSERT INTO es_testTable SET `field1` = ?, `field2` = ?";
$this->db->bind_param_push($arrBind, 'i', $field1);
$this->db->bind_param_push($arrBind, 's', $field2);
$this->db->bind_query($strSQL, $arrBind);
```

* insert 쿼리문을 선언합니다.
* INSERT할 파라미터를 `bind_param_push()` 메소드로 정의하고 `bind_query()` 메소드를 통해 쿼리문을 실행합니다.

### **UPDATE**

#### **예제 코드 1**

```php
$arrBind = $this->db->get_binding(DBTableField::testTable(), $arrData, 'update', $arrInclude);
$this->db->bind_param_push($arrBind['bind'], 's', $data);
$this->db->set_update_db('es_testTable', $arrBind['param'], 'field1 = ?', $arrBind['bind']);
```

* `get_binding()` 메소드로 수정할 테이블 정보를 배열 형태로 받아온 후, `bind_param_push()`로 WHERE 절 파라미터를 정의합니다.
* `set_update_db()` 메소드를 통해 수정합니다.

#### **예제 코드 2**

```php
$strSQL = "UPDATE es_testTable SET `field1` = ? WHERE `field2` = ?";
$this->db->bind_param_push($arrBind, 's', $field1);
$this->db->bind_param_push($arrBind, 'i', $field2);
$this->db->bind_query($strSQL, $arrBind);
```

* `bind_param_push()` 메소드로 WHERE 절 파라미터를 정의 후, `bind_query()` 메소드로 쿼리문을 실행합니다.

#### **예제 코드 3**

```php
$arrBind = $this->db->updateBinding(DBTableField::testTable(), $arrData);
$this->db->bind_param_push($arrBind['bind'], 'i', $ arrData ['sno']);
$this->db->set_update_db('es_testTable', $arrBind['param'], 'sno = ?', $arrBind['bind']);
```

* `updateBinding()` 메소드로 수정할 테이블 배열 값을 받아 온 후 `bind_param_push()` 메소드로 WHERE 절 파라미터를 정의합니다.
* `set_update_db()` 메소드로 데이터를 수정합니다.

### **DELETE**

#### **예제 코드 1**

```php
$this->db->bind_param_push($arrBind, 's', $arrData['field1']);
$this->db->bind_param_push($arrBind, 's', $arrData['field2']);
$this->db->set_delete_db('es_testTable', 'field1 = ? AND field2 = ?', $arrBind);
```

* `bind_param_push()` 메소드로 삭제할 쿼리의 WHERE 절 파라미터를 정의합니다.
* `set_delete_db()` 메소드로 삭제 쿼리문을 실행하여 WHERE 절 조건과 일치하는 레코드를 삭제합니다.

#### **예제 코드 2**

```php
$query = "DELETE FROM es_testTable WHERE field1 = ?";
$this->db->bind_param_push($arrBind, 'i', $field1);
$this->db->bind_query($query, $arrBind);
```

* delete 쿼리를 선언하고 WHERE 절 파라미터를 `bind_param_push()` 메소드로 정의합니다.
* `bind_query()`로 쿼리문을 실행하여 WHERE 절에 맞는 레코드를 찾아 삭제합니다.

### **Transaction**

트랜잭션을 이용하기 위해서는, 코드 블럭을 아래와 같이 감싸면 됩니다.

```php
try {
    \DB::begin_tran();
    $result = Some::dbResult();
    \DB::commit();
} catch (Exception $e) {
    \DB::rollback();
}
```

`Closure` 를 이용하여 좀더 심플한 코드를 작성할 수 있습니다.

```php
$result = \DB::transaction(function () {
    return Some::dbResult();
});
```


# Security 소개

고도몰의 Security 를 소개하는 내용입니다.

## 📌 Encryptor <a href="#encryptor" id="encryptor"></a>

대칭 키 암호화 알고리즘인 `RIJNDAEL 256`(레인달 256)을 이용하여 정보를 보호할수 있고, \
`BCRYPT HASH`를 이용해 패스워드를 관리할 수 있습니다.

### **Encrypt**

```php
$encrypted = Encryptor::encrypt('value');
```

### **Encrypt with salt string**

```php
$encrypted = Encryptor::encrypt('value', 'some salt string');
```

### **Decrypt**

```php
$decrypted = Encryptor::decrypt('value');
```

### **Decrypt with salt string**

```php
$decrypted = Encryptor::decrypt('value', 'some salt string');
```

### **MySQL AES 호환**

MySQL의 AES 함수이 구현되어 있으므로 암호화를 위해 MySQL에 연결하지 않아도 됩니다.

#### **MySQL AES Encrypt**

```php
$encrypted = Encryptor::mysqlAesEncrypt('value', 'some encryption key');
```

#### **MySQL AES Decrypt**

```php
$decrypted = Encryptor::mysqlAesDecrypt('value', 'some encryption key');
```

## 📌 Password <a href="#password" id="password"></a>

### **Hashing**

```php
$hash = Password::hash('somepassword');
```

### **Verifying**

```php
$result = Password::verify('somepassword', $hash);
```

### **Re-Hashing**

```php
// cost 12
$hash = Password::hash('somepassword', ['cost' => 12]);

// 이후에 cost 가 바뀌거나, hash 알고리즘이 바뀐 경우 (검증은 정상적으로 됨)
if (Password::needsRehash($hash, ['cost' => 20])) {
    $hash = Password::hash('somepassword', ['cost' => 20]);
    // save...
}
```


# Exception 소개

고도몰의 Exception 를 소개하는 내용입니다.

* 페이지의 전반적인 `오류`에 따른 처리를 할 수 있도록 지원합니다.
* 정의되어 있지 않는 경우 시스템 `Exception`의 기본 예외처리를 사용합니다.

## 📌 Usage <a href="#usage" id="usage"></a>

Exception별 사용방법은 다음과 같습니다.

### **AlertBackException**

경고창에 메시지 출력 후 페이지 뒤로 가기를 실행합니다.

```php
if ($error !== false) {
    // some code...
} else {
    throw new AlertBackException('메시지');
}
```

### **AlertCloseException**

경고창에 메시지 출력 후 브라우저를 닫습니다.

```php
if ($error !== false) {
    // some code...
} else {
    throw new AlertCloseException('메시지');
}
```

### **LayerException**

레이어에 메시지를 출력합니다.

#### **사용예제 1**

```php
if ($error !== false) {
    // some code...
} else {
    throw new LayerException('메시지', null, null, $formId, $timer, $onUnBlock, $addScript, $isPrint);
}
```

#### **사용예제 2**

메시지가 자동으로 입력되며, 저장 후 레이어 사라지게 할 때 사용합니다.

```php
if ($error !== false) {
    // some code...
} else {
    throw new LayerException();
}
```

### **AlertOnlyException**

경고창에 메시지만 출력합니다.

```php
if ($error !== false) {
    // some code...
} else {
    throw new AlertOnlyException('메시지');
}
```

### **AlertRedirectException**

경고창에 메시지 출력 후 지정된 `url`로 이동합니다. 타겟을 지정하면 지정된 타겟에서 url을 호출합니다.

{% hint style="info" %}
`redirect`만 원하는 경우 `controller`에서 `$this->redirect($url)`을 사용하세요.
{% endhint %}

```php
if ($error !== false) {
    // some code...
} else {
    throw new AlertRedirectException('메시지', null, null, $url, $target);
}
```

### **HttpException**

`Request`에 대한 서버 응답코드와 메시지를 담아 지정된 에러페이지로 출력합니다. \
`StatusCode`는 가이드 페이지 하단의 `Status Code`를 참고해주세요.

```php
if ($error !== false) {
    // some code...
} else {
    throw new HttpException($message, 404);
}
```

### **DatabaseException**

Query 실행으로 인해 `Exception`이 발생할 경우, \
`$e->getQuery()`로 `Exception`이 발생한 쿼리를 확인할 수 있습니다.

```php
if ($error !== false) {
    // some code...
} else {
    try {
        throw new DatabaseException($message, $code, $previouis, $query);
    } catch (\Exception $e) {
        printf($e->getQuery());
    }
}
```

### **UploadException**

파일 업로드시 사용하는 Exception으로 아래 정의된 `Code`를 넣어 사용합니다.

```php
if ($error !== false) {
    // some code...
} else {
    try {
        // 업로드한 파일이 upload_max_filesize를 초과했습니다.
        throw new UploadException(UPLOAD_ERR_INI_SIZE);
        
        // 업로드한 파일이 지정된 파일크기보다 큽니다.
        throw new UploadException(UPLOAD_ERR_FORM_SIZE);
        
        // 파일이 일부분만 전송되었습니다.
        throw new UploadException(UPLOAD_ERR_PARTIAL);
        
        // 파일이 전송되지 않았습니다.
        throw new UploadException(UPLOAD_ERR_NO_FILE);
        
        // 임시 폴더가 없습니다.
        throw new UploadException(UPLOAD_ERR_NO_TMP_DIR);
        
        // 디스크에 파일 쓰기를 실패했습니다.
        throw new UploadException(UPLOAD_ERR_CANT_WRITE);
        
        // 확장에 의해 파일 업로드가 중지되었습니다.
        throw new UploadException(UPLOAD_ERR_EXTENSION);
        
        // 알려지지 않은 에러가 발생했습니다.
        throw new UploadException('정의되지 않은 코드');
    } catch (\Exception $e) {
        printf($e->getMessage());
    }
}
```

## 📌 Status Code <a href="#status-code" id="status-code"></a>

<table><thead><tr><th width="100" align="center">Code</th><th>Message</th><th>Description</th></tr></thead><tbody><tr><td align="center">100</td><td>Continue</td><td></td></tr><tr><td align="center">101</td><td>Switching protocols</td><td></td></tr><tr><td align="center">200</td><td>OK</td><td></td></tr><tr><td align="center">201</td><td>Created</td><td>POST 명령 실행 및 성공</td></tr><tr><td align="center">202</td><td>Accepted</td><td>서버가 클라이언트 명령을 받음</td></tr><tr><td align="center">203</td><td>Non-Authoritative Information</td><td>서버가 클라이언트 요구 중 일부만 전송</td></tr><tr><td align="center">204</td><td>No Content</td><td>클라이언트 요구를 처리했으나 전송할 데이터가 없슴</td></tr><tr><td align="center">205</td><td>Reset content</td><td></td></tr><tr><td align="center">206</td><td>Partial content</td><td></td></tr><tr><td align="center">300</td><td>Multiple choices (최근에 옮겨진 데이터를 요청)</td><td></td></tr><tr><td align="center">301</td><td>Moved permanently</td><td>요구한 데이터를 변경된 임시 URL에서 찾음</td></tr><tr><td align="center">302</td><td>Moved temporarily</td><td>요구한 데이터가 변경된 URL에 있음을 명시</td></tr><tr><td align="center">303</td><td>See other</td><td>요구한 데이터를 변경하지 않았기 때문에 문제가 있슴</td></tr><tr><td align="center">304</td><td>Not modified</td><td></td></tr><tr><td align="center">305</td><td>Use proxy</td><td></td></tr><tr><td align="center">307</td><td>Temporary Redirect</td><td></td></tr><tr><td align="center">400</td><td>Bad request</td><td>클라이언트의 잘못된 요청으로 처리할 수 없슴</td></tr><tr><td align="center">401</td><td>Unauthorized</td><td>클라이언트의 인증 실패</td></tr><tr><td align="center">402</td><td>Payment required</td><td>예약됨</td></tr><tr><td align="center">403</td><td>Forbidden</td><td>접근이 거부된 문서를 요청함</td></tr><tr><td align="center">404</td><td>Not found</td><td>문서를 찾을 수 없음</td></tr><tr><td align="center">405</td><td>Method not allowed</td><td>리소스를 허용안함</td></tr><tr><td align="center">406</td><td>Not acceptable</td><td>허용할 수 없음</td></tr><tr><td align="center">407</td><td>Proxy authentication required</td><td>프록시 인증 필요</td></tr><tr><td align="center">408</td><td>Request timeout</td><td>요청시간이 지남</td></tr><tr><td align="center">409</td><td>Conflict</td><td>프록시 인증 필요</td></tr><tr><td align="center">410</td><td>Gone</td><td>영구적으로 사용할 수 없음</td></tr><tr><td align="center">411</td><td>Length required</td><td></td></tr><tr><td align="center">412</td><td>Precondition failed</td><td>프록시 인증 필요</td></tr><tr><td align="center">413</td><td>Request entity too large</td><td>요청 데이터가 너무 큼</td></tr><tr><td align="center">414</td><td>Request-URI too long</td><td>URL이 너무 김</td></tr><tr><td align="center">415</td><td>Unsupported media type</td><td></td></tr><tr><td align="center">500</td><td>Internal server error</td><td>내부 서버 오류</td></tr><tr><td align="center">501</td><td>Not implemented</td><td>클라이언트에서 서버가 수행할 수 없는 행동을 요구함</td></tr><tr><td align="center">502</td><td>Bad gateway</td><td>서버의 과부하 상태</td></tr><tr><td align="center">503</td><td>Service unavailable</td><td>외부 서비스가 죽었거나 현재 멈춤 상태</td></tr><tr><td align="center">504</td><td>Gateway time-out</td><td></td></tr><tr><td align="center">505</td><td>HTTP Version not supported</td><td>HTTP 버전 미지원</td></tr></tbody></table>


# Language 소개

고도몰의 Language 를 소개하는 내용입니다.

* `Locale` 에 따른 언어를 출력할 수 있도록 지원하며, `getText`방식이 적용되어 있습니다.
* 커스터마이징 상점의 경우 언어 설정을 별도 수정하여 사용할 수 없습니다. (추후 지원 예정)

## 📌 **기본 Usage**

고도몰 컨트롤러 및 컴포넌트에서의 기본적인 사용법은 아래와 같으며 치환코드는 1개만 넣을 수 있습니다.

```php
__('오류가 발생하였습니다.');
__('%s 오류가 발생하였습니다.', $erroCode);
```

치환 문자를 사용해야 하는 경우,

```php
sprintf(__(%s), $sample1, $sample2);
```

## 📌 **상세 Usage**

아래 함수는 전역함수로 어느 파일에서도 사용할 수 있습니다.

* `$original` : 기본메시지를 선언합니다.
* `$plural` : 기본메시지의 복수형을 선언합니다.
* `$value` : 복수형 사용을 위한 조건으로 정수형 숫자를 선언합니다.
* `$context` : 메시지를 포함하는 위치 정보로 동일 단어를 다르게 사용할 수 있습니다.
* `$domain` : 도메인은 언어파일의 범위(영역)를 나타내며 고도몰에서는 파일 이름을 도메인으로 사용하고 있습니다.

### **기본형**

```php
__($original)
```

```
#: data/skin/front/food_story/main/index.html:281
msgid "테스트"
msgstr "test"
```

```php
echo __('테스트');
__e('테스트');

// print
test
test
```

### **복수형**

```php
n__($original, $plural, $value)
```

```cli
#: data/skin/front/food_story/main/index.html:281
msgid "테스트"
msgid_plural "테스트들"
msgstr[0] "test"
msgstr[1] "tests"
```

```php
echo n__('테스트', '테스트들', 1);
echo n__('테스트', '테스트들', 2);

// print
test
tests
```

### **컨텍스트형**

```php
p__($context, $original)
```

```cli
#: data/skin/front/food_story/main/index.html:281
msgctxt "메뉴"
msgid "테스트"
msgstr "menu test"

#: data/skin/front/food_story/main/index.html:281
msgctxt "도구"
msgid "테스트"
msgstr "tool test"
```

```php
echo p__('메뉴', '테스트');
echo p__('도구', '테스트');

// print
menu test
tool test
```

### **도메인형**

```php
d__($domain, $original)
```

```cli
// domain1 파일
#: data/skin/front/food_story/main/index.html:281
msgid "테스트"
msgstr "domain1 test"

// domain2 파일
#: data/skin/front/food_story/main/index.html:281
msgid "테스트"
msgstr "domain2 test"
```

```php
echo d__('도메인1', '테스트');
echo d__('도메인2', '테스트');

// print
domain1 test
domain2 test
```

### **도메인 컨텍스트형**

```php
dp__($domain, $context, $original)
```

```cli
// domain1 파일
#: data/skin/front/food_story/main/index.html:281
msgctxt "메뉴"
msgid "테스트"
msgstr "domain1 test"

// domain2 파일
#: data/skin/front/food_story/main/index.html:281
msgctxt "도구"
msgid "테스트"
msgstr "domain2 test"
```

```php
echo dp__('도메인1', '메뉴', '테스트');
echo dp__('도메인1', '도구', '테스트');
echo dp__('도메인2', '메뉴', '테스트');
echo dp__('도메인2', '도구', '테스트');

// print
domain1 menu test
domain1 tool test
domain2 menu test
domain2 tool test
```

### **도메인 컨텍스트 복수형**

```php
dnp__($domain, $context, $original, $plural, $value)
```

```cli
// domain1 파일
#: data/skin/front/food_story/main/index.html:281
msgctxt "메뉴"
msgid "테스트"
msgid_plural "테스트들"
msgstr[0] "domain1 test"
msgstr[1] "domain1 tests"

// domain2 파일
#: data/skin/front/food_story/main/index.html:281
msgctxt "도구"
msgid "테스트"
msgid_plural "테스트들" 
msgstr[0] "domain2 test"
msgstr[1] "domain2 tests"
```

```php
echo dnp__('도메인1', '메뉴', '테스트', '테스트들', 1);
echo dnp__('도메인1', '도구', '테스트', '테스트들', 2);
echo dnp__('도메인1', '메뉴', '테스트', '테스트들', 1);
echo dnp__('도메인1', '도구', '테스트', '테스트들', 2);

// print
domain1 test
domain1 tests
domain2 test
domain2 tests
```


# 오픈 API 사용가이드


# 인증키 발급 방법 안내

오픈API를 통한 연동 개발에 앞서 꼭 필요한 인증키 발급 방법을 안내 드립니다.

이용 중인 쇼핑몰에서 자체 개발하거나 귀사에서 제공 중인 서비스와 \
고도몰 서비스의 연동 개발을 진행하는 경우에 필요한 정보입니다.

만약 타사 서비스를 이용하는 경우 샵링커, 이지어드민, 셀메이트 등에 해당한다면 \
서비스 제공사에 문의하시기 바랍니다.

플레이오토의 경우 바로 사용자키 신청해 주시면 됩니다. \[ [인증키 발급 신청하기](https://devcenter.nhn-commerce.com/enamoo/openapi/userKey) ]

***

연동개발에 이용되는 인증키는 총 2개로 제휴사키와 사용자키가 있습니다.

{% tabs %}
{% tab title="제휴사 키" %}
제휴사 키는 실제 개발을 진행하는 곳에 발급되는 인증키를 말합니다.

* 자체개발의 경우 최초 1회에 한하여 [오픈API > 개발자 등록](https://devcenter.nhn-commerce.com/enamoo/openapi/keyLicense) 메뉴에서 신청
* 연동개발사를 이용하는 경우 해당 개발사에 고도 서비스 이용 가능 문의\
  (플레이오토, 샵링커, 이지어드민, 셀메이트 등은 현재 개발사 등록이 되어있습니다.)

자체개발 또는 연동 개발사가 개발자 등록을 완료하면 담당자 확인 후 승인 처리되며,\
등록 시점에 사용한 회원 계정으로 마이페이지에서 사용자키 신청 URL을 확인할 수 있습니다.
{% endtab %}

{% tab title="사용자 키" %}
사용자 키는 제휴사 키와 쇼핑몰에 매칭되는 고유 인증키를 말합니다.

* 각 제휴사에 맞춰 생성된 사용자키 신청 URL에서 연동할 쇼핑몰 선택\
  (해당 쇼핑몰을 보유한 고도 회원 아이디와 쇼핑몰 도메인을 알고계셔야 합니다.)
* 신청 후 해당 쇼핑몰을 보유한 고도 회원 아이디 이메일 주소로 최종 확인 메일 발송
* 유효기간 내 메일 확인 후 사용자 인증 완료 시 최종 신청 완료

사용자 키 최종 신청(사용자 인증)까지 완료하면 담당자 확인 후 발급 처리되며,\
개발자 등록 시점에 작성한 이메일로 키 값을 전달 드립니다.\
키 값은 개발사에만 전달되며, 쇼핑몰 보유 회원에게는 발급 완료 내역이 SMS 전송됩니다.
{% endtab %}
{% endtabs %}

***

모든 인증키 신청은 개발자센터를 통해서만 가능하며,\
이외 궁금하신 사항은 [1:1문의](https://support.nhn-commerce.com/inquiry/contact)를 이용해주시기 바랍니다.

감사합니다.


# 공급사 이용 방법 안내

별도 추가 개발 없이 기존 오픈 API를 통해 바로 서비스 이용을 가능하게 해주는\
공급사 전용 인증키를 발급 방법을 안내 드립니다.

***

1. 개발사 등록이 되어있는 지 확인해 주세요. \
   개발사 등록이 되어있어야 이후 진행이 가능합니다.

   &#x20;  \[[오픈API 인증키 발급 방법 안내 참고](https://nhn-commerce.gitbook.io/undefined-13/undefined-1/api)]
2. 개발사 등록이 되어있다면 아래의 순서에 맞춰 사용자키를 신청합니다.

   ① 개발자센터 > 마이페이지 > 사용자키 신청 메뉴를 통해 사용자키 신청페이지 접속

   ② 사용자 분류 '공급사' 선택

   ③ 입점한 쇼핑몰의 대표도메인 또는 임시도메인과 공급사명 입력 후 '검색'

   ④ 공급사 선택 후 쇼핑몰 관리자에 등록된 대표운영자 아이디 입력

   ⑤ 모든 정보 정상 입력 후 '등록하기' 실행
3. 본사와 공급사 대표이메일로 발송된 사용자 인증 메일을 확인해주세요.

   본사의 경우 고도 회원계정에 등록된 이메일 주소로,

   공급사의 경우 쇼핑몰 관리자의 공급사 대표운영자 정보에 등록된 이메일 주소로

   발송된 이메일을 통해 신청 후 1주일 이내에 모든 인증이 완료되야 합니다.
4. 담당자 확인 후 사용자키가 발급되며 사용자 인증 메일이 발송된 \
   동일한 이메일로 키값이 전달됩니다.

{% hint style="warning" %}
**유의사항**

* 오픈API를 통해 조회/등록/수정/삭제되는 모든 작업은 해당 공급사의 정보로만 한정됩니다.
* 기존 오픈API를 동일하게 사용하나 공급사의 경우 쇼핑몰 관리자 이용과 동일하게 일부 기능이 제한됩니다.
* 본사에서 공급사 등록 시 부여된 상품 승인 권한 및 기능 권한에 따라 일부 기능이 제한될 수 있습니다.
  {% endhint %}

***

모든 인증키 신청은 개발자센터를 통해서만 가능하며,\
이외 궁금하신 사항은 [1:1문의](https://support.nhn-commerce.com/inquiry/contact)를 이용해주시기 바랍니다.

감사합니다.


# 커스터마이징 하기

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

{% content-ref url="/pages/G9MngvVW7SafrbrZ99Jf" %}
[소스 코드 커스터마이징](/guide/tuning/source-code)
{% endcontent-ref %}

{% content-ref url="/pages/uSQZRmIrjEEoydRIV6Tf" %}
[데이터베이스 커스터마이징](/guide/tuning/database)
{% endcontent-ref %}

{% content-ref url="/pages/5ytO0pC49FUgVVhWmx9l" %}
[디버깅 방법](/guide/tuning/debugging)
{% endcontent-ref %}

{% content-ref url="/pages/lOjPwzMwXlUPH9cWN9X7" %}
[패치 확인 및 대응 방법](/guide/tuning/patch)
{% endcontent-ref %}


# 소스 코드 커스터마이징

Front-end 및 Back-end를 포함한 고도몰 소스 커스터마이징 방법에 대한 내용입니다.

## 📌 개발소스관리 <a href="#undefined" id="undefined"></a>

* `관리자 > 상단 네비게이션 > 우측 개발소스관리` 메뉴를 통해 개발소스관리 페이지에 진입할 수 있습니다.
* 개발소스관리 내 `소스 다운로드 기능`을 통해 `원본|작업|운영` 소스 파일을 직접 다운받으실 수 있습니다.

## 📌 소스 코드 커스터마이징 진행 방법

{% content-ref url="/pages/yDtgQIv3m8wwg3WwTDBS" %}
[커스터마이징 진행 방법](/guide/base-information/structure/how-to-tuning)
{% endcontent-ref %}

## 📌 소스 코드 커스터마이징 가능 범위

{% content-ref url="/pages/kxNFbPA5GqoYyhQhOQdL" %}
[커스터마이징 가능 범위](/guide/base-information/structure/tunable-range)
{% endcontent-ref %}


# 기본 커스터마이징 방법

커스터마이징 시 공통적으로 적용되는 사항에 대한 내용입니다.

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

## 📌 기능 확장

**고도몰에서 제공하는 기본적인 기능을 기반으로 기능 확장이 필요한 경우** \
커스터마이징 전 `개발소스관리 > 원본소스보기` 에서 고도몰 원본소스를 참고하시기 바랍니다.&#x20;

{% hint style="warning" %} <mark style="color:orange;">**아래 사항을 반드시 지켜주셔야 자동패치를 지원받으실 수 있습니다.**</mark>
{% endhint %}

* `Component/Cart/Cart.php`를 예로 들어 설명드리겠습니다.

1. 자동패치를 지원받기 위해서는 **개발소스관리 > 원본소스 보기**에서 커스터마이징 하고자 하는 소스를 다운로드 받거나 복사하기 버튼을 이용해 `data/module/Component/Cart` 디렉토리로 `Cart.php`를 복사합니다.
2. 복사한 파일의 내용은 원본과 다르며 원본 소스의 class를 **상속**받아서 사용할 수 있도록 아래와 같이 Wrapping 처리하여 제공됩니다.

   ```php
   <?php
   namespace Component\Cart;

   class Cart extends \Bundle\Component\Cart\Cart
   {
   }
   ```
3. 원본 소스의 메소드를 확장 개발하실 때, 반드시 원본 소스의 부모 메서드를 상속 받아야 자동패치가 지원됩니다.

   단, 원본 소스에 없는 사용자가 정의한 Method를 추가할 때는 해당되지 않습니다.

   ```php
   public function __construct()
   {
      parent::__construct();
   }

   public function helloWorld()
   {
      parent::helloWorld();

      /**
       * 원본 소스의 부모 메소드에서 return 값이 있을 경우
       * 자식 메소드에서도 동일하게 return 처리를 하는 것을 권장합니다.
       */ 
      return parent::helloWorld();
   }
   ```
4. 개발모드(`data/module`)에서 개발이 완료되었다면, **`개발소스관리 > 개발작업소스 보기`**&#xC5D0;서 운영소스로 적용하기 버튼을 눌러 운영 소스에 반영합니다.

{% hint style="danger" %} <mark style="color:red;">`Wrapping`</mark> <mark style="color:red;"></mark><mark style="color:red;">처리를 하지 않고 원본 그대로 사용할 경우 자동 패치가 적용되지 않습니다.</mark>
{% endhint %}

## 📌 클래스 호출

커스텀 개발 시 다른 클래스를 사용하는 경우에는\
`namespace와 class 사이에 use를 이용하여 사용하려는 class를 추가`해야 합니다.

{% code fullWidth="false" %}

```php
<?php
namespace Component\Cart;

/**
 * use 를 이용하여 추가하지 않으면
 * Component\Cart\DBTableField 라는 class 를 찾게 되며
 * 해당 class 는 존재하지 않기때문에 오류가 발생합니다.
 *
 * 실제 아래 함수의 중략된 부분에서는
 * Component\Member\Util\MemberUtil 과 Component\Mall\Mall 도 함께 사용하기 때문에
 * 모두 use 를 이용하여 추가하여야 합니다.
 */
use Component\Database\DBTableField;

class Cart extends \Bundle\Component\Cart\Cart
{
    /**
     * 아래는 Cart::saveInfoCart 함수의 일부를 커스터마이징한 예제 입니다.
     * 커스터마이징 시 해당 함수에서 DBTableField 를 사용하기 때문에 use 로 추가해야 합니다.
     */
    public function saveInfoCart($arrData)
    {
        // ... 중략

        // 장바구니 테이블 필드
        $arrExclude = [
            'memNo',
            'directCart',
        ];
        /**
         * 방법 1: use 를 통한 class 추가
         * 
         * use 를 추가하면 해당 클래스 내부에서는 DBTableField class 를 찾을 때
         * use 에 선언된 namespace 기반으로 찾습니다
         */
        $fieldData = DBTableField::setTableField('tableCart', null, $arrExclude);

        /**
         * 방법 2: namespace 를 붙여서 사용
         *
         * 1번 방법을 추천합니다. 
         * 2번을 사용하게 되면 사용할 때마다 namespace 를 작성해야합니다
         */
        $fieldData = \Component\Database\DBTableField::setTableField('tableCart', null, $arrExclude);

        // ... 중략
    }
}
```

{% endcode %}


# 컨트롤러 커스터마이징 방법

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

## 📌 Controller 제공 절대상수 <a href="#controller" id="controller"></a>

<table><thead><tr><th width="276">상수 이름</th><th>상수 설명</th></tr></thead><tbody><tr><td>PATH_DATA</td><td>데이터 폴더의 경로 <code>/data/</code></td></tr><tr><td>PATH_ADMIN_SKIN</td><td>관리자 스킨의 경로 <code>/admin/</code></td></tr><tr><td>PATH_ADMIN_GD_SHARE</td><td>관리자 공통 리소스 경로 <code>/admin/gd_share/</code></td></tr><tr><td>PATH_SKIN</td><td>프론트에 적용된 라이브 스킨의 경로 <code>/data/skin/front/[스킨명]/</code></td></tr><tr><td>PATH_SKIN_WORK</td><td>프론트에 적용된 작업 스킨의 경로 <code>/data/skin/front/[스킨명]/</code></td></tr><tr><td>PATH_MOBILE_SKIN</td><td>모바일에 적용된 라이브 스킨의 경로 <code>/data/skin/front/[스킨명]/</code></td></tr><tr><td>PATH_MOBILE_SKIN_WORK</td><td>모바일에 적용된 작업 스킨의 경로 <code>/data/skin/front/[스킨명]/</code></td></tr><tr><td>USERPATH_SKIN</td><td><code>/data/skin/front/[스킨명]/</code></td></tr><tr><td>USERPATH_SKIN_ADMIN</td><td><code>/admin/</code></td></tr><tr><td>USERPATH_SKIN_MOBILE</td><td><code>/data/skin/mobile/[스킨명]/</code></td></tr><tr><td>URI_HOME</td><td>현재 도메인 링크 <code>http://example.godomall.com/</code></td></tr><tr><td>URI_SHARE</td><td>현재 도메인의 share 링크 <code>http://example.godomall.com/share/</code></td></tr><tr><td>URI_ADMIN</td><td>관리자 도메인 <code>http://gdadmin.example.godomall.com/</code></td></tr><tr><td>URI_PROVIDER</td><td>공급사 관리자 도메인 <code>http://gdadmin.example.godomall.com/provider/</code></td></tr><tr><td>URI_MOBILE</td><td>모바일 도메인 <code>http://m.example.godomall.com/</code></td></tr><tr><td>URI_API</td><td>API 도메인 <code>http://api.example.godomall.com/</code></td></tr></tbody></table>

## 📌 Controller 제공 메소드 <a href="#controller" id="controller"></a>

### **download**

```php
download($path, $newFile)
```

* `$path`의 파일을 `$newFile`이라는 이름으로 다운로드를 실시합니다.

### **json**

```php
json($data)
```

* `$data`가 비어있는 경우 `Controller` 내 `data` 를 `json`으로 변경하고 `$data`가 있는 경우 `json`을 출력하고 `exit` 처리됩니다.

### **streamedDownload**

```php
streamedDownload($path)
```

* `$path`로 `index()`에 출력하는 모든 버퍼를 파일로 저장합니다.

### **redirect**

```php
redirect($uri, $title = null, $target = 'self')
```

* 페이지를 특정 URI로 이동시킵니다. 일반적으로 동일한 프레임에서 작동하며 iframe이 타겟인 경우는 사용하시면 안됩니다.

### **alert**

```php
alert($message, $history = null, $url = null, $target = null, $addScript = null)
```

* Alert 창을 출력하며 출력 후 `exit` 처리됩니다.

### **js**

```php
js($script)
```

* `$script` 텍스트로 사용자 정의 스크립트를 작성하실 수 있습니다.

### **layer**

```php
layer($message = null, $addScript = null, $timeOut = 3000)
```

* 관리자 컨트롤러에서만 사용할 수 있습니다.
* 레이어를 출력할 수 있으며, 레이어 출력이후 레이어를 닫으면 페이지가 새로고침 됩니다.

### **layerNotReload**

```php
layerNotReload($message = null, $addScript = null, $timeOut = 2000)
```

* 관리자 컨트롤러에서만 사용할 수 있습니다.
* 레이어를 출력할 수 있으며, 레이어 출력이후 레이어를 닫아도 페이지가 새로고침 되지 않습니다.

### **addMeta**

```php
addMeta(array $metaTags)
```

* 스킨의 헤더에 메타태그를 추가할 수 있습니다.
* `front`와 `mobile`에서만 사용가능하며 `admin`에서는 사용할 수 없습니다.

### **addCss**

```php
addCss(array $styles, $isShare = false)
```

* 스타일시트의 경로를 배열로 받아서 스킨 상단에 출력합니다.
* `$isShare`를 `true`로 하는 경우 `/data/assets`에 있는 공유 리소스를 사용하실 수 있습니다.

### **addScript**

```php
addScript(array $scripts, $isShare = false, $isFooter = false)
```

* 스크립트의 경로를 Array로 받아서 스킨 상/하단에 출력합니다. (ex. `['common.js', 'common2.js']`)
  * 경로는 `/data/[skin path]/js`에 있는 공유 리소스를 사용하실 수 있습니다.
* `$isShare`를 `true`로 하는 경우 `/data/assets`에 있는 공유 리소스를 사용하실 수 있습니다.
* `$isFooter`를
  * true로 하는 경우 스킨내 `{footerScript}` 치환코드로 반환합니다.
  * false인 경우 스킨내 `{headerScript}` 치환코드로 반환합니다.

### **callMenu**

```php
callMenu($topMenu, $midMenu, $thisMenu)
```

* 관리자 메뉴 데이터를 생성합니다.
* 관리자 메뉴를 새로 추가할 경우, 추가할 메뉴 페이지에 해당되는 컨트롤러 내에서 해당 함수를 호출합니다.
* `es_adminMenu` 테이블에 추가할 메뉴 데이터를 `insert`한 후에 1차 메뉴(`$topMenu`), 2차 메뉴(`$midMenu`), 3차 메뉴(`$thisMenu`) 파라미터 대로 메소드를 호출합니다.

## 📌 사용자 정의 Controller 기본 메소드 <a href="#controller" id="controller"></a>

* 고도몰에서는 기본적으로 3개의 사용자 정의 Method를 제공합니다.
* Method 종류
  1. `pre()`
     * 시스템 전 처리기 `interceptor`의 실행 직전에 실행됩니다.
  2. `index()`
     * 사용자가 처리할 내용을 작성할 수 있습니다.
  3. `post()`
     * 시스템 후 처리기 `interceptor`의 실행 직후에 실행됩니다.
* 실제 코드 확인하시고 아래와 같이 사용하시면 됩니다.

```php
<?php
namespace Controller\Front\Test

class MyController extends \Controller\Front\Controller
{
    public function pre()
    {
        // interceptor 실행 이전 실행할 로직 구현
    }
    
    public function index()
    {
        // 사용자 정의 로직 구현
    }
    
    public function post()
    {
        // interceptor 실행 이후 실행할 로직 구현
    }
}
```

## 📌 전역으로 사용할 수 있는 사용자 정의 Controller <a href="#controller" id="controller"></a>

* 모든 페이지에 공통으로 적용할 수 있는 사용자 정의 컨트롤러를 생성할 수 있습니다.
* 프론트는 `module\Controller\Front` 경로에 `CommonController` 클래스를 생성해 주신 후 아래와 같이 사용하시면 됩니다.

```php
<?php
namespace Controller\Front;

/**
 * 사용자들이 모든 컨트롤러에 공통으로 사용할 수 있는 컨트롤러 Class
 * 컨트롤러에서 지원하는 메소드들을 사용할 수 있습니다.
 */
class CommonController
{
    public function index($controller)
    {
        /**
         * IP를 추가합니다.
         * 스킨에서 {=remoteAddr} 치환코드로 사용 가능합니다.
         */ 
        $controller->setData('remoteAddr',\Request::server()->get('REMOTE_ADDR'));
        
        /**
         * 새 변수를 추가합니다.
         * 스킨에서 {=userName} 치환코드로 사용 가능합니다.
         */
        $controller->setData('userName', '사용자 이름');
    }
}
```

* 모바일은 `module\Controller\Mobile` 경로에 `CommonController` 클래스를 생성해 주신 후 아래와 같이 사용하시면 됩니다.

```php
<?php
namespace Controller\Mobile;

/**
 * 사용자들이 모든 컨트롤러에 공통으로 사용할 수 있는 컨트롤러 Class
 * 컨트롤러에서 지원하는 메소드들을 사용할 수 있습니다.
 */
class CommonController
{
    public function index($controller)
    {
        /**
         * IP를 추가합니다.
         * 스킨에서 {=remoteAddr} 치환코드로 사용 가능합니다.
         */ 
        $controller->setData('remoteAddr',\Request::server()->get('REMOTE_ADDR'));
        
        /**
         * 새 변수를 추가합니다.
         * 스킨에서 {=userName} 치환코드로 사용 가능합니다.
         */
        $controller->setData('userName', '사용자 이름');
    }
}
```

## 📌 Api 사용자 정의 Controller <a href="#api-controller" id="api-controller"></a>

* Api 통신이 가능한 사용자 정의 컨트롤러를 생성할 수 있습니다.
* `module/Controller/Api` 경로에서 사용하시면 됩니다. 만약 디렉토리가 없다면 생성하고 `chmod 707` 변경 필수
* `Front/Mobile` 커스터마이징과 동일한 방법으로 `Controller` 생성
* 생성 예시
  * 경로: `module/Controller/Api/Load/GetApiController.php`
  * 링크: `api.{상점도메인}/load/get_api`

```php
<?php
namespace Controller\Api\Load;

class GetApiController extends \Controller\Api\Controller
{
    public function index()
    {
        // some code ...
    }
}
```

**🚨 주의**: 멀티서버(이벤트 서버) 환경에서 외부 cron 호출, 자동결제 등 서버 간 상태 공유가 필요한 기능은 반드시 `api.{도메인}` 을 통해 호출해야 합니다. 자세한 내용은 [분산 환경 개발 가이드](https://devcenter-help.nhn-commerce.com/other-guide/multi-server) 를 참고하세요.


# 템플릿 커스터마이징 방법

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

## 📌 고도몰의 템플릿 엔진 <a href="#undefined" id="undefined"></a>

* 고도몰은 2개의 템플릿 엔진으로 작동되도록 구현되어졌습니다.
* 템플릿 엔진의 종류

### `includeEngine`

* 관리자 페이지 전용
* 템플릿이 php 파일로 구성

### `template_`

* 프론트/모바일 페이지 전용
* `Template_` 엔진 사용
* 템플릿이 html 파일로 구성
* `safe mode`로 구성되어 일반적인 PHP 함수 사용 불가 (하단의 사용 가능 PHP함수 참고)

## 📌 `Template_` 플러그인 <a href="#template" id="template"></a>

| 플러그인                                                                             | 설명                                       |
| -------------------------------------------------------------------------------- | ---------------------------------------- |
| dataBank($bankCode)                                                              | 입금은행 배열, `all`로 하는 경우 전부다 반환             |
| dataBanner($bannerGroupCode, $eachFl = false)                                    | 배너리스트 배열 반환                              |
| dataBookmark($bookmarkBanner = null, $bookmarkUrl = null, $bookmarkTitle = null) | 즐겨찾기 데이터 배열 반환                           |
| dataCartGoodsCnt()                                                               | 장바구니에 담겨있는 수량 반환                         |
| dataCategoryPosition($cateCd, $arrow = null, $cateType = 'category')             | 카테고리의 현위치 출력                             |
| dataEggBanner($mode = 'banner')                                                  | 구매안전(에스크로)서비스 배너 및 설명 출력                 |
| dataGoodsMemberGroupPrice($getData, $groupSno)                                   | 회원그룹가 반환                                 |
| dataGoodsRelation($relation, $relationDate)                                      | 관련상품 데이터 배열 반환                           |
| dataGoodsReviewCnt($goodsNo)                                                     | 상품후기 데이터 배열 반환                           |
| dataHitKeyword()                                                                 | 설정된 인기검색어 반환                             |
| dataSubCategory($parentcategory, $cateType = 'category', $imageFl = 'n')         | 서브카테고리 리스트 반환                            |
| dataTodayGoods($rowNo)                                                           | 최근 본 상품 데이터 배열 반환                        |
| dataTodayGoodsCnt()                                                              | 최근 본 상품에 담긴 상품 수량을 반환                    |
| dataWishGoodsCnt()                                                               | 찜리스트 수량 반환                               |
| getArticles($bdId, $listCount, $strCut = null)                                   | 게시글 리스트 반환                               |
| includeFile($path, ...$args)                                                     | 템플릿안에서 파일을 include 처리                    |
| includeWidget($path, ...$args)                                                   | 템플릿안에서 Widget을 include 처리                |
| plusShop($path, ...$args)                                                        | 플러스샵 전용 템플릿                              |
| pollViewBanner($code = null)                                                     | 설문조사 배너 출력                               |
| setBrowserCache($filePath)                                                       | 파일의 변경 여부에 따라 브라우저 캐시가 작동되도록 리소스의 주소를 반환 |

## 📌 스킨에서 사용가능한 PHP 함수 <a href="#php" id="php"></a>

### PHP 기본 함수

#### string

```
addcslashes
addslashes
explode
implode
join
nl2br
number_format
sprintf
str_repeat
str_replace
strip_tags
stripcslashes
stripslashes
strtolower
strtoupper
strtr
strlen
strpos
substr
```

#### date, time

```
date
mktime
strtotime
time
```

#### regexp

```
preg_match
preg_replace
```

#### array

```
array_key_exists
array_keys
array_merge
array_pop
array_push
array_reverse
array_search
array_shift
array_slice
array_splice
array_sum
array_unique
array_unshift
array_values
array
arsort
asort
count
current
each
end
extract
in_array
key
key_exists
krsort
ksort
list
natcasesort
natsort
next
prev
range
reset
rsort
shuffle
sort
```

#### Math

```
ceil
floor
max
min
mt_rand
round
```

#### JSON

```
json_decode
json_encode
```

#### URL

```
rawurldecode
rawurlencode
urldecode
urlencode
```

#### Variable handling

```
empty
floatval
intval
is_array
is_int
is_null
is_numeric
is_object
is_string
isset
unset
```

### Godomall 내부 함수

```
gd_byte2str
gd_copy_protect
gd_currency_default
gd_currency_display
gd_currency_string
gd_currency_symbol
gd_date_format
gd_debug
gd_display_deposit
gd_display_group_label
gd_display_mileage_name
gd_display_mileage_unit
gd_get
gd_get_footer_logo_tag
gd_get_group_image_http_path
gd_get_login_name
gd_home_uri
gd_html_add_goods_image
gd_html_cut
gd_html_goods_image
gd_html_icon
gd_html_image
gd_htmlspecialchars
gd_htmlspecialchars_addslashes
gd_htmlspecialchars_decode
gd_htmlspecialchars_slashes
gd_htmlspecialchars_stripslashes
gd_is_html
gd_is_login
gd_is_plus_shop
gd_isset
gd_mb2byte
gd_mileage_display
gd_money_format
gd_number_figure
gd_remove_comma
gd_remove_tag
gd_select_box
gd_select_box_by_mail_domain
gd_session
gd_str_dfind
gd_str2js
gd_strtocamel
gd_trim
gd_url
gd_use_coupon
gd_use_coupon_offline
gd_use_deposit
gd_use_mileage
gd_youtube_player
```


# 커스터마이징 시 유의사항

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

## 📌 커스터마이징 위치

* 스킨을 제외한 소스 코드 커스터마이징은 module 하위에서 이루어져야 합니다.
* 지정된 구간 이외에서의 개발 작업은 운영 정책상 삭제될 수 있습니다.

## 📌 기능 확장 시

* 고도몰 원본 소스를 기반으로 기능을 확장할 때, 반드시 원본 소스의 Class와 Method를 상속받아야 합니다.
* 고도몰 Classloader의 영향으로 module 폴더 내의 Class 가 원본소스보다 우선적으로 인식되므로, \
  자동 패치 소스도 적용되려면 꼭 상속을 받도록 개발되어야합니다.
* 원본 소스 Method를 오버라이드할 때는 원본 소스의 Method에 명시된 파라미터 타입 및 값을 참고하여, \
  적절한 파라미터 타입을 지정해주어야 합니다.
* 원본 소스의 Method를 상속할 때 이중 상속으로 인해 Method들이 중복 호출될 수 있습니다.

  이는 쇼핑몰의 성능 저하 및 기능 오동작으로 이어질 수 있으므로 상속을 할 때에는 꼼꼼하게 검토해주시길 바랍니다.
* 가능하다면 원본 소스의 컴포넌트 함수를 그대로 사용하는 것보다는 필요한 기능에 맞게 새로운 함수를 생성하는 것을 권장합니다. 원본 소스의 함수를 확장해야 하는 경우에는 부모 Method를 상속받아 필요한 로직만 추가하여 확장하는 방식으로 개발해야 합니다.

## 📌 설계 <a href="#prefix" id="prefix"></a>

* 커스터마이징 시에는 `컨트롤러(Controller)`와 `컴포넌트(Component)`의 역할을 분리하여 유지보수가 용이한 구조를 만들어주시길 바랍니다.
* `컨트롤러(Controller)`는 클라이언트로부터 요청을 받아 필요한 작업을 `컴포넌트(Component)`로 요청하고, 그 결과를 바탕으로 `뷰(View)`를 호출하는 역할을 담당합니다.
* `컴포넌트(Component)`는 비즈니스 로직을 수행하며, `컨트롤러(Controller)`로부터 받은 요청을 기반으로 데이터를 조회/수정한 다음 처리된 데이터를 `컨트롤러(Controller)`로 반환하는 역할을 담당합니다.

## 📌 Prefix <a href="#prefix" id="prefix"></a>

새로운 Class를 생성하거나 View 페이지로 데이터를 전달하는 경우 고유의 Prefix 를 붙이는 것을 권장합니다. \
Class 의 경우에는 고유의 namespace 를 사용하는 것도 방법입니다.

## 📌 Namespace <a href="#namespace" id="namespace"></a>

사용자가 정의하는 namespace 의 시작은 `Framework, Bundle, Core` 를 사용할 수 없습니다.

## 📌 ClassPath <a href="#classpath" id="classpath"></a>

솔루션에서 Class 를 로드하는 경로는 module 폴더 아래 입니다. \
Class 의 이름은 파일명과 동일해야하고, namespace는 폴더 경로와 동일해야 합니다.

{% hint style="info" %}
`namespace Component/Cart; class Cart{}` 의 경우 파일의 경로는 `module/Component/Cart/Cart.php` 입니다.
{% endhint %}

## 📌 ClassLoader <a href="#classloader" id="classloader"></a>

솔루션에서 정의한 ClassLoader는 솔루션과 사용자가 동일한 namespace 와 Class 를 생성 할 경우 사용자가 정의한 Class 를 로드합니다. 사용자가 새로운 Class 를 생성할 경우 **고유의** namespace 또는 Prefix 를 붙이는 것이 좋습니다.

{% hint style="warning" %} <mark style="color:orange;">아래와 같이 클래스가 정의된 경우</mark> <mark style="color:orange;"></mark><mark style="color:orange;">`Call to undefined method Component\Print\Print::printGodomall()`</mark> <mark style="color:orange;"></mark><mark style="color:orange;">오류가 발생합니다.</mark>
{% endhint %}

```php
// 솔루션에서 정의한 MsgPrintController
namespace Controller\MsgPrint;
class MsgPrintController {
    public function index() {
    	$msgPrint = new \Component\MsgPrint\MsgPrint();
        $msgPrint->printGodomall();
    };
}

// 솔루션에서 정의한 MsgPrint 클래스와 printGodomall 함수
namespace Component\MsgPrint;
class MsgPrint {
    public function printGodomall() {
    	echo '고도몰 솔루션';
    }
}

// 사용자가 정의한 Print 클래스와 printUser 함수
namespace Component\MsgPrint;
class MsgPrint {
    public function printUser() {
    	echo '고도몰 사용자';
    }
}
```

## 📌 Superglobals <a href="#superglobals" id="superglobals"></a>

PHP 에서 제공되는 Superglobals 변수는 모두 `unset` 됩니다. \
각 변수의 역할을 대체하는 클래스 및 함수는 아래와 같습니다.

```php
$GLOBALS = Framework\Registry\Globals;
$_SERVER = \Request::server();
$_GET = \Request::get();
$_POST = \Request::post();
$_FILES = \Request::files();
$_REQUEST = \Request::request();
$_SESSION = \Session;
$_COOKIE = \Cookie;
```

## 📌 Controller 의 setData() 함수 <a href="#controller-setdata" id="controller-setdata"></a>

Controller 에서 `$this->setData(key, value)`를 이용하여 View 데이터를 넘길 때에는 key 가 중복이 될 경우 이전에 담긴 데이터를 덮어쓰게 되므로 prefix **를 붙여서 사용하는 것이 안전**합니다.

## 📌 URI 와 Controller <a href="#uri-controller" id="uri-controller"></a>

솔루션에서는 URI를 이용하여 요청을 처리할 Controller 를 찾습니다. URI 와 Controller 간의 규칙은 아래와 같습니다.

### URI : SnakeCase

> ex) gdadmin.domain.com/order/order\_list.php

### Controller : CamelCase

> ex) namespace Controller\Admin\Order\OrderListController;

## 📌 Controller 와 ViewPage <a href="#controller-viewpage" id="controller-viewpage"></a>

솔루션에서는 사용자의 요청을 Controller 가 실행한 뒤 ViewPage 를 찾습니다. \
Controller 와 Skinfile 간의 규칙은 아래와 같습니다.

### Controller : CamelCase

> ex) namespace Controller\Admin\Order; OrderListController;\
> ex) namespace Controller\Front\Order; OrderListController;

### Skinfile : SnakeCase

> ex) /admin/order/order\_list.php\
> ex) /data/skin/front/\[skin\_name]/order/order\_list.html

## 📌 URI\_HOME, URI\_SHARE <a href="#urihome-urishare" id="urihome-urishare"></a>

`URI_HOME`, `URI_SHARE` 는 View 페이지에서 링크를 지정할 시에 사용되는 상수입니다.&#x20;

링크의 용도 외에는 사용을 하지 않는 것이 좋습니다.

## 📌 Request::getDomainUrl() <a href="#requestgetdomainurl" id="requestgetdomainurl"></a>

View 페이지 외에서 도메인을 알고 싶을 때에는 `Request::getDomainUrl()` 을 이용합니다.

## 📌 App::load() <a href="#appload" id="appload"></a>

싱글톤을 이용하여 최초 생성된 객체를 저장한 뒤 요청이 올때마다 저장된 객체를 반환하는 함수입니다.

## 📌 PHP Function <a href="#php-function" id="php-function"></a>

* PHP 내장 함수 사용 시, 올바른 파라미터 타입을 사용해야 합니다. \
  부적절한 파라미터 타입을 전달하면 [타입 에러](https://www.php.net/manual/en/class.typeerror.php)가 발생할 수 있습니다.
* 자주 사용되는 PHP 내장 함수 목록과 연결된 공식 문서를 통해 파라미터 타입을 확인하고 개발해 주시길 바랍니다.

#### 자주 사용되는 PHP 함수 목록 <a href="#php" id="php"></a>

* [count](https://www.php.net/manual/en/function.count.php)
* [array\_slice](https://www.php.net/manual/en/function.array-slice.php)
* [array\_unique](https://www.php.net/manual/en/function.array-unique.php)
* [array\_values](https://www.php.net/manual/en/function.array-values.php)
* [implode](https://www.php.net/manual/en/function.implode.php)
* [in\_array](https://www.php.net/manual/en/function.in-array.php)
* [array\_intersect](https://www.php.net/manual/en/function.array-intersect.php)
* [array\_reverse](https://www.php.net/manual/en/function.array-reverse.php)
* [array\_key\_exists](https://www.php.net/manual/en/function.array-key-exists.php)
* [array\_filter](https://www.php.net/manual/en/function.array-filter.php)
* [array\_keys](https://www.php.net/manual/en/function.array-keys.php)
* [array\_flip](https://www.php.net/manual/en/function.array-flip.php)
* [array\_intersect\_key](https://www.php.net/manual/en/function.array-intersect-key.php)


# 데이터베이스 커스터마이징


# 커스터마이징 방법

{% 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>

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

**ENUM Type**

* 솔루션에서 기본 제공하는 ENUM 컬럼에 종류(값) 추가를 지양합니다.
* 추가한 ENUM 값은 솔루션 및 API 기능에서 정의되지 않은 값으로 처리되어 오작동 및 오류가 발생할 수 있습니다.
* 상태값·구분값 등 종류 확장이 필요한 경우, 기존 ENUM을 변경하지 말고 별도 컬럼을 추가하여 사용합니다.

## 📌 컬럼 생성 <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;
    }
}
```


# 커스터마이징 시 유의사항

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

## 📌 테이블 백업 <a href="#ec-9e-91-ec-97-85-ec-a0-84-ed-85-8c-ec-9d-b4-eb-b8-94-eb-b0-b1-ec-97-85-ed-95-84-ec-88-98" id="ec-9e-91-ec-97-85-ec-a0-84-ed-85-8c-ec-9d-b4-eb-b8-94-eb-b0-b1-ec-97-85-ed-95-84-ec-88-98"></a>

* 작업 전 테이블을 필수로 백업해야 합니다.
* phpmyadmin 에서 `export` 기능을 이용해서 백업할 수 있습니다.
* 아래와 같은 형식의 백업은 가능하지만 `CTAS(CREATE TABLE AS SELECT)`가 실행되는 동안 Lock이 발생하여 상점 운영에 영향을 줄 수 있으며, 용량 이슈로 서버 부하가 발생할 수 있습니다. 가급적 export 기능을 사용하는 것을 권장합니다.

  <pre class="language-sql" data-overflow="wrap"><code class="lang-sql">CREATE TABLE backup_es_order LIKE es_order;
  INSERT INTO backup_es_order SELECT orderNo, mallSno, ... FROM es_order WHERE orderNo ...
  </code></pre>

***

## 📌 오브젝트 이름에 키워드 및 예약어 사용 금지 <a href="#ec-9e-91-ec-97-85-ec-a0-84-ed-85-8c-ec-9d-b4-eb-b8-94-eb-b0-b1-ec-97-85-ed-95-84-ec-88-98" id="ec-9e-91-ec-97-85-ec-a0-84-ed-85-8c-ec-9d-b4-eb-b8-94-eb-b0-b1-ec-97-85-ed-95-84-ec-88-98"></a>

* MySQL에 내재되어 있는 예약어 사용 금지
* \` (백틱)으로 이름을 감싸서 사용하는 경우 강제로 생성되므로 백틱 사용 금지

{% code overflow="wrap" %}

```sql
# 예약어를 백틱으로 감싸면 생성 성공
CREATE TABLE reserved_word (
    `rank` int not null,
    PRIMARY KEY (`rank`)
    );

# 예약어를 그냥 사용하면 에러메세지 발생
CREATE TABLE reserved_word (
    rank int not null,
    PRIMARY KEY (rank)
)

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'rank)
    )' at line 3
```

{% endcode %}

***

## 📌 오브젝트 이름에 특수문자 사용 금지 <a href="#ec-9e-91-ec-97-85-ec-a0-84-ed-85-8c-ec-9d-b4-eb-b8-94-eb-b0-b1-ec-97-85-ed-95-84-ec-88-98" id="ec-9e-91-ec-97-85-ec-a0-84-ed-85-8c-ec-9d-b4-eb-b8-94-eb-b0-b1-ec-97-85-ed-95-84-ec-88-98"></a>

* 지원되는 문자
  * 0-9,a-z,A-Z$\_
    * &#x20;digits 0-9, basic Latin letters, dollar, underscore
* \`(백틱)으로 감싸면 강제로 생성되므로 사용 금지
* 특수문자 사용시 보안패치, 업그레이드등에서 제외될 수 있습니다.

***

## 📌 **오류 발생시**

* `접두사 사용안함`, `Table 이름, Column 명칭의 수정, 삭제`, `Column Type 변경` 등에 의한 오류발생시 해당 부분에 대한 모든 책임은 직접 데이터베이스를 컨트롤한 주체에 있으며, 본사(NHN커머스)에서는 절대 책임지지 않습니다.


# 고도몰 테이블 명세서

하단 URL에서 고도몰 테이블 명세서를 확인할 수 있습니다.

{% embed url="<http://doc.godomall5.godomall.com/godo/database/table_layout.php>" %}
고도몰 테이블 명세 안내
{% endembed %}


# PhpMyAdmin 이용

## 📌 직접 설치 제한 <a href="#undefined" id="undefined"></a>

* 보안상의 이유로 2021년 9월 1일부터 phpMyAdmin 직접 설치를 제한합니다.
* phpMyAdmin 설치하신 경우 반드시 삭제해 주시기 바랍니다.
* 2021년 9월 1일 이후 phpMyAdmin 서버 설치 발견 시 NHN커머스에서 사전 안내 없이 삭제처리됩니다.

{% hint style="danger" %} <mark style="color:red;">**phpmyadmin 으로 인한 보안 사고가 발생하는 경우 모든 책임은 고객에게 있습니다.**</mark>
{% endhint %}

## 📌 접속 조건 <a href="#undefined" id="undefined"></a>

* 고도몰 pro, 고도몰 business(pro+) 에서만 사용하실 수 있습니다.
  * 고도몰 standard, 고도몰 basic 은 제공되지 않습니다.

## 📌 접속 방법 <a href="#undefined" id="undefined"></a>

{% hint style="info" %}
\[NHN커머스> 마이페이지]를 통해 phpMyAdmin 접속 가능합니다. [\[접속 방법 자세히 보기 >\] ](https://www.nhn-commerce.com/customer/board-view.gd?type=notice\&idx=1995)
{% endhint %}

* 고도몰 pro 메뉴위치 : \[마이페이지> 쇼핑몰관리> 쇼핑몰목록> 기본관리 탭] DB 관리
* 고도몰 business(pro+) 메뉴위치 : \[마이페이지> 쇼핑몰관리> 쇼핑몰목록> 호스팅관리 탭] DB 관리

1. `[접속 허용 IP관리]` 클릭 후 phpMyAdmin에 접속할 IP 정보를 접속 허용 IP로 등록합니다.
2. `[phpMyAdmin 접속]` 클릭 후 NHN커머스 로그인 비밀번호를 입력하면 phpMyAdmin 사이트가 출력됩니다.
3. phpmyadmin 사이트에서 접속하실 `사용자명/암호` 입력 후 \[실행]을 클릭합니다.&#x20;
   * 사용자명 : 접속하실 쇼핑몰의 DB 아이디
   * 암호 : 접속하실 쇼핑몰의 DB 비밀번호
4. phpmyadmin 사이트에서 DB 데이터 추가/수정/삭제 가능합니다.

{% hint style="danger" %} <mark style="color:red;">**phpMyadmin을 통해서 관리(생성/수정/삭제) 되는 DB 데이터에 대한 책임은 회원에게 있습니다.**</mark>&#x20;
{% endhint %}


# 디버깅 방법

* 쇼핑몰에서 에러가 발생하면 오류 페이지로 이동됩니다.
* 커스터마이징으로 인한 에러가 발생할 경우, 오류 페이지에서 Exception 정보를 확인할 수 있습니다.

![](http://localhost:63343/markdownPreview/210953258/fileSchemeResource/570e645425a6b35bd9f10f1256aa8b0a-exception_page.png?_ijt=35r3eto146dpm6c4qplrmhhb4)

## 📌 디버깅 방법 <a href="#undefined" id="undefined"></a>

* 고도몰 PRO 이상에서만 사용하실 수 있습니다.
* 디버그 권한이 있는 관리자의 로그인 세션이 유효한 상태에서 오류 페이지에 접근하면 디버깅 화면이 표시됩니다.
* [\[고도몰 매뉴얼\] 메뉴 권한 설정 > 개발소스관리 권한 설정](http://manual.godomall5.godomall.com/data/manual_view.php?category=policy__management___manage_permission#%EB%A9%94%EB%89%B4%EA%B6%8C%ED%95%9C%EC%84%A4%EC%A0%95)

## 📌 디버깅 정보 <a href="#undefined" id="undefined"></a>

### 런타임 에러 <a href="#undefined" id="undefined"></a>

에러명, 에러메시지, 에러 발생 시각, 에러 발생 위치를 확인할 수 있습니다.

![](http://localhost:63343/markdownPreview/210953258/fileSchemeResource/2020270a9bfe86b0369c94aee337de24-exception_page_parse_error.png?_ijt=35r3eto146dpm6c4qplrmhhb4)

### 데이터베이스 에러 <a href="#undefined" id="undefined"></a>

에러명(DatabaseException), 에러메시지, 에러 쿼리, 에러 발생 시각, 에러 발생 위치를 확인할 수 있습니다.

![](http://localhost:63343/markdownPreview/210953258/fileSchemeResource/ef63ba7847a282f50bacd30f1efceccd-exception_page_database_exception.png?_ijt=35r3eto146dpm6c4qplrmhhb4)


# 패치 확인 및 대응 방법

{% hint style="info" %}
고도몰 패치 일시 및 개선 내용은 [NHN COMMERCE 패치&업그레이드](https://www.nhn-commerce.com/customer/patch-list.gd)에서 확인하실 수 있습니다.
{% endhint %}

## 📌 소스 배포 <a href="#undefined" id="undefined"></a>

* 배포 관련 공지사항을 통해 개선되는 Class 및 Method에 대한 정보를 함께 확인할 수 있습니다.
* 이를 바탕으로 자동 패치가 적용될 수 있도록 커스텀 개발 가이드 준수 여부를 확인하시기 바랍니다.

## 📌 스킨 배포 <a href="#undefined" id="undefined"></a>

{% hint style="info" %}
스킨은 자동 패치 영역이 아니므로 스킨 패치를 직접 적용해야 합니다.\
다음 순서에 따라 스킨 패치를 진행하시기 바랍니다.
{% endhint %}

![](http://localhost:63343/markdownPreview/1040154624/fileSchemeResource/ff334e12f2fbc6cfe4f5fe7cb58ea94e-skin_patch_01.png?_ijt=ql85clli72obb98jo59i8rne43)

1. [NHN커머스 사이트](https://www.nhn-commerce.com/)에서 로그인 후 [내 쇼핑몰 관리](https://www.nhn-commerce.com/mygodo/myGodo_shopMain.php) 페이지로 이동합니다.

![](http://localhost:63343/markdownPreview/1040154624/fileSchemeResource/ef0999ac4118e6f5cd5e29a712ed76a6-skin_patch_02.png?_ijt=ql85clli72obb98jo59i8rne43)

2. [패치&업그레이드](https://www.nhn-commerce.com/mygodo/my_patch.php) 페이지로 이동합니다.

![](http://localhost:63343/markdownPreview/1040154624/fileSchemeResource/0496792ae488a813a411126734181b97-skin_patch_03.png?_ijt=ql85clli72obb98jo59i8rne43)

3. 패치&업그레이드가 필요한 쇼핑몰 도메인을 클릭합니다.

![](http://localhost:63343/markdownPreview/1040154624/fileSchemeResource/8219e273831af3793b227710f437c518-skin_patch_04.png?_ijt=ql85clli72obb98jo59i8rne43)

4. 패치를 적용할 게시글 제목을 클릭합니다.

![](http://localhost:63343/markdownPreview/1040154624/fileSchemeResource/a069c4333304e6af77690b2a52007d6d-skin_patch_05.png?_ijt=ql85clli72obb98jo59i8rne43)

5. 게시글 하단 '다운로드하기' 버튼을 클릭하여 패치 첨부파일을 다운로드 받습니다.

![](http://localhost:63343/markdownPreview/1040154624/fileSchemeResource/efa6a41fdd0dfc581e8349e6356aa29e-skin_patch_06.png?_ijt=ql85clli72obb98jo59i8rne43)

6. 압축 파일 내 패치 관련 파일들을 확인합니다.
   * `스킨수정_(스킨명)_(디바이스타입).html` : 패치 전후 소스 코드를 비교할 수 있습니다.&#x20;

     <figure><img src="http://localhost:63343/markdownPreview/1040154624/fileSchemeResource/84f6c2ecaf9609c608214ba0ecbe65e6-skin_patch_06_1.png?_ijt=ql85clli72obb98jo59i8rne43" alt=""><figcaption></figcaption></figure>
   * `패치 내용.html` : 패치 내역에 대한 기본 정보를 확인할 수 있습니다.&#x20;

     <figure><img src="http://localhost:63343/markdownPreview/1040154624/fileSchemeResource/46aac58a0a43b02627b26ab17d5f2c4d-skin_patch_06_2.png?_ijt=ql85clli72obb98jo59i8rne43" alt=""><figcaption></figcaption></figure>
   * `data` : 패치 후의 파일별 전체 소스코드를 확인할 수 있습니다.![071](http://localhost:63343/markdownPreview/1040154624/fileSchemeResource/f4f3e41356cd0db85ba46fa196cc1138-skin_patch_07_1.png?_ijt=ql85clli72obb98jo59i8rne43) ![072](http://localhost:63343/markdownPreview/1040154624/fileSchemeResource/78e4ae9101a3aa74e5638168bde42885-skin_patch_07_2.png?_ijt=ql85clli72obb98jo59i8rne43)
7. 패치 작업 및 테스트를 마친 후 '패치확인하기'를 통해 패치 완료 여부를 저장합니다.

![](http://localhost:63343/markdownPreview/1040154624/fileSchemeResource/6fc7515456bbd31ce861a1bc266ba9a1-skin_patch_08.png?_ijt=ql85clli72obb98jo59i8rne43)

8. 패치를 완료한 날짜 및 시간을 확인합니다.

## 📌 관리자 스킨 배포 <a href="#undefined" id="undefined"></a>

* 관리자 스킨은 자동 패치 영역이 아닙니다.
* 배포 관련 공지사항을 통해 개선 사항에 커스텀에 사용된 파일이 포함되었는지 확인한 다음, \
  관리자 스킨 원본소스를 바탕으로 해당 개선 사항을 재적용 하시길 바랍니다.


# 커스터마이징 따라하기

커스터마이징은 어떻게 진행 되는 걸까요? 커스터마이징 따라하기를 통해 직접 확인해보세요!

**커스터마이징 따라하기** 에서는 특정 사례를 예시로 커스터마이징을 진행하게 되는 전반적인 상황을 정리해두었습니다.\
사례 내 제공 되는 커스터마이징 방법으로 실제 이용 중이신 고도몰에 적용해봄으로써 고도몰의 커스터마이징을 직접 경험하실 수 있습니다.

{% hint style="danger" %}
커스터마이징 사례에서 제시하는 커스터마이징 방법을 고도몰에 직접 적용해볼 수 있습니다.

다만, <mark style="color:red;">**관련 범위에**</mark><mark style="color:red;">**&#x20;**</mark><mark style="color:red;">**커스터마이징이 진행 되지 않은 상태에서 진행하시는 것을 권장 드립니다.**</mark>

해당 커스터마이징 사례 적용 시, 관련 범위에 이미 커스터마이징한 내역으로 인해 발생하는 오류에 대해서는 \
고도몰이 책임을 지지 않습니다. 주의하여 주시기 바랍니다.&#x20;
{% endhint %}

{% content-ref url="/pages/MMV7WyRlgwfJ4PMNGG1z" %}
[관리자 GNB 색상 변경하기](/guide/tuning-example/modify-admin-gnb)
{% endcontent-ref %}

{% content-ref url="/pages/cUGXrLeKOcQDpBFTYh88" %}
[즐겨찾기 메뉴 바로가기 만들기](/guide/tuning-example/add-favorite-menu)
{% endcontent-ref %}

{% content-ref url="/pages/Lrtn1dKANBHZo00Q0Nmd" %}
[관리자 메뉴 추가하기](/guide/tuning-example/add-menu)
{% endcontent-ref %}

{% content-ref url="/pages/LRupMhoevMnPihfhVIfP" %}
[관리자 메뉴 수정하기](/guide/tuning-example/modify-menu)
{% endcontent-ref %}

{% content-ref url="/pages/frJkebKiY2DyABqlPSRs" %}
[관리자 페이지 추가하기](/guide/tuning-example/add-admin-page)
{% endcontent-ref %}

{% content-ref url="/pages/BWzWyt1f20xyAzuAjwBe" %}
[관리자 페이지 수정하기](/guide/tuning-example/modify-admin-page)
{% endcontent-ref %}

{% content-ref url="/pages/vYSJWtAFhghUkr2Qsi2r" %}
[사용자 페이지 추가하기](/guide/tuning-example/add-user-page)
{% endcontent-ref %}

{% content-ref url="/pages/PMSXvrnIOwp5eNl7Hvtu" %}
[사용자 페이지 수정하기](/guide/tuning-example/modify-user-page)
{% endcontent-ref %}


# 관리자 GNB 색상 변경하기

## 📌 요구사항 정의 및 분석

* 상점의 아이덴티티를 나타내는 색상이 존재하여, 해당 색상을 상점 관리자의 GNB에 적용하고 싶음.
* 고도몰 상점 관리자 GNB 영역은 수정이 가능한 부분임을 확인하여 해당 부분 색상을 수정하고자 함.

## 📝 개선안 정리

* 색상을 변경하고자 하는 GNB 범위 선정

<figure><img src="/files/nTIXASHsZRmih2wz8LyQ" alt=""><figcaption></figcaption></figure>

* 영역 별로 다른 색상을 적용하며, ➀번은 <mark style="background-color:blue;">#213D54</mark>으로 ➁번은 <mark style="color:blue;">#5A86CB</mark> 으로 변경

## 🛠️ 커스터마이징 진행

* `admin/header.php` 파일에서 수정하고자 하는 영역의 클래스를 확인합니다.
* 관리자페이지 CSS를 추가할 수 있는 `admin/css/admin-custom.css` 파일을 엽니다.

{% code title="admin-custom.css" %}

```css
@charset "utf-8";

/**
 * custom css 입니다. 추가적인 css는 여기에 작성을 해주세요.
 */
```

{% endcode %}

* ➀번 클래스의 background-color를 <mark style="background-color:blue;">#213D54</mark> 로 지정합니다.&#x20;

{% code title="admin-custom.css" %}

```css
@charset "utf-8";

#header .navbar {
    background-color: #213D54;
}

```

{% endcode %}

* ➁번 클래스의 background-color를  <mark style="color:blue;">#5A86CB</mark> 로 지정합니다.

{% code title="admin-custom.css" %}

```css
@charset "utf-8";

#header .nav.navbar-nav.reform {
    background-color: #5A86CB;
}
```

{% endcode %}

## 🔖 결과 확인

<figure><img src="/files/oC08KHthdLSFDVHa78fN" alt=""><figcaption></figcaption></figure>


# 즐겨찾기 메뉴 바로가기 만들기

## 📌 요구사항 정의 및 현황분석

* 자주 사용하는 메뉴를 관리자 메인화면에서 바로 접속하고자 함.
* GNB 에 있는 자주쓰는 메뉴는 메뉴 단위로만 접근이 가능한 상황으로 상세 조건이 설정 된 상태로 접근 하는 것은 불가함.  ex ) 게시글 관리 메뉴의 '게시판' 설정 값이 '1:1문의'인 게시글 관리으로의 직접 연결이 불가

## 📝 개선안 정리

* 추가 방법 선정
  * 버튼의 형태로 제공
  * 버튼 클릭 시, 연결한 메뉴 페이지가 새창으로 출력 되도록 적용
* 자주쓰는 메뉴로 추가할 메뉴 선정
  * 상품 > 상품 노출형태 관리 > 상품상세 공통정보 관리
  * 게시판 >  게시판 관리 > 게시글 관리 : 게시판이 '1:1문의'로 설정 된 게시글 관리 화면
* 위치 선정

  * 관리자 메인 우측 배너 영역 상단으로 추가

  <figure><img src="/files/WNIGYviOLf0sRdAPblYp" alt=""><figcaption></figcaption></figure>

## 🛠️ 커스터마이징 진행

1. `관리자페이지 > 개발소스관리` 팝업창을 엽니다.

   <figure><img src="/files/1O3OVlN6xrrevd52pUnQ" alt=""><figcaption></figcaption></figure>
2. `관리자스킨 소스관리 > 관리자 스킨소스 보기` 에서 `data/module/Asset/Admin/base/index.php` 파일을 선택한 후, `'운영소스에 복사'버튼을` 클릭합니다.

   <figure><img src="/files/d1fN5DoDhfkfF3e03NWx" alt=""><figcaption></figcaption></figure>
3. `(상점 폴더)/admin/base/index.php` 파일을 엽니다.
4. 관리자 메인 측면 배너 구간에 원하는 버튼을 추가합니다. \
   필요에 따라 `admin/css/admin-custom.css` 에서 버튼의 css 속성을 추가합니다.

{% code title="AS-IS (index.php)" %}

```html
<!-- 관리자 메인 측면 배너 시작 -->
<?php if (gd_is_provider() === false) { ?>
    <div id="panel_banner_mainSide" class="sub-sector banner-float">
    </div>
<?php } ?>
<!-- 관리자 메인 측면 배너 끝 -->
```

{% endcode %}

{% code title="TO-BE (index.php)" %}

```html
<!-- 관리자 메인 측면 배너 시작 -->
<?php if (gd_is_provider() === false) { ?>
    <div id="panel_banner_mainSide" class="sub-sector banner-float">
        <p>
            <a class="btn btn-lg banner-btn-custom" href="../goods/common_content_list.php">
                상품상세 공통정보 관리
            </a>
        </p>
        <p>
            <a class="btn btn-lg banner-btn-custom" href="../board/article_list.php?bdId=qa">
                게시글 관리 (1:1문의)
            </a>
        </p>
    </div>
<?php } ?>
<!-- 관리자 메인 측면 배너 끝 -->
```

{% endcode %}

{% code title="admin-custom.css" %}

```css
@charset "utf-8";

/**
 * custom css 입니다. 추가적인 css는 여기에 작성을 해주세요.
 */
.banner-btn-custom {
    width: 100%;
    background-color: #FFFFFF;
    border-color: #4677E5;
    color: #4677E5;
    padding: 9px 16px 8px;
    font-size: 13px;
}
```

{% endcode %}

## 🔖 결과 확인

#### 📎 커스터마이징 전

<figure><img src="/files/SnAMO7DRpipXr7duYfpE" alt=""><figcaption></figcaption></figure>

#### 🖇️ 커스터마이징 후

<figure><img src="/files/mfQcyqEg91x2FxWXEWkY" alt=""><figcaption></figcaption></figure>


# 관리자 메뉴 추가하기

## 📌 요구사항 및 분석

* 관리자에 상점에서 별도로 사용하고자 하는 메뉴를 추가하고자 함.
* 해당 메뉴들은 고도몰에서 제공하지 않는 메뉴로, 상점에서 상점 관리에 필요한 별도의 기능을 구현하기 위한 메뉴를 추가하는 것임.

## 📝 개선안 정리

* 관리자 메뉴에 다음과 같은 메뉴 추가
  * 1차 메뉴 : 환경저장
  * 2차 메뉴 : 기본설정 > 메뉴 정책
  * 3차 메뉴 : 기본설정 > 메뉴 정책 > 메뉴 관리&#x20;

## 🛠️ 커스터마이징 진행

{% hint style="info" %}
관리자 메뉴는 `es_adminMenu` 테이블에서 관리합니다.
{% endhint %}

### 📌 관리자 1차 메뉴 추가 <a href="#esadminmenu-database-table" id="esadminmenu-database-table"></a>

<figure><img src="/files/OKDqmCI5bBkO18QNgvQe" alt=""><figcaption><p>초기 1차 메뉴</p></figcaption></figure>

adminMenuSort(관리자 메뉴 순서), adminMenuNo(관리자 메뉴 고유 번호) 값을 확인합니다.

{% hint style="info" %}
adminMenuSort, adminMenuNo는 각각 고유한 값을 가져야 합니다.
{% endhint %}

아래 SELECT 쿼리를 실행하여 마지막 관리자 메뉴 순서 값을 확인합니다.

```sql
SELECT max(adminMenuSort) 
FROM `es_adminMenu` 
WHERE adminMenuDepth = 1 
    AND adminMenuType = 'd'; # d = 본사 메뉴, s = 공급사 메뉴
```

```sql
# 실행 결과 (예시)
100
```

다음으로 아래 SELECT 쿼리를 실행하여 마지막 관리자 메뉴 고유 번호를 확인합니다.

```sql
SELECT adminMenuNo 
FROM `es_adminMenu` 
WHERE adminMenuNo LIKE 'prefix%' 
ORDER BY adminMenuNo DESC 
LIMIT 0, 1;
```

```sql
# 실행 결과 (예시)
prefix00119
```

{% hint style="danger" %}
항상 메뉴고유번호는 제작사 prefix(접두사)를 입력해야 합니다. (회사영문 또는 고유영문)\
제작사 prefix(접두사) 에 godo 는 사용하지 않습니다.(godo 를 사용하시면 오류가 발생할 수 있습니다.)

**추가되는 메뉴고유번호에 godo prefix를 사용하는 경우 고도몰 배포 시, 초기화되거나 변경될 수 있습니다.**\
\
실행 결과값이 없을 경우 추가되는 메뉴고유번호는 prefix00001 입니다.\
(숫자는 00001부터 시작하여 1씩 증가해야 합니다.)
{% endhint %}

아래 INSERT 쿼리를 실행하여 필요한 관리자 1차 메뉴를 추가합니다.

```sql
INSERT INTO `es_adminMenu` (adminMenuNo, adminMenuType, adminMenuProductCode, adminMenuPlusCode,
                            adminMenuCode, adminMenuDepth, adminMenuParentNo, adminMenuSort, adminMenuName,
                            adminMenuUrl, adminMenuDisplayType, adminMenuDisplayNo, adminMenuSettingType,
                            adminMenuEcKind, regDt)
VALUES ('prefix00120', 'd', 'godomall', null,
        'setting', '1', 'setting', '101', '환경저장',
        'setting.php', 'y', 'godo00000, 'd', 'p', now());
```

관리자페이지에서 변경된 1차 메뉴를 확인합니다.

### 📌 관리자 2차 메뉴 추가 <a href="#id-2-2" id="id-2-2"></a>

아래 SELECT 쿼리를 실행하여 추가하고자 하는 2차 메뉴의 1차 메뉴 고유번호를 확인합니다.

```sql
SELECT adminMenuNo 
FROM `es_adminMenu` 
WHERE adminMenuDepth = 1 
    AND adminMenuType = 'd' 
    AND adminMenuName = '기본설정';
```

```sql
# 실행 결과 (예시)
godo00001
```

1차 메뉴인 (기본설정)의 메뉴에서 2차 메뉴의 최대 정렬 번호를 확인합니다.

```sql
SELECT max(adminMenuSort) 
FROM `es_adminMenu` 
WHERE adminMenuDepth = 2 
    AND adminMenuType = 'd' 
    AND adminMenuParentNo = 'godo00001';
```

```sql
# 실행 결과 (예시)
100
```

다음으로 아래 SELECT 쿼리를 실행하여 마지막 관리자 메뉴 고유 번호를 확인합니다.

```sql
SELECT adminMenuNo 
FROM `es_adminMenu` 
WHERE adminMenuNo LIKE 'prefix%' 
ORDER BY adminMenuNo DESC 
LIMIT 0, 1;
```

```
prefix00120
```

{% hint style="danger" %}
항상 메뉴고유번호는 제작사 prefix(접두사)를 입력해야 합니다. (회사영문 또는 고유영문) \
제작사 prefix(접두사) 에 godo 는 사용하지 않습니다. (godo 를 사용하시면 오류가 발생할 수 있습니다.)

**추가되는 메뉴고유번호에 godo prefix를 사용하는 경우 고도몰 배포 시, 초기화되거나 변경될 수 있습니다.**

\
실행 결과값이 없을 경우 추가되는 메뉴고유번호는 prefix00001 입니다. \
(숫자는 00001부터 시작하여 1씩 증가해야 합니다.)
{% endhint %}

아래 INSERT 쿼리를 실행하여 필요한 관리자 2차 메뉴를 추가합니다.

```sql
INSERT INTO `es_adminMenu` (adminMenuNo, adminMenuType, adminMenuProductCode, adminMenuPlusCode,
                            adminMenuCode, adminMenuDepth, adminMenuParentNo, adminMenuSort, adminMenuName,
                            adminMenuUrl, adminMenuDisplayType, adminMenuDisplayNo, adminMenuSettingType,
                            adminMenuEcKind, regDt)
VALUES ('prefix00121', 'd', 'godomall', null,
        'menu', '2', 'godo00001', '101', '메뉴 정책',
        null, 'y', 'godo00000', 'd', 'p', now());
```

{% hint style="warning" %}
2차 메뉴는 1개 이상의 3차 메뉴가 등록되어야 노출됩니다.
{% endhint %}

### 📌 관리자 3차 메뉴 추가 <a href="#id-2-2" id="id-2-2"></a>

아래 SELECT 쿼리를 실행하여 추가하고자 하는 3차 메뉴의 2차 메뉴 고유번호를 확인합니다.

* 위 본사 관리자의 (메뉴 관리)이라는 3차 메뉴를 추가하려면 `DataBase > es_adminMenu` 접속하신 다음 아래 Query 를 실행합니다.
* 2차 메뉴인 (메뉴 정책)의 메뉴 고유번호를 확인합니다.

```sql
SELECT adminMenuNo 
FROM `es_adminMenu` 
WHERE adminMenuDepth = 2 
    AND adminMenuType = 'd' 
    AND adminMenuName = '메뉴 정책';
```

```sql
# 실행 결과 (예시)
prefix00121
```

2차 메뉴인 (메뉴 정책)의 메뉴에서 3차 메뉴의 최대 정렬 번호를 확인합니다.

```sql
SELECT max(adminMenuSort) 
FROM `es_adminMenu` 
WHERE adminMenuDepth = 3 
    AND adminMenuType = 'd' 
    AND adminMenuParentNo = 'prefix00121';
```

```sql
# 실행 결과 (예시)
1000
```

다음으로 아래 SELECT 쿼리를 실행하여 마지막 관리자 메뉴 고유 번호를 확인합니다.

```sql
SELECT adminMenuNo 
FROM `es_adminMenu` 
WHERE adminMenuNo LIKE 'prefix%' 
ORDER BY adminMenuNo DESC 
LIMIT 0, 1;
```

```sql
# 실행 결과 (예시)
prefix00121
```

{% hint style="danger" %}
항상 메뉴고유번호는 제작사 prefix(접두사)를 입력해야 합니다. (회사영문 또는 고유영문) \
제작사 prefix(접두사) 에 godo 는 사용하지 않습니다. (godo 를 사용하시면 오류가 발생할 수 있습니다.)

**추가되는 메뉴고유번호에 godo prefix를 사용하는 경우 고도몰 배포 시, 초기화되거나 변경될 수 있습니다.**

\
실행 결과값이 없을 경우 추가되는 메뉴고유번호는 prefix00001 입니다. \
(숫자는 00001부터 시작하여 1씩 증가해야 합니다.)
{% endhint %}

아래 INSERT 쿼리를 실행하여 필요한 관리자 3차 메뉴를 추가합니다.

```sql
INSERT INTO `es_adminMenu` (adminMenuNo, adminMenuType, adminMenuProductCode, adminMenuPlusCode,
                            adminMenuCode, adminMenuDepth, adminMenuParentNo, adminMenuSort, adminMenuName,
                            adminMenuUrl, adminMenuDisplayType, adminMenuDisplayNo, adminMenuSettingType,
                            adminMenuEcKind, regDt)
VALUES ('prefix00122', 'd', 'godomall', null,
        'menu_management', '3', 'prefix00121', '1001', '메뉴 관리',
        'menu_management.php', 'y', null, 'd', 'p', now());
```

관리자 페이지 > 기본 설정 메뉴에서 추가된 2, 3차 메뉴를 확인합니다.

### 📌 관리자 메뉴별 권한 설정 <a href="#id-4" id="id-4"></a>

<figure><img src="/files/cl2Nlj7r6mKpVBLvcjo6" alt=""><figcaption><p>관리자 페이지 > 기본설정 > 관리 정책 > 운영자 권한 설정</p></figcaption></figure>

* 권한 설정은 '권한없음 / 읽기 / 읽기+쓰기' 의 3가지 조건으로 제공됩니다.
  * 권한없음 : 메뉴의 내용 확인 허용 안함
  * 읽기 : 메뉴의 내용 확인은 허용하나 정보 변경은 허용 안함
  * 읽기+쓰기 : 메뉴의 내용 확인 및 정보 변경까지 제한 없이 모두 허용함
* 쓰기 제한 추가 예시
  * 관리자 메뉴 페이지에 해당되는 컨트롤러에서 `post()` 함수를 통해 쓰기 제한 스크립트를 정의합니다.

```php
<?php
class UserPageController extends \Controller\Admin\Controller
{

    public function post()
    {
        // 관리자 메뉴 쓰기 권한에 따른 쓰기 기능 제한
        $writable = $this->getAdminMenuWritableAuth();
        if ($writable['check'] === false) {
            $returnMenuAccessAuth = [];
            $returnMenuAccessAuth[] = '$("#frmBase").validate().destroy();';
            $returnMenuAccessAuth[] = '$("#frmBase").submit(function(){ dialog_alert("__PAGE_TITLE__의 쓰기 권한이 없습니다. 권한은 대표운영자에게 문의하시기 바랍니다."); return false; });';
            $returnMenuAccessAuth = array_map(function($script) use ($writable) {return str_replace("__PAGE_TITLE__", $writable['title'], $script);}, $returnMenuAccessAuth);
            $this->setData('menuAccessAuth', implode("\n", $returnMenuAccessAuth));
        }
    }
}
```

## 🔖 결과 확인

### 📌 관리자 1차 메뉴 추가

<figure><img src="/files/mtq6gt5pkPfMBPg8wP3x" alt=""><figcaption><p>변경 후 1차 메뉴</p></figcaption></figure>

### 📌 관리자 2, 3차 메뉴 추가

<figure><img src="/files/wFQkDDNboLyCTZNzmg8F" alt=""><figcaption></figcaption></figure>


# 관리자 메뉴 수정하기

## 📌 요구사항 및 분석

* [관리자 메뉴 추가하기](/guide/tuning-example/add-menu) 에서 추가한 1차 메뉴의 이름을 변경하고자 함.
* [관리자 메뉴 추가하기](/guide/tuning-example/add-menu) 에서 추가한 1차 메뉴의 접근 URL을 변경하고자 함.
* [관리자 메뉴 추가하기](/guide/tuning-example/add-menu) 에서 추가한 1차 메뉴의 노출 여부를 '노출함'에서 '노출안함'으로 변경하고자 함.

## 📝 개선안 정리

* 관리자 메뉴명 변경
  * 변경 전: 환경저장
  * 변경 후: 광고설정
* 관리자 메뉴 URL변경
  * 변경 전: menu.php
  * 변경 후: advertisement.php
* 관리자 메뉴 노출 여부 변경
  * 변경 전: 노출함
  * 변경 후: 노출안함

## 🛠️ 커스터마이징 진행

### 📌 관리자 메뉴 이름 변경

<figure><img src="/files/pgCQxcuPxWz9R2m5xDpG" alt=""><figcaption></figcaption></figure>

위 본사 관리자의 `'환경저장'` 1차 메뉴의 이름을 `'광고설정'` 으로 변경하려면\
아래 SELECT 쿼리를 실행하여 변경하고자 하는 1차 메뉴의 정보를 확인합니다.

```sql
SELECT * 
FROM `es_adminMenu` 
WHERE adminMenuName = '환경저장';
```

1차 메뉴의 `adminMenuNo`를 확인한 다음, \
아래 UPDATE 쿼리를 실행하여 `adminMenuName`을 `'광고설정'`으로 변경합니다.

```sql
UPDATE `es_adminMenu` 
SET adminMenuName = '광고설정' 
WHERE adminMenuNo = 'prefix00120';
```

### 📌 관리자 메뉴 URL 변경

<figure><img src="/files/pgCQxcuPxWz9R2m5xDpG" alt=""><figcaption></figcaption></figure>

위 본사 관리자의 `'광고설정'` 1차 메뉴의 링크를 `setting.php` 에서 `advertisement.php` 로 변경하려면\
아래 SELECT 쿼리를 실행하여 변경하고자 하는 1차 메뉴의 정보를 확인합니다.

```sql
SELECT * 
FROM `es_adminMenu` 
WHERE adminMenuUrl = 'setting.php';
```

1차 메뉴의 `adminMenuNo`를 확인한 다음, \
아래 UPDATE 쿼리를 실행하여 `adminMenuUrl`을 `advertisement.php` 로 변경합니다.

```sql
UPDATE `es_adminMenu` 
SET adminMenuUrl = 'advertisement.php' 
WHERE adminMenuNo = 'prefix00120';
```

### 📌 관리자 메뉴 노출 여부 변경

<figure><img src="/files/pgCQxcuPxWz9R2m5xDpG" alt=""><figcaption></figcaption></figure>

위 본사 관리자의 `'광고설정'` 1차 메뉴를 노출이 되지 않도록 변경하려면\
아래 SELECT 쿼리를 실행하여 노출 여부를 변경하고자 하는 1차 메뉴의 정보를 확인합니다.

```sql
SELECT * 
FROM `es_adminMenu` 
WHERE adminMenuName = '광고설정';
```

1차 메뉴의 `adminMenuNo`를 확인한 다음, \
아래 UPDATE 쿼리를 실행하여 `adminMenuDisplayType`을 `n` 으로 변경합니다.

```sql
UPDATE `es_adminMenu` 
SET adminMenuDisplayType = 'n' 
WHERE adminMenuNo = 'prefix00120';
```

## 🔖 결과 확인

### 📌 관리자 메뉴 이름 변경

<figure><img src="/files/5TtHTghDv9AwXyh1C4Tw" alt=""><figcaption></figcaption></figure>

### 📌 관리자 메뉴 URL 변경

```php
// '광고설정' 메뉴 클릭 시 이동하는 URL
"http://gdadmin.example.godomall.com/setting/index.php"
```

### 📌 관리자 메뉴 노출 여부 변경

<figure><img src="/files/UIf3pPOsQXRqYjKusTBC" alt=""><figcaption></figcaption></figure>


# 관리자 페이지 추가하기

## 📌 요구사항 및 분석

* [관리자 메뉴 추가하기](/guide/tuning-example/add-menu) 에서 추가한 3차 메뉴인 `관리자 > 기본설정 > 메뉴 정책 > 메뉴 관리` 에 접근할 수 있는 페이지를 만들고자 함

## 📝 개선안 정리

* <https://gdadmin.example.godomall.com/policy/menu\\_management.php&#x20>;
* 위 URL로 접근 가능한 컨트롤러 추가

## 🛠️ 커스터마이징 진행

### 📌 Controller 추가 (방법 1) <a href="#controller-1" id="controller-1"></a>

`module/Controller/Admin/Policy` 폴더에 추가할 페이지의 컨트롤러 파일(`MenuManagement.php)` 을 추가합니다.

#### 사용자 정의 `Controller` 소스 내용

```php
<?php

/**
 * Namespace는 Controller\폴더명\폴더명으로 작성합니다.
 */
namespace Controller\Admin\Policy;

/**
 * Classname는 파일명과 동일해야 합니다.
 * \Controller\Admin\Controller라는 부모 클래스를 상속받습니다.
 */
class MenuManagementController extends \Controller\Admin\Controller
{
    /**
     * Class Methods로 반드시 index()를 포함해야 합니다.
     * 추가로 Methods 만들어 동일 파일내에서 사용이 가능합니다.
     */
    public function index()
    {
        try {
            // 관리자 페이지 좌측 메뉴 불러오기
            $this->callMenu('policy', 'menu', 'menu_management');
            
            $setData = 'Hello World!';
            $this->setData('setData', $setData);

        } catch (\Exception $e) {
            throw $e;
        }
    }
}

// PHP 소스 코드만 포함된 경우 ?> 를 생략합니다. (PSR0 표준)
```

### 📌 Controller 추가 (방법 2) <a href="#controller-1" id="controller-1"></a>

* 액션 처리와 같이 스킨으로 전송할 필요가 없는 경우 `index()`메소드에서 `exit();` 처리로 강제 종료합니다.
* 고도몰에서는 `SomePsController`라는 이름으로 사용하고 있습니다. form으로 넘겨서 데이터를 가공하기 위한 목적으로 사용됩니다.

#### 사용자 정의 `Controller` 소스 내용

```php
<?php
namespace Controller\Admin\Policy;

class MenuManagementController extends \Controller\Admin\Controller
{
    public function index()
    {
        try {
            $setData = 'Hello World!';
            echo $setData;
            exit();
    
        } catch (\Exception $e) {
            throw $e;
        }
    }
}
```

### 📌 관리자 스킨 추가 <a href="#controller-2" id="controller-2"></a>

* `admin/policy/` 폴더 하위에 추가할 `HTML` 파일을 추가합니다.
* `gdadmin.example.godomall.com/policy/menu_management.php` 경로의 사용자 페이지를 추가한다면 `admin/policy/` 폴더 아래 `menu_management.php` 파일을 추가합니다.

#### `Controller`에서 선언한 `setData` 사용하기

{% code title="menu\_management.php" %}

```html
<p><?=$setData;?></p>
```

{% endcode %}

## 🔖 결과 확인

<figure><img src="/files/0HbvBDZm3ynXCILvAabq" alt=""><figcaption></figcaption></figure>

![](http://localhost:63343/markdownPreview/61509271/fileSchemeResource/d4efec3275118710f6aa2be05b7ef1e5-admin_order_skin_create_view.jpg?_ijt=ck9ogtp4gbjoonhj6jtngrd1ie)


# 관리자 페이지 수정하기

## 📌 요구사항 및 분석

* `관리자 > 주문/배송 > 주문 관리 > 주문통합리스트` 에서 필요한 데이터를 추가로 확인하고자 함.

## 📝 개선안 정리

* `order_list_all.php` 페이지와 매핑되는 Controller 에서 Front로 전달하는 데이터를 추가
* `order_list_all.php` 페이지에서 컨트롤러에서 전달받은 데이터를 화면에 노출

## 🛠️ 커스터마이징 진행

### 📌 Controller 수정하기

1. `관리자페이지 > 개발소스관리` 팝업창을 엽니다.<br>

   <figure><img src="/files/WSledqW1WuNcgTWuVtyg" alt=""><figcaption></figcaption></figure>
2. `쇼핑몰 소스관리 > 고도몰 원본소스 보기` 에서 `data/module/Bundle/Controller/Admin/Order/OrderListAllController.php` \
   파일을 선택한 후, `'개발소스에 복사'버튼을` 클릭합니다.<br>

   <figure><img src="/files/g8KQJTy7FzsKfig87NE6" alt=""><figcaption></figcaption></figure>
3. `module/Controller/Admin/Order` 폴더 하위에 복사된 파일(`OrderListAllController.php`)을 확인하여 필요한 기능을 추가합니다.

```php
<?php
namespace Controller\Admin\Order;

class OrderListAllController extends \Bundle\Controller\Admin\Order\OrderListAllController
{
    public function index()
    {
        try {
            // 부모 클래스 상속
            parent::index();

            // 데이터 추가
            $addSource = '필요한 데이터를 추가해주세요';
            $this->setData('addSource', $addSource);

        } catch (\Exception $e) {
            throw $e;
        }
    }
}

```

### 📌 관리자 스킨 수정하기

1. `관리자페이지 > 개발소스관리` 팝업창을 엽니다.<br>

   <figure><img src="/files/WSledqW1WuNcgTWuVtyg" alt=""><figcaption></figcaption></figure>
2. `관리자스킨 소스관리 > 관리자 스킨소스 보기` 에서 \
   `data/module/Asset/Admin/order/order_list_all.php` 파일을 선택한 후, \
   `'운영소스에 복사'버튼을` 클릭합니다.<br>

   <figure><img src="/files/bjNY6EJMSqrV4cM4Vf6u" alt=""><figcaption></figcaption></figure>
3. `OrderListAllController.php` 에서 추가한 `addSrouce`를 추가합니다.

```php
<div class="page-header js-affix">
    <h3><?php echo end($naviMenu->location); ?>
        <small>취소/환불/반품/교환을 포함한 전체 주문리스트입니다.</small>
    </h3>
    <?php if (!isset($isProvider) && $isProvider != true) { ?>
        <div class="btn-group">
            <a href="order_write.php" class="btn btn-red-line">수기주문 등록</a>
        </div>
    <?php } ?>
</div>
<?php include $layoutOrderSearchForm;// 검색 및 프린트 폼 ?>

<!-- 추가기능 출력 -->
<?php echo $addSource; ?>
```

## 🔖 결과 확인

<figure><img src="/files/mSnh7yn7s80fsDdJ7ZeD" alt=""><figcaption></figcaption></figure>


# 사용자 페이지 추가하기

## 📌 요구사항 및 분석

* 새로운 사용자 샘플 페이지를 추가하고자 함

## 📝 개선안 정리

* <https://gdadmin.example.godomall.com/test/sample.php>
  * 위 URL에 대한 스킨 파일 추가
  * 위 URL로 잡근 가능한 컨트롤러 추가

## 🛠️ 커스터마이징 진행

### 📌 Controller 추가 <a href="#controller-1" id="controller-1"></a>

1. `module/Controller` 폴더 하위에 `Front/Test` 폴더를 생성합니다.

{% hint style="info" %}
`module`폴더 이후의 폴더명은 `Upper Camel Case`로 작성합니다.
{% endhint %}

2. 생성한 `Test` 폴더 하위에 `SampleController.php` 파일을 생성하여 원하는 기능을 추가합니다.

{% code title="SampleController.php" %}

```php
<?php

/**
 * Namespace는 Controller\폴더명\폴더명으로 작성합니다.
 */
namespace Controller\Front\Test;

/**
 * Classname는 파일명과 동일해야 합니다.
 * \Controller\Front\Controller라는 부모 클래스를 상속받습니다.
 */
class SampleController extends \Controller\Front\Controller
{
    /**
     * Class Methods로 반드시 index()를 포함해야 합니다.
     * 추가로 Methods 만들어 동일 파일내에서 사용이 가능합니다.
     */
    public function index()
    {
        $setData = 'Hello World !!!';
        $this->setData('setData', $setData);
    }
}

// PHP 소스 코드만 포함된 경우 ?> 를 생략합니다. (PSR0 표준)
```

{% endcode %}

### 📌 스킨 파일 추가 <a href="#controller-1" id="controller-1"></a>

* `data/skin/front/[스킨]/test` 폴더를 생성합니다.
* 생성한 `test` 폴더 하위에 `sample.html` 파일을 추가한 다음, `Controller`에서 전달한 `setData`를 출력합니다.

{% code title="sample.html" %}

```html
<table border="1">
    <tr>
        <td>{=setData}</td>
    </tr>
</table>
```

{% endcode %}

## 🔖 결과 확인

<figure><img src="/files/fzA7lRtNNUDCr6YmMNmj" alt=""><figcaption></figcaption></figure>


# 사용자 페이지 수정하기

## 📌 요구사항 및 분석

* 사용자 장바구니 페이지(`order/cart.php`)에서 필요한 데이터를 추가로 확인하고자 함.

## 📝 개선안 정리

* `cart.php` 페이지와 매핑되는 Controller 에서 Front로 전달하는 데이터를 추가
* `cart.php` 페이지에서 컨트롤러에서 전달받은 데이터를 화면에 노출

## 🛠️ 커스터마이징 진행

### 📌 Controller 수정하기

1. `관리자페이지 > 개발소스관리` 팝업창을 엽니다.<br>

   <figure><img src="/files/WSledqW1WuNcgTWuVtyg" alt=""><figcaption></figcaption></figure>
2. `쇼핑몰 소스관리 > 고도몰 원본소스 보기` 에서 `data/module/Bundle/Controller/Front/Order/CartController.php` \
   파일을 선택한 후, `'개발소스에 복사'버튼을` 클릭합니다.<br>

   <figure><img src="/files/HlrK284tFIrtxdcVz7zl" alt=""><figcaption></figcaption></figure>
3. module/Controller/Front/Order 폴더 하위에 복사된 파일(`CartController.php`)을 확인하여 필요한 기능을 추가합니다.

```php
<?php
namespace Controller\Front\Order;

class CartController extends \Bundle\Controller\Front\Order\CartController
{
    public function index()
    {
        try {
            // 부모 클래스 상속
            parent::index();

            // 데이터 추가
            $displayBox = '박스를 출력';
            $this->setData('displayBox', $displayBox);

        } catch (\Exception $e) {
            throw $e;
        }
    }
}

```

### 📌 사용자 스킨 수정하기

1. `관리자 페이지 > 디자인 > 디자인 설정 > 디자인 스킨 레이아웃 설정` 페이지로 이동합니다.

   <figure><img src="/files/2JD3M30fFPEJEz1r5Dtq" alt=""><figcaption></figcaption></figure>
2. 좌측 하단 스킨 페이지들 중, 디자인 페이지 수정이 필요한 `[스킨]/order/cart.html` 파일을 선택합니다.

   <figure><img src="/files/DhZMzLbNdrW9rwhJq1dC" alt=""><figcaption></figcaption></figure>
3. CartController.php 에서 추가한 displayBox를 추가한 다음, 화면보기 버튼을 통해 결과물을 확인한 다음 디자인 페이지 저장 버튼을 클릭해 작업물을 저장합니다.<br>

   <figure><img src="/files/TTRJ8nhuuC8KDnVkEOVi" alt=""><figcaption></figcaption></figure>

{% code title="추가된 소스코드" %}

```html
<!-- CartController.php 에서 정의한 displayBox 추가 -->
<!--{ ? isset(displayBox) === true }-->
<div style="margin-top:10px; padding:10px; text-align: center; border:3px solid #cfcfcf;">{=displayBox}</div>
<!--{ / }-->
```

{% endcode %}

## 🔖 결과 확인

<figure><img src="/files/XFCODp3Px7OXO2EDEjir" alt=""><figcaption></figcaption></figure>


# 잘못된 커스터마이징 사례

**잘못된 커스터마이징 사례**는 실 사용자로부터  고도몰 1:1 문의를 통해 인입 되었던 내용들을 정리한 내용입니다.\
고도몰을 커스터마이징 하신 분들이 주로 실수하는 부분을 확인하실 수 있어요!

해당 사례들을 참고하시어, 커스터마이징 시 이슈가 발생하지 않도록 주의하여주시기 바랍니다.&#x20;

{% content-ref url="/pages/A1deI5FKKWiX2KTjkbAp" %}
[상속처리가 되지 않은 케이스](/guide/wrong-example/uninherited)
{% endcontent-ref %}

{% content-ref url="/pages/3g0LqCvfgbRbaAlcY4BO" %}
[메소드 관련](/guide/wrong-example/method-violation)
{% endcontent-ref %}

{% content-ref url="/pages/llTMxeU0K2seMLgleAXt" %}
[그 외](/guide/wrong-example/reported-issue)
{% endcontent-ref %}


# 상속처리가 되지 않은 케이스

원본소스 class 혹은  원본 소스의 부모 메서드 등 상속을 받아서 개발해야하나, 상속받지 아니하고 개발함으로써 발생한 사례 예시입니다.

### 1.   class와 method 미상속

{% hint style="success" %}
**고도몰's 개발자 코멘트**

method의 경우 상속받은 형태로 구현이 불가한 상황이 있을 수 있습니다.\
때문에 가능한 해당 method 상속이 가능한 상황으로 구현하시는 것이 좋습니다.
{% endhint %}

#### ⛔️ As-Is

```php
namespace Component\Excel;

class ExcelRequest extends \Bundle\Component\Excel\ExcelRequest
{
    public function saveInfoExcelRequest($arrData)
    {
        # write your code
    }
}
```

#### ✅ To-be

```php
namespace Component\Excel;

class ExcelRequest extends \Bundle\Component\Excel\ExcelRequest
{
    public function saveInfoExcelRequest($arrData)
    {
        parent::saveInfoExcelRequest($arrData);
        
        # write your code
    }
}
```

### 2. `system`의 `controller` 커스터마이징 시 class 미상속

{% hint style="success" %}
**고도몰's 개발자 코멘트**

하기 예시의 경우 class와 method의 상속을 받지 않고 구현된 내용입니다.\
반드시 \Bundle\Controller\Admin\Goods\GoodsListController 를 사용해서 시스템의 GoodsListController를 상속받아야 하며,  method 내에서는 parent::index(); 를 사용해서 시스템의 index()를 상속받아야 합니다.
{% endhint %}

#### ⛔️ As-Is

```php
namespace Controller\Admin\Goods;

/**
 * 상품 리스트 페이지
 */
class GoodsListController
{
    # write your code
}
```

#### ✅ To-be

```php
namespace Controller\Admin\Goods;

/**
 * 상품 리스트 페이지
 */
class GoodsListController extends \Bundle\Controller\Admin\Goods\GoodsListController
{
    parent::index();
    
    # write your code
}
```


# 메소드 관련

### 1.   오버로딩 된 메소드 삭제

{% hint style="success" %}
**고도몰's 개발자 코멘트**

커스터마이징을 하지 않았음에도 무의식적으로 메소드를 남겨놓는 경우가 있습니다.\
사용 되지 않는 메소드를 남겨둘 경우 성능개선 및 기능개선 배포 내용이 반영 되지 않을 수 있으니, \
불필요한 메소드는 삭제하여주세요.&#x20;
{% endhint %}

#### ⛔️ As-Is

```php
namespace Component\Excel;

class ExcelRequest extends \Bundle\Component\Excel\ExcelRequest
{
    public function saveInfoExcelRequest($arrData)
    {
        // 부모 메소드와 동일한 내용 (즉, 커스터마이징을 하지 않은 경우)
    }
}
```

#### ✅ To-be

```php
namespace Component\Excel;

class ExcelRequest extends \Bundle\Component\Excel\ExcelRequest
{
    // 불필요한 오버라이딩 메소드 삭제
}
```


# 그 외

### 1.   마스터 DB Query 과다 사용으로 인한 서버 부하

{% hint style="success" %}
**고도몰's 개발자 코멘트**

커스터마이징 시 부하가 많이 발생할 것 같은 Query문에는 반드시 slave method 처리를 해주세요.\
실수로 slave에 insert, update를 사용핫더라도 시스템에서 예외처리가 되기 때문에\
걱정하지 않으셔도 됩니다.
{% endhint %}

#### 📍 Slave 사용방법

* Slave DB가 존재하는 상점에서만 사용할 수 있습니다.
* 동적으로 DB의 값이 변경되는 쿼리는 사용하지 마세요.
* 정적인 값을 보유한 쿼리인 경우 다음과 같이 DB 객체에 `slave()`를 한번 더 호출
  * master : `$this->db->query_fetch()`
  * slave : `$this->db->slave()->query_fetch()`
* 만약, slave method를 사용하더라도 slave가 없는 경우 자동으로 master 전환 처리됨
* 활용방법
  * 페이징 처리를 위한 count 쿼리
  * 실시간으로 update 된 데이터를 보여줄 필요가 없는 쿼리
  * 기타 설정을 저장하는 쿼리 등
  * 위 쿼리들에 대해서는 `slave()` 메소드를 붙여서 사용하시기를 권장합니다.

### 2. 분산서버를 고려하지 않고 기능을 만든 경우

{% hint style="success" %}
**고도몰's 개발자 코멘트**

이벤트를 진행하게 되면 분산서버(이벤트 서버)를 사용하게 됩니다. 분산서버 사용 시 분산서버를 고려하여 개발해야 합니다. \
파일 업로드를 웹서버 자체에 구현할 경우 원본서버(gdadmin, api 도메인)에서 파일을 찾지못하여 이벤트 종료 시 파일이 유실될 수 있습니다.&#x20;
{% endhint %}

#### ⛔️ As-Is

```php
namespace Controller\Front\File;

/**
 * 파일 등록 하는 클래스
 */
class FileUpload
{
    # write your code    
    
    ...
    
    Storage::disk(Storage::SOME_PATH, 'local')->upload($tmpFileNm, $newFileNm);
    
    ...
    
    # write your code    
}
```

#### ✅ To-be

{% code overflow="wrap" %}

```php
namespace Controller\Front\File;

/**
 * 파일 등록 하는 클래스
 */
class FileUpload
{
    # write your code    
    
    ...
    
    1. 고도몰의 게시판 첨부파일 저장 코드를 확인 하여 분산서버 사용 시 원본 서버에 파일이 저장되도록 수정
    2. 원본서버의 api 도메인에 파일 업로드 하는 api를 만들어 해당 api로 파일 전송하여 원본에만 파일이 저장되도록 수정
    3. 기타 방법으로 첨부파일이 분산서버가 아닌 원본 서버나 다른 서버에 저장되지 않도록 변경
    
    ...
    
    # write your code    
}
```

{% endcode %}

### 3. 고도몰이 정의한 DB의 값을 임의의 값으로 변경하는 경우

{% hint style="success" %}
**고도몰's 개발자 코멘트**

고도몰이 정의한 DB컬럼의 값(ex. es\_adminMenu 의 'adminMenuNo')를 임의로 변경하는 경우, \
고객상점에서만 사용할 수 있는 문구로 수정하여주세요.\
단, 이러한 컬럼들은 대부분의 상점이 고도몰이 정의한 값을 유지하여 사용하고 있어 관련 DB패치가 진행 될때 'primary\_key'에러로 자동패치가 적용 되지 않을 수 있습니다.\
또한 UPDATE문이 배포 될 경우, 고객기 수정하여 사용중인 컬럼값이 초기화(고도몰 정의 값으로 변경)될 수 있습니다.
{% endhint %}

#### ⛔️ As-Is

```
adminMenuNo = 'godo008***'
```

#### ✅ To-be

```
# test가 아닌 임의의 4자리 문자열로 변경 필요
adminMenuNo = 'test******'
```

### 4. 모든 영향 범위에 커스터마이징 내용을 적용하지 않은 경우

{% hint style="success" %}
**고도몰's 개발자 코멘트**

새로운 값의 정의를 추가하는 경우 관련 범위의 파일도 모두 수정해주세요.

예를들어, 게시판 업로드 스킨의 form id를 변경하였다면 하기 범위를 모두 수정해주셔야 합니다.\
/data/skin/mobile/스킨명/js/gd\_board\_write.js\
/data/skin/mobile/스킨명/js/gd\_common.js\
/data/skin/mobile/스킨명/board/skin/default/write.html

form id를 frmWrite으로 사용하여 업로드 관련 정보를 input 태그로 수정합니다.
{% endhint %}

#### ⛔️ As-Is

{% code overflow="wrap" %}

```html
<!--{ ? req.bdId == 'useras' }-->
<form id="asWrite" action="../board/board_ps.php" method="post" enctype="multipart/form-data" class="frmWrite">
<!--{ : }-->
<form name="frmWrite" id="frmWrite" action="../board/board_ps.php" method="post" enctype="multipart/form-data" class="frmWrite">
<!--{ / }-->
```

{% endcode %}

#### ✅ To-be

{% code overflow="wrap" %}

```html
<form name="frmWrite" id="frmWrite" action="../board/board_ps.php" method="post" enctype="multipart/form-data" class="frmWrite">
```

{% endcode %}

### 5. DB에 이미지 바이너리데이터를 넣은 경우

{% hint style="success" %}
**고도몰's 개발자 코멘트**

고도몰 DB에는 이미지 바이너리데이터를 넣어서는 안됩니다.&#x20;

테이블에 이미지를 바이너리 형태로 입력한 데이터를 넣을 경우, 해당 테이블을 조회하는 쿼리가 실행 될 때마다 서버에 부하가 발생할 수 있습니다.
{% endhint %}

{% hint style="danger" %}
**주의하세요!**

<mark style="color:red;">부하 발생 시 상점 차단과 같은 불이익이 발생</mark>할 수 있습니다. \
서버 부하로 인해 상점이 차단 되는 경우 발생하는 불이익에 대해서는 오롯이 상점의 책임이므로\
서버 부하가 발생하지 않도록 주의하여주세요!
{% endhint %}

#### ⛔️ As-Is

{% code overflow="wrap" %}

```
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDABQODxIPDRQSEBIXFRQYHjIhHhwcHj0sLiQySUBMS0dARkVQWnNiUFVtVkVGZIhlbXd7gYKBTmCNl4x9lnN+gXz/2wBDARUXFx4aHjshITt8U0ZTfHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHz/wAARCAMCAwIDASIAAhEBAxEB/8QAGwABAAIDAQEAAAAAAAAAAAAAAAECAwUGBAf/
```

{% endcode %}

#### ✅ To-be

{% code overflow="wrap" %}

```
DB 테이블 컬럼에 as-is와 같은 이미지 바이너리 데이터를 절대로 넣지마세요.
특히 공용서버의 경우 부하 발생시 다른 상점도 영향을 받을 수 있어 차단될 수 있습니다.
```

{% endcode %}

### 6. NOT NULL 필드 추가 시 기본값 설정 필수

{% hint style="danger" %}
**주의하세요!**

Table의 새로운 필드를 NOT NULL로 추가할 경우,\
기존 데이터에 대해 기본값을 설정하지 않으면 데이터 무결성 오류가 발생할 수 있습니다.\
따라서 아래 사항을 반드시 확인하여 반영해 주세요!
{% endhint %}

#### 📍 기본값 지정

* 필드 정의 시 DEFAULT 키워드를 사용하여 기본값을 지정하세요.
* 예) ALTER TABLE your\_table ADD COLUMN new\_column VARCHAR(255) NOT NULL DEFAULT 'default\_value';


# 디자인 에디터 개발 활용 가이드

에이전시 파트너를 위한 디자인 에디터 실무 가이드

{% hint style="success" %}

### 디자인 에디터를 쉽게 사용할 수 있도록 도와드려요!

HTML 위젯 모듈화 방식부터 페이지별 작업 원칙, 납품 체크리스트까지 디자인 에디터 환경에서 커스텀 스킨을 자신 있게 제작할 수 있도록 안내합니다.
{% endhint %}

## 가이드 목차

* [들어가며](/design_editor/intro)
  * [이 가이드를 읽기 전에](/design_editor/intro/overview)
  * ["커스텀이 안 된다"는 오해와 현실](/design_editor/intro/misconception)
* [PART I : 시스템 환경 이해](/design_editor/part1_system)
  * [8개 필수 페이지 운영 정책과 권한](/design_editor/part1_system/mvp)
  * [메인 페이지의 특별 권한](/design_editor/part1_system/main)
  * [빈 페이지 활용법](/design_editor/part1_system/empty)
  * [공통 관리 섹션 - 헤더·푸터·공지 배너](/design_editor/part1_system/common)
* [PART II : HTML 위젯 모듈화](/design_editor/part2_widget)
  * [기능 단위 조립 방식](/design_editor/part2_widget/assembly)
  * [작업 자산화](/design_editor/part2_widget/asset)
  * [CS 감소 효과](/design_editor/part2_widget/cs)
* [PART III : 페이지별 실전 작업 가이드](/design_editor/part3_guide)
  * [HTML 위젯 배치 핵심 원칙](/design_editor/part3_guide/principle)
  * [메인 페이지](/design_editor/part3_guide/main)
  * [상품 목록 / 상품 상세 / 검색결과](/design_editor/part3_guide/product)
  * [장바구니 / 주문서](/design_editor/part3_guide/cart)
  * [회원가입 / 로그인](/design_editor/part3_guide/member)
  * [공통 관리 섹션 작업 가이드](/design_editor/part3_guide/common)
* [PART IV : 작업 흐름 및 납품 체크리스트](/design_editor/part4_checklist)
* [PART V : 상점 고객 커뮤니케이션 가이드](/design_editor/part5_communication)
* [⭐ Coming Soon](/design_editor/coming_soon)
* [자주 묻는 질문 (FAQ)](/design_editor/faq)


# 들어가며

디자인 에디터 도입 이후 현장에서는 "어떻게 작업해야 하는지 모르겠다"는 불확실성이 생겨났습니다. 이 파트에서는 그 불확실성의 원인을 짚고, 이 가이드가 무엇을 해결하는지 안내합니다.

***

### 이 파트에서 다루는 내용

* [이 가이드를 읽기 전에](/design_editor/intro/overview) - 가이드의 목적, 대상 독자, 전체 구성
* ["커스텀이 안 된다"는 오해와 현실](/design_editor/intro/misconception) - 현장의 선입견과 실제 가능 범위


# 이 가이드를 읽기 전에

이 페이지에서는 **디자인 에디터 실무 활용 가이드의 목적, 대상 독자, 전체 구성**을 안내합니다. \
처음 방문하셨다면 이 페이지부터 시작해 보세요.

***

### 이 가이드가 만들어진 배경

디자인 에디터가 도입된 이후, 구체적인 제작 방법론이 충분히 공유되지 않아 현장에서 불확실성이 생겨났습니다. 그 결과 상점도 선뜻 도입을 결정하지 못하는 상황이 이어지고 있습니다.

이 가이드는 그 불확실성을 해소합니다. 디자인 에디터 환경에서 커스텀 스킨을 자신 있게 제작할 수 있는 실무 방법론, 페이지별 작업 원칙, 납품 체크리스트를 제공합니다.

***

### 이 가이드의 대상 독자

이 가이드는 아래에 해당하는 분들을 위해 작성되었습니다.

* 디자인 에디터 기반 프로젝트를 처음 맡게 된 **PM·디자이너·퍼블리셔**
* 기존 스킨 방식에서 전환을 검토 중인 **에이전시 실무자**

***

### 이 가이드를 읽고 나면

* 디자인 에디터의 시스템 구조와 권한 정책을 정확히 이해할 수 있습니다.
* HTML 위젯 모듈화 방식으로 커스텀 스킨을 설계하고 제작할 수 있습니다.
* 8개 필수 페이지별 작업 원칙과 HTML 위젯 배치 전략을 적용할 수 있습니다.
* 납품 후 상점 고객에게 디자인 에디터의 가치를 효과적으로 전달할 수 있습니다.


# "커스텀이 안 된다"는 오해와 현실

이 페이지에서는 **현장에서 굳어진 "디자인 에디터로는 튜닝이 안 된다"는 인식의 실체**를 살펴봅니다. \
제약이 아닌 접근법의 차이임을 확인해 보세요.

***

### 오해가 생긴 이유

현장에서 굳어진 "디자인 에디터로는 튜닝이 안 된다"는 인식은, HTML 위젯의 존재와 활용법을 충분히 파악하지 못한 상태에서 생겨난 선입견입니다. 기존 스킨 방식이 익숙한 상황에서 새로운 방식을 시도하지 않은 채 내려진 판단입니다.

***

### 현실은 다릅니다

기존 방식과 디자인 에디터 방식의 차이는 **제약이 아니라 접근법의 차이**입니다.

| 구분         | 기존 하드코딩 방식         | HTML 위젯 모듈화 방식         |
| ---------- | ------------------ | ---------------------- |
| **작업 단위**  | 전체 페이지를 하나의 파일로 제작 | 필요한 기능 위젯만 선택적으로 개발    |
| **공통 영역**  | 헤더·푸터도 직접 구현       | 공통 UI는 시스템에 위임, 본문에 집중 |
| **수정 범위**  | 수정 시 전체 코드 파악 필요   | 해당 위젯만 수정              |
| **운영자 편집** | 납품 후 운영자 편집 불가     | 운영자가 위젯 표시/숨김·순서 직접 제어 |

***

### 접근법을 바꾸면 가능합니다

HTML 위젯을 통해 기존 튜닝 작업의 결과물을 모듈화된 형태로 그대로 구현할 수 있습니다. 전체를 하드코딩하는 대신, 필요한 기능만 HTML 위젯으로 개발하여 페이지에 조립하는 방식입니다.

> 8개 필수 페이지 외 영역은 빈 페이지를 생성하여 자유롭게 커스텀할 수 있습니다. 브랜드 스토리, 이벤트 페이지 등이 여기에 해당합니다.

***

### 현재 스펙의 제약과 대응 방법

작업 범위에 제약이 있는 것은 사실입니다. 아래 내용을 미리 파악해두면 프로젝트를 더 원활하게 진행할 수 있습니다.

| 제약 사항                 | 대응 방법                       |
| --------------------- | --------------------------- |
| 8개 필수 페이지 외 영역 편집 불가  | 빈 페이지를 생성하여 자유롭게 커스텀        |
| 필수 페이지 본문 섹션 삭제·숨김 불가 | 섹션 삭제 및 HTML 직접 편집 기능 추가 예정 |
| 헤더·푸터에 HTML 위젯 추가 불가  | UI 기반 편집 범위 내에서 사전 조율 필요    |


# PART I : 시스템 환경 이해

규칙을 알아야 전략이 나옵니다. 이 파트에서는 디자인 에디터의 페이지 구조, 권한 정책, 편집 가능 범위를 정확히 파악합니다. 작업 착수 전 반드시 숙지해야 할 내용입니다.

***

### 이 파트에서 다루는 내용

* [8개 필수 페이지 운영 정책과 권한](/design_editor/part1_system/mvp) - 페이지별 제어 권한 일람
* [메인 페이지의 특별 권한](/design_editor/part1_system/main) - 메인 페이지에서만 가능한 작업
* [빈 페이지 활용법](/design_editor/part1_system/empty) - 제약 없이 자유롭게 편집 가능한 영역
* [공통 관리 섹션 - 헤더·푸터·공지 배너](/design_editor/part1_system/common)- 작업 범위와 주의 사항


# 8개 필수 페이지 운영 정책과 권한

이 페이지에서는 **디자인 에디터가 제공하는 8개 필수 페이지의 운영 정책과 제어 권한**을 정리합니다. 작업 범위를 정확히 파악하고 프로젝트를 설계하는 데 기준이 되는 내용입니다.

***

### 8개 필수 페이지란?

디자인 에디터는 쇼핑몰의 핵심 구매 여정을 구성하는 8개 페이지를 기본으로 제공합니다.

**메인 → 상품 목록 → 상품 상세 → 검색결과 → 장바구니 → 회원가입 → 로그인 → 주문서**

이 8개 페이지는 쇼핑몰의 핵심 구매 여정 전체를 커버합니다.

***

### 페이지별 제어 권한 일람

| 구분                 | 해당 페이지                                   | 권한                                                    |
| ------------------ | ---------------------------------------- | ----------------------------------------------------- |
| **메인 페이지**         | 메인 (index)                               | 명칭·URL 변경 가능 / 복사 가능 / 삭제 가능 / 본문 섹션 삭제 가능 / 팝업 설정 가능 |
| **일반 필수 페이지 (7개)** | 상품 목록, 상품 상세, 검색결과, 장바구니, 회원가입, 로그인, 주문서 | 명칭·URL 변경 불가 / 복사 불가 / 삭제 불가 / 본문 섹션 삭제·숨김 불가         |

***

### 주의 사항

> **일반 필수 페이지의 본문 섹션은 현재 삭제·숨김이 모두 불가합니다.**\
> 섹션 삭제 기능 및 HTML 직접 편집 기능이 추가될 예정입니다. 작업 전 고객에게 현재 스펙을 안내해 두세요.

***

### HTML 위젯 배치 가능 위치

일반 필수 페이지에서는 시스템 필수 섹션을 유지한 채, 그 위아래로 HTML 위젯을 조립하는 방식으로 작업합니다.

* **페이지 상단** - 브랜드 요소, 배너, 안내 문구 등
* **시스템 필수 섹션** - 상품 목록, 상품 상세 정보 등 (현재 삭제·숨김 불가)
* **페이지 하단** - 관련 상품 추천, 프로모션 안내 등


# 메인 페이지의 특별 권한

이 페이지에서는 **메인 페이지에서만 사용할 수 있는 기능**을 안내합니다. 일반 필수 페이지와 다른 메인 페이지만의 권한을 작업에 적극 활용해 보세요.

***

### 메인 페이지가 특별한 이유

메인 페이지는 일반 필수 페이지와 달리 훨씬 넓은 편집 권한을 가집니다. 아래 4가지 기능은 메인 페이지에서만 사용할 수 있습니다.

***

### 1. 복사 기능

메인 페이지를 복사하여 별도 페이지로 활용할 수 있습니다.

* 시즌 기획전 전용 랜딩 페이지
* 브랜드 캠페인 전용 화면
* 광고 랜딩 페이지 (URL 독립 설정 가능)

> 복사된 페이지는 URL을 독립적으로 설정할 수 있어 프로모션 목적에 맞게 운영할 수 있습니다.

***

### 2. 명칭·URL 변경

메인 페이지와 복사된 페이지의 명칭과 URL을 자유롭게 변경할 수 있습니다. 프로모션 목적에 맞는 URL을 설정하여 광고 랜딩 페이지로 활용하세요.

***

### 3. 팝업 설정

이벤트 팝업, 공지 팝업은 **메인 페이지에서만 설정 및 노출**이 가능합니다.

> 팝업 기획은 메인 페이지 중심으로 구성하세요. 다른 필수 페이지에서는 팝업을 설정할 수 없습니다.

***

### 4. 본문 섹션 삭제

메인 페이지에 한해 본문 섹션을 삭제할 수 있습니다. 불필요한 기본 섹션을 정리하고 HTML 위젯으로 원하는 레이아웃을 자유롭게 구성할 수 있습니다.

일반 필수 페이지(7개)에서는 현재 본문 섹션 삭제가 불가하니 메인 페이지의 이 권한을 적극 활용하세요.


# 빈 페이지 활용법

이 페이지에서는 **8개 필수 페이지 외에 자유롭게 생성하고 편집할 수 있는 빈 페이지**의 활용 방법을 안내합니다. 필수 페이지의 제약을 보완하는 핵심 영역입니다.

***

### 빈 페이지란?

8개 필수 페이지 외에 별도로 생성하는 페이지입니다. 필수 페이지와 달리 제약 없이 자유롭게 편집할 수 있습니다.

***

### 빈 페이지에서 가능한 것

| 기능            | 가능 여부          |
| ------------- | -------------- |
| 섹션 자유 추가·삭제   | 가능             |
| 페이지 명칭·URL 변경 | 가능             |
| HTML 위젯 자유 배치 | 가능             |
| 팝업 설정         | 불가 (메인 페이지 전용) |

***

### 주요 활용 예시

* **브랜드 스토리 페이지** - 브랜드 아이덴티티와 스토리를 자유롭게 구성
* **브랜드 랜딩 페이지** - 광고 소재와 연결되는 독립 랜딩
* **기획전 페이지** - 시즌별 기획전 레이아웃을 독립적으로 운영
* **이벤트 페이지** - 프로모션 이벤트 전용 페이지

***

### 실무 팁

> 8개 필수 페이지에서 구현하기 어려운 콘텐츠 페이지는 빈 페이지를 적극 활용하세요. HTML 위젯을 자유롭게 배치할 수 있어 사실상 제약 없이 원하는 레이아웃을 구성할 수 있습니다.


# 공통 관리 섹션 - 헤더·푸터·공지 배너

이 페이지에서는 **헤더·푸터·공지 배너의 작업 가능 범위와 주의 사항**을 안내합니다. 작업 착수 전 반드시 확인하고 고객과 사전 조율하세요.

***

### 공통 관리 섹션이란?

헤더·푸터·공지 배너는 개별 페이지에 종속되지 않는 공통 관리 섹션으로, 전 페이지에 일괄 적용됩니다.

***

### 작업 가능 범위

| 섹션        | 가능한 것                      | 불가능한 것     |
| --------- | -------------------------- | ---------- |
| **헤더**    | UI 기반 편집 (로고, 메뉴, 링크 등)    | HTML 위젯 추가 |
| **푸터**    | UI 기반 편집 (연락처, SNS, 저작권 등) | HTML 위젯 추가 |
| **공지 배너** | UI 기반 편집 (텍스트, 링크, 배경색 등)  | HTML 위젯 추가 |

***

### 반드시 확인하세요

> **공통 관리 섹션에는 HTML 위젯을 추가할 수 없습니다.**\
> 작업 착수 전 고객의 헤더·푸터 커스텀 요구사항이 UI 편집 범위 내에서 해결 가능한지 반드시 사전 확인하세요.

***

### 실무 팁

고객이 헤더·푸터에 복잡한 커스텀을 요구하는 경우, 현재 UI 편집 범위 내에서 가능한 수준을 미리 조율하세요. HTML 편집 자유도가 확대되는 업데이트 이후 재검토할 수 있음을 함께 안내하면 좋습니다.


# PART II : HTML 위젯 모듈화

디자인 에디터 방식의 핵심은 HTML 위젯 모듈화입니다. 이 파트에서는 기능 단위 조립 방식의 개념과 실무적 이점을 설명합니다.

***

### 이 파트에서 다루는 내용

* [기능 단위 조립 방식](/design_editor/part2_widget/assembly) - 하드코딩 방식과의 차이와 작업 구조
* [작업 자산화](/design_editor/part2_widget/asset) - 위젯을 재사용 가능한 영구 자산으로 쌓는 방법
* [CS 감소 효과](/design_editor/part2_widget/cs) - 운영자 자율성이 높아지면 에이전시에도 좋은 이유


# 기능 단위 조립 방식

이 페이지에서는 **HTML 위젯 모듈화 방식의 개념과 기존 하드코딩 방식과의 차이**를 설명합니다. 새로운 작업 패러다임을 이해하고 실무에 적용해 보세요.

***

### 작업 방식의 차이

전체를 하드코딩하는 대신, 필요한 기능만 HTML 위젯으로 개발하여 페이지에 조립합니다.

| 기존 하드코딩 방식          | HTML 위젯 모듈화 방식         |
| ------------------- | ---------------------- |
| 전체 페이지 파일을 처음부터 제작  | 필요한 기능 위젯만 선택적으로 개발    |
| 공통 UI(헤더·푸터)도 직접 구현 | 공통 UI는 시스템에 위임, 본문에 집중 |
| 수정 시 전체 코드 파악 필요    | 해당 위젯만 수정              |
| 납품 후 운영자 편집 불가      | 운영자가 위젯 표시/숨김·순서 직접 제어 |

***

### 조립 구조 이해하기

모든 필수 페이지 작업의 기본 구조는 동일합니다.

1. &#x20;**페이지 상단**\
   브랜드 배너, 안내 문구 등 → HTML 위젯 배치
2. **시스템 필수 섹션**\
   상품 목록, 장바구니 등 시스템이 제공하는 영역 → 현재 삭제·숨김 불가
3. **페이지 하단**\
   관련 상품 추천, 프로모션 안내 등 → HTML 위젯 배치

***

### 위젯 개발 원칙

* 각 위젯이 **독립적으로 동작**하도록 설계합니다.
* PC·모바일 **반응형 레이아웃**을 적용합니다.
* 헤더·푸터·공지 배너 등 공통 영역은 시스템이 관리하므로 **본문 커스텀에만 집중**합니다.


# 작업 자산화

이 페이지에서는 **한 번 제작한 HTML 위젯을 여러 프로젝트에서 재사용하는 자산화 전략**을 안내합니다. 반복 작업을 줄이고 납기를 단축하는 방법을 확인해 보세요.

***

### 위젯 하나 = 영구 자산

한 번 제작한 HTML 위젯은 다른 프로젝트에서도 재사용할 수 있습니다. 프로젝트를 거치며 위젯 라이브러리가 쌓일수록 제작 시간이 단축됩니다.

> 위젯 1개 = 프로젝트를 넘어 사용 가능한 영구 자산

***

### 자산화 전략

#### 공통 위젯 라이브러리 구축

자주 사용되는 위젯을 라이브러리로 축적하면 프로젝트 간 제작 시간이 단축됩니다.

* 상품 추천 영역 위젯
* 브랜드 띠 배너 위젯
* 배송·혜택 안내 위젯
* 카테고리 바로가기 위젯

#### 재사용 가능한 위젯 분류

| 분류            | 설명                         |
| ------------- | -------------------------- |
| **공통 위젯**     | 업종·브랜드에 관계없이 재사용 가능한 범용 위젯 |
| **페이지 전용 위젯** | 특정 페이지 목적에 맞게 커스텀된 위젯      |
| **브랜드 전용 위젯** | 특정 고객사 브랜드에 맞게 제작된 위젯      |

***

### 비즈니스 연결

축적된 위젯 라이브러리는 단순한 효율화를 넘어 새로운 수익 모델로 연결됩니다.

* **반복 작업 제거** → 단가 유지 + 납기 단축
* **디자인 스토어 판매** → 디자인 에디터 호환 스킨을 표준 상품으로 판매 가능 (지원 예정)
* **1:1 맞춤 제작 → 1:N 판매 구조**로 수익성 극대화


# CS 감소 효과

이 페이지에서는 **HTML 위젯 모듈화 방식이 에이전시의 단순 수정 요청을 줄이는 이유**를 설명합니다. 운영자 자율성이 높아지면 에이전시도 더 가치 있는 업무에 집중할 수 있습니다.

***

### 운영자가 직접 처리하게 되는 작업

디자인 에디터를 도입하면 상점 운영자가 직접 처리할 수 있는 작업 범위가 넓어집니다.

* 배너 이미지 교체
* 위젯 표시·숨김 설정
* 위젯 순서 변경
* 시즌 이벤트 프로모션 문구 수정

***

### 에이전시 입장에서의 변화

| 기존 구조               | 디자인 에디터 방식                  |
| ------------------- | --------------------------- |
| 단순 수정도 에이전시에 요청     | 운영자가 직접 처리                  |
| 에이전시 자원이 단순 작업에 소모  | 에이전시는 고부가가치 업무에 집중          |
| 소규모 수정 CS가 반복적으로 발생 | 결제 연동, 신규 기능 개발 등 전문 작업에 집중 |

***

### 에이전시에게 더 좋은 구조입니다

> 단순 수정 요청이 줄어들면 에이전시는 결제 연동, 기능 개발 등 고부가가치 업무에 자원을 집중할 수 있습니다. 고객 만족도가 높아지고, 에이전시는 더 의미 있는 작업에 집중할 수 있는 구조입니다.


# PART III : 페이지별 실전 작업 가이드

8개 필수 페이지 각각의 제약과 가능 범위를 파악했다면, 이제 실전 작업에 적용할 차례입니다. 이 파트에서는 페이지별 HTML 위젯 배치 원칙과 구체적인 활용 예시를 안내합니다.

***

### 이 파트에서 다루는 내용

* [HTML 위젯 배치 핵심 원칙](/design_editor/part3_guide/principle) - 모든 필수 페이지에 공통으로 적용되는 원칙
* [메인 페이지](/design_editor/part3_guide/main) - 메인 페이지 활용법
* [상품 목록 / 상품 상세 / 검색결과](/design_editor/part3_guide/product) - 상품 탐색·발견 흐름에서의 위젯 배치
* [장바구니 / 주문서](/design_editor/part3_guide/cart) - 결제 전환율을 높이는 위젯 활용
* [회원가입 / 로그인](/design_editor/part3_guide/member) - 가입·재방문 흐름에서의 위젯 배치
* [공통 관리 섹션 작업 가이드](/design_editor/part3_guide/common) - 헤더·푸터·공지 배너 실무 주의 사항


# HTML 위젯 배치 핵심 원칙

이 페이지에서는 **모든 필수 페이지 작업에 공통으로 적용되는 HTML 위젯 배치 원칙**을 안내합니다. 페이지별 작업을 시작하기 전에 이 원칙을 먼저 숙지해 보세요.

***

### 기본 구조

모든 필수 페이지 작업의 출발점은 동일합니다. 시스템이 제공하는 필수 섹션을 유지한 채, 그 위아래로 HTML 위젯을 조립하는 방식입니다.

***

### 위젯 배치 원칙

**1. 페이지 최상단**

브랜드 배너, 안내 문구 등 브랜드 요소를 HTML 위젯으로 배치합니다.

* 카테고리 소개 배너
* 시즌 프로모션 안내
* 브랜드 아이덴티티 비주얼

**2. 시스템 필수 섹션**

상품 목록, 상품 상세 정보, 장바구니 등 시스템이 제공하는 핵심 영역입니다.

> 현재 삭제·숨김이 불가합니다. 섹션 삭제 및 HTML 편집 기능은 추가될 예정입니다.

**3. 페이지 하단**

관련 상품 추천, 프로모션 안내 등 전환을 유도하는 콘텐츠를 HTML 위젯으로 배치합니다.

* 관련 상품 추천 영역
* 브랜드 스토리 띠 배너
* 프로모션 안내

***

### 위젯 설계 시 고려할 것

* 각 위젯이 **독립적으로 동작**하도록 설계합니다.
* **PC·모바일 반응형** 레이아웃을 반드시 적용합니다.
* 시스템 필수 섹션과 HTML 위젯 간 **레이아웃 충돌**이 없는지 확인합니다.
* 운영자가 이후 **표시/숨김·순서 변경**을 직접 할 수 있도록 위젯 단위를 적절히 분리합니다.


# 메인 페이지

이 페이지에서는 **메인 페이지의 특별 권한을 활용한 실전 작업 방법**을 안내합니다.&#x20;

***

### 메인 페이지의 강점

메인 페이지는 본문 섹션 삭제가 가능하므로, 불필요한 기본 섹션을 제거하고 제공되는템플릿 및 HTML 위젯으로 원하는 레이아웃을 자유롭게 구성할 수 있습니다.

***

### 실전 활용 포인트

#### 복사 기능 활용

메인 페이지를 복사하여 별도 랜딩 페이지로 운영할 수 있습니다.

* URL을 독립적으로 설정하면 광고 랜딩 페이지로 활용 가능
* 시즌 기획전 전용 화면을 별도 페이지로 운영
* 브랜드 캠페인 전용 랜딩 페이지 제작

#### 섹션 자유 편집

메인 페이지에 한해 본문 섹션 삭제가 가능합니다. 기본 섹션을 정리하고 HTML 위젯으로 브랜드에 맞는 레이아웃을 구성하세요.

#### 팝업 배치

이벤트 팝업, 공지 팝업은 메인 페이지에서만 설정 가능합니다.

> 팝업이 필요한 기획은 메인 페이지를 중심으로 설계하세요. 다른 필수 페이지에서는 팝업을 설정할 수 없습니다.

***

### HTML 위젯 활용 예시

| 위치     | 활용 예시                       |
| ------ | --------------------------- |
| **상단** | 메인 비주얼 배너, 슬라이드, 브랜드 핵심 메시지 |
| **중단** | 카테고리 바로가기, 신상품·베스트 상품 진열    |
| **하단** | 브랜드 스토리, SNS 피드, 이벤트 배너     |


# 상품 목록 / 상품 상세 / 검색결과

이 페이지에서는 **상품 목록, 상품 상세, 검색결과 페이지에서의 HTML 위젯 활용 예시**를 안내합니다. 고객이 상품을 탐색하고 발견하는 흐름에서 브랜드 경험을 강화하는 방법을 확인해 보세요.

***

### 상품 목록 페이지

고객이 카테고리를 탐색하는 단계입니다. 상단과 하단에 HTML 위젯을 배치하여 카테고리 특성과 브랜드 메시지를 전달하세요.

| 위치     | HTML 위젯 활용 예시                      |
| ------ | ---------------------------------- |
| **상단** | 카테고리 소개 배너, 시즌 프로모션 안내, 필터 안내      |
| **하단** | 브랜드 스토리 띠 배너, 관련 카테고리 바로가기, 기획전 연결 |

***

### 상품 상세 페이지

고객이 구매를 결정하는 핵심 단계입니다. 상품 정보를 보완하고 전환을 유도하는 위젯을 배치하세요.

| 위치     | HTML 위젯 활용 예시                  |
| ------ | ------------------------------ |
| **상단** | 브랜드 아이덴티티 배너, 상품 주요 특징 요약      |
| **하단** | 관련 상품 추천, 브랜드 보증 안내, 사용 후기 CTA |

***

### 검색결과 페이지

고객이 원하는 상품을 찾는 단계입니다. 검색 결과를 보완하고 이탈을 방지하는 위젯을 배치하세요.

| 위치     | HTML 위젯 활용 예시                      |
| ------ | ---------------------------------- |
| **상단** | 검색 결과 안내 배너, 카테고리 추천 바로가기          |
| **하단** | 검색 결과 없을 때 대체 추천 상품 영역, 인기 상품 바로가기 |

***

### 작업 시 주의 사항

> 상품 목록, 상품 상세, 검색결과 페이지의 시스템 필수 섹션은 현재 삭제·숨김이 불가합니다. HTML 위젯은 해당 섹션의 위아래에 배치하는 방식으로 작업하세요.


# 장바구니 / 주문서

이 페이지에서는 **장바구니, 주문서 페이지에서의 HTML 위젯 활용 예시**를 안내합니다. 결제 직전 단계에서 전환율을 높이고 신뢰를 강화하는 위젯 구성을 확인해 보세요.

***

### 장바구니 페이지

고객이 구매를 확정하기 직전 단계입니다. 결제를 유도하고 추가 구매를 안내하는 위젯을 배치하세요.

| 위치     | HTML 위젯 활용 예시                 |
| ------ | ----------------------------- |
| **상단** | 무료배송 조건 안내, 배송 혜택 요약 배너       |
| **하단** | 관련 상품 추천, 결제 전 프로모션 안내, 쿠폰 안내 |

***

### 주문서 페이지

고객이 구매를 최종 확정하는 단계입니다. 불안 요소를 줄이고 안심하고 결제할 수 있는 정보를 제공하세요.

| 위치     | HTML 위젯 활용 예시                  |
| ------ | ------------------------------ |
| **상단** | 배송 정책 요약, 주의사항 안내, 반품·교환 정책 요약 |

***

### 작업 시 주의 사항

> 장바구니·주문서 페이지의 시스템 필수 섹션은 현재 삭제·숨김이 불가합니다. 특히 주문서 페이지는 결제 흐름과 직결되므로, HTML 위젯이 시스템 섹션과 레이아웃 충돌을 일으키지 않는지 반드시 확인하세요.


# 회원가입 / 로그인

이 페이지에서는 **회원가입, 로그인 페이지에서의 HTML 위젯 활용 예시**를 안내합니다. 가입과 재방문 흐름에서 이탈을 줄이고 브랜드 신뢰를 높이는 위젯 구성을 확인해 보세요.

***

### 회원가입 페이지

신규 고객이 처음 브랜드와 관계를 맺는 단계입니다. 가입 혜택을 명확히 전달하여 가입 완료율을 높이세요.

| 위치     | HTML 위젯 활용 예시                       |
| ------ | ----------------------------------- |
| **상단** | 가입 혜택 안내 배너 (적립금, 웰컴 쿠폰, 첫 구매 혜택 등) |

***

### 로그인 페이지

재방문 고객이 쇼핑몰로 돌아오는 진입점입니다. 브랜드 아이덴티티와 로그인 혜택을 함께 전달하세요.

| 위치     | HTML 위젯 활용 예시            |
| ------ | ------------------------ |
| **상단** | 브랜드 아이덴티티 비주얼, 로그인 혜택 안내 |

***

### 작업 시 주의 사항

> 회원가입·로그인 페이지의 시스템 필수 섹션은 현재 삭제·숨김이 불가합니다. HTML 위젯은 해당 섹션의 위아래에 배치하는 방식으로 작업하세요.


# 공통 관리 섹션 작업 가이드

이 페이지에서는 **헤더·푸터·공지 배너 작업 시 실무에서 반드시 확인해야 할 사항**을 안내합니다. 착수 전 고객과 반드시 사전 조율하세요.

***

### 작업 가능 범위 요약

| 공통 관리 섹션  | 작업 가능 범위                                   |
| --------- | ------------------------------------------ |
| **헤더**    | UI 편집 가능 (로고, 메뉴, 링크 등) / HTML 위젯 추가 불가    |
| **푸터**    | UI 편집 가능 (연락처, SNS, 저작권 등) / HTML 위젯 추가 불가 |
| **공지 배너** | UI 편집 가능 (텍스트, 링크, 배경색 등) / HTML 위젯 추가 불가  |

***

### 착수 전 필수 확인

> **공통 관리 섹션에는 HTML 위젯을 추가할 수 없습니다.**\
> 작업 착수 전 고객의 헤더·푸터 커스텀 요구사항이 UI 편집 범위 내에서 해결 가능한지 항목별로 사전 확인하세요.

***

### 고객 요구사항 조율 방법

**Step 1.** 고객의 헤더·푸터 커스텀 요구사항 목록을 작성합니다.\
**Step 2.** 각 항목이 UI 편집 범위 내에서 구현 가능한지 검토합니다.\
**Step 3.** 불가한 항목은 고객에게 현재 스펙을 안내하고, HTML 자유도 확대 업데이트 이후 재검토 가능함을 함께 설명합니다.

***

### 실무 팁

고객이 헤더·푸터에 복잡한 커스텀을 요구하는 경우, 무리하게 진행하기보다 현재 UI 편집 범위 내에서 가능한 수준을 먼저 조율하는 것이 좋습니다. 추후 HTML 편집 자유도가 확대되는 업데이트 시점에 재작업을 제안하는 방식도 고려해 보세요.


# PART IV : 작업 흐름 및 납품 체크리스트

이 페이지에서는 **프로젝트 착수부터 고객 인수인계까지 단계별 점검 항목**을 안내합니다. 각 단계를 순서대로 확인하며 진행하세요.

### Step 0. 사전 확인 - 디자인 에디터 지원 여부

* [ ] 고객 상점이 디자인 에디터를 지원하는 고도26 상점인지 확인했나요?
* [ ] 반응형 스킨 설치가 가능한 상점인지 확인했나요?

> 디자인 에디터는 고도26 기반 상점에서만 사용할 수 있습니다. \
> 프로젝트 착수 전 고객 상점의 버전과 반응형 스킨 설치 가능 여부를 반드시 먼저 확인하세요.

***

### Step 1. 요구사항 분석

* [ ] 고객 튜닝 항목을 목록화하고 8개 필수 페이지 내 구현 가능 여부를 항목별로 검토했나요?
* [ ] 공통 관리 섹션(헤더·푸터·공지 배너) 커스텀 요구사항을 UI 편집 범위 내에서 조율했나요?
* [ ] 고객에게 현재 지원 범위와 Coming Soon 스펙을 사전 안내했나요?

***

### Step 2. 디자인 에디터 환경 파악

* [ ] 고도몰 관리자 > 디자인 에디터에서 각 필수 페이지 기본 섹션 구성을 직접 확인했나요?
* [ ] HTML 위젯 삽입 가능 위치와 순서 변경 인터페이스를 직접 확인했나요?

***

### Step 3. 위젯 구조 설계

* [ ] 페이지별 HTML 위젯 배치 구조를 설계했나요?\
  (상단 위젯 / 시스템 필수 섹션 / 하단 위젯)
* [ ] 재사용 가능한 공통 위젯과 페이지 전용 위젯을 구분했나요?

***

### Step 4. HTML 위젯 개발

* [ ] 각 위젯이 독립적으로 동작하도록 설계했나요?
* [ ] PC·모바일 반응형 레이아웃을 적용했나요?

***

### Step 5. 통합 테스트 및 QA

* [ ] 위젯 순서 변경·표시/숨김 기능이 정상 작동하는지 테스트했나요?
* [ ] PC·모바일 브라우저 크로스 체크를 완료했나요?
* [ ] 시스템 필수 섹션과 HTML 위젯 간 레이아웃 충돌 여부를 확인했나요?

***

### Step 6. 고객 인수인계

* [ ] 완성된 스킨을 운영자 계정에서 최종 확인했나요?
* [ ] 위젯 표시/숨김, 순서 변경 기본 사용법을 안내했나요?
* [ ] HTML 편집 자유도 확대 예정 및 치환코드 지원 예정을 안내했나요?


# PART V : 상점 고객 커뮤니케이션 가이드

이 페이지에서는 **납품 후 상점이 디자인 에디터의 가치를 체감할 수 있도록 전달하는 방법**을 안내합니다. 좋은 납품은 기술 완성도만큼이나 가치 전달에서도 완성됩니다.

***

### 납품 시 전달해야 할 핵심 포인트

| 전달 포인트         | 설명 예시                                                                            |
| -------------- | -------------------------------------------------------------------------------- |
| **비용 절감 효과**   | 초기 구축 비용은 동일하지만, 이후 배너 교체·위젯 순서 변경 등을 직접 처리할 수 있어 장기 운영 비용이 줄어듭니다.               |
| **즉각적인 운영 대응** | 시즌 프로모션, 이벤트 배너 등 시의성이 중요한 변경을 에이전시 일정에 구애받지 않고 즉시 처리할 수 있습니다.                   |
| **운영 자율성**     | 쇼핑몰 운영자가 디자인 주도권을 가지며, 고부가가치 작업은 에이전시 전문 지원을 받을 수 있는 협업 구조입니다.                   |
| **미래 확장성**     | HTML 편집 자유도가 대폭 확대되는 업데이트가 예정되어 있습니다. 지금 구축해 두면 업데이트 즉시 더 강력한 기능을 바로 활용할 수 있습니다. |

***

### 운영자 인수인계 시 안내할 내용

#### 직접 처리할 수 있는 작업 안내

납품 후 운영자가 스스로 처리할 수 있는 작업 범위를 명확히 안내해 주세요.

* 배너 이미지 교체 방법
* 위젯 표시·숨김 설정 방법
* 위젯 순서 변경 방법
* 새 위젯 추가 방법

#### Coming Soon 스펙 안내

> 조만간 HTML 편집 자유도가 대폭 확대되는 업데이트가 예정되어 있습니다. 지금 디자인 에디터 기반으로 구축해 두면 업데이트 시 별도 재구축 없이 바로 활용하실 수 있습니다.

***

### 실무 팁

납품 후 간단한 사용 가이드 문서나 영상을 함께 제공하면 운영자의 적응 속도가 빨라지고 초기 문의도 줄어듭니다. 인수인계 완료 후 일정 기간 운영 지원을 제안하는 것도 고객 만족도를 높이는 방법입니다.


# ⭐ Coming Soon

이 페이지에서는 **추후** **추가될 디자인 에디터 업데이트 내용**과, 지금 선점할 수 있는 비즈니스 기회를 안내합니다.

***

### 곧 업그레이드됩니다

조만간 8개 필수 페이지에서 **HTML 편집 자유도가 획기적으로 높아지는 스펙**이 추가될 예정입니다. 이 업데이트가 완료되면 현재의 HTML 위젯 방식보다 훨씬 높은 수준의 페이지 커스터마이징이 가능해집니다.

> 지금 HTML 위젯 모듈화 방식에 익숙해지면, 자유도가 열리는 시점에 디자인 에디터 커스텀 시장을 가장 빠르게 선점할 수 있습니다.

세부 활용 전략은 스펙 확정 후 이 가이드에 추가될 예정입니다.

***

### 지금 잡을 수 있는 비즈니스 기회

#### 1. 디자인 스토어 판매 (신규 수익 채널)

디자인 에디터 호환 스킨을 제작하면 NHN Commerce 디자인 스토어를 통해 표준 상품으로 판매할 수 있는 수익 모델이 열립니다.

* 1:1 맞춤 제작에서 **1:N 판매 구조**로 수익성 극대화
* 스킨 판매 기능은 현재 준비 중으로, 관련 업데이트는 에이전시 채널을 통해 공지될 예정입니다.

#### 2. 기존 고객 업그레이드 제안

곧 출시 예정인 기능을 통해 상점이 고도26으로 업그레이드할 수 있게 됩니다.

* 업그레이드 시점에 기존 고객에게 **디자인 에디터 기반 스킨 전환 서비스**를 제안하세요.
* 전환 구축 작업 자체가 새로운 프로젝트 기회가 됩니다.

#### 3. 하이브리드 운영 모델 구축

기본적인 디자인 변경은 운영자가 직접 처리하고, 에이전시는 결제 연동·신규 기능 개발 등 고부가가치 영역에 집중하는 하이브리드 모델을 제안하세요.

* 에이전시 의존도가 적절히 분산되면 고객 만족도가 높아집니다.
* 에이전시는 고수익 업무에 자원을 집중할 수 있습니다.

***

### 지금 시작해야 하는 이유

> HTML 위젯 모듈화 방식에 지금 익숙해질수록, 자유도가 확대되는 업데이트 시점에 경쟁 에이전시보다 빠르게 움직일 수 있습니다.


# 자주 묻는 질문 (FAQ)

디자인 에디터 기반 프로젝트를 진행하면서 현장에서 가장 많이 나오는 질문을 모았습니다. 작업 착수 전 미리 확인해 두세요.

<details>

<summary>기존 스킨 방식과 작업 구조가 너무 달라서 어디서부터 시작해야 할지 모르겠습니다.</summary>

이 가이드의 PART I(시스템 환경 이해)부터 순서대로 읽어보시길 권장합니다.

먼저 8개 필수 페이지의 권한 정책을 파악하고, 메인 페이지와 일반 페이지의 차이를 이해한 뒤, HTML 위젯 배치 핵심 원칙을 숙지하면 자연스럽게 작업 구조가 잡힙니다.

</details>

<details>

<summary>헤더·푸터 커스텀 요구사항이 있는데 HTML 위젯을 추가할 수 없다고 하면 어떻게 설명해야 하나요?</summary>

현재 헤더·푸터·공지 배너는 UI 기반 편집만 가능하며, HTML 위젯 추가는 지원되지 않습니다.

고객에게는 **현재 UI 편집 범위 내에서 구현 가능한 수준을 먼저 조율**하고, HTML 편집 자유도가 확대되는 업데이트 이후 재검토할 수 있음을 함께 안내하는 것이 좋습니다.

</details>

<details>

<summary>필수 페이지 본문 섹션을 숨기거나 삭제할 수 없나요?</summary>

현재 메인 페이지를 제외한 7개 일반 필수 페이지의 본문 섹션은 **삭제·숨김이 모두 불가**합니다.

섹션 삭제 기능 및 HTML 직접 편집 기능이 추가될 예정입니다. 현재는 시스템 필수 섹션을 유지한 채, 그 위아래로 HTML 위젯을 조립하는 방식으로 작업하세요.

</details>

<details>

<summary>8개 필수 페이지 외에 브랜드 스토리나 기획전 페이지도 만들 수 있나요?</summary>

네, 가능합니다. **빈 페이지를 생성**하면 섹션 추가·삭제, HTML 위젯 자유 배치, 명칭·URL 변경이 모두 가능합니다.

브랜드 스토리, 기획전, 이벤트 페이지 등 8개 필수 페이지 외의 콘텐츠는 빈 페이지를 활용해 자유롭게 구성하세요.

</details>

<details>

<summary>한 번 만든 HTML 위젯을 다른 고객사 프로젝트에서도 쓸 수 있나요?</summary>

네, 가능합니다. HTML 위젯은 독립적으로 동작하도록 설계하면 다른 프로젝트에서도 재사용할 수 있습니다.

자주 사용되는 위젯(상품 추천 영역, 브랜드 띠 배너 등)을 라이브러리로 축적하면 프로젝트 간 제작 시간을 단축할 수 있습니다. 자세한 내용은 [작업 자산화](/design_editor/part2_widget/asset) 페이지를 참고하세요.

</details>

<details>

<summary>Coming Soon 업데이트는 언제 적용되나요?</summary>

구체적인 일정은 **고도몰 공지사항**을 통해 안내드릴 예정입니다.

지금 HTML 위젯 모듈화 방식에 익숙해지면, 자유도가 확대되는 업데이트 시점에 바로 활용할 수 있습니다.

</details>

***

> **디자인 에디터 관련 문의**\
> 디자인 에디터 적용 과정에서 궁금한 사항이 있으시면 NHN Commerce 고객지원팀으로 문의해 주세요.


# 기타 개발 가이드

### 📍 [PHP 표준 권장 사항](https://www.php-fig.org/)

고도몰의 PHP 소스는 FIG의 표준 권장사항을 따르고 있습니다. 고도몰 커스터마이징 전 FIG 표준 권고 사항을 확인해주세요!


# 분산 환경 개발 가이드

### ℹ️ 목적

* 고도몰은 트래픽 분산을 위해 **분산 웹(이벤트 서버) 환경**도 제공합니다.
* **분산 웹(이벤트 서버) 환경**의 상점에서 외부 cron 호출, 자동결제, 파일 업로드 등 **서버 간 상태 공유가 필요한 기능**을 사용자 정의 개발할 경우, 이 문서의 내용을 반드시 확인하시기 바랍니다.

### ℹ️ 서버 구조

* 단일 서버 환경
  * 모든 요청이 하나의 서버에서 처리됩니다. 세션, 임시 파일, 로컬 변수 등이 동일 서버에 존재하므로 별도 고려가 필요 없습니다.
* 분산 웹(이벤트 서버) 환경
  * 분산 서버(A, B, C): 사용자 요청을 처리하는 서버. 요청마다 다른 서버로 라우팅될 수 있음
  * Origin 서버: 파일 저장, 데이터 원본을 관리하는 서버
* **분산 웹 환경에서는 동일 요청이 항상 같은 서버에서 처리된다는 보장이 없습니다.**
* 따라서 다음과 같은 경우 반드시 `api.{도메인}`을 사용해야 합니다.

### 🤔 `api.` 도메인이란

* 고도몰은 용도별로 서브도메인을 분리하여 운영합니다.
* `api.` 도메인으로 들어오는 요청은 **Origin 서버로 직접 라우팅**됩니다. 따라서 서버 간 상태 불일치 문제가 발생하지 않습니다.
* 사용자 정의 API 컨트롤러는 `module/Controller/Api` 경로에 생성하며
* `api.{도메인}/경로/파일명` 형식으로 접근합니다. 상세한 컨트롤러 생성 방법은 [컨트롤러 > API Controller](https://devcenter-help.nhn-commerce.com/guide/tuning/source-code/controller#api-controller) 를 참고하세요.

### 🧑🏻‍💻 개발 케이스

#### 1. 외부 cron에서 URL을 호출하는 경우

* 정기결제, 자동발송, 배치 처리 등 외부 cron에서 쇼핑몰 URL을 호출하는 경우
* \`[www.\`](http://www.`) 도메인을 사용하면 요청이 매번 다른 서버로 분산됩니다
* 잘못된 예
  * 분산 웹 환경에서 요청이 분산되어 상태 불일치 발생
  * <https://www.example.com/cron/auto_payment.php>
* 올바른 예
  * Origin 서버로 고정 라우팅
  * [https://api.example.com/cron/auto\_payment.php](<  https://api.example.com/cron/auto_payment.php>)

#### 2. 서버 간 상태 공유가 필요한 처리

* 다음 항목들은 서버 로컬에 저장되므로 분산 웹 환경에서 서버 간 공유되지 않습니다.

<table><thead><tr><th>항목</th><th>단일 웹</th><th width="180">분산 웹</th><th width="193.46484375">대응 방법</th></tr></thead><tbody><tr><td>파일 시스템 (임시 파일, 업로드 파일)</td><td>동일 디스크</td><td>서버별 별도 디스크</td><td><code>api.</code> 도메인 사용</td></tr><tr><td>PG 결제 토큰/인증값</td><td>동일 서버</td><td>생성 서버와 검증 서버 불일치 가능</td><td><code>api.</code> 도메인 사용</td></tr></tbody></table>

#### 3. 서버 간 순서 보장이 필요한 처리

분산 웹 환경에서는 동일 사용자의 연속 요청이 같은 서버로 가지 않을 수 있습니다.

* 결제 요청 -> 결제 승인 콜백 -> 주문 완료 처리
* 파일 업로드 -> 업로드된 파일 참조

이러한 처리가 하나의 트랜잭션으로 이루어져야 한다면, `api.` 도메인을 사용하여 Origin 서버에서 일관되게 처리되도록 해야 합니다.

### 📢 주의사항

* `api.` 도메인의 SSL 인증서가 정상 설정되어 있어야 합니다. 관리자 > 기본설정 > 보안서버(SSL)에서 확인하세요.
* `api.` 도메인은 Origin 서버로 직접 연결되므로 과도한 트래픽을 `api.` 도메인으로 보내면 Origin 서버에 부하가 집중될 수 있습니다.&#x20;
* 일반 사용자 트래픽은 `www.` 또는 `m.`도메인을 유지하고 서버 간 상태 공유가 필요한 처리에만 `api.` 도메인을 사용하세요.


# 로그 사용 가이드

## 소개

* 커스터마이징 시 사용자 로그 채널을 이용하여 로그를 남기면 확인이 가능합니다.
* 아래 가이드를 따라 확인 및 개발을 진행해주세요.

***

## 로그 추가 방법

* 커스터마이징 시 데이터 확인 등이 필요할 때 원하는 위치에 아래 소스를 참고하여 로그를 추가합니다.

#### 로그 추가 예시

{% code overflow="wrap" %}

```
\Logger::channel('userLog')->debug(__METHOD__ . '[' . __LINE__ . '], ' . ' USER LOG : ', ['로그'=>'테스트']);
```

{% endcode %}

#### 로그 내용 확인

{% code overflow="wrap" %}

```
[2024-04-08 11:55:34] : Bundle\Controller\Admin\Goods\GoodsListController::index[39],  USER LOG :  {"로그":"테스트"} {"process_id":27076}
```

{% endcode %}

* 채널 : userLog
* 레벨 : debug
* 최대 생성 파일 개수 : 7개
* 경로 : /data/custom\_log/custom\_log-yyyy-mm-dd.log
* 압축 : 하루 지난 로그 파일은 zip 파일 압축 됩니다. (암호 x)

{% hint style="warning" %}
**해당 채널 및 레벨 외에는 로그가 남지 않아 확인이 불가합니다.**
{% endhint %}


# \[PMA] 내보내기(export) 이용 안내

고도몰 PMA(PhpMyAdmin)를 통한 내보내기 기능 이용 방법을 안내 드립니다.

{% hint style="info" %}
**내보내기(export) 기능 차단**

* PMA(PhpMyAdmin)의 보안 강화를 위해, 내보내기(export) 기능은 차단되었습니다.
* 내보내기(export) 기능 사용이 필요하신 경우, 아래 안내에 따라 이용 부탁 드립니다.
  {% endhint %}

## 내보내기(export) 차단 해제 안내

1. PMA 내보내기(export) 기능 사용이 필요한 경우, <mark style="color:red;">**1:1문의를 통해 차단 해제를 요청**</mark> 할 수 있습니다.
2. 차단 해제는 요청일로부터 <mark style="color:red;">**업무영업일 +2일 내 차단 해제**</mark>가 진행됩니다.
3. 보안 유지를 위해 <mark style="color:red;">**차단 해제일로부터 +3일 후 재 차단**</mark>이 진행됩니다.

***

## 차단 해제 요청 방법

> 1:1문의를 통한 내보내기 차단 해제 요청 시, 아래 내용을 작성해주세요.

차단 해제 요청 시, 아래 항목을 기입하여 1:1문의로 해제 요청 부탁 드립니다.\
(해제 요청 시, 차단 해제 확인을 위한 유선 연락을 드릴 수 있습니다.)

* [ ] **차단 해제 사유**
* [ ] **차단 해제가 필요한 table 명**

[**\[1:1문의하기\]**](https://support.nhn-commerce.com/inquiry/contact)

***

## 데이터 관리 시, 유의 사항

1. 내보내기를 통한 데이터 관리 시, 정보유출/누락/자료 손실 등의 이슈가 발생하지 않도록 각별한 주의 부탁 드립니다.
2. 아래 고도몰 이용약관을 참고해주세요. [**\[약관보기\]**](https://www.nhn-commerce.com/etc/agreement.gd?termsType=godomall)

{% hint style="success" %}
**고도몰 이용약관 안내**

제 14조(고객의 의무)

⑤ 고객은 자신이 운영 중인 서비스의 데이터 등에 대해 별도로 저장할 의무가 있으며 외부 침입 등으로 인한 정보의 유출, 누락 또는 자료의 손실에 대해 회사는 책임을 지지 않습니다. 단, 회사가 해당 자료를 백업하여 별도로 보관 중인 경우에는 복구 시 도움을 줄 수 있으며, 백업자료가 없는 경우에는 회사는 책임을 지지 않습니다.
{% endhint %}


# 외부 스크립트 사용 가이드

## 외부 스크립트 등록/조회/삭제 가이드 <a href="#id-7jm467aaleykpo2broumve2kuc3rk7hroz0v7kgw7zqml-2bycreygnc3qsidsnbtrk5w-3d" id="id-7jm467aaleykpo2broumve2kuc3rk7hroz0v7kgw7zqml-2bycreygnc3qsidsnbtrk5w-3d"></a>

쇼핑몰에 스크립트를 적용하는 방법은 2가지가 있습니다.

\
1\. 쇼핑몰 관리자 설정 기능 활용하기\
\- 관리자 경로 : 쇼핑몰 관리자>기본설정>기본정책>외부서비스 설정\
\
2\. 외부 스크립트 API 활용하기\
\- [외부 스크립트 API 문서 바로가기](https://server-docs.godomall.com/?activeName=%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8)

스크립트 작동 시 쇼핑몰 화면단에서 필요한 정보가 있다면 SDK를 사용하시면 됩니다.\
단, SDK를 사용하여 쇼핑몰 회원의 정보를 제3자에게 제공하거나 개인정보처리업무를 위탁하는 경우, 개인정보보호법에 따라 정보 주체가 알기 쉬운 형태로 해당 내용을 공개해야 하며, 필요한 조치를 취하지 않아 발생하는 불이익에 대해서는 당사가 책임지지 않습니다.

셀러어드민에 판매앱 등록 시 \[셀러어드민>앱 등록/수정] 화면 내 '수집 데이터 정보' 항목에 쇼핑몰 회원 개인정보 수집 항목을 반드시 기재해 주시기 바랍니다.\
고도몰에서 제공하는 SDK 스펙과 사용예시는 [SDK 사용 가이드](/other-guide/sdk)를 참고해 주시기 바랍니다.

{% hint style="danger" %}
스크립트 안에서는 치환코드 사용이 불가하여 필요한 정보는 반드시 SDK를 사용해 주셔야 합니다.
{% endhint %}

### **1. 스크립트 등록** <a href="#ms4t7iqk7ygs66a97yq4leutseuhnq-3d-3d" id="ms4t7iqk7ygs66a97yq4leutseuhnq-3d-3d"></a>

쇼핑몰 플랫폼(PC 또는 모바일)을 지정하여 플랫폼에 따라 다른 스크립트를 등록하거나, 특정 플랫폼에만 스크립트 등록이 가능하며, 페이지를 지정하여 특정 페이지에만 등록도 가능합니다.\
고도몰에서는 아래의 위치에 스크립트를 등록할 수 있도록 지원하고 있습니다.

<table data-full-width="false"><thead><tr><th>스크립트 등록 위치</th><th>구분</th><th>location</th></tr></thead><tbody><tr><td>상단 공통</td><td>scriptHeader</td><td>-</td></tr><tr><td>하단 공통</td><td>scriptFooter</td><td>-</td></tr><tr><td>메인 페이지</td><td>scriptPage</td><td>INDEX</td></tr><tr><td>상품 리스트 페이지</td><td></td><td>GOODS_LIST</td></tr><tr><td>인기 상품 리스트 페이지</td><td></td><td>GOODS_POPULATE</td></tr><tr><td>상품 상세 페이지</td><td></td><td>GOODS_VIEW</td></tr><tr><td>상품 검색 결과 페이지</td><td></td><td>GOODS_SEARCH</td></tr><tr><td>장바구니 페이지</td><td></td><td>ORDER_CART</td></tr><tr><td>주문하기 페이지</td><td></td><td>ORDER</td></tr><tr><td>주문완료 페이지</td><td></td><td>ORDER_END</td></tr><tr><td>주문 목록 페이지</td><td></td><td>MYPAGE_ORDER_LIST</td></tr><tr><td>주문 상세 페이지</td><td></td><td>MYPAGE_ORDER_VIEW</td></tr><tr><td>로그인 페이지</td><td></td><td>MEMBER_LOGIN</td></tr><tr><td>회원가입 페이지</td><td></td><td>MEMBER_JOIN</td></tr><tr><td>회원가입 완료 페이지</td><td></td><td>MEMBER_JOIN_OK</td></tr><tr><td>마이페이지</td><td></td><td>MYPAGE_INDEX</td></tr></tbody></table>

<br>

API 활용 시에는 API 호출 시점을 지정할 수 있기 때문에 스크립트를 등록할 시점을 지정하여 등록할 수 있습니다.\
예를 들어 앱이 쇼핑몰에 설치된 후 토큰이 발급되자마자 스크립트를 등록할 수도 있고, 앱에 대한 사용료가 결제된 시점에 스크립트를 등록할 수도 있습니다.

<br>

### **2. 스크립트 실행** <a href="#mi4t7iqk7ygs66a97yq4leylpo2wiq-3d-3d" id="mi4t7iqk7ygs66a97yq4leylpo2wiq-3d-3d"></a>

쇼핑몰에 접속하면 쇼핑몰 플랫폼 및 페이지에 등록된 스크립트가 실행됩니다.\
쇼핑몰 관리자에서 등록한 스크립트는 쇼핑몰 관리자에서 설정한 사용 설정에 따라 동작되며,\
외부 스크립트 등록 API로 등록한 스크립트는 API 호출 시 사용한 systemkey가 발급된 앱의 설치여부와 만료일에 따라 동작됩니다.

<br>

### **3. 스크립트 조회** <a href="#my4t7iqk7ygs66a97yq4leyhso2aja-3d-3d" id="my4t7iqk7ygs66a97yq4leyhso2aja-3d-3d"></a>

등록된 스크립트를 조회하는 것은 스크립트 실행여부와는 관계가 없어서, 실행되지 않는 스크립트도 조회할 수 있습니다.\
쇼핑몰 관리자에서는 쇼핑몰 관리자에서 등록한 스크립트만 조회할 수 있으며, API로 등록한 스크립트는 호출 시 사용한 systemkey로만 조회 가능합니다.\
즉, A라는 systemkey로 등록한 스크립트는 B라는 systemkey로는 조회 불가하며, 쇼핑몰 관리자에서 조회할 수도 없습니다.

<br>

### **4. 스크립트 삭제** <a href="#nc4t7iqk7ygs66a97yq4leycreygna-3d-3d" id="nc4t7iqk7ygs66a97yq4leycreygna-3d-3d"></a>

API로 등록한 스크립트는 API 호출 시 사용한 systemkey가 발급된 앱이 쇼핑몰에서 삭제되면 등록된 스크립트도 자동으로 삭제됩니다.

쇼핑몰 관리자에서는 쇼핑몰 관리자에서 등록한 스크립트만 삭제할 수 있으며, API로 등록한 스크립트는 호출 시 사용한 systemkey로만 삭제 가능합니다.\
즉, A라는 systemkey로 등록한 스크립트는 B라는 systemkey로는 삭제 불가하며, 쇼핑몰 관리자에서 삭제할 수도 없습니다.\
또한 쇼핑몰 플랫폼(PC 또는 모바일)이나 페이지를 지정하여서 삭제할 수도 없습니다.

API를 활용하여 스크립트 삭제 시에는 scriptNo 기준으로 삭제해야 하기 때문에, 스크립트가 등록된 후 반환된 scriptNo를 기억해 두어야 합니다.\
scriptNo를 잊었다면 스크립트 조회 API를 통해 scriptNo를 조회할 수 있습니다.&#x20;


# SDK 사용 가이드

## SDK 사용 가이드 <a href="#u0rlleycroyaqs3qsidsnbtrk5w-3d" id="u0rlleycroyaqs3qsidsnbtrk5w-3d"></a>

스크립트에서 SDK를 사용할 수 있도록 고도몰 모든 상점에는 아래의 스크립트가 설치되어 있습니다.

```javascript
<script src="//obs-address/godomall-sdk.js" onload="GodomallSDK.setup()">
</script>
```

{% hint style="danger" %}
SDK 사용 시에는 위 스크립트가 완전히 로드된 이후에 실행될 수 있도록 반드시 다음과 같이 defer 처리를 해주셔야 합니다. **defer 처리를 하지 않는 경우 오류가 발생할 수 있습니다.**
{% endhint %}

```javascript
<script defer>
    var mySDK = GodomallSDK.init('SystemKey');
    mySDK.getMemberProfile(function(err, res) {
    });
</script>
```

GodomallSDK.init('시스템키') 스크립트를 삽입할 때마다 새로운 객체가 생성됩니다.

> ### **결과정보**

SDK 실행 시 결과는 아래와 같이 전달됩니다.

```javascript
/**
 * 조회 및 처리 실패 / err
 * return {}
 */
{
    name: '오류 명칭',
    kind: '오류 종류',
    status: 'HTTP 상태 코드',
    message: '오류 메시지',
    data: {전체 오류 정보}
}

/**
 * 조회 및 처리 성공 / res
 * return {} or []
 */
// 사용 메소드에 따라 {}객체, []배열로 전달
```

> ### **메소드 구조**

기본구조에서 추가 파라미터가 없을 경우 version = '1.0' 으로 고정됩니다.

```javascript
// 기본 구조
mySDK.[메소드](callback)

// 추가 파리미터가 있을 경우의 구조
mySDK.[메소드]({ 추가 파라미터 }, callback)
```

> ### **SDK 목록**

사용 가능한 SDK는 다음과 같습니다.

| 변수명              | 설명                 |
| ---------------- | ------------------ |
| getMemberSummary | 회원 요약 정보           |
| getMemberProfile | 회원 프로필             |
| getMallInfo      | 쇼핑몰 식별 정보          |
| getMallLocation  | 접속 페이지 정보          |
| getGoods         | 상품 번호로 상품 상세 정보 조회 |
| getCart          | 장바구니 조회            |
| getGoodsSearch   | 상품 검색              |
| getOrders        | 주문 상세 조회           |

> ### **SDK 목록 상세**

#### <mark style="background-color:green;">**회원 요약 정보**</mark>

**제공 데이터**

| 필드명                     | 데이터 형식 | 설명                   |
| ----------------------- | ------ | -------------------- |
| totalCartGoodsCount     | number | 장바구니 총 개수 (상품 기준)    |
| totalCartCount          | number | 장바구니 총 개수 (상품 옵션 기준) |
| totalOrderAmount        | number | 총 주문 금액              |
| totalOrderGoodsCount    | number | 총 주문 상품 개수           |
| totalPaymentAmount      | number | 총 결제 금액              |
| usableCouponCount       | number | 사용 가능한 쿠폰 개수         |
| totalCartQuantity       | number | 장바구니 수량 합계           |
| totalOrderCount         | number | 총 주문 수               |
| totalOrderGoodsQuantity | number | 주문 상품 수량 합계          |

**사용 예시**

```javascript
/*
 새로 생성되는 객체의 변수명은 반드시 systemKey를 발급받은 앱의 일련번호를 기재해 주셔야 합니다.
*/

<script defer>    
    var 변수명_SDK = GodomallSDK.init('systemKey');
    변수명_SDK.getMemberProfile(function(err, res) {
        if (err) {
            console.log(err.name, err.kind, err.data, err.status, err.message);
        } else {
            console.log(res);
        }
    });
    변수명_SDK.getMemberSummary(function(err, res) {
        if (res) {
            // 필요한 코드 작성
        }
    });
</script>
```

#### <mark style="background-color:green;">**회원 프로필**</mark>

**제공 데이터**

<table><thead><tr><th>필드명</th><th width="249">데이터 형식</th><th>설명</th></tr></thead><tbody><tr><td>sno</td><td>number</td><td>회원번호</td></tr><tr><td>id</td><td>string</td><td>회원 아이디</td></tr><tr><td>name</td><td>string</td><td>성명</td></tr><tr><td>email</td><td>string</td><td>이메일</td></tr><tr><td>cellPhone</td><td>string</td><td>휴대전화번호</td></tr><tr><td>mileage</td><td>number</td><td>적립금</td></tr><tr><td>deposit</td><td>number</td><td>예치금</td></tr><tr><td>grade</td><td>array</td><td>회원 등급 정보</td></tr><tr><td>     sno</td><td>number</td><td>회원 등급 번호</td></tr><tr><td>     name</td><td>string</td><td>회원 등급명</td></tr><tr><td>age</td><td>number</td><td>만 나이</td></tr><tr><td>gender</td><td>string</td><td>성별<br>- MALE : 남성<br>- FEMALE : 여성<br>- UNKNOWN : 모름</td></tr><tr><td>zipcode</td><td>string</td><td>우편번호</td></tr><tr><td>address</td><td>string</td><td>주소</td></tr><tr><td>addressDetail</td><td>string</td><td>상세주소</td></tr><tr><td>adultFlag</td><td>string</td><td>성인인증여부<br>- Y : 인증완료<br>- N : 미인증</td></tr><tr><td>mailingFlag</td><td>string</td><td>이메일 수신여부<br>- Y : 수신허용<br>- N : 수신거부</td></tr><tr><td>smsFlag</td><td>string</td><td>SMS 수신여부<br>- Y : 수신허용<br>- N : 수신거부</td></tr><tr><td>signupDateTime</td><td>string</td><td>가입 일시</td></tr></tbody></table>

**사용 예시**

```javascript
/* 
새로 생성되는 객체의 변수명은 반드시 systemKey를 발급받은 앱의 일련번호를 기재해 주셔야 합니다.
*/

<script defer>
    var 변수명_SDK = GodomallSDK.init('systemKey');
    변수명_SDK.getMemberProfile(function(err, res) {
        if (err) {
            오류 핸들링이 필요하다면 코드 작성
        } else if (res) {
            // 필요한 코드 작성
        }
    });
</script>
```

#### <mark style="background-color:green;">**쇼핑몰 식별 정보**</mark>

**제공 데이터**

<table><thead><tr><th>필드명</th><th width="249">데이터 형식</th><th>설명</th></tr></thead><tbody><tr><td>mallDomain</td><td>string</td><td>쇼핑몰 도메인</td></tr><tr><td>mallNm</td><td>string</td><td>쇼핑몰 명</td></tr><tr><td>mallNmEng</td><td>string</td><td>쇼핑몰 영문 명</td></tr><tr><td>mallUsageStatus</td><td>array</td><td>몰 사용 여부<br>- Y : 사용<br>- N : 미사용</td></tr><tr><td>     kr</td><td>string</td><td>국문몰  사용  여부<br>- Y : 사용<br>- N : 미사용</td></tr><tr><td>     us</td><td>string</td><td>영문몰  사용  여부<br>- Y : 사용<br>- N : 미사용</td></tr><tr><td>     cn</td><td>string</td><td>중문몰  사용  여부<br>- Y : 사용<br>- N : 미사용</td></tr><tr><td>     jp</td><td>string</td><td>일문몰  사용  여부<br>- Y : 사용<br>- N : 미사용</td></tr></tbody></table>

<mark style="color:red;">※ 커스터마이징 상점의 경우 쇼핑몰명 (mallNm), 쇼핑몰영문명 (mallNmEng), 해외몰 사용 여부 (mallUsageStatus)는 응답되지 않을 수 있습니다.</mark>

**사용 예시**

```javascript
<script defer>
    var 변수명_SDK = GodomallSDK.init('systemKey');
    변수명_SDK.getMallInfo(function(err, res) {
        if (res) {
            // 필요한 코드 작성
        }
    });
</script>
```

#### <mark style="background-color:green;">**접속 페이지 정보**</mark>

**제공 데이터**

<table><thead><tr><th>필드명</th><th width="249">데이터 형식</th><th>설명</th></tr></thead><tbody><tr><td>path</td><td>string</td><td>현재 경로 (기본 도메인 제외)<br>ex. /member/join_method.php</td></tr><tr><td>pathSegments</td><td>array</td><td>현재 경로에 대한 배열 정보<br>ex. goods, member,join_method..</td></tr></tbody></table>

**사용 예시**

```javascript
<script defer>
    var 변수명_SDK = GodomallSDK.init('systemKey');
    변수명_SDK.getMallLocation(function(err, res) {
        if (res) {
            // 필요한 코드 작성
        }
    });
</script>
```

#### <mark style="background-color:green;">**상품 번호로 상품 상세 정보 조회**</mark>

**요청 파라메터**

<table><thead><tr><th width="249">필드명</th><th>데이터 형식</th><th>설명</th></tr></thead><tbody><tr><td>goodsNo</td><td>string</td><td>상품 번호</td></tr></tbody></table>

**제공 데이터**

<table><thead><tr><th>필드명</th><th width="249">데이터 형식</th><th>설명</th></tr></thead><tbody><tr><td>sno</td><td>number</td><td>상품 번호</td></tr><tr><td>name</td><td>string</td><td>상품명</td></tr><tr><td>categories</td><td>array</td><td>대표  카테고리 정보</td></tr><tr><td>     code</td><td>number</td><td>카테고리 코드</td></tr><tr><td>     depth</td><td>number</td><td>카테고리 뎁스</td></tr><tr><td>     name</td><td>string</td><td>카테고리명</td></tr><tr><td>images</td><td>array</td><td>상품 이미지 목록</td></tr><tr><td>     kind</td><td>string</td><td>상품 이미지 종류</td></tr><tr><td>     sortNo</td><td>number</td><td>상품 이미지 순번</td></tr><tr><td>     url</td><td>string</td><td>상품 이미지 url</td></tr><tr><td>status</td><td>array</td><td>상품 상태</td></tr><tr><td>     sellFlag</td><td>string</td><td>판매 상태<br>- Y : 판매중<br>- N : 판매 중지</td></tr><tr><td>     soldOutFlag</td><td>string</td><td>품절 상태<br>- Y : 판매중<br>- N : 판매 중지</td></tr><tr><td>options</td><td>array</td><td>상품 옵션</td></tr><tr><td>     sno</td><td>number</td><td>상품 옵션 번호</td></tr><tr><td>     option1</td><td>array</td><td>옵션 1</td></tr><tr><td>          name</td><td>string</td><td>옵션 제목</td></tr><tr><td>          value</td><td>string</td><td>옵션 값</td></tr><tr><td>     option2</td><td>array</td><td>옵션 2</td></tr><tr><td>     option3</td><td>array</td><td>옵션 3</td></tr><tr><td>     option4</td><td>array</td><td>옵션 4</td></tr><tr><td>     option5</td><td>array</td><td>옵션 5</td></tr><tr><td>     originPrice</td><td>number</td><td>상품 옵션 가격</td></tr><tr><td>     discountAmount</td><td>number</td><td>타임세일 할인 가격</td></tr><tr><td>     stockCount</td><td>number</td><td>옵션 재고 수</td></tr><tr><td>     memo</td><td>string</td><td>옵션 메모</td></tr><tr><td>textOptions</td><td>array</td><td>텍스트 상품 옵션</td></tr><tr><td>     name</td><td>string</td><td>옵션 제목</td></tr><tr><td>     price</td><td>number</td><td>옵션 가격</td></tr><tr><td>     requiredFlag</td><td>string</td><td>옵션 필수 여부<br>- Y : 사용<br>- N : 미사용</td></tr><tr><td>addGoods</td><td>array</td><td>추가 상품</td></tr><tr><td>     title</td><td>string</td><td>추가 상품 제목</td></tr><tr><td>     requiredFlag</td><td>string</td><td>추가 상품 필수 여부<br>- Y : 필수<br>- N : 미필수</td></tr><tr><td>     items</td><td>array</td><td>추가 상품 정보</td></tr><tr><td>          sno</td><td>number</td><td>추가 상품 번호</td></tr><tr><td>          name</td><td>string</td><td>추가 상품 명</td></tr><tr><td>          price</td><td>number</td><td>추가 상품 가격</td></tr><tr><td>registerDateTime</td><td>string</td><td>등록 일시</td></tr></tbody></table>

**사용 예시**

```javascript
<script defer>
    var 변수명_SDK = GodomallSDK.init('systemKey');
    변수명_SDK.getGoods(
        {
            goodsNo: 1000
        },
        function(err, res) {
            if (res) {
                // 필요한 코드 작성
            }
        }
    });
</script>
```

#### <mark style="background-color:green;">**장바구니 조회**</mark>

**제공 데이터**

<table><thead><tr><th>필드명</th><th width="249">데이터 형식</th><th>설명</th></tr></thead><tbody><tr><td>totalAmount</td><td>number</td><td><p>상품 옵션 합산 가격</p><p><sub>(상품+옵션+텍스트옵션+추가상품)-(상품+회원+쿠폰)</sub></p></td></tr><tr><td>shipping</td><td>array</td><td>배송비 정보</td></tr><tr><td>     amount</td><td>number</td><td>배송비 금액</td></tr><tr><td>     chargeType</td><td>string</td><td>배송비 지불 방식</td></tr><tr><td>sno</td><td>number</td><td>장바구니 번호</td></tr><tr><td>addGoods</td><td>array</td><td>추가 상품 정보</td></tr><tr><td>     sno</td><td>number</td><td>추가 상품 번호</td></tr><tr><td>     price</td><td>number</td><td>추가 상품 가격 (개당)</td></tr><tr><td>     count</td><td>number</td><td>추가 상품 개수</td></tr><tr><td>registerDateTime</td><td>string</td><td>등록 일자</td></tr><tr><td>goods</td><td>array</td><td>상품 정보</td></tr><tr><td>     sno</td><td>number</td><td>상품 번호</td></tr><tr><td>     textOptions</td><td>array</td><td>텍스트 옵션</td></tr><tr><td>          sno</td><td>number</td><td>텍스트 옵션 번호</td></tr><tr><td>          price</td><td>number</td><td>텍스트 옵션 가격</td></tr><tr><td>          title</td><td>string</td><td>텍스트 옵션 제목</td></tr><tr><td>          value</td><td>string</td><td>텍스트 옵션 값</td></tr><tr><td>     count</td><td>number</td><td>상품 개수</td></tr><tr><td>     name</td><td>string</td><td>상품명</td></tr><tr><td>     option</td><td>array</td><td>상품 옵션 정보</td></tr><tr><td>          sno</td><td>number</td><td>상품 옵션 번호</td></tr><tr><td>          price</td><td>number</td><td>옵션 가격</td></tr><tr><td>          option 1~5</td><td>array</td><td>옵션 (1~5)</td></tr><tr><td>                title</td><td>string</td><td>옵션 제목</td></tr><tr><td>               value</td><td>string</td><td>옵션값</td></tr><tr><td>          discountAmount</td><td>number</td><td>옵션 할인된 가격</td></tr><tr><td>benefit</td><td>array</td><td>구매혜택 정보</td></tr><tr><td>     sale</td><td>array</td><td>구매혜택 - 할인</td></tr><tr><td>          coupon</td><td>number</td><td>구매혜택 - 쿠폰 할인 </td></tr><tr><td>          member</td><td>number</td><td>구매 혜택 - 회원 등급 할인</td></tr><tr><td>          goods</td><td>number</td><td>구매 혜택 - 상품 할인</td></tr><tr><td>     mileage</td><td>array</td><td>구매 혜택 - 마일리지</td></tr><tr><td>          coupon</td><td>number</td><td>구매 혜택 - 쿠폰 마일리지</td></tr><tr><td>          member</td><td>number</td><td>구매 혜택 - 회원 등급 마일리지</td></tr><tr><td>          goods</td><td>number</td><td>구매 혜택 - 상품 마일리지</td></tr></tbody></table>

**사용 예시**

```javascript
<script defer>     
    mySDK.getCarts(function(err, res) {
        console.log(err, res)
    });
</script>
```

**샘플 구조**

```javascript
[
  {
    "sno": 1,
    "goods": {
      "sno": 1000004033,
      "name": "쿠폰사용가능범위_카테고리B",
      "count": 1,
      "option": {
        "sno": 7462,
        "option1": {
          "title": "타이틀1",
          "value": "옵션값1"
        },
        "option2": {
          "title": "타이틀1",
          "value": "옵션값1"
        },
        "option3": {
          "title": "타이틀1",
          "value": "옵션값1"
        },
        "option4": {
          "title": "타이틀1",
          "value": "옵션값1"
        },
        "option5": {
          "title": "타이틀1",
          "value": "옵션값1"
        },
        "price": 1000,
        "discountAmount": 0
      },
      "textOptions": [
        {
          "sno": 10,
          "price": 1000,
          "title": "텍스트 옵션 제목",
          "value": "텍스트 옵션 값"
        }
      ]
    },
    "addGoods": [
      {
        "sno": 1000004033,
        "count": 1,
        "price": 1000
      }
    ],
    "benefit": {
      "sale": {
        "goods": 0,
        "member": 0,
        "coupon": 0
      },
      "mileage": {
        "goods": 0,
        "member": 0,
        "coupon": 0
      }
    },
    "totalAmount": 2000,
    "shipping": {
      "amount": 2500,
      "chargeType": "PREPAID"
    },
    "registerDateTime": "2024-08-28 14:59:04"
  }
]
```

#### <mark style="background-color:green;">**상품 검색**</mark>

**요청 파라메터**

<table><thead><tr><th width="249">필드명</th><th>데이터 형식</th><th>설명</th></tr></thead><tbody><tr><td>searchType</td><td>string</td><td>검색 타입<br><sub>GOODS_NO: 상품 번호</sub><br><sub>GOODS_NAME: 상품명</sub><br><sub>GOODS_CODE: 자체 상품 코드</sub><br><sub>MAKER_NAME: 제조사</sub><br><sub>ORIGIN_NAME: 원산지</sub><br><sub>SEARCH_WORD: 검색 키워드</sub></td></tr><tr><td>keyword</td><td>string</td><td>검색 키워</td></tr><tr><td>page</td><td>number</td><td>베이지 번호</td></tr><tr><td>pageSize</td><td>number</td><td>페이지당 항목 수</td></tr><tr><td>sort</td><td>string</td><td>정렬 기준</td></tr></tbody></table>

**제공 데이터**

| 필드명              | 데이터 형식 | 설명       |
| ---------------- | ------ | -------- |
| contents         | array  | 조회 결과    |
| sno              | number | 상품 번호    |
| price            | number | 상품 가격    |
| registerDateTime | string | 등록 일시    |
| name             | string | 상품 명     |
| discountAmount   | number | 할인 금액    |
| totalCount       | number | 전체 조회 건수 |

**사용 예시**

```javascript
<script defer>
     mySDK.getGoodsSearch({
        searchType: 'GOODS_NAME',
        keyword: '상품명',
        page: 1,
        pageSize: 100,
        sort: '+GOODS_NO,-REGISTER_DATE'
    }, function(err, res) {
        console.log(err, res)
    });
</script>

# searchType : GOODS_NO, GOODS_NAME, GOODS_CODE, MAKER_NAME, ORIGIN_NAME, SEARCH_WORD
# sort : +GOODS_NAME,+GOODS_NO,+REGISTER_DATE,-GOODS_NAME,-GOODS_NO,-REGISTER_DATE
   ('+' : 오름차순, '-' : 내림차순)
```

#### <mark style="background-color:green;">**주문 상세 조회**</mark>

**제공 데이터**

| 필드명             | 데이터 형식 | 설명                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| --------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| orderDateTime   | string | 주문 날짜                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| receiver        | array  | 배송지 목록                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| zipcode         | string | 수령인 우편번호                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| addressDetail   | string | 수령인 상세 주소                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| address         | string | 수령인 주소                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| sno             | number | 배송지 일련 번호                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| name            | string | 수령인 이름                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| message         | string | 배송 메시지                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| cellPhone       | string | 수령인 휴대폰 번호                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| method          | string | <p><sub>결제 방법</sub><br><sub>EB: 에스크로 계좌이체, EC: 에스크로 신용카드, EV: 에스크로 가상계좌, FB: 간편결제 계좌이체, FC: 간편결제 신용카드, FH: 간편결제 휴대폰, FP: 간편결제 포인트, FV: 간편결제 가상계좌, FA: 간편결제 무통장입금, GB: 무통장 입금, PB: 계좌이체, PC: 신용카드, PH: 휴대폰, PV: 가상계좌, PK: 간편결제 카카오페이, PL: 간편결제 후불결제, PN: 간편결제 네이버페이, GD: 예치금, GM: 마일리지, GZ: 전액할인, GR: 기타</sub> </p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| settleAmount    | number | 실 결제 금액                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| channel         | string | <p><sub>주문 채널</sub><br><sub>SHOP: 쇼핑몰, NAVERPAY: 네이버페이, PAYCO: 페이코, ETC: 기타</sub></p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| orderGoods      | array  | 주문 상품 목록                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| totalGoodsPrice | number | 총 상품 가격                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| quantity        | number | 상품 수량                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| sno             | number | 주문 상품 번호                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| receiverSno     | number | 배송지 일련 번호                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| goods           | array  | 상품 정보                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| sno             | number | 상품 번호                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| textOptions     | array  | 상품 텍스트 옵션 목록                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| price           | number | 텍스트 옵션 가격                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| title           | string | 텍스트 옵션 제목                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| value           | string | 텍스트 옵션 값                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| name            | string | 상품명                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| option          | array  | 상품 옵션                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| price           | number | 상품 가격                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| option 1\~5     | array  | 옵션 (1\~5)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| title           | string | 텍스트 옵션 값                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| value           | string | 상품명                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| optionPrice     | number | 옵션 가격                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| type            | string | <p>상품 유형<br><sup>GOODS: 상품, ADD\_GOODS: 추가상품</sup></p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| status          | string | <p>상품 상태<br><sub>ORDER: 입금대기, PAYMENT: 결제완료, GOODS\_READY: 상품준비중, GOODS\_PLACEMENT: 구매발주, GOODS\_RECEIVED: 상품입고, GOODS\_SHIPPED: 상품출고,  DELIVERY: 배송중</sub>,  <sub>DELIVERY\_COMPLETE: 배송완료,  SETTLE: 구매확정,  BACK\_REQUEST: 반품접수, BACK\_IN\_TRANSIT: 반송중, BACK\_ON\_HOLD: 반품보류, BACK\_COMPLETE: 반품회수완료, REFUND\_REQUEST: 환불접수, REFUND\_ON\_HOLD: 환불보류, REFUND\_COMPLETE: 환불완료, EXCHANGE\_REQUEST: 교환접수, EXCHANGE\_IN\_TRANSIT: 반송중, EXCHANGE\_REDELIVERY: 재배송중, EXCHANGE\_ON\_HOLD: 교환보류, EXCHANGE\_COMPLETE: 교환완료, PAYMENT\_ATTEMPT: 결제시도, PAYMENT\_CUSTOMER\_ABORTED:  고객결제중단,  PAYMENT\_FAILED: 결제실패, CANCEL\_AUTO: 자동취소, CANCEL\_OUT\_OF\_STOCK: 품절취소, CANCEL\_ADMIN: 관리자취소, CANCEL\_CUSTOMER\_REQUEST: 고객취소요청, ADDITIONAL\_PAYMENT\_PENDING: 추가입금대기, ADDITIONAL\_PAYMENT\_COMPLETE:  추가결제완료, ADDITIONAL\_DELIVERY\_IN\_PROGRESS: 추가배송중, ADDITIONAL\_DELIVERY\_COMPLETE:  추가배송완료, ADDITIONAL\_EXCHANGE\_COMPLETE:  교환추가완료</sub></p> |
| benefit         | array  |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| sale            | array  | 할인                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| coupon          | number | 쿠폰 할인 금액                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| member          | number | 회원 할인 금액                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| deposit         | number | 예치금 할인 금액                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| goods           | number | 상품 할인 금액                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| mileage         | number | 마일리지 할인 금액                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| apiOrderNo      | string | API 주문 번호                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| sno             | string | 주문 번호                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| orderer         | array  |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| zipcode         | string | 주문자 우편번호                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| addressDetail   | string | 주문자 상세주소                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| address         | string | 주문자 주소                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| name            | string | 주문자 이름                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| email           | string | 주문자 이메일                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| cellPhone       | string | 주문자 휴대폰 번호                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| shippingAmount  | number | 총 배송비                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| paymentDateTime | string | 결제 날짜                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| gifts           | array  | 사은품 목록                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| quantity        | number | 사은품 수량                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| name            | string | 사은품 이름                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |

**사용 예시**

```javascript
<script defer>
     mySDK.getOrders({
         orderNo: 2505121522000309
    }, function(err, res) {
        console.log(err, res)
    }); 
</script>
```

**샘플 구조**

```javascript
{
  "sno": "123456789",
  "apiOrderNo": "API123456789",
  "channel": "SHOP",
  "method": "GB",
  "orderGoods": [
    {
      "sno": 1,
      "type": "GOODS",
      "goods": {
        "sno": 101,
        "name": "테스트 상품",
        "option": {
          "option1": {
            "title": "색상",
            "value": "빨강"
          },
          "option2": {
            "title": "색상",
            "value": "빨강"
          },
          "option3": {
            "title": "색상",
            "value": "빨강"
          },
          "option4": {
            "title": "색상",
            "value": "빨강"
          },
          "option5": {
            "title": "색상",
            "value": "빨강"
          },
          "price": 1000,
          "optionPrice": 200
        },
        "textOptions": [
          {
            "title": "텍스트 옵션",
            "value": "옵션 값",
            "price": 500
          }
        ]
      },
      "quantity": 2,
      "totalGoodsPrice": 2000,
      "status": "DELIVERY_COMPLETE",
      "receiverSno": 10
    }
  ],
  "gifts": [
    {
      "name": "사은품",
      "quantity": 1
    }
  ],
  "benefit": {
    "sale": {
      "goods": 100,
      "member": 50,
      "coupon": 30,
      "mileage": 20,
      "deposit": 10
    }
  },
  "orderer": {
    "name": "홍길동",
    "zipcode": "12345",
    "address": "서울특별시 강남구 테헤란로",
    "addressDetail": "101호",
    "cellPhone": "010-1234-5678",
    "email": "test@example.com"
  },
  "receiver": [
    {
      "sno": 10,
      "name": "김철수",
      "zipcode": "54321",
      "address": "서울특별시 강남구 역삼로",
      "addressDetail": "202호",
      "cellPhone": "010-8765-4321",
      "message": "부재 시 경비실에 맡겨주세요."
    }
  ],
  "shippingAmount": 3000,
  "settleAmount": 5000,
  "orderDateTime": "2025-03-16 12:00:00",
  "paymentDateTime": "2025-03-16 12:05:00"
}
```


# \[DB] 사용 가이드

### DB Prepare Statement 바인딩 가이드

사용 예시

```php
// db 모듈 호출
$db = \App::getInstance('DB');

// bind 할 배열 생성
$arrBind = [];

// prepare statement query 생성
$query = "SELECT COUNT(*) as cnt FROM "
    . CUSTOM_TABLE 
    . " WHERE sno = ? AND customColumn = ?";

// 데이터 바인딩
// 첫 번째 ?에 $customSno가 바인딩됩니다 (정수)
$db->bind_param_push($arrBind, 'i', $customSno);
// 두 번째 ?에 $customColumn가 바인딩됩니다 (문자열)
$db->bind_param_push($arrBind, 's', $customColumn);
// 쿼리 실행
$result = $db->query_fetch($query, $arrBind, false);
unset($arrBind);

return $result['cnt'];
```

DB Prepare Statement 바인딩 사용 방법

* 쿼리문 내에서 바인딩이 필요한 값은 `?`로 표시해 주시기 바랍니다.
* 각 ?에는 bind\_param\_push로 추가한 값이 입력 순서대로 차례로 바인딩됩니다.
  * 예를 들어, 첫 번째 bind\_param\_push의 값은 쿼리의 첫 번째 ?에, 두 번째 값은 두 번째 ?에 바인딩됩니다.
* 파라미터는 `$db->bind_param_push($arrBind, '타입', $값);` 형태로 바인딩 배열에 추가해 주시면 됩니다.
* 쿼리 실행 시에는 `$db->query_fetch($query, $arrBind, false);`와 같이 바인딩 배열을 함께 전달해 주세요.
* 바인딩 타입은 아래 표를 참고하여 데이터 타입에 맞게 지정해 주시기 바랍니다.
* 이 방식을 사용하시면 SQL 인젝션을 효과적으로 방지할 수 있으며, 코드의 가독성과 유지보수성도 높아집니다.

#### 바인딩 타입 표

| 타입 | 설명                      |
| -- | ----------------------- |
| i  | int(정수)                 |
| d  | float(실수)               |
| s  | string(문자열)             |
| b  | blob(이진 데이터, 패킷 단위로 전송) |


# Memcached 사용 가이드

고도몰에서 제공하는 멤캐시를 사용하여 시스템 성능을 향상시킬 수 있는 방법을 안내 드립니다.

## 고도몰 멤캐시 소개

#### 라이브러리

* 고도몰 멤캐시 기능은 Symfony Cache v3.4 라이브러리를 바탕으로 구현되었습니다.
* [Symfony Cache v3.4 구현 코드 바로가기](https://github.com/symfony/symfony/tree/3.4/src/Symfony/Component/Cache)

#### Eviction 정책

* 고도몰 멤캐시 Eviction 정책은 LRU (Least Recently Used) 방식입니다.
* [Symfony 공식 구현에서의 Memcached 설정 예시](https://github.com/symfony/symfony/blob/0a9296a8b23360475c282cd98b1fd36e3937d259/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php#L22-L31)

## 코딩 가이드

### Using namespaces

* 고도몰에서 제공하는 캐시 함수는 SimpleCache 클래스 내부에 구현되어 있습니다.
* 캐시 함수를 사용하는 곳에서 SimpleCache namespaces 를 불러와주세요.

```php
use Framework\SimpleCache\SimpleCache;
```

### 고도몰 캐시 함수

* 고도몰에서 제공하는 캐시 함수의 종류는 총 5개입니다.
  * set()
  * has()
  * get()
  * getSet()
  * delete()

#### set

```php
/**
 * Save cache item
 *
 * @param string $key
 * @param mixed $value
 * @param int $ttl 1 or more, up to 300 (seconds)
 *
 * @return bool stating if caching succeeded or not
 */
```

* 캐시 내부에 데이터를 저장하는 함수입니다.

```php
use Framework\SimpleCache\SimpleCache;

$cacheKey = "(CACHE_KEY)";
$cacheValue = "(CACHE_VALUE)";
$ttl = 300;

$setResult = SimpleCache::init(SimpleCache::MEMCACHED)->set($cacheKey, $cacheValue, $ttl);
```

* 위와 같이 set 함수를 이용할 수 있습니다.
* ttl 값은 300을 초과할 수 없습니다.

#### has

```php
/**
 * Confirms if the cache contains specified cache item.
 *
 * @param string $key
 *
 * @return bool True if item exists in the cache, false otherwise
 */
```

* 캐시 내 조회하고자 하는 key에 대한 데이터가 있는지 확인하는 함수입니다.

```php
use Framework\SimpleCache\SimpleCache;

$cacheKey = "(CACHE_KEY)";
$hasKey = SimpleCache::init(SimpleCache::MEMCACHED)->has($cacheKey);
```

* 위와 같이 has 함수를 이용할 수 있습니다.

#### get

```php
/**
 * Fetches cache item.
 *
 * @param string $key
 *
 * @return mixed The corresponding values found in the cache, returning null if no value is present in the cache.
 */
```

* 캐시 내 저장된 데이터의 value를 반환하는 함수입니다. \
  조회하고자 하는 키값이 존재하지 않을 경우 null을 반환합니다.

```php
use Framework\SimpleCache\SimpleCache;

$cacheKey = "(CACHE_KEY)";
$cacheData = SimpleCache::init(SimpleCache::MEMCACHED)->get($cacheKey);
```

* 위와 같이 get 함수를 이용할 수 있습니다.

#### getSet

```php
/**
 * Finding the corresponding value in the cache, 
 * setting the value if it is not present in the cache, and returning the value stored in the cache.
 *
 * @param string $key
 * @param callable $callback
 * @param int $ttl 1 or more, up to 300 (seconds)
 *
 * @return mixed The corresponding values found in the cache, returning values from the cache. 
 *               If no value is present in the cache, it returns the result of the lambda function provided as the second parameter.
 */
```

* 캐시 내 조회하고자 하는 키값의 데이터가 있을 경우, 캐시 데이터를 반환하고 캐시 내 조회하고자 하는 키값의 데이터가 없을 경우, 2번째 파라미터의 람다 함수 내 로직 실행 결과를 캐시에 set 한 다음 저장된 데이터를 반환합니다.
* `$callback` 이 `null` 일 경우에는 캐시에 저장되는 값이 없으며, `null` 로 return 됩니다.

```php
use Framework\SimpleCache\SimpleCache;

$cacheKey = "(CACHE_KEY)";
$ttl = 300;
$cacheData = SimpleCache::init(SimpleCache::MEMCACHED)->getSet(
    $cacheKey,
    function () {
        $cacheValue = "(CACHE_VALUE)";
        return $cacheValue;
    },
    $ttl
);
```

* 위와 같이 getSet 함수를 이용할 수 있습니다.
* ttl 값은 300을 초과할 수 없습니다.

#### delete

```php
/**
 * Removes cache item.
 *
 * @param string $key
 *
 * @return mixed True if the items were successfully removed, false otherwise
 */
```

* 캐시 내 저장된 데이터를 삭제하는 함수입니다.

```php
use Framework\SimpleCache\SimpleCache;

$cacheKey = "(CACHE_KEY)";
$cacheData = SimpleCache::init(SimpleCache::MEMCACHED)->delete($cacheKey);
```

* 위와 같이 delete 함수를 이용할 수 있습니다.

### 개발 시 유의사항

* 캐싱 처리가 필요한 위치에서 직접 가이드에 제공된 함수를 호출하여 사용해주세요.

  ```php
  /**
   * 캐시 내 goods_benefit_config 키에 할당된 값이 있는지 확인합니다.
   * set()을 하지 않았거나 ttl(만료 시간)이 지나 캐시가 삭제된 경우에는 has() 값이 false 로 반환됩니다.
   */
  $cacheKey = "(CACHE_KEY)";
  if (SimpleCache::init(SimpleCache::MEMCACHED)->has($cacheKey)) {
      /**
       * goods_benefit_config 키에 할당된 값이 있으면
       * 캐시에서 값을 가져와 $goodsBenefitConfig 에 할당합니다.
       */
      $goodsBenefitConfig = SimpleCache::init(SimpleCache::MEMCACHED)->get($cacheKey);

  } else {
      /**
       * goods_benefit_config 키에 할당된 값이 없으면
       * 저장을 원하는 데이터를 가져와 다시 캐시에 set()을 합니다.
       * 
       * set()을 통해 goods_benefit_config 키에는 $goodsBenefitConfig 값이 300초 동안 저장됩니다.
       */
      $goodsBenefit = \App::load('\\Component\\Goods\\GoodsBenefit');
      $goodsBenefitConfig = $goodsBenefit->getConfig();
      $ttl = 300;
      SimpleCache::init(SimpleCache::MEMCACHED)->set($cacheKey, $goodsBenefitConfig, 300);
  }

  /**
   * getSet 함수를 활용한 캐시 개발 가이드입니다.
   * 1번째 파라미터의 $cacheKey에 대한 데이터가 캐시에 있을 경우,
   * 2번째 람다 함수 내 로직이 수행되지 않고 캐시 내 저장된 데이터가 반환됩니다.
   *
   * 1번째 파라미터의 $cacheKey에 대한 데이터가 캐시에 없을 경우,
   * 2번째 람다 함수 내 로직이 수행된 결과가 캐시 내 set 되며, set 된 결과가 반환됩니다.
   */
  $cacheKey = "(CACHE_KEY)";
  $ttl = 300;
  $goodsBenefitConfig = SimpleCache::init(SimpleCache::MEMCACHED)->getSet(
      $cacheKey,
      function () {
          $goodsBenefit = \App::load('\\Component\\Goods\\GoodsBenefit');
          $goodsBenefitConfig = $goodsBenefit->getConfig();
          return $goodsBenefitConfig;
      },
      $ttl
  );
  ```

{% hint style="danger" %} <mark style="color:red;">**캐싱 처리를 위한 클래스를 생성하여 기존 클래스를 상속받는 방법은 성능 저하와 클래스 간의 복잡성을 증가시킬 수 있습니다.**</mark> \ <mark style="color:red;">**가급적 가이드 내에 소개된 방식에 맞춰 활용하시는 것을 권장합니다.**</mark>
{% endhint %}


# 개발 환경 FAQ

{% hint style="warning" %}
개발 환경 이용이 처음이신가요?\
FAQ에서 개발 환경 이용 방법과 상황 별 해결 팁을 빠르게 확인해보세요.
{% endhint %}

운영 환경에 바로 소스를 수정하거나 신규 기능을 적용하면,\
잠재적인 오류나 예상치 못한 문제로 운영 중인 쇼핑몰에 영향이 발생할 수 있어요.&#x20;

고도몰 최신 패치가 적용되어 있는 개발 환경에서 운영 소스 수정 내역을 안전하게 테스트 및 검증해보세요!&#x20;

***

### 📍개발 환경 이해&#x20;

<details>

<summary><strong>개발 환경이 무엇인가요?</strong></summary>

개발 환경이란 운영 중인 실제 쇼핑몰(운영 환경)과 **동일한 운영 소스가 적용되어 있는 개발 전용 어드민과 쇼핑몰**을 의미합니다.\
고도몰에 신규 기능이 적용되면 개발 환경에도 신규 업데이트 사항이 자동 반영됩니다.\
운영 중인 상점에 커스터마이징이 적용되어 있다면, 현재 운영 중인 소스가 새로운 업데이트와 충돌이 없는지 미리 확인하실 수 있습니다. 또한 개발 환경에서는 실제 쇼핑몰에 영향을 주지 않고 **새로운 기능이나 소스 수정 사항을 안전하게 테스트**할 수 있습니다.\
개발 환경에서 커스터마이징 소스에 대한 테스트와 검증이 완료되면, 상점에서 직접 **운영 환경에 안정적으로 배포**할 수 있습니다.  (배포 기능 출시 예정)

</details>

<details>

<summary><strong>개발 환경과 운영 환경의 차이가 무엇인가요?</strong></summary>

운영 환경은 실제 쇼핑몰이 서비스되는 공간이며, 개발 환경은 운영 환경의 운영 소스를 복제해 테스트 및 소스 수정을 진행할 수 있도록 별도로 제공되는 환경입니다.\
\
개발 환경에서 고도몰의 최신 소스와의 충동 여부를 바로 확인하실 수 있도록 최초 개발 환경 사용 신청 시점의 운영 중인 상점의 소스를 그대로 복제하여 개발 환경에 적용해 드립니다.

다만, 실 운영 중인 상품, 주문, 회원 정보 등의 데이터는 안전한 개인정보 관리 및 데이터 운영을 위해 복사하여 제공되지 않습니다.\
대신 바로 테스트가 가능하도록 샘플 데이터를 제공해드리고 있으며, 샘플 데이터 상세 항목은 하단 표를 참고해 주세요.

<table><thead><tr><th width="157"></th><th>개발 환경 샘플 데이터</th><th data-hidden></th></tr></thead><tbody><tr><td>상품</td><td>샘플 상품 5개 </td><td></td></tr><tr><td>카테고리</td><td>샘플 카테고리 1개</td><td></td></tr><tr><td>주문</td><td>주문 0건</td><td></td></tr><tr><td>회원</td><td>회원 0명</td><td></td></tr><tr><td>운영자</td><td>최고 운영자 1명<br>(운영 환경의 최고 운영자 정보)</td><td></td></tr><tr><td>스킨</td><td>모먼트 스킨<br>(무료스킨 다운로드 가능) </td><td></td></tr><tr><td>PG 및 부가서비스</td><td>별도 세팅 필요</td><td></td></tr><tr><td>운영 소스</td><td>개발 환경 생성 당시 운영 환경의 운영 소스와 동일 <br>- *_godomall_com/module: 프로그램 소스<br>- *_godomall_com/admin: 관리자 스킨</td><td></td></tr><tr><td>DB(데이터베이스)</td><td>개발 환경 생성 당시 운영 환경의 DB와 동일</td><td></td></tr></tbody></table>

</details>

<details>

<summary><strong>개발 환경은 어떻게 이용할 수 있나요?</strong></summary>

어드민 내 \[개발 소스 관리 > Support > 개발 환경 사용설정]에서 **사용하기 버튼을 클릭하시면 개발 환경 세팅이 자동 접수**됩니다.\
접수 후 **수 분 내로 개발 환경이 생성되며**, 메일과 알림톡(SMS)을 통해 개발 환경 세팅 완료 소식을 안내드립니다.

생성된 개발 환경 정보와 접근 경로는 메일과 알림톡(SMS), NHN 커머스 마이페이지에서 확인하실 수 있습니다.

</details>

<details>

<summary><strong>개발 환경 사용 설정이 일시적으로 제한되었는데 어떻게 해결하나요?</strong></summary>

개발 환경을 생성하기 어려운 경우 사용 설정이 일시적으로 제한됩니다. 개발 환경 사용을 원하시면 각 제한 사유 별로 아래 방법 대로 수정해 주세요. \
(쇼핑몰 내 MyISAM을 사용하거나 PK가 없는 테이블은 개발 환경 사용 신청 시 안내드린 참고 테이블에서 확인하실 수 있습니다.)

| 제한 사유                            | 해결 방법                                                                                                                                          |
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| 상점 최고운영자 계정과 NHN 커머스 통합회원 정보 미연동 | <ol><li>상점 최고운영자 계정으로 고도몰  관리자에로그인합니다.</li><li>메인 페이지의 통합회원 연동 팝업에서 \[NHN 커머스 통합회원 연동하러 가기] 버튼을 클릭하여 간편하게 최고운영자 계정과 통합회원 정보를 연동합니다. </li></ol> |
| 쇼핑몰 내 MyISAM 엔진을 사용하는 테이블 존재     | <ol><li>MyISAM 테이블을 삭제하거나 InnoDB로 마이그레이션합니다. </li></ol>                                                                                        |
| 쇼핑몰 내 PK가 없는 테이블 존재              | <ol><li>PK가 없는 테이블에 PK 컬럼을 추가합니다.</li></ol>                                                                                                    |

안내된 방법으로 해결이 어려우신 경우, 1:1문의로 문의해 주시면 확인 후 안내드리겠습니다.\
[1:1문의 바로가기 > ](https://www.nhn-commerce.com/support/inquiry/contact)

</details>

<details>

<summary><strong>개발 환경 사용 신청했는데 메일/알림톡(SMS)이 오지 않았어요.</strong></summary>

사용 신청  후 개발 환경이 구축되는 데 몇 분이 소요되며, 쇼핑몰 데이터가 많을 경우 최대 1시간까지 소요될 수 있습니다.

구축이 완료된 시점에 개발 환경 사용을 신청한 개발 담당자님과 쇼핑몰 최고 운영자님께 메일, 알림톡(SMS)을 발송해 드리고 있습니다.&#x20;

</details>

<details>

<summary><strong>개발 환경에 어떻게 접속하나요?</strong></summary>

개발 환경은 운영 환경의 기본 도메인 뒤에 dev가 추가된 형태로 제공됩니다. 운영 환경과 개발 환경을 혼동하지 않도록, 작업 전 반드시 접속한 상점이 개발 환경인지 확인해 주세요.&#x20;

* 운영 환경 쇼핑몰기본 도메인 : example.godomall.com
* 개발 환경 쇼핑몰 기본 도메인 : example**dev**.godomall.com
* 개발 환경 관리자 기본 도메인 : gdadmin-example**dev**.godomall.com&#x20;
  * 쇼핑몰 최고운영자의 NHN 커머스 통합 계정으로 개발 환경 관리자에 로그인할 수 있습니다.&#x20;

</details>

<details>

<summary><strong>개발 환경은 주문, 결제 테스트가 가능한가요?</strong> </summary>

> 비슷한 문의 : PG나 부가서비스 설정은 따로 다시 해야 하나요?

개발 환경에서도 주문 및 결제 테스트가 가능합니다. 단, 운영 환경의 PG(전자결제) 정보가 개발 환경으로 이관되지 않기 때문에\
신용카드, 계좌이체, 가상계좌, 에스크로, 간편결제 등을 진행하시려면 개발 환경에 별도로 PG를 연동해 주셔야 합니다.

PG 결제 외 무통장 입금, 마일리지/예치금 결제 테스트는 별도 설정 없이 바로 이용하실 수 있습니다.

[PG 신청 바로가기 > ](https://www.nhn-commerce.com/main/payments)

</details>

<details>

<summary><strong>개발 환경의 FTP/DB 접속 정보가 궁금해요.</strong></summary>

개발 환경의 FTP/DB 접속 정보는 쇼핑몰 최고운영자의 \[NHN 커머스 마이페이지 > 쇼핑몰 관리 > 쇼핑몰 목록 > FTP/DB 관리]에서 확인하실 수 있습니다.

[NHN 커머스 바로가기 >](https://www.nhn-commerce.com/)\
[FTP/DB 이용 가이드 바로가기 >](https://godomall-help.nhn-commerce.com/faq/manage/shop-information)

</details>

<details>

<summary><strong>개발 환경을 하나 더 받을 수 없나요?</strong></summary>

개발 환경은 운영 쇼핑몰 당 1개만 개설 가능합니다.&#x20;

</details>

<details>

<summary><strong>개발 환경은 이용일 연장이 가능한가요?</strong> </summary>

개발 환경은 이용 동의일로부터 **최대 3개월 동안** 이용 가능합니다.\
개발 환경 이용일을 연장하기를 원하시는 경우 1:1문의로 문의해 주시면 확인 후 안내해드리겠습니다.

[1:1문의 바로가기 > ](https://www.nhn-commerce.com/support/inquiry/contact)

</details>

<details>

<summary><strong>개발 환경은 꼭 이용해야 하나요?</strong></summary>

개발환경은 운영에 꼭 필요한 필수 조건은 아닙니다. 다만 쇼핑몰 기능을 커스터마이징하여 사용하시는 경우, 개발 환경을 이용하시는 것을 권장해드립니다.  \
\
개발 환경에서는 고도몰 최신 패치가 항시 적용되기 때문에, 개발 환경에 커스터마이징 소스를 반영해 두었을 때 주문, 가입 등 핵심 기능이 안정적으로 동작하는지 미리 확인할 수 있습니다.

운영 중인 쇼핑몰에 영향없이 테스트가 가능하므로, 커스터마이징 범위가 넓거나 소스 수정이 잦은 경우라면 개발 환경을 활용해 보시는 걸 추천해드립니다.

</details>

### 📍운영 소스 수정&#x20;

<details>

<summary><strong>개발 가이드나 매뉴얼 같은 것이 있나요?</strong></summary>

NHN 커머스에서는 고객님이 쇼핑몰 운영에 영향을 미치지 않는 선에서 안정적으로 소스를 수정하실 수 있도록 커스터마이징 가이드를 제공하고 있습니다.\
\
반드시 고도몰 커스터마이징 가이드에서 안내되는 내용에 따라서 수정을 해야만 고도몰 업데이트 패치가 정상적으로 작동하며, 커스터마이징 가이드 내용이 아닌 임의적으로 수정할 경우 적용되지 않을 수 있습니다.

[커스터마이징 가이드 바로가기 > ](https://devcenter-help.nhn-commerce.com/)

</details>

<details>

<summary><strong>운영 소스 검증에서 안내 받은 업데이트 필요 항목 수정 시에 다른 기능은 문제가 없나요?</strong></summary>

> 비슷한 문의 : 개발 환경에서 기존 커스터마이징 이슈까지 같이 확인할 수 있나요?

운영 소스 검증에서는 고도몰 신규 기능의 패치 범위를 기준으로 쇼핑몰 내 해당 파일의 커스터마이징 가이드 준수 여부를 확인하고 있습니다.\
다만 업데이트마다 패치 범위가 달라질 수 있으므로, 전체 운영 소스를 함께 점검해  주시는 것을 권장드립니다.

또한 \[개발소스관리 > 개발 작업소스 보기]에서 '소스검증 Beta' 기능을 이용하시면, 개발 환경에서 수정 중인 소스의 커스터마이징 가이드 준수 여부를 확인하실 수 있습니다.

운영 소스를 사전 정비해 두면, 업데이트 후에도 쇼핑몰의 기존 기능이 안정적으로 유지됩니다. 지속적인 업데이트를 고려하신다면 커스터마이징 가이드 준수 상태를 주기적으로 확인해 주세요.

</details>

<details>

<summary><strong>신규 기능이 왜 우리 상점에는 자동 패치되지 않나요?</strong></summary>

고도몰은 고객님의 쇼핑몰 운영에 불편을 최소화하고자, 업데이트 이후 발생할 수 있는 잠재적인 문제를 사전에 점검하고 있습니다.\
이 과정에서 쇼핑몰 운영 소스와 업데이트 패치가 충돌할 가능성이 확인되면, 문제가 발생할 수 있는 위험을 줄이기 위해 신규 기능을 자동으로 패치하지 않고 있습니다.

신규 기능을 자동 패치로 이용하고 싶으시다면, 아래 절차를 따라 진행해 주세요.

1. 개발 환경의 운영소스 검증에서 수정 필요한 파일과 가이드 메시지를 확인해 주세요.
2. 개발 환경 운영 소스를 고도몰 커스터마이징 가이드에 맞게 수정 후  주문, 가입 등 기본 기능이 정상 작동하는지 확인해 주세요.
3. 운영 소스 검증에서 더 이상 수정 필요 파일이 없다면, 소스 배포 관리에서 개발 환경 소스를 운영 환경으로 배포해 신규 기능이 안전하게 반영해 보세요. (배포 기능 출시 예정)

</details>

<details>

<summary><strong>기능 업데이트를 받지 않거나 스킨 패치를 하지 않으면 어떤 문제가 생기나요?</strong></summary>

기능 업데이트나 스킨 패치를 장기간 진행하지 않으면, 쇼핑몰 운영에 도움이 되는 고도몰의 최신 기능을 이용하지 못하는 불편이 생길 수 있습니다.\
또한 보안 패치가 적용되지 않아, 해킹 등 보안 위험에 노출될 가능성도 높아집니다.

업데이트와 스킨 패치는 쇼핑몰 기능 안정성과 보안 강화를 위해 중요한 작업이므로, 개발 환경에서 소스를 수정, 점검한 뒤 정기적으로 기능 업데이트와 스킨 패치를 진행해 주실 것을 권장드립니다.

</details>

<details>

<summary><strong>소스 수정이 직접 어려운데 비용을 드릴 테니 고도몰에서 해주시면 안될까요?</strong></summary>

NHN 커머스에서 소스 수정을 대행해드리는 서비스는 제공하지 않습니다.\
소스 수정이 필요한 경우, NHN 커머스 협력 업체를 통해 유지보수 서비스를 이용하실 수 있습니다.

유지보수 서비스란 쇼핑몰 운영 중 발생하는 기능 개선이나 소스 수정 작업을 전문적으로 지원해드리는 서비스입니다.

[유지보수 서비스 바로가기 > ](https://design.nhn-commerce.com/custom/brandshop-list.php)

</details>


# include 사용 가이드

관리자 스킨(.php) 또는 Front(.html) 스킨 내 include  사용 가이드

> 파일 경로를 직접 include 하지 않고
>
> 연관된 Controller를 통해 include 대상을 전달하는 방식으로 구현한다.

#### 적용 목적

* 스킨과 비즈니스 로직 분리
* 경로 변경 시, 스킨 수정 최소화
* 보안 및 유지보수성 확보
* 관리자 스킨 구조 일관성 유지

### ⚠️ 잘못된 사용 예시

```
<?php
include "/goods/goods_register.php";
?>

```

### ✅ 권장 사용 방식

* include 대상은 Controller에서 정의
* 스킨에서는 전달받은 변수만 사용

#### 관리자 스킨

```
<?php
...
include($testPage);
?>
```

#### Controller

```
<?php
...
$this->getView()->setDefine('testPage', '{연결하고자 하는 파일 경로}');
?>
```

#### 예시

```
<?php
...
$this->getView()->setDefine(
    'testPage',
    $this->getPath() . '/goods/goods_register.php'
);
?>
```


