PHpullh
개발자 면접 준비/시스템 디자인

시스템 디자인

캐시 설계 면접: 무엇을 얼마나 오래 어디에 둘 것인가

캐시를 성능 장치가 아니라 정합성 계약으로 설명하는 방법입니다. 배치와 수명, 무효화, 무너지는 순간까지 순서대로 다룹니다.

캐시 질문이 실제로 재는 것

면접에서 “트래픽이 늘면 어떻게 하시겠습니까”라고 물었을 때 “캐시를 붙이겠습니다”는 답이 되지 않습니다. 캐시를 모른다고 생각해서 묻는 것이 아니기 때문입니다. 이 질문이 재는 것은 캐시를 넣은 뒤에 생기는 새로운 문제들을 미리 아는가입니다. 캐시는 읽기 지연을 줄여 주는 대신 두 벌의 진실을 만듭니다. 그 순간부터 “이 값이 지금 맞는 값인가”라는 질문이 시스템 전체에 붙습니다.

그래서 캐시를 설명할 때는 순서가 정해져 있습니다. 무엇이 느린지 먼저 말하고, 그 느린 것 중 캐시해도 되는 부분을 고르고, 어디에 둘지 정하고, 언제까지 유효한지 정하고, 누가 어떻게 지울지 정하고, 마지막으로 캐시가 없을 때 시스템이 버티는지 확인합니다. 이 여섯 단계 중 하나라도 건너뛴 답은 면접관 입장에서 붙잡을 곳이 생깁니다.

특히 마지막 항목이 중요합니다. 캐시는 언젠가 비워집니다. 배포로 프로세스가 재시작되거나, 캐시 서버가 한 대 빠지거나, 키 스키마를 바꿔서 전부 미스가 나는 날이 반드시 옵니다. 그때 원본이 버티지 못한다면 그 시스템은 캐시로 성능을 얻은 것이 아니라 캐시에 생존을 의탁한 것입니다. 이 구분을 말로 표현할 수 있으면 캐시 질문의 절반은 넘어간 셈입니다.

연습 문제: 상품 상세 응답을 캐시하세요

커머스 서비스입니다. 상품 상세 페이지가 초당 수천 건 조회되고, 응답을 만들려면 상품 기본 정보, 재고, 가격, 판매자 정보, 리뷰 요약을 각각 조회해야 합니다. 데이터베이스 부하가 한계에 가까워졌습니다. 어떻게 하시겠습니까.

이 문제를 고른 이유는 한 응답 안에 성격이 완전히 다른 데이터가 섞여 있기 때문입니다. 상품명과 설명은 며칠에 한 번 바뀌고, 가격은 하루에 몇 번 바뀌며, 재고는 초 단위로 바뀝니다. “상품 상세를 캐시하겠습니다”라고 한 덩어리로 답하는 순간 가장 자주 바뀌는 재고에 수명이 맞춰지고, 그러면 캐시가 거의 아무것도 하지 않게 됩니다.

그래서 첫 문장은 이렇게 나와야 합니다. “한 응답으로 보이지만 안에 갱신 주기가 다른 다섯 조각이 있으니, 캐시 단위를 응답이 아니라 조각으로 잡겠습니다.” 캐시 설계에서 가장 먼저 하는 일은 무효화 주기가 같은 것들끼리 묶는 것입니다.

첫 번째 갈래 · 누가 캐시를 채우는가

배치를 정했으면 채우는 주체를 정합니다. 실무에서 쓰이는 방식은 크게 두 갈래입니다.

캐시 어사이드는 애플리케이션이 먼저 캐시를 보고, 없으면 원본에서 읽어 캐시에 넣는 방식입니다. 캐시가 죽어도 애플리케이션은 느려질 뿐 계속 동작하고, 캐시할 값과 하지 않을 값을 코드에서 자유롭게 고를 수 있습니다. 대신 미스 처리 코드가 조회 지점마다 흩어지고, 방금 쓴 값이 아직 캐시에 없어서 한 번은 반드시 미스가 납니다.

라이트 스루는 쓰기 시점에 캐시와 원본을 함께 갱신하는 방식입니다. 쓰기 직후 곧바로 읽히는 데이터에서는 첫 미스를 없애 줍니다. 문제는 쓰기 경로가 캐시에 묶인다는 점입니다. 캐시가 응답하지 않으면 쓰기까지 흔들리고, 아무도 읽지 않을 값까지 미리 캐시에 채우게 됩니다. 그리고 두 저장소에 순서대로 쓰는 이상 중간에 실패하면 두 값이 갈라집니다.

이 문제에서는 조회가 쓰기보다 압도적으로 많고, 조회 조합이 다양하며, 캐시 없이도 서비스가 되어야 하므로 기본은 캐시 어사이드가 맞습니다. 다만 가격처럼 “바꾸자마자 확인 화면에서 곧바로 읽는” 데이터는 갱신 직후 캐시를 채워 두는 편이 사용자 경험에 낫습니다. 면접에서는 이렇게 두 방식을 한 시스템 안에서 데이터 성격별로 나눠 쓴다고 말할 수 있으면 충분히 좋은 답입니다.

TIP

쓰기 경로에서 캐시를 새 값으로 갱신하는 것보다 그냥 삭제하는 편이 안전합니다. 두 요청이 거의 동시에 쓰면 캐시에 늦게 도착한 옛 값이 남을 수 있는데, 삭제는 그런 역전이 생기지 않습니다. 다음 읽기가 원본에서 최신 값을 가져오면 됩니다.

두 번째 갈래 · 수명을 시간으로 끊을 것인가 사건으로 끊을 것인가

TTL은 “이 값은 얼마나 낡아도 괜찮은가”를 시간으로 선언하는 방법입니다. 장점은 아무도 무효화를 호출하지 않아도 언젠가는 반드시 회복된다는 점입니다. 무효화 코드를 빠뜨린 경로가 있어도, 캐시를 지우는 이벤트가 유실되어도, TTL이 지나면 시스템은 스스로 정상으로 돌아옵니다. 그래서 TTL은 성능 장치가 아니라 안전망이고, 명시적 무효화를 하더라도 반드시 함께 둡니다.

명시적 무효화는 “값이 바뀌었다는 사건이 발생하면 그 즉시 지운다”입니다. 가격, 권한, 공개 여부처럼 낡은 값이 곧바로 사고가 되는 데이터에는 필수입니다. 대신 비용이 있습니다. 한 값이 바뀔 때 그 값이 들어간 모든 캐시 키를 알아야 합니다. 상품 하나의 가격이 바뀌면 상품 상세 캐시뿐 아니라 카테고리 목록 캐시, 검색 결과 캐시, 장바구니 요약 캐시가 함께 낡습니다. 이 목록을 관리하지 못하면 무효화는 반쯤만 동작합니다.

그래서 실무의 답은 대부분 조합입니다. 재고처럼 초 단위로 바뀌고 조금 틀려도 되는 값은 아주 짧은 TTL만 두고 무효화를 하지 않습니다. 가격처럼 정확해야 하는 값은 중간 길이 TTL에 쓰기 경로 삭제를 붙입니다. 상품 설명처럼 거의 안 바뀌는 값은 긴 TTL을 주고, 편집이 일어나면 지웁니다. 각 조각에 다른 답을 줄 수 있다는 것이 조각 단위로 나눈 보람입니다.

CACHE-ASIDE · 읽기 · 쓰기 · 무효화

# 읽기 경로: 캐시 어사이드 + 지터 TTL + 부재 캐시 + 스탬피드 잠금
def get_product(pid):
    key = "product:v3:" + str(pid)     # v3 = 값 형식이 바뀌면 올리는 버전 태그

    hit = cache.get(key)
    if hit is not None:
        # 존재하지 않는 상품도 캐시된다. 없는 키 폭격이 DB로 새지 않는다.
        return None if hit == MISSING else decode(hit)

    # 만료 순간 수천 요청이 동시에 DB로 몰리는 것을 막는 키 단위 짧은 잠금
    token = new_token()
    if not cache.set_if_absent("lock:" + key, token, ttl_sec=3):
        sleep(0.05)
        return get_product(pid)        # 잠깐 기다렸다가 캐시를 다시 본다

    try:
        row = db.query_one("SELECT id, name, price FROM products WHERE id = ?", pid)
        if row is None:
            cache.set(key, MISSING, ttl_sec=30)          # 부재는 짧게만
            return None
        # 만료 시각을 흩어 놓아 동시 만료로 인한 스탬피드를 예방한다
        cache.set(key, encode(row), ttl_sec=jitter(base=300, spread=60))
        return row
    finally:
        cache.delete_if_owner("lock:" + key, token)


# 쓰기 경로: 원본은 항상 DB. 캐시는 갱신하지 않고 삭제한다.
def update_price(pid, new_price):
    with db.transaction():
        db.execute("UPDATE products SET price = ? WHERE id = ?", new_price, pid)
        cat = db.query_value("SELECT category_id FROM products WHERE id = ?", pid)

    # 이 값이 들어간 모든 키를 지운다. 목록을 문서로 관리하지 않으면 반드시 샌다.
    cache.delete("product:v3:" + str(pid))
    cache.delete("product:list:cat:" + str(cat))
    cache.delete("product:price:" + str(pid))


# 상품 생성 시: 부재 캐시를 남겨 두면 새 상품이 30초간 없는 것처럼 보인다
def create_product(row):
    pid = db.insert_returning_id("INSERT INTO products ... ", row)
    cache.delete("product:v3:" + str(pid))
    return pid

이 코드에서 면접 대화가 나올 지점은 네 곳입니다. 키에 붙은 버전 태그, 삭제 대신 갱신하지 않는 쓰기, 부재 캐시, 그리고 잠금입니다. 버전 태그는 저장 형식을 바꿀 때 전체를 지우지 않고 새 키 공간으로 넘어가기 위한 장치입니다. 배포 도중 옛 코드와 새 코드가 같은 키를 서로 다른 형식으로 읽고 쓰는 사고를 이 한 글자가 막아 줍니다.

캐시가 무너지는 세 가지 순간

캐시 질문의 난이도는 대개 여기서 갈립니다. 잘 도는 상태를 설명하는 것은 누구나 하고, 무너지는 상태를 먼저 꺼내는 사람이 드물기 때문입니다.

스탬피드는 인기 있는 키가 만료되는 순간 그 키를 기다리던 요청 수천 개가 동시에 원본으로 쏟아지는 현상입니다. 평소에는 초당 한 건이던 질의가 순간적으로 수천 건이 되고, 데이터베이스가 느려지면 응답이 늦어지고, 늦어진 만큼 대기 요청이 더 쌓입니다. 대응은 세 가지를 겹쳐 씁니다. 만료 시각에 지터를 섞어 한꺼번에 만료되지 않게 하고, 키 단위 잠금으로 원본을 읽는 요청을 하나로 줄이고, 만료된 값을 잠깐 그대로 내보내면서 뒤에서 갱신합니다. 마지막 방법은 “조금 낡은 값을 주는 것이 오류를 주는 것보다 낫다”는 제품 판단이 있어야 쓸 수 있습니다.

캐시 침투는 존재하지 않는 키를 계속 조회하는 상황입니다. 캐시에 없으니 매번 미스가 나고, 원본에도 없으니 캐시에 채울 것도 없어서 모든 요청이 그대로 데이터베이스에 도달합니다. 삭제된 상품 링크가 외부에 남아 있거나, 누군가 무작위 아이디를 훑을 때 생깁니다. 대응은 부재 자체를 짧은 TTL로 캐시하는 것입니다. 이때 반드시 함께 말해야 하는 것은 부작용입니다. 부재를 캐시해 두면 방금 만든 리소스가 잠깐 없는 것처럼 보이므로, 생성 시점에 부재 캐시를 지워야 합니다.

핫 키는 한 키에 트래픽이 몰려 그 키를 담당하는 캐시 노드 하나만 포화되는 현상입니다. 캐시를 여러 대로 늘려도 그 키의 위치는 변하지 않으므로 증설이 답이 되지 않습니다. 이럴 때는 애플리케이션 프로세스 안에 아주 짧은 수명의 로컬 캐시를 한 겹 더 두어 공유 캐시 호출 자체를 줄입니다. 다만 로컬 캐시는 인스턴스마다 값이 다를 수 있고 밖에서 지울 수 없으므로, 수명은 초 단위로 짧게 잡아야 합니다.

WARNING

캐시 장애를 대비한다면서 “캐시가 죽으면 원본으로 폴백한다”고만 답하면 위험합니다. 캐시가 흡수하던 트래픽이 전부 원본으로 가면 원본이 곧바로 무너집니다. 폴백에는 반드시 제한이 따라야 합니다. 원본 동시 질의 수를 제한하거나, 일부 요청은 축약된 응답이나 오류로 흘려보내겠다고 말해야 답이 완성됩니다.

낡은 데이터는 버그가 아니라 결정입니다

캐시를 넣는 순간 사용자는 언젠가 낡은 값을 봅니다. 이것을 없앨 수는 없고, 어디까지 허용할지 정할 수 있을 뿐입니다. 그래서 좋은 답은 “정합성을 지키겠습니다”가 아니라 “이 화면은 최대 몇 초까지 낡아도 되는지”를 데이터별로 말하는 답입니다.

이 문제로 돌아오면 이렇게 정리됩니다. 상품 설명이 10분 낡아도 사고가 아닙니다. 리뷰 요약 점수가 1분 낡아도 아무 일도 일어나지 않습니다. 재고 수량이 몇 초 낡는 것은 허용하되, 실제 차감은 주문 시점에 원본에서 다시 확인합니다. 가격은 표시가 낡을 수 있지만 결제 금액은 반드시 원본 기준으로 계산합니다. 즉 “보여 주는 값”과 “돈이나 재고를 움직이는 값”을 분리하는 것이 핵심입니다. 화면은 캐시가 담당하고, 결정은 원본이 담당합니다.

이 문장을 면접에서 말할 수 있으면 캐시를 성능 최적화로만 이해한 사람과 확실히 구분됩니다. 관련해서 데이터 자체를 어떻게 나눌지는 데이터 모델링 면접 가이드에서, 캐시 앞뒤의 트래픽 처리는 확장 가능한 서비스 설계에서 이어집니다.

같은 질문, 두 개의 답

앞의 연습 문제에 대한 두 답을 나란히 놓겠습니다.

약한 답 — “상품 상세 조회가 느리니까 앞에 캐시를 두겠습니다. 조회할 때 캐시를 먼저 보고 없으면 DB에서 읽어서 캐시에 넣습니다. TTL은 5분 정도 주고, 데이터가 바뀌면 캐시를 지웁니다. 이러면 DB 부하가 크게 줄어들 겁니다.”

강한 답 — “먼저 문제를 다시 정리하겠습니다. 상세 응답 하나를 만들 때 조회가 다섯 번 일어나고 그중 무엇이 부하의 대부분인지 아직 모릅니다. 우선 질의별 호출량과 소요 시간을 확인해 상위 두 개를 대상으로 잡겠습니다.

가정을 말씀드리면, 조회가 쓰기보다 훨씬 많고 캐시가 없어도 서비스는 계속되어야 한다고 보겠습니다. 그러면 방식은 세 가지가 후보입니다. 응답 전체를 통째로 캐시하는 방법, 조각별로 캐시하는 방법, 데이터베이스 앞에 읽기 복제본을 늘리는 방법입니다. 응답 통째 캐시는 구현이 가장 쉽지만 수명이 가장 자주 바뀌는 재고에 맞춰지므로 적중률이 낮습니다. 읽기 복제본은 정합성 고민이 적지만 비용이 선형으로 늘고 지연을 근본적으로 줄이지는 못합니다. 그래서 조각별 캐시 어사이드를 기본으로 고르겠습니다.

조각은 갱신 주기로 묶습니다. 상품 기본 정보와 판매자 정보는 TTL 10분에 편집 시 삭제, 가격은 TTL 1분에 쓰기 경로 삭제, 리뷰 요약은 TTL 5분에 무효화 없음, 재고는 TTL 5초로 두고 표시용으로만 씁니다. 실제 재고 차감과 결제 금액 계산은 캐시를 보지 않고 원본에서 다시 읽겠습니다.

무너지는 경우도 같이 막겠습니다. 인기 상품 키가 동시에 만료되지 않도록 TTL에 지터를 주고, 미스 시 키 단위 잠금으로 원본 질의를 하나로 줄이겠습니다. 없는 상품 아이디를 반복 조회하는 트래픽에 대비해 부재를 30초 캐시하고, 상품 생성 시 그 키를 지우겠습니다. 캐시 전체가 비는 상황에 대비해 원본 동시 질의 수에 상한을 두고, 초과분은 축약 응답으로 내리겠습니다.

여기서 받아들이는 대가는 명확합니다. 코드가 복잡해지고 무효화해야 할 키 목록을 계속 관리해야 합니다. 그 대신 데이터별로 낡음의 허용치를 다르게 줄 수 있고, 캐시가 없어도 서비스가 죽지 않습니다. 적중률과 원본 질의 수를 지표로 보면서 TTL을 조정하겠습니다.”

강한 답이 이긴 이유

강한 답이 나은 이유는 용어를 더 많이 써서가 아닙니다. 실제로 등장한 개념 수는 크게 다르지 않습니다. 차이는 말하는 순서에 있습니다.

첫째, 강한 답은 문제를 다시 정리하는 문장으로 시작합니다. “다섯 번 조회 중 무엇이 부하인지 아직 모른다”는 한 문장이 그 뒤 모든 결정을 측정 위에 올려놓습니다. 약한 답은 “느리니까 캐시”로 곧장 건너뛰어서, 만약 실제 병목이 리뷰 집계 하나였다면 나머지 작업이 전부 헛수고가 됩니다.

둘째, 강한 답은 가정을 소리 내어 말합니다. 조회가 쓰기보다 많다는 것, 캐시 없이도 서비스가 되어야 한다는 것을 명시했기 때문에 캐시 어사이드를 고른 이유가 자동으로 따라옵니다. 약한 답에도 캐시 어사이드가 나오지만 왜 그것인지가 없으므로, 면접관이 “쓰기가 더 많으면요”라고 물으면 답이 무너집니다.

셋째, 강한 답은 후보를 세 개 늘어놓고 각각을 탈락시킵니다. 응답 통째 캐시가 왜 안 되는지, 읽기 복제본이 왜 부족한지 말한 뒤에 남은 것을 고릅니다. 이 과정이 있어야 선택이 취향이 아니라 판단으로 읽힙니다.

넷째, 강한 답은 자기가 받아들인 대가를 스스로 이름 붙입니다. 무효화 키 목록 관리라는 비용을 먼저 꺼내 놓았기 때문에, 면접관이 그 지점을 찔러도 이미 알고 고른 것이 됩니다. 약한 답에는 대가가 하나도 없습니다. 세상에 공짜 개선은 없으므로, 대가가 언급되지 않은 답은 아직 끝까지 생각하지 않은 답으로 읽힙니다. 요약하면 강한 답은 문제 재진술, 가정 명시, 후보 비교, 대가 수용의 순서를 지켰고 약한 답은 결론 하나만 던졌습니다.

면접관이 이어서 던지는 질문

위 답을 마치면 대화는 보통 이렇게 이어집니다. 각 질문이 무엇을 확인하려는 것인지와 함께 정리했습니다.

TTL 값은 어떻게 정하셨나요?

숫자 자체는 중요하지 않고 근거가 중요합니다. “이 데이터가 몇 초 낡으면 사용자가 손해를 보는가”와 “TTL을 두 배로 늘리면 적중률이 얼마나 오르는가” 두 축으로 설명하면 됩니다. 처음에는 짧게 시작해 적중률을 보며 늘리겠다고 말하는 편이, 처음부터 확신에 찬 숫자를 대는 것보다 낫습니다.

캐시와 DB가 어긋나면 어떻게 알아차리나요?

이 질문은 캐시를 관측 대상으로 보는지를 확인합니다. 적중률, 원본 질의 수, 키별 만료 분포를 지표로 두고, 주기적으로 표본을 뽑아 캐시 값과 원본 값을 비교하는 점검 작업을 두겠다고 답합니다. 어긋남을 영원히 막을 수는 없으므로 빨리 발견하고 짧게 되돌리는 쪽으로 말하는 것이 정직합니다.

캐시를 지웠는데 옛 값이 계속 보이면요?

계층을 하나씩 짚는지를 봅니다. 브라우저 캐시, CDN, 애플리케이션 로컬 캐시, 공유 캐시 순서로 확인하고, 회수할 수 없는 계층에는 애초에 긴 수명을 주지 않았다고 설명하면 좋습니다. 정적 자산이라면 파일 이름에 해시를 넣어 아예 다른 주소로 만드는 방법도 함께 말할 수 있습니다.

목록 조회 결과도 캐시해도 되나요?

단건 캐시와 목록 캐시의 차이를 아는지를 봅니다. 목록은 조건 조합이 많아 키가 폭발하고, 항목 하나만 바뀌어도 그 항목이 포함된 모든 목록이 낡습니다. 그래서 목록은 캐시 대상이 아니라 아이디 목록만 짧게 캐시하고 본문은 단건 캐시에서 채우는 방식을 쓴다고 답하면 깊이가 드러납니다.

로그인한 사용자별 응답은 어떻게 하나요?

개인화된 응답을 공유 캐시에 넣는 것이 왜 위험한지 말해야 합니다. 키에 사용자 식별자가 빠지면 다른 사람의 데이터가 노출됩니다. 개인화 조각과 공용 조각을 나누고, 공용 부분만 공유 캐시에 두겠다고 답하는 것이 안전합니다. 이 지점에서 실수하면 성능 문제가 아니라 보안 사고가 됩니다.

캐시 서버를 늘리면 성능이 그만큼 좋아지나요?

선형 확장을 당연하게 말하는지 확인하는 질문입니다. 부하가 고르게 퍼져 있으면 도움이 되지만 핫 키가 있으면 증설이 효과가 없다는 점, 노드를 추가할 때 키 재배치로 대량 미스가 발생할 수 있다는 점을 짚어야 합니다.

자주 나오는 실수

이 주제에서 실제로 답이 나빠지는 지점은 정해져 있습니다.

가장 흔한 것은 캐시를 넣는 이유를 측정 없이 말하는 것입니다. “느리니까 캐시”라고 하면 무엇이 느린지 모른 채 대책을 정한 것이 되어, 뒤이어 “적중률이 20%밖에 안 나오면요”라는 질문에 답할 근거가 없습니다.

두 번째는 무효화를 한 줄로 처리하는 것입니다. “데이터가 바뀌면 캐시를 지웁니다”는 문장은 지울 키를 전부 안다는 전제를 숨기고 있습니다. 실제로는 한 값이 여러 키에 복사되어 있어서, 무효화는 설계에서 가장 손이 많이 가는 부분입니다. 이 어려움을 언급하지 않으면 캐시를 운영해 본 적이 없다는 인상을 줍니다.

세 번째는 캐시가 비는 상황을 생각하지 않는 것입니다. 배포, 장애, 키 형식 변경은 정기적으로 일어납니다. 그때 원본이 버티는지 확인하지 않은 설계는 평상시에만 동작하는 설계입니다.

네 번째는 정합성을 절대적인 목표로 말하는 것입니다. “캐시를 써도 항상 최신 값을 보장하겠습니다”라고 하면 그 순간 캐시가 아니라 원본을 매번 읽겠다는 말이 됩니다. 낡음을 허용 범위로 다루지 못하면 대화가 더 진행되지 않습니다.

다섯 번째는 캐시를 상태 없는 부품처럼 취급하는 것입니다. 캐시에는 크기 한계가 있고 축출 정책이 있으며, 메모리가 차면 TTL이 남아 있어도 값이 사라집니다. “TTL 안에는 반드시 있다”를 전제로 짠 로직은 언젠가 틀립니다.

마지막은 개인 정보를 공유 캐시에 담는 것입니다. 앞의 후속 질문에서 다뤘듯이 이건 성능 실수가 아니라 사고입니다. 캐시 키에 어떤 축이 들어가야 하는지 먼저 적는 습관을 들이면 대부분 예방됩니다.

준비 체크리스트

  • 지금 다루는 서비스에서 캐시할 만한 데이터 다섯 개를 고르고, 각각 몇 초까지 낡아도 되는지 숫자로 적어 보십시오.
  • 그 다섯 개에 대해 캐시 키 이름을 실제로 지어 보고, 키에 들어가야 할 축(사용자, 지역, 버전)을 빠짐없이 넣었는지 확인하십시오.
  • 값 하나가 바뀔 때 지워야 할 키 목록을 종이에 적어 보십시오. 세 개를 넘어가면 캐시 단위를 잘못 잡은 신호일 수 있습니다.
  • 캐시 어사이드 읽기 함수를 직접 손으로 작성하고, 미스·부재·잠금 실패 세 경로가 모두 있는지 확인하십시오.
  • “캐시가 지금 전부 비었다면 원본이 버티는가”라는 질문에 숫자로 답할 수 있는지 점검하십시오.
  • 스탬피드, 침투, 핫 키 세 가지를 각각 한 문장으로 정의하고 대응을 한 문장씩 붙여 소리 내어 말해 보십시오.
  • 표시용 값과 결정용 값을 나누는 기준을 자기 언어로 설명해 보십시오. 결제·재고·권한이 결정용에 들어가는 이유까지 말할 수 있어야 합니다.
  • 5분 타이머를 켜고 위 연습 문제에 답한 뒤, 문제 재진술·가정·후보 비교·대가 네 가지가 모두 나왔는지 스스로 채점하십시오.

캐시는 혼자 존재하지 않습니다. 계약이 어떻게 생겼는지에 따라 캐시할 수 있는 범위가 달라지므로 API 설계 면접을 함께 보시고, 비동기 처리와 큐가 얽히는 부분은 언어별 비동기 처리 비교로 감각을 잡으시기 바랍니다. 전체 흐름은 백엔드 개발 로드맵과 면접 준비 목록에 정리되어 있습니다.

관련 언어 학습으로 복습하기