2021-02-26(Fri)

항목

내용

학습 날짜

2021-02-26(금)

학습 시간

11:00~24:00

학습 범위 및 주제

ActiveJob

학습 목표

Tournament 페이지 백엔드를 완성한다.

동료 학습 방법

eunhkim님과 학습을 진행함

상세 학습 내용

액티브 잡 Background job을 사용할 때 Sidekiq Gem을 쓰는 것을 고려했으나 이는 Redis-server에 의존하는 방식이어서 아쉽지만 적용하지 못했다. subject에서는 psql만 써야한다고 제약을 걸어놨기 때문에.. 흠 Redis는 따로 써봐야겠다.

참고

CQRS(Command and Query Responsibility Segregation)..

..는 명령과 조회의 책임을 분리하는 것이다. 그럼 여기서 말하는 명령과 조회는 무엇일까?

  • 명령은 시스템의 상태를 변경하는 작업을 의미한다.

  • 조회는 시스템의 상태를 반환하는 작업을 의미한다.

사실 이 것이 전부이다. 이 단순한 규칙이 몇 가지 응요기술과 조합되어 시스템에 적용되면서 다양하게 구현된다.

CQRS는 왜 쓸까? 상태를 변경할 때와 조회할 때 단일 도메인을 사용하기 때문에 발생하는 아래 문제들을 해결하기 위해서이다.

  • ORM은 도메인의 상태 변경을 구현하는 데 적합하지만, 여러 집계(복잡한 조회)에서 데이터를 갖와 출력하는 기능을 구현하다보면 도메인 복잡도가 높아지는 문제가 발생할 수 있다. 여러 도메인이 조인이 걸려있고 다수의 조인 쿼리가 발생하면 그만큼 DB에 부하는 커지게 되며, 도메인 객체의 디자인 자체도 점점 복잡해진다.

즉, 상태를 변경하는 기능과 상태 정보를 조회하는 기능을 분리하여 도메인을 구성하는 것이다.

도메인 모델 관점에서 상태 변경 기능은 주로 한 집계의 상태를 변경한다.

  • 주문 취소 기능과 배송지 정보 변경 기능은 한 개의 Order 집계에서 진행한다.

조회 기능은 하나의 집계로 조회할 수 있지만, 두 개 이상의 집계에서 데이터를 조회할 수 있다.

  • 단일 모델로 두 종류의 기능을 구현하면 모델이 불필요하게 복잡해진다.

참고

참고2

아래 내용처럼 PR을 작성하였다.

작업내용 or 이슈링크

토너먼트 인덱스 페이지를 구현했습니다.

  • My tournament 페이지에는 현재 참여한 토너먼트의 'next_match' 정보가 카드형태로 표현됩니다.

  • 만약 아직 토너먼트 매치 상대가 정해지지 않은 상태라면, default_dummy 정보가 next_match 카드에 표현됩니다.

  • 토너먼트 매치 최초시작일 이후에는 매일 자정에 토너먼트 매치가 생성될 예정입니다. 이 때 round는 현재 토너먼트에 참여 중인 유저 수에 따라 셋팅됩니다.

    • ex) 16강에 참여한 iwoo가 부전승했을 때 next_match 정보에는 경기예정일은 다음날(8강 예정일)이 셋팅됩니다. 그런데 16강에 참여한 사람 16명 중 iwoo 제외한 2명만 남았다면, 8강 예정일 00시에 현재 토너먼트에 참여 중인 3명 기준으로 4강이 round로 셋팅됩니다.

    • ex) 16강에 참여한 iwoo가 부전승했을 때 next_match 정보에는 경기예정일은 다음날(8강 예정일)이 셋팅됩니다. 그런데 16강에 참여한 사람 16명 중 iwoo 제외한 모두가 토너먼트 매치에 참여하지 않았다면, 8강 예정일 00시에 현재 토너먼트에 참여 중인 1명 기준으로 우승자가 결정되며 My tournament 페이지에서 카드가 삭제됩니다. 우승여부는 user_profile에 셋팅될 예정입니다.

참고: PR단위가 변경됨에 따라 렌더링까지만 구현된 상태입니다. 이어서 각 버튼 별 '이벤트' 핸들링은 추가할 예정입니다.

토너먼트가 있는 경우

토너먼트가 없는 경우

구현방법

토너먼트 인덱스

토너먼트 인덱스에서 요청하면 아래 두 조건의 토너먼트들이 응답됩니다.

  1. 진행 중인 토너먼트 (completed, canceled 상태가 아닌 토너먼트)

  2. 내가 이미 탈락한 토너먼트 (tournament_membership이 completed 상태가 아닌 토너먼트) 이 때 current_user_next_match 값이 null이면 My Tournament에, Opened Tournament에 렌더링되는 데이터로 쓰입니다.

토너먼트 round 계산

next_match_of 메서드로 다음 match를 찾습니다. 만약 메서드 실행 시점에 생성되어있는 match가 없다면, 부전승이라 판단됩니다.

특이사항

DB에 저장하는 datetime에 대해서

  1. 편의를 위해 applicatoin.rb에서 time_zone을 Seoul 기준으로 셋팅해뒀습니다. 덕분에 DB에도 KST를 저장할 수 있는 것을 확인했습니다. 따라서 클라이언트에 보내는 datetime 값과 받는 datetime 값 모두 KST로 통일할 수 있다고 판단했고, 그리 구현했습니다. war 만드실 때도 시간 값은 KST로 통일하면 좋겠습니다.

  2. 현재 Tournament의 registered_user_count에 제대로 값이 기입되고 있지 않고, 따라서 토너먼트 카드뷰에도 0명으로 기재되고 있습니다. 이는 다음 PR에서 아래 내용에 따라 fix되었습니다. 참고해주세요!

    • registered_user_count column 삭제

    • index 응답 값에 registered_user_count 키의 밸류를 요청될 때마다 계산해서 넘겨줍니다.

학습 내용에 대한 개인적인 총평

Redis를 제대로 학습하지 못한 것이 아쉽다. 주말에는 꼭 시간내서 테스트 관련해서도 파봐야겠다.

다음 학습 계획

  • Rails test

Last updated