2025/03 18

Cursor 페이지네이션에서의 정렬, 필터링

현재 모든 게시글을 불러올 때, 댓글 개수를 따로 조회하고 합치는 방식으로 구현되어 있음.이 방식의 문제점과 해결 방법을 살펴보자.1. 기존 방식의 문제점현재는 게시글을 먼저 불러오고, 댓글 개수를 따로 조회하여 합치는 방식을 사용하고 있다.✅ 기존 코드@Query("SELECT p FROM Post p " + "LEFT JOIN FETCH p.user " + "WHERE (:cursor IS NULL OR p.id findAllPostsByCursor(@Param("cursor") Long cursor, @Param("limit") int limit);@Query("SELECT c.post.id, COUNT(c) FROM Comment c WHERE c.post.id IN :postIds ..

Project/Boilerplate 2025.03.10

게시글 Pagination 적용 (2 / 2 - 인피니티 스크롤형 게시판)

게시글 Pagination 적용 (1 / 2 - 리스트형 게시판) 지난 글에서는 OFFSET 기반 페이지네이션을 구현했다. 하지만 OFFSET 방식은 데이터가 많아질수록 성능이 저하되는 문제가 있다.이번에는 커서(Cursor) 기반 페이지네이션을 적용해보겠다.1. Offset vs. Cursor 페이지네이션 차이구분Offset 페이지네이션Cursor 페이지네이션쿼리 방식OFFSET 1000 LIMIT 10WHERE id 읽기 연산량1,010개 읽고 1,000개 스킵10개만 읽음속도데이터가 많아질수록 OFFSET 연산이 느려짐OFFSET 없이 빠름일관성중간에 데이터 추가/삭제 시 결과가 틀어질 가능성 있음항상 정확한 데이터 반환결론:데이터가 적다면 OFFSET 기반도 괜찮지만, 데이터가 많아질수록 Curs..

Project/Boilerplate 2025.03.10

게시글 Pagination 적용 (1 / 2 - 리스트형 게시판)

현 상황현재 데이터베이스에는 다음과 같은 데이터 존재유저(User): 50명게시글(Post): 10,000개댓글(Comment): 각 게시글당 5개씩, 총 50,000개기존 성능 문제  기존 방식으로 전체 게시글을 조회하면 총 15,791ms 소요 또한, 10,000개의 게시글 모두 불러옴 기존 쿼리 분석기존에는 LEFT JOIN FETCH를 사용하여 게시글과 모든 댓글을 한 번에 불러오는 방식@Query("SELECT DISTINCT p FROM Post p " + "LEFT JOIN FETCH p.comments c " + "LEFT JOIN FETCH c.user " + "LEFT JOIN FETCH p.user")List findAllWithComments(); 문제점모든 댓글을 ..

Project/Boilerplate 2025.03.10

Mock 객체 테스트 시 필드 주의점

문제:@BeforeEachvoid setUp() { mockUser = new User("testEmail", "testUser", "password", "testName", Role.USER); mockPost = new Post("Test Title", "Test Content", 0, mockUser); mockComment = new Comment("Test Comment", mockPost, mockUser, null);}이후, mockUser.getId()를 가져오는 것에 실패. 원인:mock 객체이기 때문에 JPA 엔티티가 아니라 Id가 존재하지 않음 해결:@BeforeEachvoid setUp() { mockUser = new User("testEmail", "test..

Project/Boilerplate 2025.03.06

Spring Boot response로 header가 추가되지 않는 현상

문제:response.addHeader(JwtProperties.HEADER_AUTHORIZATION, JwtProperties.ACCESS_TOKEN_PREFIX + newAccessToken);스프링 서버에서 응답 헤더에 추가한 헤더가 Front 서버에서 출력했을 때, undefined로 출력됨 원인:configuration.setExposedHeaders(Collections.singletonList("Set-Cookie"));configuration.setExposedHeaders(Collections.singletonList("Authorization"));configuration.setExposedHeaders(Collections.singletonList("x-reissue-token"..

Project/Boilerplate 2025.03.06

Mockito를 이용한 테스트 vs. SpringBootTest의 차이점

테스트를 진행할 때 Mockito 기반의 단위 테스트(Unit Test) 와 SpringBootTest 기반의 통합 테스트(Integration Test) 는 각기 다른 목적과 장점이 있습니다.1️⃣ Mockito를 이용한 단위 테스트 (Unit Test)💡 목표:특정 클래스의 동작이 개별적으로 올바르게 동작하는지 검증.Spring 컨텍스트를 로드하지 않고 빠르게 테스트 실행.Mock 객체를 사용하여 실제 데이터베이스와의 상호작용을 차단.💡 특징:✅ Spring의 컨텍스트를 사용하지 않으므로 테스트 속도가 빠름✅ Mock 객체를 이용하여 DB 등의 외부 의존성을 제거 (테스트가 독립적)✅ 특정 메서드가 의도한 대로 동작하는지 세밀하게 검증 가능 💡 Mock 객체 (@Mock)postRepositor..