본문 바로가기

전체 글42

Cursor기반 페이지네이션으로 응답 속도 개선하기 OffSet기반 페이지네이션에서속도 개선 경험을 작성한글 입니다. 테스트 환경 : M1 mac - RAM 8GB 문제점OffSet기반 페이지네이션을 사용할 때, DB에서 넘겨준 offset 위치를 찾기 위해서 맨 처음부터 데이터를 한번 훑게 됩니다.만약, 총 100만개의 데이터가 DB에 존재하고, offset을 100만이라고 주는 경우, 100만개의 데이터를 훑은 다음에 이후의 데이터를 가져와야 하므로, 성능 저하가 발생할 수 있다. 즉, offset이 클수록 성능이 저하된다. 성능저하 확인하기테스트 환경 : POSTMANDB에는 100만개의 더미데이터를 저장해 두었고, 극단적인 성능 저하를 확인하기 위해서, [offset:0, size:1]과 [offset:999999, size:1]인 두 상황의 응답.. 2024. 10. 10.
인덱스로 빠른 조회 만들기 인덱스를 사용해서 쿼리 조회성능을 개선한 경험을 글로 작성하였습니다.준비물Mysql에 100만개의 데이터를 먼저 넣어줍니다.@Test@DisplayName("대용량 데이터 넣기")void bulkInsert() throws Exception{ //given EasyRandom easyRandom = PostFactory.get(3L, LocalDate.of(1999,1,1), LocalDate.of(2024, 2,1)); //when ObjectStopWatch.start(); List posts = IntStream.range(0, 10000 * 100) .parallel() .mapToObj(i -> easyRandom.next.. 2024. 10. 8.
[테스트 환경] 벌크 쿼리(Bulk Query) 사용하기 테스트 환경에서 벌크 쿼리를 사용해성능을 개선한 경험을담았습니다. 🙆🏻‍♂️ 개선할 점테스트 코드에서 데이터베이스(MySQL)에 데이터를 저장할 때, 반복문을 사용하여 데이터 저장을 수행했습니다. 하지만 반복문이 실행되는 횟수만큼 쿼리가 실행되기 때문에, 예를 들어 100만 건의 데이터를 저장할 경우, 100만 번의 쿼리가 실행됩니다. 이는 저장할 데이터와 쿼리 실행 횟수가 1:1 비율로 증가하여 매우 비효율적이라고 생각합니다.  개선한 방법벌크 쿼리(Bulk Query)를 사용하여 만 건의 데이터를 한 번의 쿼리로 처리했습니다. 이를 통해 데이터 저장 시 쿼리 실행 횟수를 줄이고 성능을 크게 향상시킬 수 있었습니다.   벌크 쿼리 사용전 코드@Testvoid not_use_bulkInsert() .. 2024. 10. 7.
자바 메모리 구조 자바 메모리 구조Deep Dive 자바 실제 메모리 구조 메서드 영역, 스택 영역, 힙 영역으로 총 3가지 영역으로 나뉜다. 메서드 영역메서드 영역은 프로그램을 실행하는데 필요한 공통 데이터를 관리한다. 이 영역은 프로그램의 모든 영역에서 공유한다. 어떤 정보가?클래스 정보 : 클래스 실행 코드(바이트 코드), 필드, 메서드 생성자 코드static 영역 : static 변수들을 보관런타임 상수 풀 : 공통 리터럴 상수를 보관 스택 영역스택 영역은 자바 실행 시, 하나의 실행 스택이 생성된다. 각 스택 프레임은 지역 변수, 중간 연산 결과, 메서드 호출 정보 등이 포함된다.스택 프레임 : 스택에 쌓이는 네모 박스 하나가 스택 프레임 (메서드 호출시 하나의 스택 프레임이 쌓이고, 메서드 종료시 해당 스택 프.. 2024. 10. 2.
Redis사용시, 발생하는 데이터 정합성 문제 Redis를 사용하면서 겪은 데이터 정합성 문제 해결 과정을작성한 글입니다.  문제 상황게시물을 새로 등록을 하고, 조회를 한뒤 기존 게시물을 업데이트하고,다시 조회를 해보니 업데이트된 게시물이 조회되는 것이 아닌, 업데이트 이전 게시물이 조회가 되는 상황 문제 원인게시물이 업데이트되었을 때, Redis에 저장된 데이터는 동기화되지 않으므로, 데이터 정합성 문제가 발생할 수 있다. 데이터베이스의 게시물 내용이 변경되었지만, Redis는 여전히 이전 데이터를 반환할 수 있어 최신 상태가 유지되지 않는다. 문제 해결 방법게시물을 업데이트할 때, 해당 게시물과 관련된 Redis에 저장된 캐시 데이터를 삭제하여, 다음 조회 시 최신 데이터가 반영되도록 한다. @CacheEvict(value = "getPosts.. 2024. 10. 1.
Redis, 캐싱하면 정말 응답 속도가 빨라? Redis가 정말 캐싱을 잘 해주는지 아닌지확인하는 글입니다. 성능을 높이고자 하는 부분게시물을 불러올때 카테고리를 기준으로 불러오게 됩니다. 매번 카테고리에 관련된 글을 불러올때, 속도를 개선하고자DB에 직접 쿼리를 날려 조회하는 방식이 아닌, 한번 조회된 데이터는 Redis에 저장해 놓고, 다음번 조회시엔 Redis에서 조회하도록 하는 상황입니다.  Redis관련 설정 코드package com.sangyunpark.smileboard.config;import com.fasterxml.jackson.databind.ObjectMapper;import java.time.Duration;import org.springframework.beans.factory.annotation.Value;import or.. 2024. 10. 1.
세션 로직 개선기 (feat. 더티 코드) 세션 처리 로직을 개선하는 과정을 담은 글입니다.Version #1session이 필요할 때마다 3줄씩 반복되는 로직 String id = SessionUtils.getLoginDefaultId(session); if(id == null) SessionUtils.getLoginAdminId(session); if(id == null) throw new NotFoundSession(SESSION_NOT_FOUND); 로직이 사용되는 부분 @Transactional(readOnly = true) public void updatePassword(final UserUpdatePasswordRequest request, final HttpSession session) { String encryptBeforePas.. 2024. 9. 29.
HttpMediaTypeNotAcceptableException - No acceptable representation 에러가 발생한 상황을 해결하기 위한 생각의 흐름을 정리한 글입니다. 에러가 발생한 상황은 다음과 같습니다. UserController에서 회원가입 기능을 하고, 로컬 테스트를 하기 위해서 postman을 사용해서 테스트를 하고, 결과를 받은 response가 다음과 같다. 응답 결과로 406 Not Acceptable 오류가 발생했다. 시스템 로그를 확인해보자. 로그의 쿼리문을 먼저 확인해보겠습니다. Postman 요청을 보낸 후, 다음과 같은 쿼리가 나간다. 현재 내가 짠 로직에 맞게 쿼리가 알맞게 나갔는지부터 확인해보자. 쿼리를 각각 분리해보면 select 쿼리와 insert 쿼리로 나뉘어져 있다. 쿼리를 날리는 로직은 대개 UserServcie 클래스에 작성을 해두었다. 쿼리가 사용되는 로직은 다음.. 2024. 9. 28.
🙆🏻‍♂️ DP 너, 정복당해라 [백준 2240번 - 알약 편] 문제70세 박종수 할아버지는 매일 매일 약 반알을 먹는다. 손녀 선영이는 종수 할아버지에게 약이 N개 담긴 병을 선물로 주었다.첫째 날에 종수는 병에서 약 하나를 꺼낸다. 그 다음, 그 약을 반으로 쪼개서 한 조각은 먹고, 다른 조각은 다시 병에 넣는다.다음 날부터 종수는 병에서 약을 하나 꺼낸다. (약은 한 조각 전체 일 수도 있고, 쪼갠 반 조각 일 수도 있다) 반 조각이라면 그 약을 먹고, 아니라면 반을 쪼개서 한 조각을 먹고, 다른 조각은 다시 병에 넣는다.종수는 손녀에게 한 조각을 꺼낸 날에는 W를, 반 조각을 꺼낸 날에는 H 보낸다. 손녀는 할아버지에게 받은 문자를 종이에 기록해 놓는다. 총 2N일이 지나면 길이가 2N인 문자열이 만들어지게 된다. 이때, 가능한 서로 다른 문자열의 개수는 총 .. 2024. 9. 26.