강의

멘토링

로드맵

Inflearn brand logo image

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

See Go님의 프로필 이미지
See Go

작성한 질문수

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

인기글 Consumer 설계

댓글 신규 path 동시성 이슈

해결된 질문

작성

·

93

0

댓글의 path를 설정하는 과정에서

public CommentPath createChildCommentPath(String descendantsTopPath) {
    if (descendantsTopPath == null) {
        return CommentPath.create(path + MIN_CHUNK);
    }
    String childrenTopPath = findChildrenTopPath(descendantsTopPath);
    return CommentPath.create(increase(childrenTopPath));
 }

 

이런식으로 findChildrenTopPath를 설정하게 되는데 이 과정에서 동시성 이슈가 발생할 수 있을 것 같아 질문 드립니다.

 

increase하는 함수에서도 동시성 제어를 하는 파트가 없어 동시에 같은 계층의 댓글이 생성되면 id가 겹칠 것 같습니다!

 

 

답변 2

0

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

See Go님, 안녕하세요!

 

동시성에 대해 깊이 고민해보고 계신 것 같군요! 아주 날카롭고 좋은 지적입니다!

일단 말씀하신 내용이 맞습니다.

그런데 사실 관련해서 가볍게 언급하는 장표를 넣었다가 너무 과한 느낌이 있어서 제거한 부분이기도 합니다.

왜 이렇게 생각했는지는 이어서 설명 드려보겠습니다.

 

일단 path에 유니크 인덱스가 걸려있기 때문에 데이터 정합성 이슈는 발생하지 않고, 사용자에게 실패 응답이 내려갈 수는 있습니다.

또, 해결 방법 자체는 그렇게 어렵지 않습니다.

실패 시에 재처리 1~2회 정도 수행해보는걸로 충분할 수도 있고,

댓글 생성 과정에 대해 락을 잡아둘 수도 있고,

비동기로 처리되어도 괜찮은 상황이라면 순차적으로 댓글을 생성하여 충돌 상황 자체를 방지할 수도 있습니다.

(락과 비동기 개념 및 구성 방법은 강의 듣다보면 모두 배우게 됩니다!)

 

그런데 서비스 특성 상 정말 동시성 이슈가 빈번하게 발생하고 치명적일지에 대해 고민해볼 수 있을 것 같습니다.

게시글마다 댓글 path가 충돌될 수 있고, 각 댓글 생성은 밀리세컨드 단위로 생성됩니다.

사용자에게 이러한 과정은 게시글 목록을 조회하고, 게시글을 선택하여 내용을 확인하고, 댓글을 직접 입력 및 생성 버튼을 누르기까지 꽤나 험난한 과정입니다.

그런데 이렇게 복잡한 사용자 액션과 각 게시글별 짧은 간격으로 처리되는 댓글 생성에 대해 path 중복되는 상황이 얼마나 발생할 수 있을까요? (심지어 게시글 단위가 아닌 각 상위 댓글 기준으로 충돌)

물론, 이러한 상황 자체가 완전히 불가한 것도 아니고 미리 신경쓴다면 극소수의 사용자 불편 상황을 미연에 방지할 수 있겠지만, 극히 드물고 치명적이지 않은 상황으로 인해 "정말 모든 상황"을 다 고려한다는 것은 오히려 오버엔지니어링일 수 있습니다.

저도 만약에 실서비스 구성이었다면, 예상 트래픽 수준에 따라 미리 신경써서 개발했을 수도 있습니다.

그런데 그렇다고 하더라도 실패 시에 재처리 1~2회 정도 넣는 것으로 충분하다고 판단했을 것 같네요. (1~2회 마저 실패되면, 에러 응답 내려주고 사용자 재시도 요청)

만약 게시글 서비스가 아니라, 결제 서비스처럼 실패가 치명적이고 정합성이 중요한 곳이라면, 더욱 복잡한 방법이더라도 해결책을 강구하는게 맞을 것이고요.

강의에서는 요구사항과 문제의 간소화를 위해 언급하지 않았다고 봐주시면 될 것 같습니다! (정확히는 뒤에서 해결 방법들을 간접적으로 배우게 되는데, 앞에서부터 다 신경 쓰면 너무 복잡하고 머리 아플까봐 뺀 것도 있습니다.. ㅎㅎㅎ)

 

수동적으로 따라오기만 하는게 아닌, 능동적으로 학습하는 자세 너무 좋습니다!

혹시 더 궁금한 점 있으시면 편히 문의 주세요!

See Go님의 프로필 이미지
See Go
질문자

감사합니다! 강의 정말 잘듣고 있습니다!

 

특히 샤딩을 잡아주는 기준, 인덱싱을 잡는 기준 등을 보면서 많은 관점을 얻어가고 있습니다.

이전에 게시판을 만들었던 경험이 있어서 더 와닿았구요.

 

더 많은 강의를 기대하고 있겠습니다! 꿀팀 좀 많이 배워가고 싶네요.

0

안녕하세요, 인프런 AI 인턴입니다. See Go님.

질문해주신 댓글의 path 설정 과정에서 발생할 수 있는 동시성 이슈는 댓글 트리 구조에서 매우 중요한 부분입니다. 특히, 두 개 이상의 스레드가 동시에 특정 레벨의 댓글을 생성하려고 할 때 충돌 가능성이 존재할 수 있습니다. 이와 같은 동시성 문제를 해결하기 위해 몇 가지 접근 방식을 고려할 수 있습니다.

동시성 문제 해결 방법

  1. 비관적 락(Pessimistic Locking):

    • 데이터베이스 수준에서 비관적 락을 사용하여 특정 댓글 path에 접근하거나 수정할 때 하나의 트랜잭션만 접근하도록 제한할 수 있습니다. 이는 동시성 문제를 방지하는 확실한 방법이지만, 성능 저하가 발생할 수 있다는 단점이 있습니다.
    • 예를 들면, Java Persistence API(JPA)에서 @Lock(LockModeType.PESSIMISTIC_WRITE)를 사용하여 특정 레코드에 락을 걸어줄 수 있습니다.
  2. 낙관적 락(Optimistic Locking):

    • 낙관적 락은 데이터베이스가 아닌 애플리케이션 레벨에서 버전 체크를 하여 병합 충돌을 감지하는 방식입니다. 댓글 수정을 시도할 때, 저장된 버전과 현재 버전을 비교하여 충돌 여부를 판단합니다.
    • JPA에서는 @Version 어노테이션을 사용하여 엔티티의 버전을 관리할 수 있습니다.
  3. 트랜잭션 격리 수준 조정:

    • 트랜잭션의 격리 수준을 SERIALIZABLE로 설정하여 트랜잭션 간 읽기/쓰기 작업이 겹치지 않도록 할 수 있습니다. 이것은 동시성 문제를 해결할 수 있는 강력한 방법이지만, 성능에 영향을 줄 수 있습니다.

관련하여 유사한 문제를 다룬 질문과 답변 링크를 참고할 수 있습니다:
- 무한 depth 설계에 path enumeration 방식을 선택한 이유?

위의 사항들을 고려하여 동시성 문제를 해결할 수 있는 적절한 방법을 선택하시는 것이 좋습니다. 이러한 접근 방식들은 모두 장단점이 있고, 시스템 요구사항과 현재 구조에 따라 적절한 방법을 선택하는 것이 중요합니다.

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

See Go님의 프로필 이미지
See Go

작성한 질문수

질문하기