# memcached 예찬

> Clean Markdown view of GeekNews topic #30778. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=30778](https://news.hada.io/topic?id=30778)
- GeekNews Markdown: [https://news.hada.io/topic/30778.md](https://news.hada.io/topic/30778.md)
- Type: GN+
- Author: [xguru](https://news.hada.io/@xguru)
- Published: 2026-06-24T09:39:36+09:00
- Updated: 2026-06-24T09:39:36+09:00
- Original source: [jchri.st](https://jchri.st/blog/in-praise-of-memcached/)
- Points: 1
- Comments: 1

## Topic Body

- 캐시는 데이터베이스 부하를 줄이기 위해 들어오지만, Redis처럼 쓰기 쉬운 도구는 시간이 지나며 **영속 저장소처럼 의존**되기 쉬움  
- 문제는 Redis의 영속성 기능이 아니라, 처음에는 **휘발성 캐시**로 도입된 구성 요소가 애플리케이션의 핵심 상태와 엮이는 운영 흐름임  
- memcached는 공식 정의부터 **분산 메모리 객체 캐싱 시스템**이고 디스크 저장을 전제로 하지 않아, 상태 없는 캐시 워크로드로 다루기 쉬움  
- 여러 memcached 인스턴스는 서버가 아니라 클라이언트가 URL 목록과 키 해시로 나누며, 장애 노드는 해셔에서 빠졌다가 나중에 재연결을 시도함  
- “데이터베이스가 느리다”는 이유로 캐시부터 추가하기보다, 먼저 **느린 쿼리와 누락된 인덱스**를 확인해야 함  
  
---  
  
### Redis가 캐시에서 저장소로 변하는 순간  
- 인프라를 운영하다 보면 “캐시가 필요하다”는 요구가 자주 나오고, 익숙하고 기능이 많은 Redis가 먼저 떠오르기 쉬움  
- Redis 홈페이지는 AI 앱용 실시간 컨텍스트 엔진인 Redis Iris를 전면에 내세우지만, Redis가 수익을 내야 하는 회사라는 점에서는 이해 가능한 방향임  
- Redis를 배포하고 연결 문자열을 넘기면 처음에는 **신뢰할 수 있는 캐시**처럼 동작함  
  
### 몇 달 후 발생하는 문제  
- 시간이 지나면 `cache.set("key", "value")`가 `INSERT INTO table VALUES ('key', 'value')`보다 훨씬 단순해, 사람들이 Redis를 다음처럼 취급하기 시작함  
  - 항상 존재하는 구성 요소로, 데이터를 보존하는 장소. 사실상의 **데이터베이스**  
  - **REmote DIctionary Server**를 휘발성 캐시가 아닌 영구 저장소로 인식하게 됨  
- 당신도, 당신의 운영자팀 동료들도 이 사실을 모르며, 캐시를 휘발성으로 가정할 것 이라고 생각하기 때문에 **알림(alerting) 시스템**도 이를 감지하지 못함  
  - 업그레이드, 노드 이전, 또는 RAID0 서버 HDD 트레이가 빠지는 사고 등 Redis에 무언가를 했을 때 비로소 문제가 드러남  
- 핵심 문제는 Redis에 영속성 기능이 없다는 점이 아니라, **캐시로 도입된 Redis를 사람들이 캐시처럼 다루지 않는다**는 가정의 어긋남에 있음  
- 뒤늦게 의존성을 발견하면 Redis가 애플리케이션에 너무 깊게 엮여 제거하기 어렵고, 결국 “애완동물”처럼 **유지보수하고 모니터링**해야 함  
  
### memcached가 캐시 역할에 더 직접적인 이유  
- [memcached](https://memcached.org/)는 “무료 오픈소스, 고성능, **분산 메모리 객체 캐싱 시스템**”이며, 데이터베이스 부하를 줄여 동적 웹 애플리케이션을 빠르게 하기 위한 범용 캐시임  
- Django처럼 [플러그형 캐싱](https://docs.djangoproject.com/en/6.0/topics/cache/)을 지원하는 프레임워크에서는 캐싱 백엔드를 바꿀 수 있음  
- Redis보다 기능이 적어도 memcached를 선택할 만한 이유는 **운영 특성**이 단순하기 때문임  
  - **다운타임 처리**가 쉬움: 클라이언트 라이브러리가 연결 예외를 무시하는 경우가 많고, 단순 `get`은 서버가 내려가도 기본값이나 `None`을 반환할 수 있음  
  - memcached는 클러스터링 기능이 내장되어 있지 않아 오히려 **클러스터링**이 편리함  
    - 클라이언트 라이브러리에 여러 URL을 설정하면 키 해시로 대상 인스턴스를 고름  
    - 클라이언트 호출이 인스턴스 다운을 감지하면 [해셔에서 노드를 제거](https://pymemcache.readthedocs.io/en/latest/getting_started.html#using-a-memcached-cluster)하고, 일정 시간이 지난 뒤 자동으로 재연결을 시도함  
  - **영속성 부담**이 구조적으로 줄어듦: memcached는 디스크에 저장하지 않아 상태 없는 워크로드로 원하는 곳에 스케줄링하기 좋음  
- Redis로도 비슷한 운영 방식을 만들 수는 있지만, memcached의 아키텍처는 이런 방향에 더 가까워 **캐시로 다루기 직관적**임  
- memcached는 비교적 단순한 애플리케이션이고, 약 **64MB 캐시 크기의 인스턴스를 수십 개 실행해도 오버헤드가 거의 없다**는 점이 선택 이유가 됨  
- 많은 “데이터베이스가 느리다” 문제는 실제로 **느린 쿼리**나 누락된 인덱스에서 시작하므로, 캐시 추가와 함께 쿼리 최적화도 봐야 함  
- memcached의 설계 결정이 궁금하면 [memcached blog](https://memcached.org/blog)에서 흥미로운 글을 많이 볼 수 있는데, 그 중 하나는 5월에 올라온 [“답변 받는 데 정말 얼마나 걸리는 거죠?(How Long Does That Response Take… For Real?)”](https://memcached.org/blog/how-long-for-real/)임

## Comments



### Comment 60237

- Author: neo
- Created: 2026-06-24T09:39:37+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=48638886) 
- Redis는 훌륭한 기술이지만 **영속 데이터 구조**와 **휘발성 캐시**라는 서로 다른 두 역할을 동시에 잘하려다 어려움을 겪는다고 봄  
  실제 Redis에서도 둘은 잘 섞이지 않아서, 영속성은 전역으로 켜거나 끄는 식임  
  순수 캐시에는 memcached나 동등한 것을 쓰고, 점수판 같은 데이터 구조가 필요할 때만 영속성을 켠 Redis를 쓰겠음  
  $WORK에서는 둘 다 도입하지 않았고, 느린 작업용 캐시 계층은 파일시스템과 키-값 저장소처럼 쓰는 DB 테이블 양쪽에 데이터를 둠  
  DB는 thundering herd를 조율하는 데 도움이 되고, 같은 서버의 읽기는 파일시스템만 치며, 다른 서버의 읽기는 DB를 한 번 본 뒤 파일시스템에 유지함  
  파일시스템 계층을 memcached로 바꿀 수도 있지만 지금까지는 아주 잘 동작하고 있음
  - 2000년대 후반에 **Memcachedb**(memcache + 영속성용 bdb)를 다뤄본 뒤 거의 같은 결론에 도달했음  
    Redis가 기능은 확실히 더 많았고, antirez도 매력적이면서 놀랄 만큼 겸손한 인물이라 Redis가 더 인기 있어진 이유는 이해됨  
    그래도 내게 memcached는 항상 **지루한 기술을 선택하라**의 정점이었음  
    플랫폼 엔지니어로서는 둘 다 지원할 수 있지만, 개발자가 Redis의 고급 기능인 영속성, 복제, 클러스터링을 쓰기 시작하면 그 결정의 단점을 제대로 이해했는지 확인하려고 함
  - DB 테이블을 **키-값 저장소**처럼 쓰고 파일시스템을 곁들이는 것만으로도, 전용 캐시 저장소를 세팅하는 비용을 치르기 전에 할 수 있는 일이 정말 많음  
    이런 해법을 제안할 때마다 캐시는 반드시 전용 저장소에 있어야 한다고 느끼는 미숙한 사람들과 엔지니어링 현장에서 수없이 싸워왔음

- memcache라고 해서 이런 문제를 피할 수 있는 것은 전혀 아님  
  2000년대 중반에 memcache를 쓰는 확장 시스템을 다뤘는데, 개발자들이 글에서 Redis 사례로 든 문제와 똑같은 함정에 빠졌음  
  memcache로 분산 시스템의 법칙을 우회하려 했고, **캐시 중독** 때문에 memcache가 켜져 있다는 전제로 서버군 크기를 잡았다가 장애가 나면 갑자기 DDoS처럼 터졌음  
  어떤 호스트가 TPS가 높은 키를 날리면 다른 모든 호스트가 그 키를 다시 채우려고 의존 서비스를 때리는 **쓰기 증폭**도 있었고, 핫 키가 핫 호스트를 만들었으며 memcached를 서비스 데몬과 함께 올려서 정체불명의 CPU 스파이크로 이어졌음  
  오래된 DNS 항목의 고착성 때문에 memcache 호출이 블랙홀로 빠지기도 했음  
  모두 memcache를 더 잘 쓰면 피할 수 있었지만, 남용의 유혹이 너무 강했음

- 글쓴이가 언급한 Redis/Valkey 문제는 프로덕션에서 거의 다 본 것 같음  
  Valkey에 메모리 정책이 없어 메모리를 전부 먹고 append-only file 쓰기 오류를 만든 장애가 있었고, 디스크 자체가 꽉 차서 AOF 쓰기가 실패한 경우도 있었음  
  Redis가 살아 있고 실행 중이며 모든 사용자 데이터로 채워져 있다고 완전히 기대하면서, 느린 경로로 되돌아가는 장치가 없어 500 오류가 난 적도 있음  
  정렬 집합과 다른 데이터 구조를 창의적으로 쓰면서 그 집합이 절대 축출되지 않는다는 데 의존한 경우도 있었음  
  현장 관찰에도 불구하고 Redis보다 memcache를 먼저 추천하기는 여전히 어렵다고 봄  
  memcache 친화적인 캐시 배치를 갖도록 앱을 설계하는 일이 까다로울 수 있고, 충분히 큰 팀이 memcache를 쓰면 결국 Redis가 필요해지는 길을 찾을 가능성이 매우 높음  
  그러면 캐시 기술을 2개 유지해야 함
  - 누군가 Redis를 캐시가 아닌 용도로 쓰기로 하면 사실상 **캐시 기술 2개**를 가진 셈임  
    캐시용으로 설정한 Redis 인스턴스는 다른 목적에 쓸 수 없고, 캐시 인스턴스에는 축출이 있어야 하며 비캐시 인스턴스에는 축출이 없어야 함  
    결국 설정이 다른 두 번째 Redis가 필요함  
    솔직히 앱을 memcache 친화적인 캐시 배치로 설계하는 일은 Redis 친화적인 캐시 배치로 설계하는 것과 같음  
    이런 애플리케이션 캐시의 패턴은 동일해서, 가져오고 없으면 계산해서 설정하는 방식임
  - 이미 없다면 **추상화 인터페이스**를 만들어서, 키를 요청하면서 캐시 미스 때 원천에서 값을 가져올 비동기 함수나 람다를 넘기는 편임  
    `var value = cache.lookup(  
    keyname,  
    () => db.query(...),  
    TimeSpan.FromMinutes(5) // or CacheOptions  
    );`  
    이렇게 하면 캐시 미스 때 바로 대체 경로로 가거나 삽입할 수 있음
  - 캐시 기술 2개를 유지하지 않는다는 건 언제나 이기는 논리임

- memcache에서 잘 언급되지 않는 또 다른 특징은 모든 연산이 설계상 **O(1)** 이라는 점임  
  저자들이 의식적으로 고른 설계라 제약은 있지만, 단순 연산에서 무작위로 멈추는 일이 없도록 보장함  
  반면 Redis는 단일 스레드 코어 설계라 임의 복잡도의 연산을 실행할 수 있고, 개발자 입장에서는 그걸 쓰며 똑똑해진 느낌이 들겠지만 그 연산이 끝날 때까지 나머지가 모두 기다리게 됨

- 오픈소스 프로젝트나 장기 유지되는 프로그램에서는 이런 일이 자주 생김  
  코드베이스가 커지면 원래 계획에 없던 것들을 결국 지원하기 시작함  
  기능이 많아지면 사용자도 늘고, 어떤 사람은 예전 기능만 쓰고 어떤 사람은 새 기능을 받아들이며, 결국 특정 값이 사실상의 기본값이 되어 더는 선택 사항처럼 보이지 않게 됨  
  Redis를 예로 들면 AOF를 끄면 휘발성 인메모리 캐시로 동작하지만, 대부분은 그렇게 생각하지도 않음  
  그래서 기능이 적고 단순한 편이 낫다는 논리가 나오고, 이 맥락에서 Memcached가 그런 **구속복식 접근**의 예임  
  큰 팀에는 완전히 말이 되지만, 오픈소스 프로젝트는 자금이나 기여를 계속 얻으려면 정기적인 업데이트가 필요하니 내재된 긴장이 있음  
  때로는 한 틈새 영역에 특화된 포크나 파생 프로젝트로 이어짐  
  개인적으로는 정답이 없고 맥락에 달렸다고 봄  
  커뮤니케이션 자체도 공짜가 아니기 때문임
  - 커뮤니케이션이 공짜가 아니라는 점이 **마이크로서비스**에 대해 내가 가진 문제임  
    개발자들이 이걸 전혀 모르는 것처럼 보임
  - 가장 명확한 예는 사람들이 Redis가 충돌이나 종료 때 데이터를 잃는 캐시로만 동작한다고 생각하는 것임  
    Memcached를 Redis로 바꾸면서 똑같은 것을 기대했기 때문이라고 봄
  - 대규모에서 **AOF**는 장애를 일으키므로 꺼버리게 됨  
    그래도 훌륭한 캐시이긴 함

- 지난 몇 년 동안 Flask 작업을 꽤 했고, 풀타임은 아니지만 작은 전자상거래 사업의 기술 스택 일부로 써왔음  
  MongoEngine, SQLAlchemy, Celery, Google/eBay/Shopify용 Python 스택에서는 온갖 발밑 지뢰와 이상함을 겪었지만 Redis에서는 그런 적이 없음  
  아마 Redis를 영속 저장소라고 생각하는 아무에게나 관리자 권한을 주지 않아서일 수도 있지만, 솔직히 Redis는 **매우 견고하고 잘 설계된 기술**이라고 표현하고 싶음  
  API는 극도로 단순하고, 조금 이상한 일을 해야 할 때마다 합리적이고 잘 생각된 방법이 있음
  - 지금 Flask, SQLAlchemy, Celery로 프로젝트를 시작하는 중인데, 왜 **Celery**를 피해야 하는지와 대신 무엇을 써야 하는지 더 듣고 싶음
  - 내 세계에서 memcached와 Redis 같은 캐시 시스템은 그냥 넣고 가져오는 캐시임  
    태깅 같은 무효화 시스템을 쓸 수는 있겠음  
    캐시 시스템으로 할 수 있는 이상한 일이 무엇인지, 단순히 데이터를 캐싱하는 것 말고 사람들이 캐시로 무엇을 하는지 진심으로 궁금함

- memcached를 좋아하지만, Redis를 휘발성 캐시로 설정해놓고 사람들이 **영속 데이터 저장소**처럼 다룬다면 그건 Redis 탓이 아님  
  memcached도 영속적이지 않다는 점에서 비교가 특히 이상함
  - 많은 회사, 아마 대부분에서 Redis는 언제든 사라져도 되는 캐시가 아니라 실제 **내구성 있는 프로덕션 데이터베이스**로 인식되고 그렇게 운영됨  
    별도로 말해주지 않는다면 새 개발자가 그렇게 가정하는 것도 무리는 아님

- Memcached는 출시 당시 캐싱의 구원자였음  
  2003년에 Brad Fitzpatrick이 LiveJournal을 위해 만들었다는 점도 좋음  
  사용자 피드의 각 게시물마다 접근 제한이 다를 수 있었고, 덕분에 게시물이나 전체 페이지를 캐시할 수 있었음  
  Ruby on Rails와 함께 여러 해 썼고, 페이지가 빨라졌으며 그냥 잘 동작했음  
  단점이자 속도 측면의 장점은 캐시가 디스크가 아니라 **메모리**에 저장된다는 점이었음  
  캐시해야 할 데이터가 넓고 대규모 사이트라면 호스팅 비용이 비싸질 수 있음  
  그런 경우에는 Solid Cache가 내게 구원자였음  
  지금 작업 중인 프로젝트에는 캐시가 100GB 넘게 있고, PostgreSQL 디스크에 저장되며 인덱스로 빠르게 조회하고 Rails가 자동으로 만료를 처리해 해당 행을 지움  
  캐시 규모가 더 작고 이미 Redis를 쓰고 있다면 아마 그냥 Redis를 쓸 것 같음  
  하지만 속도가 1순위라면 Memcached와 Redis를 벤치마크해 보겠음

- memcached가 일시적이라는 점과, 사람들이 그것을 영속적인 것처럼 쓸지 여부는 별개의 문제임  
  캐시 적중률이 99.9%처럼 보이고 항상 존재한다면, 조만간 누군가는 그 동작에 의존하는 코드를 작성하게 됨  
  개발 모드에서는 클라이언트 라이브러리가 10% 정도 null을 반환하도록 도와줄 수도 있지 않을까 싶음

- memcached는 단순한 **키-값 캐시** 작업에서 Redis보다 말도 안 되게 빠름  
  스레드가 있고, 한 가지 일을 아주 잘하도록 고도로 최적화되어 있음  
  반면 Redis는 모든 데이터 구조와 단일 스레드 등을 가진 임의의 공유 Python 힙 같은 느낌에 더 가까움  
  Notion에서는 Redis를 여러 용도로 쓰지만, 실제 캐싱은 memcached에 맡김
  - 키-값에서는 그렇게까지 빠르지 않다는 점을 확인할 수 있음  
    읽기당 평균 **300마이크로초 대 350마이크로초** 정도임  
    단일 스레드라는 점도 크게 중요하지 않은데, CPU 병목이 아니라 반응형 입출력이기 때문임
  - 스레드는 공짜가 아님  
    더 많은 CPU 코어를 쓰게 해주지만, 부하가 그리 높지 않다면 단일 스레드 memcached가 다중 스레드보다 CPU를 덜 씀
