세션과 메모리 캐시를 엮어 콜백 인증 데이터를 안전하게 지키는 방법

김민석·2025년 10월 9일
0

Tech Deep Dive

목록 보기
24/58

Intro

  • 저는 본인확인 콜백을 다루면서 두 번이나 세션이 비는 사고를 맞았어요.
  • 브라우저는 GET으로, 일부 모바일 브라우저는 POST로 돌아오고, 로드밸런서는 세션을 가끔 잊어버리더군요.
  • 그래서 세션만 믿지 말고 메모리 캐시를 함께 쓰는 하이브리드 전략을 직접 설계했습니다.

핵심 아이디어 요약

  • 토큰 기준으로 세션과 프로세스 메모리에 동시에 데이터를 저장합니다.
  • 콜백이 들어오면 메모리 캐시를 먼저 확인하고, 없으면 세션을 폴백합니다.
  • 1시간짜리 만료 타이머를 두어 인증 정보가 무한정 남지 않도록 합니다.

준비와 선택

  • 로드밸런서(ALB) 뒤에서 세션 스티키가 잘 걸리지 않는다는 걸 인정하고, 세션만으로는 불안하다는 결론을 냈습니다.
  • Redis까지 들고 오기엔 과한 상황이라, 최소한의 안전장치로 Node.js 프로세스 메모리를 활용하기로 했습니다.
  • 토큰 만료를 자동으로 돌리기 위해 setInterval 기반 청소 루틴을 추가했습니다.

구현 여정

  • Step 1: 토큰 저장 구조 정의
    tokenStorage라는 Map을 만들고, 복호화를 위해 필요한 key, iv, hmac_key, req_no를 묶어 저장합니다.
  • Step 2: 만료 타이머 설정
    1시간(3,600초)을 상수로 두고, 매분 실행되는 청소 루틴을 붙였습니다. 덕분에 메모리 누수 걱정을 덜었죠.
const TOKEN_EXPIRE_TIME = 60 * 60 * 1000; // 1시간
setInterval(() => {
  const now = Date.now();
  for (const [token_version_id, data] of tokenStorage.entries()) {
    if (now - data.created_at > TOKEN_EXPIRE_TIME) {
      tokenStorage.delete(token_version_id);
      console.log(`만료된 토큰 삭제: ${token_version_id}`);
    }
  }
}, 60000);
  • Step 3: 발급 시 이중 저장
    토큰을 발급할 때 세션과 tokenStorage에 동시에 넣습니다. 이중화 덕분에 콜백이 다른 노드로 튀더라도 최소한 한 곳에서 데이터를 건질 수 있습니다.
  • Step 4: 콜백 처리에서 폴백 순서 설계
    /checkplus_success에서는 먼저 메모리 캐시를 확인하고, 없을 때만 세션으로 내려갑니다. 로그를 남겨 두 경로 중 어떤 것을 탔는지 추적했습니다.
const tokenData = tokenStorage.get(token_version_id);
let key: string, iv: string, hmac_key: string, req_no: string;

if (tokenData) {
  ({ key, iv, hmac_key, req_no } = tokenData); // 캐시 히트
} else {
  key = req.session.key || ""; // 세션 폴백
  iv = req.session.iv || "";
  hmac_key = req.session.hmac || "";
  req_no = req.session.req_no || "";
}
  • Step 5: 디버깅 로그와 정리
    무결성 검증에 실패하면 자세한 로그를 남기고, 성공하면 세션 값을 정리했습니다. 세션 누수로 인한 이상 동작을 막는 마지막 장치였습니다.
  • 캐시 청소 주기가 너무 짧은 건 아닌지 확인하려고, 저는 GPT에게 시뮬레이션 로직을 물어봤고 10분 주기로도 충분하지만 1시간이 사용자 경험상 든든하다는 판단을 다시 확인했습니다.

결과와 회고

  • 세션만 쓸 때 겪었던 "토큰을 찾을 수 없습니다" 오류가 현저히 줄어들었습니다.
  • 요청마다 저장소 상황을 로그로 남겨두니, 운용 중 문제를 재현하기도 쉬워졌습니다.
  • 다만 여러 프로세스나 서버로 스케일 아웃하면 Map만으로는 부족하니, 다음에는 Redis나 DynamoDB 같은 외부 스토리지를 연동할 예정입니다.
  • 여러분은 콜백 인증 데이터를 어디에 저장하시나요? 로컬 세션을 계속 쓰는지, 아니면 별도 캐시를 두고 계신지 궁금합니다.

Reference

profile
동업자와 함께 창업 3년차입니다. Nextjs 위주의 프로젝트를 주로 하며, React Native, Supabase, Nestjs를 주로 사용합니다. 인공지능 야간 대학원을 다니고 있습니다.

0개의 댓글