| Event와 Price 1:1로 연관관계를 가지지만 분리되어 있습니다. 1:1 관계인 엔티티를 분리하였을 때의 느꼈던 장점과 단점이 무엇이 있었나요? 각각의 도메인을 정의하고 분리할 때 어떤 근거를 사용하였나요? R / S / A가 아닌 다른 등급의 좌석이 있거나, 어떠한 장소에는 R석이 없다면 어떻게 대응할 수 있나요? 혹은 이벤트 일자별로 동일한 등급의 좌석이여도 가격이 달라진다는 요구사항이 추가되면 어떻게 해야 할까요? 위와 같은 상황에서 어떻게 구조를 바꿔야 할지 생각해본 점 있을까요? | 엔티티를 분리하는 설계 방식은 여러 가지 장단점을 가지고 있습니다. 이 방식은 특히 변동성이 큰 요소들, 예를 들어 가격의 변동이나 좌석의 확장 및 축소와 같은 상황에 대응하기 위해 설계의 확장성을 높이는 데 큰 장점을 가집니다. 예를 들어, 가격(Price)에 대해서는 일대일(OneToOne) 관계를 설정하여 변동이 잦은 정보를 관리하기 용이하게 하고, 특정 이벤트(Event)에 대한 다양한 사용 가능한 좌석(AvailableSeat)의 경우는 일대다(OneToMany) 관계를 설정하여 하나의 이벤트가 생성될 때 연달아 여러 좌석이 생성되어야 하는 상황에 효과적으로 대응할 수 있습니다.

하지만, 이런 설계 방식에는 단점도 존재합니다. 특히 원투원(OneToOne) 관계를 다룰 때, 부모-자식 간의 관계 설정에서 복잡성이 발생할 수 있습니다. 또한, 매우 큰 데이터 세트를 다루는 경우, 불필요한 조인 연산이 발생할 수 있어 성능 저하의 원인이 될 수 있습니다. 이는 특히, 다양한 엔티티 간의 관계가 복잡하게 얽혀 있을 때 더욱 문제가 될 수 있습니다.

다른 좌석 구성이나 일자별 가격 변경과 같은 상황에 대해서도, 가격 정보를 분리하여 관리했듯이, 각각의 좌석 타입이나 가격 변경 정보를 별도의 엔티티로 분리하여 일대일 관계로 관리하는 것이 가능합니다. 이러한 접근 방식은 설계의 유연성을 증가시키고, 시스템의 확장성을 향상시킬 수 있는 장점을 가집니다. ———아래는 결론임, 꼭 얘기 안해도 됨———— 종합하자면, 엔티티 분리 설계 방식은 시스템의 확장성과 유연성을 크게 향상시킬 수 있는 장점이 있지만, 관계 설정의 복잡성과 큰 데이터 세트를 처리할 때의 성능 저하 문제를 고려해야 합니다. 따라서, 이러한 설계를 적용할 때는 이러한 장단점을 면밀히 고려하여 시스템의 요구 사항과 목표에 맞는 최적의 방법을 선택하는 것이 중요합니다.저희는 처음 설계할 당시 변동이 잦을 법한 정보에 대해 일대일 관계를 설정했습니다. | | --- | --- | | TicketService.createTicket의 역할이 필요 이상으로 커서 코드에서 하는 일이 무엇인지 한번에 파악하기 어렵고, 락을 잡고 있는 시간이 길어질 것처럼 보이는데요. 어떻게 이 메소드를 쪼개서 분리할 수 있을까요? 특히나 오버부킹이 되지 않도록 잔여 좌석을 저장하는 부분의 정합성이 틀어지지 않도록 메소드를 분리할 수 있을까요? | 코드의 역할을 명료하게 구분하기 위해 크게 세 개의 메서드로 나눌 수 있습니다.

  1. 선택한 이벤트와 예매하고자하는 티켓의 정보를 비교하여 유효한 날짜/좌석/예약가능상태 등을 확인.
  2. 데이터베이스를 조회하여 중복되는 티켓이 있는지 확인.
  3. 티켓을 생성하고, 좌석 테이블을 업데이트.

락 유지 시간이 길어지는 것을 막기 위해 수정을 한다면 1,2 번의 정합성 체크와 중복체크를 통과한 시점에서 락을 해제하고 다른 요청을 무효화 시키고, 실제 티켓을 생성하고 좌석테이블을 업데이트 하는 부분은 분리할 수 있을 것 같습니다.

또한 2번 데이터베이스를 조회하는 시간을 단축시키기 위해 캐싱을 활용하여 예매 완료된 티켓을 등록 해놓고 중복체크를 캐시에서 확인하는 방법도 사용해보았습니다.

이 방법은 빠르게 중복티켓을 확인할 수 있어 응답시간은 줄일 수 있었지만, 캐싱 서버의 오류 혹은 티켓 테이블의 변화를 놓치면 오버부킹의 문제가 발생할 수 있기 때문에 안정성을 중시하기 위해 DB 에서 직접 확인하는 방법을 선택하였습니다.

트랜잭션의 범위와 락의 범위가 같아야 하는지 ? 레디스 서버를 통해 빠르게 체크하는 방법 락이 오버부킹을 막는 대책이 되어야 함 | | 실제 결제 시스템을 연동하려면 어떻게 프로젝트를 바꾸거나 개선을 해야 할까요? 결제를 먼저 하고 티켓 예약 정보를 업데이트 해야 할까요? 그렇다면 결제는 성공했는데 이미 티켓이 품절되었다면 어떻게 해야 될까요?반대로 티켓 예약을 먼저 하고, 이후 결제를 하는 방식으로 구현한다고 가정하면, 티켓은 예약됐는데 결제는 실패할 수 있습니다. 이런 상황을 어떻게 처리해야 할까요? | 사용자에게 부여한 락의 유지시간을 최소화하고, 티켓의 유실을 막기 위해 다음과 같은 단계를 구상해 보았습니다.

  1. 사용가 좌석을 선택한 후 [결제하기] 단계로 진입한 시점에서 티켓 생성 메서드가 실행됨
  2. 티켓의 정합성과 오버부킹 체크가 완료된 시점에서 락을 해제하고, 같은 요청을 모두 무효화 시킴.
  3. Unpaid 상태로 티켓을 생성하여 사용자에게 소유권을 부여
  4. 생성된 티켓은 짧은시간(5~10)분 정도의 결제 유예 시간을 두고 그 시간 안에 결제되지 않으면 취소 처리.

위와 같은 방법으로 티켓의 오버부킹을 막고, 사용자는 결제 단계에서의 실패가 있더라도 유예 시간 안에 처리가 된다면 무사히 티켓을 발급받을 수 있기 때문에 안정성 있는 서비스를 경험하게 될 것으로 생각합니다. |

질문

CS(문의 상황)이 들어올 때를 대비해 로깅을 잘 해둘것

QA, 상담사 분들이 사용할 백오피스 기능도 제공해야함

예) 회사의 서비스에 대해 이런 기능 이렇게 하면 될거같은데 맞나요?

면접 내 질문에 대한 생각 / 정답 확인 ?

이력서 작성 시 사용한 기술스택과 관련 내용의 질문이 들어올 것을 예상해야함

직접 구현한 부분은 아니지만~ / 그래도 개념적으로 알아보아야 하는 것. 질답은 준비해야함.

검색 - 엘라스틱 서치

레디스 유료화 관련 다른 방안을 찾아본 적 있는지

vercel 이외 다른거 바꿔보는것

softdelete 관련 → 보관 기간.

카카오 / 구글 개인정보 보관기간 사이트 참조해서 이용약관 작성

예상 질문지

왜 락에 Redisson을 썼는지

redisson은 싱글 스레드 형식이라서 동시성 제어에 적합하다고 판단하였고, 이미 내부에 SpinLock 방식이나 Pub-SubLock 방식의 구현체들이 있어서 락을 공부하고 적용하기에도 좋아보였다.

왜 Pub-Sub Lock을 사용했나요

비슷한 락인 스핀락과 비교했을때 락을 점유하려고 계속 요청을 보내는 스핀락과 달리 펍섭락은 레디스 쪽에서 점유를 하라고 알려주는 방식이기 때문에 레디스 서버에 부하가 적을거라고 판단하여서 펍섭락을 사용함

왜 Redis를 이용해서 cache 를 했는지

In-memory 기반으로 매우 빠른 응답을 제공하기 때문에 인기 검색어와 자주 찾는 이벤트리스트를 읽고 쓰는데 사용하였습니다. 특히 다른 캐시 시스템에 비해 다양한 데이터 구조를 지원하기 때문에 복잡한 구조의 Entity를 사용하는 이번 프로젝트에서 데이터 처리가 유리한 점이 있었습니다. 추후 서비스가 커지면 Scale-out 의 측면에서도 클러스터링을 통해 안정적인 서비스 제공을 기대할 수 있습니다.

같은 역할을 하는 Memcached 는 데이터의 복잡한 구조를 다루는데 제한이 있고, 데이터를 메모리에만 저장하고 디스크엔 저장하지 않기 때문에 서버 재시작시 데이터 손실의 우려가 있습니다. 또한 Redis 는 Pub/sub, 트랜잭션 등의 현재 프로젝트에 필요한 다른 기능들도 수행할 수 있어 선택하게 되었습니다.