티스토리 뷰

CS

[CS] 캐시(cache)란?

무화과(Fig) 2024. 4. 3. 15:13

팀 미팅 시간에 캐시(cache)에 대해 팀원분과 얘기를 나누게 됐다.

 

데일리 퀴즈에서 나왔던 문제를 cache를 사용해서 푸는 방법과 리액트의 Virtual DOM이 일종의 cache라는 것을 알게됐는데, 여러 가지들을 알게돼서 너무 재밌었다ㅋㅋㅋ

 

그래서 오늘은 cache에 대한 내용을 주제로 글을 작성하려 한다.

 

 

1. 캐시(cache)란?


cache는 자주 사용하는 데이터나 값을 미리 복사해 놓는 임시 장소를 말한다.

 

아래 그림은 저장공간의 계층 구조를 나타낸 그림인데, 그림을 보면 캐시는 저장공간이 작고 비용이 비싼 대신 빠른 성능을 제공한다.

 

캐시는 다음과 같은 경우에 사용하면 좋다.

 

1. 동일한 API 데이터를 빠르게 제공해야 할 때

위의 경우 다음과 같은 예시를 들 수 있다.

온라인 상점의 제품 카탈로그를 생각해보자. 많은 사용자가 동시에 이 카탈로그에 접근하고, 이 카탈로그의 데이터는 자주 변경되지 않는다. 서버는 모든 사용자에게 동일한 카탈로그 데이터를 제공하며, 이 데이터를 요청할 때마다 매번 새로운 요청을 처리한다면 서버에 부담이 될 수 있다.

이런 경우, 서버는 데이터를 한 번 로드하고 캐시에 저장하여 여러 사용자에게 동일한 데이터를 제공할 수 있다. 캐시를 사용하면 다수의 사용자가 동일한 데이터를 반복적으로 요청해도 서버는 매번 데이터를 다시 생성할 필요 없이 캐시된 데이터를 제공할 수 있다. 이렇게 함으로써 서버 부하를 줄이고 응답 시간을 개선할 수 있다.

 

2. 반복적으로 동일한 결과를 돌려주는 경우 (이미지나 썸네일)

위의 경우 다음과 같은 예시를 들 수 있다.

웹 페이지에서 특정 이미지를 여러 번 사용하는 경우를 생각해보자. 사용자가 페이지를 여러 번 방문할 때마다 같은 이미지가 사용되는 경우가 많다. 이때 매번 이미지를 새로 다운로드하고 요청하는 것은 비효율적일 수 있다.

이런 경우 이미지를 한 번 다운로드하고 캐시에 저장하여 다음에 동일한 이미지가 필요할 때 캐시된 이미지를 사용할 수 있다. 이렇게 하면 동일한 이미지에 대한 반복적인 다운로드 요청을 피할 수 있으며, 사용자 경험을 향상시킬 수 있다. 또한 이미지가 캐시되어 있기 때문에 네트워크 대역폭을 절약할 수 있으며, 페이지 로딩 속도도 개선될 수 있다.

 

 

 

2. 캐시가 사용되는 과정


다음으로 캐시가 사용되는 과정에 대해 알아보자.

 

1. 먼저, 클라이언트가 서버로 데이터를 요청한다. (ex. 이미지, 값)

2. 서버는 요청받은 데이터가 캐시메모리에 존재하는지 확인한다. 만약 캐시 메모리에 데이터가 존재하면 서버는 해당 데이터를 클라이언트에게 반환한다.

3. 데이터가 캐시 메모리에 존재하지 않거나 만료된 경우, 서버는 DB(실제 데이터 소스)에서 데이터를 조회한다.

4. 서버는 가져온 데이터를 클라이언트에게 반환하기 전에, 캐시 메모리에 해당 데이터를 저장한다.

 

위와 같은 프로세스를 캐싱 용어에 대입하면 다음과 같다.

  • 캐시 미스(Cache Miss): 요청한 데이터나 연산의 결과가 캐시에 없는 경우 시스템은 본래 소스(예: 메인 메모리, 데이터베이스)에서 데이터를 가져와 캐시에 저장하고, 동시에 클라이언트에게 결과를 반환한다. (위의 2~3의 과정)
  • 캐시 히트(Cache Hit): 요청한 데이터나 연산의 결과가 캐시에 있는 경우 시스템은 캐시에서 빠르게 데이터를 읽어와 클라이언트에게 결과를 반환한다. (위의 2의 과정)

이처럼 cache는 이전 값을 재사용 할 수 있어서 효율이 올라갈 수 있다.

 

하지만 cache는 양날의 검이기도 하다. 만약 cache에 부정확한 값이나 노후된(outdated) 값이 들어가면 큰 문제로 이어질 수 있기 때문이다.

 

이런 cache의 특성 때문에 캐싱 전략이 필수적이다.

 

3. 캐싱 전략


캐싱 전략은 어떻게 데이터를 캐시에 저장하고 관리할지에 대한 계획과 규칙을 말한다. 지금부터 알아 볼 캐시 전략은 총 5가지 이다.

 

1. 읽기 전략(Read Cache Strategy) - Look Aside 전략

 

일반적으로 많이 사용되는 전략이다.

기본적으로 Cache에서 데이터를 확인하고, 없다면 DB를 통해 조회해 오는 방식이다.

 

진행되는 방식은 다음과 같다.

 

  1. 먼저 Cache에 데이터가 있는지 찾아봄
  2. 없으면 다음으로 DB에 데이터를 찾아봄
  3. DB에 데이터가 있는 경우 DB에서 가져온 데이터를 캐시에 저장
  4. 이후 데이터를 사용자에게 전달

 

장점

  • 다수의 사용자가 'Read'연산을 하는 경우 빠른 속도를 보장한다.
  • Redis가 중간에 뻗어도 DB를 통해 값을 가져올 수 있어서 서비스 장애가 나지 않는다.
  • 캐시와 DB가 따로 존재하기 때문에 원하는 데이터만을 Redis에 저장 가능하다.
    • 이를 통해 데이터를 낭비하지 않을 수 있다.

단점

  • 'CUD'연산을 하는 경우, DB와 Cache data 사이의 정합성 문제가 발생할 수 있다.
    • DB에는 변경되었지만 Cache Data에서 변경되지 않는경우
  • 'Read'연산의 경우도 각각의 사용자가 다 다른 데이터를 불러오는 경우에는 적합하지 않다.
  • 최초 실행시 Redis상에 데이터가 없다면 매번 DB를 통해 가져와야 한다.
    • 이를 해결하기 위해 Cache warming(미리 데이터 캐싱)을 진행할 수 있다.

정리하자면 다수의 사용자가 비슷한 Data의 Read를 진행할 때에 알맞는 전략이다.

 

 

 

2. Read Through 전략

 

캐시에서만 데이터를 불러오는 전략이다.

 

위의 Look Aside와 비슷하지만 다른점은 Cache에 데이터가 없을 때에 Server가 아니라, Cache가 DB에 데이터를 조회하여 업데이트 한 후에 그 데이터를 보여주는 방식이다.

  1. 먼저 Cache에 데이터가 있는지 찾아봄
  2. 없으면 Cache가 DB에서 데이터를 찾아봄
  3. DB에 데이터가 있는 경우 DB에서 가져온 데이터를 캐시에 저장
  4. 캐시를 통해 이 데이터를 사용자에게 전달

 

장점

  • Server가 DB에 접근하지 않기 때문에 'Read'시 소모 자원을 줄일 수 있다.

단점

  • 캐시가 뻗는 경우 캐시 서버가 SPOF가 될 수 있다.
    • 따라서 Replication이나 Clustering을 통해 가용성을 확보해야 한다.
  • 최초 실행시 Redis상에 데이터가 없다면 매번 DB를 통해 가져와야 한다.
    • 이를 해결하기 위해 Cache warming(미리 데이터 캐싱)을 진행할 수 있다.

 

 

3. 쓰기 전략(Write Cache Strategy) - Write Back 전략

 

데이터를 삽입할 때에 이를 캐시에 보관해 두고, 일정 시간마다 DB에 저장시키는 방식이다. 쓰기가 굉장히 빈번하게 일어나는 경우 사용하는 방식이다.

  • 로그 데이터의 경우 매번 DB에 데이터를 저장하기 번거로우니 이 방식이 요긴하게 쓰인다고 한다.
로그(log data)란?

컴퓨터의 처리 내용이나 이용 상황을 시간의 흐름에 따라 기록한 것이라고 볼 수 있다.
IT인프라 운영을 위한 서버, 네트워크, 보안장비 등에서 발생하는 모든 정상/비정상적인 기록이 로그(log)이다.
따라서 로그 데이터는 소프트웨어 및 하드웨어,인프라의 상태를 파악하는 시각적 정보의 역할을 한다.

 

쓰기 전략이 진행되는 방식은 다음과 같다.

  1. Cache에 데이터를 저장시켜 준다.
  2. 특정 시간마다 DB에 해당 데이터를 저장시킨다.
  3. DB에 데이터가 저장되면 Cache에서는 이걸 지울수도 있고, 가지고 있을수도 있다.

참고로 DB에 데이터를 저장할 때에 굳이 모아서 배치(여러 개의 작업을 한 번에 묶어서 처리)로 하는 이유는 insert를 뭉탱이로 한꺼번에 처리해주면 연산이 훨씬 줄어서이다.(예를 들어 1000번의 데이터 입력을 1000번 DB에 insert를 보내는 것 보다 insert*1000으로 한번에 보내는게 빠른것)

일반적으로 데이터베이스에 데이터를 추가하는 작업은 개별적으로 수행된다. 즉, 하나의 데이터를 추가할 때마다 데이터베이스에 INSERT 쿼리가 실행된다. 이런 방식으로 대량의 데이터를 추가하려면 많은 수의 INSERT 쿼리가 실행되어야 하므로 처리 시간이 오래 걸릴 수 있다.

그러나 "배치로 처리한다"는 방식은 다르게 작동한다. 대량의 데이터를 묶어서 한 번에 삽입하는 방식이기 때문에 INSERT 쿼리를 한 번만 실행하면 된다. 이렇게 하면 데이터베이스와의 통신 횟수가 줄어들어 전체적인 처리 시간이 효율적으로 단축될 수 있다.

 

장점

  • 'Write'연산이 많은 경우 이를 Redis에 보관하기 떄문에 자원 소모를 줄일 수 있음
  • 데이터 정합성이 확보된다
    • 이는 캐시에서 데이터를 읽어오는데, 최신 데이터가 캐시에 보관되기 때문이다.

단점

  • 중간에 캐시가 뻗으면 데이터가 없어져버림
  • Cache에 읽을일도 없는 정보가 너무 많이 저장될수 있다.
    • 그래서 저장 후 삭제하는 경우도 있다.

 

쓰기 전략은 로그 데이터처럼 write는 빈번하지만 읽을 일은 별로 없는 데이터의 저장에 알맞는 전략이다.

 

 

 

4.Write Through 전략

 

DB와 Cache에 동시에 데이터를 저장하는 전략이다. 방식은 다음과 같다.

  1. 데이터 write시 Cache에 데이터 저장
  2. Cache에서 이를 바로 DB에 저장(batch 아님)
  3. Cache에는 데이터 저장되어 있음.

 

장점

  • 'Write'한 데이터를 'Read'하는 경우 cache를 이용해서 해결 가능하다.
    • 최근 데이터를 불러오는 일이 많은 경우(공통 최신 read가 많은 경우) 좋은 성능을 갖는다.
  • 캐시-데이터간의 데이터 차이가 없다.
    • 정합성도, 데이터 유실 위험도 없다.

단점

  • 'Write', 'Update'가 많은 경우 성능이 좀 별로다.
    • Cache에서도 DB에서도 매번 변경하기 때문
  • 읽을일 없는 쓸데없는 데이터를 가지는 경우가 있다.

 

따라서 Write Through 전략은 최신 피드를 가져오는 경우에 알맞는 전략이다.

 

 

 

5. Write Around 전략

 

데이터를 DB에 저장하고, 캐시에 값이 없는 경우 저장시켜주는 방식이다.

  1. 데이터 write시 DB에 데이터 저장
  2. 데이터 read시 Cache를 통해 찾아봄
  3. Cache에 해당 데이터가 없는 경우 DB를 통해 찾고, 서버가 해당 데이터를 DB에 저장해준다.

 

장점

  • Write Through보다 속도가 빠르다.
    • 매번 DB, Cache를 변경하지 않고 DB만을 변경하고 cache miss인 경우만 cache를 바꾸기 때문

단점

  • 데이터 불일치가 발생할 수 있다.
    • DB에서는 변경된 값이 Cache에서는 변경되지 않는 경우가 있을 수 있다.
      • 이를 위해 Cache expire시간을 짧게 유지해야 한다.

 

추가로 , cache의 근간을 이루는 값이 변경될 때 마다 재구축(rebuilding)이 필요하다. (windows를 업데이트할 때 n일 마다 확인하고 업데이트가 없으면 그 결과를 저장하는 것도 cache다.)

 

또한 근간하는 값이 변경된다고 해서 바로 재구축하는 것이 아니라 필요할 때만 구축하는 방식도 있다. (리액트의 Virtual DOM 같은)