본문 바로가기

분류 전체보기116

페이징 성능 개선: offset vs no offset vs covering index 페이징 성능 개선: offset vs no offset vs covering index 웹 서비스에서 페이징은 아주 흔하게 사용되는 기능이다. 일반적으로 페이징은 구현한다면 LIMIT ... OFFSET ...; 와 같은 패턴으로 OFFSET을 사용하는데 이는 점차 데이터가 많아짐에 따라 수십초 ~ 수분까지 조회가 느려질 수도 있다. 따라서 No offset과 Covering index를 통해서 페이징 기능을 개선하는 방법에 대해서 살펴보자. product 테이블에 대략 1,572만 건 상품 데이터가 있다. OFFSET LIMIT 쿼리는 결과에서 지정된 순서에 위치한 레코드만 가져오고자 할 때 사용된다. 위 쿼리는 다음과 같은 순서로 실행된다. ORDER BY id DESC: 일반적으로 최신에서 과거순으.. 2023. 12. 25.
synchronized vs Pessimistic Lock vs Distributed Lock synchronized vs Pessimistic Lock vs Distributed Lock DB의 무결성을 보장하기 위해서는 다양한 방법이 있다. 물론 synchronized는 적합한 방법은 아니지만 왜 적합하지 않은지에 대해 살펴보고, 그 뒤 비관적 락(Pessimistic Lock)과 분산락(Distributed Lock)을 통해 성능 비교를 해보자. 재고 차감 로직을 통한 DB 부정합 문제 살펴보기 위 ProductService는 주문 관련 비즈니스 로직 중 하나로 "상품 조회 -> 상품의 재고 차감 가능 여부 확인 -> 재고 차감"의 순서로 이루어지는 로직이다. 해당 비즈니스 로직을 통해서 어떻게 DB 부정합 문제가 발생하게 되는지 테스트 코드를 작성해보자. 위 테스트 코드는 한 번에 100개.. 2023. 12. 21.
Nginx와 WAS의 로깅 식별자(request_id) 공유하기 Nginx와 WAS의 로깅 식별자(request_id) 공유하기 현재 프로젝트의 서비스 환경은 위 그림과 같다. WAS만 사용하는 것이 아니라 Nginx와 같은 Web Server를 앞단에 두고 사용하고 있다. 따라서 Nginx 로그와 WAS 로그를 함께 봐야하는 경우가 많은데, 이때 Nginx와 WAS가 동일한 request_id를 공유하면 로그 파악이 매우 용이해진다. Nginx 설정 Nginx에서는 제공하는 변수 중 하나로 $request_id가 있다. 이 변수는 각 HTTP 요청에 대해 고유한 식별자를 생성하여 주로 로깅이나 디버깅 목적으로 사용된다. 이 변수는 ngx_http_core_module 모듈에서 제공되며 32개의 16진수 문자열로 각 HTTP 요청이 도착하면 자동으로 할당된다. Log.. 2023. 12. 17.
Blue/Green 방식으로 서비스 중단없이 배포하기 Blue/Green 방식으로 서비스 중단없이 배포하기 어플리케이션을 배포하는데 있어 Rolling 배포, Blue/Green 배포, 그리고 Canary 배포와 같은 다양한 배포 전략들이 있다. 각 전략의 특징과 장담점을 살펴보고 프로젝트에 어떤 전략을 선택할지 고민해보려고 한다. Rolling 배포 롤링 배포는 각 서버를 한 개씩 새로운 버전으로 (점진적) 배포하는 방법을 말한다. 즉, 위 그림처럼 기존 버전에서 새 버전으로 서비스를 전환하는 과정을 순차적으로 진행한다. 서비스 중인 인스턴스 하나를 로드밸런서에 라우팅하지 않도록 한 뒤 새 버전을 적용하여 다시 라우팅하는 방식으로 구성된 자원을 그대로 유지한 채로 무중단 배포가 가능하므로 관리가 편하다는 장점이 있지만 배포가 진행되는 동안 구버전과 신버전.. 2023. 12. 17.
쿼리 작성과 최적화 (1/2) 쿼리 작성과 최적화 어플리케이션 코드를 튜닝해서 성능을 2배 개선하는 것은 쉽지 않지만 DBMS에서 몇십 배에서 몇백 배의 성능 향상이 이뤄지는 것은 상당히 흔한 일이다. 그만큼 SQL 처리에서 "어떻게(HOW)"를 이해하고, 쿼리를 작성하는 것이 중요하다. 쿼리 작성과 연관된 시스템 변수 대소문자 구분, 문자열 표기 방법 등과 같은 SQL 작성 규칙은 MySQL 서버의 시스템 설정에 따라 달라진다. MySQL 서버의 시스템 설정이 쿼리에 어떤 영향을 주는지 살펴보자. SQL 모드 MySQL 서버의 sql_mode라는 시스템 설정에는 여러 개의 값이 동시에 설정될 수 있다. 그중에서 대표적으로 SQL 작성과 결과에 영향을 미치는 값은 어떤 것들이 있는지 살펴보고, sql_mode를 설정할 때는 구분자(,.. 2023. 12. 13.
Jenkins으로 CI/CD 구축하기 Jenkins으로 CI/CD 구축하기 다른 분들과 협업 프로젝트를 진행하면서 요구사항은 계속 바뀔 수 있기 마련이다. 하지만 폭포수 모델처럼 분석, 설계 영역에 상당한 시간이 할당되고, 해당 작업이 끝난 후에는 개발 시 어떤 추가나 수정도 허용되지 않으면서 전체 개발이 끝난 후에 통합이 진행된다면 그 결과로 수 많은 통합 이슈가 가장 마지막 단계에서 발생하는 문제가 발생할 수 있다. 따라서 현재 진행하는 이커머스 프로젝트는 충분히 잦은 요구사항이 발생할 수 있는 서비스이기 때문에 애자일처럼 빠르고 유연하며 조금씩 발전되는 소프트웨어 개발을 통해 목표를 계속 수정해나가는 방법론을 선택했다. 따라서 하나 혹은 그 이상의 기능을 구현하고 테스트, 빌드, 배포하는 것이 자주 발생하기 때문에 이러한 반복적인 개발.. 2023. 12. 9.
세션은 어느 계층에서 처리해야 할까? 세션은 어느 계층에서 처리해야 할까? 세션을 통해 사용자 관련 로그인, 로그아웃 기능을 구현하고 있을 때 현재 어떤 문제가 있는지에 대해서 살펴보고, 리팩토링해보자! 리팩토링 전 코드 먼저 리팩토링을 하기 전에 로그인은 어떻게 동작하고 있는지에 대해서 살펴보자. @MemberLoginCheck @Target(ElementType.METHOD) @Retention(value = RetentionPolicy.RUNTIME) public @interface MemberLoginCheck { } 먼저, @MemberLoginCheck 어노테이션을 생성해줬다. Controller 레이어에서 @MemberLoginCheck 어노테이션이 붙어있는 메서드는 실행 전에 로그인 검증이 일어날 수 있도록 Aspect 클래스.. 2023. 11. 30.
실행 계획 실행 계획 옵티마이저가 관리자나 사용자의 개입 없이 항상 좋은 실행 계획을 만들어내는 것은 아니다. 이러한 문제에 대해 MySQL 서버에서 보여주는 실행 게획을 일고 이해하려면 MySQL 서버가 데이터를 처리하는 로직을 이해할 필요가 있다. MySQL 서버의 실행 계획에 가장 큰 영향을 미치는 통계 정보에 대해 간략히 살펴보고, MySQL 서버가 보여주는 실행 계획을 읽는 순서와 실행 계획에 출력되는 키워드, 그리고 알고리즘에 대해 살펴보겠다. 통계 정보 MySQL 8.0 버전부터 인덱스되지 않은 컬럼들에 대해서도 데이터 분포도를 수집해서 저장하는 히스토그램(Histogram) 정보가 도입됐다. 히스토그램이 도입됐다고 해서 기존의 테이블이나 인덱스의 통계 정보가 필요한 것은 아니다. 테이블 및 인덱스에 .. 2023. 11. 30.
인덱스를 사용하는 이유와 트레이드 오프 인덱스 인덱스는 여러 가지 방식에서 사용될 수 있다. 예를 들어, 락 관점에서 보면 인덱스가 걸려있지 않은 테이블로 WHERE 조건 검색을 하면 전체 레코드가 락이 걸리는 반면 인덱스를 통해 WHERE 조건 검색을 하면 해당 레코드만 락을 걸어 락을 최소화할 수 있다. 또한 테이블 전체 파일을 읽기 보다는 상대적으로 작은 인덱스 파일을 읽어 더 빠르게 조회를 할 수 있다. 이러한 여러 가지 장점이 있는 인덱스에 대해 알아보고, 인덱스를 사용하는 대신 그에 따른 트레이드 오프가 무엇이 있을지 살펴보자. 인덱스의 데이터 저장방식(알고리즘) 데이터 저장방식(알고리즘)별로 구분할 경우 상당히 많은 분류가 가능하지만 대표적으로 B-Tree 인덱스와 Hash 인덱스로 구분할 수 있다. B-Tree 알고리즘은 가장 .. 2023. 11. 28.