프로그래밍/프로젝트

    상품 목록 조회 시, 페이징 처리 성능 개선

    현재 굿즈포유 프로젝트에서는, 다음과 같이 등록된 상품의 목록을 조회할 수 있는 기능이 있습니다. 굿즈포유 서비스의 메인이 되는 화면이기에 메인 기능이라고 볼 수 있습니다. (페이징 처리 관련한 코드를 확인하고 싶으신 분들은 링크를 참고해주세요) 이러한 상품 목록을 조회기능을 구현할 때, 단순히 아래와 같은 쿼리를 이용해 구현할 수도 있습니다. SELECT * FROM PRODUCT; 만약, 해당 서비스에 등록된 상품의 수가 적은 경우에는 별다른 문제점이 없을 것 입니다. 하지만 적재된 데이터가 10만 건, 100만건.. 많은 양의 데이터가 존재한다면 테이블 전체를 스캔하는 쿼리의 작업 시간은 매우 오래 걸릴 것 입니다. 위 그림은 실제로 약 102만건의 데이터를 조회하는데 걸린 시간입니다. 실행 시간은..

    JMeter를 통한 부하테스트

    현재 진행중인 굿즈 포유 프로젝트의 서버 성능과 가용성을 테스트 하기 위해 JMeter를 통해, 로그인 요청에 대한 부하 테스트를 진행했습니다. 위 그림과 같이로그인 요청에 대해, 토큰을 저장하는 레디스 서버와 웹 서버가 단일 인스턴스에 존재하는 형태에서의 테스트 결과 입니다. 테스트 시, user 수(Number of Threads)는 100명으로, 초당 요청(Ramp-up period)은 1번으로, 반복 횟수(Loop Count)는 1로 설정 했습니다. 즉, 100명의 사용자가 1초에 1개씩 요청을 보내는 상황을 가정했습니다. 단일 서버 환경에서의 굿즈 포유 서버의 처리량은 6.3TPS입니다. 단일 서버 환경에서 웹 서버 - 캐시 서버 - 데이터베이스 서버를 각각 분리한 후 처리량은 5.8TPS 입니..

    테스트 시, Redis Session 으로 인해 생긴 문제 해결

    문제 상황 현재 진행 중인 프로젝트에서, Redis를 세션 서버로 사용해 세션을 관리하고 있습니다. 테스트시에는 Redis를 이용한 세션관리가 아닌, spring 에서 기본으로 제공해주는 세션 관리 방법을 통해 세션 관리를 진행하려 했으나, 지속적으로 세션 관리 시, Redis가 사용되는 문제가 발생했습니다. org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis at 그로 인해 위와 같은 예외가 발생하게 되었습니다. 해당 예외는 레디스 연결에 실패했다는 예외 입니다.(테스트 시에는, 레디스가 구동중이지 않기 때문에 예외가 발생하는게 당연합니다.) 원인 분석 테스트 시에, 레디스 커넥션 관련 예외가..

    SQL Injection

    개요 현재 진행중인 개인 프로젝트에서, mybatis를 이용해 쿼리문을 작성하고 있습니다. @Insert("insert into TRADE (buyer_id, seller_id, product_id,transaction_date,transaction_status,transaction_product_quantity) VALUES (#{buyerId}, #{sellerId}, #{productId}, #{transactionDate},#{transactionStatus}, #{transactionProductQuantity})") 위와 같이 직접 sql 문을 작성하고 있지만, #{buyerId} 와 같이 입력 값을 설정하게 된다면, SQL injection 공격에 더 안전한 PreparedStatement를..

    Builder 패턴?

    현재 진행중인 프로젝트에서, 유저의 거래 기능을 담당하는 도메인 객체인 Trade 객체를 생성시에, 파라미터로 5개의 변수를 받아야 하는 상황이 생겼습니다. 그에 따라 생성자 코드가 다음과 같이 public Trade(Long buyerId, Long sellerId, Long productId, LocalDateTime tradeDate, int tradeProductQuantity) { this.buyerId = buyerId; this.sellerId = sellerId; this.productId = productId; this.tradeDate = tradeDate; this.tradeStatus = TradeStatus.BEFORE_TRADE; this.tradeProductQuantity =..

    테스트 커버리지를 70% 이상 유지하면서 느낀점

    굿즈 포유 프로젝트를 진행하면서, Jacoco와 Github Action을 통해 테스트 커버리지가 70%를 넘기지 못하면 빌드를 실패하게 설정했습니다. 이 과정에서 70% 이상의 테스트 커버리지를 유지하면서 느낀 점에 대해 본 포스팅을 통해 얘기해 보겠습니다.(작성한 테스트 코드는 https://github.com/f-lab-edu/Goods-For-You 를 통해 보실 수 있습니다😊) 처음 테스트 코드를 작성할 때는 커버리지를 70% 이상 유지하기 위해, 모든 클래스의 테스트 코드를 작성했습니다. 위 사진과 같이 모든 클래스에 대해 테스트 코드를 작성하면서, 느낀 점은 다음과 같습니다. 첫 번째. 테스트 코드도 프로덕션 코드와 동일한 수준으로 주의를 기울여 작성해야 한다는 것이었습니다. 명확하고 간결한..

    도커 컴포즈 사용 시 DB 초기화 문제 해결 과정

    문제 상황 Github Action을 통해 CD(자동화 배포)과정을 구축하는 상황 - name: Deploy to Prod uses: appleboy/ssh-action@master id: deploy-prod with: host: ${{ secrets.NCP_PROD_SERVER_IP }} username: ${{ secrets.NCP_PROD_SERVER_USER }} password: ${{ secrets.NCP_PROD_SERVER_PASSWORD }} port: ${{ secrets.NCP_PROD_SERVER_SSH_PORT }} script: | sudo docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD..

    캐싱은 언제 적용하는게 좋을까?

    개요 현재 진행중인 Goods-For-You 프로젝트에서, Redis를 도입해 서버가 여러 대로 구성된 분산 시스템 환경에서 사용자의 로그인 정보를 저장하는 세션 저장소로 사용하고 있습니다. 하지만 Redis는 세션 저장소로 사용할 수도 있지만, 캐싱을 통해 성능 향상을 도모할 수 있는 장점도 있습니다. 따라서 현재 프로젝트에서는 어떤 부분에 캐싱을 적용하면 좋을지에 대해 고민해보고 그에 앞서 관련 개념들을 알아보도록 하겠습니다 캐시란? 캐시는 사용 빈도가 높은 데이터또는 값 비싼 연산 결과를 빠른 속도로 접근할 수 있는 위치에 두는 것을 의미합니다. CPU의 1차 캐시나, 2차 캐시, 저장소 캐시, OS 페이지 캐시, 데이터베이스 버퍼 캐시, KVS(데이터를 메모리에 캐시하는 것)등 광범위하게 캐시 기..