7주차 발표 - g-market/b-shop-backend GitHub Wiki

📈 진행률

진행률 : 99%..(고도화...)


LAST WEEK WE DID!

  • 동시성 제어
    • Redis를 통한 thread락 기능을 적용해 재고에 대한 동시성 제어 로직을 구현하고자 함 -> DB 비관적 락을 통해 해결
  • 상품 조회(카테고리별, 연도별)조회 추가적으로 구현
  • 상품관련 CRUD 기능 테스트코드 추가 구현
    • 상품 옵션 관련기능 테스트 코드
    • 상품 이미지 관련기능 테스트 코드
    • 상품 예약 관련 테스트 코드
    • 카테고리 관련 테스트 코드
  • 프론트엔드 작업 및 배포
  • 초기 데이터 생성 -> 조금씩 꾸미고 있는 중..

📝 금주 수행 작업

📌 3차 MR

👉 !53

📌 프론트엔드, 백엔드 서비스 VM상에 배포


📌 인프라 구성

image

2) 구축 과정 중 고민사항

  • CORS이슈를 nginx에서 해결하려면 어떻게 해야할까?

  • 139.150.73.182:80 -> 139.150.73.182:8080 CORS! 발생

  • 프론트엔드 nginx 서버에서 139.15.73.182/api/URI-PATH 로 들어온 요청을 리버스 프록시 서버로 라우팅 해서 해결

  upstream b-shop-proxy {
    server b-shop-nginx:80;
  }

  server {
    listen       80 default_server;
    listen      [::]:80 default_server;
    server_name  _;
    
    root   /usr/share/nginx/html;
    index  index.html;
      
    # error_page   500 502 503 504  /50x.html;
    
    location / {
      try_files $uri $uri/ /index.html;
    }

    location /api/ {
      rewrite /api/(.*)$ /$1 break; // b-shop.com:80/api/ -> b-shop.com:80/
      proxy_pass        http://b-shop-proxy; // b-shop.com:80 -> b-shop-nginx:80
      proxy_set_header  Host $host;
      proxy_set_header  X-Real-IP $remote_addr;
      proxy_set_header  X-Forwarded-Proto https;
      proxy_set_header  X-Forwarded-For $remote_addr;
      proxy_set_header  X-Forwarded-Host $remote_addr;
      proxy_set_header  X-NginX-Proxy true;
      
      proxy_ssl_session_reuse off;
      proxy_redirect off;

      add_header 'Access-Control-Allow-Origin' '*';
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
      add_header 'Access-Control-Allow-Headers' 'X-Requested-With,Accept,Content-Type, Origin' always;

      client_body_temp_path           /tmp/;
      client_body_in_file_only        on;
      client_body_buffer_size         128K;
      client_max_body_size            100M;
    }
  }

3) 개선해야할 점

  • 인프라, 어플리케이션, loging, 발생된 에러에 대한 추적 관리 필요성을 느낌...

image

📌 동시성 제어 - nGrinder를 사용하여 부하테스트

  1. nGrinder란
  • 네이버에서 성능 측정 목적으로 개발된 성능 부하 및 스트레스 테스트 도구
  1. nGrinder 적용
  • local Docker환경에 nGrinder Contoller, Agent 설치

3. Script 작성 - 서버 부하를 발생시킬 api 요청 스크립트 작성 - groovy Script 작성
@RunWith(GrinderRunner)
class TestRunner {

        private String accessToken = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJBY2Nlc3NUb2tlbiIsImlhdCI6MTY3ODMzNjQ2MiwiZXhwIjoxNjc4MzQwMDYyLCJpZCI6MTEsInJvbGUiOiJBRE1JTiJ9.A_9S3Nhh_UnDNCH5dnuYLpTYD0qsywXZ0p0kZBcpzwo"
        ...
        @Test
	public void test() {
		headers["Authorization"] = "Bearer " + accessToken
		request.setHeaders(headers)
		
		def param = "{\"orderItemDtoList\":[{\"itemId\":1,\"itemOptionId\":1,\"orderCount\":1}]}"
		HTTPResponse response = request.POST("http://b-shop.com/api/orders", param.getBytes());

		if (response.statusCode == 301 || response.statusCode == 302) {
			grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", response.statusCode)
		} else {
			assertThat(response.statusCode, is(201))
		}
	}

  1. VM 서버로 부하 테스트 수행 image
  • Vusers : 동시 접속하는 유저의 수 ( vuser = agent * process * thread )
  • TPS(Transaction per Second) : 초당 처리수, 높을 수록 성능 좋음
  • Peak TPS : 초당 처리 수의 최대치
  • Mean Test Time : 응답 시간

📌 장바구니

프론트엔드에서 장바구니 페이지에서 주문 페이지로 이동할 때

상품 상세 페이지에서 주문하기 버튼을 눌러 주문 페이지로 이동할 때를 구분하였습니다.

이에 전자의 경우에만 장바구니가 지워지도록 하였습니다. (`회원의 장바구니에서 주문한 itemId, itemOptionId 만 지워지도록 변경하였습니다.)


2) 구현 과정 중 고민점

장바구니는 현재 Hashes 자료구조를 사용하고 있습니다.

image

key: memberId (위 그림에서 KEY)
hashKey: itemId + '-'(Delimiter) + itemOptionId ('NAME')
hashvalue: CartDto(itemId, itemOptionId, orderCount) ('GARIM')

이에 따라 장바구니페이지에서 (주문하기 버튼을 눌러) 주문 페이지로 이동할 때,

아이템 상세 페이지에서 주문 페이지로 바로 갔을 때를 구분하였습니다.

이를 해결하는 방법으로

  1. /orders API를 하나로 사용하고 있어 이를 API를 분리
  2. 장바구니에 대한 id를 만들어 이를 전달하는 방식
  3. /orders?delete=true API의 @RequsetParam
  4. 장바구니에서 시작하면 장바구니 삭제 API를 추가

이에 따라 4번 방식인 장바구니페이지에서 (주문하기 버튼을 눌러) 주문 페이지로 이동할 때만 장바구니를 지우는 방식으로 구현하였습니다.


⛓ 남은 작업 사항

  • application logging, infra status logging -> docker-compose 로깅 ing
  • 성능부하테스트(nGrinder) ing
  • 코드 아키텍처 리팩토링(Clean Architecture, CQRS, 추상화) ing
  • DB I/O 줄이는 리팩토링 ing
  • API 리팩토링 ing
⚠️ **GitHub.com Fallback** ⚠️