By |

WordPress "업로드 권한이 없습니다" 오류: 해결 방법

요약: 이 오류는 요청을 보내는 iPhone 앱, 브라우저, 스크립트가 아니라 WordPress 서버에서 발생합니다. 가장 흔한 두 가지 원인은 다음과 같습니다: (1) Application Password에 연결된 사용자에게 upload_files 권한이 없는 경우, 또는 (2) 보안 플러그인 / WAF가 WordPress가 요청을 평가하기 전에 /wp-json/wp/v2/media를 차단하는 경우. 해당 사용자를 작성자(Author)(또는 upload_files를 포함하는 모든 역할)로 승격하거나 미디어 엔드포인트를 문제의 방화벽 규칙에서 면제하면 즉시 업로드가 작동합니다.

2026년 6월 2일 WordPress 6.7에서 검증되었습니다.

빠른 진단: 응답이 알려주는 것

아무것도 변경하기 전에 클라이언트가 받는 HTTP 응답을 살펴보십시오. 상태 코드와 오류 본문의 조합마다 근본 원인이 다릅니다.

HTTP 상태 오류 코드 유력한 원인 첫 단계
403 rest_cannot_create 사용자 역할에 upload_files가 없음 역할을 작성자(Author) 이상으로 변경 (근본 원인 1 참조)
401 rest_invalid_authentication Application Password가 잘못되었거나 폐기됨 Application Password 재생성 (근본 원인 4 참조)
403 HTML 페이지, JSON 없음 보안 플러그인 또는 WAF가 요청을 차단 Wordfence / iThemes / Cloudflare 이벤트 로그 확인
503 / 타임아웃 (본문 없음) WAF 또는 속도 제한기가 연결을 끊음 Cloudflare 또는 오리진 방화벽 로그 확인
200 HTML 페이지, JSON 아님 플러그인이 WP REST API를 비활성화 "Disable REST API" 또는 동등한 플러그인 비활성화

오류가 실제로 클라이언트에 도달하는 과정

클라이언트가 WordPress에 사진을 업로드할 때 /wp-json/wp/v2/media로 POST 요청을 보냅니다. 이 요청은 Authorization 헤더에 사용자 이름과 Application Password를 담아 전송합니다 — Application Password는 사용자 -> 프로필 -> Application Passwords에서 생성하는 토큰이며, WordPress 5.6부터 코어 기능으로 제공됩니다 (공식 통합 가이드).

그러면 WordPress 코어는 파일을 받아들이기 전에 권한 검사를 실행합니다. WP_REST_Attachments_Controller::create_item_permissions_check()의 관련 로직은 다음과 같습니다:

if ( ! current_user_can( 'upload_files' ) ) {
    return new WP_Error(
        'rest_cannot_create',
        __( 'Sorry, you are not allowed to upload media on this site.' ),
        array( 'status' => rest_authorization_required_code() )
    );
}

Application Password에 연결된 사용자에게 upload_files 권한이 없으면 WordPress는 HTTP 403과 함께 "code": "rest_cannot_create"를 포함한 JSON 본문을 반환합니다. 클라이언트가 이 응답을 받아 "업로드 권한이 없습니다"로 표시합니다.

즉, 이 메시지는 문자 그대로의 의미입니다. WordPress가 해당 사용자에게 업로드가 허용되지 않는다고 알려주고 있는 것입니다. 다음 단계는 그런지 파악하는 것입니다. 역할별 권한의 전체 목록은 공식 WordPress Roles and Capabilities 페이지에 정리되어 있습니다.

근본 원인 1: 사용자 역할에 upload_files가 없음

SnapPress 지원 사례에서 가장 자주 관찰되는 원인입니다. WordPress에는 다섯 개의 기본 역할이 있으며, 그중 일부만이 미디어를 업로드할 수 있습니다:

역할 미디어 업로드 가능?
Administrator
Editor
Author
Contributor아니오
Subscriber아니오

Application Password가 기여자(Contributor) 또는 구독자(Subscriber)에게 속해 있다면, 인증 자체는 성공해도(비밀번호 자체는 유효하므로) 모든 업로드 시도는 권한 오류로 실패합니다. 다만 접근 권한이 부족할 뿐입니다.

역할 확인 방법

  1. https://your-site.example/wp-admin/에서 WordPress 관리자에 로그인합니다.
  2. 사용자 -> 모든 사용자를 엽니다.
  3. 클라이언트 앱에 등록한 Application Password의 소유 사용자를 찾습니다.
  4. 역할(Role) 열을 확인합니다.

역할이 기여자(Contributor), 구독자(Subscriber)이거나, upload_files를 포함하지 않는 커스텀 역할이라면 그것이 문제입니다.

해결 방법 (최소 권한 우선)

가장 안전한 해결책은 사용자를 작성자(Author)로 승격하는 것입니다. 작성자는 upload_files를 포함하는 최소 기본 역할이며, 자신의 글을 작성하고 발행할 수도 있습니다. 다른 사용자, 플러그인, 설정을 관리할 수는 없으므로 업로드 워크플로만 필요한 경우 권장되는 선택입니다.

다른 작성자의 글을 편집하고 발행할 필요도 있다면 편집자(Editor)로 승격하고, 사용자가 실제로 전체 사이트 제어가 필요한 경우(예: 직접 관리하는 단독 소유 사이트)에만 관리자(Administrator)로 승격하십시오. 역할 변경 후에는 올바른 사용자 아래에서 새로운 Application Password를 생성하고 클라이언트 앱을 업데이트하십시오. 새 비밀번호 생성은 권장되지만 엄격히 필수는 아닙니다. "오래된 자격 증명" 가설을 제거해 줍니다.

역할이 커스텀일 때는?

사이트가 MembersUser Role Editor 같은 역할 플러그인을 사용한다면 명명된 역할이 기본값과 일치하지 않을 수 있습니다. 역할 편집기를 열고 사용자에게 할당된 역할을 찾아 upload_files 체크박스가 활성화되어 있는지 확인하십시오. 저장한 후 다시 시도하십시오. 대부분의 권한 회귀(regression)도 커스텀 역할에 숨어 있습니다. 한때 업로드가 작동했다가 플러그인 업데이트 후 조용히 작동을 멈췄다면 여기서 시작하십시오. 다중 사용자 사이트에서는 upload_files와 실제로 필요한 최소한의 게시 권한만 가진 전용 커스텀 역할이 가장 깔끔한 방법입니다.

근본 원인 2: 보안 플러그인이 REST API를 차단함

사용자 역할에 이미 upload_files가 포함되어 있는데도 업로드가 실패한다면, 다음으로 의심해야 할 것은 WordPress 코어가 REST API 요청을 보기 전에 가로채는 보안 플러그인입니다. 흔한 가해자:

  • Wordfence — 방화벽 규칙이 비정상적인 Authorization 헤더와 일치할 수 있고, Rate Limiting이 REST 트래픽을 제한할 수 있습니다.
  • iThemes Security / Solid Security — REST API 강화 옵션이 로그인된 브라우저 세션 외의 /wp-json/wp/v2/* 접근을 차단할 수 있습니다.
  • Disable REST API — 이름 그대로 모든 REST 엔드포인트를 기본적으로 차단하는 플러그인입니다. 앱 업로드가 작동하려면 /wp/v2/media를 화이트리스트에 추가해야 합니다.
  • SecuPress, Shield Security 및 유사 플러그인도 동등한 설정을 가지고 있습니다.

이러한 플러그인 중 하나가 요청을 차단할 때, 플러그인이 WordPress 자체 오류와 유사한 403을 반환하므로 클라이언트에는 동일한 "업로드 권한 없음" 증상이 나타납니다. 차이점은 코어의 current_user_can() 검사가 결코 실행되지 않는다는 것입니다.

Wordfence 관련 세부 사항

확인할 가치가 있는 두 가지 설정이 있습니다. Wordfence -> All Options -> Firewall Options를 여십시오:

  • Brute Force Protection: 공격적인 잠금 설정은 단 한 번의 재시도 후 Application Password를 차단할 수 있습니다.
  • Rate Limiting: "누군가의 요청이 ...를 초과하는 경우" 임계값은 REST 트래픽에도 적용됩니다. 실패한 업로드를 재시도하는 모바일 앱이 이를 발동시킬 수 있습니다.

Wordfence가 의심된다면 Wordfence -> Tools -> Live Traffic을 열고 클라이언트에서 업로드를 시도하십시오. 요청이 차단되면 발동한 규칙과 함께 사유가 로그 항목에 표시됩니다. 전체 방화벽 참조는 wordfence.com/help/firewall/에서 확인할 수 있습니다.

iThemes Security / Solid Security 관련 세부 사항

Solid Security는 릴리스 간에 REST API 강화 설정의 위치를 옮겨왔습니다. 최근 버전에서는 Security -> Settings -> Advanced -> WordPress Tweaks에서 REST API 옵션을 찾으십시오(이전 빌드에서는 Tools 아래에 있었습니다). 중요한 두 가지 상태는:

  1. Default (REST API enabled) — 앱 업로드에 필요한 상태입니다.
  2. Restricted — REST 엔드포인트를 로그인된 브라우저 세션으로 제한합니다. 여기서 Application Password 요청이 실패할 수 있습니다.

가능하면 Default로 전환하거나 /wp/v2/media를 명시적으로 화이트리스트에 추가하십시오. 정확한 레이블은 버전에 따라 다를 수 있으니, 사용 중인 릴리스에 대한 Solid Security 문서를 참고하십시오.

진단 방법

의심되는 플러그인을 한 번에 하나씩 비활성화하고 그 사이에 업로드를 재시도하십시오. 비활성화했을 때 업로드가 성공하는 플러그인이 범인입니다. 식별되면 REST API를 차단하는 특정 설정을 찾아 /wp-json/wp/v2/media를 면제하십시오. 위 목록의 모든 플러그인은 어떤 형태로든 엔드포인트별 면제를 지원하지만, 메뉴 경로는 버전에 따라 다릅니다.

근본 원인 3: WAF가 요청을 차단함

사이트가 웹 애플리케이션 방화벽(Cloudflare WAF, Sucuri, AWS WAF, BunkerWeb) 뒤에 있다면, WAF가 WordPress 서버에 도달하기 전에 업로드 요청을 거부할 수 있습니다. 특히 Cloudflare에는 대용량 multipart POST 본문과 비정상적인 Content-Type 조합을 대상으로 하는 WAF 관리 규칙이 있는데, 이 둘 모두 미디어 업로드가 사용합니다. 규칙 카탈로그는 Cloudflare WAF 문서를 참조하십시오.

증상은 다양하지만 일반적으로 다음 중 하나입니다:

  • 응답 본문에 Cloudflare 오류 페이지가 포함된 HTTP 403.
  • HTTP 503 또는 타임아웃, 오류 본문이 전혀 없음.
  • JSON 대신 HTML 응답이 포함된 HTTP 200.

Cloudflare 한정 좁은 해결책

Cloudflare의 관리 규칙을 전면적으로 비활성화하지 마십시오. 대신 발동된 특정 규칙을 식별하십시오:

  1. Cloudflare 대시보드를 열고 Security -> Events(이전의 Firewall Events)로 이동합니다.
  2. 클라이언트에서 실패하는 업로드를 시도합니다.
  3. 호스트 또는 URI /wp-json/wp/v2/media로 이벤트를 필터링하십시오. 차단 규칙이 ruleset ID와 rule ID와 함께 나타납니다.
  4. Security -> WAF -> Custom Rules에서 업로드 엔드포인트에 대해서만 식별된 특정 관리 규칙을 건너뛰는 커스텀 규칙을 생성하십시오:
(http.request.uri.path eq "/wp-json/wp/v2/media") and (http.request.method eq "POST")

규칙 동작을 모든 관리 챌린지가 아니라 식별한 특정 ruleset / rule을 대상으로 한 "Skip"으로 설정하십시오. 이 규칙을 모든 "Block" 규칙보다 우선순위에서 위에 두십시오. 이렇게 하면 /wp-json/의 나머지에 대한 보호는 유지하면서 합법적인 미디어 업로드는 통과시킬 수 있습니다.

근본 원인 4: 인증 실패 또는 폐기된 Application Password

Application Password에는 기본 만료가 없습니다. 일단 발급되면 수동으로 폐기될 때까지 유효합니다. 따라서 여기서의 증상은 보통 403 권한 오류가 아니라 rest_invalid_authentication이 포함된 HTTP 401입니다. 다만 다른 어떤 것도 들어맞지 않을 때 확인해 볼 가치는 있습니다:

  1. WordPress 관리자 -> 사용자 -> 프로필 -> Application Passwords를 엽니다.
  2. 클라이언트 앱에 등록한 비밀번호가 여전히 목록에 있는지 확인합니다.
  3. 제거되었다면(수동으로, 보안 플러그인에 의해, 또는 비밀번호 변경 이벤트로 인해) 새로 생성하고 클라이언트를 업데이트합니다.
  4. 사이트가 HTTPS로 접근 가능한지 확인합니다. WordPress는 보안상 일반 HTTP에서 Authorization 헤더를 제거하므로, http-to-https 불일치가 간헐적인 401을 일으킬 수 있습니다.
  5. 보안 플러그인이나 커스텀 코드가 wp_is_application_passwords_available 필터를 통해 Application Passwords를 비활성화하지 않았는지 확인합니다.

일부 보안 플러그인은 특정 이벤트(비밀번호 변경, 역할 변경, 의심스러운 활동) 시 Application Passwords를 자동으로 폐기합니다. 최근에 역할이 변경되었다면 그것만으로도 기존 비밀번호가 폐기되었을 수 있습니다. 재생성은 1분이면 끝나는 해결책입니다.

커맨드 라인에서 수정 확인하기

수정을 적용한 후에는 클라이언트 앱을 전혀 거치지 않고도 업로드가 작동하는지 확인할 수 있습니다. curl이 있는 모든 머신에서 다음을 실행하십시오:

curl -u 'your-username:your-application-password' \
  -X POST \
  -H 'Content-Disposition: attachment; filename=test.jpg' \
  -H 'Content-Type: image/jpeg' \
  --data-binary @test.jpg \
  https://your-site.example/wp-json/wp/v2/media

성공적인 업로드는 HTTP 201과 새 미디어 항목의 id, source_url, media_details를 포함하는 JSON 본문을 반환합니다. 그 외의 응답은 이 글 상단의 진단 표로 다시 이어지며, 보통 응답 본문이 어느 행에 해당하는지 알려줍니다.

curl을 실행할 수 없다면 동일한 테스트를 Postman이나 Basic 인증과 multipart form data를 지원하는 모든 HTTP 클라이언트에서 수행할 수 있습니다. 엔드포인트, 자격 증명, 예상 응답은 동일합니다.

모바일 앱이 이 문제를 해결해 줄 수 없는 이유

업로드 버그가 앱에 있을 것이라고 추정하기 쉽습니다. 앱이 사슬에서 눈에 보이는 부분이기 때문입니다. 하지만 WordPress REST API는 어떤 클라이언트(브라우저, iOS 앱, Zapier, 커맨드 라인)에게 무엇이 허용되는지를 결정하는 최종 게이트키퍼입니다. 앱의 역할은 유효한 자격 증명으로 잘 구성된 요청을 보내고 응답을 표시하는 것입니다. WordPress가 "업로드 권한 없음"이라고 말한다면, 앱을 바꿔도 답은 바뀌지 않습니다. 수정은 WordPress 측에서 이루어져야 합니다: 역할, 플러그인 설정, WAF 규칙 또는 Application Password.

이는 의도된 설계이며 REST API 모델의 강점입니다. 누군가가 휴대폰 앱, 데스크톱 클라이언트를 사용하든, 커스텀 스크립트를 작성하든 동일한 검사가 사이트를 보호합니다.

요약 체크리스트

  1. 실제 응답에서 HTTP 상태 코드와 오류 코드를 읽으십시오. 상단의 진단 표와 매칭하십시오.
  2. WordPress 사용자 역할을 확인하십시오. upload_files가 포함되어야 합니다(기본 역할 중에서는 작성자(Author) 이상).
  3. 역할이 올바르다면 보안 플러그인을 한 번에 하나씩 비활성화하고 업로드를 재시도하십시오.
  4. 플러그인이 원인이 아니라면 WAF 이벤트 로그를 확인하고, 발동된 특정 규칙에 대해서만 /wp-json/wp/v2/media에 좁은 규칙 예외를 추가하십시오.
  5. Application Password가 여전히 사용자 프로필에 나열되어 있는지, 사이트가 HTTPS인지 확인하십시오. 필요하면 재생성하십시오.
  6. 클라이언트 앱으로 돌아가기 전에 curl로 종단 간 검증하십시오.

이 순서를 따르면 SnapPress 사용자에게서 보고되는 "업로드 권한 없음" 사례의 대부분이 해결됩니다. 오류 메시지는 자기 역할을 다하고 있을 뿐, 행동할 올바른 맥락이 필요할 뿐입니다.

자주 묻는 질문

WordPress가 왜 내 iPhone 앱에 '업로드 권한이 없습니다'를 반환합니까?
REST API 엔드포인트 /wp-json/wp/v2/media는 WordPress 사용자가 upload_files 권한을 보유하도록 요구합니다. 구독자(Subscriber)와 기여자(Contributor) 역할에는 이 권한이 없습니다. iPhone 앱이 이러한 역할의 사용자로 인증하면 모든 업로드 시도는 HTTP 403과 함께 rest_cannot_create 오류 코드를 반환합니다. 해당 사용자를 작성자(Author)(또는 upload_files를 포함하는 모든 역할)로 승격하면 해결됩니다.
저는 사이트 관리자인데 여전히 '업로드 권한 없음' 오류가 나옵니다. 무엇이 문제입니까?
사용자 역할이 올바르다면 다음으로 가능성이 높은 원인은 REST API를 차단하는 보안 플러그인 또는 WAF 규칙입니다. Wordfence, iThemes Security, Solid Security, "Disable REST API" 플러그인은 모두 브라우저가 아닌 REST 트래픽을 거부할 수 있는 설정이 있습니다. /wp-json/을 대상으로 하는 Cloudflare WAF 규칙도 같은 효과를 냅니다. 방화벽 이벤트 로그로 차단 중인 특정 규칙을 찾은 다음, /wp-json/wp/v2/media에 대해서만 해당 규칙을 면제하십시오.
WordPress Application Password는 소속 사용자와 동일한 역할을 부여합니까?
네. Application Password는 사용자별로 발급되며, 이를 사용해 인증된 모든 요청은 해당 사용자의 정확한 권한으로 실행됩니다. 기본 사용자가 구독자(Subscriber)라면 Application Password가 성공적으로 생성되었더라도 업로드할 수 없습니다. Application Password에는 기본 만료 기간이 없으며, 수동으로 폐기될 때까지 유효합니다.
터미널에서 upload_files 권한을 어떻게 확인합니까?
curl을 -u username:application-password 옵션과 함께 실행하여 작은 테스트 이미지를 /wp-json/wp/v2/media로 POST하십시오. HTTP 201과 새 미디어 ID가 포함된 JSON 본문이 반환되면 업로드가 작동합니다. HTTP 403과 코드 rest_cannot_create는 역할에 upload_files가 없음을 의미합니다. HTTP 401과 rest_invalid_authentication은 Application Password가 잘못되었거나 폐기되었음을 의미합니다. WordPress 응답이 아닌 본문(HTML 오류 페이지, Cloudflare 챌린지)에서 HTTP 403이 반환된다면 WordPress가 요청을 받기 전에 상위 필터가 차단하고 있다는 뜻입니다.
그냥 사용자를 관리자(Administrator)로 승격하면 되지 않습니까?
최후의 수단으로만, 그리고 전적으로 통제 가능한 사이트에서만 그렇게 하십시오. 최소 권한 원칙에 따르면 upload_files를 부여하는 가장 작은 역할을 주어야 하며, 그것이 작성자(Author)입니다. 관리자(Administrator)는 실제로 설정, 플러그인 또는 다른 사용자를 관리해야 하는 계정에만 부여하십시오. 공유 사이트에서는 upload_files와 최소한의 게시 권한만 가진 전용 커스텀 역할이 더 안전합니다.