티스토리 뷰

목차


     

    텅 빈 화면 대신 마주한 406 Not Acceptable 에러, 당황하지 말고 해결해 보세요!

    안녕하세요, 여러분! 웹 서핑을 하거나 열심히 개발한 서비스를 테스트하던 중, 갑자기 마주치는 406 Not Acceptable 에러 메시지에 당황했던 경험, 한 번쯤 있으실 겁니다. 마치 외국인에게 한국어로만 열심히 설명했는데, 상대방이 전혀 알아듣지 못하는 답답한 상황과 비슷하다고 할 수 있죠. 이 에러는 서버가 클라이언트(여러분 또는 여러분의 프로그램)가 요청한 형식으로 응답할 수 없을 때 발생합니다.

    "대체 이게 무슨 소리야?", "왜 나한테만 이런 일이?" 하며 좌절하셨다면, 이제 걱정 마세요! 오늘 이 시간에는 406 Not Acceptable 에러의 정체부터 주요 원인, 그리고 명쾌한 해결 방법까지 속 시원하게 파헤쳐 드리겠습니다. 이 글을 끝까지 읽으신다면, 더 이상 406 에러 앞에서 작아지지 않을 거예요!

    406 Not Acceptable 에러, 너는 누구냐? (개념 알기)

    406 Not Acceptable 에러는 HTTP 상태 코드 중 하나입니다. HTTP 상태 코드는 클라이언트가 서버에 요청을 보냈을 때, 그 요청이 성공적으로 처리되었는지, 아니면 어떤 문제가 발생했는지를 알려주는 일종의 약속된 신호입니다. 우리가 흔히 보는 404 Not Found (페이지를 찾을 수 없음) 에러와 비슷한 맥락이죠.

    여기서 "Not Acceptable"이라는 말 그대로, 서버가 클라이언트의 요청을 "수용할 수 없다"는 뜻입니다. 좀 더 구체적으로 말하면, 클라이언트는 HTTP 요청 시 Accept 헤더 라는 것을 통해 "나는 이런 형식(미디어 타입, MIME 타입)의 데이터만 받을 수 있어!"라고 서버에 미리 알려줍니다. 예를 들어, application/json (JSON 형식), application/xml (XML 형식), text/html (HTML 형식) 등이 대표적인 미디어 타입입니다.

    만약 서버가 클라이언트가 Accept 헤더에 명시한 형식으로 응답 데이터를 생성할 수 없거나, 해당 미디어 타입을 아예 지원하지 않는다면, 서버는 "미안하지만, 네가 원하는 형식으로는 줄 수가 없어"라는 의미로 406 에러를 반환하는 것입니다.

    406 에러, 도대체 왜 발생하는 걸까요?

    406 에러는 생각보다 다양한 원인으로 발생할 수 있습니다. 마치 감기의 원인이 바이러스, 면역력 저하 등 다양한 것처럼 말이죠. 주요 원인들을 하나씩 살펴보겠습니다.

    1. 클라이언트와 서버의 엇갈린 기대: Accept 헤더 불일치

    가장 흔한 원인입니다. 클라이언트가 서버에게 "나는 XML 형식으로 된 데이터만 원해! ( Accept: application/xml )"라고 요청했는데, 서버는 "미안하지만, 나는 JSON 형식( application/json )으로만 줄 수 있어."라고 하는 상황인 거죠. 이런 경우 서버는 406 에러를 보낼 수밖에 없습니다.

    • 핵심 : 클라이언트가 요청한 Accept 헤더의 미디어 타입과 서버가 제공할 수 있는 응답의 미디어 타입이 맞지 않을 때 발생합니다.

    2. 서버 내부의 복잡한 사정: 애플리케이션 로직 및 설정 오류

    때로는 서버 측 애플리케이션 자체에 문제가 있거나 설정이 잘못되어 406 에러가 발생하기도 합니다. 특히 웹 애플리케이션 개발 환경에서는 다음과 같은 경우를 의심해 볼 수 있습니다.

    자바 Spring Framework 개발자라면 주목하세요!
    • DTO(Data Transfer Object)에 Getter 메소드가 없을 때 : 서버가 클라이언트에게 데이터를 보내려면, 객체(DTO)에 담긴 정보를 특정 형식(주로 JSON이나 XML)으로 변환하는 직렬화(Serialization) 과정이 필요합니다. 이때 DTO 클래스의 필드 값을 읽어올 수 있는 getter 메소드가 없다면, Jackson 같은 라이브러리가 "데이터 포장 상자에 손잡이가 없어서 내용물을 꺼낼 수가 없네!"라며 직렬화에 실패하고 406 에러를 유발할 수 있습니다.
      • 해결책 : DTO 클래스에 Lombok의 @Getter 어노테이션을 사용하거나, 각 필드에 대한 public getter 메소드를 직접 만들어주세요.
      ```java // 예시: Lombok 사용 import lombok.Getter; import lombok.Setter;
    • @Getter @Setter // 필요에 따라 Setter도 추가 public class UserDto { private String username; private String email; // 생성자, 기타 메소드 등 } ```
    • jackson 라이브러리가 없거나 설정이 꼬였을 때 : jackson 은 자바 객체를 JSON으로, 또는 JSON을 자바 객체로 변환하는 데 핵심적인 역할을 하는 라이브러리입니다. Spring Boot는 기본적으로 jackson 을 포함하고 있지만, 만약 의존성이 누락되었거나, 다른 라이브러리와 버전 충돌이 있거나, 커스텀 설정에 오류가 있다면 "JSON 번역기가 고장났거나 아예 없어요!" 상태가 되어 406 에러가 발생할 수 있습니다.
      • 해결책 : 프로젝트의 pom.xml (Maven) 또는 build.gradle (Gradle) 파일에 jackson-databind 와 같은 관련 jackson 라이브러리 의존성이 올바르게 포함되어 있는지 확인하고, 필요하다면 추가하거나 버전을 조정해야 합니다.
    • HttpMessageConverter 설정이 잘못되었을 때 : Spring MVC는 HttpMessageConverter 를 사용하여 HTTP 요청 본문을 객체로 변환하거나, 객체를 HTTP 응답 본문으로 변환합니다. 클라이언트가 Accept 헤더를 통해 요청한 미디어 타입을 처리할 수 있는 HttpMessageConverter (예: JSON의 경우 MappingJackson2HttpMessageConverter , XML의 경우 Jaxb2RootElementHttpMessageConverter )가 Spring 설정에 제대로 등록되어 있지 않거나 구성이 잘못되었다면, "데이터 변환 전문가가 부재중입니다!" 상태가 되어 406 에러가 발생합니다.
      • 해결책 : WebMvcConfigurer 인터페이스를 구현하고 configureMessageConverters 또는 extendMessageConverters 메소드를 오버라이드하여 필요한 HttpMessageConverter 를 명시적으로 등록하고 설정할 수 있습니다. 대부분 Spring Boot가 알아서 잘 해주지만, 특별한 상황에서는 수동 설정이 필요할 수 있습니다.
    웹 크롤링 시에도 주의하세요!
    • User-Agent 헤더가 없거나 부적절할 때 : 많은 웹 서버는 무분별한 봇(bot)의 접근을 막기 위해 User-Agent 요청 헤더를 확인합니다. 웹 크롤러가 User-Agent 헤더를 보내지 않거나, 일반적이지 않은 값을 사용하면 서버는 "손님, 누구신지 먼저 밝혀주셔야 합니다!"라며 정상적인 요청이 아니라고 판단하여 406 에러나 다른 오류를 반환할 수 있습니다.
      • 해결책 : 웹 크롤링 라이브러리(예: Python의 requests )를 사용할 때, 실제 웹 브라우저의 User-Agent 문자열을 headers 옵션에 포함시켜 요청하세요.
    • 서버가 요구하는 특정 Accept 헤더를 지키지 않았을 때 : 일부 서버는 특정 Accept 헤더 값을 가진 요청에만 응답하도록 특별히 구성될 수 있습니다. 마치 "저희 식당은 특정 드레스 코드를 갖춘 손님만 받습니다!"와 같은 경우죠. 크롤러가 이러한 요구사항을 만족시키지 못하면 406 에러가 발생할 수 있습니다.

    3. 보이지 않는 벽: 서버 환경 및 보안 설정 문제

    때로는 서버 자체의 환경 설정이나 보안 시스템이 406 에러의 원인이 되기도 합니다.

    • 웹 서버(Nginx, Apache 등) 또는 WAS(Tomcat 등) 설정 : 서버 설정에서 특정 미디어 타입의 응답만 허용하도록 제한되어 있을 수 있습니다.
    • 웹 방화벽 (WAF, 예: ModSecurity) : 서버 보안을 위해 설치된 웹 방화벽의 특정 규칙이 클라이언트의 요청을 위협으로 간주하여 차단하고 406 에러를 반환할 수 있습니다. 이는 Accept 헤더 내용이나 다른 요청 파라미터와 관련될 수 있으며, 마치 "과도한 경호로 인해 정상적인 손님도 출입을 거부당하는" 상황과 비슷합니다.
      • 해결책 (서버 관리자) : ModSecurity와 같은 웹 방화벽 로그를 확인하여 차단 원인이 된 규칙을 파악하고, 해당 규칙을 조정하거나 예외 처리해야 합니다. 웹 호스팅 서비스를 이용하는 경우, 호스팅 업체에 문의하여 지원을 받아야 할 수 있습니다.
    • SSL/HTTPS 인증서 문제 : 매우 드물지만, SSL 인증서 구성 오류나 HTTP/HTTPS 프로토콜 불일치로 인해 406 에러가 발생하는 경우도 보고됩니다. 예를 들어, HTTPS로만 서비스되는 페이지에 HTTP로 접근하려고 하거나, 그 반대의 경우에 문제가 생길 수 있습니다.

    4. 혹시 내 컴퓨터가 문제? 클라이언트 측 설정 점검

    놀랍게도, 때로는 문제의 원인이 서버가 아닌 클라이언트 측에 있을 수도 있습니다.

    • 브라우저 확장 프로그램 : 일부 브라우저 확장 프로그램이 요청 헤더를 변경하거나 네트워크 요청에 영향을 미쳐 406 에러를 유발할 수 있습니다.
    • 프록시 서버 또는 VPN : 프록시 서버나 VPN을 사용하는 경우, 해당 서비스가 요청을 변경하거나 서버와의 통신에 문제를 일으켜 406 에러가 발생할 수 있습니다.
    • 잘못된 브라우저 설정 또는 오래된 캐시 : 오래된 캐시 데이터나 잘못된 브라우저 설정이 원인이 될 수도 있습니다.

    406 에러, 이제는 안녕! (해결 방법 및 디버깅 절차)

    자, 이제 406 에러의 다양한 원인들을 살펴봤으니, 이 답답한 에러로부터 탈출할 방법을 알아볼 차례입니다. 문제 해결의 열쇠는 체계적인 접근과 정확한 진단에 있습니다.

    1단계: 요청 헤더 점검 - Accept 헤더부터 살펴보자!

    가장 먼저 클라이언트가 서버로 보내는 Accept 헤더를 확인해야 합니다.

    • 브라우저 개발자 도구(F12) 활용 : 웹 브라우저에서 F12 키를 눌러 개발자 도구를 열고, '네트워크(Network)' 탭에서 해당 요청을 선택한 후 '헤더(Headers)' 섹션을 살펴보세요. 여기에 클라이언트가 보낸 Accept 헤더 값이 명시되어 있습니다.
    • 서버 API 문서 확인 : 서버가 어떤 미디어 타입을 지원하는지 API 문서를 통해 확인하거나, 이전에 성공했던 요청의 Accept 헤더를 참고하세요.
    • API 테스트 도구 활용 : Postman, Insomnia, curl과 같은 API 테스트 도구를 사용하여 다양한 Accept 헤더 값(예: application/json , application/xml , text/plain , 심지어 */* (모든 미디어 타입 허용))으로 요청을 보내보면서 서버의 반응을 테스트해 볼 수 있습니다.

    2단계: 서버 로그 확인 - 단서는 언제나 현장에 있다!

    클라이언트 측에서 특별한 문제를 찾지 못했다면, 이제 서버 측 로그를 살펴볼 차례입니다.

    • 웹 서버 로그, WAS 로그, 애플리케이션 로그 등을 자세히 확인하여 406 에러 발생 시점의 구체적인 오류 메시지나 스택 트레이스(stack trace)를 찾아보세요. 이는 문제의 근본적인 원인을 파악하는 데 매우 중요한 단서가 됩니다. "어떤 요청을 처리하다가, 어떤 부분에서 문제가 생겼는지"에 대한 정보가 담겨 있을 가능성이 높습니다.

    3단계: 서버 코드 및 설정 검토 (애플리케이션 개발자라면 필수!)

    서버 측 개발자라면, 애플리케이션 코드와 설정을 꼼꼼히 검토해야 합니다.

    • 앞서 언급된 Spring Framework 환경에서의 DTO Getter 부재, Jackson 라이브러리 문제, HttpMessageConverter 설정 등을 다시 한번 점검하세요.
    • 응답을 생성하는 컨트롤러 메소드의 반환 타입과 실제 반환되는 객체가 클라이언트가 요청한 Accept 헤더와 호환되는지 확인해야 합니다.

    4단계: 웹 크롤러 코드 수정 (크롤러 개발자라면!)

    웹 크롤링 중에 406 에러를 만났다면, 크롤러 코드를 수정해야 합니다.

    • User-Agent 헤더 를 실제 브라우저의 값으로 설정해 보세요.
    • 필요하다면, 대상 웹사이트가 요구하는 특정 Accept 헤더 값 을 명시적으로 포함시켜 요청을 보내세요.

    5단계: 클라이언트 환경 점검 - 내 PC부터 깨끗하게!

    의외의 복병일 수 있는 클라이언트 환경도 점검해 보세요.

    • 브라우저 캐시와 쿠키를 삭제 해 봅니다.
    • 시크릿 모드(Incognito mode) 또는 다른 브라우저 를 사용하여 접속해 보세요. 이를 통해 브라우저 확장 프로그램이나 특정 설정의 영향을 배제할 수 있습니다.
    • 설치된 브라우저 확장 프로그램을 일시적으로 모두 비활성화 하고 테스트해 보세요.
    • 프록시 서버나 VPN 사용을 잠시 중지 하고 접속해 보세요.

    6단계: 서버 환경 및 보안 설정 점검 (서버 관리자라면!)

    서버 관리자라면 서버 환경과 보안 설정을 확인해야 합니다.

    • 웹 서버(Nginx, Apache 등) 및 WAS(Tomcat 등) 설정 을 검토하여 특정 미디어 타입만 허용하도록 제한되어 있는지 확인합니다.
    • 웹 방화벽(WAF) 로그 를 확인하고, 406 에러를 유발하는 규칙이 있다면 해당 규칙을 조정하거나 예외 처리합니다. 잘 모르겠다면 호스팅 업체나 보안 솔루션 업체에 문의하는 것이 좋습니다.
    문제 유형 주요 점검 사항 담당자 역할
    Accept 헤더 불일치 클라이언트 요청 헤더, 서버 지원 미디어 타입 확인 클라이언트/서버 개발자
    Spring DTO Getter 부재 DTO 클래스 내 Getter 메소드 확인 서버 개발자
    Jackson 라이브러리 문제 의존성 확인, 버전 체크, 설정 오류 점검 서버 개발자
    HttpMessageConverter 설정 Spring MVC 설정, 컨버터 등록 여부 확인 서버 개발자
    웹 크롤링 헤더 문제 User-Agent , Accept 헤더 설정 점검 크롤러 개발자
    웹 방화벽(WAF) 차단 WAF 로그 확인, 규칙 조정 서버 관리자
    클라이언트 환경 문제 브라우저 캐시/확장 프로그램, 프록시/VPN 점검 사용자/클라이언트 개발자

    마치며: 406 에러, 이제 두렵지 않아요!

    406 Not Acceptable 에러는 처음 마주하면 당황스럽고 막막할 수 있습니다. 하지만 오늘 함께 살펴본 것처럼, 그 원인은 다양하며 체계적으로 접근하면 반드시 해결의 실마리를 찾을 수 있습니다.

    가장 중요한 것은 클라이언트가 무엇을 원하는지( Accept 헤더)와 서버가 무엇을 제공할 수 있는지 를 명확히 파악하는 것입니다. 마치 대화처럼, 서로가 이해할 수 있는 언어와 방식으로 소통해야 하는 것이죠.

    이제 여러분은 406 에러의 원인부터 해결 방법까지 든든한 지식을 갖추셨습니다. 다음에 이 에러 메시지를 다시 만나더라도 당황하지 말고, 오늘 배운 내용을 차근차근 적용해 보세요. 분명 시원하게 문제를 해결하고, 텅 빈 화면 대신 원하던 결과를 마주하게 될 것입니다.

    혹시 406 에러와 관련하여 더 궁금한 점이나 공유하고 싶은 경험이 있다면 언제든지 댓글로 남겨주세요! 여러분의 성공적인 문제 해결을 항상 응원합니다!