Cherishu 기존 프로젝트 리팩토링 일지 - 조회수,Docker-compose 환경 구성

Coodori·2024년 2월 2일
0

CherishU

목록 보기
27/29
post-thumbnail

문제 발생

기존 프로젝트를 리팩토링하는 시간을 가지려고한다.
새로운 프로젝트를 하는 것 보단 기존 프로젝트를 리팩토링하고 유지보수하는 사람은 별로 없기에 기존 프로젝트를 다시 한번 보고 개선 방안에 대해 고민을 해보려고한다.

개선 방안이 크게 없으면 그래프 탐색을 하여 DTO와 비교를 하려고했지만 생각 외로 리팩토링 요소가 많아 천천히 하나씩 코딩테스트를 준비하면서 진행해볼 예정이다.

일단, 기존 CSV 파서는 @Profile로 직접 스프링과 연관이 되어있기에 직접 프로필을 바꾸고 서버를 재시작해야 가동이 된다. => 해당은 나중에 배치성으로나 아예 제거하면 좋을 듯하다.

추가로 각 @Transactional readOnly 기능마다 Master-Slave 구조를 가져가 보려고 한다.
(추후 업데이트)

일단 오늘은 예전부터 해보고싶었던 상품 조회 로직 개선

오늘의 개선할점

  1. docker-compose 로 운영환경 만들기 구축

  2. 조회수가 동시성 고려가 되지 않아 JMeter 테스트를 진행하였을 때
    500번 2번

실행은 모두 되었지만 총 등록된 조회수는 141회

  1. 성능 조회가 되지 않은 한방 쿼리 개선 차이점 확인

1번) docker-compose 로 운영환경 구축

version: '3.9'

services:
  postgresql:
    # 사용할 이미지
    image: postgres
    # 컨테이너 실행 시 재시작
    restart: always
    # 컨테이너명 설정
    container_name: postgres
    # 접근 포트 설정 (컨테이너 외부:컨테이너 내부)
    ports:
      - "5432:5432"
    # 환경 변수 설정
    environment: 
      # PostgreSQL 계정 및 패스워드 설정 옵션
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: 비밀번호
    # 볼륨 설정
    volumes:
      - ./data/postgres/:/var/lib/postgresql/data

  redis:
    image: redis:latest
    container_name: redis
    hostname: redis
    ports:
      - 6379:6379
    labels:
      - "name=redis"
      - "mode=standalone"

방법 처럼 docker-compose 로 구성을 하였고 Dockerfile로도 충분히 두개를 작성해서 조합하는 것을 docker-compose에서 제공하였다.

version: '3.9'

services:
  db:
    build:
      context: ${PWD}/postgresql
      dockerfile: Dockerfile
    environment:
      - POSTGESQL_PASSWORD=비밀번호
    container_name: postgresql
    
    ports: 
      - 5432:5432
    stdin_open: true
    tty: true
  redis:
    image: redis:latest
    container_name: redis
    hostname: redis
    ports:
      - 6379:6379
    labels:
      - "name=redis"
      - "mode=standalone"

하지만 직접 만든 빌드된 파일을 사용하지 않아 구체적인 경로명을 쓰는 장점이 없다는점
별도의 Dockerfile를 각 인스턴스마다 만들어야해서 관리가 어렵다는 점에서
이번 개선 프로젝트는 docker-compose.yml 에 모두 기재하여 동시에 이미지를 가져오고 실행시켰다.

컨테이너들이 함께 관리 되는 것을 볼 수 있었다.

이렇게 사용하면 다른 프로그램 환경들과 구분점을 둘 수 있고 다른 환경에서 해당 프로젝트를 사용할때 명령어 한줄이면 동일한 환경을 구축할 수 있었다.

진행 하다가 문제점과 깨달은 점

문제: 데이터커넥션을 받아오는데 테이블을 만들어주면 반영이 안되는 사안이 발생했다.

결과: 로컬 PostgreSQL과 같은 5432포트를 사용하여 5432 포트로 연결을 했을 경우 로컬 PostgreSQL로 연결이 되어 내가 원하는 Docker와 연결이 안됨.

해결방법:
MACOS 업데이트로 인한 brew 사용 에러

Error: homebrew/core/postgresql@14: unknown or unsupported macOS version: :dunno
brew update

수행

brew services stop postgresql@14

로 실행 중단

해당 수행 후 다시 docker-compose up 진행 하니 해결되었음

psql -U postgres
\c 데이터베이스
\dt

2번) 조회수 동시성 문제

현재 조회수 로직

문제점: 조회를 DTO로 하고 재 조회를 하여 증가시킴

1번 해결 방법 시도: 조회를 엔티티로 받아온뒤 더티체킹으로 조회수 변경

개선된 것: 쿼리가 하나줄었다.(재 조회 쿼리)
하지만 아직 조회수는 500번을 하여도 500개가 늘지 않는다.

2번 방법: 직접 view 증가를 1 날려버린다.

정확하게 500개가 늘었다.
하지만 아쉬운점은 도메인의 상태를 변경하는 비즈니스로직은 도메인 클래스하고 같이 있으면 좋을 것 같은데 해당 코드는 리포지토리에 있다는 점이다.

이렇게 도메인에 있으면 바로바로 늘려줘서 밀접한 관련을 보여줄 수 있고 직접 업데이트를 하는 쿼리이기 때문에 영속성 컨텍스트에는 반영이 안되는것을 알수 있다.

3번 방법: 비관적 락모드를 건다.

LockModeType = PESSIMISTIC_WRITE 배타락
PESSIMISTIC_READ 공유락

최초 조회시에 걸어주어야하며 Spring data jpa 로는

이렇게 사용하며 Querydsl 로는

이렇게 사용한다.
새삼 또다시 QueryDsl을 숭배할 수 밖에 없다.
젠장 또 너야!!!!

성공적이다.

근데 이렇게 배타락을 쓰면 성능 차이가 꽤나 심하지 않을까 싶다.... 우리는 확인해보자

또한 성능 테스트 차트를 보기 위해 외부라이브러리를 Jmeter에 넣어줬다.

https://jmeter-plugins.org/install/Install/

해당 파일을 다운로드서 Jmeter의 /lib/ext 폴더에 넣어주면 우상단에

깃털 표시가 뜨게 된다.

그러면 이제 그것을 클릭해서 원하는 그래프를 다운 받으면 되는데
나는 3 Basic Graphs 를 선택했다.

성능 테스트 순간 상식

  • 응답 시간 = 클라이언트가 서버에 요청을 하고 그 요청에 대한 응답을 받을 때까지 걸린 시간

    응답시간(Respose Time) = [동시 사용자 수 / 초당 요청 수(TPS)] - 인지시간(Think Time)

  • TPS 서버가 초당 처리할 수 있는 요청의 개수 -> 높을 수록 처리 속도가 높음

    초당 요청 수(TPS) = 동시 사용자 수 / 응답시간(Response Time) + 인지시간(Think Time)

배타락

동시성 고려 X

벌크쿼리

시간적으로는 동시성X가 제일빠르고 배타락이 제일 느렸다.
하지만 동시성을 지키지 않으면 조회수 같은 항목들이 누락이 된다는점.
데이터 정확성에 신뢰가 가지 않는다는 점이있다.

하지만 배타락같은 경우 시간이 거의 5배가 늘어났기 때문에 해당은 만능이 아니다.
해당 프로젝트에서는 update 쿼리를 사용하여 의도에 맞게 조회수를 정확히 올려주고 쿼리를 1개 줄이는 방향으로 설계했다.

그러면 해결방법은?

  1. Redis Sorted set

  2. Kafka 메세징 큐

  3. API Gateway 에서 처리율 제한 정도

3번은 다음편에 이어서 적도록 하겠습니당

느낀점

Jmeter라는 성능 테스트 툴을 활용하여 어떤 방식이 장단점이있는지 실제로 눈으로 확인하며 개발을 진행했습니다. 다른 성능 테스트 툴을 활용하여 3번 쿼리 성능에 대해 비교를 할 예정이며 성능테스트를 돌려보며 정확하지만 최적의 성능을 보이는 코드를 짜도록 노력해야겠습니다.

성능테스트 동시성 테스트를 하지 않았다면 몰랐을 동시성 누락 조회수 였습니다.

REFERENCE

https://velog.io/@pppp0722/%EB%8F%99%EC%8B%9C%EC%84%B1%EC%9D%84-%EA%B3%A0%EB%A0%A4%ED%95%9C-%EC%A1%B0%ED%9A%8C%EC%88%98-%EC%A6%9D%EA%B0%80-%EA%B8%B0%EB%8A%A5

https://velog.io/@znftm97/%EB%8F%99%EC%8B%9C%EC%84%B1-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0-V2-%EB%B9%84%EA%B4%80%EC%A0%81-%EB%9D%BDPessimistic-Lock
https://leeggmin.tistory.com/10

https://velog.io/@sdsd0908/JPA-%EB%B2%8C%ED%81%AC-%EC%BF%BC%EB%A6%AC%EC%97%B0%EC%82%B0-%EC%82%AC%EC%9A%A9%EB%B2%95-em.flush

profile
https://coodori.notion.site/0b6587977c104158be520995523b7640

0개의 댓글