요즘 개발적 학대를 당하고 있는 퇴물이 왔다.

나는 Nuxt를 주로 쓰고, Next는 잘 모르지만 대충 원리든 거기서 거기기 때문에 대충 듣길 바람.


보통은 페이징을 서빙하는 Nuxt 류의 인스턴스가 있고.
실제 GET/POST를 받아주는 API 인스턴스를 두는 경우가 종종 있다.
남들은 안 친해서 잘 모르겠고 뭐 적어도 나는 그러케하는 편임.


Nuxt에도 server/request event handler 를 제공함.
클라이언트 페이지에서 API 인스턴스로 까지 호출하지 않더래도 서빙 인스턴스 선에서 리퀘스트를 핸들 해줄 수 있음.

(Nuxt 메뉴얼에 Server 탭 참고)


일반적(?)인지 아닌진 모르겠지만 보통 도메인을 로드밸런서에 연결하고.
그 로드밸런서 아래에 다수의 페이지 서빙용 인스턴스(Nuxt)들이 있을 것이다.


로드밸런서를 쓰는 이유는, 부하분산 / 무중단 인스턴스 교체 / AB테스트 등 여러 이유가 있는데. GPT한테 물어보고.
고객사한테 사이트 안된다고 전화 안 받을려고 그렇게 셋팅함.

그냥 가끔 AWS 인스턴스 혼자 CPU 100% 찍고 돌연사 할 때가 어쩌다 나오는데,
인스턴스가 숨지면, 이벤트 감지 후 람다로 강제 재부팅 시키는데 이때 재부팅 시간이 좀 걸림.
이때 로드밸런서 쓰면 500 Gateway 몇번 뜨면 정상 인스턴스에만 트래픽 몰아주니까. 일단 재부팅까진 잘 버텨줌.



보통 무념무상으로 개발한건. 페이지 리퀘스트가 왔을때.

어.. 잠깐만.. 하면서 API 서버한테 axio.get으로 물어보고,
API 서버는 또 잠깐만 디비 찾아볼게.. 이러면서..

DB에 쿼리 날리고 반환하고.. 반환하고.. 이러는 레이턴시 타임이 각각 1~2ms라고 할 때.

쿼리 날리느라 1ms 쓰고. API 호출하느라 2ms쓰고 총 3ms를 쓴다.
그럼 초당 333회 처리밖에 못 하잖아. (실제로는 멀티프로세싱+넌 블락킹이라서 훨씬 더 받긴 함.)


그래서 레이턴시 때문이라도 다른 곳에 안 물어보는게 제일 조타.
JS에서 Object 에 Key Value 인덱싱 진짜 오지게 빠르니까.
여기다 데이터 암만 짱박아 봐도 실 사용량 10메가 넘기가 힘들다.

그니까 nuxt/api eventhandler로 1차로 물어보고 캐싱된거 꺼내주는데. 이것을 TTL(만료시간)을 셋팅해서.
이 현재 시간이 만료시간을 초과하면. 다시 DB에 한번 갔다와서 채워 넣는 개념이지.
어차피 nuxt install는 stateless 라서 휘발성이고 이 데이터 싹 날아가도 다시 조회하면 되니까 상관이 없음.


그러면 이 설정타임이 1분이라면 TTL 이내의 시간엔 업데이트 안 될텐데 이건 겐찬? 최신 게시물 어쩔?

보통은 10초정도 설정해서 메인에 10초 늦게떠도 머라 할 사람 아무도 없음. 있으면 강퇴 ㅂㅇㅂㅇ.


근데 손님보다 무서운게 고객 관리자임.
"어어어 제가 글 썻는데 왜 안떠요 개발자님아 이거 안데요.. " 이러면서 에러 티켓 날림..

그럴 때 뜬금없이 Redis가 등장한다.
Redis에는 KeyValue Set 기능도 있지만 Event PubSub도 지원하거던.
Nuxt 인스턴스지만 Redis로 invalidation 채널 하나 파서 구독해놓고.
신규 뻘글 작성, 게시판 설정, 사이트 설정등 데이터 변경건이 발생하면. 만료이벤트를 퍼블리싱함.
그렇게 Nuxt 인스턴스들이 이벤트 받아서 즉시 TTL을 만료시킴.
그러면 짠~ 데이터 바뀐 후 사용자가 페이지에 들어오면 새삥이 보이는거임.


"아니 또 그럼 Redis 인스턴스 비용들잖아.. 퇴물아.." 하며
이렇게 나오시겠지?

Redis Labs에서 운영하는 Redis Cloud에 Free Tier 가 있는데 30메가 준다. 이게 AWS에 떠있음.
30메가를 어따쓰나 싶겠는데, Pub/sub만 사용하면 용량을 전혀 차지하지 않음.. ㅋㅋ
심지어 고가용성 지원해서 다운타임 없이 메니지드로 관리 개잘함.

난 4년째 pub/sub용으로 공짜로 쓰고 있음.

MongoDB Cloud도 512메가 프리티어준다.

이거랑 오라클 프리티어, 삼위일체면 서비스 뚝딱~ (+AWS 프리티어까지)



암튼 난 실무에서도 API서버에 ORM을 쓸 때 class 확장해서
.find로 조회할 때(select 개념) TTL 옵션을 추가로 넣어서 조회하면. 캐싱한거 반환하게 만듬.
위에서 말한 redis ttl expire 도 낑궈 넣어서 씀.

const rs = await fuckers.find({ query: { tags: { $in: '깃붕이' }}, options: { ttl: 30000 }})
약간 이런느낌?


아무튼 나는 대충 이렇게 씀.
실무에선 기능 구현하기 급급해서 캐시까지 신경 못쓰고 개발 종료되는 경우도 빈번함.
다른 개발자 소스에서 캐싱 전략 이런거 본 적도 별로 없음. (사실 사용량 적으면 이런거 신경도 안쓰는게 맞음 ㅋㅋ)
근데 저렇게 ORM에 박으면 신경 안써도 알아서 되니까 좋음.

글이 길었다. 끗.