워드프레스 REST API로 글을 발행하려면 인증이 필요합니다. 애플리케이션 비밀번호를 발급해 Basic 인증으로 보내면 되는데, 분명히 맞는 비밀번호인데도 401만 돌아오는 경우가 있습니다. 이 글은 그 401의 진짜 원인을 찾는 과정을 정리한 기록입니다. 결론부터 말하면 비밀번호가 틀린 게 아니었습니다.
증상: 읽기는 되는데 쓰기만 401
공개 글 목록을 읽는 요청은 잘 됩니다. 인증이 필요 없으니까요. 문제는 인증이 필요한 요청입니다.
GET /wp-json/wp/v2/posts → 200 (인증 불필요)
GET /wp-json/wp/v2/users/me → 401 rest_not_logged_in
POST /wp-json/wp/v2/posts → 401
응답 코드는 rest_not_logged_in, 메시지는 현재 로그인 상태가 아닙니다였습니다. 애플리케이션 비밀번호 기능이 켜져 있는지, 사용자명이 맞는지, 비밀번호에 공백이 섞였는지를 몇 번이나 확인했지만 그대로였습니다.
핵심 진단: 일부러 틀린 비밀번호를 보내본다
여기서 결정적인 단서를 얻었습니다. 같은 사용자명에 아무렇게나 만든 틀린 비밀번호를 넣어 봤더니, 결과가 완전히 똑같은 rest_not_logged_in이었습니다.
맞는 비밀번호 → 401 rest_not_logged_in
틀린 비밀번호 → 401 rest_not_logged_in ← 똑같다
이게 왜 중요하냐면, 비밀번호가 틀렸다면 incorrect_password 같은 다른 코드가 나와야 정상입니다. 맞든 틀리든 결과가 같다는 건 워드프레스가 비밀번호를 비교조차 하지 못하고 있다는 뜻입니다. 인증 정보가 아예 워드프레스에 도착하지 않은 겁니다. 이 한 번의 대조 실험이 문제의 방향을 통째로 바꿔놓았습니다. 비밀번호를 의심하던 것에서, 인증 헤더의 전달 경로를 의심하는 쪽으로요.
진짜 원인: Authorization 헤더가 중간에 사라진다
원인은 서버가 Authorization 헤더를 PHP로 넘기지 않는 것이었습니다. 이건 비밀번호 문제도 워드프레스 문제도 아니고, 웹서버 구성 문제입니다. PHP를 CGI나 FastCGI로 구동할 때 흔히 생깁니다. Basic 인증 헤더가 CGI 규격상 자동으로 전달되지 않아서, 서버 설정에 명시적으로 넘겨주는 규칙을 넣어야 합니다.
웹서버 종류에 따라 설정이 다릅니다.
# Apache (.htaccess, 루트에)
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# nginx (PHP location 블록)
fastcgi_param HTTP_AUTHORIZATION $http_authorization;
여기서도 함정이 있었습니다. 서버가 nginx인데 Apache용 .htaccess 규칙을 넣으면 아무 효과가 없습니다. nginx는 .htaccess를 아예 읽지 않기 때문입니다. 그래서 헤더가 어디서 사라지는지 실제로 확인하는 단계가 필요했습니다.
헤더가 어디서 잘리는지 좁히기
리버스 프록시나 CDN을 앞에 두면 사라지는 지점이 더 늘어납니다. 프록시가 헤더를 떨어뜨릴 수도, 웹서버가 PHP로 안 넘길 수도 있습니다. 저는 헤더가 어디까지 도달하는지 찍어보는 작은 PHP 파일을 임시로 올려서, 두 지점에서 각각 호출해 비교했습니다.
서버 안에서 직접 호출 → 헤더 도착 여부 확인
외부(프록시 경유) 호출 → 헤더 도착 여부 확인
둘 다 도착 O → 웹서버/PHP 설정 문제
안쪽 O 바깥 X → 프록시/CDN 구간 문제
둘 다 도착 X → PHP 처리 단계에서 유실
이렇게 하면 고쳐야 할 지점이 한 곳으로 좁혀집니다. 참고로 이 진단 파일은 비밀번호 값 자체를 출력하지 않고, 헤더가 도착했는지 여부만 확인하도록 만들었습니다. 그리고 확인이 끝나면 반드시 삭제해야 합니다. 서버 정보를 드러내는 파일을 공개 경로에 두면 안 됩니다.
정리: 401을 만나면 순서대로
애플리케이션 비밀번호 인증이 401로 막힐 때는 이 순서로 좁혀가면 원인이 빨리 드러납니다. 첫째, 틀린 비밀번호로도 같은 응답이 나오는지 본다. 같다면 비밀번호가 아니라 헤더 전달 문제다. 둘째, 서버가 Apache인지 nginx인지 확인하고 그에 맞는 헤더 전달 규칙을 넣는다. 셋째, 프록시나 CDN이 앞에 있다면 헤더 유실 지점을 실제로 찍어서 좁힌다.
성공 응답이 곧 정상 동작을 뜻하지 않듯, 실패 응답도 표면 메시지가 원인을 정확히 가리키지는 않습니다. rest_not_logged_in이라는 메시지는 로그인 정보가 틀렸다고 말하는 것 같지만, 실제로는 로그인 정보가 도착조차 하지 않았다는 뜻이었습니다. 대조 실험 하나가 이 차이를 갈라줍니다.
'자동화·AI 실무' 카테고리의 다른 글
| 워드프레스 REST 예약 발행이 9시간 밀리는 이유 (타임존 함정) (0) | 2026.09.06 |
|---|---|
| 티스토리 Open API 종료 후 자동 발행 구축기 (CDP 브라우저 자동화) (0) | 2026.09.04 |
| 구독자 3천 명 채널이 4,295만 조회수를 만든 방법 (0) | 2026.06.28 |
| 유튜브 쇼츠 자동화 방법: 하루 1개 이상 자동으로 업로드하는 시스템 만들기 (1) | 2025.04.14 |
| ImageFX 이미지 상업적 이용 가능할까? 저작권, 라이선스, 그리고 실제 활용 팁까지! (2) | 2025.04.12 |