kuke
@kuke
Students
1,933
Reviews
205
Course Rating
4.9
안녕하세요.
IT 기업 개발자로 근무하며, 대규모 시스템을 지탱하기 위해 다양한 기술을 활용해보고 있습니다.
실무 관점의 개발 지식을 공유하고자 개설하였고, 많은 도움이 되었으면 좋겠습니다.
[문의]
Email : kukekyakya@gmail.com
Courses
Reviews
kwanghopark9031
·
Learning Large-Scale System Design by Building Directly with Spring Boot - Bulletin BoardLearning Large-Scale System Design by Building Directly with Spring Boot - Bulletin Boarddblab977687
·
Learning Large-Scale System Design by Building Directly with Spring Boot - Bulletin BoardLearning Large-Scale System Design by Building Directly with Spring Boot - Bulletin Boarddlqm16810666
·
Learning Large-Scale System Design by Building Directly with Spring Boot - Bulletin BoardLearning Large-Scale System Design by Building Directly with Spring Boot - Bulletin Boardhystom5332
·
Learning Large-Scale System Design by Building Directly with Spring Boot - Bulletin BoardLearning Large-Scale System Design by Building Directly with Spring Boot - Bulletin Board- Learning Large-Scale System Design by Building with Spring Boot - Caching Strategies
Posts
Q&A
좋아요 기능 정합성 보장 방법
근것님, 안녕하세요! 일단 1차적으로 사용자 단에서 막는 것부터 시작일 것 같습니다.사용자 클라이언트 애플리케이션에서는, 서버에 요청을 보내고 응답을 받기까지 중복 클릭/터치(따닥)를 막으면, 정상 사용자에 대한 중복 요청은 1차적으로 걸러질 수 있게 됩니다. 또는, 이미 성공한 결과에 대해서 중복 요청을 아예 못보내도록 막을 수도 있겠네요. 하지만 공격자, 별도 스크립트를 통한 요청, 네트워크 문제, 중복 요청에 대해 열려있는 기능 등으로 인해 중복 요청은 당연히 보내질 수 있습니다.서버 애플리케이션에서 이를 막을 방법은 필요하다고 생각할 수 있고 방법들도 너무나도 다양하겠지만,사실 그렇게까지 필요한지는 잘 모르겠습니다.질문 주신 의도는 중복 요청을 다루기 위한 정합성 관점보단, DB까지 트래픽 전파를 막고 싶다는 관점에서 주신 것으로 이해했습니다.그리고 적절한 방법이 무엇인지 질문을 주셨지만, 오히려 아무런 조치도 취하지 않는 것이 적절할 수도 있다는 생각이 있네요.물론, 공격자라면 당연히 막아야합니다. 하지만 이건 중복 요청에 대한 방지책이라기 보단, 공격자 자체를 차단해야하는 문제라서 사실 다른 문제로 보입니다.이미 열려있는 기능 또는 정상적인 사용자 또는 일시적으로 발생하는 네트워크 순단 등으로 인해서 말씀주신 상황이 얼마나 많이 발생할까요?DB까지 중복 요청에 대한 트래픽이 전파된다고 하더라도, 이러한 트래픽이 크게 문제가 될 수준이 된다면, 오히려 시스템 정책과 DB 스펙에 대해서 다시 검토가 필요할 것 같습니다.굳이 만들고자 한다면 무상태 서버 애플리케이션에 어떠한 상태를 관리해야 할텐데, 서버 애플리케이션에서 이를 위한 시스템을 구축하는 것은 오히려 메모리 관리도 어렵고 낭비일 수도 있을 것 같네요. 그렇다고 별도 리모트 시스템을 구축하자니 이것도 리모트 시스템에 관리 비용은 늘어나게 됩니다.로컬 메모리에 중복을 관리하든, 리모트 저장소에 중복을 관리하든, 중복에 대한 상태가 저장되기까지 중복 요청은 여전히 있을 수 있으니, 결국에 원점으로 돌아가는 셈입니다.exists -> insert 의 동시성 문제는 찰나일 수 있고 대부분의 정상 요청에서는 exists에서 막히게 될 것으로 기대하므로,이것 자체가 애플리케이션에서 취할 수 있는 가장 간단하고 적절한 방법으로 생각됩니다. 제가 질문에 대한 의도와 상황을 모두 제대로 이해하고 답변드린지는 모르겠습니다.혹시 더 궁금한 점 있으시면 편히 남겨주세요!모든 상황을 가정하다보면 끝도 없어질 수 있어서, 좋아요라는 도메인과 지금 시스템 동작 방식 내에서 어느 정도 선을 그은 부분도 있는데요, 왜 문제로 생각했는지 구체적인 예시를 고민해 주셔도 좋을 것 같네요!
- 0
- 2
- 30
Q&A
좋아요 동시성처리 최적의 선택?
쵸잉님, 안녕하세요! 1.강의에서는 비관적 락과 낙관적 락을 다루셨는데, 일반적으로 대규모 서비스가 아닌이상 좋아요 자체가 순식간에 많은 트래픽이 몰릴것같지않아 낙관락으로 처리하는 것이 더 효율적일것같다고 생각이듭니다.말씀하신대로 트래픽이 엄청 몰리지 않는다면 낙관적 락으로도 충분할 수 있습니다. 다만, 낙관적 락 특성 상 정상 사용자도 동시 요청 시에 실패 응답을 받을 수 있으므로, 사용성과 시스템 신뢰에 문제가 생길 수 있습니다. 이를 위해 간단하게 재처리 1~2회 정도만 넣어줘도 실패할 확률은 대폭 줄일 수 있게 되네요. 근데 또 다시 생각해보면, 어차피 트래픽이 적다면 비관적 락으로도 충분할 수 있는 것이고요. 굳이 낙관적 락으로 사용자에게 실패 상황을 만들어줄 필요는 없을 것 같습니다!그래도 극단적인 상황을 대비해서, 뒤에서 나오는 조회수 처리처럼 레디스로 좋아요 수를 증가시키고 스케줄링같은걸로 RDB에 백업하는 방식은 어떤가요?조회수처럼 레디스/RDB 백업 전략을 취할 수도 있겠지만, 조회수에서 제시한 전략은 유실에 대해 열려 있었습니다. 그리고 좋아요를 위한 RDB와 좋아요 수를 위한 Redis는 트랜잭션 통합을 지원하지 않습니다.또, 레디스와 스케줄링 시스템을 위해서 시스템 및 구현 복잡도는 더욱 올라갈 수 있는 것이고요. RDB만으로 충분하다면, 인프라 복잡도를 올리는 것보다 현재 가용한 자원을 활용하는 것이 좋다고 생각됩니다! 2.동시성처리에서 비관적 락으로만 처리해야 하는 상황이 있을까요? 레디스의 분산 락을 사용하는 것이 성능 측면에서 비관락보다 유리할 때도 있을 것 같은데, 실제로 비관락을 반드시 써야 하는 예시나 사례가 궁금합니다.락을 위해 레디스 등을 활용할 수도 있고 RDB에서 락에 대한 부하를 감소시킬 수 있다는 장점은 있겠지만, 인프라 복잡도와 서버 및 운영 비용 증가에 대한 부분도 고려해야할 것 같습니다.레디스도 결국에 네트워크 통신을 거쳐서 락을 획득해야 합니다. 이러한 경우에 RDB로 처리하는게 오히려 더 빠른 선택지가 될 수 있습니다.또, 레디스에 장애가 발생 시에 락이 유실될 수 있는 것이고요. 이 경우에 데이터에 대한 정합성을 반드시 보장할 수 없을 수 있고, 레디스 복구까지 작업 처리에 지연이 생길 수 있습니다. 이러한 경우 RDB로만 처리하는 것이 유리할 것으로 생각되네요!예를 들어, 레디스 락 획득 -> 결제 -> 레디스 장애로 락 유실(장애 시에 복구까지 아예 지연시킬 수 있으나, 레플리카가 마스터로 승격되어서 장애는 복구되었지만 비동기 복제 지연으로 인해 유실되는 상황을 가정할 수도 있겠음) -> 중복된 요청이 다시 레디스 락 획득 -> 결제.. 이러한 시나리오를 생각해볼 수 있을 것 같습니다. 3.RDB와 레디스는 트랜잭션이 통합되지 않기 때문에(다른 시스템이고, 레디스는 준비 과정 없고 트랜잭션 지원 안하기 때문에 2PC 지원 안함) @Transactional로 묶을 필요도 없고 묶지 않는 것이 좋습니다. 레디스에서 응답 지연이 생긴다면, 트랜잭션을 계속 점유하며 레디스 응답을 기다리게 되고, 여러 비슷한 요청이 중첩된다면 커넥션 풀도 고갈나고, 결국 DB 또는 애플리케이션까지 장애가 전파될 수 있는 위험이 있습니다.이러한 문제를 방지하기 위해서 레디스 요청은 트랜잭션 범위 바깥으로 꺼내는 것이 일반적이고요.유실에 대해 별다른 위험성이 없는 경우를 가정한다면, 꼭 트랜잭션을 통합으로 관리할 필요는 없습니다.대부분의 상황에는 유실이 발생하지 않고, 드물게 발생하는 문제 시에 로그나 원본 데이터 기반으로 복구하면 충분할 수 있습니다.정합성을 반드시 맞춰야 한다면, 강의에서 제시한 Outbox 패턴 등을 활용해서 이벤트를 발행하고 레디스에 동기화해줄 수 있습니다. 다만, 이 경우는 비동기에 대한 고려가 필요하기 때문에 시스템 정책에 대한 검토가 필요할 수는 있습니다!
- 0
- 2
- 29
Q&A
프론트엔드 msa 환경 api 주소 통합? 과 서버끼리 통신 방식에대해
쵸잉님, 안녕하세요! 요즘 본업으로 정신이 없어서 질문이 올라온지도 모르고 있었네요;; 일단 답변이 늦어서 죄송합니다. 포트 번호로 분리되었다는 것이, 단일 서버에서 여러개의 애플리케이션을 띄우는 상황을 말씀하신 것으로 이해했습니다. 말씀하신대로 path 기반으로 라우팅하는 것이 무난하고 일반적인 방법일 것 같습니다! (꼭 nginx가 아니어도 게이트웨이 역할을 하는 서버를 의미합니다.) 중간 게이트웨이에서 별도 도메인을 발급해서 관리하고 있다면, 도메인 단위로 분리할 수도 있는 것이고요.CQRS는 서버 통신 방식에 대한 관점 보단, Command와 Query의 분리 관점에서 봐주시면 좋을 것 같습니다. 말씀하신 http 통신과 카프카 방식의 차이에 대해서는, 동기와 비동기의 관점으로 바라보는 것이 좋을 것 같고요! 현재 article-read에서는 http와 kafka 두 방식을 모두 취하고 있습니다. 조회 트래픽 전파를 막기 위해 비동기로 데이터를 받아서 쿼리 모델을 만들어주고 있지만, 네트워크 또는 장비 이슈 등 항상 장애 없이 이상적으로 동작하진 않기 때문에, 쿼리 모델의 동기화 지연에 대한 대비책으로 http 통신 전략도 겸할 수 있는 것입니다. 두 방식은 목적이 다르기 때문에 각기 적용될 수 있는 것입니다. 또, 클라이언트와 서버는 상대적인 개념인데요(물론, 클라이언트가 사용자 기기를 말씀하신 부분은 이해하고 있습니다). 서버 간 통신이더라도 요청을 보내는 쪽은 클라이언트, 요청을 받는 쪽은 서버가 됩니다. 그리고 클라이언트와 서버 통신을 위한 프로토콜은 다양하지만, 강의에서는 http 1.1을 활용할 뿐이고요. 동기식, 범용적, 자주 사용되기 때문에 이해가 쉽고 구현이 간단하다는 장점은 있지만, 꼭 http 1.1을 활용할 필요는 없습니다. 성능이나 비용 측면에서 grpc(http 2.0 위에서 동작)도 자주 사용되는 선택지입니다!
- 0
- 2
- 39
Q&A
안녕하세요 무한스크롤 강의듣다가 질문이 있습니다.
동훈님, 안녕하세요! 쿼리 플랜에서 나오는 rows는 통계치 기반이고 실제로 그렇게 스캔하는게 아니므로 문제될 부분은 없습니다.줄이는 방법에 대해서 고민해본 적은 없고, 줄여야하는 이유에 대해서도 크게 신경 쓸 필요는 없을 것 같습니다.플랜은 실제로 스캔하는게 아니라 말 그대로 예상치를 기반으로 만들어진 계획으로 인지하시면 됩니다.반드시 플랜과 동일한 방식으로 수행되는 것도 아니고요.rows 수가 강의와 다르게 나오는 것에 대해서도, 각 환경의 데이터 분포나 통계치 갱신 시점 등에 따라서 차이가 있다고 봐주시면 될 것 같습니다.실제 쿼리는 LIMIT만큼 스캔하고 종료됩니다!
- 0
- 1
- 26
Q&A
조회수 조회 로직 질문
쵸잉님, 안녕하세요! 말씀하신대로 레디스에 값이 없을 경우, 백업용 rdb를 추가로 확인해볼 수도 있습니다.해당 부분은 구현하기 나름이고 전략적인 부분으로 봐주시면 될 것 같네요.실시간으로 백업용 rdb를 조회해서 자동으로 복구 가능하도록 하거나,사람이 수동 개입해서 자동으로 복구 가능하도록 하거나 등 어떤 정책을 삼을지는 개발자의 선택이 될 수 있을 것 같습니다.일단 백업용 rdb는 이름 그대로 백업을 위해 설계된 것이고, 현 설계 특성 상 항상 데이터가 동일하진 않습니다.레디스 자체에서 복구 가능한 문제일 수 있는데, rdb로 모든 트래픽을 유입시키거나 레디스의 데이터를 아예 날려버리는게 문제가 되는 선택일 수 있습니다.그래서 정책을 정하기 나름인 것이고, 비슷한 개념으로 standby와 replica 차이에 대해서도 한번 고민해보시면 좋을 것 같네요!
- 1
- 2
- 33
Q&A
비로그인 유저도 어뷰징 방지 정책
쵸잉님, 안녕하세요! 비로그인 사용자에 대한 완벽한 해결책은 없습니다.말씀하신대로 IP는 계속 변할 수 있고, User-Agent와 브라우저 쿠키 모두 조작이 가능한 값입니다.말씀 주신 http only 쿠키도 마찬가지고요.User-Agent와 쿠키는 서버에서 지정해둔 값들만 허용하도록 한다면, 조작하는 방법을 모르는 비정상 사용자만큼은 적어도 방지할 수 있습니다.그래도 조작이 있다면 IP와 같이 매번 바꾸기 어려운 값을 보고, 특정 임계치를 넘어간다면 제한을 걸어버릴 수도 있네요.도메인의 성격에 따라서 정책으로 풀어내는 것도 방법일 것이고요.강의에서는 동기적으로 처리하는 방식이지만, 모든 요청을 따로 쌓아놓고 비정상으로 판단되는 요청들은 필터링하는 등의 비동기 전략을 취할 수도 있습니다.또는, 애초에 비로그인 사용자 요청은 집계 안하거나 어떠한 문제를 풀게 해서 봇이 아닌 사람이라는 사실을 확인시키는 등의 방법들이 있을 것 같네요!꼭 한 가지 방법으로 해결할 수 있는 문제는 아니고, 시스템 특성에 따라서 다양한 방법을 고민해볼 수 있습니다. 실제로도 여러 방법들을 종합하게 되네요!
- 1
- 2
- 34
Q&A
CommentServiceTest의 테스트 로직 질문
bebe님, 안녕하세요! 저도 다시 살펴보니 위 가정에서는 굳이 1로 반환할 필요가 없네요.테스트 결과에 영향은 없지만 commentId=2의 자식은 아무도 없으므로 0으로 반환하는게 이치 상 맞고 이해도 수월할 것 같습니다.결론은 bebe님이 이해하신 부분이 맞습니다! 혼란을 드려 죄송합니다.
- 0
- 2
- 30
Q&A
무한 스크롤 방식에서 페이지 번호 방식 쿼리의 문제점 의문
재량님, 안녕하세요!사용성과 실제 쿼리 사이에서 혼동이 있으셨을 것 같습니다.무한 스크롤은 사용성 기준이고, offset/limit 방식의 쿼리에서 위 문제가 발생한다는 의미입니다.무한 스크롤 사용성이든, 페이지 번호 사용성이든, offset/limit 방식의 쿼리에서는 위 문제가 여전히 발생합니다.무한 스크롤 사용성에서는 위 문제가 사용자에게 혼란을 야기할 수 있기 때문에 새로운 쿼리 방식을 설명하게 되는 것입니다!
- 1
- 2
- 46
Q&A
path 쿼리 관련 질문드립니다!
안녕하세요!이 부분은 제보 받고 저도 뒤늦게 인지된 부분인데요, 말씀하신대로 findByArticleIdAndPath가 맞습니다..!강의 메모 남겨둬야겠네요. 제보 감사합니다.
- 0
- 2
- 29
Q&A
프로젝트 구조
rmcns님, 안녕하세요! 실제 프로젝트 구조는 팀마다 다를 수 있고 세부적인 사항까지 제가 모두 다 알 수 없기 때문에 "주로" 사용한다고 말씀 드리긴 어렵지만, 현업에서도 사용해도 충분한 구조이고 더욱 개선해서 사용할 수도 있습니다.현업에서는 도메인이나 애플리케이션이 더욱 많기 때문에 네이밍 또는 구조 등으로 더욱 체계적인 구성이 필요할 수 있네요.업무 진행하시는 환경처럼 멀티레포로 관리할 수도 있고, 모노레포에서 멀티모듈 구조를 관리할 수도 있는 것이므로 꼭 특정한 구조가 정답이라고 생각하실 필요는 없습니다.처음에 모노레포 운영하다가 멀티레포로 분리하는 상황이 생길 수도 있고, 멀티레포를 모노레포로 합쳐야할 수도 있고, 프로젝트마다 구조가 다를 수도 있기도 합니다.개인적으로는 강의 구조보다 더욱 복잡하고 세분화된 구조를 운영하고 있는데, 여기에서 근거 등을 담아내기엔 어려움이 있네요.각 도메인의 비즈니스를 체계적으로 잘 관리할 수 있다면, 처한 환경에 알맞은 구조를 만들어나가면 충분할 것 같습니다.
- 0
- 2
- 55





