Ver2.5 워드프레스 우커머스, 나만의 주문 관리 시스템 만들기 🚀

워드프레스 우커머스, 나만의 주문 관리 시스템 만들기 🚀
코딩 쪼렙도 따라 할 수 있는 주문 관리 확장 플러그인 개발 A to Z
들어가며: "사장님, 주문 또 밀렸어요!" 이젠 안녕 👋
온라인 쇼핑몰을 운영하다 보면 행복한 비명이 터져 나올 때가 있죠. 바로 '주문 폭주'의 순간입니다! 🥳
하지만 그 기쁨도 잠시, 늘어나는 주문만큼 복잡해지는 관리의 늪에 빠지게 됩니다.
"이 주문은 배송 준비 중인가?", "송장 번호는 입력했나?", "특정 고객의 VIP 메모는 어디에 적어뒀지?"
우커머스(WooCommerce)가 기본적으로 훌륭한 주문 관리 기능을 제공하지만, 내 쇼핑몰의 특수한 상황까지 모두 커버하기엔 2% 부족할 때가 많습니다.
예를 들어, 주문 제작 상품이라 '시안 확인 중'이라는 상태가 필요하거나, 배송 기사님 정보를 따로 기록해야 하는 경우, 혹은 특정 주문에 '긴급 처리' 플래그를 달고 싶을 때...
기본 기능만으로는 한계에 부딪히고, 결국 엑셀과 수기 장부를 오가는 번거로운 작업을 반복하게 되죠.
이 글은 바로 그런 사장님, 그리고 개발자들을 위한 맞춤 가이드입니다.
단순히 플러그인을 '설치'하는 것을 넘어, 내 쇼핑몰에 딱 맞는 주문 관리 기능을 '개발'하는 방법을 알려드릴 거예요.
코드를 한 줄 한 줄 따라가다 보면, 어느새 당신의 쇼핑몰 운영 효율은 수직 상승하고, 칼퇴는 현실이 될 겁니다.
물론 PHP와 워드프레스의 기본 구조를 알면 더 좋겠지만, 몰라도 괜찮아요. 중요한 건 '내 문제를 해결하겠다'는 의지니까요! 함께 차근차근 만들어봅시다.
1. 왜 굳이 직접 만들어야 할까? 🤔 (feat. 기성 플러그인의 한계)
"그냥 좋은 플러그인 사서 쓰면 안 되나요?" 라고 물으실 수 있습니다. 물론입니다! 이미 훌륭한 유료 플러그인들이 많이 나와 있죠.
하지만 기성복이 모든 사람의 몸에 완벽하게 맞지 않듯, 기성 플러그인도 우리 쇼핑몰의 독특한 워크플로우를 100% 만족시키기는 어렵습니다.
기성 플러그인을 썼을 때 마주하는 현실
1. 불필요한 기능의 역습 (기능 과부하)
나는 그냥 '배송 기사' 이름만 입력하는 칸이 하나 필요할 뿐인데, 플러그인을 설치하니 배송 추적, 예상 도착 시간 알림, 기사 평가 시스템 등... 쓰지도 않는 기능들이 대시보드를 어지럽힙니다. 이런 기능들은 사이트 속도를 저하시키는 주범이 되기도 하죠. 🐢
2. 미묘하게 아쉬운 2% (커스터마이징의 한계)
"아, 이 버튼 위치만 조금 옮길 수 있으면 좋겠는데...", "필드 이름을 '메모'가 아니라 '특이사항'으로 바꾸고 싶은데..."
기성 플러그인은 개발자가 정해놓은 틀 안에서만 움직여야 합니다. 이런 사소한 아쉬움들이 쌓이면 결국 업무 효율을 떨어뜨리게 됩니다.
3. 끝나지 않는 비용과 종속성 (업데이트와 호환성 문제)
유료 플러그인은 보통 연간 구독 형태로 비용이 발생합니다. 그리고 워드프레스나 우커머스가 업데이트될 때마다 플러그인 개발사가 제때 대응해주길 기다려야 하죠. 만약 업데이트가 중단되거나 다른 플러그인과 충돌이라도 발생하면... 상상만 해도 끔찍합니다. 😱
직접 개발했을 때의 압도적인 장점 ✨
1. 100% 맞춤 제작 (Perfect Fit!)
우리 쇼핑몰에 필요한 기능만 쏙쏙 골라 담을 수 있습니다. 군더더기 없이 가볍고 빠른, 우리만을 위한 주문 관리 시스템이 탄생하는 거죠.
2. 무한한 확장성 (The Sky's the Limit)
사업이 성장하면서 새로운 관리 기능이 필요해졌나요? 문제없습니다. 직접 만든 플러그인이니 언제든 원하는 기능을 추가하고 수정할 수 있습니다. 외부 ERP 시스템이나 배송사 API 연동 같은 고난도 작업도 가능해집니다.
3. 개발 능력 향상 (Level Up!)
단순히 문제를 해결하는 것을 넘어, 워드프레스와 우커머스의 작동 원리를 깊이 이해하게 됩니다. 이는 앞으로 쇼핑몰을 운영하면서 마주할 다른 문제들을 스스로 해결할 수 있는 든든한 자산이 될 거예요. 혹시 아나요? 이 경험을 살려 재능넷 같은 플랫폼에서 다른 사람들을 돕는 전문가가 될지요!
직접 개발하는 것은 우리 쇼핑몰의 업무 효율을 극대화하고, 장기적으로는 비용과 시간을 절약하며, 나아가 나의 개발 실력까지 키워주는 최고의 투자입니다.
2. 개발 환경 세팅: 우리의 디지털 공방 만들기 🛠️
자, 이제 본격적으로 연장을 챙길 시간입니다. 훌륭한 목수는 좋은 작업대에서 시작하죠.
우리도 코딩을 시작하기 전에 안전하고 효율적인 '디지털 공방', 즉 개발 환경을 구축해야 합니다.
"그냥 운영 중인 사이트에서 바로 코딩하면 안 되나요?"
절대 안 됩니다! 🙅♀️ 라이브 서버에서 직접 코드를 수정하는 것은 달리는 자동차의 엔진을 고치려는 것과 같습니다. 작은 실수 하나가 쇼핑몰 전체를 멈추게 할 수 있어요. 고객들은 '사이트 오류' 화면을 보게 될 거고, 그동안의 주문은 모두 날아갈 수 있습니다.
그래서 우리는 '내 컴퓨터'에 실제 서버와 똑같은 환경을 만들어주는 프로그램을 사용할 겁니다. 이걸 '로컬 개발 환경'이라고 불러요.
준비물 리스트 ✅
1. 로컬 서버 프로그램 (셋 중 하나만 선택하세요)
- Local (구 Local by Flywheel): 워드프레스 개발에 특화되어 있어 가장 추천합니다. 클릭 몇 번으로 워드프레스 사이트를 뚝딱 만들 수 있어 초보자에게 매우 편리합니다.
- XAMPP: 가장 전통적이고 널리 쓰이는 프로그램입니다. Apache, MariaDB, PHP, Perl을 한 번에 설치해주죠. 범용성이 높지만 초기 설정이 조금 필요할 수 있습니다.
- MAMP: XAMPP와 비슷하지만 주로 Mac 유저들이 선호하는 경향이 있습니다. (물론 윈도우 버전도 있어요!)
2. 코드 에디터 (메모장 말고 전문 도구를 씁시다)
- Visual Studio Code (VS Code): 현재 개발자 씬에서 가장 사랑받는 무료 코드 에디터입니다. 강력한 기능, 수많은 확장 프로그램, 쾌적한 속도까지. 이걸로 시작하세요. 두 번 말하면 입 아픕니다.
3. 깨끗한 워드프레스 & 우커머스
- 로컬 서버에 새로운 워드프레스를 설치하고, 관리자 페이지에서 우커머스 플러그인을 설치 및 활성화해주세요. 테스트용 상품 몇 개도 미리 등록해두면 앞으로의 작업이 편해집니다.
우리의 첫 플러그인 파일 만들기
모든 준비가 끝났다면, 이제 진짜 우리 플러그인의 '뼈대'를 만들어 보겠습니다.
1. 로컬에 설치한 워드프레스 폴더로 이동합니다. 경로는 보통 `wp-content/plugins/` 입니다. 2. 여기에 우리 플러그인을 담을 새 폴더를 하나 만듭니다. 이름은 멋지게 `jaenung-order-manager` 라고 해볼까요? 3. 방금 만든 `jaenung-order-manager` 폴더 안에, VS Code를 이용해서 새로운 파일을 하나 만듭니다. 파일 이름도 폴더 이름과 똑같이 `jaenung-order-manager.php` 로 만들어 주세요.
자, 이제 이 빈 PHP 파일에 생명을 불어넣을 시간입니다. 아래 코드를 그대로 복사해서 붙여넣어 보세요.
jaenung-order-manager.php
<?php
/**
* Plugin Name: 재능넷 주문 관리 도우미
* Plugin URI: https://www.jaenung.net
* Description: 우커머스 주문 관리를 위한 우리 쇼핑몰만의 맞춤 기능을 추가합니다.
* Version: 1.0.0
* Author: 나야나 개발자
* Author URI: https://example.com
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: jaenung-order-manager
* Domain Path: /languages
*/
// 보안을 위한 직접 접근 방지
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
// 우리 플러그인의 메인 클래스가 앞으로 이곳에 자리 잡을 예정입니다!
// Coming Soon... 🚀
- Plugin Name: 워드프레스 관리자 '플러그인' 메뉴에 표시될 이름입니다.
- Description: 플러그인에 대한 간단한 설명입니다.
- Version: 플러그인의 버전. 나중에 업데이트할 때 이 번호를 올려주면 됩니다.
- Author: 제작자 이름. 당신의 이름을 적어주세요!
- Text Domain: 나중에 플러그인을 다국어로 번역할 때 필요한 고유 식별자입니다. 보통 플러그인 폴더명(슬러그)과 일치시킵니다.
그리고 `if ( ! defined( 'ABSPATH' ) ) { exit; }` 이 코드는 정말 중요해요! 웹 브라우저에서 이 PHP 파일에 직접 접근하는 것을 막아주는 보안 장치입니다. 모든 워드프레스 플러그인과 테마 파일의 맨 앞에는 이 코드를 넣어주는 것이 국룰입니다.
파일을 저장하고 워드프레스 관리자 페이지 > 플러그인 메뉴로 가보세요.
'재능넷 주문 관리 도우미'라는 이름의 새로운 플러그인이 목록에 나타났다면, 성공입니다! 🎉
이제 '활성화' 버튼을 눌러주세요. 물론 아직 아무 기능도 없지만, 우리는 우리만의 플러그인을 세상에 태어나게 한 첫걸음을 뗀 것입니다.
3. 워드프레스의 핵심 철학: '훅(Hook)'을 이해하자 🎣
자, 이제부터 진짜 개발의 세계로 들어갑니다. 워드프레스와 우커머스를 자유자재로 요리하려면 반드시 이해해야 하는 개념이 있습니다. 바로 '훅(Hook)'입니다.
훅이 뭐냐고요? 낚시할 때 쓰는 그 '갈고리'를 떠올리면 쉽습니다.
워드프레스는 웹페이지를 만들고 여러 기능을 실행하는 과정(코어 로딩) 곳곳에 수많은 '갈고리'를 걸어두었습니다. 우리는 우리가 만든 함수(기능)를 이 갈고리에 딱! 걸어서, 원하는 타이밍에 정확하게 실행시킬 수 있습니다.
만약 훅 시스템이 없다면 어떨까요? 우리는 원하는 기능을 추가하기 위해 워드프레스 코어 파일을 직접 수정해야 할 겁니다. 이건 정말 끔찍한 일이에요. 워드프레스가 업데이트될 때마다 내가 수정한 내용이 전부 날아가 버릴 테니까요.
하지만 훅이 있기 때문에, 우리는 코어 파일을 단 한 줄도 건드리지 않고도 안전하게 기능을 추가하거나 기존 기능을 변경할 수 있습니다. 이것이 바로 워드프레스 생태계가 그토록 강력하고 유연한 이유입니다.
훅의 두 종류: 액션(Action) vs 필터(Filter)
훅은 크게 두 가지 종류로 나뉩니다. 처음엔 헷갈릴 수 있지만, 역할이 명확하게 다르니 금방 익숙해질 거예요.
1. 액션 훅 (Action Hook): "이 타이밍에, 이 일을 추가해줘!"
액션은 말 그대로 특정 시점에 어떤 '행동'을 추가하는 겁니다.
- 예시:
- `wp_head`: 웹사이트의 `
- 사용법: `add_action( '훅_이름', '실행할_내_함수_이름' );`
2. 필터 훅 (Filter Hook): "이 데이터를, 이렇게 변경해서 줘!"
필터는 기존의 데이터를 중간에 가로채서, 우리가 원하는 대로 '수정'하거나 '가공'한 뒤 다시 돌려주는 역할을 합니다.
- 예시:
- `the_title`: 글 제목이 화면에 표시되기 직전에, 제목 앞뒤에 특정 문구를 붙이고 싶을 때
- `the_content`: 글 본문 내용에서 특정 단어를 다른 단어로 자동으로 바꾸고 싶을 때
- `woocommerce_product_price`: 상품 가격 표시 형식을 바꾸고 싶을 때 (예: '50000원' -> '50,000원')
- 사용법: `add_filter( '훅_이름', '변경할_내_함수_이름' );`
- 액션(Action): 라면을 끓이는 중간에 '계란을 하나 깨서 넣는 행위'. 기존 레시피(실행 흐름)에 새로운 단계(행동)를 추가하는 거죠.
- 필터(Filter): 완성된 라면을 그릇에 담기 전에 '국물 맛을 보고 싱거워서 스프를 조금 더 넣는 행위'. 기존의 결과물(데이터)을 변경해서 최종 결과물을 바꾸는 거죠.
우리가 사용할 핵심 우커머스 훅들
이제 이 훅 개념을 우리 플러그인에 적용해볼 시간입니다. 주문 관리를 위해 우리가 주로 사용하게 될 우커머스 훅들은 다음과 같습니다. 이름만 봐도 대충 어떤 역할을 할지 감이 오죠?
- `wc_order_statuses`: 주문 상태 목록을 필터링하여 새로운 상태를 추가할 때. - `manage_edit-shop_order_columns`: 주문 목록 페이지의 컬럼(열)을 필터링하여 새로운 컬럼을 추가할 때. - `manage_shop_order_posts_custom_column`: 새로 추가한 컬럼에 어떤 내용을 표시할지 액션을 추가할 때. - `woocommerce_admin_order_data_after_billing_address`: 주문 상세 페이지의 특정 위치에 새로운 입력 필드 등을 표시하는 액션을 추가할 때. - `woocommerce_process_shop_order_meta`: 주문 상세 페이지에서 '저장' 버튼을 눌렀을 때, 우리가 추가한 필드의 데이터를 저장하는 액션을 추가할 때.
이 훅들만 잘 활용해도 주문 관리의 80%는 해결할 수 있습니다. 이제 이 훅들을 가지고 실제로 기능을 만들어보면서 감을 익혀봅시다!
4. 실전! 첫 기능 개발: '시안 확인 중' 커스텀 주문 상태 만들기 🎨
백문이 불여일견! 이제 직접 코드를 작성하며 첫 기능을 만들어봅시다.
주문 제작 쇼핑몰을 운영한다고 가정해볼게요. 고객이 주문을 완료하면, 바로 '처리 중'으로 넘기는 게 아니라 디자이너가 만든 '시안'을 고객에게 보내고 확인받는 과정이 필요합니다.
이럴 때 '시안 확인 중'이라는 주문 상태가 있다면, 주문 관리가 훨씬 수월해지겠죠? 지금부터 이 상태를 직접 만들어 보겠습니다.
`jaenung-order-manager.php` 파일을 열고, 맨 아래에 다음 코드를 추가해주세요.
Step 1: 새로운 주문 상태 등록하기
먼저 워드프레스에 "우리 이런 새로운 주문 상태를 쓸 거야!"라고 알려줘야 합니다. 이때 사용하는 훅이 바로 `wc_order_statuses` 필터 훅입니다.
jaenung-order-manager.php
// 1. 새로운 주문 상태를 등록하는 함수
function jaenung_register_custom_order_status( $order_statuses ) {
// $order_statuses 에는 기존의 주문 상태들이 배열 형태로 담겨있습니다.
// 여기에 우리의 새로운 상태를 추가하는 겁니다.
$new_order_statuses = array();
// 기존 상태들 앞에 우리의 상태를 추가하고 싶을 때
foreach ( $order_statuses as $key => $status ) {
$new_order_statuses[ $key ] = $status;
// '처리 중(processing)' 상태 바로 다음에 '시안 확인 중'을 추가해봅시다.
if ( 'wc-processing' === $key ) {
$new_order_statuses['wc-design-confirm'] = '시안 확인 중';
}
}
return $new_order_statuses;
}
add_filter( 'wc_order_statuses', 'jaenung_register_custom_order_status' );
- `function jaenung_register_custom_order_status( $order_statuses ) { ... }`: `jaenung_register_custom_order_status` 라는 이름의 우리 함수를 정의합니다. 괄호 안의 `$order_statuses`는 우커머스가 넘겨주는 '기존 주문 상태 목록' 데이터입니다.
- `$new_order_statuses['wc-design-confirm'] = '시안 확인 중';`: 새로운 주문 상태를 추가하는 핵심 코드입니다.
- `wc-design-confirm`: 시스템이 사용할 주문 상태의 고유 ID(슬러그)입니다. 다른 플러그인과 겹치지 않도록 `wc-` 접두사를 붙이는 것이 규칙입니다.
- `'시안 확인 중'`: 관리자 화면에 실제로 표시될 이름입니다.
- `return $new_order_statuses;`: 필터 훅에 연결된 함수는 반드시 가공된 결과(`$new_order_statuses`)를 `return` 해주어야 합니다. 이걸 빼먹으면 모든 주문 상태가 사라지는 마법을 보게 될 겁니다!
- `add_filter( 'wc_order_statuses', 'jaenung_register_custom_order_status' );`: "우커머스의 `wc_order_statuses` 필터가 실행될 때, 우리가 만든 `jaenung_register_custom_order_status` 함수를 실행해줘!" 라고 워드프레스에 알려주는, 즉 '훅에 거는' 코드입니다.
이 코드를 저장하고, 우커머스 주문 상세 페이지로 가서 '주문 상태' 드롭다운 메뉴를 클릭해보세요.
'처리 중' 바로 아래에 '시안 확인 중'이라는 새로운 옵션이 생긴 것을 볼 수 있습니다!
Step 2: 주문 목록 '일괄 작업'에도 추가하기
새로운 상태를 만들었으니, 이제 주문 목록 페이지에서 여러 주문을 한 번에 '시안 확인 중'으로 바꿀 수 있으면 더 편리하겠죠?
jaenung-order-manager.php (아래에 이어서 추가)
// 2. 일괄 작업(Bulk Actions)에 새로운 주문 상태 추가
function jaenung_add_bulk_order_status( $bulk_actions ) {
// 'mark_processing' (처리 중으로 변경) 다음에 추가해봅시다.
$bulk_actions['mark_design-confirm'] = '상태를 시안 확인 중으로 변경';
return $bulk_actions;
}
add_filter( 'bulk_actions-edit-shop_order', 'jaenung_add_bulk_order_status' );
이 코드를 추가하고 주문 목록 페이지(`wp-admin/edit.php?post_type=shop_order`)로 가서 확인해보세요.
'일괄 작업' 드롭다운 메뉴에 '상태를 시안 확인 중으로 변경'이라는 옵션이 추가되었을 겁니다.
Step 3: 새로운 상태에 색깔 옷 입히기 (CSS 추가)
기능은 완성됐지만, 주문 목록에서 '시안 확인 중' 상태가 회색으로만 표시되니 눈에 잘 띄지 않네요.
우리만의 색상을 지정해서 시각적으로 구분하기 쉽게 만들어 봅시다. 관리자 페이지에 CSS를 추가하는 `admin_head` 액션 훅을 사용하면 됩니다.
jaenung-order-manager.php (아래에 이어서 추가)
// 3. 새로운 주문 상태에 대한 CSS 스타일 추가
function jaenung_custom_order_status_style() {
echo '<style>
.order-status.status-design-confirm {
background: #c8e6c9; /* 연한 녹색 배경 */
color: #2e7d32; /* 진한 녹색 글씨 */
}
</style>';
}
add_action( 'admin_head', 'jaenung_custom_order_status_style' );
우리가 만든 상태의 슬러그가 `wc-design-confirm` 이었죠? 여기서 `wc-`를 떼고 `design-confirm` 앞에 `status-`를 붙여서 `.status-design-confirm` 이라는 클래스를 선택자로 사용하는 겁니다.
이제 다시 주문 목록을 확인해보세요. '시안 확인 중' 상태의 주문에 예쁜 녹색 라벨이 붙어 한눈에 쏙 들어올 겁니다! 🤩
어때요, 생각보다 어렵지 않죠? 우리는 단지 몇 줄의 코드로 우커머스의 핵심 기능을 확장했습니다. 이것이 바로 훅 시스템의 강력함입니다.
5. 레벨 업! 주문에 나만의 정보 추가하기 (커스텀 필드) 📝
커스텀 주문 상태만으로는 부족할 때가 있습니다. 예를 들어, 배송을 담당할 내부 직원이나 배송 기사님을 특정 주문에 할당해야 하는 경우를 생각해봅시다. 또는 고객과의 상담 내용을 간단히 메모해둬야 할 수도 있죠.
이럴 때 필요한 것이 바로 '커스텀 필드(Custom Field)'입니다. 주문 상세 정보에 우리가 원하는 입력란을 만들고, 데이터를 저장하고, 또 보여주는 기능이죠.
이번에는 '내부 관리 메모'라는 텍스트 입력란을 주문 편집 화면에 추가해보겠습니다. 이 메모는 관리자에게만 보이고 고객에게는 노출되지 않도록 할 거예요.
Step 1: 주문 편집 화면에 입력 필드 표시하기
먼저 관리자가 주문을 편집하는 화면(`wp-admin/post.php?post=주문ID&action=edit`)에 '내부 관리 메모'를 입력할 수 있는 `<textarea>`를 만들어야 합니다.
어디에 표시할까요? '청구 주소' 정보 아래가 적당해 보이네요. 이때 사용하는 훅이 바로 `woocommerce_admin_order_data_after_billing_address` 입니다. 이름 그대로 '관리자 주문 데이터 중 청구 주소 뒤에' 실행되는 액션 훅이죠.
jaenung-order-manager.php (아래에 이어서 추가)
// 4. 주문 편집 화면에 커스텀 필드 추가
function jaenung_add_custom_field_to_order( $order ) {
// $order 객체에서 주문 ID를 가져옵니다.
$order_id = $order->get_id();
// 이전에 저장된 메모 값을 불러옵니다. get_post_meta 함수를 사용합니다.
// '_internal_memo'는 우리가 데이터를 저장할 때 사용할 고유 키(key)입니다.
$memo = get_post_meta( $order_id, '_internal_memo', true );
echo '<div class="address_class">';
echo '<h3>📝 내부 관리 메모</h3>';
// textarea 필드를 만듭니다.
woocommerce_wp_textarea_input( array(
'id' => '_internal_memo',
'label' => '관리자 전용 메모:',
'wrapper_class' => 'form-field-wide',
'value' => $memo,
'description' => '이 메모는 고객에게 표시되지 않습니다.',
'desc_tip' => true,
) );
echo '</div>';
}
add_action( 'woocommerce_admin_order_data_after_billing_address', 'jaenung_add_custom_field_to_order' );
코드를 저장하고 아무 주문이나 편집 화면으로 들어가 보세요. 청구 주소 아래에 '내부 관리 메모'라는 제목과 함께 텍스트 입력란이 짠! 하고 나타났을 겁니다.
Step 2: 입력된 데이터 저장하기
이제 입력란에 내용을 쓰고 '업데이트' 버튼을 눌렀을 때, 그 내용이 데이터베이스에 저장되도록 만들어야 합니다.
이때 사용하는 훅이 `woocommerce_process_shop_order_meta` 입니다. 주문 메타 정보가 처리될 때 실행되는 액션이죠.
jaenung-order-manager.php (아래에 이어서 추가)
// 5. 커스텀 필드 데이터 저장
function jaenung_save_custom_field_data( $order_id ) {
// 우리 필드(_internal_memo)에 데이터가 넘어왔는지 확인합니다.
if ( isset( $_POST['_internal_memo'] ) ) {
// 데이터베이스에 저장하기 전에 항상 데이터를 소독(sanitize)해야 합니다.
// 여러 줄의 텍스트이므로 sanitize_textarea_field 함수를 사용합니다.
$memo_value = sanitize_textarea_field( $_POST['_internal_memo'] );
// update_post_meta 함수로 데이터를 저장(또는 업데이트)합니다.
update_post_meta( $order_id, '_internal_memo', $memo_value );
}
}
add_action( 'woocommerce_process_shop_order_meta', 'jaenung_save_custom_field_data' );
`sanitize_textarea_field()` 같은 워드프레스의 '소독(Sanitization)' 함수는 이런 위험한 코드를 제거하고 안전한 텍스트만 남겨주는 역할을 합니다. 사용자 입력을 다룰 때는 반드시, 무조건, 꼭! 데이터 종류에 맞는 소독 함수를 거쳐야 합니다.
- `sanitize_text_field()`: 일반적인 한 줄 텍스트용
- `sanitize_email()`: 이메일 주소용
- `absint()`: 양의 정수(숫자)용
이제 모든 준비가 끝났습니다. 주문 편집 화면으로 돌아가 '내부 관리 메모'에 아무 내용이나 입력하고 '업데이트' 버튼을 눌러보세요.
페이지가 새로고침된 후에도 내가 입력한 내용이 그대로 남아있다면, 데이터가 성공적으로 저장된 것입니다! 🎉
우리는 이제 주문마다 고유한 추가 정보를 기록할 수 있는 강력한 무기를 손에 넣었습니다. 이 원리를 응용하면 '배송 기사 선택', '포장 담당자', '고객 등급' 등 원하는 어떤 정보든 추가하고 관리할 수 있게 됩니다.
6. 주문 목록 페이지 커스터마이징: 한눈에 모든 정보 파악하기 📊
'내부 관리 메모'를 주문마다 저장할 수 있게 되었지만, 한 가지 아쉬운 점이 있습니다.
메모를 확인하려면 주문 하나하나를 클릭해서 상세 페이지로 들어가야 한다는 거죠. 주문이 수십, 수백 개라면 이건 엄청난 시간 낭비입니다.
만약 주문 목록 페이지에서 이 메모를 바로 볼 수 있다면 어떨까요? 혹은 메모가 있는 주문만 따로 필터링할 수 있다면요?
이번 챕터에서는 주문 목록 페이지(`wp-admin/edit.php?post_type=shop_order`)를 우리 입맛에 맞게 '튜닝'하는 방법을 배워보겠습니다.
Step 1: 주문 목록에 새로운 '메모' 컬럼 추가하기
먼저 '주문', '날짜', '상태', '총계' 등이 표시되는 주문 목록 테이블에 '내부 메모'라는 새로운 열(Column)을 추가해 보겠습니다.
이때 사용하는 훅은 `manage_edit-shop_order_columns` 필터 훅입니다.
jaenung-order-manager.php (아래에 이어서 추가)
// 6. 주문 목록에 새로운 컬럼 추가
function jaenung_add_order_list_custom_column( $columns ) {
// 기존 컬럼들을 재정렬해서 '총계(order_total)' 컬럼 뒤에 새 컬럼을 추가합니다.
$reordered_columns = array();
foreach ( $columns as $key => $column ) {
$reordered_columns[$key] = $column;
if ( $key === 'order_total' ) {
// 새 컬럼을 추가합니다.
// 'internal_memo_column'은 컬럼의 고유 ID, '내부 메모'는 화면에 표시될 이름입니다.
$reordered_columns['internal_memo_column'] = '내부 메모 📝';
}
}
return $reordered_columns;
}
add_filter( 'manage_edit-shop_order_columns', 'jaenung_add_order_list_custom_column' );
코드를 저장하고 주문 목록 페이지를 새로고침 해보세요. '총계' 열 바로 옆에 '내부 메모 📝'라는 새로운 열이 생긴 것을 확인할 수 있습니다. 물론 아직은 내용이 비어있죠. 이제 이 빈칸을 채워줄 차례입니다.
Step 2: 새로 만든 컬럼에 데이터 채우기
새로 만든 열에 실제 메모 데이터를 표시하려면 `manage_shop_order_posts_custom_column` 액션 훅을 사용해야 합니다.
이 훅은 각 주문(행)의 각 컬럼(열)이 렌더링될 때마다 실행됩니다. 우리는 이 훅을 이용해서 "지금 렌더링하는 컬럼이 우리가 만든 'internal_memo_column'이 맞다면, 이 주문에 저장된 메모 값을 가져와서 출력해줘!" 라고 명령할 겁니다.
jaenung-order-manager.php (아래에 이어서 추가)
// 7. 새로 추가한 컬럼에 데이터 표시
function jaenung_display_data_in_custom_column( $column, $post_id ) {
// 현재 처리 중인 컬럼이 우리가 추가한 'internal_memo_column'인지 확인합니다.
if ( 'internal_memo_column' === $column ) {
// $post_id가 바로 주문 ID입니다.
// get_post_meta 함수로 저장된 메모 값을 가져옵니다.
$memo = get_post_meta( $post_id, '_internal_memo', true );
if ( ! empty( $memo ) ) {
// 메모가 존재하면 출력합니다.
// esc_html() 함수로 감싸서 보안을 강화합니다.
echo esc_html( $memo );
} else {
// 메모가 없으면 '-'를 표시합니다.
echo '–';
}
}
}
// 훅에 함수를 연결할 때, 뒤에 숫자 2를 추가했습니다.
// 이는 이 함수가 2개의 파라미터($column, $post_id)를 받는다는 것을 워드프레스에 알려주는 의미입니다.
add_action( 'manage_shop_order_posts_custom_column', 'jaenung_display_data_in_custom_column', 10, 2 );
- `10` (Priority, 우선순위): 같은 훅에 여러 함수가 연결되어 있을 때, 어떤 함수를 먼저 실행할지 정하는 숫자입니다. 숫자가 작을수록 먼저 실행됩니다. 기본값은 10이라 보통 생략하지만, 명시적으로 적어주는 것이 좋습니다.
- `2` (Accepted Arguments, 인자 개수): 이 훅이 실행될 때 우리 함수로 몇 개의 파라미터(인자)를 전달받을지 알려주는 숫자입니다. `manage_shop_order_posts_custom_column` 훅은 `$column`과 `$post_id` 두 개의 인자를 제공하므로, `2`라고 적어줘야 두 개 모두 정상적으로 받을 수 있습니다.
자, 이제 다시 주문 목록 페이지를 확인해보세요! 이전에 메모를 입력했던 주문의 '내부 메모' 칸에 해당 내용이 멋지게 표시될 겁니다. 이제 더 이상 메모를 확인하기 위해 주문 상세 페이지를 들락날락할 필요가 없어졌습니다. 업무 효율이 또 한 단계 상승했네요!
응용: 컬럼을 클릭해서 정렬 가능하게 만들기 (심화)
여기서 한 걸음 더 나아가, '내부 메모' 컬럼 헤더를 클릭했을 때 메모가 있는 주문과 없는 주문을 정렬할 수 있다면 어떨까요? 이건 조금 더 복잡하지만, 한번 도전해볼 만한 가치가 있습니다.
이 기능은 워드프레스의 메인 쿼리를 수정해야 하므로, 코드가 조금 길어집니다. 하지만 원리를 이해하면 다른 어떤 컬럼이든 정렬 가능하게 만들 수 있습니다.
먼저 컬럼을 정렬 가능하게 등록하고(`manage_edit-shop_order_sortable_columns` 필터), 그 다음 정렬 요청이 들어왔을 때 실제로 쿼리를 어떻게 변경할지(`pre_get_posts` 액션) 정의해야 합니다.
jaenung-order-manager.php (아래에 이어서 추가)
// 8. '내부 메모' 컬럼을 정렬 가능하게 만들기
function jaenung_make_memo_column_sortable( $columns ) {
$columns['internal_memo_column'] = 'internal_memo_column';
return $columns;
}
add_filter( 'manage_edit-shop_order_sortable_columns', 'jaenung_make_memo_column_sortable' );
// 9. 정렬 로직 처리
function jaenung_memo_column_orderby( $query ) {
// 관리자 페이지의 메인 쿼리가 아니면 그냥 리턴
if ( ! is_admin() || ! $query->is_main_query() ) {
return;
}
// 정렬 기준이 'internal_memo_column'일 때만 실행
if ( 'internal_memo_column' === $query->get( 'orderby' ) ) {
$query->set( 'meta_key', '_internal_memo' );
// 메타 값이 존재하는지 여부로 정렬하기 위해 meta_value_num 대신 meta_key로 정렬
// 또는 특정 텍스트로 정렬하고 싶다면 $query->set('orderby', 'meta_value');
$query->set( 'orderby', 'meta_value' );
}
}
add_action( 'pre_get_posts', 'jaenung_memo_column_orderby' );
이 코드를 추가하면 '내부 메모' 컬럼 헤더에 위아래 화살표가 생기고, 클릭하면 메모 내용의 가나다순으로 주문들이 정렬됩니다. 이제 특정 메모를 찾거나, 메모가 있는 주문들만 모아보기가 훨씬 쉬워졌습니다.
7. 고객 경험 개선: 내 계정 페이지에 정보 보여주기 🙋♀️
지금까지 우리는 관리자 입장에서의 효율성 향상에 집중했습니다.
하지만 쇼핑몰의 성공은 결국 고객 만족에 달려있죠. 우리가 만든 커스텀 기능을 고객에게도 유용한 정보로 제공할 수 있다면 어떨까요?
예를 들어, 주문 제작 상품의 '시안 확인 중' 상태를 고객이 '내 계정' 페이지에서 직접 볼 수 있게 하거나, 발송이 완료된 주문에 '담당 배송 기사: 김재능' 같은 정보를 표시해주는 겁니다. 이런 사소한 디테일이 고객에게 신뢰감을 주고, 재방문을 유도하는 강력한 무기가 될 수 있습니다.
이번에는 '내부 관리 메모'와는 별개로, 고객에게 보여줄 '배송 관련 안내'라는 새로운 커스텀 필드를 만들고, 이 정보를 고객의 주문 상세 페이지에 표시해보겠습니다.
Step 1: '배송 관련 안내' 커스텀 필드 추가 (관리자용)
이 과정은 5장에서 했던 '내부 관리 메모' 필드 추가와 거의 동일합니다. 복습하는 셈 치고 빠르게 만들어 봅시다.
jaenung-order-manager.php (아래에 이어서 추가)
// 10. 고객 안내용 커스텀 필드 추가 (관리자 주문 편집 화면)
function jaenung_add_shipping_notice_field_to_order( $order ) {
woocommerce_wp_textarea_input( array(
'id' => '_shipping_notice',
'label' => '🚚 배송 관련 안내 (고객에게 표시됩니다):',
'wrapper_class' => 'form-field-wide',
'value' => $order->get_meta( '_shipping_notice' ), // $order 객체에서 직접 메타 데이터 가져오기
'description' => '이 내용은 고객의 내 계정 > 주문 상세 페이지에 표시됩니다.',
'desc_tip' => true,
) );
}
// 이번에는 배송 주소 뒤에 붙여볼까요?
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'jaenung_add_shipping_notice_field_to_order' );
// 11. 고객 안내용 커스텀 필드 데이터 저장
function jaenung_save_shipping_notice_field_data( $order_id ) {
if ( isset( $_POST['_shipping_notice'] ) ) {
$notice_value = sanitize_textarea_field( $_POST['_shipping_notice'] );
update_post_meta( $order_id, '_shipping_notice', $notice_value );
}
}
add_action( 'woocommerce_process_shop_order_meta', 'jaenung_save_shipping_notice_field_data' );
위 코드를 추가하고 주문 편집 페이지에 가보면 '배송 주소' 정보 아래에 새로운 입력란이 생긴 것을 확인할 수 있습니다. 여기에 "오후 3시경 로젠택배로 발송 예정입니다." 와 같은 안내 문구를 입력하고 저장해보세요.
Step 2: '내 계정' 주문 상세 페이지에 안내 문구 표시하기
이제 가장 중요한 부분입니다. 관리자가 입력한 이 안내 문구를 고객이 볼 수 있도록 만들어야 합니다.
고객이 '내 계정 > 주문' 메뉴에서 특정 주문을 클릭했을 때 나오는 상세 페이지에 이 정보를 추가할 겁니다.
이때 사용할 수 있는 아주 유용한 훅이 `woocommerce_order_details_after_order_table` 입니다. 이름 그대로 '주문 상세 정보 테이블 바로 뒤'에 실행되는 액션 훅이죠.
jaenung-order-manager.php (아래에 이어서 추가)
// 12. '내 계정' 주문 상세 페이지에 배송 안내 문구 표시
function jaenung_display_shipping_notice_to_customer( $order ) {
// 주문 객체에서 메타 데이터를 가져옵니다.
$shipping_notice = $order->get_meta( '_shipping_notice' );
// 안내 문구가 존재할 경우에만 표시합니다.
if ( ! empty( $shipping_notice ) ) {
echo '<h2 class="woocommerce-order-details__title">배송 관련 안내</h2>';
echo '<div style="border: 1px solid #e0e0e0; padding: 15px; margin-bottom: 20px; border-radius: 5px;">';
// nl2br() 함수는 줄바꿈(\n)을 <br> 태그로 변환해줍니다.
// wp_kses_post() 함수는 허용된 HTML 태그만 남기고 나머지는 제거하여 보안을 강화합니다.
echo wp_kses_post( nl2br( $shipping_notice ) );
echo '</div>';
}
}
add_action( 'woocommerce_order_details_after_order_table', 'jaenung_display_shipping_notice_to_customer' );
`) 같은 서식을 유지해주는 것이 좋습니다.
이때 `wp_kses_post()` 함수를 사용하면, 워드프레스가 기본적으로 글(Post)에 허용하는 안전한 HTML 태그들(예: `, , ,
,
`)은 남겨두고, 위험한 `<script>` 같은 태그는 제거해줍니다. 고객에게 데이터를 보여줄 때는 `esc_html()`보다 `wp_kses_post()`가 더 유연하고 안전한 선택이 될 수 있습니다.
이제 고객 계정으로 로그인해서, 방금 안내 문구를 추가했던 주문의 상세 페이지를 확인해보세요.
주문 상품 목록 아래에 '배송 관련 안내'라는 제목과 함께 우리가 입력한 내용이 예쁘게 표시되는 것을 볼 수 있습니다!
이처럼 관리자 페이지의 데이터를 프론트엔드와 연결하는 것만으로도 고객 경험을 크게 향상시킬 수 있습니다. 고객은 더 이상 전화나 게시판으로 배송 상황을 묻지 않아도 되고, 쇼핑몰은 CS 업무 부담을 줄일 수 있으니, 이것이야말로 진정한 윈윈(Win-Win) 전략 아닐까요?
8. 플러그인 품격 높이기: 베스트 프랙티스 & 다음 단계 🚀
축하합니다! 🎉 여러분은 이제 우커머스 주문 관리의 핵심 기능을 직접 개발하고 확장할 수 있는 능력을 갖추게 되었습니다.
하지만 '작동하는 코드'를 만드는 것과 '좋은 코드'를 만드는 것 사이에는 차이가 있습니다. 우리가 만든 플러그인을 더 안정적이고, 유지보수하기 쉽고, 다른 개발자와 협업하기 좋게 만들려면 몇 가지 원칙을 지키는 것이 좋습니다.
이번 챕터에서는 우리의 플러그인 코드를 한 단계 업그레이드하는 '베스트 프랙티스'와 앞으로 무엇을 더 배울 수 있을지에 대해 이야기해 보겠습니다.
보안, 보안, 그리고 또 보안! (Security) 🛡️
이미 여러 번 강조했지만, 보안은 아무리 강조해도 지나치지 않습니다.
- 데이터 입력(Input) 시에는 항상 소독(Sanitize): `$_POST`, `$_GET` 등 사용자로부터 들어오는 모든 데이터는 `sanitize_*` 계열 함수로 반드시 소독한 후 사용하세요. - 데이터 출력(Output) 시에는 항상 이스케이프(Escape): 데이터베이스에서 가져온 값을 화면에 표시할 때는 `esc_html()`, `esc_attr()`, `esc_url()`, `wp_kses_post()` 등 상황에 맞는 이스케이프 함수로 감싸서 예기치 않은 스크립트 실행(XSS 공격)을 방지하세요. - 권한 확인(Nonce): 폼(Form)을 통해 데이터를 전송받을 때는 Nonce(Number used once)를 사용해서 요청이 올바른 위치에서, 올바른 사용자에 의해 발생했는지 검증해야 합니다. (이 글에서는 다루지 않았지만, 중요한 개념이니 꼭 따로 학습해보세요!)
코드를 정리정돈하자 (Maintainability) 整理
지금은 모든 코드가 하나의 PHP 파일 안에 있지만, 기능이 점점 많아지면 이 파일은 수천 줄에 달하는 스파게티 코드가 될 겁니다. 🍝
나중에 내가 봐도 알아보기 힘든 코드는 절대 좋은 코드가 아닙니다.
- 기능별로 파일 분리: 관리자 관련 기능은 `includes/admin/class-admin-features.php`, 프론트엔드 관련 기능은 `includes/public/class-public-display.php` 와 같이 파일을 분리하고, 메인 플러그인 파일에서는 이 파일들을 `require_once` 로 불러오는 구조를 사용하세요. - 객체 지향 프로그래밍 (OOP) 도입: 모든 함수를 그냥 나열하는 대신, 관련 있는 함수와 변수들을 하나의 클래스(Class)로 묶어서 관리하면 코드의 구조가 훨씬 명확해지고 재사용성도 높아집니다.
// jaenung-order-manager.php (메인 파일)
class Jaenung_Order_Manager {
public function __construct() {
$this->load_dependencies();
$this->init_hooks();
}
private function load_dependencies() {
require_once plugin_dir_path( __FILE__ ) . 'includes/class-custom-status.php';
require_once plugin_dir_path( __FILE__ ) . 'includes/class-custom-fields.php';
}
private function init_hooks() {
$status_handler = new Jaenung_Custom_Status();
add_filter( 'wc_order_statuses', array( $status_handler, 'register_status' ) );
$field_handler = new Jaenung_Custom_Fields();
add_action( 'woocommerce_admin_order_data_after_billing_address', array( $field_handler, 'display_field' ) );
add_action( 'woocommerce_process_shop_order_meta', array( $field_handler, 'save_field' ) );
}
}
new Jaenung_Order_Manager();
위와 같이 코드를 구조화하면, 각 기능의 책임이 명확하게 분리되어 관리가 훨씬 쉬워집니다.
세계를 무대로 (Internationalization, i18n) 🌍
우리 쇼핑몰이 해외로 진출할 수도 있고, 혹은 우리가 만든 플러그인을 다른 나라 사람들도 사용할 수 있게 배포하고 싶을 수도 있습니다.
이때를 대비해 플러그인 내의 모든 문자열을 번역 가능하게 만드는 것이 좋습니다.
- `__()` 와 `_e()` 함수 사용:
- `'내부 메모'` -> `__( 'Internal Memo', 'jaenung-order-manager' )`
- `echo '내부 메모';` -> `_e( 'Internal Memo', 'jaenung-order-manager' );`
이렇게 문자열을 감싸주기만 하면, Poedit 같은 프로그램을 통해 번역 파일을 쉽게 생성할 수 있습니다. 두 번째 인자는 플러그인 헤더에 정의했던 'Text Domain'과 일치시켜야 합니다.
다음 스텝: 무엇을 더 해볼까?
우리가 배운 것은 빙산의 일각에 불과합니다. 우커머스 개발의 세계는 무궁무진하죠.
- 플러그인 설정 페이지 만들기: 워드프레스 Settings API를 사용해서 관리자가 직접 커스텀 필드를 추가/삭제하거나, 주문 상태의 색상을 변경할 수 있는 설정 페이지를 만들어보세요. - REST API 확장: 우커머스 REST API에 우리가 만든 커스텀 필드 데이터를 포함시키거나, 특정 주문 상태의 주문 목록만 가져오는 새로운 API 엔드포인트를 만들어보세요. 외부 앱이나 서비스와 연동할 때 필수적인 기술입니다. - 자동화(Automation): 특정 상품이 포함된 주문은 자동으로 '제작 요청' 상태로 변경하거나, 주문 상태가 '배송 완료'로 변경된 후 7일이 지나면 자동으로 '구매 확정' 상태로 변경하는 등의 자동화 로직을 구현해보세요.
물론 이 모든 것을 혼자서 해내기란 쉽지 않을 수 있습니다. 개발 중에 막히는 부분이 생기거나, 내 아이디어를 구현하기에 기술적으로 벅찰 때가 분명히 올 겁니다. 그럴 때는 주저하지 말고 전문가의 도움을 받는 것이 현명한 선택일 수 있습니다. 재능넷과 같은 전문가 플랫폼에는 여러분의 문제를 해결해 줄 수 있는 실력 있는 워드프레스 개발자들이 많이 있습니다. 때로는 전문가의 도움을 통해 시간을 절약하고 더 높은 퀄리티의 결과물을 얻는 것이 장기적으로 더 큰 이득이 될 수 있습니다.
마치며: 이제 당신도 우커머스 마스터! 🧙♂️
여기까지 따라오시느라 정말 고생 많으셨습니다!
우리는 단순히 코드를 복사-붙여넣기 한 것이 아닙니다. 워드프레스의 핵심 철학인 '훅' 시스템을 이해했고, 이를 활용해 우커머스의 주문 관리 기능을 우리 쇼핑몰에 맞게 재단하는 방법을 배웠습니다.
이제 여러분의 관리자 화면은 더 이상 밋밋한 기본 화면이 아닐 겁니다. 여러분의 비즈니스 로직이 고스란히 담긴, 살아 숨 쉬는 강력한 대시보드가 되었을 겁니다. '시안 확인 중' 상태를 보며 디자인팀과 원활하게 소통하고, '내부 메모' 컬럼을 보며 CS팀의 업무를 한눈에 파악하고, 고객에게 전송되는 '배송 관련 안내'를 통해 고객 만족도를 높이는 모습을 상상해보세요.
오늘 배운 지식은 단지 시작일 뿐입니다. 이 경험을 발판 삼아 더 대담한 아이디어에 도전해보세요.
"결제 수단에 따라 주문 상태를 다르게 지정할 수 있을까?", "특정 카테고리 상품 주문 시, 자동으로 특정 담당자에게 이메일을 보낼 수 있을까?"
정답은 'YES'입니다. 워드프레스와 우커머스, 그리고 여러분의 손에 들린 '훅'이라는 강력한 도구가 있다면, 상상하는 대부분의 기능을 구현할 수 있습니다.
두려워하지 말고, 일단 만들어보세요. 에러가 나면 원인을 찾아 해결하고, 더 좋은 방법이 떠오르면 코드를 개선해나가세요. 그 과정 하나하나가 여러분을 더 뛰어난 개발자, 더 효율적인 쇼핑몰 운영자로 만들어 줄 겁니다.
이제 코드는 당신의 비즈니스를 성장시키는 가장 강력한 무기입니다.
이 글이 여러분의 여정에 작은 도움이 되었기를 바랍니다. Happy Coding! 💻✨
댓글 작성
이 글에 대한 여러분의 생각을 들려주세요
로그인이 필요합니다
댓글을 작성하려면 먼저 로그인해주세요.
댓글 0
지식인의 숲 - 지적 재산권 보호 고지
지적 재산권 보호 고지
- 저작권 및 소유권: 본 컨텐츠는 재능넷의 독점 AI 기술로 생성되었으며, 대한민국 저작권법 및 국제 저작권 협약에 의해 보호됩니다.
- AI 생성 컨텐츠의 법적 지위: 본 AI 생성 컨텐츠는 재능넷의 지적 창작물로 인정되며, 관련 법규에 따라 저작권 보호를 받습니다.
- 사용 제한: 재능넷의 명시적 서면 동의 없이 본 컨텐츠를 복제, 수정, 배포, 또는 상업적으로 활용하는 행위는 엄격히 금지됩니다.
- 데이터 수집 금지: 본 컨텐츠에 대한 무단 스크래핑, 크롤링, 및 자동화된 데이터 수집은 법적 제재의 대상이 됩니다.
- AI 학습 제한: 재능넷의 AI 생성 컨텐츠를 타 AI 모델 학습에 무단 사용하는 행위는 금지되며, 이는 지적 재산권 침해로 간주됩니다.
아직 댓글이 없습니다.