[Spring] 이중 API 호출을 위한 Cache 처리

SangDosa·2025년 6월 22일

Spring

목록 보기
10/10

ConcurrentHashMap을 통한 Cache 처리

  • ConcurrentHashMap을 활용해서 Spring 내부에서 서버 메모리 기반의 임시 저장소로 개발
  • API 실행 시 임시 키 형태의 데이터 저장 및 서비스 마무리 되면 finally에서 key 형태 데이터 삭제
  • ConcurrentHashMap은 자바 객체이기 때문에, 프로세스가 살아 있는 동안 메모리에 상주
  • 애플리케이션이 실행되고 있는 서버의 메인 메모리(RAM) 에 존재
  • 서버 1대에서만 유효하며, 애플리케이션 종료 시 데이터는 모두 삭제

예시

import org.springframework.stereotype.Service;

import java.time.Instant;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class SimpleRequestLockService {

    // key: 사용자ID + API명, value: 잠금 만료 시간(Unix epoch millis)
    private final Map<String, Long> lockMap = new ConcurrentHashMap<>();

    private final long lockDurationMillis = 5000; // 5초 동안 요청 막기

    public synchronized boolean tryLock(String key) {
        Long expireTime = lockMap.get(key);
        long now = Instant.now().toEpochMilli();

        if (expireTime == null || expireTime < now) {
            // 잠금 없거나 만료됨 → 새로 잠금 설정
            lockMap.put(key, now + lockDurationMillis);
            return true;
        }

        // 아직 잠금 유효 → 중복 요청임
        return false;
    }

    public synchronized void releaseLock(String key) {
        lockMap.remove(key);
    }
}

Guava Cache

  • in-memory 캐시 (JVM 내에 존재)
  • TTL 지원 (자동 만료 시간 설정 가능)
  • 동시성(Thread-safe) 기본 지원
  • LRU(Least Recently Used) 제거 정책 지원
  • Spring의 @Cacheable 같은 복잡한 설정 없이 사용 가능

예시

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class GuavaLockService {

    // TTL 60초
    private final Cache<String, Boolean> lockCache = CacheBuilder.newBuilder()
            .expireAfterWrite(60, TimeUnit.SECONDS)
            .build();

    public boolean tryLock(String key) {
        // 이미 존재하면 중복 요청
        Boolean prev = lockCache.asMap().putIfAbsent(key, true);
        return prev == null;
    }

    public void releaseLock(String key) {
        lockCache.invalidate(key);
    }
}
profile
조용한 개발자

0개의 댓글