> For the complete documentation index, see [llms.txt](https://devcenter-help.nhn-commerce.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://devcenter-help.nhn-commerce.com/php.md).

# PHP 버전업에 따른 변경점

PHP가 기존 버전에서 8버전으로 업그레이드되었습니다.\
개발 언어 자체의 세세한 변경점은 [PHP 공식 매뉴얼](https://www.php.net/manual/en/history.php)을 참고해주세요.\
여기서는 **고도몰에서 달라진 특징만** 쉽게 설명드리겠습니다.

### 1. 엄격한 타입 관리

이전  버전에서는 숫자가 아닌 값을 숫자처럼 계산하면 “경고(Warning)”만 나왔습니다.\
예를 들어, 아래와 같은 코드가 있었습니다:

```php
count('2'); // 문자열 "2"를 count()에 넣음
```

* 이전  버전 → **경고만 발생하고 실행은 계속됨**
* PHP 8 → **경고가 아니라 에러가 발생하여 실행이 멈춤**

즉, PHP가 더 엄격하게 데이터를 구분하게 된 것입니다.

***

고도몰에서는 이전  버전의 느슨한 타입 체크 (특히 널, 배열) 에서 8버전에 엄격한 타입 체크로 변경 시, 기존 소스에 위반되는 문법들이 대부분 허용해 왔으므로 사이드이펙트 우려, 이를 방지하고자 `gd_count()`라는 자체 함수가 임시 적용되어 있습니다.

```php
// PHP 8버전 호환을 위해 변경됨
gd_count('2'); // 안전하게 동작
```

{% hint style="danger" %}
앞으로 원본 소스에서 잘못된 부분들을 점차 수정하면, 다시 PHP 기본 함수(`count()`)로 돌려놓을 예정입니다.\
즉, **현재는 임시 함수(`gd_count`)가 쓰이는 곳이 있지만 해당 함수는 deprecate 될 예정**입니다.

튜닝 시 데이터 타입을 고려하여 개발하여 **gd\_ 를 사용하지 않도록 합니다.**
{% endhint %}

&#x20;

### 2.  암호화 모듈&#x20;

Mcrypt 모듈이 더이상 지원되지 않습니다.

[*DEPRECATED* as of PHP 7.1.0 and *REMOVED* as of PHP 7.2.0](https://www.php.net/manual/en/function.mcrypt-encrypt.php)

&#x20;모든 Mcrypt 암호화는 openSSL 등 다른 암호화 알고리즘을 사용하도록 변경되었습니다.

<details>

<summary>mcrypt -> openssl 교체 작업 예시 코드</summary>

```
<?php
function encrypt($plaintext, $secret_key)
{
    $key = hash('sha256', $secret_key, true);
    $iv  = random_bytes(openssl_cipher_iv_length('AES-256-CBC'));

    $encrypted = openssl_encrypt(
        $plaintext,
        'AES-256-CBC',
        $key,
        OPENSSL_RAW_DATA,
        $iv
    );

    return base64_encode($iv . $encrypted);
}

function decrypt($ciphertext_base64, $secret_key)
{
    $key  = hash('sha256', $secret_key, true);
    $data = base64_decode($ciphertext_base64);
    $iv_length = openssl_cipher_iv_length('AES-256-CBC');

    $iv = substr($data, 0, $iv_length);
    $ciphertext = substr($data, $iv_length);

    $decrypted = openssl_decrypt(
        $ciphertext,
        'AES-256-CBC',
        $key,
        OPENSSL_RAW_DATA,
        $iv
    );

    return $decrypted;
}

// 사용 예시
$secret = 'my-secret-key';
$plain  = 'Hello World';

$enc = encrypt($plain, $secret);
$dec = decrypt($enc, $secret);

echo "ENC: $enc\n";
echo "DEC: $dec\n";
```

</details>

### 3. 0으로 나누기 방지 (안전 나누기)

PHP 8버전에서는 **나누기 연산**에서 분모(나누는 값)가 0이면 **즉시 에러**가 발생합니다.\
쇼핑몰 지표(전환율, 평균값 등)를 계산할 때 분모가 0이 될 수 있어, 화면이 멈추거나 오류가 노출될 위험이 있습니다.

이 문제를 막기 위해 **고도몰은** 다음 헬퍼를 제공합니다:

<pre class="language-php"><code class="lang-php">use Framework\Utility\NumberUtils;
 /*
     * 나누기 연산 시 피제수에 0을 주입할 경우 발생하는 division by zero 오류 방어
     * @param mixed $dividend 피제수
     * @param mixed $divisor 제수
     * @param null|string $returnZeroType 0으로 강제 리턴될 경우 지정한 타입으로 강제 형변환
     * @return float|int $quotient 몫
<strong> */
</strong>NumberUtils::divisionExceptZero($numerator, $denominator, $fallback = 0, $scale = null);
</code></pre>

### 4. 외부 PHP 라이브러리 호환성 확인

상점에 직접 설치한 외부 PHP 라이브러리가 있다면 **PHP 8 호환 여부를 확인하고 필요 시 업데이트**해 주세요.

> 직접 설치한 라이브러리는 각 공식 저장소에서 PHP 8 지원 버전을 확인해 주세요.

### 5. 소스 튜닝 관련 확인

#### 🗑️ 의미 없는 튜닝 파일 정리 <a href="#ef-b8-8f-ec-9d-98-eb-af-b8-ec-97-86-eb-8a-94-ed-8a-9c-eb-8b-9d-ed-8c-8c-ec-9d-bc-ec-a0-95-eb-a6-ac" id="ef-b8-8f-ec-9d-98-eb-af-b8-ec-97-86-eb-8a-94-ed-8a-9c-eb-8b-9d-ed-8c-8c-ec-9d-bc-ec-a0-95-eb-a6-ac"></a>

불필요한 튜닝 파일이 많을수록 이전 작업 시간이 늘어나고 오류 가능성이 높아집니다.\
아래 기준에 해당하는 파일은 **사전에 제거**해 주세요.

| 유형     | 설명                                | 예시                                                  |
| ------ | --------------------------------- | --------------------------------------------------- |
| 빈 클래스  | 상속만 받고 추가 정의가 없는 파일               | `class MyOrder extends GdOrder {}` (본문 없음)          |
| 빈 생성자  | `parent::__construct()` 호출만 있는 파일 | `function __construct() { parent::__construct(); }` |
| 빈 컨트롤러 | `parent::index()` 호출만 있는 파일       | `function index() { parent::index(); }`             |
| 복붙 파일  | 원본 소스와 내용이 완전히 동일한 파일             | diff 결과가 없는 튜닝 파일                                   |

**📂 상점 튜닝 경로**

| 구분     | 경로              |
| ------ | --------------- |
| 관리자 스킨 | `{상점}/admin/*`  |
| 고도몰 로직 | `{상점}/module/*` |

#### 🔤 PHP8 예약어 충돌 확인 <a href="#php8-ec-98-88-ec-95-bd-ec-96-b4-ec-b6-a9-eb-8f-8c-ed-99-95-ec-9d-b8" id="php8-ec-98-88-ec-95-bd-ec-96-b4-ec-b6-a9-eb-8f-8c-ed-99-95-ec-9d-b8"></a>

PHP8에서 새롭게 예약어로 지정된 단어를 클래스명·함수명으로 사용하고 있다면 **수동으로 변경**해야 합니다.

**💥 충돌 대상 예약어**

```
match  /  enum  /  readonly  /  never  /  fn  /  final
```

**수정 예시**

```
// ❌ 충돌 — 'match'는 PHP8 예약어
class match {
    public function fn() { ... }
}

// ✅ 수정 — 예약어와 겹치지 않는 이름으로 변경
class MatchHandler {
    public function processFilter() { ... }
}
```

### 6. DB 커스터마이징 관련 확인

#### 🔑 PK 없는 커스텀 테이블 <a href="#pk-ec-97-86-eb-8a-94-ec-bb-a4-ec-8a-a4-ed-85-80-ed-85-8c-ec-9d-b4-eb-b8-94" id="pk-ec-97-86-eb-8a-94-ec-bb-a4-ec-8a-a4-ed-85-80-ed-85-8c-ec-9d-b4-eb-b8-94"></a>

직접 생성한 커스텀 테이블에 **Primary Key(PK)가 없으면 MySQL 8 이전 시 DDL 오류가 발생**합니다.\
이전 전에 해당 테이블에 PK를 추가해 주세요.

```
-- PK 없는 테이블 확인
SELECT TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = '{your_db_name}'
  AND TABLE_NAME NOT IN (
    SELECT TABLE_NAME
    FROM information_schema.TABLE_CONSTRAINTS
    WHERE CONSTRAINT_TYPE = 'PRIMARY KEY'
      AND TABLE_SCHEMA = '{your_db_name}'
  );

-- PK 추가 (예시)
ALTER TABLE 커스텀_테이블명 ADD PRIMARY KEY (id);
```

#### ⚙️ MyISAM 엔진 사용 테이블 <a href="#ef-b8-8f-myisam-ec-97-94-ec-a7-84-ec-82-ac-ec-9a-a9-ed-85-8c-ec-9d-b4-eb-b8-94" id="ef-b8-8f-myisam-ec-97-94-ec-a7-84-ec-82-ac-ec-9a-a9-ed-85-8c-ec-9d-b4-eb-b8-94"></a>

MySQL 8 환경에서는 **MyISAM 엔진을 사용할 수 없습니다.**\
직접 생성한 커스텀 테이블 중 MyISAM을 사용하는 경우 업그레이드 전에 **InnoDB로 변경**해 주세요.

```
-- MyISAM 테이블 확인
SELECT TABLE_NAME, ENGINE
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = '{your_db_name}'
  AND ENGINE = 'MyISAM';

-- InnoDB로 변경
ALTER TABLE 테이블명 ENGINE = InnoDB;
```

#### 🔄 백업 테이블 컬럼 동기화 <a href="#eb-b0-b1-ec-97-85-ed-85-8c-ec-9d-b4-eb-b8-94-ec-bb-ac-eb-9f-bc-eb-8f-99-ea-b8-b0-ed-99-94" id="eb-b0-b1-ec-97-85-ed-85-8c-ec-9d-b4-eb-b8-94-ec-bb-ac-eb-9f-bc-eb-8f-99-ea-b8-b0-ed-99-94"></a>

원본 테이블(예: `es_order`, `es_orderHandle`)에 컬럼을 추가했다면,\
백업 테이블(`es_*Original`)에도 **동일하게 컬럼을 반영**해 주세요.

> 🔴 동기화가 누락되면 이전 후 **취소·교환·반품 등 클레임 처리 시 오류가 발생**합니다.

**동기화 누락 시 발생 문제 예시**

```
원본 테이블: es_order          (컬럼 A, B, C, D 추가됨)
백업 테이블: es_orderOriginal  (컬럼 A만 반영됨)
→ 이전 후 취소/교환/반품 처리 시 "Unknown column 'B'" 오류 발생
```

**컬럼 추가 예시**

```
-- 원본에 추가한 컬럼을 백업 테이블에도 동일하게 반영
ALTER TABLE es_orderOriginal
  ADD COLUMN custom VARCHAR(255) DEFAULT '' AFTER order_id;
```

### 7. 상품 등록/수정 관련 확인

#### 🔍 현재 상점이 어떤 화면을 사용 중인지 확인하는 방법 <a href="#ed-98-84-ec-9e-ac-ec-83-81-ec-a0-90-ec-9d-b4-ec-96-b4-eb-96-a4-ed-99-94-eb-a9-b4-ec-9d-84-ec-82-ac-e" id="ed-98-84-ec-9e-ac-ec-83-81-ec-a0-90-ec-9d-b4-ec-96-b4-eb-96-a4-ed-99-94-eb-a9-b4-ec-9d-84-ec-82-ac-e"></a>

아래 쿼리로 현재 상점의 상품 등록 화면 설정을 확인할 수 있습니다.

```
SELECT * FROM es_config WHERE groupCode = 'goods' AND code = 'option_1903';
```

| 쿼리 결과                   | 사용 중인 화면                                  |
| ----------------------- | ----------------------------------------- |
| 결과 없음 또는 `{"use": "n"}` | `goods_register.php` (기존 화면)              |
| `{"use": "y"}`          | `goods_register_option_stock.php` (개선 화면) |

***

#### 🖥️ 화면 차이 <a href="#ef-b8-8f-ed-99-94-eb-a9-b4-ec-b0-a8-ec-9d-b4" id="ef-b8-8f-ed-99-94-eb-a9-b4-ec-b0-a8-ec-9d-b4"></a>

**`goods_register.php` (기존 화면)**

* 관리자 > 상품 등록 화면에서 **옵션 탭**과 **재고 탭**이 **별도로 분리**되어 있습니다.
* 옵션을 설정한 뒤 별도 탭으로 이동하여 재고를 입력하는 방식입니다.

**`goods_register_option_stock.php` (개선 화면)**

* **옵션과 재고가 하나의 탭에 통합**되어 있습니다.
* 옵션 설정 시 재고 수량을 바로 같은 화면에서 함께 입력할 수 있습니다.

***

#### ⚠️ 기존 화면(`goods_register.php`) 사용 시 주의사항 <a href="#ef-b8-8f-ea-b8-b0-ec-a1-b4-ed-99-94-eb-a9-b4goods_registerphp-ec-82-ac-ec-9a-a9-ec-8b-9c-ec-a3-bc-ec" id="ef-b8-8f-ea-b8-b0-ec-a1-b4-ed-99-94-eb-a9-b4goods_registerphp-ec-82-ac-ec-9a-a9-ec-8b-9c-ec-a3-bc-ec"></a>

`goods_register.php` 파일을 직접 **튜닝하여 사용하는 상점**은 이전 후 상품 등록/수정 기능에서 오류가 발생할 수 있습니다.

* 해당 파일을 튜닝한 경우 이전 전후로 **별도 QA 및 수정이** 필요합니다
* ✅ `goods_register_option_stock.php`로의 **변경을 권장합니다**

#### 🔧 개선 화면으로 전환하는 방법 <a href="#ea-b0-9c-ec-84-a0-ed-99-94-eb-a9-b4-ec-9c-bc-eb-a1-9c-ec-a0-84-ed-99-98-ed-95-98-eb-8a-94-eb-b0-a9-e" id="ea-b0-9c-ec-84-a0-ed-99-94-eb-a9-b4-ec-9c-bc-eb-a1-9c-ec-a0-84-ed-99-98-ed-95-98-eb-8a-94-eb-b0-a9-e"></a>

아래 방법으로 처리할 수 있습니다.

```
INSERT INTO es_config VALUES ('goods','option_1903','{\"use\": \"y\"}',now(),NULL);
```

### 8. 이미지/CDN 관련 확인

※ **Proplus** 서버의 경우 해당 사항은 별도 확인하지 않으셔도 됩니다.

상품 상세 설명을 **HTML 탭으로 직접 편집**하면서 이미지 URL을 절대 경로로 입력한 경우, \
버전 업그레이드 후 이미지가 정상 표시되지 않을 수 있습니다.

#### 🔍 왜 문제가 되나요? <a href="#ec-99-9c-eb-ac-b8-ec-a0-9c-ea-b0-80-eb-90-98-eb-82-98-ec-9a-94" id="ec-99-9c-eb-ac-b8-ec-a0-9c-ea-b0-80-eb-90-98-eb-82-98-ec-9a-94"></a>

고도몰은 서버 환경에 따라 CDN 도메인이 다릅니다.

| 환경             | CDN URL 형식          | 예시                                                    |
| -------------- | ------------------- | ----------------------------------------------------- |
| **Pro 서버**     | IP가 포함된 CDN 서비스 도메인 | `https://cdn-pro-web-250-211.cdn-nhncommerce.com/...` |
| **Proplus 서버** | 업체 실제 도메인 기반 URL    | `https://my-shop-domain.com/...`                      |

서버 환경에 따라 CDN 도메인이 달라지기 때문에, HTML 탭에서 절대 URL로 입력된 이미지는 **업그레이드 이후 깨질 수 있기 때문에 미리 점검 부탁드립니다.**

#### 🛠️ 확인 방법 <a href="#ef-b8-8f-ed-99-95-ec-9d-b8-eb-b0-a9-eb-b2-95" id="ef-b8-8f-ed-99-95-ec-9d-b8-eb-b0-a9-eb-b2-95"></a>

상품 상세 설명 데이터에 절대 CDN URL이 포함된 경우가 있는지 **DB에서 직접 확인**해 주세요.

```
-- 상품 상세 설명에 절대 CDN URL이 포함된 상품 확인
SELECT *
FROM es_goods
WHERE goodsDescription LIKE '%https://cdn%'
   OR goodsDescription LIKE '%http://cdn%';
```

해당 데이터가 존재한다면 아래와 같이 절대 URL을 **상대 URL로 수정**해 주세요.

```
<!-- ❌ 절대 URL — 이전 후 도메인이 바뀌면 깨짐 -->
<img src="https://cdn-pro-web-123-456.cdn-nhncommerce.com/my_shop/goods/detail.jpg">

<!-- ✅ 상대 URL — 환경에 관계없이 정상 작동 -->
<img src="/goods/detail.jpg">
```

### 9. 주문 개선 플래그 확인

#### 📌 개요

주문 개선(신주문, `OrderNew`) 구조는 PHP 7 / 8 공통으로 적용되어 있습니다. 다만 **GODO26 버전에서 추가된 신규 주문 관련 기능(정기결제, 선물하기 등)** 은 이 `OrderNew` 기준으로 처리되도록 작업되어 있어, 해당 기능을 사용하려면 상점이 **주문 개선이 적용된 상태(`T`)** 여야 합니다.

상점별 적용 여부는 다음 플래그로 관리됩니다.

* **📁 파일:** `config/orderNew.php` → `{"flag":"T"}` / `{"flag":"F"}`

| 플래그 | 상태                   | GODO26 신규 주문 기능(정기결제·선물하기 등) |
| --- | -------------------- | ---------------------------- |
| `F` | 주문 개선 **적용 전** (레거시) | ❌ 사용 불가                      |
| `T` | 주문 개선 **적용 완료**      | ✅ 정상 사용                      |

#### ✅ 권장 조치

**신규 주문 기능을 사용하려면 먼저 플래그 상태를 확인하세요.**

* **현재 `T`** → 신규 주문 기능 사용 가능 (추가 조치 불필요)
* **현재 `F`** → ⚠️ **`T`로 전환**해야 정기결제·선물하기 등 신규 주문 기능을 사용할 수 있습니다.

#### 🔍 플래그 상태 확인 방법

`config/orderNew.php` 파일의 `flag` 값으로 확인합니다.

#### 🔧 `T`로 전환하는 방법

관리자 **기본설정 ▸ 주문 정책 ▸ 주문 기본 설정** 화면에서 **주문 개선(업그레이드) 적용** 기능을 제공합니다. (최고운영자 기준)

* 현재 `F`인 상점은 화면에서 적용 가능 여부를 점검한 뒤, **주문 업그레이드 적용**을 실행하면 전환됩니다.
* 전환 시 `config/orderNew.php`가 `{"flag":"T"}`로 기록되고, 주문 정책(`order.upgrade`)도 `T`로 저장되어 이후 신주문(`OrderNew`) 로직이 적용됩니다.

**⚠️ 전환 전 점검 사항 (화면에서 자동 점검·안내)**

주문 관련 소스를 튜닝한 상점은 전환 전 반드시 확인하세요. 아래 항목은 관리자 화면이 자동으로 점검해 안내합니다.

* **주문 관련 튜닝 파일 존재 여부** — 다음 파일이 `module/` 하위에 튜닝되어 있으면, 신주문(`OrderNew`) 구조와 충돌할 수 있어 사전 점검이 필요합니다.
  * `Controller/Front/Goods/NaverPayController.php`
  * `Controller/Front/Order/OrderPsController.php`
  * `Controller/Mobile/Order/OrderPsController.php`
  * `Component/Order/Order.php`
  * `Component/Order/OrderAdmin.php`
  * `Component/Order/OrderNew.php`
  * `Component/Order/OrderAdminNew.php`


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://devcenter-help.nhn-commerce.com/php.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
