Conditional GET: 개념, 조건부 요청 메커니즘

저자: IT Sectr 게시일: 2026-06-14 읽는 시간: 7 분

Conditional GET — 클라이언트가 전체 다운로드 전에 캐시된 리소스의 최신 상태를 확인할 수 있는 HTTP 메커니즘입니다. 클라이언트는 If-None-Match(ETag 포함) 또는 If-Modified-Since(날짜 포함) 헤더와 함께 GET 요청을 보내고, 리소스가 변경되지 않은 경우 서버는 응답 본문 없이 304 Not Modified를 반환합니다. MDN Web Docs, 2025에 따르면 조건부 요청은 서버와 클라이언트의 네트워크 트래픽을 줄입니다. 304 Not Modified는 효율적인 모바일 애플리케이션 동기화를 위한 중요한 HTTP 상태입니다.

핵심 사항

  • Conditional GET — 캐시 최신 상태 확인을 위한 If-None-Match 또는 If-Modified-Since 헤더가 포함된 HTTP 요청.
  • 304 Not Modified — 리소스가 변경되지 않았음을 나타내는 서버 응답. 응답 본문이 전송되지 않아 트래픽을 절약.
  • If-None-Match — ETag(버전 해시)가 포함된 헤더로, 리소스 콘텐츠 수준에서 정확한 검증 제공.
  • If-Modified-Since — 마지막 수정 날짜가 포함된 헤더, 구현은 간단하지만 정확도가 낮음(1초 해상도).
  • 효율성 — Conditional GET은 변경되지 않은 리소스의 동기화 중 데이터 양을 80–95% 감소.

HTTP에서 Conditional GET이란?

Conditional GET은 하나 이상의 조건부 헤더를 포함하는 GET 요청으로, 서버는 이를 기반으로 완전한 응답을 반환할지 아니면 304 Not Modified 상태만 반환할지 결정합니다. 주요 목적은 마지막 요청 이후 리소스가 변경되지 않은 경우 응답 본문 전송을 피하는 것입니다. 이것은 RFC 7232에 정의된 기본 HTTP 캐싱 메커니즘입니다.

모바일 애플리케이션의 경우 Conditional GET은 네트워크 트래픽을 최적화하는 가장 효과적인 방법 중 하나입니다. 일반적인 시나리오: 앱을 열 때 클라이언트는 피드, 프로필 및 설정을 로드하기 위해 일련의 조건부 GET 요청을 보냅니다. 데이터가 변경되지 않은 경우 앱은 304를 수신하고 로컬 복사본을 사용합니다. 이는 초가 아닌 밀리초가 소요되며 모바일 데이터를 소비하지 않습니다.

Google Web Fundamentals(2025)에 따르면 모바일 애플리케이션에서 조건부 GET 요청을 구현하면 반복 방문 시 평균 로드 시간이 40–60% 단축되고 업데이트가 드문 페이지의 트래픽 사용량이 70–90% 감소합니다. 이 효과는 모든 바이트가 중요한 느린 연결(3G, Edge)에서 특히 두드러집니다.

조건부 GET 요청의 작동 방식

프로세스는 세 단계로 구성됩니다. 첫째 — 클라이언트가 일반 GET 요청을 보내면 서버가 캐싱 헤더(ETag, Last-Modified)와 함께 리소스를 반환합니다. 둘째 — 클라이언트가 리소스와 검증기를 로컬에 저장합니다. 셋째 — 반복 요청 시 클라이언트가 If-None-Match(ETag용) 및/또는 If-Modified-Since(Last-Modified용)와 함께 GET을 보냅니다. 서버는 검증기를 확인하고 리소스가 변경되지 않은 경우 304, 새 데이터가 있는 경우 200으로 응답합니다.

서버는 두 헤더가 모두 있을 때 ETag를 Last-Modified보다 우선합니다. ETag가 더 정확한 검증을 제공하기 때문입니다 — 콘텐츠 해시는 수정 시 변경되지만 Last-Modified는 1초 해상도를 가집니다. ETag가 일치하면 서버는 Last-Modified를 확인하지 않고 즉시 304를 반환합니다.

요청 시퀀스에서 완전한 Conditional GET 주기의 예:

kotlin
// 스텝 1: 첫 번째 요청 — 데이터와 ETag 획득
GET /api/profile
Response: 200 OK
ETag: "33a64df551425fcc55e"
Body: { "name": "Alice" }

// 스텝 2: 요청 반복 — If-None-Match로
GET /api/profile
If-None-Match: "33a64df551425fcc55e"
Response: 304 Not Modified
// 응답 본문 없음 — 로컬 복사본 사용

두 번째 요청에서 서버는 If-None-Match의 ETag를 현재 리소스 해시와 비교합니다. 일치하면 본문 없이 304를 반환합니다 — 클라이언트는 캐시된 데이터를 계속 사용합니다. 이것이 Conditional GET의 핵심입니다: 최소 트래픽으로 최대 데이터 최신성.

Conditional GET vs 일반 GET

일반 GET 요청은 항상 본문이 포함된 완전한 200 OK 응답을 반환합니다. 리소스가 변경되지 않은 경우에도 서버는 모든 데이터를 다시 전송합니다. 이는 작은 리소스나 드문 요청에는 허용되지만, 실행할 때마다 수백 개의 요청을 보내는 모바일 애플리케이션의 경우 이 접근 방식은 과도한 트래픽과 배터리 소모로 이어집니다.

Conditional GET은 헤더 형태로 오버헤드를 추가하지만(보통 요청당 50–200바이트) 304 응답으로 킬로바이트와 메가바이트를 절약합니다. 리소스가 클수록 조건부 요청의 이점이 커집니다. 10KB 이상의 이미지, 데이터 목록 및 JSON 문서의 경우 Conditional GET은 첫 번째 반복 요청부터 효과를 발휘합니다.

두 접근 방식의 비교 특성:

매개변수일반 GETConditional GET
트래픽(변경 없음)완전한 응답헤더만(~200바이트)
지연 시간전체 다운로드밀리초(304)
서버 부하생성 + 전송ETag 확인만
구현 복잡성최소ETag 저장 필요
대규모 데이터 효율낮음높음

Kotlin 구현 예제

전체 구현을 살펴보겠습니다 — OkHttp와 Room을 사용한 Kotlin에서의 Conditional GET 구현(ETag 저장용). 작업 목록 애플리케이션이 서버에서 작업을 로드하고 트래픽을 최소화하기 위해 조건부 요청을 사용합니다. ETag는 세션 간 유지를 위해 로컬 데이터베이스에 저장됩니다.

Kotlin에서 Conditional GET을 사용하는 리포지토리:

kotlin
class TaskRepository(
    private val api: TaskApi,
    private val etagDao: EtagDao
) {
    suspend fun getTasks(): List<Task> {
        val savedEtag = etagDao.getEtag("tasks")

        val response = api.fetchTasks(
            ifNoneMatch = savedEtag
        )

        return when (response.code()) {
            304 -> taskDao.getAll() // 로컬 캐시에서
            200 -> {
                response.header("ETag")?.let {
                    etagDao.saveEtag("tasks", it)
                }
                val tasks = response.body() ?: emptyList()
                taskDao.replaceAll(tasks)
                tasks
            }
            else -> throw Exception(
                "Sync failed: ${response.code()}")
        }
    }
}

TaskRepository는 응답 코드를 확인합니다: 304는 변경 없음을 의미하며 데이터는 로컬 Room 캐시에서 반환됩니다. 200의 경우 새 ETag가 저장되고 작업이 로컬 데이터베이스에서 업데이트됩니다. 이 패턴은 REST API 동기화가 있는 모바일 애플리케이션의 표준입니다.

모바일 개발에서 Conditional GET 사용

Conditional GET은 널리 사용됩니다 — 모바일 애플리케이션의 데이터 동기화 최적화에. 주요 시나리오: 뉴스 피드 로드(Twitter, Instagram은 정기적으로 If-None-Match로 API 폴링), 사용자 프로필 업데이트, 알림 목록 로드 및 작업 동기화. 각 경우에서 앱은 데이터를 다시 다운로드하지 않고 최신 상태를 확인할 수 있습니다.

오프라인 우선 애플리케이션의 경우 Conditional GET은 동기화의 첫 번째 단계로 작동합니다. 앱은 먼저 마지막 동기화 이후 로컬에서 변경된 모든 리소스에 대해 조건부 GET 요청을 보냅니다. 304 리소스는 다운로드가 필요하지 않습니다. 그 후 앱은 로컬 변경 사항에 대해 PUT/POST를 보냅니다. 이 2단계 접근 방식은 최소 트래픽 소비를 보장합니다.

충돌 해결과 결합하여 Conditional GET은 효율적인 충돌 감지를 가능하게 합니다. 클라이언트가 새 데이터와 함께 200을 수신했지만(리소스가 변경됨) 보내지 않은 로컬 변경 사항이 있는 경우 충돌이 등록됩니다. 클라이언트는 LWW를 적용하거나(로컬 변경 사항 손실) 병합 전략을 시작하여 로컬 및 원격 변경 사항을 병합할 수 있습니다. Meta Engineering Blog(2025)에 따르면 Messenger에서 Conditional GET을 구현하여 평균 동기화 트래픽이 73% 감소했습니다.

자주 묻는 질문

Conditional GET 요청이란?

Conditional GET — 조건부 헤더(If-None-Match, If-Modified-Since)가 있는 HTTP GET 요청. 리소스가 변경되지 않은 경우 서버가 304 Not Modified를 반환하고 새 데이터가 있는 경우 200을 반환합니다. 효율적인 캐싱 메커니즘입니다.

Conditional GET과 일반 요청의 차이점은?

일반 GET은 항상 본문이 포함된 완전한 응답을 반환합니다. Conditional GET은 버전 확인 헤더(ETag, 날짜)를 추가합니다. 데이터가 변경되지 않은 경우 서버는 본문 없이 304로 응답하여 트래픽과 로드 시간을 절약합니다.

캐싱에 Conditional GET을 사용하는 방법

효과적인 캐싱을 위해 각 서버 응답에서 ETag와 Last-Modified를 로컬 데이터베이스에 저장합니다. 다음 요청 시 If-None-Match 및 If-Modified-Since 헤더로 보냅니다. 304의 경우 로컬 캐시의 데이터를 사용합니다.

Conditional GET이 트래픽을 절약하는 방법

304 응답 시 서버는 응답 본문을 전송하지 않고 헤더만(~200바이트) 전송합니다. 50KB 리소스의 경우 99.6%의 트래픽 절약을 의미합니다. 하루 50회 동기화하는 앱의 경우 월간 수십 메가바이트의 절약 효과가 있습니다.

동기화에 Conditional GET을 사용할 수 있나?

네, 표준 접근 방식입니다 — 델타 동기화에서. 클라이언트는 Conditional GET을 통해 각 리소스의 최신 상태를 확인하고 변경된 리소스만 다운로드하며 로컬 변경 사항을 보냅니다. 이 접근 방식은 Twitter, Instagram, Telegram 및 대부분의 최신 API에서 사용됩니다.

요약

  • Conditional GET — 조건부 If-None-Match 및 If-Modified-Since 헤더를 통해 캐시된 리소스의 최신 상태를 확인하기 위한 HTTP 메커니즘.
  • 304 Not Modified — 리소스가 변경되지 않았음을 나타내는 서버 응답. 응답 본문이 전송되지 않아 트래픽과 로드 시간을 절약.
  • ETag vs Last-Modified — ETag가 더 정확함(콘텐츠 해시), Last-Modified가 더 간단함(날짜). 최대 효율을 위해 둘 다 결합 권장.
  • 트래픽 절약 — 변경되지 않은 리소스의 경우 Conditional GET이 리소스 크기에 따라 전송 데이터량을 70–95% 감소.
  • 응용 — Twitter, Instagram, Telegram 및 대부분의 최신 REST API에서 표준 동기화 메커니즘.
  • 통합 — 클라이언트 측에서는 로컬 데이터베이스에 ETag 저장 필요; 서버 측에서는 각 요청에서 ETag 생성 및 비교 필요.
  • 권장 사항 — 모바일 API의 모든 GET 엔드포인트에 Conditional GET을 구현하세요. 사용자에게 가장 큰 영향을 미치는 가장 저렴한 최적화입니다.

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기