728x90
개요
CDN에서 이미지를 가져오는 리액트를 활용한 어드민을 코파일럿과 함께 개발중이였다.
그떄, 이미지에 대한 픽셀, 사이즈를 가져오는 요구사항이 있었고, 해당 이미지의 size을 가져오기 위해 HEAD 헤더 메소드를 통해 가져오는 것을 추천하였다.
근데 0으로 가져오는 이슈가 있었다.
아래 내용을 통해 자세히 알아보자
왜 HEAD에는 사이즈가 없고, Range GET에는 있나?
CDN의 정책
- 대부분 CDN/오브젝트 스토리지는 HEAD 요청에서
Content-Length
를 생략하거나0
으로 넣는다. (압축/청크 전송, 헤더 정규화, 오리진에 HEAD를 안 넘기는 정책 등) - 반면 Range GET(206) 은 설계상
Content-Range: bytes start-end/total
를 꼭 내보내므로 총 크기(total) 를 노출하기 쉽다. CDN이 객체 메타데이터로 총 크기를 알고 있어서 안정적으로 넣을 수 있다.
결론은 Range에서는 사이즈가 보이고, HEAD에서는 없을 수 있기 때문에, Range Get으로 사이즈를 파싱하는 것이 실무에서 더 안정적이다.
일부 스토어는 커스텀 헤더(
x-object-size
) 로 총 크기를 주기도 하는데, 이것도 CDN/오리진 쪽 정책
그렇다면, HEAD와 RANGE는 정확히 뭘까?
HEAD 메서드란?
- GET과 동일한 헤더를 보내되 본문(body)은 없다. 링크 체크, 메타데이터 조회(길이, ETag, 최종 수정일 등)에 쓰라고 정의.
- 서버가
Content-Length
를 보낼 수는 있지만 반드시 넣으라는 강제는 아님(구현/정책에 따라 생략 가능)
HEAD 예시
요청
HEAD /images/cat.jpg HTTP/1.1
Host: example.com
응답(본문 없음)
HTTP/1.1 200 OK
Content-Type: image/jpeg
Content-Length: 10742344
ETag: "abc123"
Last-Modified: Wed, 18 Jun 2025 00:44:54 GMT
Range 요청이란?
- 클라이언트가 리소스의 일부만 달라고 요청(예:
bytes=0-0
처음 1바이트). - 서버가 수락하면 206 Partial Content 와 함께
Content-Range
로 전체 크기와 범위를 알려줌. - 만족 못 하면 416 Range Not Satisfiable 과
Content-Range: */총길이
. (IETF HTTP Working Group, MDN)
Range 예시 (부분 전송 한 구간)
요청
GET /images/cat.jpg HTTP/1.1
Host: example.com
Range: bytes=0-0
응답(206 + 본문: 1바이트)
HTTP/1.1 206 Partial Content
Content-Type: image/jpeg
Content-Range: bytes 0-0/10742344
Content-Length: 1
<1바이트 이진 데이터>
- 여기서
/10742344
가 전체 길이라서, 총 용량 파악이 가능해요. (CDN이 Range는 잘 채우는 경우가 많음) (MDN)
헤더/바디 보는 법 요약
- 요청줄:
METHOD SP path SP version
- 요청 헤더:
Range
,If-None-Match
,Accept
… - 요청 바디: 보통 POST/PUT/PATCH에 존재
- 응답줄:
version SP status SP reason
- 응답 헤더:
Content-Type
,Content-Length
,ETag
,Content-Range
… - 응답 바디: HEAD는 없음, GET/Range GET은 있음
HEAD는 언제 쓰나?
- 메타데이터만 필요할 때: 본문 없이 타입/길이/ETag/최종수정일만 확인.
- 예) 링크 유효성 점검, 썸네일 올바른 MIME인지 확인, 서명 URL 만료 체크.
- 캐시 재검증:
If-None-Match
,If-Modified-Since
와 같이 써서 변경 없으면 304만 받기. - 트래픽 절약: 큰 파일을 받기 전에 “받을 가치가 있는지” 빠르게 판단.
예)
HEAD /files/movie.mp4 HTTP/1.1
Host: cdn.example.com
HTTP/1.1 200 OK
Content-Type: video/mp4
Content-Length: 734561234
ETag: "abc123"
Last-Modified: Wed, 18 Jun 2025 00:44:54 GMT
주의: 일부 CDN/서버는 HEAD에
Content-Length
를 안 넣거나 0으로 줄 수 있다.(정책/압축/프록시 때문).
Range(부분 요청)는 언제 쓰나?
- 대용량 파일 부분 다운로드/스트리밍: 오디오/비디오 시킹, 문서 일부만 미리보기.
- 다운로드 이어받기/멀티 파트 병렬 받기: 끊긴 지점부터 재시작, 여러 구간을 나눠서 빠르게 받기.
- 총 파일 크기만 빠르게 알 때:
bytes=0-0
로 1바이트만 요청하고 응답의Content-Range
에서 전체 크기 추출. - 랜덤 액세스가 필요한 포맷: ZIP 중앙 디렉터리, ISO 등 뒤쪽 메타만 읽기.
예)
GET /files/movie.mp4 HTTP/1.1
Host: cdn.example.com
Range: bytes=1000000-1999999
HTTP/1.1 206 Partial Content
Content-Type: video/mp4
Content-Range: bytes 1000000-1999999/734561234
Content-Length: 1000000
<해당 구간 바이트>
주의: 서버가 Range를 지원해야 하고(보통
Accept-Ranges: bytes
), 미지원이면 200 전체 응답을 줄 수 있어요. 브라우저에서 교차 출처로 헤더를 읽으려면 CORS +Access-Control-Expose-Headers
설정도 필요
현업 패턴 요약
- 빠른 크기 파악: HEAD가 부정확할 수 있어
Range: bytes=0-0
로Content-Range
에서 총 크기를 읽는 게 더 안정적. - 안전한 재시작:
If-Range: <ETag/Last-Modified>
와 함께 Range를 써서, 파일이 바뀌었으면 전체로, 안 바뀌었으면 부분만 받기.리액트 이슈 - 사진용량 가져오기 HEAD는 안되고, RANGE는 되는 이유