elasticache의 경우, 글로벌 레플리카를 지원하는데, 이 역시도 mysql/dynamodb와 크게 다르지 않은 과정으로 사용할 수 있다.
다만, 나의 경우에는 글로벌 레플리카를 사용하지 않았다.
서로 동기화되지 않는, 별개의 elasticache를 사용했다. 기존에는 리전 A에 elasticache A가 올라가 있었다. 글로벌 배포를 진행하면서 리전 B에 새로 elasticache B를 올리게 되었다.
이 때, 키값에 따라서 다른 레디스에 접근할 필요가 생겼다. redis의 어떤 값들은 단순한 캐싱으로, 리전 간 공유할 필요가 없다. 이러한 것들은 각자의 리전에 있는 redis에 적재하면 된다.
하지만 어떤 값들은 공유할 필요가 있어서, 하나의 redis를 공유했야만 했다.
비록 위의 상황이 흔히 발생할 수 있는 문제상황은 아니지만, 어쨌든 하나의 해결책을 제시해보려한다.
우선, 키값에 따라 다른 레디스에 접근해야하므로 두 개의 레디스를 만들어야한다.
const Redis = require('ioredis');
const cacheRedis = new Redis(cacheConfig);
const shareRedis = new Redis(shareConfig);
만약 일일히 키값에 따라서 커넥션을 선택적으로 사용한다고 해보자. 그러면 기존에 redis를 사용하는 모든 부분들을 찾아서 키값에 따라 일일히 바꾸어줘야할 것이다.
이는 너무 번거롭고, 하나의 값을 서로 다른 redis에 연결하는 등, 실수의 가능성도 있다.
이 때 쓸 수 있는 것이 바로 proxy이다.
JavaScript의 Proxy 기능이다.
해당 기능을 공부하기 위해
를 참고했다.
해당 포스팅은 글로벌 구축에 대한 포스팅이므로, proxy에 대한 내용은 서술하지 않는다. 필요할 경우 별도의 포스팅을 작성하여 서술한다.
proxy는 대상 객체에 대한 접근을 가로챌 수 있다. 그리고, 그 가로채는 방법은 handler가 정의한다.
우리는 redis.get, redis.set 등의 일반적인 redis 명령어 호출 함수를 가로채서, 새로운 함수를 리턴하기 위해 사용할 것이다.
const isCachedRedisKey = (key) => {
// key가 cacheRedis를 위한 key라면 true 리턴
// key가 shareRedis를 위한 key라면 false 리턴
// 확인할 수 없다면 not boolean value 리턴
}
const redisProxy = new Proxy(shareRedis, {
get(originalRedis, p) {
if (typeof originalRedis[p] !== 'function') return originalRedis[p];
return (key, ...args) => {
const flag = isCacheRedisKey(key);
if (typeof flag !== 'boolean') {
const err = new Error(`Unknown Redis Key ${key}`);
console.error(JSON.parse(JSON.stringify(err, Object.getOwnPropertyNames(err))));
}
const redis = flag ? cacheRedis : originalRedis;
return redis[p](key, ...args);
};
},
});
우선, isCachedRedisKey는 잘 정의되어있다고 가정하자.
그렇다면, 앞으로 redisProxy를 사용한 redis 접근은 다음과 같이 동작한다.
위 과정을 거쳐서, 키값에 따라 적절하게 cacheRedis와 shareRedis 사이에서 라우팅해준다.
따라서, 외부에서 사용할 때에는, 그냥 하나의 redis만 있다고 생각하고 redis를 사용할 수 있게된다.
Proxy를 통해서 객체로의 접근을 가로챌 수 있다.
이를 통해서 코드를 깔끔하게 유지하면서 여러 개의 redis 연결을 사용할 수 있다.
다만 성능 이슈 및 최초 코드 파악 시의 난해함이 문제가 될 수 있다.