강의

멘토링

로드맵

인프런 커뮤니티 질문&답변

Hyo Kyun Lee님의 프로필 이미지
Hyo Kyun Lee

작성한 질문수

스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판

게시글 조회 최적화 전략 도입 관련, 조회수 원본 데이터와 비교하였을때 원본과 캐싱 데이터 모두 Redis에서 추출하는 데이터임에도 (별도의 key 운용 등) Redis 캐싱 과정을 원본추출 과정과 따로 간주하는 이유(데이터를 가져오는 과정만 보았을때)

해결된 질문

작성

·

34

·

수정됨

0

  • 학습 관련 질문을 최대한 상세히 남겨주세요!

  • 고민 과정도 같이 나열해주셔도 좋습니다.

  • 먼저 유사한 질문이 있었는지 검색해보세요.

  • 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.

안녕하세요 선생님!

지난번에 남겨주신 답변내용을 보면서 전략도입의 배경부터 처리과정까지 복기해보았습니다.

그러다가 의문이 생긴 점이 있습니다.

1) 의문점
Request Collapsing, 캐싱중복적재를 제외하고 캐싱하여 데이터를 추출하는 과정만을 보았을때, 원본과 캐싱 데이터 모두 Redis에서 추출해오는 것인데, 원본추출과 비교하였을때 과정적으로 어떠한 차이점이 추가적으로 있있기에 별도의 과정으로 간주하는 것일까? 즉, "캐싱하여 가지고 오는 과정"과 "원본 데이터 추출"을 따로 보고 계셨기에, 어떠한 차이점이 있는지 의문점이 들었습니다.



2) 의문점이 생긴 이유

단순하게 간략히 말씀드리자면,

조회수 원본데이터는 Redis에서 가져오는 조회수이고, 캐싱해서 가져오는 것 역시 Redis에서 가져오는 조회수로 보여집니다. 원본데이터가 MySQL과 같은 디스크 조회 비용이 큰 저장소에 들어있는 것이 아니라, 동일한 In Memory database인 Redis에서 가져오는 것이기에 성능/비용적으로 캐싱 데이터를 가지고 오는 것에 큰 이점을 느끼지 못하였습니다.

 

세부적으로 살펴보았을때,

  • ViewClient에서 원본 데이터를 가지고 오는 경우 아래 로직을 통해 Redis에서 추출합니다.

articleViewCountRepository.read(articleId);

이떄 key는 view::article::#articleId::view_count 입니다.

  • ViewClient에서 Aspect를 처리하여 캐싱 데이터를 가지고 오는 경우 Redis에서 추출합니다.

이때 key는 articleViewCount::#articleId입니다.

이 과정에 대해 캐싱을 하는 목적을 생각해보았을때(=원본데이터 추출에 시간이 오래 걸릴 경우 성능이 빠른 다른 데이터저장소를 운용하여 이곳에서 데이터를 추출해오기 위함), 동일하게 Redis에서 추출하는 데이터임에에도 key를 별도로 운용하고, 데이터를 추출하는 과정도 다르게 가져가는(간주하는) 이유가 무엇인지 궁금하여 문의코자 합니다(물론 전체 로직을 살펴보았을때는 기존 대비 중복적재/Request Collapsing 과정을 추가하였기에 당연히 성능적인 이점이 존재하겠지만, 데이터를 가져오는 과정 그 자체만을 보았을때는 의문점이 들었습니다).

 

이게 데이터를 추출하는 과정이 다르기에, 동일한 key로 운용하면 실무적으로 로직이나 key관리방안이 복잡해져서 관리의 효율화를 위해 나누는 것일까요(즉, 기존과 달리 분산락도 사용하고 중복적재를 방지하기 위해 이용하므로 목적 자체가 다르기에 key 포맷 및 캐싱을 별도로 운용하는 것으로 이해하는 것이 적절한지)?

제가 캐싱의 목적 부터 잘못 이해하고 있는 것일 수 있고, 실무적으로 비용/성능적 유리하다는 의미가 무엇인지 잘못 이해하고 있는 것일 수 있다고 생각하고 있습니다. 그렇기에 챗지피티에게 물어보기보다는 실무적으로 경험이 풍부하시고 그만큼 검증된 선생님의 판단이 더 정확하고 궁금하여 질문드리게 되었습니다.

 

바쁘신데도 항상 성심성의껏 답변해주시는 선생님께 감사의 말씀 드립니다.

 

이효균 드림.

 

답변 2

0

쿠케님의 프로필 이미지
쿠케
지식공유자

Hyo Kyun Lee님, 안녕하세요!

 

먼저 캐시가 해결해 주는 문제를 언급 드리면 좋을 것 같은데요,

성능 뿐만 아니라 부하 분산 관점에서의 이점을 생각하면 더욱 와닿으실 것 같습니다.

 

article-read sevice에서 조회수를 가져오든, view service에서 조회수를 가져오든,

둘다 동일하게 메모리에서 가져온다는 것은 동일합니다.

하지만 article-read service에서 조회수를 가져오는건, 즉시 Redis에서 조회하는게 아닙니다.

반드시 article-read service -> view service로 요청하는 과정은 네트워크 I/O가 필요합니다.

이에 대한 캐시를 적용한 것이고요.

article-read service가 view service에서 항상 조회수를 조회할 때의 네트워크 통신에 대해 성능 및 트래픽 전파 방지 이점을 챙기게 됩니다.

 

혹시 client가 직접 view service에서 호출하여 조회수를 조합하면 되는 것 아닌지 의문이 드신다면, 아래 질문을 참고 부탁드립니다.

https://inf.run/oKxuq

https://inf.run/dzpG4

 

또, 아마 관련하여 이러한 의문도 드신 것 같습니다.

‘어차피 두 마이크로서비스 모두 동일한 Redis를 사용하는데, article-read service도 바로 동일한 Key 데이터에 접근하면 되는 것 아닌가?’

이번에는 경계와 격리에 대한 관점에서 고민해보면 좋을 것 같습니다.

article-read service와 view service는 데이터베이스가 다를 수 있고(각 마이크로서비스마다 DB를 운용할 수도 있습니다.), 코드 베이스가 별도의 레포지토리로 분리되어 있을 수 있고, 담당자도 다를 수 있고, 운영하는 팀도 아예 다를 수도 있고, 심지어 다른 회사 소속일 수도 있습니다.

지금은 단일 프로젝트에서 혼자 개발하고 있다보니, 이러한 관점이 잘 와닿진 않을 수는 있을 것 같습니다.

시스템 전체를 혼자 또는 단일 팀에서 모두 개발하기 어려울 수는 있고, 다른 담당자 또는 다른 팀에서는 조회수에 대해 비즈니스 관점에서 활용하는 측면이 전혀 다를 수도 있습니다.

이러한 상황에는 경계에 대해 잘 고민해봐야합니다.

경계를 넘어서는 영역까지 침범하게 되면 인지 과부하가 생길수도 있고, 몰라도 되는 영역까지 알아야 하는 어려움과 복잡함이 수반될 수 있습니다. 

Key를 구분한 것도, 강의에서는 인프라 구조의 복잡도를 최소화하기 위해 단일 Redis를 운영한 것이지만, Key에 대한 네임스페이스만큼은 구분하기 위함이었습니다.

(실제로도 물리적으로 구분하기보단, 논리적으로만 구분하는 경우도 많습니다.)

각 담당한 도메인(또는 마이크로서비스)의 경계는 필요하다는 의미입니다.

 

article-read service와 view service가 독립된 경계를 구성하고 있다고 본다면,

article-read service는 view service가 내부적으로 redis를 사용하는지 알 필요도 없고, 알 방법이 없을 수도 있습니다. article-read service는 view service에게 그저 API(I는 Interface)를 통해서 조회수를 가져왔을 뿐입니다.

그저 조회수를 가져올 방법을 인터페이스를 통해 공유 받고, 이를 통해 자신의 “게시글 Query” 기능을 구현한 것이고요.

view service의 내부 데이터 관리 구조는 article-read service가 몰라도 되는 영역일 수 있습니다.

물론, 예시일뿐이고 단일 시스템 및 단일 프로젝트에서 작성된다면 직접 알고 접근해도 문제 없을 수는 있지만, 격리된 상황에서의 전략 중 하나라고 생각하시면 될 것 같습니다.

그리고 각각을 격리된 경계로 취급한다면, 처음부터 서로 결합되는 부분 없이 독립적으로 구성하는게 장기적으로 관리 측면에서 유리한 부분은 있습니다.

 

이것도 결국 큰 시스템을 여러 구성원들과 운영해봐야 와닿을 수 있을 것 같은데요, 당장은 관점에 대해서만 대략적으로 이해하고 넘어가도 충분할 것 같습니다!

0

안녕하세요, 인프런 AI 인턴입니다. Hyo Kyun Lee님.

먼저, 강의를 깊이 있게 이해하시고 질문해 주셔서 감사합니다. 캐싱 전략에 대한 질문은 매우 중요한 주제이며, 이를 통해 성능 최적화의 핵심을 배우실 수 있을 것입니다.

캐싱의 목적과 서로 다른 접근 방식의 이유

  1. 캐싱의 목적

    • 캐싱은 흔히 메인 데이터 저장소의 부하를 줄이기 위해 사용하는 기술입니다. 그러나 원본과 캐싱이 동일한 저장소일 경우에도 캐싱은 여전히 중요합니다.
    • 단순화: 특정 요청의 반복 횟수를 줄여 부하를 줄이는 것보다도, 데이터의 복잡도를 줄이는 면에서 도움이 될 수 있습니다.
    • 특화된 접근 방식: 캐싱 데이터가 사용되는 문맥에 따라 최적화된 형태로 데이터를 구성하고 관리할 수 있습니다.
  2. 별도의 키 운용

    • 관리의 효율성: 각각의 데이터에 대해 별도로 키를 운용하는 것은 다양한 데이터를 관리하기 용이하게 합니다. 또한 키 관리의 단순화는 실수를 줄이고, 유지 보수성을 높입니다.
    • 데이터 일관성: 다른 종류의 작업 요구 사항에 맞춰 데이터를 별도로 관리함으로써 데이터 일관성을 유지할 수 있습니다. 예를 들어, 조회수와 같이 변화가 잦은 데이터는 빠르게 갱신될 수 있어야 하며, 캐시에 저장되어 있는 데이터는 이를 반영해야 합니다.
  3. 성능적 고려사항

    • 중단 없는 서비스: 데이터 접근 과정에서 캐싱 데이터를 별도로 운용함으로써, 메인 데이터에 문제가 생겼을 때에도 서비스의 중단을 방지할 수 있습니다.
    • 메모리 활용: Redis와 같은 메모리 기반 데이터베이스에서는 데이터 구조와 관리 방식이 성능에 직접적인 영향을 미칠 수 있습니다. 따라서 적절한 캐싱 및 키 전략은 성능을 극대화 할 수 있습니다.

이러한 고려사항들은 일반적으로 캐시 전략을 설계할 때 많이 배려되는 요소들이며, 시스템의 규모 및 요구 사항에 맞춰 적절히 적용해야 합니다.

아래 링크는 관련된 유사 질문으로, 캐싱과 성능 최적화에 대한 더 많은 정보를 얻으실 수 있습니다:
- 게시글 조회 최적화 전략과 게시글 목록 최적화 전략 구분에 따른 정책수립/관리의 비용 관련 문의

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

Hyo Kyun Lee님의 프로필 이미지
Hyo Kyun Lee

작성한 질문수

질문하기