Inflearn Community Q&A
좋아요 기능 정합성 보장 방법
Resolved
Written on
·
30
0
학습 관련 질문을 최대한 상세히 남겨주세요!
고민 과정도 같이 나열해주셔도 좋습니다.
먼저 유사한 질문이 있었는지 검색해보세요.
인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.
좋아요에 대한 정합성을 (article_id, user_id) 유니크 인덱스로 보장하는 것은 DB의 역할이라고 생각합니다.
그렇다면, 다수의 동시 요청이나 사용자의 반복 클릭(예: 좋아요 버튼을 연속으로 누르는 경우) 상황에서 불필요한 DB 부하와 예외 발생을 줄이기 위해 애플리케이션 단에서는 어떤 방식으로 이를 보완하고 처리하는 것이 적절한가요?
좋아요에 대한 정합성을 (article_id, user_id) 유니크 인덱스로 보장하는 것은 DB의 역할이라고 생각합니다.
다만, 다수의 동시 요청이나 사용자의 반복 클릭(예: 좋아요 버튼을 연속으로 누르는 경우) 상황에서는 애플리케이션 단의 단순한 선행 검증만으로는 이를 제어하기 어렵다고 느꼈습니다.
예를 들어, 아래와 같은 코드에서는 다음과 같은 경쟁 상태(race condition)가 발생할 수 있습니다.
T1: exists → false
T2: exists → false
T1: insert
T2: insert ❌ (유니크 제약 위반)
if (!likeRepository.exists(postId, userId)) {
likeRepository.save(...);
}
이처럼 애플리케이션 레벨의 exists → insert 패턴이 동시성 문제를 해결하지 못하는 상황에서
DB 예외에만 의존하지 않고 불필요한 중복 요청과 예외 발생을 줄이기 위해 애플리케이션 단에서는 어떤 방식으로 이를 보완하는 것이 바람직하다고 보시는지 궁금합니다.
Answer 2
0
근것님, 안녕하세요!
일단 1차적으로 사용자 단에서 막는 것부터 시작일 것 같습니다.
사용자 클라이언트 애플리케이션에서는, 서버에 요청을 보내고 응답을 받기까지 중복 클릭/터치(따닥)를 막으면, 정상 사용자에 대한 중복 요청은 1차적으로 걸러질 수 있게 됩니다. 또는, 이미 성공한 결과에 대해서 중복 요청을 아예 못보내도록 막을 수도 있겠네요.
하지만 공격자, 별도 스크립트를 통한 요청, 네트워크 문제, 중복 요청에 대해 열려있는 기능 등으로 인해 중복 요청은 당연히 보내질 수 있습니다.
서버 애플리케이션에서 이를 막을 방법은 필요하다고 생각할 수 있고 방법들도 너무나도 다양하겠지만,
사실 그렇게까지 필요한지는 잘 모르겠습니다.
질문 주신 의도는 중복 요청을 다루기 위한 정합성 관점보단, DB까지 트래픽 전파를 막고 싶다는 관점에서 주신 것으로 이해했습니다.
그리고 적절한 방법이 무엇인지 질문을 주셨지만, 오히려 아무런 조치도 취하지 않는 것이 적절할 수도 있다는 생각이 있네요.
물론, 공격자라면 당연히 막아야합니다. 하지만 이건 중복 요청에 대한 방지책이라기 보단, 공격자 자체를 차단해야하는 문제라서 사실 다른 문제로 보입니다.
이미 열려있는 기능 또는 정상적인 사용자 또는 일시적으로 발생하는 네트워크 순단 등으로 인해서 말씀주신 상황이 얼마나 많이 발생할까요?
DB까지 중복 요청에 대한 트래픽이 전파된다고 하더라도, 이러한 트래픽이 크게 문제가 될 수준이 된다면, 오히려 시스템 정책과 DB 스펙에 대해서 다시 검토가 필요할 것 같습니다.
굳이 만들고자 한다면 무상태 서버 애플리케이션에 어떠한 상태를 관리해야 할텐데, 서버 애플리케이션에서 이를 위한 시스템을 구축하는 것은 오히려 메모리 관리도 어렵고 낭비일 수도 있을 것 같네요. 그렇다고 별도 리모트 시스템을 구축하자니 이것도 리모트 시스템에 관리 비용은 늘어나게 됩니다.
로컬 메모리에 중복을 관리하든, 리모트 저장소에 중복을 관리하든, 중복에 대한 상태가 저장되기까지 중복 요청은 여전히 있을 수 있으니, 결국에 원점으로 돌아가는 셈입니다.
exists -> insert 의 동시성 문제는 찰나일 수 있고 대부분의 정상 요청에서는 exists에서 막히게 될 것으로 기대하므로,
이것 자체가 애플리케이션에서 취할 수 있는 가장 간단하고 적절한 방법으로 생각됩니다.
제가 질문에 대한 의도와 상황을 모두 제대로 이해하고 답변드린지는 모르겠습니다.
혹시 더 궁금한 점 있으시면 편히 남겨주세요!
모든 상황을 가정하다보면 끝도 없어질 수 있어서, 좋아요라는 도메인과 지금 시스템 동작 방식 내에서 어느 정도 선을 그은 부분도 있는데요, 왜 문제로 생각했는지 구체적인 예시를 고민해 주셔도 좋을 것 같네요!
0
안녕하세요, 인프런 AI 인턴입니다. 근것님.
현재 질문은 “좋아요 기능에서의 정합성 보장”에 대한 것입니다. 데이터베이스에 유니크 인덱스를 두어 (article_id, user_id) 조합을 통해 정합성을 보장할 수 있지만, 다수의 동시 요청이나 사용자 반복 클릭에 대해 애플리케이션 레벨에서 어떻게 최적화할 수 있는지에 대한 부분을 고민하신 것 같습니다.
애플리케이션 레벨에서의 동시성 문제 해결 방안
분산 잠금(Distributed Lock) 사용:
- Redis나 Zookeeper를 사용하여 특정 레코드에 대한 임의의 잠금을 설정함으로써 동시성 문제를 어느 정도 해결할 수 있습니다. 이러한 잠금은 중복된 요청을 하나의 요청으로 간주하고 나머지는 대기시키거나 거부할 수 있습니다.
- Redis나 Zookeeper를 사용하여 특정 레코드에 대한 임의의 잠금을 설정함으로써 동시성 문제를 어느 정도 해결할 수 있습니다. 이러한 잠금은 중복된 요청을 하나의 요청으로 간주하고 나머지는 대기시키거나 거부할 수 있습니다.
Rate Limiting:
- API 게이트웨이 레벨에서 특정 유저에 대해 요청 빈도를 제한하는 방법도 있습니다. 일정 시간 내에 허용된 요청 수를 초과하는 사용자 요청은 제한시켜, 불필요한 중복 요청을 줄일 수 있습니다.
- API 게이트웨이 레벨에서 특정 유저에 대해 요청 빈도를 제한하는 방법도 있습니다. 일정 시간 내에 허용된 요청 수를 초과하는 사용자 요청은 제한시켜, 불필요한 중복 요청을 줄일 수 있습니다.
Optimistic Locking (낙관적 잠금):
- JPA의 Versioning을 이용하여 특정 엔티티의 버전을 체크하고 업데이트하는 중간에 다른 스레드에 의해 변경이 되지 않도록 보장할 수 있습니다.
- JPA의 Versioning을 이용하여 특정 엔티티의 버전을 체크하고 업데이트하는 중간에 다른 스레드에 의해 변경이 되지 않도록 보장할 수 있습니다.
Pseudo-Unique Key 생성:
- 예를 들어, 특정 이벤트 전후의 시간 간격을 기준으로 한 임시 유니크 키를 발급하고 이를 통해 중복 클릭을 감지하고 방지할 수 있습니다.
- 예를 들어, 특정 이벤트 전후의 시간 간격을 기준으로 한 임시 유니크 키를 발급하고 이를 통해 중복 클릭을 감지하고 방지할 수 있습니다.
프론트엔드 레벨에서의 UX 개선:
- 사용자가 버튼을 클릭했을 때, 일시적으로 비활성화하고 처리 완료 시 다시 활성화하는 방법으로 중복 클릭을 방지할 수 있습니다.
- 사용자가 버튼을 클릭했을 때, 일시적으로 비활성화하고 처리 완료 시 다시 활성화하는 방법으로 중복 클릭을 방지할 수 있습니다.
이러한 방법을 통해 애플리케이션 레벨에서 추가적인 보호를 통해 불필요한 DB 부하와 예외 발생을 최소화할 수 있겠습니다.
유사한 문제 및 해결책을 다루고 있는 게시물들이 있어 도움이 될 것입니다:
- 좋아요 기능 구현 시의 데이터베이스 유니크 제약 조건 활용 방법 (게시글 제목)
- 멀티 서버 환경에서의 데이터 동기화 및 캐싱 전략에 관한 질문 (게시글 제목)
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천합니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.





