์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿ›’ WooCommerce ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐœ๋ฐœ๊ณผ ์›Œ๋“œํ”„๋ ˆ์Šค ์‡ผํ•‘๋ชฐ ํ™•์žฅ ์™„๋ฒฝ ๊ฐ€์ด๋“œ

๐Ÿ›’ WooCommerce ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐœ๋ฐœ๊ณผ ์›Œ๋“œํ”„๋ ˆ์Šค ์‡ผํ•‘๋ชฐ ํ™•์žฅ ์™„๋ฒฝ ๊ฐ€์ด๋“œ

์นœ๊ตฌ์ฒ˜๋Ÿผ ์‰ฝ๊ฒŒ ์•Œ๋ ค์ฃผ๋Š” ์‹ค์ „ ๊ฐœ๋ฐœ ๋…ธํ•˜์šฐ

WooCommerce Development Plugin Extension Architecture

๐ŸŽฏ WooCommerce, ์™œ ์ด๋ ‡๊ฒŒ ์ธ๊ธฐ๊ฐ€ ๋งŽ์„๊นŒ?

์•ˆ๋…•! ์˜ค๋Š˜์€ ์›Œ๋“œํ”„๋ ˆ์Šค ๊ธฐ๋ฐ˜ ์‡ผํ•‘๋ชฐ์˜ ์ ˆ๋Œ€๊ฐ•์ž, WooCommerce์— ๋Œ€ํ•ด ๊นŠ์ด ์žˆ๊ฒŒ ํŒŒํ—ค์ณ๋ณผ ๊ฑฐ์•ผ. ํ˜น์‹œ ์˜จ๋ผ์ธ ์‡ผํ•‘๋ชฐ์„ ๋งŒ๋“ค์–ด๋ณด๊ณ  ์‹ถ์—ˆ๋˜ ์  ์žˆ์–ด? ์•„๋‹ˆ๋ฉด ์ด๋ฏธ ์šด์˜ ์ค‘์ธ ์‡ผํ•‘๋ชฐ์— ํŠน๋ณ„ํ•œ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์—ˆ๋˜ ์ ์€? ๊ทธ๋ ‡๋‹ค๋ฉด ์ด ๊ธ€์ด ๋”ฑ ๋งž์„ ๊ฑฐ์•ผ! ๐Ÿ˜Š

WooCommerce๋Š” ์ „ ์„ธ๊ณ„ ์˜จ๋ผ์ธ ์‡ผํ•‘๋ชฐ์˜ ์•ฝ 28%๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ํ”Œ๋žซํผ์ด์•ผ. ์™œ ์ด๋ ‡๊ฒŒ ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ์„ ํƒํ• ๊นŒ? ๊ฐ„๋‹จํ•ด. ๋ฌด๋ฃŒ์ด๋ฉด์„œ๋„ ๊ฐ•๋ ฅํ•˜๊ณ , ํ™•์žฅ์„ฑ์ด ๋›ฐ์–ด๋‚˜๊ฑฐ๋“ . ๋งˆ์น˜ ๋ ˆ๊ณ  ๋ธ”๋ก์ฒ˜๋Ÿผ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ž์œ ๋กญ๊ฒŒ ์กฐ๋ฆฝํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒŒ ๊ฐ€์žฅ ํฐ ๋งค๋ ฅ์ด์ง€.

๐Ÿ’ก WooCommerce์˜ ํ•ต์‹ฌ ์žฅ์ 

โ€ข ์˜คํ”ˆ์†Œ์Šค๋กœ ์™„์ „ ๋ฌด๋ฃŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
โ€ข ์›Œ๋“œํ”„๋ ˆ์Šค ์ƒํƒœ๊ณ„์™€ ์™„๋ฒฝํ•œ ํ†ตํ•ฉ
โ€ข ์ˆ˜์ฒœ ๊ฐœ์˜ ํ™•์žฅ ํ”Œ๋Ÿฌ๊ทธ์ธ ์ง€์›
โ€ข ์ „ ์„ธ๊ณ„ ๊ฐœ๋ฐœ์ž ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ํ™œ๋ฐœํ•œ ์ง€์›
โ€ข ์†Œ๊ทœ๋ชจ๋ถ€ํ„ฐ ๋Œ€๊ทœ๋ชจ ์‡ผํ•‘๋ชฐ๊นŒ์ง€ ํ™•์žฅ ๊ฐ€๋Šฅ

ํŠนํžˆ ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ๋„ WooCommerce ๊ฐœ๋ฐœ ๊ด€๋ จ ์žฌ๋Šฅ์„ ์ฐพ๋Š” ์‚ฌ๋žŒ๋“ค์ด ์ •๋ง ๋งŽ์•„. ์‡ผํ•‘๋ชฐ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•๋ถ€ํ„ฐ ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐœ๋ฐœ๊นŒ์ง€, ๋‹ค์–‘ํ•œ ๋‹ˆ์ฆˆ๊ฐ€ ์กด์žฌํ•˜๊ฑฐ๋“ .

๐Ÿ—๏ธ WooCommerce ์•„ํ‚คํ…์ฒ˜ ์ดํ•ดํ•˜๊ธฐ

ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐœ๋ฐœ์— ๋›ฐ์–ด๋“ค๊ธฐ ์ „์—, WooCommerce๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๊ตฌ์กฐ๋ฅผ ์ดํ•ดํ•˜๋Š” ๊ฒŒ ์ •๋ง ์ค‘์š”ํ•ด. ์ง‘์„ ์ง“๊ธฐ ์ „์— ์„ค๊ณ„๋„๋ฅผ ๋ณด๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ง์ด์•ผ.

๐Ÿ“ฆ ํ•ต์‹ฌ ๊ตฌ์„ฑ ์š”์†Œ

WooCommerce๋Š” ํฌ๊ฒŒ ๋„ค ๊ฐ€์ง€ ํ•ต์‹ฌ ๋ ˆ์ด์–ด๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์–ด:

1. ๋ฐ์ดํ„ฐ ๋ ˆ์ด์–ด (Data Layer)

์ œํ’ˆ, ์ฃผ๋ฌธ, ๊ณ ๊ฐ ์ •๋ณด ๋“ฑ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ณ„์ธต์ด์•ผ. WooCommerce๋Š” ์›Œ๋“œํ”„๋ ˆ์Šค์˜ ์ปค์Šคํ…€ ํฌ์ŠคํŠธ ํƒ€์ž…(Custom Post Type)์„ ํ™œ์šฉํ•ด์„œ ์ œํ’ˆ์„ ์ €์žฅํ•˜๊ณ , ๋ณ„๋„์˜ ํ…Œ์ด๋ธ”๋กœ ์ฃผ๋ฌธ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•ด.

2. ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๋ ˆ์ด์–ด (Business Logic Layer)

์žฅ๋ฐ”๊ตฌ๋‹ˆ ๊ณ„์‚ฐ, ์žฌ๊ณ  ๊ด€๋ฆฌ, ๊ฒฐ์ œ ์ฒ˜๋ฆฌ ๋“ฑ์˜ ํ•ต์‹ฌ ๋กœ์ง์ด ์—ฌ๊ธฐ์— ์žˆ์–ด. ์ด ๋ถ€๋ถ„์ด ๋ฐ”๋กœ ์šฐ๋ฆฌ๊ฐ€ ํ”Œ๋Ÿฌ๊ทธ์ธ์œผ๋กœ ํ™•์žฅํ•˜๊ฒŒ ๋  ์ฃผ์š” ์˜์—ญ์ด์ง€.

3. ํ”„๋ ˆ์  ํ…Œ์ด์…˜ ๋ ˆ์ด์–ด (Presentation Layer)

์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๋Š” ํ™”๋ฉด์„ ๋‹ด๋‹นํ•ด. ํ…œํ”Œ๋ฆฟ ํŒŒ์ผ๋“ค์ด ์—ฌ๊ธฐ์— ์†ํ•˜๊ณ , ํ›…(Hook)๊ณผ ํ•„ํ„ฐ(Filter)๋ฅผ ํ†ตํ•ด ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ˆ˜ ์žˆ์–ด.

4. API ๋ ˆ์ด์–ด (API Layer)

REST API์™€ ์›นํ›…์„ ์ œ๊ณตํ•ด์„œ ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ์˜ ์—ฐ๋™์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด์ค˜. ๋ชจ๋ฐ”์ผ ์•ฑ์ด๋‚˜ ๋‹ค๋ฅธ ์„œ๋น„์Šค์™€ ์—ฐ๊ฒฐํ•  ๋•Œ ํ•„์ˆ˜์ ์ด์•ผ.

๐ŸŽ“ ๊ฐœ๋ฐœ์ž ํŒ: WooCommerce์˜ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•˜๋Š” ๊ฑด ์ ˆ๋Œ€ ๊ธˆ๋ฌผ์ด์•ผ! ์—…๋ฐ์ดํŠธํ•  ๋•Œ๋งˆ๋‹ค ๋‚ ์•„๊ฐ€๊ฑฐ๋“ . ๋Œ€์‹  ํ›…๊ณผ ํ•„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•˜๋Š” ๊ฒŒ ์ •์„์ด์•ผ.

๐Ÿ”ง ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์„ธํŒ…ํ•˜๊ธฐ

์ž, ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์„ ๊ตฌ์ถ•ํ•ด๋ณผ๊นŒ? ์ œ๋Œ€๋กœ ๋œ ํ™˜๊ฒฝ ์„ค์ •์€ ๊ฐœ๋ฐœ ํšจ์œจ์„ 2๋ฐฐ, 3๋ฐฐ๋กœ ๋†’์—ฌ์ค˜! ๐Ÿš€

๐Ÿ’ป ํ•„์ˆ˜ ๋„๊ตฌ๋“ค

1. ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ

์‹ค์ œ ์„œ๋ฒ„์—์„œ ๋ฐ”๋กœ ์ž‘์—…ํ•˜๋Š” ๊ฑด ์œ„ํ—˜ํ•ด. ๋กœ์ปฌ ํ™˜๊ฒฝ์—์„œ ์ถฉ๋ถ„ํžˆ ํ…Œ์ŠคํŠธํ•œ ํ›„์— ๋ฐฐํฌํ•˜๋Š” ๊ฒŒ ์•ˆ์ „ํ•˜์ง€. ์ถ”์ฒœํ•˜๋Š” ๋„๊ตฌ๋“ค์€:

โ€ข Local by Flywheel: ๊ฐ€์žฅ ์‰ฝ๊ณ  ์ง๊ด€์ ์ธ ์›Œ๋“œํ”„๋ ˆ์Šค ๋กœ์ปฌ ํ™˜๊ฒฝ
โ€ข XAMPP: ์ „ํ†ต์ ์ด์ง€๋งŒ ๊ฐ•๋ ฅํ•œ Apache+MySQL ํ™˜๊ฒฝ
โ€ข Docker: ํ”„๋กœํŽ˜์…”๋„ํ•œ ์ปจํ…Œ์ด๋„ˆ ๊ธฐ๋ฐ˜ ํ™˜๊ฒฝ
โ€ข MAMP: Mac ์‚ฌ์šฉ์ž์—๊ฒŒ ์นœํ™”์ ์ธ ์„ ํƒ

2. ์ฝ”๋“œ ์—๋””ํ„ฐ

๋‚˜๋Š” ๊ฐœ์ธ์ ์œผ๋กœ Visual Studio Code๋ฅผ ๊ฐ•๋ ฅ ์ถ”์ฒœํ•ด. ๋ฌด๋ฃŒ์ด๋ฉด์„œ๋„ ํ™•์žฅ ๊ธฐ๋Šฅ์ด ์—„์ฒญ๋‚˜๊ฒŒ ๋งŽ๊ฑฐ๋“ . ํŠนํžˆ ์ด๋Ÿฐ ํ™•์žฅ๋“ค์„ ์„ค์น˜ํ•˜๋ฉด ๊ฐœ๋ฐœ์ด ํ›จ์”ฌ ํŽธํ•ด์ ธ:

โ€ข PHP Intelephense: PHP ์ž๋™์™„์„ฑ๊ณผ ๋ฌธ๋ฒ• ๊ฒ€์‚ฌ
โ€ข WordPress Snippets: ์›Œ๋“œํ”„๋ ˆ์Šค ํ•จ์ˆ˜ ์ž๋™์™„์„ฑ
โ€ข WooCommerce Snippets: WooCommerce ์ „์šฉ ์Šค๋‹ˆํŽซ
โ€ข GitLens: Git ํ†ตํ•ฉ ๊ด€๋ฆฌ
โ€ข Prettier: ์ฝ”๋“œ ์ž๋™ ํฌ๋งทํŒ…

3. ๋””๋ฒ„๊น… ๋„๊ตฌ

๋ฒ„๊ทธ ์—†๋Š” ์ฝ”๋“œ๋Š” ์—†์–ด. ๋ฌธ์ œ๋ฅผ ๋น ๋ฅด๊ฒŒ ์ฐพ์•„๋‚ด๋Š” ๊ฒŒ ์‹ค๋ ฅ์ด์ง€!

// wp-config.php์— ์ถ”๊ฐ€
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
define('SCRIPT_DEBUG', true);

์ด๋ ‡๊ฒŒ ์„ค์ •ํ•˜๋ฉด ์—๋Ÿฌ ๋กœ๊ทธ๊ฐ€ wp-content/debug.log ํŒŒ์ผ์— ๊ธฐ๋ก๋ผ. ํ™”๋ฉด์—๋Š” ํ‘œ์‹œ๋˜์ง€ ์•Š์œผ๋‹ˆ๊นŒ ๊ณ ๊ฐ์—๊ฒŒ ๋ณด์—ฌ์ค„ ๊ฑฑ์ •๋„ ์—†์–ด!

โšก ํ”„๋กœ ํŒ: Query Monitor ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์„ค์น˜ํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ, ํ›… ์‹คํ–‰ ์ˆœ์„œ, PHP ์—๋Ÿฌ ๋“ฑ์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ๋งํ•  ์ˆ˜ ์žˆ์–ด. ์„ฑ๋Šฅ ์ตœ์ ํ™”ํ•  ๋•Œ ํ•„์ˆ˜์•ผ!

๐ŸŽจ ์ฒซ ๋ฒˆ์งธ ํ”Œ๋Ÿฌ๊ทธ์ธ ๋งŒ๋“ค๊ธฐ

์ด๋ก ์€ ์ด์ œ ์ถฉ๋ถ„ํ•ด! ์‹ค์ œ๋กœ ๊ฐ„๋‹จํ•œ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋งŒ๋“ค์–ด๋ณด๋ฉด์„œ ๊ฐ์„ ์žก์•„๋ณด์ž. ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค ๊ฑด "์ œํ’ˆ ์ƒ์„ธํŽ˜์ด์ง€์— ์ปค์Šคํ…€ ํ•„๋“œ ์ถ”๊ฐ€ํ•˜๊ธฐ"์•ผ. ์‹ค๋ฌด์—์„œ ์ •๋ง ์ž์ฃผ ์“ฐ์ด๋Š” ๊ธฐ๋Šฅ์ด๊ฑฐ๋“ ! ๐Ÿ˜Ž

๐Ÿ“ ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ตฌ์กฐ ๋งŒ๋“ค๊ธฐ

๋จผ์ € wp-content/plugins/ ํด๋”์— ์ƒˆ ํด๋”๋ฅผ ๋งŒ๋“ค์–ด. ์ด๋ฆ„์€ wc-custom-fields๋กœ ํ•˜์ž.

wc-custom-fields/
โ”œโ”€โ”€ wc-custom-fields.php (๋ฉ”์ธ ํŒŒ์ผ)
โ”œโ”€โ”€ includes/
โ”‚   โ”œโ”€โ”€ class-product-fields.php
โ”‚   โ””โ”€โ”€ class-admin-settings.php
โ”œโ”€โ”€ assets/
โ”‚   โ”œโ”€โ”€ css/
โ”‚   โ””โ”€โ”€ js/
โ””โ”€โ”€ languages/

๋ฉ”์ธ ํ”Œ๋Ÿฌ๊ทธ์ธ ํŒŒ์ผ ์ž‘์„ฑ

์ด์ œ wc-custom-fields.php ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ  ํ”Œ๋Ÿฌ๊ทธ์ธ ํ—ค๋”๋ฅผ ์ž‘์„ฑํ•ด๋ณด์ž:

<?php
/**
 * Plugin Name: WooCommerce Custom Product Fields
 * Plugin URI: https://www.jaenung.net
 * Description: ์ œํ’ˆ์— ์ปค์Šคํ…€ ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ
 * Version: 1.0.0
 * Author: Your Name
 * Author URI: https://www.jaenung.net
 * Text Domain: wc-custom-fields
 * Domain Path: /languages
 * Requires at least: 5.8
 * Requires PHP: 7.4
 * WC requires at least: 5.0
 * WC tested up to: 8.0
 */

// ์ง์ ‘ ์ ‘๊ทผ ์ฐจ๋‹จ
if (!defined('ABSPATH')) {
    exit;
}

// WooCommerce ํ™œ์„ฑํ™” ์ฒดํฌ
if (!in_array('woocommerce/woocommerce.php', 
    apply_filters('active_plugins', get_option('active_plugins')))) {
    return;
}

// ํ”Œ๋Ÿฌ๊ทธ์ธ ์ƒ์ˆ˜ ์ •์˜
define('WC_CUSTOM_FIELDS_VERSION', '1.0.0');
define('WC_CUSTOM_FIELDS_PATH', plugin_dir_path(__FILE__));
define('WC_CUSTOM_FIELDS_URL', plugin_dir_url(__FILE__));

// ๋ฉ”์ธ ํด๋ž˜์Šค
class WC_Custom_Fields {
    
    private static $instance = null;
    
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        $this->init_hooks();
        $this->load_dependencies();
    }
    
    private function init_hooks() {
        add_action('plugins_loaded', array($this, 'load_textdomain'));
    }
    
    private function load_dependencies() {
        require_once WC_CUSTOM_FIELDS_PATH . 'includes/class-product-fields.php';
    }
    
    public function load_textdomain() {
        load_plugin_textdomain(
            'wc-custom-fields',
            false,
            dirname(plugin_basename(__FILE__)) . '/languages'
        );
    }
}

// ํ”Œ๋Ÿฌ๊ทธ์ธ ์ดˆ๊ธฐํ™”
function wc_custom_fields_init() {
    return WC_Custom_Fields::get_instance();
}

add_action('plugins_loaded', 'wc_custom_fields_init');

์ด ์ฝ”๋“œ์˜ ํ•ต์‹ฌ ํฌ์ธํŠธ๋ฅผ ์งš์–ด๋ณผ๊ฒŒ:

๐Ÿ” ์ฝ”๋“œ ๋ถ„์„

โ€ข ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด: ํ”Œ๋Ÿฌ๊ทธ์ธ ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•˜๋‚˜๋งŒ ์ƒ์„ฑ๋˜๋„๋ก ๋ณด์žฅํ•ด
โ€ข ์ง์ ‘ ์ ‘๊ทผ ์ฐจ๋‹จ: ๋ณด์•ˆ์„ ์œ„ํ•ด ์ง์ ‘ ํŒŒ์ผ ์ ‘๊ทผ์„ ๋ง‰์•„
โ€ข WooCommerce ์˜์กด์„ฑ ์ฒดํฌ: WooCommerce๊ฐ€ ์—†์œผ๋ฉด ์‹คํ–‰ ์•ˆ ๋ผ
โ€ข ์ƒ์ˆ˜ ์ •์˜: ๊ฒฝ๋กœ์™€ ๋ฒ„์ „์„ ์ƒ์ˆ˜๋กœ ๊ด€๋ฆฌํ•ด์„œ ์œ ์ง€๋ณด์ˆ˜ ํŽธํ•˜๊ฒŒ
โ€ข ๋‹ค๊ตญ์–ด ์ง€์›: ํ…์ŠคํŠธ ๋„๋ฉ”์ธ ์„ค์ •์œผ๋กœ ๋ฒˆ์—ญ ๊ฐ€๋Šฅํ•˜๊ฒŒ

๐ŸŽฏ ์ œํ’ˆ ํ•„๋“œ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ ๊ตฌํ˜„

์ด์ œ includes/class-product-fields.php ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์„œ ์‹ค์ œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด๋ณด์ž:

<?php
class WC_Product_Custom_Fields {
    
    public function __construct() {
        // ๊ด€๋ฆฌ์ž ์ œํ’ˆ ํŽธ์ง‘ ํŽ˜์ด์ง€์— ํ•„๋“œ ์ถ”๊ฐ€
        add_action('woocommerce_product_options_general_product_data', 
            array($this, 'add_custom_fields'));
        
        // ํ•„๋“œ ์ €์žฅ
        add_action('woocommerce_process_product_meta', 
            array($this, 'save_custom_fields'));
        
        // ํ”„๋ก ํŠธ์—”๋“œ์— ํ‘œ์‹œ
        add_action('woocommerce_single_product_summary', 
            array($this, 'display_custom_fields'), 25);
    }
    
    public function add_custom_fields() {
        global $post;
        
        echo '<div class="options_group">';
        
        // ํ…์ŠคํŠธ ํ•„๋“œ
        woocommerce_wp_text_input(array(
            'id' => '_custom_text_field',
            'label' => __('์ปค์Šคํ…€ ํ…์ŠคํŠธ', 'wc-custom-fields'),
            'placeholder' => 'ํŠน๋ณ„ํ•œ ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”',
            'desc_tip' => true,
            'description' => __('์ œํ’ˆ ์ƒ์„ธํŽ˜์ด์ง€์— ํ‘œ์‹œ๋  ์ถ”๊ฐ€ ์ •๋ณด', 'wc-custom-fields'),
            'type' => 'text'
        ));
        
        // ์ˆซ์ž ํ•„๋“œ
        woocommerce_wp_text_input(array(
            'id' => '_custom_number_field',
            'label' => __('๋ฐฐ์†ก ์†Œ์š”์ผ', 'wc-custom-fields'),
            'placeholder' => '3',
            'desc_tip' => true,
            'description' => __('์˜ˆ์ƒ ๋ฐฐ์†ก ์†Œ์š” ์ผ์ˆ˜', 'wc-custom-fields'),
            'type' => 'number',
            'custom_attributes' => array(
                'step' => '1',
                'min' => '1'
            )
        ));
        
        // ์…€๋ ‰ํŠธ ๋ฐ•์Šค
        woocommerce_wp_select(array(
            'id' => '_custom_select_field',
            'label' => __('์ œํ’ˆ ๋“ฑ๊ธ‰', 'wc-custom-fields'),
            'options' => array(
                '' => __('์„ ํƒํ•˜์„ธ์š”', 'wc-custom-fields'),
                'premium' => __('ํ”„๋ฆฌ๋ฏธ์—„', 'wc-custom-fields'),
                'standard' => __('์Šคํƒ ๋‹ค๋“œ', 'wc-custom-fields'),
                'basic' => __('๋ฒ ์ด์ง', 'wc-custom-fields')
            )
        ));
        
        // ์ฒดํฌ๋ฐ•์Šค
        woocommerce_wp_checkbox(array(
            'id' => '_custom_checkbox_field',
            'label' => __('ํŠน๋ณ„ ๋ฐฐ์†ก', 'wc-custom-fields'),
            'description' => __('ํŠน๋ณ„ ๋ฐฐ์†ก ์„œ๋น„์Šค ์ œ๊ณต', 'wc-custom-fields')
        ));
        
        echo '</div>';
    }
    
    public function save_custom_fields($post_id) {
        // ํ…์ŠคํŠธ ํ•„๋“œ ์ €์žฅ
        $custom_text = isset($_POST['_custom_text_field']) 
            ? sanitize_text_field($_POST['_custom_text_field']) 
            : '';
        update_post_meta($post_id, '_custom_text_field', $custom_text);
        
        // ์ˆซ์ž ํ•„๋“œ ์ €์žฅ
        $custom_number = isset($_POST['_custom_number_field']) 
            ? absint($_POST['_custom_number_field']) 
            : '';
        update_post_meta($post_id, '_custom_number_field', $custom_number);
        
        // ์…€๋ ‰ํŠธ ๋ฐ•์Šค ์ €์žฅ
        $custom_select = isset($_POST['_custom_select_field']) 
            ? sanitize_text_field($_POST['_custom_select_field']) 
            : '';
        update_post_meta($post_id, '_custom_select_field', $custom_select);
        
        // ์ฒดํฌ๋ฐ•์Šค ์ €์žฅ
        $custom_checkbox = isset($_POST['_custom_checkbox_field']) 
            ? 'yes' 
            : 'no';
        update_post_meta($post_id, '_custom_checkbox_field', $custom_checkbox);
    }
    
    public function display_custom_fields() {
        global $product;
        
        $custom_text = get_post_meta($product->get_id(), '_custom_text_field', true);
        $custom_number = get_post_meta($product->get_id(), '_custom_number_field', true);
        $custom_select = get_post_meta($product->get_id(), '_custom_select_field', true);
        $custom_checkbox = get_post_meta($product->get_id(), '_custom_checkbox_field', true);
        
        if ($custom_text || $custom_number || $custom_select || $custom_checkbox === 'yes') {
            echo '<div class="custom-product-fields">';
            
            if ($custom_text) {
                echo '<p class="custom-field-text">';
                echo '<strong>' . __('์ถ”๊ฐ€ ์ •๋ณด:', 'wc-custom-fields') . '</strong> ';
                echo esc_html($custom_text);
                echo '</p>';
            }
            
            if ($custom_number) {
                echo '<p class="custom-field-delivery">';
                echo '<strong>' . __('๋ฐฐ์†ก ์†Œ์š”:', 'wc-custom-fields') . '</strong> ';
                echo sprintf(__('%d์ผ', 'wc-custom-fields'), $custom_number);
                echo '</p>';
            }
            
            if ($custom_select) {
                $grades = array(
                    'premium' => __('ํ”„๋ฆฌ๋ฏธ์—„', 'wc-custom-fields'),
                    'standard' => __('์Šคํƒ ๋‹ค๋“œ', 'wc-custom-fields'),
                    'basic' => __('๋ฒ ์ด์ง', 'wc-custom-fields')
                );
                
                echo '<p class="custom-field-grade">';
                echo '<strong>' . __('์ œํ’ˆ ๋“ฑ๊ธ‰:', 'wc-custom-fields') . '</strong> ';
                echo esc_html($grades[$custom_select]);
                echo '</p>';
            }
            
            if ($custom_checkbox === 'yes') {
                echo '<p class="custom-field-special">';
                echo 'โญ ' . __('ํŠน๋ณ„ ๋ฐฐ์†ก ์„œ๋น„์Šค ์ œ๊ณต', 'wc-custom-fields');
                echo '</p>';
            }
            
            echo '</div>';
        }
    }
}

new WC_Product_Custom_Fields();

๐Ÿ›ก๏ธ ๋ณด์•ˆ ์ฃผ์˜์‚ฌํ•ญ: ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ์ €์žฅํ•  ๋•Œ๋Š” ๋ฐ˜๋“œ์‹œ sanitize_text_field(), absint() ๊ฐ™์€ ํ•จ์ˆ˜๋กœ ๊ฒ€์ฆํ•ด์•ผ ํ•ด. ์ถœ๋ ฅํ•  ๋•Œ๋Š” esc_html()๋กœ ์ด์Šค์ผ€์ดํ”„ ์ฒ˜๋ฆฌ! ์ด๊ฒŒ XSS ๊ณต๊ฒฉ์„ ๋ง‰๋Š” ๊ธฐ๋ณธ์ด์•ผ.

๐ŸŽจ ํ”„๋ก ํŠธ์—”๋“œ ์Šคํƒ€์ผ๋ง

๊ธฐ๋Šฅ์€ ์™„์„ฑํ–ˆ์ง€๋งŒ, ๋””์ž์ธ์ด ์—†์œผ๋ฉด ํ—ˆ์ „ํ•˜์ง€? CSS๋กœ ์˜ˆ์˜๊ฒŒ ๊พธ๋ฉฐ๋ณด์ž! ๐Ÿ˜Š

assets/css/frontend.css ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ :

.custom-product-fields {
    background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
    padding: 20px;
    border-radius: 12px;
    margin: 20px 0;
    border-left: 4px solid #a29bfe;
}

.custom-product-fields p {
    margin: 10px 0;
    font-size: 15px;
    line-height: 1.6;
}

.custom-product-fields strong {
    color: #6c5ce7;
    font-weight: 600;
}

.custom-field-special {
    background: #ffeaa7;
    padding: 10px 15px;
    border-radius: 8px;
    display: inline-block;
}

๊ทธ๋ฆฌ๊ณ  ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ฉ”์ธ ํŒŒ์ผ์—์„œ CSS๋ฅผ ๋กœ๋“œํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด:

public function __construct() {
    // ๊ธฐ์กด ์ฝ”๋“œ...
    add_action('wp_enqueue_scripts', array($this, 'enqueue_styles'));
}

public function enqueue_styles() {
    if (is_product()) {
        wp_enqueue_style(
            'wc-custom-fields-frontend',
            WC_CUSTOM_FIELDS_URL . 'assets/css/frontend.css',
            array(),
            WC_CUSTOM_FIELDS_VERSION
        );
    }
}

is_product() ์กฐ๊ฑด์„ ์‚ฌ์šฉํ•ด์„œ ์ œํ’ˆ ์ƒ์„ธํŽ˜์ด์ง€์—์„œ๋งŒ CSS๋ฅผ ๋กœ๋“œํ•˜๋„๋ก ํ–ˆ์–ด. ๋ถˆํ•„์š”ํ•œ ๋ฆฌ์†Œ์Šค ๋‚ญ๋น„๋ฅผ ๋ง‰๋Š” ๊ฑฐ์ง€! ๐Ÿ‘

๐Ÿ”Œ WooCommerce ํ›…(Hook) ์‹œ์Šคํ…œ ๋งˆ์Šคํ„ฐํ•˜๊ธฐ

WooCommerce์˜ ์ง„์งœ ํŒŒ์›Œ๋Š” ๋ฐ”๋กœ ํ›… ์‹œ์Šคํ…œ์— ์žˆ์–ด. ์•ก์…˜(Action)๊ณผ ํ•„ํ„ฐ(Filter)๋ฅผ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๋ฉด, ๊ฑฐ์˜ ๋ชจ๋“  ๊ฑธ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ !

โšก ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ์•ก์…˜ ํ›…

์ œํ’ˆ ๊ด€๋ จ ํ›…

โ€ข woocommerce_before_single_product: ์ œํ’ˆ ํŽ˜์ด์ง€ ์‹œ์ž‘ ์ „
โ€ข woocommerce_single_product_summary: ์ œํ’ˆ ์š”์•ฝ ์ •๋ณด ์˜์—ญ
โ€ข woocommerce_after_single_product_summary: ์ œํ’ˆ ์š”์•ฝ ์ •๋ณด ํ›„
โ€ข woocommerce_product_meta_end: ์ œํ’ˆ ๋ฉ”ํƒ€ ์ •๋ณด ๋

์žฅ๋ฐ”๊ตฌ๋‹ˆ ๊ด€๋ จ ํ›…

โ€ข woocommerce_before_cart: ์žฅ๋ฐ”๊ตฌ๋‹ˆ ํŽ˜์ด์ง€ ์‹œ์ž‘ ์ „
โ€ข woocommerce_cart_contents: ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋‚ด์šฉ ํ‘œ์‹œ
โ€ข woocommerce_cart_totals: ์žฅ๋ฐ”๊ตฌ๋‹ˆ ํ•ฉ๊ณ„ ํ‘œ์‹œ
โ€ข woocommerce_after_cart_table: ์žฅ๋ฐ”๊ตฌ๋‹ˆ ํ…Œ์ด๋ธ” ํ›„

๊ฒฐ์ œ ๊ด€๋ จ ํ›…

โ€ข woocommerce_before_checkout_form: ๊ฒฐ์ œ ํผ ์‹œ์ž‘ ์ „
โ€ข woocommerce_checkout_order_review: ์ฃผ๋ฌธ ๊ฒ€ํ†  ์˜์—ญ
โ€ข woocommerce_after_checkout_form: ๊ฒฐ์ œ ํผ ํ›„
โ€ข woocommerce_thankyou: ์ฃผ๋ฌธ ์™„๋ฃŒ ํŽ˜์ด์ง€

๐ŸŽฏ ์‹ค์ „ ์˜ˆ์ œ: ์žฅ๋ฐ”๊ตฌ๋‹ˆ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•

์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ํŠน๋ณ„ ๋ฉ”์‹œ์ง€๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ , ํŠน์ • ๊ธˆ์•ก ์ด์ƒ ๊ตฌ๋งค ์‹œ ๋ฌด๋ฃŒ๋ฐฐ์†ก ์•ˆ๋‚ด๋ฅผ ํ‘œ์‹œํ•ด๋ณด์ž:

class WC_Cart_Customizer {
    
    public function __construct() {
        // ์žฅ๋ฐ”๊ตฌ๋‹ˆ ์ƒ๋‹จ์— ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€
        add_action('woocommerce_before_cart', array($this, 'add_cart_notice'));
        
        // ๋ฌด๋ฃŒ๋ฐฐ์†ก ์ง„ํ–‰๋ฅ  ํ‘œ์‹œ
        add_action('woocommerce_before_cart_table', array($this, 'free_shipping_progress'));
        
        // ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋น„์šฐ๊ธฐ ๋ฒ„ํŠผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•
        add_filter('woocommerce_return_to_shop_text', array($this, 'custom_return_text'));
    }
    
    public function add_cart_notice() {
        if (WC()->cart->get_cart_contents_count() > 0) {
            echo '<div class="woocommerce-info custom-cart-notice">';
            echo '๐ŸŽ‰ ' . __('์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ์ƒํ’ˆ์ด ๋‹ด๊ฒผ์Šต๋‹ˆ๋‹ค! ์ง€๊ธˆ ๊ฒฐ์ œํ•˜์‹œ๋ฉด ์˜ค๋Š˜ ์ถœ๊ณ ๋ฉ๋‹ˆ๋‹ค.', 'wc-custom-fields');
            echo '</div>';
        }
    }
    
    public function free_shipping_progress() {
        $free_shipping_threshold = 50000; // ๋ฌด๋ฃŒ๋ฐฐ์†ก ๊ธฐ์ค€ ๊ธˆ์•ก
        $current_total = WC()->cart->get_subtotal();
        
        if ($current_total < $free_shipping_threshold) {
            $remaining = $free_shipping_threshold - $current_total;
            $progress_percent = ($current_total / $free_shipping_threshold) * 100;
            
            echo '<div class="free-shipping-progress">';
            echo '<div class="progress-bar-container">';
            echo '<div class="progress-bar" style="width: ' . $progress_percent . '%"></div>';
            echo '</div>';
            echo '<p class="progress-text">';
            echo sprintf(
                __('๋ฌด๋ฃŒ๋ฐฐ์†ก๊นŒ์ง€ <strong>%s</strong> ๋‚จ์•˜์Šต๋‹ˆ๋‹ค! ๐Ÿšš', 'wc-custom-fields'),
                wc_price($remaining)
            );
            echo '</p>';
            echo '</div>';
        } else {
            echo '<div class="free-shipping-achieved">';
            echo 'โœ… ' . __('๋ฌด๋ฃŒ๋ฐฐ์†ก ๋Œ€์ƒ์ž…๋‹ˆ๋‹ค!', 'wc-custom-fields');
            echo '</div>';
        }
    }
    
    public function custom_return_text($text) {
        return __('โ† ์‡ผํ•‘ ๊ณ„์†ํ•˜๊ธฐ', 'wc-custom-fields');
    }
}

new WC_Cart_Customizer();

์ด ์ฝ”๋“œ๋Š” ์‹ค์ œ๋กœ ๋งŽ์€ ์‡ผํ•‘๋ชฐ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ํŒจํ„ด์ด์•ผ. ๊ณ ๊ฐ์˜ ๊ตฌ๋งค ์˜์š•์„ ๋†’์ด๋Š” ์‹ฌ๋ฆฌ์  ํšจ๊ณผ๊ฐ€ ์žˆ๊ฑฐ๋“ ! ๐Ÿ’ช

๐Ÿ’ฐ ๋น„์ฆˆ๋‹ˆ์Šค ํŒ: ๋ฌด๋ฃŒ๋ฐฐ์†ก ์ง„ํ–‰๋ฅ  ํ‘œ์‹œ๋Š” ํ‰๊ท  ์ฃผ๋ฌธ ๊ธˆ์•ก์„ 15-20% ๋†’์ด๋Š” ํšจ๊ณผ๊ฐ€ ์žˆ๋‹ค๋Š” ์—ฐ๊ตฌ ๊ฒฐ๊ณผ๊ฐ€ ์žˆ์–ด. ์ž‘์€ ๊ธฐ๋Šฅ์ด์ง€๋งŒ ๋งค์ถœ์— ํฐ ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์ง€!

๐Ÿ” ๊ฒฐ์ œ ๊ฒŒ์ดํŠธ์›จ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐœ๋ฐœ

์ด์ œ ์ข€ ๋” ๊ณ ๊ธ‰ ์ฃผ์ œ๋กœ ๋„˜์–ด๊ฐ€๋ณผ๊นŒ? ์ปค์Šคํ…€ ๊ฒฐ์ œ ๊ฒŒ์ดํŠธ์›จ์ด๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž. ์ด๊ฑด ์ •๋ง ์‹ค๋ฌด์—์„œ ์ž์ฃผ ์š”์ฒญ๋ฐ›๋Š” ๊ธฐ๋Šฅ์ด์•ผ! ๐Ÿ’ณ

๐Ÿฆ ๊ฒฐ์ œ ๊ฒŒ์ดํŠธ์›จ์ด ๊ธฐ๋ณธ ๊ตฌ์กฐ

WooCommerce๋Š” WC_Payment_Gateway ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์•„์„œ ๊ฒฐ์ œ ๊ฒŒ์ดํŠธ์›จ์ด๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด. ์˜ˆ์ œ๋กœ ๊ฐ„๋‹จํ•œ ๋ฌดํ†ต์žฅ์ž…๊ธˆ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค์–ด๋ณด์ž:

class WC_Gateway_Custom_Bank extends WC_Payment_Gateway {
    
    public function __construct() {
        // ๊ฒŒ์ดํŠธ์›จ์ด ID (๊ณ ์œ ๊ฐ’)
        $this->id = 'custom_bank_transfer';
        
        // ๊ฒฐ์ œ ๋ฐฉ๋ฒ• ์•„์ด์ฝ˜
        $this->icon = apply_filters('woocommerce_custom_bank_icon', '');
        
        // ์ง์ ‘ ๊ฒฐ์ œ ์—ฌ๋ถ€
        $this->has_fields = true;
        
        // ๊ด€๋ฆฌ์ž ํŽ˜์ด์ง€ ์ œ๋ชฉ
        $this->method_title = __('์ปค์Šคํ…€ ๋ฌดํ†ต์žฅ์ž…๊ธˆ', 'wc-custom-fields');
        
        // ๊ด€๋ฆฌ์ž ํŽ˜์ด์ง€ ์„ค๋ช…
        $this->method_description = __('๊ณ ๊ฐ์ด ์€ํ–‰ ๊ณ„์ขŒ๋กœ ์ง์ ‘ ์ž…๊ธˆํ•˜๋Š” ๋ฐฉ์‹', 'wc-custom-fields');
        
        // ์ง€์› ๊ธฐ๋Šฅ
        $this->supports = array(
            'products',
            'refunds'
        );
        
        // ์„ค์ • ํ•„๋“œ ๋กœ๋“œ
        $this->init_form_fields();
        $this->init_settings();
        
        // ์„ค์ •๊ฐ’ ๊ฐ€์ ธ์˜ค๊ธฐ
        $this->title = $this->get_option('title');
        $this->description = $this->get_option('description');
        $this->instructions = $this->get_option('instructions');
        $this->account_details = $this->get_option('account_details');
        
        // ์„ค์ • ์ €์žฅ ํ›…
        add_action('woocommerce_update_options_payment_gateways_' . $this->id, 
            array($this, 'process_admin_options'));
        
        // ์ฃผ๋ฌธ ์™„๋ฃŒ ์ด๋ฉ”์ผ์— ๊ณ„์ขŒ ์ •๋ณด ์ถ”๊ฐ€
        add_action('woocommerce_email_before_order_table', 
            array($this, 'email_instructions'), 10, 3);
    }
    
    public function init_form_fields() {
        $this->form_fields = array(
            'enabled' => array(
                'title' => __('ํ™œ์„ฑํ™”', 'wc-custom-fields'),
                'type' => 'checkbox',
                'label' => __('๋ฌดํ†ต์žฅ์ž…๊ธˆ ๊ฒฐ์ œ ํ™œ์„ฑํ™”', 'wc-custom-fields'),
                'default' => 'no'
            ),
            'title' => array(
                'title' => __('์ œ๋ชฉ', 'wc-custom-fields'),
                'type' => 'text',
                'description' => __('๊ฒฐ์ œ ์ˆ˜๋‹จ ์„ ํƒ ์‹œ ํ‘œ์‹œ๋˜๋Š” ์ œ๋ชฉ', 'wc-custom-fields'),
                'default' => __('๋ฌดํ†ต์žฅ์ž…๊ธˆ', 'wc-custom-fields'),
                'desc_tip' => true
            ),
            'description' => array(
                'title' => __('์„ค๋ช…', 'wc-custom-fields'),
                'type' => 'textarea',
                'description' => __('๊ฒฐ์ œ ์ˆ˜๋‹จ ์„ ํƒ ์‹œ ํ‘œ์‹œ๋˜๋Š” ์„ค๋ช…', 'wc-custom-fields'),
                'default' => __('์•„๋ž˜ ๊ณ„์ขŒ๋กœ ์ž…๊ธˆํ•ด์ฃผ์„ธ์š”.', 'wc-custom-fields'),
                'desc_tip' => true
            ),
            'instructions' => array(
                'title' => __('์ž…๊ธˆ ์•ˆ๋‚ด', 'wc-custom-fields'),
                'type' => 'textarea',
                'description' => __('์ฃผ๋ฌธ ์™„๋ฃŒ ํŽ˜์ด์ง€์— ํ‘œ์‹œ๋  ์•ˆ๋‚ด ๋ฌธ๊ตฌ', 'wc-custom-fields'),
                'default' => __('์ž…๊ธˆ ํ™•์ธ ํ›„ ์ƒํ’ˆ์ด ๋ฐœ์†ก๋ฉ๋‹ˆ๋‹ค.', 'wc-custom-fields'),
                'desc_tip' => true
            ),
            'account_details' => array(
                'title' => __('๊ณ„์ขŒ ์ •๋ณด', 'wc-custom-fields'),
                'type' => 'textarea',
                'description' => __('์€ํ–‰๋ช…, ๊ณ„์ขŒ๋ฒˆํ˜ธ, ์˜ˆ๊ธˆ์ฃผ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”', 'wc-custom-fields'),
                'default' => '',
                'desc_tip' => true,
                'placeholder' => "๊ตญ๋ฏผ์€ํ–‰\n123-456-789012\nํ™๊ธธ๋™"
            )
        );
    }
    
    public function payment_fields() {
        // ๊ฒฐ์ œ ํŽ˜์ด์ง€์— ํ‘œ์‹œ๋  ๋‚ด์šฉ
        if ($this->description) {
            echo wpautop(wptexturize($this->description));
        }
        
        if ($this->account_details) {
            echo '<div class="bank-account-details">';
            echo '<h4>' . __('์ž…๊ธˆ ๊ณ„์ขŒ ์ •๋ณด', 'wc-custom-fields') . '</h4>';
            echo '<pre>' . esc_html($this->account_details) . '</pre>';
            echo '</div>';
        }
    }
    
    public function process_payment($order_id) {
        $order = wc_get_order($order_id);
        
        // ์ฃผ๋ฌธ ์ƒํƒœ๋ฅผ '์ž…๊ธˆ ๋Œ€๊ธฐ'๋กœ ๋ณ€๊ฒฝ
        $order->update_status('on-hold', __('๋ฌดํ†ต์žฅ์ž…๊ธˆ ๋Œ€๊ธฐ ์ค‘', 'wc-custom-fields'));
        
        // ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋น„์šฐ๊ธฐ
        WC()->cart->empty_cart();
        
        // ์ฃผ๋ฌธ ์™„๋ฃŒ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ
        return array(
            'result' => 'success',
            'redirect' => $this->get_return_url($order)
        );
    }
    
    public function email_instructions($order, $sent_to_admin, $plain_text = false) {
        // ๊ด€๋ฆฌ์ž์—๊ฒŒ ๋ณด๋‚ด๋Š” ์ด๋ฉ”์ผ์ด ์•„๋‹ˆ๊ณ , ๋ฌดํ†ต์žฅ์ž…๊ธˆ ์ฃผ๋ฌธ์ด๋ฉฐ, ์ž…๊ธˆ ๋Œ€๊ธฐ ์ƒํƒœ์ผ ๋•Œ
        if (!$sent_to_admin && 
            $this->id === $order->get_payment_method() && 
            $order->has_status('on-hold')) {
            
            if ($this->instructions) {
                echo wpautop(wptexturize($this->instructions)) . PHP_EOL;
            }
            
            if ($this->account_details) {
                echo '<h3>' . __('์ž…๊ธˆ ๊ณ„์ขŒ', 'wc-custom-fields') . '</h3>' . PHP_EOL;
                echo '<pre>' . esc_html($this->account_details) . '</pre>' . PHP_EOL;
            }
        }
    }
    
    // ํ™˜๋ถˆ ์ฒ˜๋ฆฌ
    public function process_refund($order_id, $amount = null, $reason = '') {
        $order = wc_get_order($order_id);
        
        if (!$order) {
            return false;
        }
        
        // ์‹ค์ œ ํ™˜๋ถˆ ๋กœ์ง ๊ตฌํ˜„
        // ์˜ˆ: ๊ด€๋ฆฌ์ž์—๊ฒŒ ์•Œ๋ฆผ ์ „์†ก, ํ™˜๋ถˆ ์š”์ฒญ ๊ธฐ๋ก ๋“ฑ
        
        $order->add_order_note(
            sprintf(__('ํ™˜๋ถˆ ์š”์ฒญ: %s (์‚ฌ์œ : %s)', 'wc-custom-fields'), 
            wc_price($amount), 
            $reason)
        );
        
        return true;
    }
}

// ๊ฒŒ์ดํŠธ์›จ์ด ๋“ฑ๋ก
function add_custom_bank_gateway($gateways) {
    $gateways[] = 'WC_Gateway_Custom_Bank';
    return $gateways;
}
add_filter('woocommerce_payment_gateways', 'add_custom_bank_gateway');

๐ŸŽ“ ํ•™์Šต ํฌ์ธํŠธ: ์‹ค์ œ PG์‚ฌ ์—ฐ๋™์€ ์ด๋ณด๋‹ค ํ›จ์”ฌ ๋ณต์žกํ•ด. API ํ†ต์‹ , ์•”ํ˜ธํ™”, ์ฝœ๋ฐฑ ์ฒ˜๋ฆฌ ๋“ฑ์ด ํ•„์š”ํ•˜๊ฑฐ๋“ . ํ•˜์ง€๋งŒ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋Š” ๋™์ผํ•˜๋‹ˆ๊นŒ ์ด๊ฑธ ์ดํ•ดํ•˜๋ฉด ์–ด๋–ค ๊ฒŒ์ดํŠธ์›จ์ด๋“  ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด!

๐Ÿ’ณ ์‹ค์ œ PG ์—ฐ๋™ ์‹œ ๊ณ ๋ ค์‚ฌํ•ญ

๋ณด์•ˆ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

โœ… API ํ‚ค๋Š” ์ ˆ๋Œ€ ํ•˜๋“œ์ฝ”๋”ฉํ•˜์ง€ ๋ง๊ณ  ์„ค์ •์—์„œ ๊ด€๋ฆฌ
โœ… ๋ชจ๋“  ํ†ต์‹ ์€ HTTPS๋กœ๋งŒ ์ง„ํ–‰
โœ… ๊ฒฐ์ œ ๋ฐ์ดํ„ฐ๋Š” ์•”ํ˜ธํ™”ํ•ด์„œ ์ „์†ก
โœ… ์ฝœ๋ฐฑ URL์€ nonce๋‚˜ ํ† ํฐ์œผ๋กœ ๊ฒ€์ฆ
โœ… ๋ฏผ๊ฐํ•œ ์ •๋ณด๋Š” ๋กœ๊ทธ์— ๋‚จ๊ธฐ์ง€ ์•Š๊ธฐ
โœ… PCI DSS ์ปดํ”Œ๋ผ์ด์–ธ์Šค ์ค€์ˆ˜

ํŠนํžˆ ํ•œ๊ตญ์—์„œ๋Š” ์ด๋‹ˆ์‹œ์Šค, KG์ด๋‹ˆ์‹œ์Šค, ๋‚˜์ด์ŠคํŽ˜์ด, ํ† ์ŠคํŽ˜์ด๋จผ์ธ  ๊ฐ™์€ PG์‚ฌ๋“ค์ด ๋งŽ์ด ์“ฐ์ด๋Š”๋ฐ, ๊ฐ๊ฐ API ๋ฌธ์„œ๊ฐ€ ๋‹ค๋ฅด๋‹ˆ๊นŒ ๊ผผ๊ผผํžˆ ์ฝ์–ด๋ด์•ผ ํ•ด. ์žฌ๋Šฅ๋„ท์—์„œ PG ์—ฐ๋™ ๊ฒฝํ—˜์ด ์žˆ๋Š” ๊ฐœ๋ฐœ์ž๋ฅผ ์ฐพ์•„์„œ ๋ฉ˜ํ† ๋ง ๋ฐ›๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด์•ผ!

๐Ÿ“Š ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค์Šคํ„ฐ๋งˆ์ด์ง•

๋•Œ๋กœ๋Š” WooCommerce์˜ ๊ธฐ๋ณธ ํ…Œ์ด๋ธ”๋งŒ์œผ๋กœ๋Š” ๋ถ€์กฑํ•  ๋•Œ๊ฐ€ ์žˆ์–ด. ์ปค์Šคํ…€ ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ค์–ด์„œ ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž! ๐Ÿ—„๏ธ

๐Ÿ”จ ์ปค์Šคํ…€ ํ…Œ์ด๋ธ” ์ƒ์„ฑ

์˜ˆ๋ฅผ ๋“ค์–ด, ์ œํ’ˆ๋ณ„ ์ƒ์„ธ ๋ฆฌ๋ทฐ ํ†ต๊ณ„๋ฅผ ์ €์žฅํ•˜๋Š” ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ค์–ด๋ณด์ž:

class WC_Custom_Database {
    
    private $table_name;
    private $version = '1.0';
    
    public function __construct() {
        global $wpdb;
        $this->table_name = $wpdb->prefix . 'wc_product_review_stats';
        
        // ํ”Œ๋Ÿฌ๊ทธ์ธ ํ™œ์„ฑํ™” ์‹œ ํ…Œ์ด๋ธ” ์ƒ์„ฑ
        register_activation_hook(__FILE__, array($this, 'create_table'));
    }
    
    public function create_table() {
        global $wpdb;
        
        $charset_collate = $wpdb->get_charset_collate();
        
        $sql = "CREATE TABLE IF NOT EXISTS {$this->table_name} (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            product_id bigint(20) NOT NULL,
            total_reviews int(11) DEFAULT 0,
            average_rating decimal(3,2) DEFAULT 0.00,
            five_star int(11) DEFAULT 0,
            four_star int(11) DEFAULT 0,
            three_star int(11) DEFAULT 0,
            two_star int(11) DEFAULT 0,
            one_star int(11) DEFAULT 0,
            last_updated datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            PRIMARY KEY  (id),
            KEY product_id (product_id)
        ) $charset_collate;";
        
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);
        
        // ๋ฒ„์ „ ์ •๋ณด ์ €์žฅ
        add_option('wc_custom_db_version', $this->version);
    }
    
    // ๋ฆฌ๋ทฐ ํ†ต๊ณ„ ์—…๋ฐ์ดํŠธ
    public function update_review_stats($product_id) {
        global $wpdb;
        
        // ์ œํ’ˆ์˜ ๋ชจ๋“  ๋ฆฌ๋ทฐ ๊ฐ€์ ธ์˜ค๊ธฐ
        $reviews = get_comments(array(
            'post_id' => $product_id,
            'status' => 'approve',
            'type' => 'review'
        ));
        
        $stats = array(
            'total_reviews' => count($reviews),
            'five_star' => 0,
            'four_star' => 0,
            'three_star' => 0,
            'two_star' => 0,
            'one_star' => 0,
            'total_rating' => 0
        );
        
        // ๋ณ„์ ๋ณ„ ์นด์šดํŠธ
        foreach ($reviews as $review) {
            $rating = intval(get_comment_meta($review->comment_ID, 'rating', true));
            $stats['total_rating'] += $rating;
            
            switch ($rating) {
                case 5: $stats['five_star']++; break;
                case 4: $stats['four_star']++; break;
                case 3: $stats['three_star']++; break;
                case 2: $stats['two_star']++; break;
                case 1: $stats['one_star']++; break;
            }
        }
        
        // ํ‰๊ท  ๊ณ„์‚ฐ
        $average_rating = $stats['total_reviews'] > 0 
            ? round($stats['total_rating'] / $stats['total_reviews'], 2) 
            : 0;
        
        // ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ
        $existing = $wpdb->get_var($wpdb->prepare(
            "SELECT id FROM {$this->table_name} WHERE product_id = %d",
            $product_id
        ));
        
        $data = array(
            'product_id' => $product_id,
            'total_reviews' => $stats['total_reviews'],
            'average_rating' => $average_rating,
            'five_star' => $stats['five_star'],
            'four_star' => $stats['four_star'],
            'three_star' => $stats['three_star'],
            'two_star' => $stats['two_star'],
            'one_star' => $stats['one_star']
        );
        
        if ($existing) {
            // ์—…๋ฐ์ดํŠธ
            $wpdb->update(
                $this->table_name,
                $data,
                array('product_id' => $product_id),
                array('%d', '%d', '%f', '%d', '%d', '%d', '%d', '%d'),
                array('%d')
            );
        } else {
            // ์ƒˆ๋กœ ์‚ฝ์ž…
            $wpdb->insert(
                $this->table_name,
                $data,
                array('%d', '%d', '%f', '%d', '%d', '%d', '%d', '%d')
            );
        }
    }
    
    // ํ†ต๊ณ„ ์กฐํšŒ
    public function get_review_stats($product_id) {
        global $wpdb;
        
        return $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$this->table_name} WHERE product_id = %d",
            $product_id
        ), ARRAY_A);
    }
    
    // ์ธ๊ธฐ ์ œํ’ˆ ์กฐํšŒ (๋ฆฌ๋ทฐ ๋งŽ์€ ์ˆœ)
    public function get_most_reviewed_products($limit = 10) {
        global $wpdb;
        
        return $wpdb->get_results($wpdb->prepare(
            "SELECT product_id, total_reviews, average_rating 
            FROM {$this->table_name} 
            ORDER BY total_reviews DESC 
            LIMIT %d",
            $limit
        ), ARRAY_A);
    }
}

$wc_custom_db = new WC_Custom_Database();

// ๋ฆฌ๋ทฐ ์ž‘์„ฑ/์ˆ˜์ •/์‚ญ์ œ ์‹œ ํ†ต๊ณ„ ์—…๋ฐ์ดํŠธ
add_action('comment_post', function($comment_id, $approved) {
    $comment = get_comment($comment_id);
    if ($comment->comment_type === 'review' && $approved === 1) {
        global $wc_custom_db;
        $wc_custom_db->update_review_stats($comment->comment_post_ID);
    }
}, 10, 2);

add_action('edit_comment', function($comment_id) {
    $comment = get_comment($comment_id);
    if ($comment->comment_type === 'review') {
        global $wc_custom_db;
        $wc_custom_db->update_review_stats($comment->comment_post_ID);
    }
});

add_action('delete_comment', function($comment_id) {
    $comment = get_comment($comment_id);
    if ($comment->comment_type === 'review') {
        global $wc_custom_db;
        $wc_custom_db->update_review_stats($comment->comment_post_ID);
    }
});

โšก ์„ฑ๋Šฅ ์ตœ์ ํ™” ํŒ

โ€ข ์ž์ฃผ ์กฐํšŒํ•˜๋Š” ์ปฌ๋Ÿผ์—๋Š” ์ธ๋ฑ์Šค(KEY) ์ถ”๊ฐ€
โ€ข ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋Š” ํŽ˜์ด์ง€๋„ค์ด์…˜ ํ•„์ˆ˜
โ€ข ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋Š” ์บ์‹ฑ ํ™œ์šฉ (Transient API)
โ€ข JOIN์€ ์ตœ์†Œํ™”ํ•˜๊ณ  ํ•„์š”์‹œ ์„œ๋ธŒ์ฟผ๋ฆฌ ๊ณ ๋ ค
โ€ข ์ •๊ธฐ์ ์ธ ๋ฐ์ดํ„ฐ ์ •๋ฆฌ ํฌ๋ก ์žก ์„ค์ •

๐Ÿ“ˆ ํ†ต๊ณ„ ๋ฐ์ดํ„ฐ ์‹œ๊ฐํ™”

์ด์ œ ์ €์žฅํ•œ ํ†ต๊ณ„๋ฅผ ์˜ˆ์˜๊ฒŒ ๋ณด์—ฌ์ฃผ๋Š” ์œ„์ ฏ์„ ๋งŒ๋“ค์–ด๋ณด์ž:

class WC_Review_Stats_Widget extends WP_Widget {
    
    public function __construct() {
        parent::__construct(
            'wc_review_stats_widget',
            __('์ œํ’ˆ ๋ฆฌ๋ทฐ ํ†ต๊ณ„', 'wc-custom-fields'),
            array('description' => __('์ œํ’ˆ์˜ ๋ฆฌ๋ทฐ ํ†ต๊ณ„๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค', 'wc-custom-fields'))
        );
    }
    
    public function widget($args, $instance) {
        global $product, $wc_custom_db;
        
        if (!is_product() || !$product) {
            return;
        }
        
        $stats = $wc_custom_db->get_review_stats($product->get_id());
        
        if (!$stats || $stats['total_reviews'] == 0) {
            return;
        }
        
        echo $args['before_widget'];
        
        if (!empty($instance['title'])) {
            echo $args['before_title'] . apply_filters('widget_title', $instance['title']) . $args['after_title'];
        }
        
        ?>
        <div class="review-stats-widget">
            <div class="average-rating">
                <span class="rating-number"><?php echo $stats['average_rating']; ?></span>
                <span class="rating-stars">
                    <?php echo wc_get_rating_html($stats['average_rating']); ?>
                </span>
                <span class="total-reviews">
                    <?php printf(__('%d๊ฐœ์˜ ๋ฆฌ๋ทฐ', 'wc-custom-fields'), $stats['total_reviews']); ?>
                </span>
            </div>
            
            <div class="rating-breakdown">
                <?php
                $ratings = array(
                    5 => $stats['five_star'],
                    4 => $stats['four_star'],
                    3 => $stats['three_star'],
                    2 => $stats['two_star'],
                    1 => $stats['one_star']
                );
                
                foreach ($ratings as $star => $count) {
                    $percentage = $stats['total_reviews'] > 0 
                        ? ($count / $stats['total_reviews']) * 100 
                        : 0;
                    ?>
                    <div class="rating-row">
                        <span class="star-label"><?php echo $star; ?>โญ</span>
                        <div class="rating-bar">
                            <div class="rating-fill" style="width: <?php echo $percentage; ?>%"></div>
                        </div>
                        <span class="rating-count"><?php echo $count; ?></span>
                    </div>
                    <?php
                }
                ?>
            </div>
        </div>
        <?php
        
        echo $args['after_widget'];
    }
    
    public function form($instance) {
        $title = !empty($instance['title']) ? $instance['title'] : __('๋ฆฌ๋ทฐ ํ†ต๊ณ„', 'wc-custom-fields');
        ?>
        <p>
            <label for="<?php echo $this->get_field_id('title'); ?>">
                <?php _e('์ œ๋ชฉ:', 'wc-custom-fields'); ?>
            </label>
            <input class="widefat" 
                   id="<?php echo $this->get_field_id('title'); ?>" 
                   name="<?php echo $this->get_field_name('title'); ?>" 
                   type="text" 
                   value="<?php echo esc_attr($title); ?>">
        </p>
        <?php
    }
    
    public function update($new_instance, $old_instance) {
        $instance = array();
        $instance['title'] = (!empty($new_instance['title'])) 
            ? sanitize_text_field($new_instance['title']) 
            : '';
        return $instance;
    }
}

// ์œ„์ ฏ ๋“ฑ๋ก
function register_review_stats_widget() {
    register_widget('WC_Review_Stats_Widget');
}
add_action('widgets_init', 'register_review_stats_widget');

์ด ์œ„์ ฏ์€ ์ œํ’ˆ ํŽ˜์ด์ง€ ์‚ฌ์ด๋“œ๋ฐ”์— ๋ฐฐ์น˜ํ•˜๋ฉด ๊ณ ๊ฐ๋“ค์ด ํ•œ๋ˆˆ์— ๋ฆฌ๋ทฐ ๋ถ„ํฌ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์–ด์„œ ๊ตฌ๋งค ๊ฒฐ์ •์— ๋„์›€์„ ์ค˜. ์‹ค์ œ๋กœ ์ด๋Ÿฐ ์‹œ๊ฐํ™”๋Š” ์ „ํ™˜์œจ์„ ๋†’์ด๋Š” ๋ฐ ํšจ๊ณผ์ ์ด์•ผ! ๐Ÿ“Š

๐ŸŒ REST API ํ™•์žฅํ•˜๊ธฐ

๋ชจ๋ฐ”์ผ ์•ฑ์ด๋‚˜ ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ ์—ฐ๋™ํ•˜๋ ค๋ฉด REST API๋ฅผ ์ž˜ ๋‹ค๋ค„์•ผ ํ•ด. WooCommerce๋Š” ๊ฐ•๋ ฅํ•œ REST API๋ฅผ ์ œ๊ณตํ•˜์ง€๋งŒ, ๋•Œ๋กœ๋Š” ์ปค์Šคํ…€ ์—”๋“œํฌ์ธํŠธ๊ฐ€ ํ•„์š”ํ•˜๊ฑฐ๋“ ! ๐Ÿš€

๐Ÿ”Œ ์ปค์Šคํ…€ API ์—”๋“œํฌ์ธํŠธ ๋งŒ๋“ค๊ธฐ

์˜ˆ๋ฅผ ๋“ค์–ด, ํŠน์ • ์นดํ…Œ๊ณ ๋ฆฌ์˜ ์ธ๊ธฐ ์ œํ’ˆ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” API๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž:

class WC_Custom_REST_API {
    
    private $namespace = 'wc-custom/v1';
    
    public function __construct() {
        add_action('rest_api_init', array($this, 'register_routes'));
    }
    
    public function register_routes() {
        // ์ธ๊ธฐ ์ œํ’ˆ ์กฐํšŒ
        register_rest_route($this->namespace, '/popular-products', array(
            'methods' => 'GET',
            'callback' => array($this, 'get_popular_products'),
            'permission_callback' => '__return_true',
            'args' => array(
                'category' => array(
                    'required' => false,
                    'type' => 'string',
                    'description' => '์นดํ…Œ๊ณ ๋ฆฌ ์Šฌ๋Ÿฌ๊ทธ'
                ),
                'limit' => array(
                    'required' => false,
                    'type' => 'integer',
                    'default' => 10,
                    'minimum' => 1,
                    'maximum' => 100
                )
            )
        ));
        
        // ์ œํ’ˆ ์ƒ์„ธ ํ†ต๊ณ„
        register_rest_route($this->namespace, '/product-stats/(?P<id>\d+)', array(
            'methods' => 'GET',
            'callback' => array($this, 'get_product_stats'),
            'permission_callback' => '__return_true',
            'args' => array(
                'id' => array(
                    'required' => true,
                    'type' => 'integer',
                    'description' => '์ œํ’ˆ ID'
                )
            )
        ));
        
        // ์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ์ œํ’ˆ ์ถ”๊ฐ€ (์ธ์ฆ ํ•„์š”)
        register_rest_route($this->namespace, '/cart/add', array(
            'methods' => 'POST',
            'callback' => array($this, 'add_to_cart'),
            'permission_callback' => array($this, 'check_authentication'),
            'args' => array(
                'product_id' => array(
                    'required' => true,
                    'type' => 'integer'
                ),
                'quantity' => array(
                    'required' => false,
                    'type' => 'integer',
                    'default' => 1
                )
            )
        ));
    }
    
    public function get_popular_products($request) {
        $category = $request->get_param('category');
        $limit = $request->get_param('limit');
        
        $args = array(
            'post_type' => 'product',
            'posts_per_page' => $limit,
            'meta_key' => 'total_sales',
            'orderby' => 'meta_value_num',
            'order' => 'DESC'
        );
        
        // ์นดํ…Œ๊ณ ๋ฆฌ ํ•„ํ„ฐ
        if ($category) {
            $args['tax_query'] = array(
                array(
                    'taxonomy' => 'product_cat',
                    'field' => 'slug',
                    'terms' => $category
                )
            );
        }
        
        $query = new WP_Query($args);
        $products = array();
        
        if ($query->have_posts()) {
            while ($query->have_posts()) {
                $query->the_post();
                $product = wc_get_product(get_the_ID());
                
                $products[] = array(
                    'id' => $product->get_id(),
                    'name' => $product->get_name(),
                    'price' => $product->get_price(),
                    'regular_price' => $product->get_regular_price(),
                    'sale_price' => $product->get_sale_price(),
                    'on_sale' => $product->is_on_sale(),
                    'stock_status' => $product->get_stock_status(),
                    'image' => wp_get_attachment_url($product->get_image_id()),
                    'permalink' => get_permalink($product->get_id()),
                    'total_sales' => $product->get_total_sales(),
                    'average_rating' => $product->get_average_rating(),
                    'rating_count' => $product->get_rating_count()
                );
            }
            wp_reset_postdata();
        }
        
        return new WP_REST_Response(array(
            'success' => true,
            'data' => $products,
            'total' => count($products)
        ), 200);
    }
    
    public function get_product_stats($request) {
        global $wc_custom_db;
        
        $product_id = $request->get_param('id');
        $product = wc_get_product($product_id);
        
        if (!$product) {
            return new WP_Error(
                'product_not_found',
                __('์ œํ’ˆ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค', 'wc-custom-fields'),
                array('status' => 404)
            );
        }
        
        $stats = $wc_custom_db->get_review_stats($product_id);
        
        $data = array(
            'product_id' => $product_id,
            'name' => $product->get_name(),
            'total_sales' => $product->get_total_sales(),
            'stock_quantity' => $product->get_stock_quantity(),
            'reviews' => $stats ? $stats : array(
                'total_reviews' => 0,
                'average_rating' => 0
            ),
            'views' => get_post_meta($product_id, 'product_views', true) ?: 0
        );
        
        return new WP_REST_Response(array(
            'success' => true,
            'data' => $data
        ), 200);
    }
    
    public function add_to_cart($request) {
        $product_id = $request->get_param('product_id');
        $quantity = $request->get_param('quantity');
        
        // ์ œํ’ˆ ์กด์žฌ ํ™•์ธ
        $product = wc_get_product($product_id);
        if (!$product) {
            return new WP_Error(
                'invalid_product',
                __('์œ ํšจํ•˜์ง€ ์•Š์€ ์ œํ’ˆ์ž…๋‹ˆ๋‹ค', 'wc-custom-fields'),
                array('status' => 400)
            );
        }
        
        // ์žฌ๊ณ  ํ™•์ธ
        if (!$product->is_in_stock()) {
            return new WP_Error(
                'out_of_stock',
                __('ํ’ˆ์ ˆ๋œ ์ƒํ’ˆ์ž…๋‹ˆ๋‹ค', 'wc-custom-fields'),
                array('status' => 400)
            );
        }
        
        // ์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ์ถ”๊ฐ€
        $cart_item_key = WC()->cart->add_to_cart($product_id, $quantity);
        
        if ($cart_item_key) {
            return new WP_REST_Response(array(
                'success' => true,
                'message' => __('์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค', 'wc-custom-fields'),
                'cart_item_key' => $cart_item_key,
                'cart_total' => WC()->cart->get_cart_contents_count()
            ), 200);
        } else {
            return new WP_Error(
                'add_to_cart_failed',
                __('์žฅ๋ฐ”๊ตฌ๋‹ˆ ์ถ”๊ฐ€์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค', 'wc-custom-fields'),
                array('status' => 500)
            );
        }
    }
    
    public function check_authentication($request) {
        // JWT ํ† ํฐ์ด๋‚˜ API ํ‚ค ๊ฒ€์ฆ ๋กœ์ง
        // ์—ฌ๊ธฐ์„œ๋Š” ๊ฐ„๋‹จํžˆ ๋กœ๊ทธ์ธ ์—ฌ๋ถ€๋งŒ ์ฒดํฌ
        return is_user_logged_in();
    }
}

new WC_Custom_REST_API();

๐Ÿ” API ๋ณด์•ˆ ํŒ: ์‹ค์ œ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ๋Š” JWT ํ† ํฐ์ด๋‚˜ OAuth 2.0์„ ์‚ฌ์šฉํ•ด์„œ ์ธ์ฆ์„ ๊ตฌํ˜„ํ•ด์•ผ ํ•ด. WooCommerce๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ Consumer Key์™€ Consumer Secret์„ ์ œ๊ณตํ•˜๋‹ˆ๊นŒ ์ด๊ฑธ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์•„!

๐Ÿ“ฑ API ํ…Œ์ŠคํŠธํ•˜๊ธฐ

API๋ฅผ ๋งŒ๋“ค์—ˆ์œผ๋ฉด ํ…Œ์ŠคํŠธํ•ด๋ด์•ผ๊ฒ ์ง€? Postman์ด๋‚˜ cURL๋กœ ๊ฐ„๋‹จํžˆ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์–ด:

# ์ธ๊ธฐ ์ œํ’ˆ ์กฐํšŒ
curl -X GET "https://yoursite.com/wp-json/wc-custom/v1/popular-products?category=electronics&limit=5"

# ์ œํ’ˆ ํ†ต๊ณ„ ์กฐํšŒ
curl -X GET "https://yoursite.com/wp-json/wc-custom/v1/product-stats/123"

# ์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ์ถ”๊ฐ€ (์ฟ ํ‚ค ํ•„์š”)
curl -X POST "https://yoursite.com/wp-json/wc-custom/v1/cart/add" \
  -H "Content-Type: application/json" \
  -d '{"product_id": 123, "quantity": 2}' \
  --cookie "wordpress_logged_in_xxx=..."

API ์‘๋‹ต์€ ํ•ญ์ƒ ์ผ๊ด€๋œ ํ˜•์‹์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒŒ ์ข‹์•„. ์„ฑ๊ณต ์‹œ์—๋Š” success: true์™€ ํ•จ๊ป˜ ๋ฐ์ดํ„ฐ๋ฅผ, ์‹คํŒจ ์‹œ์—๋Š” ๋ช…ํ™•ํ•œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ํฌํ•จ์‹œ์ผœ์•ผ ํ•ด!

โšก ์„ฑ๋Šฅ ์ตœ์ ํ™” ์ „๋žต

์‡ผํ•‘๋ชฐ์€ ์†๋„๊ฐ€ ์ƒ๋ช…์ด์•ผ! ๋กœ๋”ฉ์ด 1์ดˆ ๋Šฆ์–ด์งˆ ๋•Œ๋งˆ๋‹ค ์ „ํ™˜์œจ์ด 7% ๋–จ์–ด์ง„๋‹ค๋Š” ์—ฐ๊ตฌ ๊ฒฐ๊ณผ๋„ ์žˆ๊ฑฐ๋“ . ์„ฑ๋Šฅ ์ตœ์ ํ™”๋Š” ์„ ํƒ์ด ์•„๋‹ˆ๋ผ ํ•„์ˆ˜์•ผ! ๐Ÿ’จ

๐Ÿš€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ ์ตœ์ ํ™”

1. ๋ถˆํ•„์š”ํ•œ ์ฟผ๋ฆฌ ์ œ๊ฑฐ

Query Monitor ํ”Œ๋Ÿฌ๊ทธ์ธ์œผ๋กœ ์ค‘๋ณต ์ฟผ๋ฆฌ๋ฅผ ์ฐพ์•„๋‚ด. ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์กฐํšŒํ•˜๊ณ  ์žˆ๋‹ค๋ฉด ๋ณ€์ˆ˜์— ์ €์žฅํ•ด์„œ ์žฌ์‚ฌ์šฉํ•ด!

// โŒ ๋‚˜์œ ์˜ˆ: ๋ฃจํ”„ ์•ˆ์—์„œ ๋ฐ˜๋ณต ์ฟผ๋ฆฌ
foreach ($product_ids as $id) {
    $product = wc_get_product($id); // ๋งค๋ฒˆ DB ์กฐํšŒ!
    echo $product->get_name();
}

// โœ… ์ข‹์€ ์˜ˆ: ํ•œ ๋ฒˆ์— ์กฐํšŒ
$products = wc_get_products(array(
    'include' => $product_ids,
    'limit' => -1
));

foreach ($products as $product) {
    echo $product->get_name();
}

2. ์บ์‹ฑ ํ™œ์šฉ

์ž์ฃผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ์ž์ฃผ ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ๋Š” Transient API๋กœ ์บ์‹ฑํ•ด:

function get_featured_products_cached() {
    $cache_key = 'featured_products_list';
    $products = get_transient($cache_key);
    
    if (false === $products) {
        // ์บ์‹œ๊ฐ€ ์—†์œผ๋ฉด DB์—์„œ ์กฐํšŒ
        $products = wc_get_products(array(
            'featured' => true,
            'limit' => 10,
            'orderby' => 'popularity'
        ));
        
        // 1์‹œ๊ฐ„ ๋™์•ˆ ์บ์‹œ
        set_transient($cache_key, $products, HOUR_IN_SECONDS);
    }
    
    return $products;
}

// ์ œํ’ˆ ์—…๋ฐ์ดํŠธ ์‹œ ์บ์‹œ ์‚ญ์ œ
add_action('woocommerce_update_product', function($product_id) {
    delete_transient('featured_products_list');
});

3. ๊ฐ์ฒด ์บ์‹ฑ

Redis๋‚˜ Memcached ๊ฐ™์€ ๊ฐ์ฒด ์บ์‹œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์„ฑ๋Šฅ์ด ๊ทน์ ์œผ๋กœ ํ–ฅ์ƒ๋ผ:

function get_product_with_cache($product_id) {
    $cache_key = 'product_data_' . $product_id;
    $product_data = wp_cache_get($cache_key, 'products');
    
    if (false === $product_data) {
        $product = wc_get_product($product_id);
        
        $product_data = array(
            'id' => $product->get_id(),
            'name' => $product->get_name(),
            'price' => $product->get_price(),
            'stock' => $product->get_stock_status()
        );
        
        wp_cache_set($cache_key, $product_data, 'products', 3600);
    }
    
    return $product_data;
}

๐ŸŽจ ํ”„๋ก ํŠธ์—”๋“œ ์ตœ์ ํ™”

์ด๋ฏธ์ง€ ์ตœ์ ํ™”

โ€ข WebP ํฌ๋งท ์‚ฌ์šฉ (์šฉ๋Ÿ‰ 30% ๊ฐ์†Œ)
โ€ข Lazy Loading ์ ์šฉ
โ€ข ์ ์ ˆํ•œ ์ด๋ฏธ์ง€ ํฌ๊ธฐ ์‚ฌ์šฉ (์ธ๋„ค์ผ, ์ค‘๊ฐ„, ํฐ ํฌ๊ธฐ)
โ€ข CDN ํ™œ์šฉ
โ€ข ์ด๋ฏธ์ง€ ์••์ถ• ํ”Œ๋Ÿฌ๊ทธ์ธ ์‚ฌ์šฉ (Imagify, ShortPixel ๋“ฑ)

// ์ด๋ฏธ์ง€ Lazy Loading ์ถ”๊ฐ€
add_filter('wp_get_attachment_image_attributes', function($attr) {
    if (!is_admin()) {
        $attr['loading'] = 'lazy';
    }
    return $attr;
});

// WebP ์ง€์›
add_filter('wp_generate_attachment_metadata', function($metadata, $attachment_id) {
    $file = get_attached_file($attachment_id);
    
    if (function_exists('imagewebp')) {
        $image = wp_get_image_editor($file);
        
        if (!is_wp_error($image)) {
            $webp_file = preg_replace('/\.(jpg|jpeg|png)$/i', '.webp', $file);
            $image->save($webp_file, 'image/webp');
        }
    }
    
    return $metadata;
}, 10, 2);

JavaScript/CSS ์ตœ์ ํ™”

โ€ข ํ•„์š”ํ•œ ํŽ˜์ด์ง€์—์„œ๋งŒ ์Šคํฌ๋ฆฝํŠธ ๋กœ๋“œ
โ€ข ํŒŒ์ผ ์••์ถ• ๋ฐ ๋ณ‘ํ•ฉ
โ€ข ๋น„๋™๊ธฐ ๋กœ๋”ฉ ํ™œ์šฉ
โ€ข Critical CSS ์ธ๋ผ์ธ ์ฒ˜๋ฆฌ

// ํŠน์ • ํŽ˜์ด์ง€์—์„œ๋งŒ ์Šคํฌ๋ฆฝํŠธ ๋กœ๋“œ
function enqueue_conditional_scripts() {
    // ์ œํ’ˆ ํŽ˜์ด์ง€๊ฐ€ ์•„๋‹ˆ๋ฉด ์ œํ’ˆ ๊ด€๋ จ JS ๋กœ๋“œ ์•ˆ ํ•จ
    if (!is_product()) {
        wp_dequeue_script('wc-single-product');
        wp_dequeue_script('zoom');
        wp_dequeue_script('flexslider');
    }
    
    // ์žฅ๋ฐ”๊ตฌ๋‹ˆ/๊ฒฐ์ œ ํŽ˜์ด์ง€๊ฐ€ ์•„๋‹ˆ๋ฉด ๊ฒฐ์ œ ์Šคํฌ๋ฆฝํŠธ ๋กœ๋“œ ์•ˆ ํ•จ
    if (!is_cart() && !is_checkout()) {
        wp_dequeue_script('wc-cart');
        wp_dequeue_script('wc-checkout');
    }
}
add_action('wp_enqueue_scripts', 'enqueue_conditional_scripts', 100);

๐Ÿ—„๏ธ ์„œ๋ฒ„ ๋ ˆ๋ฒจ ์ตœ์ ํ™”

PHP ์„ค์ • ์ตœ์ ํ™”

โ€ข PHP 7.4 ์ด์ƒ ์‚ฌ์šฉ (PHP 8.x ๊ถŒ์žฅ)
โ€ข OPcache ํ™œ์„ฑํ™”
โ€ข memory_limit ์ตœ์†Œ 256MB
โ€ข max_execution_time ์ ์ ˆํžˆ ์„ค์ •

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ตœ์ ํ™”

โ€ข ์ •๊ธฐ์ ์ธ ํ…Œ์ด๋ธ” ์ตœ์ ํ™”
โ€ข ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋น„์ „ ์‚ญ์ œ
โ€ข ํŠธ๋žœ์ง€์–ธํŠธ ์ •๋ฆฌ
โ€ข ์ธ๋ฑ์Šค ์ตœ์ ํ™”

// ์ฃผ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ •๋ฆฌ ํฌ๋ก ์žก
function schedule_db_cleanup() {
    if (!wp_next_scheduled('weekly_db_cleanup')) {
        wp_schedule_event(time(), 'weekly', 'weekly_db_cleanup');
    }
}
add_action('wp', 'schedule_db_cleanup');

function perform_db_cleanup() {
    global $wpdb;
    
    // ์˜ค๋ž˜๋œ ํŠธ๋žœ์ง€์–ธํŠธ ์‚ญ์ œ
    $wpdb->query("DELETE FROM {$wpdb->options} 
                  WHERE option_name LIKE '_transient_%' 
                  AND option_value < UNIX_TIMESTAMP()");
    
    // ์˜ค๋ž˜๋œ ์žฅ๋ฐ”๊ตฌ๋‹ˆ ์„ธ์…˜ ์‚ญ์ œ (30์ผ ์ด์ƒ)
    $wpdb->query("DELETE FROM {$wpdb->prefix}woocommerce_sessions 
                  WHERE session_expiry < UNIX_TIMESTAMP() - (30 * 24 * 60 * 60)");
    
    // ํ…Œ์ด๋ธ” ์ตœ์ ํ™”
    $tables = $wpdb->get_results("SHOW TABLES", ARRAY_N);
    foreach ($tables as $table) {
        $wpdb->query("OPTIMIZE TABLE {$table[0]}");
    }
}
add_action('weekly_db_cleanup', 'perform_db_cleanup');

๐Ÿ’ก ์‹ค์ „ ํŒ: GTmetrix๋‚˜ Google PageSpeed Insights๋กœ ์ •๊ธฐ์ ์œผ๋กœ ์„ฑ๋Šฅ์„ ์ธก์ •ํ•ด. ๋ชฉํ‘œ๋Š” ๋ชจ๋ฐ”์ผ์—์„œ 3์ดˆ ์ด๋‚ด ๋กœ๋”ฉ์ด์•ผ. ์ด๊ฒŒ ์•ˆ ๋˜๋ฉด ๊ณ ๊ฐ์˜ ์ ˆ๋ฐ˜์€ ์ดํƒˆํ•œ๋‹ค๊ณ  ๋ด์•ผ ํ•ด!

๐Ÿ”’ ๋ณด์•ˆ ๊ฐ•ํ™”ํ•˜๊ธฐ

์‡ผํ•‘๋ชฐ์€ ๊ณ ๊ฐ์˜ ๊ฐœ์ธ์ •๋ณด์™€ ๊ฒฐ์ œ ์ •๋ณด๋ฅผ ๋‹ค๋ฃจ๊ธฐ ๋•Œ๋ฌธ์— ๋ณด์•ˆ์ด ์ •๋ง ์ค‘์š”ํ•ด. ํ•œ ๋ฒˆ์˜ ๋ณด์•ˆ ์‚ฌ๊ณ ๋กœ ์Œ“์•„์˜จ ์‹ ๋ขฐ๊ฐ€ ๋ฌด๋„ˆ์งˆ ์ˆ˜ ์žˆ๊ฑฐ๋“ ! ๐Ÿ›ก๏ธ

๐Ÿšจ ํ•„์ˆ˜ ๋ณด์•ˆ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

1. ์ž…๋ ฅ ๊ฒ€์ฆ ๋ฐ ์‚ด๊ท 

๋ชจ๋“  ์‚ฌ์šฉ์ž ์ž…๋ ฅ์€ ์˜์‹ฌํ•˜๊ณ  ๊ฒ€์ฆํ•ด์•ผ ํ•ด:

// ์‚ฌ์šฉ์ž ์ž…๋ ฅ ์ฒ˜๋ฆฌ ์˜ˆ์ œ
function process_custom_form_data() {
    // Nonce ๊ฒ€์ฆ (CSRF ๋ฐฉ์ง€)
    if (!isset($_POST['custom_nonce']) || 
        !wp_verify_nonce($_POST['custom_nonce'], 'custom_form_action')) {
        wp_die(__('๋ณด์•ˆ ๊ฒ€์ฆ ์‹คํŒจ', 'wc-custom-fields'));
    }
    
    // ๊ถŒํ•œ ํ™•์ธ
    if (!current_user_can('edit_posts')) {
        wp_die(__('๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค', 'wc-custom-fields'));
    }
    
    // ์ž…๋ ฅ๊ฐ’ ์‚ด๊ท 
    $text_field = isset($_POST['text_field']) 
        ? sanitize_text_field($_POST['text_field']) 
        : '';
    
    $email = isset($_POST['email']) 
        ? sanitize_email($_POST['email']) 
        : '';
    
    $url = isset($_POST['url']) 
        ? esc_url_raw($_POST['url']) 
        : '';
    
    $number = isset($_POST['number']) 
        ? absint($_POST['number']) 
        : 0;
    
    // HTML ํ—ˆ์šฉ ์‹œ (์ œํ•œ์ ์œผ๋กœ)
    $allowed_html = array(
        'a' => array('href' => array(), 'title' => array()),
        'br' => array(),
        'em' => array(),
        'strong' => array()
    );
    $html_content = isset($_POST['content']) 
        ? wp_kses($_POST['content'], $allowed_html) 
        : '';
    
    // ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ...
}

// ์ถœ๋ ฅ ์‹œ ์ด์Šค์ผ€์ดํ”„
function display_user_content($content) {
    // HTML ์ถœ๋ ฅ
    echo wp_kses_post($content);
    
    // ์ผ๋ฐ˜ ํ…์ŠคํŠธ
    echo esc_html($text);
    
    // ์†์„ฑ๊ฐ’
    echo '<div data-value="' . esc_attr($value) . '">';
    
    // URL
    echo '<a href="' . esc_url($url) . '">';
    
    // JavaScript
    echo '<script>var data = ' . wp_json_encode($data) . ';</script>';
}

2. SQL ์ธ์ ์…˜ ๋ฐฉ์ง€

์ง์ ‘ SQL ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ๋Š” ๋ฐ˜๋“œ์‹œ prepared statement๋ฅผ ์‚ฌ์šฉํ•ด:

// โŒ ์œ„ํ—˜ํ•œ ์ฝ”๋“œ
$user_id = $_GET['user_id'];
$query = "SELECT * FROM {$wpdb->users} WHERE ID = $user_id";
$result = $wpdb->get_results($query);

// โœ… ์•ˆ์ „ํ•œ ์ฝ”๋“œ
$user_id = isset($_GET['user_id']) ? absint($_GET['user_id']) : 0;
$query = $wpdb->prepare(
    "SELECT * FROM {$wpdb->users} WHERE ID = %d",
    $user_id
);
$result = $wpdb->get_results($query);

// ๋ณต์žกํ•œ ์ฟผ๋ฆฌ ์˜ˆ์ œ
$product_ids = array(1, 2, 3, 4, 5);
$placeholders = implode(',', array_fill(0, count($product_ids), '%d'));
$query = $wpdb->prepare(
    "SELECT * FROM {$wpdb->posts} 
    WHERE ID IN ($placeholders) 
    AND post_type = %s 
    AND post_status = %s",
    array_merge($product_ids, array('product', 'publish'))
);
$products = $wpdb->get_results($query);

3. ํŒŒ์ผ ์—…๋กœ๋“œ ๋ณด์•ˆ

ํŒŒ์ผ ์—…๋กœ๋“œ๋Š” ํŠนํžˆ ์กฐ์‹ฌํ•ด์•ผ ํ•ด:

function secure_file_upload($file) {
    // ํŒŒ์ผ ํƒ€์ž… ๊ฒ€์ฆ
    $allowed_types = array('jpg', 'jpeg', 'png', 'gif', 'pdf');
    $file_ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
    
    if (!in_array($file_ext, $allowed_types)) {
        return new WP_Error('invalid_file_type', 
            __('ํ—ˆ์šฉ๋˜์ง€ ์•Š๋Š” ํŒŒ์ผ ํ˜•์‹์ž…๋‹ˆ๋‹ค', 'wc-custom-fields'));
    }
    
    // MIME ํƒ€์ž… ๊ฒ€์ฆ
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mime_type = finfo_file($finfo, $file['tmp_name']);
    finfo_close($finfo);
    
    $allowed_mimes = array(
        'image/jpeg',
        'image/png',
        'image/gif',
        'application/pdf'
    );
    
    if (!in_array($mime_type, $allowed_mimes)) {
        return new WP_Error('invalid_mime_type', 
            __('ํŒŒ์ผ ๋‚ด์šฉ์ด ํ™•์žฅ์ž์™€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค', 'wc-custom-fields'));
    }
    
    // ํŒŒ์ผ ํฌ๊ธฐ ์ œํ•œ (5MB)
    $max_size = 5 * 1024 * 1024;
    if ($file['size'] > $max_size) {
        return new WP_Error('file_too_large', 
            __('ํŒŒ์ผ ํฌ๊ธฐ๋Š” 5MB๋ฅผ ์ดˆ๊ณผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค', 'wc-custom-fields'));
    }
    
    // ํŒŒ์ผ๋ช… ์‚ด๊ท 
    $file['name'] = sanitize_file_name($file['name']);
    
    // ์›Œ๋“œํ”„๋ ˆ์Šค ์—…๋กœ๋“œ ์ฒ˜๋ฆฌ
    require_once(ABSPATH . 'wp-admin/includes/file.php');
    $upload = wp_handle_upload($file, array('test_form' => false));
    
    if (isset($upload['error'])) {
        return new WP_Error('upload_failed', $upload['error']);
    }
    
    return $upload;
}

๐Ÿ” ์ถ”๊ฐ€ ๋ณด์•ˆ ์กฐ์น˜

API ํ‚ค ๊ด€๋ฆฌ

API ํ‚ค๋‚˜ ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ์ ˆ๋Œ€ ์ฝ”๋“œ์— ํ•˜๋“œ์ฝ”๋”ฉํ•˜์ง€ ๋งˆ!

// wp-config.php์— ์ •์˜
define('CUSTOM_API_KEY', 'your-secret-key-here');
define('CUSTOM_API_SECRET', 'your-secret-here');

// ํ”Œ๋Ÿฌ๊ทธ์ธ์—์„œ ์‚ฌ์šฉ
$api_key = defined('CUSTOM_API_KEY') ? CUSTOM_API_KEY : '';

// ๋˜๋Š” ์˜ต์…˜์œผ๋กœ ์ €์žฅ (์•”ํ˜ธํ™” ๊ถŒ์žฅ)
function save_encrypted_api_key($key) {
    $encrypted = base64_encode($key); // ์‹ค์ œ๋กœ๋Š” ๋” ๊ฐ•๋ ฅํ•œ ์•”ํ˜ธํ™” ์‚ฌ์šฉ
    update_option('encrypted_api_key', $encrypted);
}

function get_decrypted_api_key() {
    $encrypted = get_option('encrypted_api_key');
    return base64_decode($encrypted);
}

Rate Limiting

API ๋‚จ์šฉ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•œ ์š”์ฒญ ์ œํ•œ:

class API_Rate_Limiter {
    
    private $max_requests = 100; // ์‹œ๊ฐ„๋‹น ์ตœ๋Œ€ ์š”์ฒญ ์ˆ˜
    private $time_window = 3600; // 1์‹œ๊ฐ„
    
    public function check_rate_limit($user_id) {
        $transient_key = 'api_requests_' . $user_id;
        $requests = get_transient($transient_key);
        
        if (false === $requests) {
            $requests = array();
        }
        
        // ํ˜„์žฌ ์‹œ๊ฐ„ ์œˆ๋„์šฐ ๋‚ด์˜ ์š”์ฒญ๋งŒ ์นด์šดํŠธ
        $current_time = time();
        $requests = array_filter($requests, function($timestamp) use ($current_time) {
            return ($current_time - $timestamp) < $this->time_window;
        });
        
        // ์ œํ•œ ์ดˆ๊ณผ ํ™•์ธ
        if (count($requests) >= $this->max_requests) {
            return new WP_Error(
                'rate_limit_exceeded',
                __('์š”์ฒญ ํ•œ๋„๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค. ์ž ์‹œ ํ›„ ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.', 'wc-custom-fields'),
                array('status' => 429)
            );
        }
        
        // ์ƒˆ ์š”์ฒญ ๊ธฐ๋ก
        $requests[] = $current_time;
        set_transient($transient_key, $requests, $this->time_window);
        
        return true;
    }
}

// REST API์— ์ ์šฉ
add_filter('rest_pre_dispatch', function($result, $server, $request) {
    $limiter = new API_Rate_Limiter();
    $user_id = get_current_user_id() ?: $_SERVER['REMOTE_ADDR'];
    
    $check = $limiter->check_rate_limit($user_id);
    if (is_wp_error($check)) {
        return $check;
    }
    
    return $result;
}, 10, 3);

๐Ÿ”’ ๋ณด์•ˆ ํ”Œ๋Ÿฌ๊ทธ์ธ ์ถ”์ฒœ: Wordfence Security, iThemes Security, Sucuri Security ๊ฐ™์€ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ธฐ๋ณธ์ ์ธ ๋ณด์•ˆ์€ ์ž๋™์œผ๋กœ ๊ด€๋ฆฌ๋ผ. ํ•˜์ง€๋งŒ ์ปค์Šคํ…€ ์ฝ”๋“œ์˜ ๋ณด์•ˆ์€ ๊ฐœ๋ฐœ์ž์˜ ์ฑ…์ž„์ด์•ผ!

๐Ÿงช ํ…Œ์ŠคํŠธ ๋ฐ ๋””๋ฒ„๊น…

์™„๋ฒฝํ•œ ์ฝ”๋“œ๋Š” ์—†์–ด. ์ค‘์š”ํ•œ ๊ฑด ๋ฒ„๊ทธ๋ฅผ ๋นจ๋ฆฌ ์ฐพ์•„๋‚ด๊ณ  ๊ณ ์น˜๋Š” ๊ฑฐ์ง€! ์ฒด๊ณ„์ ์ธ ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž. ๐Ÿ”

๐ŸŽฏ ์œ ๋‹› ํ…Œ์ŠคํŠธ ์ž‘์„ฑ

PHPUnit์„ ์‚ฌ์šฉํ•ด์„œ ์ฝ”๋“œ๋ฅผ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์–ด:

// tests/test-product-fields.php
class Test_Product_Fields extends WP_UnitTestCase {
    
    private $product_id;
    
    public function setUp() {
        parent::setUp();
        
        // ํ…Œ์ŠคํŠธ์šฉ ์ œํ’ˆ ์ƒ์„ฑ
        $this->product_id = wp_insert_post(array(
            'post_title' => 'Test Product',
            'post_type' => 'product',
            'post_status' => 'publish'
        ));
    }
    
    public function tearDown() {
        // ํ…Œ์ŠคํŠธ ํ›„ ์ •๋ฆฌ
        wp_delete_post($this->product_id, true);
        parent::tearDown();
    }
    
    public function test_custom_field_save() {
        // ์ปค์Šคํ…€ ํ•„๋“œ ์ €์žฅ
        update_post_meta($this->product_id, '_custom_text_field', 'Test Value');
        
        // ๊ฐ’ ํ™•์ธ
        $value = get_post_meta($this->product_id, '_custom_text_field', true);
        $this->assertEquals('Test Value', $value);
    }
    
    public function test_custom_field_sanitization() {
        // XSS ์‹œ๋„
        $malicious_input = '<script>alert("XSS")</script>';
        $sanitized = sanitize_text_field($malicious_input);
        
        // ์Šคํฌ๋ฆฝํŠธ ํƒœ๊ทธ๊ฐ€ ์ œ๊ฑฐ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ
        $this->assertNotContains('<script>', $sanitized);
    }
    
    public function test_product_stats_calculation() {
        global $wc_custom_db;
        
        // ํ…Œ์ŠคํŠธ ๋ฆฌ๋ทฐ ์ถ”๊ฐ€
        for ($i = 1; $i <= 5; $i++) {
            $comment_id = wp_insert_comment(array(
                'comment_post_ID' => $this->product_id,
                'comment_content' => 'Test review ' . $i,
                'comment_type' => 'review',
                'comment_approved' => 1
            ));
            
            add_comment_meta($comment_id, 'rating', $i);
        }
        
        // ํ†ต๊ณ„ ์—…๋ฐ์ดํŠธ
        $wc_custom_db->update_review_stats($this->product_id);
        
        // ํ†ต๊ณ„ ํ™•์ธ
        $stats = $wc_custom_db->get_review_stats($this->product_id);
        
        $this->assertEquals(5, $stats['total_reviews']);
        $this->assertEquals(3.0, $stats['average_rating']); // (1+2+3+4+5)/5 = 3
    }
}

// ํ…Œ์ŠคํŠธ ์‹คํ–‰
// vendor/bin/phpunit tests/test-product-fields.php

๐Ÿ› ๋””๋ฒ„๊น… ๊ธฐ๋ฒ•

1. ๋กœ๊น… ์‹œ์Šคํ…œ ๊ตฌ์ถ•

class WC_Custom_Logger {
    
    private static $log_file;
    
    public static function init() {
        $upload_dir = wp_upload_dir();
        self::$log_file = $upload_dir['basedir'] . '/wc-custom-logs/debug.log';
        
        // ๋กœ๊ทธ ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ
        $log_dir = dirname(self::$log_file);
        if (!file_exists($log_dir)) {
            wp_mkdir_p($log_dir);
        }
    }
    
    public static function log($message, $level = 'INFO') {
        if (!self::$log_file) {
            self::init();
        }
        
        $timestamp = date('Y-m-d H:i:s');
        $formatted_message = "[{$timestamp}] [{$level}] {$message}" . PHP_EOL;
        
        error_log($formatted_message, 3, self::$log_file);
    }
    
    public static function debug($message) {
        if (defined('WP_DEBUG') && WP_DEBUG) {
            self::log($message, 'DEBUG');
        }
    }
    
    public static function error($message) {
        self::log($message, 'ERROR');
    }
    
    public static function info($message) {
        self::log($message, 'INFO');
    }
}

// ์‚ฌ์šฉ ์˜ˆ์ œ
WC_Custom_Logger::debug('์ œํ’ˆ ID: ' . $product_id);
WC_Custom_Logger::info('๊ฒฐ์ œ ์ฒ˜๋ฆฌ ์‹œ์ž‘');
WC_Custom_Logger::error('API ํ˜ธ์ถœ ์‹คํŒจ: ' . $error_message);

2. ๊ฐœ๋ฐœ ๋ชจ๋“œ ํ† ๊ธ€

// ๊ฐœ๋ฐœ ๋ชจ๋“œ ํ™•์ธ ํ•จ์ˆ˜
function is_dev_mode() {
    return defined('WC_CUSTOM_DEV_MODE') && WC_CUSTOM_DEV_MODE;
}

// ๊ฐœ๋ฐœ ๋ชจ๋“œ์—์„œ๋งŒ ์‹คํ–‰๋˜๋Š” ์ฝ”๋“œ
if (is_dev_mode()) {
    // ์ƒ์„ธํ•œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ํ‘œ์‹œ
    add_filter('woocommerce_add_error', function($error) {
        $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5);
        $error .= '<pre>' . print_r($trace, true) . '</pre>';
        return $error;
    });
    
    // ์ฟผ๋ฆฌ ๋กœ๊น…
    add_action('shutdown', function() {
        global $wpdb;
        WC_Custom_Logger::debug('Total Queries: ' . $wpdb->num_queries);
        WC_Custom_Logger::debug('Queries: ' . print_r($wpdb->queries, true));
    });
}

3. ์—๋Ÿฌ ํ•ธ๋“ค๋ง

// ์ „์—ญ ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ
function custom_error_handler($errno, $errstr, $errfile, $errline) {
    $error_types = array(
        E_ERROR => 'ERROR',
        E_WARNING => 'WARNING',
        E_NOTICE => 'NOTICE',
        E_USER_ERROR => 'USER_ERROR',
        E_USER_WARNING => 'USER_WARNING',
        E_USER_NOTICE => 'USER_NOTICE'
    );
    
    $type = isset($error_types[$errno]) ? $error_types[$errno] : 'UNKNOWN';
    
    $message = sprintf(
        "[%s] %s in %s on line %d",
        $type,
        $errstr,
        $errfile,
        $errline
    );
    
    WC_Custom_Logger::error($message);
    
    // ๊ฐœ๋ฐœ ๋ชจ๋“œ๊ฐ€ ์•„๋‹ˆ๋ฉด ์‚ฌ์šฉ์ž์—๊ฒŒ ์นœ์ ˆํ•œ ๋ฉ”์‹œ์ง€ ํ‘œ์‹œ
    if (!is_dev_mode() && $errno === E_USER_ERROR) {
        wp_die(__('์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ์ผ์‹œ์ ์ธ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ž ์‹œ ํ›„ ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.', 'wc-custom-fields'));
    }
    
    return true;
}

set_error_handler('custom_error_handler');

// ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ
function custom_exception_handler($exception) {
    $message = sprintf(
        "Uncaught Exception: %s in %s on line %d\nStack trace:\n%s",
        $exception->getMessage(),
        $exception->getFile(),
        $exception->getLine(),
        $exception->getTraceAsString()
    );
    
    WC_Custom_Logger::error($message);
    
    if (!is_dev_mode()) {
        wp_die(__('์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๊ธฐ์น˜ ์•Š์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.', 'wc-custom-fields'));
    }
}

set_exception_handler('custom_exception_handler');

๐ŸŽฏ ํ”„๋กœ ํŒ: ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ๋Š” ์ ˆ๋Œ€ ์ƒ์„ธํ•œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋…ธ์ถœํ•˜์ง€ ๋งˆ! ํ•ด์ปค๋“ค์—๊ฒŒ ์‹œ์Šคํ…œ ์ •๋ณด๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ๊ผด์ด์•ผ. ๋Œ€์‹  ๋กœ๊ทธ ํŒŒ์ผ์— ๊ธฐ๋กํ•˜๊ณ , ์‚ฌ์šฉ์ž์—๊ฒŒ๋Š” ์นœ์ ˆํ•œ ๋ฉ”์‹œ์ง€๋งŒ ๋ณด์—ฌ์ค˜.

๐Ÿ“ฆ ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ฐฐํฌ ์ค€๋น„

ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์™„์„ฑํ–ˆ๋‹ค๋ฉด ์ด์ œ ๋ฐฐํฌํ•  ์ฐจ๋ก€์•ผ! ์›Œ๋“œํ”„๋ ˆ์Šค ๊ณต์‹ ์ €์žฅ์†Œ์— ๋“ฑ๋กํ•˜๊ฑฐ๋‚˜, ์ง์ ‘ ํŒ๋งคํ•  ์ˆ˜๋„ ์žˆ์–ด. ๐Ÿš€

๐Ÿ“‹ ๋ฐฐํฌ ์ „ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

โœ… ์ฝ”๋“œ ํ’ˆ์งˆ

โ€ข WordPress Coding Standards ์ค€์ˆ˜
โ€ข PHP_CodeSniffer๋กœ ์ฝ”๋“œ ๊ฒ€์‚ฌ
โ€ข ๋ชจ๋“  ํ•จ์ˆ˜์™€ ํด๋ž˜์Šค์— ์ฃผ์„ ์ž‘์„ฑ
โ€ข ๋ถˆํ•„์š”ํ•œ ์ฝ”๋“œ ์ œ๊ฑฐ (console.log, var_dump ๋“ฑ)

โœ… ๋ณด์•ˆ

โ€ข ๋ชจ๋“  ์ž…๋ ฅ๊ฐ’ ๊ฒ€์ฆ ๋ฐ ์‚ด๊ท 
โ€ข SQL ์ธ์ ์…˜ ๋ฐฉ์ง€
โ€ข XSS ๋ฐฉ์ง€
โ€ข CSRF ํ† ํฐ ์‚ฌ์šฉ
โ€ข ๊ถŒํ•œ ์ฒดํฌ

โœ… ํ˜ธํ™˜์„ฑ

โ€ข ์ตœ์‹  ์›Œ๋“œํ”„๋ ˆ์Šค ๋ฒ„์ „ ํ…Œ์ŠคํŠธ
โ€ข ์ตœ์‹  WooCommerce ๋ฒ„์ „ ํ…Œ์ŠคํŠธ
โ€ข ์ฃผ์š” ํ…Œ๋งˆ์™€ ํ˜ธํ™˜์„ฑ ํ™•์ธ
โ€ข ๋‹ค์–‘ํ•œ PHP ๋ฒ„์ „ ํ…Œ์ŠคํŠธ (7.4, 8.0, 8.1)

โœ… ๋ฌธ์„œํ™”

โ€ข README.txt ์ž‘์„ฑ
โ€ข ์„ค์น˜ ๊ฐ€์ด๋“œ
โ€ข ์‚ฌ์šฉ ์„ค๋ช…์„œ
โ€ข FAQ
โ€ข ๋ณ€๊ฒฝ ๋กœ๊ทธ

๐Ÿ“ README.txt ์ž‘์„ฑ

์›Œ๋“œํ”„๋ ˆ์Šค ๊ณต์‹ ์ €์žฅ์†Œ์— ๋“ฑ๋กํ•˜๋ ค๋ฉด ํŠน์ • ํ˜•์‹์˜ README.txt๊ฐ€ ํ•„์š”ํ•ด:

=== WooCommerce Custom Product Fields ===
Contributors: yourname
Tags: woocommerce, custom fields, product, ecommerce
Requires at least: 5.8
Tested up to: 6.4
Requires PHP: 7.4
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

์ œํ’ˆ์— ์ปค์Šคํ…€ ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฐ•๋ ฅํ•œ WooCommerce ํ™•์žฅ ํ”Œ๋Ÿฌ๊ทธ์ธ

== Description ==

WooCommerce Custom Product Fields๋Š” ์ œํ’ˆ ํŽ˜์ด์ง€์— ๋‹ค์–‘ํ•œ ์ปค์Šคํ…€ ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์ž…๋‹ˆ๋‹ค.

**์ฃผ์š” ๊ธฐ๋Šฅ:**

* ํ…์ŠคํŠธ, ์ˆซ์ž, ์…€๋ ‰ํŠธ, ์ฒดํฌ๋ฐ•์Šค ๋“ฑ ๋‹ค์–‘ํ•œ ํ•„๋“œ ํƒ€์ž… ์ง€์›
* ๊ด€๋ฆฌ์ž ํŽ˜์ด์ง€์—์„œ ์‰ฝ๊ฒŒ ํ•„๋“œ ๊ด€๋ฆฌ
* ํ”„๋ก ํŠธ์—”๋“œ์— ์ž๋™์œผ๋กœ ํ‘œ์‹œ
* ์™„์ „ํ•œ ๋‹ค๊ตญ์–ด ์ง€์›
* ๊ฐœ๋ฐœ์ž ์นœํ™”์ ์ธ ํ›…๊ณผ ํ•„ํ„ฐ ์ œ๊ณต

**์‚ฌ์šฉ ์˜ˆ์‹œ:**

* ๋ฐฐ์†ก ์†Œ์š”์ผ ํ‘œ์‹œ
* ์ œํ’ˆ ๋“ฑ๊ธ‰ ํ‘œ์‹œ
* ํŠน๋ณ„ ์„œ๋น„์Šค ์•ˆ๋‚ด
* ์ถ”๊ฐ€ ์ •๋ณด ์ œ๊ณต

== Installation ==

1. ํ”Œ๋Ÿฌ๊ทธ์ธ ํŒŒ์ผ์„ `/wp-content/plugins/wc-custom-fields` ๋””๋ ‰ํ† ๋ฆฌ์— ์—…๋กœ๋“œํ•˜๊ฑฐ๋‚˜,
   ์›Œ๋“œํ”„๋ ˆ์Šค ๊ด€๋ฆฌ์ž ํŽ˜์ด์ง€์—์„œ ์ง์ ‘ ์„ค์น˜ํ•˜์„ธ์š”.
2. ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ฉ”๋‰ด์—์„œ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ํ™œ์„ฑํ™”ํ•˜์„ธ์š”.
3. WooCommerce > ์„ค์ • > ์ œํ’ˆ ํƒญ์—์„œ ์„ค์ •์„ ์กฐ์ •ํ•˜์„ธ์š”.

== Frequently Asked Questions ==

= WooCommerce๊ฐ€ ํ•„์ˆ˜์ธ๊ฐ€์š”? =

๋„ค, ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์€ WooCommerce 5.0 ์ด์ƒ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

= ํ•„๋“œ๋ฅผ ๋” ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‚˜์š”? =

๋„ค, ๊ฐœ๋ฐœ์ž ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์ปค์Šคํ…€ ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

= ๋‹ค๊ตญ์–ด๋ฅผ ์ง€์›ํ•˜๋‚˜์š”? =

๋„ค, WPML๊ณผ Polylang๊ณผ ์™„๋ฒฝํ•˜๊ฒŒ ํ˜ธํ™˜๋ฉ๋‹ˆ๋‹ค.

== Screenshots ==

1. ๊ด€๋ฆฌ์ž ์ œํ’ˆ ํŽธ์ง‘ ํŽ˜์ด์ง€์˜ ์ปค์Šคํ…€ ํ•„๋“œ
2. ํ”„๋ก ํŠธ์—”๋“œ ์ œํ’ˆ ํŽ˜์ด์ง€ ํ‘œ์‹œ
3. ์„ค์ • ํŽ˜์ด์ง€

== Changelog ==

= 1.0.0 =
* ์ตœ์ดˆ ๋ฆด๋ฆฌ์Šค
* ๊ธฐ๋ณธ ํ•„๋“œ ํƒ€์ž… ์ง€์›
* ๊ด€๋ฆฌ์ž ์ธํ„ฐํŽ˜์ด์Šค
* ํ”„๋ก ํŠธ์—”๋“œ ํ‘œ์‹œ

== Upgrade Notice ==

= 1.0.0 =
์ตœ์ดˆ ๋ฆด๋ฆฌ์Šค์ž…๋‹ˆ๋‹ค.

== Developer Documentation ==

**ํ›… ์‚ฌ์šฉ ์˜ˆ์ œ:**

`
// ์ปค์Šคํ…€ ํ•„๋“œ ์ถ”๊ฐ€
add_action('wc_custom_fields_after_fields', function() {
    echo '<div>์ถ”๊ฐ€ ํ•„๋“œ</div>';
});

// ํ•„๋“œ ๊ฐ’ ํ•„ํ„ฐ๋ง
add_filter('wc_custom_field_value', function($value, $field_id) {
    return strtoupper($value);
}, 10, 2);
`

๋” ์ž์„ธํ•œ ๋ฌธ์„œ๋Š” https://yoursite.com/docs ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

๐ŸŽจ ์Šคํฌ๋ฆฐ์ƒท ์ค€๋น„

ํ”Œ๋Ÿฌ๊ทธ์ธ ํŽ˜์ด์ง€์— ํ‘œ์‹œ๋  ์Šคํฌ๋ฆฐ์ƒท์„ ์ค€๋น„ํ•ด. ํŒŒ์ผ๋ช…์€ screenshot-1.png, screenshot-2.png ํ˜•์‹์œผ๋กœ ์ €์žฅํ•˜๊ณ , assets ํด๋”์— ๋„ฃ์–ด์ค˜.

์Šคํฌ๋ฆฐ์ƒท ๊ฐ€์ด๋“œ๋ผ์ธ

โ€ข ํฌ๊ธฐ: 1280x960px (4:3 ๋น„์œจ)
โ€ข ํฌ๋งท: PNG ๋˜๋Š” JPG
โ€ข ์šฉ๋Ÿ‰: ๊ฐ 1MB ์ดํ•˜
โ€ข ๋‚ด์šฉ: ์ฃผ์š” ๊ธฐ๋Šฅ์„ ๋ช…ํ™•ํ•˜๊ฒŒ ๋ณด์—ฌ์ค„ ๊ฒƒ

๐Ÿš€ ๋ฐฐํฌ ๋ฐฉ๋ฒ•

1. ์›Œ๋“œํ”„๋ ˆ์Šค ๊ณต์‹ ์ €์žฅ์†Œ

โ€ข ๋ฌด๋ฃŒ๋กœ ๋ฐฐํฌ
โ€ข ์ž๋™ ์—…๋ฐ์ดํŠธ ์ง€์›
โ€ข ๋†’์€ ์‹ ๋ขฐ๋„
โ€ข ๊ฒ€ํ†  ๊ณผ์ • ํ•„์š” (1-2์ฃผ ์†Œ์š”)

2. ์ง์ ‘ ํŒ๋งค

โ€ข CodeCanyon, Creative Market ๋“ฑ์˜ ๋งˆ์ผ“ํ”Œ๋ ˆ์ด์Šค
โ€ข ์ž์ฒด ์›น์‚ฌ์ดํŠธ์—์„œ ํŒ๋งค
โ€ข ๋ผ์ด์„ ์Šค ๊ด€๋ฆฌ ํ•„์š”
โ€ข ์—…๋ฐ์ดํŠธ ์‹œ์Šคํ…œ ๊ตฌ์ถ• ํ•„์š”

3. GitHub

โ€ข ์˜คํ”ˆ์†Œ์Šค๋กœ ๊ณต๊ฐœ
โ€ข ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ธฐ์—ฌ ๋ฐ›๊ธฐ
โ€ข ์ด์Šˆ ํŠธ๋ž˜ํ‚น
โ€ข ๋ฒ„์ „ ๊ด€๋ฆฌ

๊ฐœ์ธ์ ์œผ๋กœ๋Š” ์›Œ๋“œํ”„๋ ˆ์Šค ๊ณต์‹ ์ €์žฅ์†Œ์— ๋ฌด๋ฃŒ ๋ฒ„์ „์„ ์˜ฌ๋ฆฌ๊ณ , ํ”„๋ฆฌ๋ฏธ์—„ ๊ธฐ๋Šฅ์€ ๋ณ„๋„๋กœ ํŒ๋งคํ•˜๋Š” ํ”„๋ฆฌ๋ฏธ์—„ ๋ชจ๋ธ์„ ์ถ”์ฒœํ•ด. ์‚ฌ์šฉ์ž ๊ธฐ๋ฐ˜์„ ๋„“ํžˆ๋ฉด์„œ๋„ ์ˆ˜์ต์„ ์ฐฝ์ถœํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ !

๐Ÿ’ฐ ์ˆ˜์ตํ™” ์ „๋žต

ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐœ๋ฐœ ์‹ค๋ ฅ์ด ์žˆ๋‹ค๋ฉด ์ด๊ฑธ๋กœ ์ˆ˜์ต์„ ๋‚ผ ์ˆ˜ ์žˆ์–ด! ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์œผ๋‹ˆ๊นŒ ์ž์‹ ์—๊ฒŒ ๋งž๋Š” ๊ฑธ ์„ ํƒํ•ด๋ด. ๐Ÿ’ต

๐ŸŽฏ ์ˆ˜์ต ๋ชจ๋ธ

1. ํ”„๋ฆฌ๋ฏธ์—„ ๋ชจ๋ธ (Freemium)

โ€ข ๊ธฐ๋ณธ ๊ธฐ๋Šฅ์€ ๋ฌด๋ฃŒ๋กœ ์ œ๊ณต
โ€ข ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ์€ ์œ ๋ฃŒ ๋ฒ„์ „์—์„œ๋งŒ
โ€ข ์˜ˆ: ๊ธฐ๋ณธ ํ•„๋“œ๋Š” ๋ฌด๋ฃŒ, ์กฐ๊ฑด๋ถ€ ๋กœ์ง์€ ์œ ๋ฃŒ
โ€ข ์ „ํ™˜์œจ: ์•ฝ 1-3%

2. ๊ตฌ๋… ๋ชจ๋ธ

โ€ข ์›”/์—ฐ ๋‹จ์œ„ ๊ตฌ๋…๋ฃŒ
โ€ข ์ง€์†์ ์ธ ์—…๋ฐ์ดํŠธ์™€ ์ง€์› ์ œ๊ณต
โ€ข ์•ˆ์ •์ ์ธ ์ˆ˜์ต
โ€ข ์˜ˆ: ์›” $9.99, ์—ฐ $99

3. ์ผํšŒ์„ฑ ๊ตฌ๋งค

โ€ข ํ•œ ๋ฒˆ ๊ตฌ๋งค๋กœ ์˜๊ตฌ ์‚ฌ์šฉ
โ€ข ์—…๋ฐ์ดํŠธ๋Š” 1๋…„๊ฐ„ ๋ฌด๋ฃŒ
โ€ข ๋†’์€ ์ดˆ๊ธฐ ๊ฐ€๊ฒฉ ์„ค์ • ๊ฐ€๋Šฅ
โ€ข ์˜ˆ: $49 ~ $199

4. ์ปค์Šคํ…€ ๊ฐœ๋ฐœ ์„œ๋น„์Šค

โ€ข ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ํฌํŠธํด๋ฆฌ์˜ค๋กœ ํ™œ์šฉ
โ€ข ๋งž์ถค ๊ฐœ๋ฐœ ์˜๋ขฐ ๋ฐ›๊ธฐ
โ€ข ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ ์žฌ๋Šฅ ํŒ๋งค
โ€ข ์‹œ๊ฐ„๋‹น $50 ~ $150

๐Ÿ“Š ๊ฐ€๊ฒฉ ์ฑ…์ • ์ „๋žต

๊ฐ€๊ฒฉ ๊ฒฐ์ • ์š”์†Œ

โ€ข ๊ธฐ๋Šฅ์˜ ๋ณต์žก๋„์™€ ๊ฐ€์น˜
โ€ข ๊ฒฝ์Ÿ ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐ€๊ฒฉ
โ€ข ํƒ€๊ฒŸ ๊ณ ๊ฐ์ธต (๊ฐœ์ธ/๊ธฐ์—…)
โ€ข ์ง€์› ๋ฒ”์œ„
โ€ข ์—…๋ฐ์ดํŠธ ์ฃผ๊ธฐ

์˜ˆ๋ฅผ ๋“ค์–ด, ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  ์ปค์Šคํ…€ ํ•„๋“œ ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ ๊ฐ€๊ฒฉ์„ ์ฑ…์ •ํ•œ๋‹ค๋ฉด:

๋ฌด๋ฃŒ ๋ฒ„์ „:
- ๊ธฐ๋ณธ ํ•„๋“œ ํƒ€์ž… 3๊ฐœ (ํ…์ŠคํŠธ, ์ˆซ์ž, ์ฒดํฌ๋ฐ•์Šค)
- ์ œํ’ˆ๋‹น ํ•„๋“œ 3๊ฐœ๊นŒ์ง€
- ์ปค๋ฎค๋‹ˆํ‹ฐ ์ง€์›

ํ”„๋กœ ๋ฒ„์ „ ($49):
- ๋ชจ๋“  ํ•„๋“œ ํƒ€์ž… (10๊ฐœ ์ด์ƒ)
- ๋ฌด์ œํ•œ ํ•„๋“œ
- ์กฐ๊ฑด๋ถ€ ๋กœ์ง
- ํ•„๋“œ ๊ทธ๋ฃน
- ์ด๋ฉ”์ผ ์ง€์›

๋น„์ฆˆ๋‹ˆ์Šค ๋ฒ„์ „ ($149):
- ํ”„๋กœ ๋ฒ„์ „ ๋ชจ๋“  ๊ธฐ๋Šฅ
- ๋‹ค์ค‘ ์‚ฌ์ดํŠธ ๋ผ์ด์„ ์Šค
- ์šฐ์„  ์ง€์›
- ์ปค์Šคํ…€ ํ•„๋“œ ํ…œํ”Œ๋ฆฟ
- API ์•ก์„ธ์Šค

์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ($499):
- ๋น„์ฆˆ๋‹ˆ์Šค ๋ฒ„์ „ ๋ชจ๋“  ๊ธฐ๋Šฅ
- ๋ฌด์ œํ•œ ์‚ฌ์ดํŠธ
- ์ „ํ™” ์ง€์›
- ๋งž์ถค ๊ฐœ๋ฐœ 1์‹œ๊ฐ„ ํฌํ•จ
- SLA ๋ณด์žฅ

๐ŸŽ ๋งˆ์ผ€ํŒ… ์ „๋žต

1. ์ฝ˜ํ…์ธ  ๋งˆ์ผ€ํŒ…

โ€ข ๋ธ”๋กœ๊ทธ์— ํŠœํ† ๋ฆฌ์–ผ ์ž‘์„ฑ
โ€ข YouTube ๋น„๋””์˜ค ์ œ์ž‘
โ€ข ์ผ€์ด์Šค ์Šคํ„ฐ๋”” ๊ณต์œ 
โ€ข SEO ์ตœ์ ํ™”

2. ์ปค๋ฎค๋‹ˆํ‹ฐ ์ฐธ์—ฌ

โ€ข ์›Œ๋“œํ”„๋ ˆ์Šค ํฌ๋Ÿผ ํ™œ๋™
โ€ข Facebook ๊ทธ๋ฃน ์ฐธ์—ฌ
โ€ข Stack Overflow ๋‹ต๋ณ€
โ€ข ์˜คํ”ˆ์†Œ์Šค ๊ธฐ์—ฌ

3. ์ œํœด ํ”„๋กœ๊ทธ๋žจ

โ€ข ๋ธ”๋กœ๊ฑฐ/์ธํ”Œ๋ฃจ์–ธ์„œ์™€ ํ˜‘์—…
โ€ข 20-30% ์ปค๋ฏธ์…˜ ์ œ๊ณต
โ€ข ์ œํœด ๋งํฌ ์ถ”์ 
โ€ข ์ •๊ธฐ์ ์ธ ํ”„๋กœ๋ชจ์…˜

๐Ÿ’ก ์‹ค์ „ ํŒ: ์ฒ˜์Œ์—๋Š” ๊ฐ€๊ฒฉ์„ ๋‚ฎ๊ฒŒ ์ฑ…์ •ํ•˜๊ณ  ๋ฆฌ๋ทฐ๋ฅผ ๋งŽ์ด ๋ฐ›๋Š” ๊ฒŒ ์ข‹์•„. ์ข‹์€ ํ‰๊ฐ€๊ฐ€ ์Œ“์ด๋ฉด ๊ฐ€๊ฒฉ์„ ์˜ฌ๋ ค๋„ ํŒ๋งค๊ฐ€ ์ž˜ ๋ผ. ๊ทธ๋ฆฌ๊ณ  ์ •๊ธฐ์ ์œผ๋กœ ํ• ์ธ ์ด๋ฒคํŠธ๋ฅผ ํ•˜๋ฉด ๋งค์ถœ์ด 2-3๋ฐฐ ๋›ฐ์–ด!

๐ŸŽ“ ๊ณ„์† ์„ฑ์žฅํ•˜๊ธฐ

๊ฐœ๋ฐœ์€ ๋์ด ์—†๋Š” ์—ฌ์ •์ด์•ผ. ํ•ญ์ƒ ์ƒˆ๋กœ์šด ๊ฑธ ๋ฐฐ์šฐ๊ณ  ์‹ค๋ ฅ์„ ํ‚ค์›Œ๋‚˜๊ฐ€์•ผ ํ•ด! ๐ŸŒฑ

๐Ÿ“š ํ•™์Šต ๋ฆฌ์†Œ์Šค

๊ณต์‹ ๋ฌธ์„œ

โ€ข WooCommerce ๊ณต์‹ ๋ฌธ์„œ
โ€ข WordPress Developer Resources
โ€ข WooCommerce GitHub

์˜จ๋ผ์ธ ๊ฐ•์˜

โ€ข Udemy: WooCommerce ๊ฐœ๋ฐœ ์ฝ”์Šค
โ€ข LinkedIn Learning: WordPress ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐœ๋ฐœ
โ€ข YouTube: ๋ฌด๋ฃŒ ํŠœํ† ๋ฆฌ์–ผ ๋งŽ์Œ
โ€ข ์žฌ๋Šฅ๋„ท: ์‹ค์ „ ๊ฒฝํ—˜์ž์˜ 1:1 ๋ฉ˜ํ† ๋ง

์ปค๋ฎค๋‹ˆํ‹ฐ

โ€ข WooCommerce Slack
โ€ข WordPress Stack Exchange
โ€ข Reddit r/WordPress
โ€ข ํ•œ๊ตญ ์›Œ๋“œํ”„๋ ˆ์Šค ์‚ฌ์šฉ์ž ๋ชจ์ž„

๐Ÿš€ ๋‹ค์Œ ๋‹จ๊ณ„

๊ธฐ๋ณธ์„ ๋งˆ์Šคํ„ฐํ–ˆ๋‹ค๋ฉด ์ด๋Ÿฐ ๊ณ ๊ธ‰ ์ฃผ์ œ๋“ค์— ๋„์ „ํ•ด๋ด:

1. ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ ๊ตฌํ˜„

โ€ข ๋‹ค์ค‘ ํ†ตํ™” ์ง€์›
โ€ข ๊ตฌ๋… ์ƒํ’ˆ ์‹œ์Šคํ…œ
โ€ข ๋ณต์žกํ•œ ๋ฐฐ์†ก ๊ณ„์‚ฐ
โ€ข ์žฌ๊ณ  ๊ด€๋ฆฌ ์ž๋™ํ™”
โ€ข AI ๊ธฐ๋ฐ˜ ์ถ”์ฒœ ์‹œ์Šคํ…œ

2. ์™ธ๋ถ€ ์„œ๋น„์Šค ์—ฐ๋™

โ€ข ERP ์‹œ์Šคํ…œ ์—ฐ๋™
โ€ข CRM ํ†ตํ•ฉ
โ€ข ๋งˆ์ผ€ํŒ… ์ž๋™ํ™”
โ€ข ๋ฌผ๋ฅ˜ ์‹œ์Šคํ…œ ์—ฐ๋™
โ€ข ํšŒ๊ณ„ ์†Œํ”„ํŠธ์›จ์–ด ์—ฐ๋™

3. ์„ฑ๋Šฅ ๊ทน๋Œ€ํ™”

โ€ข ๋Œ€์šฉ๋Ÿ‰ ํŠธ๋ž˜ํ”ฝ ์ฒ˜๋ฆฌ
โ€ข ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒค๋”ฉ
โ€ข CDN ์ตœ์ ํ™”
โ€ข ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜
โ€ข ์„œ๋ฒ„๋ฆฌ์Šค ๊ตฌ์กฐ

๐Ÿ’ผ ์ปค๋ฆฌ์–ด ๋ฐœ์ „

WooCommerce ๊ฐœ๋ฐœ ์‹ค๋ ฅ์€ ์ •๋ง ๊ฐ€์น˜ ์žˆ์–ด. ์ด๋Ÿฐ ๋ฐฉํ–ฅ์œผ๋กœ ์ปค๋ฆฌ์–ด๋ฅผ ๋ฐœ์ „์‹œํ‚ฌ ์ˆ˜ ์žˆ์ง€:

ํ”„๋ฆฌ๋žœ์„œ

โ€ข Upwork, Fiverr ๋“ฑ์—์„œ ํ”„๋กœ์ ํŠธ ์ˆ˜์ฃผ
โ€ข ์‹œ๊ฐ„๋‹น $50-150 ์ˆ˜์ต ๊ฐ€๋Šฅ
โ€ข ์ž์œ ๋กœ์šด ๊ทผ๋ฌด ํ™˜๊ฒฝ
โ€ข ๋‹ค์–‘ํ•œ ํ”„๋กœ์ ํŠธ ๊ฒฝํ—˜

์—์ด์ „์‹œ ์ทจ์—…

โ€ข ์›น ๊ฐœ๋ฐœ ์—์ด์ „์‹œ
โ€ข ์ด์ปค๋จธ์Šค ์ „๋ฌธ ํšŒ์‚ฌ
โ€ข ์•ˆ์ •์ ์ธ ์ˆ˜์ž…
โ€ข ํŒ€ ํ˜‘์—… ๊ฒฝํ—˜

์ œํ’ˆ ๊ฐœ๋ฐœ

โ€ข ์ž์ฒด ํ”Œ๋Ÿฌ๊ทธ์ธ/ํ…Œ๋งˆ ํŒ๋งค
โ€ข SaaS ์„œ๋น„์Šค ๋Ÿฐ์นญ
โ€ข ์ˆ˜๋™์  ์ˆ˜์ž… ์ฐฝ์ถœ
โ€ข ์Šค์ผ€์ผ์—… ๊ฐ€๋Šฅ

์ปจ์„คํŒ…

โ€ข ๊ธฐ์—… ๋Œ€์ƒ ์ปจ์„คํŒ…
โ€ข ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„
โ€ข ์ฝ”๋“œ ๋ฆฌ๋ทฐ
โ€ข ๋†’์€ ์‹œ๊ฐ„๋‹น ๋‹จ๊ฐ€

๐ŸŽฌ ๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ

์™€, ์—ฌ๊ธฐ๊นŒ์ง€ ์ฝ์—ˆ๋‹ค๋ฉด ์ •๋ง ๋Œ€๋‹จํ•ด! ๐Ÿ‘ WooCommerce ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐœ๋ฐœ์˜ A๋ถ€ํ„ฐ Z๊นŒ์ง€ ํ•จ๊ป˜ ์‚ดํŽด๋ดค์–ด. ์ฒ˜์Œ์—๋Š” ๋ณต์žกํ•ด ๋ณด์ผ ์ˆ˜ ์žˆ์ง€๋งŒ, ํ•˜๋‚˜์”ฉ ์ฐจ๊ทผ์ฐจ๊ทผ ๋”ฐ๋ผํ•˜๋‹ค ๋ณด๋ฉด ์–ด๋А์ƒˆ ๋ฉ‹์ง„ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋งŒ๋“ค๊ณ  ์žˆ๋Š” ์ž์‹ ์„ ๋ฐœ๊ฒฌํ•˜๊ฒŒ ๋  ๊ฑฐ์•ผ.

๊ธฐ์–ตํ•ด์ค˜. ์™„๋ฒฝํ•œ ์ฝ”๋“œ๋Š” ์—†์–ด. ์ค‘์š”ํ•œ ๊ฑด ๊ณ„์† ๋ฐฐ์šฐ๊ณ , ๊ฐœ์„ ํ•˜๊ณ , ๋„์ „ํ•˜๋Š” ๊ฑฐ์•ผ. ๋ฒ„๊ทธ๋ฅผ ๋งŒ๋‚˜๋„ ์ขŒ์ ˆํ•˜์ง€ ๋ง๊ณ , ๊ทธ๊ฑธ ๋ฐฐ์›€์˜ ๊ธฐํšŒ๋กœ ์‚ผ์•„. ๋ชจ๋“  ๊ณ ์ˆ˜๋“ค๋„ ์ฒ˜์Œ์—” ์ดˆ๋ณด์˜€๊ฑฐ๋“ ! ๐Ÿ˜Š

๐ŸŽฏ ํ•ต์‹ฌ ์š”์•ฝ

โ€ข WooCommerce๋Š” ๊ฐ•๋ ฅํ•˜๊ณ  ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ์ด์ปค๋จธ์Šค ํ”Œ๋žซํผ
โ€ข ํ›…๊ณผ ํ•„ํ„ฐ๋ฅผ ํ™œ์šฉํ•œ ์•ˆ์ „ํ•œ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•
โ€ข ๋ณด์•ˆ๊ณผ ์„ฑ๋Šฅ์€ ํ•„์ˆ˜, ์„ ํƒ ์•„๋‹˜
โ€ข ์ฒด๊ณ„์ ์ธ ํ…Œ์ŠคํŠธ์™€ ๋””๋ฒ„๊น…
โ€ข ์ง€์†์ ์ธ ํ•™์Šต๊ณผ ์ปค๋ฎค๋‹ˆํ‹ฐ ์ฐธ์—ฌ
โ€ข ๋‹ค์–‘ํ•œ ์ˆ˜์ตํ™” ๋ฐฉ๋ฒ• ์กด์žฌ

์ด์ œ ๋‹น์‹  ์ฐจ๋ก€์•ผ! ์˜ค๋Š˜ ๋ฐฐ์šด ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ์ฒซ ๋ฒˆ์งธ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋งŒ๋“ค์–ด๋ด. ์ž‘์€ ๊ฒƒ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ ์ ์  ๋ณต์žกํ•œ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด ๋‚˜๊ฐ€๋ฉด ๋ผ. ๊ทธ๋ฆฌ๊ณ  ๋ง‰ํžˆ๋Š” ๋ถ€๋ถ„์ด ์žˆ์œผ๋ฉด ์ปค๋ฎค๋‹ˆํ‹ฐ์— ์งˆ๋ฌธํ•˜๊ฑฐ๋‚˜, ์žฌ๋Šฅ๋„ท์—์„œ ๊ฒฝํ—˜ ๋งŽ์€ ๊ฐœ๋ฐœ์ž์˜ ๋„์›€์„ ๋ฐ›๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด์•ผ.

๋‹น์‹ ์˜ ๊ฐœ๋ฐœ ์—ฌ์ •์— ํ–‰์šด์„ ๋นŒ์–ด! ์–ธ์  ๊ฐ€ ๋‹น์‹ ์ด ๋งŒ๋“  ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์ˆ˜์ฒœ, ์ˆ˜๋งŒ ๊ฐœ์˜ ์‡ผํ•‘๋ชฐ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋‚ ์„ ๊ธฐ๋Œ€ํ• ๊ฒŒ. ํ™”์ดํŒ…! ๐Ÿš€โœจ

๐Ÿ“ฌ ๋งˆ์ง€๋ง‰ ํŒ: ์ด ๊ธ€์ด ๋„์›€์ด ๋๋‹ค๋ฉด ๋ถ๋งˆํฌํ•ด๋‘๊ณ , ๊ฐœ๋ฐœํ•˜๋ฉด์„œ ์ฐธ๊ณ  ์ž๋ฃŒ๋กœ ํ™œ์šฉํ•ด๋ด. ๊ทธ๋ฆฌ๊ณ  ์ฃผ๋ณ€์— WooCommerce ๊ฐœ๋ฐœ์— ๊ด€์‹ฌ ์žˆ๋Š” ์นœ๊ตฌ๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ณต์œ ํ•ด์ฃผ๋Š” ๊ฒƒ๋„ ์žŠ์ง€ ๋งˆ!

Happy Coding! ๐ŸŽ‰

๋Œ“๊ธ€ ์ž‘์„ฑ

์ด ๊ธ€์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ์„ ๋“ค๋ ค์ฃผ์„ธ์š”

๋Œ“๊ธ€ 0