부트캠프

두 번째 팀프로젝트 회고 - 상품 조회, 옵션 및 AWS RDS 담당

달팽이포뇨 2023. 8. 29. 22:23
  • 기간: 2023.08.14~08.25 
  • 개발환경: Java, Spring, AWS RDS/EC2
  • 고양이 용품 쇼핑몰, Roupang
  • 백엔드 6명, 프론트엔드 5명이서 개발
  • 백엔드 역할 분배: 회원 2명, 마이페이지와 장바구니 2명, 쇼핑몰과 판매자: 2명
  • 나의 역할: 쇼핑몰 - 상품 옵션, 상품 조회, 검색 및 AWS RDS 관리 담당
  • 목표: Stream API 많이 사용하기, 검색 및 조회 부분에서의 성능 향상

1. 복잡한 옵션 테이블

이커머스의 경우, 상품 옵션 관련된 부분을 NoSQL로 처리하는 것으로 알고 있었습니다. NoSQL은 스키마 변경이 자유로워서 확장성이 좋기 때문이고 배열로 값을 저장할 수 있기 때문입니다. 하지만, 저희 프로젝트 요구사항에 MySQL을 사용하라는 것이 있었습니다. 따라서, 상품 옵션을 MySQL 테이블로 복잡하게 구현할 수 밖에 없었습니다.

옵션 관련 테이블은 등록, 조회, 삭제를 위해 3개로 구성하였습니다.

- option_type 테이블: 각 상품의 모든 옵션 정보 

- option_type_name 테이블: 각 상품의 옵션 범주 이름 

- option_detail 테이블: 각 옵션 범주의 세부 옵션 정보

erd를 이렇게 구성하기는 하였지만 실제로는 엔티티에 모든 연관관계를 넣지는 않았습니다.

이렇게 테이블 간의 관계가 복잡했기 때문에 제가 따로 그림을 그려서 올리기도 하였습니다.

2. DB - Too Many Connections 오류 발생!

제가 코드를 작성하고 인텔리제이를 실행시켰을 때, Too Many Connections 오류가 발생하였습니다.

AWS 콘솔에서 RDS를 확인해본 결과, 오른쪽 사진과 같이 보여졌습니다.

검색해본 결과, 이전까지는 혼자 개발하거나 인원이 적었어서 이런 문제가 발생하지 않았던 것 같습니다.

해당 이슈는 max connections 수와 wait timeout 시간과 관련되어있습니다. Spring boot의 기본 커넥션 풀 라이브러리인 Hikari CP의 MySQL 기본 커넥션 풀 크기는 10이고, AWS RDS의 t2.micro 인스턴스의 기본 max connections 수는 66입니다. 또한, AWS RDS의 MySQL의 기본 wait timeout은 8시간입니다. 즉, 현재 저희 팀 백엔드 인원 6명+배포한 서버 1대 이렇게 해서 최대 약 70개의 커넥션이 필요한데, 인스턴스의 기본 max connections 수가 66개라서 초과되었던 것입니다. 또한, wait timeout이 너무 길어서  DB에 접근하지 않을 때에도 오랜 시간동안 커넥션을 점유하고 있는 상황이 생겼던 것입니다.

이 이슈는 AWS RDS의 파라미터 그룹에서 max connections와  wait timeout 설정을 변경해주며 해결하였습니다.  

 

3. 판매순 정렬 - LEFT JOIN

 상품 조회 및 검색할 때, 판매순 정렬을 구현해야했습니다. OUTER JOIN은 학교 데이터베이스 강의 실습 때 이외에는 처음 사용해보았습니다. "상품 테이블 LEFT JOIN 구매 테이블" 이렇게 쿼리문을 구성하였습니다. 만약, 구매 테이블에 기준을 두고 RIGHT JOIN을 한다면 판매량이 0인 물품은 조회되지 않으므로 적합하지 않다고 판단하였습니다.

 

4. Stream API 많이 사용하기

이번 프로젝트를 진행할 때, Stream API를 많이 사용하려고 노력하였습니다. Stream API를 사용하면 for문을 일일히 다 순회하지 않아도 되고, 가독성이 좋아진다는 장점이 있습니다. 물론 Stream API를 사용하면 조금 느려질 수 있다는 점 등 단점이 존재하기도 하지만 가독성이 좋아진다는 부분이 굉장히 크게 와닿았고 현업에서도 많이 사용한다고 들어서 이번에 많이 사용해보자고 결심하였습니다.

Stream API를 많이 사용해보고 싶어서 일부러 검색, 조회가 많은 쇼핑몰 파트를 맡으려고 자원하였습니다.

예를 들어, 이 5줄의 코드를

Stream API를 활용하여 이렇게 1줄로 줄였습니다. 

 

5. 검색, 조회 성능 향상시켜보기

  • Spring Cache - @Cacheable(value="캐시된 데이터값 저장할 테이블 이름", key="캐시된 데이터값에 할당할 key 값")이런 식으로 정의하여 메소드에 붙여봄으로써 Spring Cache를 사용해보았습니다. 원래는 아래와 같이 651ms나 걸렸던 요청이었는데  

캐시 적용 후, 아래와 같이 10ms로 드라마틱하게 줄어드는 것을 볼 수 있었습니다.

  • MySQL Index
    • 상품 이름 검색하는 부분에서 product_name에 인덱스를 걸고 테스트를 해보았습니다.
    • 인덱스는 원래 중복되는 값들이 적을 때, 효과가 잘 나타나는데 이미 중복된 이름의 상품 데이터가 많이 들어가있어서 그런지 속도 차이가 거의 없었습니다.

알게된 점

왜 이커머스 분야에서 NoSQL을 많이 사용하는지 체감할 수 있었습니다. 그리고 현업에서 왜 Stream API를 많이 사용하는지도 알 수 있었습니다. Stream API를 적극적으로 사용해보니, 확실하게 코드의 양이 줄어들었고 가독성이 높아지는 현상을 볼 수 있었습니다. Spring Cache를 사용하면 속도가 확실히 빨라지기는 하지만 사용할 때 은근히 사용법이 까다롭고 원하는 값이 잘 나오지 않을 수 있다는 것을 깨달았습니다. 그리고 많은 사람들이 사용할 때를 대비해서, 미리 DB 튜닝을 잘해놓아야겠다는 점도 깨달았습니다.

 

개선해야할 점

상품 이름을 unique한 값으로 바꿔보고 다시 인덱스를 적용해보면서 성능 차이를 확실하게 알고 싶습니다. 

 

느낀 점

첫 번째 프로젝트보다 Git을 활용하는 것이 편해졌습니다. 그리고 첫 번째 프로젝트와 다르게 프론트엔드 개발자님들과 함께 작업하다보니 회의도 많이 갖고 따로 얘기도 하면서 정말 소통의 중요성을 다시 한번 느꼈습니다. Stream API의 간결함이 크게 와닿아서 앞으로도 Stream API를 많이 쓸 것 같습니다. 그리고 AWS RDS 파라미터 그룹을 편집해보면서 제가 좋아하는 클라우드 서비스에 대해 조금 더 알게 된 것 같아서 좋았습니다.

 

Github

https://github.com/mkwkw/Roupang-backend/tree/develop