캐시 사용시 주의점

  • 갱신은 자주 일어나지 않지만 참조는 빈번이 일어난다면 고려할만 하다.
  • 일반적으로 RAM에서 동작
  • 캐시는 휘발성이므로 영속적으로 보관할 데이터는 캐시에 두는것이 바람직하지 않다.
  • 캐시는 언제 어떻게 만료(expire)되는가?에 대한 정책을 수립할 필요가 있다. 만료시간을 너무 짧게, 너무 길게 가져가지 않도록 주의해야한다.
  • 데이터베이스와 일관성을 어떻게 유지할 것인가? 에 대한 생각도 해봐야한다. 찾아보니 이는 논문도 나올정도로 많은 연구가 진행되고 있는 것 같다.
  • 장애에는 어떻게 대처할 지도 생각해봐야한다. 캐시 서버를 하나로 두면 해당 서버는 단일 장애 지점이 되어버릴 가능성이 있다. 때문에 여러 지역에 걸쳐 캐시 서버를 분산 시켜야 한다.

단일 장애 지점(Single Point of Failure, SPOF)는 어떤 특정 지점에서의 장애가 전체 시스템의 동작을 중단시켜버릴 수 있는 경우 그 지점을 단일 장애 지점이라고 부른다.

  • 캐시 메모리는 얼마나 크게 잡을 것인가? 캐시 메모리가 작다면 데이터가 밀려나면서 자주 갱신되기에 성능이 저하된다. 크게 잡는편이 좋다고 한다.
  • 데이터 방출(eviction) 정책도 수립해야한다. 캐시가 꽉 차면 기존 데이터를 내보내고 새로 데이터를 받아야하는데, 자주 쓰이는 알고리즘은 LRU(Least Recently Used)방식이다. 외에 LFU, FIFO 등이 있다.
  • API 캐시
    • API 캐싱은 주로 변경되지 않거나 자주 변경되지 않는 데이터에 사용됩니다. 예를 들어 날씨 정보, 뉴스 기사, 사용자 프로필 등의 데이터
    • 이 캐시는 메모리에 저장될 수도 있고, 별도의 캐시 서버(예: Redis, Memcached)에 저장
  • 데이터베이스 캐싱
    • 데이터베이스에서 상품 데이터를 조회하고, 이를 캐시에 저장합니다. 시스템은 캐시된 버전을 제공하여 데이터베이스에 대한 추가적인 쿼리를 방지
  • HTTP 프로토콜인데 ETag(Entity Tag)는 웹에서 콘텐츠의 버전을 식별하는 메커니즘
    • 서버 ETag 생성 HTTP 응답 헤더에 포함 클라이언트 전달
    • 클라이언트는 ETag 사용해 자원 특정 버전 캐싱
    • "If-None-Match" HTTP 요청 헤더에 포함시켜 서버에 전달
    • 서버는 이 헤더의 ETag 값을 확인하고, 현재 자원의 ETag 값과 비교
    • 두 값이 일치하면, 콘텐츠가 변경되지 않음
    • HTTP 304 Not Modified 상태 코드를 반환
  • 로컬 캐시
    • 로컬 캐시는 일반적으로 단일 클라이언트나 서버 인스턴스 내에 위치
    • 해당 인스턴스에서만 접근하고 사용할 수 있는 캐시
  • 글로벌 캐시
    • 글로벌 캐시는 여러 클라이언트나 서버 인스턴스가 네트워크를 통해 공유하고 접근할 수 있는 중앙 집중식 캐시
    • Redis 나 Memcached를 사용

 

CDN(컨텐츠 전송 네트워크)

CDN은 정적 콘텐츠를 전송하는데 쓰이는 지리적으로 분산된 서버 네트워크다

이미지, 비디오, CSS, javascript파일 등을 캐시할 수 있다.

동작방식은 다음과 같이 간단하다.

  • 사용자가 웹 사이트에 방문
  • 지리적으로 가까운 CDN 서버가 정적 콘텐츠를 사용자에게 전달.

지리적으로 분산된 네트워크라서 거리가 멀면 응답이 느린건 당연하다.

거리가 멀수록 요청전달이 느려진다.

CDN은 이런식으로 캐싱하여 전달된다.

동작방식은 어렵지 않아서 설명하지 않아도 되지만 추가적으로 알아야할 것들이 있다.

사용자는 이미지 URL을 통해 image.png에 접근하는데, 이 URL 도메인은 CDN 사업자가 제공한 것이다.

1. https://mysite.cloudfront.net/logo.png

와 같은 이미지 URL 예시가 있다.

또한 3번에서 이미지를 저장하고 있는 원본 서버에서 파일을 CDN서버에 반환할 때, 파일이 얼마나 오래 캐시 될 수 있는지를 설명하는 TTL(Time-To-Live) 값이 들어 있다. 이 값을 통해 CDN은 해당 이미지가 캐시에 얼마나 존재할 수 있는지를 정할 수 있다.

 

CDN 사용 시 고려해야할 사항

  • 비용: CDN은 보통 제 3 사업자에 의해 운영되고, 데이터 전송 양에 따라 요금을 내기 때문에 자주 참조되지 않는 콘텐츠를 캐싱해두는건 비용적으로 손실이 있다.
  • 적절한 만료 시한 설정: 캐시와 마찬가지로 만료시간을 잘 설정해야 성능을 개선할 수 있다.
  • CDN 장애에 대한 대처 방안: CDN이 응답하지 않는 경우 어떻게 해야할 지 생각해야한다. 원본 서버에서 직접 콘텐츠를 가져오도록 클라이언트를 구성하는 것도 방법 중 하나다.
  • 콘텐츠 무효화(invalidation) 방법: 콘텐츠의 새로운 버전이 배포된 경우 CDN에 저장된 오래된 버전을 제거하여 사용자들이 최신 버전의 콘텐츠를 받도록 하는 것
    • CDN 서비스 사업자가 제공하는 API를 이용하여 무효화
    • 콘텐츠의 다른 버전을 서비스하도록 **오브젝트 버저닝(object versioning)**이용. 새로운 버전을 지어하기 위해 URL 마지막에 버전 번호를 인자로 주면 된다. ex) image.png?v=2

웹서버, 데이터베이스 서버, 로드밸런서, 데이터베이스 다중화(Master-Slave), 캐시 서버, CDN을 추가하면 다음과 같은 시스템 설계가 될 것이다.

무상태(stateless) 웹 계층

상태 아키텍처

웹 계층을 수평적으로 확장하기 위해서는 상태 정보(사용자 세션 데이터 등)을 웹 서버에서 제거해야한다. 만약 3개의 서버(A서버, B서버, C서버)가 있고, 3명의 사용자(A유저, B유저, C유저)가 있다고 치자.

서버 A에는 A유저의 인증정보가, 서버 B에는 B유저의 인증정보가, 서버 C에는 C유저의 인증정보가 있다고 하면 유저가 요청 보낼때마다 해당 서버에 요청이 전달되어야할 것이다. 즉, 사용자에 따라 항상 같은 서버에 요청을 보내야한다. 대부분 로드밸런서는 **고정 세션(sticky session)**이라는 기능을 제공하여 위의 상황을 지원하는데 로드밸런스 입장에서는 부담이다. 게다가 추가적으로 서버를 늘리거나 제거할 때도 예기치 않은 장애를 일으킬 수 있고 로드밸런서 설정을 건드려줘야하기에 까다로워진다.

무상태 아키텍처

그렇기에 사용자의 데이터들을 따로 모아놓는 저장소를 두는게 좋다. 이 저장소는 공유 저장소(shared storage)라고 불려진다.

위처럼 구성하면 요청에 대해 물리적으로 분리해줄 필요는 없기에 부담없이 웹 서버를 수평적으로 확장할 수 있고 이처럼 단순하고 안정적이라 규모확장에도 이점이 있다.

보통 공유 저장소는 관계형 데이터베이스일 수도 있고, Redis와 같은 캐시 시스템일수도 있고, NoSQL일수도 있다.

만약에 서비스가 성장하여 전 세계에 배포되고 서비스를 제공해야 한다면 전 세계에서 빠르게 편하게 사용할 수 있도록 **데이터 센터(data center)**를 지원하는 것이 필수다.


HTTP 특징

  • 무상태 프로토콜(Stateless Protocol)
  • 클라이언트-서버 구조
  • HTTP 헤더를 통해, 프로토콜은 데이터의 타입, 인증, 캐싱 지침 등과 같은 많은 추가 정보를 전달
  • HTTP는 텍스트, 이미지, 비디오, 오디오 등 다양한 형식의 미디어를 전송
  • HTTP 메서드 지원
  • HTTP는 웹 콘텐츠의 효율적인 로딩을 위해 캐싱 기능을 지원
  • 여러 버전 존재