밤빵's 개발일지
[TIL]20241218 멱등성 처리 설계 초안 본문
PUBG 프로젝트에서 API를 여러 번 호출하거나 데이터를 저장하는 과정에서 중복 처리를 방지해야 할 필요가 있었다. API 호출이 실패하거나 여러 번 요청되면 중복 데이터가 저장되거나 시스템의 데이터 정합성이 깨질 수 있기 때문에, 해결하기 위해 Redis의 SETNX 명령어를 활용한 멱등성(Idempotency) 구조를 설계했다. 아직 Redis를 적용하지는 않았지만, 나중에 도입할 때를 대비해 중복 처리 방안과 구현 가능성을 구상했다.
1. 멱등성이란?
멱등성은 같은 요청을 여러 번 수행하더라도 결과가 변하지 않는 성질을 의미한다.
동일한 matchId로 PUBG 매치 데이터를 여러 번 요청하더라도 결과적으로 하나의 데이터만 저장되어야 한다.
2. 멱등성이 필요한 이유
API 재시도 처리
네트워크 지연이나 서버 오류로 동일한 요청이 여러 번 발생할 수 있다.
데이터 중복 저장 방지
중복 데이터가 저장되면 리소스 낭비와 데이터 불일치 문제가 발생할 수 있다.
시스템 신뢰성 확보
중복 처리를 방지하면 데이터 정합성과 시스템 안정성을 보장할 수 있다.
3. Redis를 활용한 중복 처리 설계
3-1. 설계 방향
중복 요청을 방지하기 위해 Redis의 SETNX(SET if Not eXists) 명령어를 활용하기로 구상했다.
- matchId를 Redis의 키로 사용한다.
- Redis에 해당 키가 존재하지 않을 때만 값을 저장한다.
- TTL을 설정해 오래된 중복 처리 상태를 방지한다.
이 방식을 통해 동일한 matchId에 대한 중복 처리를 최소화할 수 있다고 판단했다.
3-2. 구상한 구현 예시
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import reactor.core.publisher.Mono;
import java.time.Duration;
@Service
public class MatchesService {
private final ReactiveRedisTemplate<String, String> redisTemplate;
private final WebClient webClient;
public MatchesService(ReactiveRedisTemplate<String, String> redisTemplate, WebClient.Builder webClientBuilder) {
this.redisTemplate = redisTemplate;
this.webClient = webClientBuilder.baseUrl("https://api.pubg.com/shards/").build();
}
public Mono<String> processMatchData(String platform, String matchId) {
String redisKey = "match:processing:" + matchId;
// [Redis의 SETNX 명령어를 활용하는 구조 구상]
return redisTemplate.opsForValue()
.setIfAbsent(redisKey, "processing", Duration.ofMinutes(5))
.flatMap(success -> {
if (Boolean.TRUE.equals(success)) {
// [중복 처리가 방지된 경우 API 호출 및 데이터 처리]
return fetchAndSaveMatchData(platform, matchId)
.doFinally(signal -> redisTemplate.delete(redisKey).subscribe());
} else {
// [이미 처리 중인 데이터일 경우 에러 반환]
return Mono.error(new IllegalStateException("이미 처리 중인 요청입니다: " + matchId));
}
});
}
private Mono<String> fetchAndSaveMatchData(String platform, String matchId) {
return webClient.get()
.uri("/{platform}/matches/{matchId}", platform, matchId)
.header("Authorization", "Bearer YOUR_API_KEY")
.retrieve()
.bodyToMono(String.class)
.doOnNext(data -> {
System.out.println("매치 데이터 저장: " + matchId);
// [DB 저장 로직을 여기에 추가할 예정]
});
}
}
4. 설계 과정에서의 고민
Redis의 SETNX 사용 이유
Redis의 SETNX 명령어는 키가 존재하지 않을 때만 값을 설정하기 때문에 간단하게 중복 처리를 방지할 수 있다.
API 호출이 여러 번 발생해도 중복 데이터 저장을 방지할 수 있다고 판단했다.
TTL 설정의 중요성
Redis에 TTL을 설정하지 않으면 장애로 인해 키가 삭제되지 않을 수 있다. 이를 방지하기 위해 TTL을 5분으로 설정해 오래된 중복 상태를 자동으로 정리할 수 있도록 했다.
아직 Redis 미적용 상태
실제로 Redis를 적용하지는 않았기 때문에 코드 레벨에서만 구현을 구상한 상태다. Redis 적용 시 이 구조를 빠르게 도입할 수 있을 것이라 예상중...!
5. 배운 점과 느낀 점
멱등성 설계의 중요성
중복 요청을 방지하고 데이터 정합성을 유지하기 위해 멱등성을 보장하는 구조가 필요하다는 것을 배웠다.
Redis 활용 가능성
Redis의 SETNX와 TTL 기능을 활용하면 중복 처리를 간단하게 구현할 수 있다는 점이 인상적이었다.
확장성을 고려한 설계
멱등성 구조를 미리 설계하면서 서비스가 확장되더라도 중복 처리 문제를 예방할 수 있다는 자신감을 얻었다.
중복 처리를 방지하고 데이터 정합성을 보장하기 위해 Redis를 활용한 멱등성 처리 구조를 설계했다. 아직 Redis를 적용하지는 않았지만, 이번 설계를 통해 미래에 빠르게 도입하고 확장할 수 있을 것이라 기대한다. Redis를 적용하고 테스트를 진행하면서 실제 상황에 맞게 추가적인 개선을 진행할 계획이다.
'개발Article' 카테고리의 다른 글
[TIL]20241219 RestTemplate과 WebClient (2) | 2024.12.19 |
---|---|
[TIL]20241217 Observability (2) | 2024.12.17 |
[TIL]20241216 벨루가 추천 시스템 (1) | 2024.12.16 |
[TIL]20241215 DDD 이해하기 (0) | 2024.12.15 |
[TIL]20241214 내 시각에서 이해한 클러스터링 개념 (0) | 2024.12.14 |