Skip to content

f-lab-edu/logout

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 

Repository files navigation

logout

호텔(숙박)예약 서비스 API

2023.06 ~

개요

숙박 예약 플랫폼 API 구현 프로젝트

프로젝트 사용기술

  • Spring Boot, Java, JPA, MySQL, Mybatis, QueryDSL, Gradle, Docker
  • intellij IDEA

주요 관심사

  • 코드 리뷰를 통해 고품질의 코드를 작성하는 경험
  • 비즈니스 로직을 직접 설계하고 구현하는 경험
  • 추후 확장 가능한, 성장 가능한 서비스를 만드는 경험

주요 비즈니스 로직

  • 광고 커미션을 적용한 검색 기능

  • ERD

    전체 ERD

    • 호텔

      호텔

    • 광고

      광고

  1. 검색시 상단 노출
  • 정책:

    • 상단노출 광고 상품을 구매한 호텔은 검색시에 상단에 노출, 일반 호텔(무료광고상품)은 그 후위에 노출됨
  • 로직: 호텔 등록 → 기본 무료광고 라는 상품으로 등록

    광고 구매 → 무료광고 삭제(delete아님) → 상단노출 광고 새로 insert

    매일 서비스 기간 체크하여 기간 넘을시에 expired 체크(배치작업)

    클라이언트 검색 request → 광고 테이블에서 expired=false 인 상단노출 호텔우위, 무료광고 호텔 후위로 조회하여 페이징

  1. 파워링크 광고
  • 정책 : 파워링크 광고 상품을 구매한 호텔은 검색시에 검색내역 위 파워링크 인벤토리에 광고상품 노출(랜덤 2개)

  • 로직 : 호텔 등록 → 기본 무료광고 라는 상품으로 등록

    광고 구매 → 무료광고 삭제(delete아님) → 파워링크 광고 새로 insert

    매일 서비스 기간 체크하여 기간 넘을시에 expired 체크(배치작업)

    클라이언트 검색 request → 광고 테이블에서 파워링크 구매한 호텔 가져옴 limit 2

  • 플로우차트

    image

  1. 오너를 위한 대시보드
  • 로직 : 사용자들이 컴포넌트 클릭시 이벤트 발생, 이후 클릭로그 테이블에 bulk INSERT -> 통계데이터의 기반 데이터가 됨
  • API 종류 : a) 월별 예약/취소 횟수 b) 예약한 사용자들의 주 연령대, 평균 예약 기간 c) 광고(계약한 광고가 있을 시에) 클릭 수

Challenge

1. Mybatis 에서 JPA 변환

도메인 단위의 설계를 적용하기 위해 MyBatis에서 JPA로 변환했습니다. MyBatis에서 DB에서 데이터를 가져오는 로직을 모두 작성해 주어야해서 어려움이 컸고, 스키마 변경시 SQL 쿼리를 직접 수정해주어야하는 번거로움 때문에 JPA를 적용하였습니다. jpa가 좀 더 개발자 친화적으로 개발할 수 있다는 장점에, JPA로 변환하였습니다.

  1. JPA 엔터티 은닉화 

    JPA의 영속성 컨텍스트는 엔터티를 더티체킹 하여 초기 스냅샷과 비교해 변경된 값을 반영합니다. 따라서 엔터티에 누구나 접근할 수 있다면, DB 값이 변경될 수 있습니다. 이를 방지하기 위해, Builder 패턴을 적용하였습니다. (설명 추가.. ) 또한, 데이터의 접근 영역을 서비스와 리포지토리로 국한하기 위해 다른 클래스에서는 request/response 객체(DTO) 를 활용하였습니다. DTO -> Entity , Entity -> DTO 로 변경하는 메서드를 사용해, 해당 서비스를 제외한 다른 클래스와 엔터티의 의존성을 제거하여 한 방향으로 흘러가는 클린 아키텍처를 적용하려 노력했습니다

  2. n+1쿼리 

    JPA 를 사용하면서 발생할 수 있는 이슈 중 하나로, 여러개의 select 쿼리가 불필요하게 나가는 것을 방지하고자 이번 프로젝트에서는 fetch 전략을 lazy로 설정하였고, n+1 문제가 발생하는 부분을 찾아 리팩토링하여 필요한 쿼리만 실행되는 부분을 최소화하도록 노력했습니다.

2. 페이징 기능 offset -> cursor (no offset)

기존에 구현했던 페이징 처리를 offset 방식에서 cursor방식으로 변경하였습니다. 기존의 offset 방식은 offset 값이 점점 늘어날 수록, 많은 행을 읽은 후 offset수 만큼 지나간 후 삭제하는 과정을 거치기 때문에 데이터베이스에 많은 부하를 주게 됩니다. 그래서 마지막으로 조회했던 cursor 를 반환하여 해당 cursor 이후부터 데이터를 조회하는 방식인 cursor방식으로 변환하였습니다.

3. 클릭 이벤트 로그 데이터 축적 로직 수정

클릭 데이터를 쌓아서 통계데이터를 쌓아, 대시보드에 필요한 통계로직을 추가하였습니다.

초반 클릭 이벤트 구현시에는, 사용자가 컴포넌트를 클릭할 시에, 단순히 api 가 호출되어 하나의 로그데이터를 save 하는 방식으로 구현하였습니다. 하지만 만약 서비스가 확장되어 많은 사용자가 몰릴시에 성능이 느려질 거라고 판단했고, 이를 검증하기 위해 대량의 api를 호출하여 부하를 주어 ngrinder를 활용하여 성능테스트를 해보았습니다. 가상 유저 100명일때 10분동안의 부하를 주어 테스트를 진행한 결과, cpu, memory를 90~95% 정도의 부하를 보이고, tps 가 정점을 찍고나서 성능이 수직낙하하여 0이 뜨는 현상을 확인했습니다. 단건으로 데이터가 적재되는 것이 명목지점으로 판단되어, 로직을 bulk insert 로 변경하였습니다. 이벤트로 스케쥴을 걸어서 bulk insert 시키는 로직으로 변경하여 성능테스트를 해본 결과, tps 의 변화는 거의 없었지만, 낙하하는 비율이 적어졌으며, cpu, memory 의 부하를 60%정도로 줄일 수 있었습니다.

About

호텔(숙박)예약시스템

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published