워드프레스 방식의 폼 데이터 처리 및 페이지 템플릿으로 간단하게 회원 탈퇴 만들기

워드프레스는 기본으로 회원 가입은 제공하지만, 탈퇴 기능은 제공하지 않습니다. 가입 회원의 의지로 탈퇴할 수 있는 편리 기능을 제공하지 않는다는 뜻이며, 기능이 완전히 제한되어 있다는 것은 아닙니다.

회원 삭제를 위한 기본 함수와 예시

워드프레스 wp_delete_user 함수는 사이트에 가입한 회원을 삭제하는 함수로 삭제 회원과, 삭제 회원이 작성한 포스트를 이전할 회원을 지정할 수 있습니다.

// $id - 삭제할 회원 아이디
// $reassign - 삭제할 회원의 포스트를 이전할 회원 아이디

wp_delete_user( $id, $reassign );

다음은 로그인 회원(가입 회원) 계정 삭제 코덱스 기본 예시입니다.

if ( is_user_logged_in() && ! empty( $_GET['DeleteMyAccount'] ) ) {
    add_action( 'init', 'remove_logged_in_user' );
}

function remove_logged_in_user() {
    // Verify that the user intended to take this action.
    if ( ! wp_verify_nonce( 'delete_account' ) ) {
        return;
    }

    require_once( ABSPATH.'wp-admin/includes/user.php' );
    $current_user = wp_get_current_user();
    wp_delete_user( $current_user->ID );
}

함수 wp_delete_user를 따로(사용자 정의 함수) 사용하려면 11번 줄의 user.php 파일 인클루드를 코덱스에서 안내하고 있습니다.

준비

간단한 예제로 경험하면서 구성하면 이해를 더할 수 있습니다. 따라서 몇 가지 미리 준비합니다.

임의 회원 추가

다음은 4명의 임의 회원을 사이트에 등록하는 것인데, functions.php 파일에 추가하고 저장한 후 사이트를 한 번 새로 고칩니다.

$userdata_user01 = array(
    'user_login' => 'user01',
    'user_email' => 'user01@localhost.com',
    'user_pass' => 1234,
    'role' => 'author'
);
$userdata_user02 = array(
    'user_login' => 'user02',
    'user_email' => 'user02@localhost.com',
    'user_pass' => 1234,
    'role' => 'author'
);
$userdata_user03 = array(
    'user_login' => 'user03',
    'user_email' => 'user03@localhost.com',
    'user_pass' => 1234,
    'role' => 'author'
);
// 탈퇴 회원의 포스트를 받을 회원
$userdata_user04 = array(
    'user_login' => 'user04',
    'user_email' => 'user04@localhost.com',
    'user_pass' => 1234,
    'role' => 'author'
);

wp_insert_user( $userdata_user01 );
wp_insert_user( $userdata_user02 );
wp_insert_user( $userdata_user03 );
wp_insert_user( $userdata_user04 );

다시 추가한 위의 코드를 지우고 파일을 저장합니다. 그리고 사이트에 관리자로 로그인 후 회원 목록에서 4명의 추가 회원을 확인하면 됩니다.

페이지 템플릿 파일

사용하는 테마에 page-templates 디렉터리가 있을 수도 있지만, 없다면 page-templates 디렉터리를 만들고 디렉터리 경로에 다음 코드를 포함한 resign.php 이름의 파일을 만듭니다.

<?php
/**
 * Template Name: 탈퇴
 */

그리고 다음 정보로 page 포스트를 만듭니다. 제목과 퍼머링크는 달라도 문제없습니다.

  • 제목 –  ‘탈퇴’
  • 퍼머링크 – resign
  • 페이지 템플릿 선택 – ‘탈퇴’ 선택
  • 저장 (공개)
  • 사이트 메뉴에 ‘탈퇴’ page 포스트 추가

브라우저에 도메인/resign 주소로 접근하면 되므로 사이트 메뉴 추가는 원하지 않는다면 생략해도 되며, 포스트에서는 메뉴로 안내합니다.

세션이 다른 브라우저 실행

관리자 로그인 브라우저 외에 일반 사용자 로그인을 위한 브라우저를 실행하여 user01 회원으로 로그인합니다. 포스트에서는 크롬 브라우저를 기준으로 안내하므로 크롬 브라우저의 ‘사용자 추가’ 기능을 이용하여 2개의 브라우저를 만드는 것이 좋습니다.

페이지 템플릿과 워드프레스 폼 데이터 처리로 회원 탈퇴 구성

탈퇴 페이지 템플릿을 구성하고, 폼 데이터를 기준으로 회원 계정을 삭제(탈퇴)합니다.

페이지 템플릿 구성

다음 코드를 resign.php 파일에 이어서 추가하고 저장합니다.

if ( !is_user_logged_in() ) {
    wp_redirect( esc_url( home_url( '/' ) ) );
    exit;
} else {
    $cuid = get_current_user_id(); // 로그인 회원 ID
}

get_header(); ?>

    <div id="primary" class="content-area">
        <main id="main" class="site-main" role="main">
            <header class="entry-header">
                <?php the_title( '<h1 class="entry-title">', '</h1>' ); ?>
            </header>

            <div class="entry-content">
                <form method="POST" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
                    <input type="hidden" name="action" value="remove_logged_in_user">
                    <?php wp_nonce_field( 'delete_account-' . $cuid, 'delete_user_nonce-' . $cuid ); ?>
                    <button type="submit" class="btn_resign">떠납니다</button>
                </form>
            </div>

        </main>
    </div>

<?php get_footer(); ?>

1번에서 6번 줄은, 로그인 전 이 파일에 접근하지 못하며, 로그인 후 접근 시 폼 데이터로 사용하기 위한 로그인 회원 ID를 구하는 것입니다.

17, 18, 19번 줄이 코드의 핵심으로 17번 줄 admin-post.php 폼 액션 URL과 18번 줄 필드 이름 action 및 값 remove_logged_in_user 이 워드프레스 방식의 폼 데이터 처리를 위한 기본 흐름입니다. 값이 액션 이름이 된다는 것만 기억하고, 예제를 통해 이해를 더하는 게 좋습니다.

19번 줄 nonce 필드는 탈퇴 페이지에 접근한 로그인 회원 ID 기준으로 nonce 액션 이름nonce 필드 이름을 지정한 것입니다. 이후 nonce 인증 함수 코드와 함께 확인하여 이해하면 됩니다. 지정하지 않으면 기본 이름을 사용하므로 염려할 필요는 없습니다.

탈퇴 기능을 위한 이 포스트의 페이지 템플릿 코드는 이것이 전부입니다. 반드시 페이지 템플릿으로 구성해야 하는 것은 아니며 템플릿 태그(함수)로 정의하거나 Shortcode 정의로 원하는 영역에 자유롭게 추가할 수도 있습니다.

폼 데이터 확인

일반 사용자 브라우저(현재, user01 회원으로 로그인)에서 사이트의 ‘탈퇴’ 메뉴를 클릭하여 탈퇴 페이지에 접근합니다. 그리고 F12 키를 눌러 크롬 브라우저의 ‘개발자 도구’를 미리 열어 둡니다.

이제 ‘떠납니다’ 버튼을 클릭합니다. 브라우저 주소는 도메인/wp-admin/admin-post.php로 나오며, 개발자 도구 창에서 다음 그림처럼 admin-post.php 파일에 전송된 폼 데이터를 확인할 수 있습니다.

탈퇴 폼에서 전송한 데이터
탈퇴 폼에서 전송한 데이터

워드프레스의 폼 데이터 처리 방식이라고 부르는 것은 admin-post.php 파일을 폼 액션 URL로 지정하여 폼 데이터를 받고, 폼 데이터 중 action 필드의 값을 사용자 액션 훅에 연결(지정)하여 원하는 결과를 얻는 방법을 말합니다.

액션과 함수 정의

이 포스트 처음에 wp_delete_user 함수 사용의 코덱스 기본 예시를 안내하였습니다. 그 코드를 바탕으로 다음처럼 폼 데이터 기준의 회원 계정을 삭제(탈퇴)할 수 있습니다. 다음 코드를 functions.php 파일에 추가하고 저장합니다.

add_action( 'admin_post_remove_logged_in_user', 'func_remove_logged_in_user' );
function func_remove_logged_in_user() {
    $current_user = wp_get_current_user();
    $user_id = $current_user->ID; // 현재 로그인 회원 ID
    
    $_wp_http_referer = $_REQUEST['_wp_http_referer'];  
    $_nonce = $_REQUEST[ 'delete_user_nonce-' . $user_id ]; // 폼 nonce
    if ( ! wp_verify_nonce( $_nonce, 'delete_account-' . $user_id ) ) {
        wp_die( '<span style="margin-bottom:1.5em;font-size: 1.5em; display: block">뭔가 이상합니다.</span><a href="' . esc_url( home_url( $_wp_http_referer ) ) .'">이전 페이지로</a>' );
    }

    require_once( ABSPATH . 'wp-admin/includes/user.php' ); 
    wp_delete_user( $current_user->ID );
    wp_redirect( esc_url( home_url( '/' ) ) );
    exit;
}

1번 줄 admin_post_remove_logged_in_user 액션 훅은 다음으로 구분할 수 있습니다.

admin_post_{$action} // admin_post_hook
action - remove_logged_in_user // 폼의 action 필드(파라미터) 값

admin_post_$action 액션과 함께 admin_post_nopriv_$action 액션이 존재하는데, 간단하게 로그인 전·후를 구분하여 폼의 액션 요청에 관하여 다르게 정의할 수 있다는 정도로 이해하면 됩니다.

회원 탈퇴는 로그인 후의 요청으로 보는 것이 상식이므로 이 포스트에서는 로그인 전 상태에 관한 것은 정의하지 않습니다.

폼 데이터 검증

위의 코드 7, 8번 줄 nonce 데이터 검증은 3, 4번에서 구한 현재 로그인 회원(탈퇴 요청 회원)의 ID 기준으로 정의한 것인데, 페이지 템플릿 파일에서도 $cuid 변수에 로그인 회원의 ID가 있으므로 회원 ID를 전송할 필드를 추가하여 폼 데이터로 전송 받을 수 있습니다.

그러나, 탈퇴 요청 로그인 회원 ID는 폼 데이터의 ID와 따로 구한 ID가 같아야 하므로 함수에서 따로 얻어 폼 데이터 검증을 강화하는 효과도 볼 수 있어 따로 정의한 것입니다.

회원 계정 삭제(탈퇴)

이제 일반 사용자 로그인 브라우저(user01 회원 로그인)에서 탈퇴 페이지에 다시 접근합니다. 그리고 ‘떠납니다’ 버튼을 클릭합니다. 사이트 홈 페이지로 이동하였고, 로그아웃 상태가 된다면 올바른 결과입니다.

관리자 로그인 브라우저에서 관리페이지 회원 목록 페이지를 새로 고쳐 user01 회원이 제거되었는지 확인하세요.

탈퇴 회원의 포스트를 다른 회원에게 이전

직전 과정으로 워드프레스 회원 탈퇴 기능은 완성되었습니다. 그런데, 워드프레스 관리페이지에서 관리자가 회원 계정을 삭제(탈퇴)하면 삭제할 회원이 작성한 포스트가 있을 때는 그 포스트를 누구에게 이전(소유)할 것인가 묻는 과정이 나옵니다.

그러나, 지금 이 포스트는 코드에서 처리하는 것이므로 wp_delete_user 함수에 이전할 회원의 ID를 추가하여 지정해야 합니다.

포스트 작성

로그인 이름 user01 회원은 삭제되었으므로, 일반 회원 브라우저에서 user02 회원으로 로그인한 후 포스트(타입 post) 하나를 작성합니다. 다음 정보를 참고하세요.

  • 제목 – user02 포스트
  • 상태 – Save Draft (임시 글로 저장, 공개로 저장해도 됩니다)
  • 관리자 로그인 브라우저에서 포스트(글) 목록 페이지를 확인하여 제목 ‘user02 포스트’ Author(글쓴이, 작성자) ‘user02’ 확인

코드 변경

functions.php 파일에 추가한 코드에서 다음 두 줄의 코드를 찾습니다.

require_once( ABSPATH . 'wp-admin/includes/user.php' ); 
wp_delete_user( $current_user->ID );

위의 두 줄을 다음으로 대체합니다.

$receive_user = get_user_by( 'login', 'user04' );
$receive_user_id = $receive_user->ID;
require_once( ABSPATH . 'wp-admin/includes/user.php' ); 
wp_delete_user( $current_user->ID, $receive_user_id );

1, 2번 줄은 회원의 로그인 이름(user04)으로 ID를 구하는 것이며, 4번 줄 wp_delete_user 함수 $receive_user_id 두 번째 파라미터에 user04 회원의 ID를 추가한 것입니다.

탈퇴 및 포스트 이전

일반 회원 user02 브라우저에서 사이트로 접근한 후 탈퇴 메뉴를 클릭합니다. 그리고 ‘떠납니다’ 버튼을 클릭하세요.

로그아웃 상태를 확인한 후 관리자 브라우저에서 회원 목록의 user02 제거, 그리고 포스트 목록에서 제목 ‘user02 포스트’ Author ‘user04‘ 변경을 확인하세요.

이전할 포스트가 없다면 이전하지 않으므로 현재까지의 코드는 지속해도 문제가 없습니다.

탈퇴 전에 추가할 작업 정의

이 포스트에서 사용하는 wp_delete_user 함수는 delete_user 훅을 호출하는데, 이 훅은 탈퇴(삭제) 회원 및 관련 데이터를 데이터베이스에서 삭제하기 전에 특정 작업을 수행합니다. 직전에 코드를 추가하여 확인한 ‘특정 사용자에게 포스트 이전’도 그중 하나라고 볼 수 있습니다. ID가 없다면 포스트 이전 등 탈퇴 회원의 정보(데이터)를 구할 수 없기에 당연한 것으로 생각할 수 있습니다.

따라서, wp_delete_user 함수에 포스트를 이전할 회원 ID를 정의하지 않고, 훅을 사용하여 따로 정의해도 된다는 것으로도 생각할 수 있습니다. 그러나 번거로우므로 포스트 이전은 함수에서 처리하는 것이 간편합니다.

회원 탈퇴 전에 회원 ID를 기준으로 여러 작업이 필요할 수 있습니다. 탈퇴 안내 메일 발송, 탈퇴 기록을 특정 필드에 남기기 등. 이 포스트에서는 탈퇴 회원에게 탈퇴 확인 메일을 보내는 것만 코덱스 예시를 그대로 사용하여 정의합니다.

다음 코드를 functions.php 파일에 추가하고 저장합니다.

add_action( 'delete_user', 'func_before_delete_user' );
function func_before_delete_user( $user_id ) {
    $user_obj = get_userdata( $user_id ); // 탈퇴 회원 데이터
    $email = $user_obj->user_email; // 탈퇴 회원 이메일

    $headers = 'From: ' . get_bloginfo( "name" ) . ' <' . get_bloginfo( "admin_email" ) . '>' . "\r\n";
    wp_mail( $email, '계정 삭제 확인', get_bloginfo( "name" ) . '에서 계정이 삭제되었습니다.', $headers );
}

일반 회원 브라우저에서 user03 회원으로 로그인한 후 관리페이지 프로필 메뉴를 클릭하여 실제 존재하는, 결과를 확인할 수 있는 이메일 주소를 입력하고 저장합니다.

사이트에서 탈퇴 메뉴를 클릭하고, ‘떠납니다’ 버튼을 클릭하세요. 로그아웃 상태로 변경되는지 확인하고, ‘계정 삭제 확인’ 제목의 메일이 왔는지 확인하면 됩니다. 각자의 테스트 환경에 따라 메일 수신이 되지 않을 수 있으므로 나중에 제대로 확인하면 됩니다.

끝으로, 관리자 브라우저의 관리페이지에서 user04 회원을 삭제합니다. 이 회원 소유의 포스트(임시 포스트)가 존재하므로 포스트 처리에 관하여 묻는 옵션이 나오면 모두 삭제하는 옵션을 선택하여 삭제합니다.

정리

이 포스트의 워드프레스 계정 삭제(탈퇴)는 관련 함수보다 함수를 실행하기 위한 폼 구성과 삭제 전·후의 과정 정의에 초점을 두고 있습니다. 이 포스트의 페이지 템플릿 및 폼 데이터 처리 방식이 아니라 admin-ajax.php, WP REST API 등 다른 기준과 방법이 존재하므로 사이트 운용 기준에 적합한 방법을 찾는 것이 필요합니다.

또, 실제 사이트에 적용할 때는 가능성을 확장하여 반복 확인과 검증을 거쳐야 합니다.