* 이 게시물은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
(워드프레스 해부 ⑲) 보안
워드프레스를 확장하다 보면 폼을 만들고, 입력을 받고, 값을 출력한다. 이 세 지점이 각각 공격 표면이다. 그래서 방어도 세 가지 — nonce, sanitize, escape. 이 3종을 습관으로 만들면 대부분의 흔한 취약점을 막는다.
- nonce — 요청 위조(CSRF) 방지. “이 폼 제출이 정말 우리 사이트에서, 이 사용자가 보낸 게 맞나”를 확인하는 일회성 토큰.
- sanitize(정화) — 입력을 저장하기 전에 위험한 걸 걸러낸다.
sanitize_text_field(),sanitize_email()등. - escape(이스케이프) — 출력할 때 HTML/JS로 해석될 수 있는 문자를 무해하게.
esc_html(),esc_attr(),esc_url().
외우기 쉽게: “들어올 땐 sanitize, 나갈 땐 escape, 폼엔 nonce.” 특히 escape는 “신뢰할 수 없는 데이터”뿐 아니라 출력하는 거의 모든 동적 값에 습관적으로 거는 게 안전하다.
직접 해보기
// 안전한 폼 처리의 전형
// 1) 폼에 nonce 필드 심기
wp_nonce_field( 'save_my_form', 'my_form_nonce' );
// 2) 제출 처리 — nonce 검증 → sanitize → 저장
if ( isset( $_POST['my_form_nonce'] )
&& wp_verify_nonce( $_POST['my_form_nonce'], 'save_my_form' ) ) {
$name = sanitize_text_field( $_POST['name'] ); // 입력 정화
update_option( 'my_name', $name );
}
// 3) 출력 — 언제나 escape
echo '<p>' . esc_html( get_option( 'my_name' ) ) . '</p>';
✅ 확인 — 폼을 만들 때
wp_nonce_field()를 넣고, 처리에서wp_verify_nonce()로 검증하는 흐름을 갖추자. nonce 없이 저장 처리를 하면, 외부 사이트가 사용자 몰래 요청을 위조할 수 있는 구멍이 생긴다. 이 3종이 워드프레스 개발의 기본 위생이다.
코드로 보는 3종 세트
폼 하나의 생애로 보면 어디에 무엇을 쓰는지 명확해진다. 출력 시 nonce 심기 → 제출 시 nonce 검증 + sanitize → 화면 출력 시 escape.
// 폼 출력 — nonce 심기
wp_nonce_field( 'save_profile', 'profile_nonce' );
// 제출 처리 — 검증 후 정화
if ( ! isset( $_POST['profile_nonce'] ) ||
! wp_verify_nonce( $_POST['profile_nonce'], 'save_profile' ) ) wp_die( '요청 거부' );
$name = sanitize_text_field( $_POST['name'] ?? '' ); // 입력 정화
update_user_meta( $uid, 'display', $name );
// 화면 출력 — 이스케이프
echo '<span>' . esc_html( $name ) . '</span>';
sanitize vs escape — 헷갈리지 않기
핵심 구분 하나. sanitize는 ‘들어올 때'(입력·저장), escape는 ‘나갈 때'(출력)다. 둘은 대체가 아니라 짝이다. 저장 시 정화했더라도, 출력할 땐 다시 이스케이프한다 — DB의 값이 어디서 왔든 믿지 않는 게 원칙이기 때문이다(신뢰 경계). ‘입력은 sanitize, 출력은 escape’를 주문처럼 외우자.
escape는 ‘넣는 자리’에 맞춰
이스케이프 함수는 값을 어디에 넣느냐로 고른다. 맥락을 틀리면(속성 자리에 esc_html) 여전히 뚫린다.
| 넣는 자리 | 함수 |
|---|---|
| HTML 본문 | esc_html() |
| 태그 속성값 | esc_attr() |
| URL | esc_url() |
| 인라인 JS | esc_js() |
| 번역문 + 출력 | esc_html__() / esc_html_e() |
권한 검사도 잊지 말고
한 가지 더. nonce는 ‘위조 방지‘지 ‘권한‘이 아니다. nonce가 맞아도, 그 사용자가 그 작업을 할 자격이 있는지는 current_user_can(11편)으로 따로 확인해야 한다. nonce(진짜 우리 폼이 맞나) + capability(이 사람이 해도 되나) + sanitize/escape(값이 안전한가), 이 셋이 함께여야 방어가 완성된다.
이걸로 코어 엔진 모듈 끝. 훅으로 끼어들고, 쿼리로 뽑고, 템플릿으로 그리고, 자원을 싣고, 예약·캐시·보안까지 — 워드프레스가 “동작”하는 방식을 다 봤다. 다음 모듈은 이 엔진 위에 내 기능을 얹는 확장 — 커스텀 포스트 타입, 숏코드, REST API로 넘어간다.
자주 묻는 질문 (FAQ)
nonce·sanitize·escape는 각각 뭘 막나요?
nonce는 위조 요청(CSRF), sanitize는 잘못된 입력, escape는 출력 시 XSS를 막습니다. 입력은 sanitize, 출력은 escape가 원칙입니다.
escape는 언제 하나요?
값을 화면에 출력하는 바로 그 순간, 맥락에 맞는 함수(esc_html·esc_attr·esc_url)로 이스케이프합니다.

답글 남기기