dataloader를 활용하면서 장점만 넘쳐서 대부분 dataloader 형태로 이용하고 ...
# 질문
e
dataloader를 활용하면서 장점만 넘쳐서 대부분 dataloader 형태로 이용하고 있는데, dataloader 중심으로 graphql 운영하시는분 많으신가요?
h
현 회사에서는 GraphQL을 안쓰고 있는데 이전 회사에서는 캐시레이어가 Dataloader로 대체(...)되어서 운영했었어요.
🤔 1
h
"dataloader 중심" 이라는게 어떤 의미인지...
e
로더를 최대한 많이 생성하여 운영한다? 정도의 의미로 적었습니다
h
뭐 로더 있는 건 다 쓰죠.. 아주 초기엔 안쓰고 빨리 리졸버 짜기도 하는데, 기본적으로는 다 만들고 더 최적화 더 필요하면 커스텀 배치 로더를 만들기도 합니다.
적어도 루트쿼리엔 로더 안쓰는 리졸버가 없죠
서버든 클라이언트이던 graphql 에서 서비스 엔드포인트에 맞닿아 있는 부분엔 무조건 캐시레이어가 들어가는데 data-loader가 서버 측의 대표적인 캐시레이어 입니다.
사실상 GraphQL Server의 전신같은 녀석이라 안쓰이는 데가 더 드물어요 ㅋㅋ
t
DataLoader 사랑해요…
h
아 근데 v2 아직 안올려봤어요
t
혹시 DataLoader + Redis/Memcached 붙여서 쓰시는 분 계신가요??
🙅‍♂️ 1
e
저도 장점 알고나니 점점 Dataloader 만으로만 만드니 ㅎㅎ 괜히 불안한 마음에 질문던져봤습니다. 다들 잘 쓰고 있군요. 장점에 비교하여 소개가 적더라구요.
h
실제 사례 있을까요? 캐시 클러스터링 하는 용도인거죠?
t
모르겠어요 ㅠㅠ

https://www.youtube.com/watch?v=MPRQRlrixls

요거 기반으로 쿼리 기반 캐싱 구현했는데요.
query variable이 엄청 다양하면 무의미해질거같아서… 어차피 DataLoader 떡칠되어있으니까 batch함수 내부에서 캐싱 로직을 일반화해볼까 하고 있었어요.
h
캐시 수명이 per-request 를 넘어가는 순간 다른 종류의 엔지니어링 문제가 되니 ㅋㅋㅋ 전 스케일 그 정도 서비스를 다룰 일이 없어서 쓸일이 없을것 같네요
t
Copy code
class CachedDataLoader extends DataLoader {
  …
}
e
리퀘스트 들어올때 데이터로더 생성하여 사용하시죠?
h
batch함수 내부에서 캐싱 로직을 일반화해볼까 하고 있었어요.
사실 이 것만 해도 캐시 정책(키) 잘못 만들어서 버그가 넘 자주 나는 것….
😆 1
t
넵 당연하죠 ㅋㅋ
e
nestjs에서 요청당 생성 깔끔하게 만들어보려고 고민해서 지금은
message has been deleted
h
근데 만약 일관성 조금 포기해서 캐시끼고 최적화한다 치면
Redis 같은걸 운영하기 보단 CDN으로 뿌릴 것 같네요
e
좀 커스텀하게 만들어서 운영하고 있어요
t
@Han BaHwan 혹시 캐시레이어가 DataLoader로 대체되었다는건 DataLoader를 request 당 생성이 아니라, 전역으로 생성해놓고 In-memory 캐시처럼 사용했다는 말씀이세요??
h
ㅎㄷㄷ;
h
아 아뇨; 별도의 redis/memcache같은 롱타임(?) 캐시레이어를 사용하지 않고 않고 request마다 dataloader하는것만 이용했었다는 의미였어요.
💪 2
h
혹시 “전회사“가 여기 말씀하시는건가…
h
(쉿)
e
지금 데이터로더 요청별로 LRU 캐싱만 적용한 상태인데
cdn 캐싱, 통쿼리 캐싱, 리졸버 수준 캐싱 이런거 추가로 사용하시나요?
h
비용이 비싼 작업에는 리솔버 수준 캐싱이 필요할 것 같긴 한데요.
e
저도 리졸버 수준 캐싱까지 만들어 놨는데, 만들어만 두고 사용할만한곳을 찾지 못했네요 ㅎㅎ
h
근데 사실 그정도 수준이면 저라면 그냥 서비스를 분리해서 해당 서비스에서 알아서 캐시하게 할 것 같아요 (..)
👍 1
h
리졸버 수준 캐시라는게 리졸버 함수 자체를 memoize 한다는 그런건가요?
저도 바환님 말씀처럼 할거같은데
h
저는 그렇게 생각했어요.
e
네 함수 자체입니다.
h
이 쪽 context 객체는 immutable 하다는 보장이 딱히 없어서
h
variables랑 context serialization해서 캐시키로 쓰면 되지않을까요(?)
h
뭐 그럼 되겠죵. 근데 단일 리졸버가 그렇게 비싸질 일이 있을까 싶네요.
사실 쿼리 리졸버는 거의 최적화할 일이 없고
IO 있는 곳들이 문제인데
e
로직 별로 많이 다를꺼같은데 dataloader뒤 늦게 사용하고 batchFunction만 최적화 하면 지금까지는 성능저하가 있을만한게 별로 없네요
dataloader ❤️
로더별로 캐시맵을 따로 설정가능하니, 무거운 작업 있다면 로더를 전역 캐시맵을 붙이는것도 괜찮을꺼 같은데 이렇게 쓰시는 분은 없죠?
t
저는 admin.user.id + user.id + query 해시 + variables 해시 + 캐시 버전 요렇게 해서 키로 만들었어요.
e
{API|GQL}{PUBLICuser.id|orgId}:{cacheKey|reqHash}
api controller또는 gql에서 public정보랑, org캐싱인지정보 받고 위처럼 키 생성하게끔 만들어 뒀네요
h
전 개인적으로는 verbose 하게 다 만드는게 취향 ㅋㅋ
아마 갠프로젝트 한다면 코드생성기 쓸 것 같네요