Closed
Conversation
[내용] 1. Redis CacheManager 설정 추가 - RedisConfig에 JSON 직렬화(GenericJackson2JsonRedisSerializer) 및 JavaTimeModule을 적용한 CacheManager Bean 등록 - 기본 TTL 1시간 설정 2. 공지사항(Notice) 조회 최적화 (Over-fetching 해결) - 목록 조회용 DTO(NoticeListResponse)와 상세 조회용 DTO(NoticeResponse) 분리 - 목록 조회 시 불필요한 본문(Content) 데이터 제외하여 네트워크 페이로드 감소 3. 캐싱(@Cacheable) 및 정합성 관리(@CacheEvict) 적용 - NoticeService: 목록(페이징 키 적용) 및 상세 조회 캐싱 적용 - FaqService: 전체 목록 및 카테고리별 조회 캐싱 적용 - 데이터 생성/수정/삭제 시 관련 캐시(목록/상세) 초기화 로직 구현
1. MyPage 조회 성능 개선 - '내가 쓴 글', '북마크한 글' 조회용 경량 DTO(MyPostResponse, MyBookmarkPostResponse) 도입 - DB 레벨에서 Content를 요약(SUBSTRING)하여 네트워크 페이로드 감소 2. N+1 문제 해결 및 로직 단순화 - PostRepositoryImpl에 QueryDSL Projections 및 Left Join 적용 - PostService의 어플리케이션 레벨 조인 로직(mapWriterInfo 등) 제거 및 쿼리 이관 - 게시글 상세 조회 시 작성자 정보 및 댓글 목록을 효율적으로 가져오도록 구조 개선
- PortfolioService: 상세 조회 시 DB Update 제거 및 Redis 캐싱 적용 - PortfolioService: 응답 시 DB 값 + Redis 캐시 값 합산 반환 - PortfolioBatchScheduler: 조회수 동기화 및 인기 점수 재계산 스케줄러 구현 - PortfolioEntity: 배치용 메서드 추가 및 점수 계산 로직 리팩토링 - PortfolioRepositoryImpl: 정렬 조건 최적화
- 상세 조회(getPortfolioDetails) 시 정적/동적 데이터 분리 조회 구현 - 정적 데이터(본문): Redis Cache-Aside 패턴 적용 (TTL 1시간) - 동적 데이터(조회수, 좋아요): Redis Hash 구조로 실시간 관리 - 좋아요(Bookmark) 기능 Write-Through 전략 적용 - DB 즉시 반영 및 Redis 캐시 실시간 동기화로 정합성 보장 - 조회수(ViewCount) Write-Back 배치 처리 구현 - Redis에 버퍼링된 조회수를 10분 주기 스케줄러로 DB 일괄 반영 - 사용자 Display용 키와 배치 처리용 키 분리하여 안정성 확보 - 포트폴리오 목록 조회(getPortfolioList) 최적화 - 메인 페이지(Page 0)에 한해 Redis 캐싱 적용 (TTL 3분)
1. Redis 캐싱 전략 재설계 (Split & Merge)
- 게시글 본문(변경 빈도 낮음)과 통계/댓글(변경 빈도 높음)을 분리하여 관리
- 본문 정보는 post:info:{id} 키로 캐싱하여 DB 부하 감소
- 댓글 목록은 캐싱하지 않고 DB에서 실시간 조회하여 데이터 정합성 보장
2. 조회수 Write-Back(쓰기 지연) 구현
- 조회수 증가 요청 시 DB Update 없이 Redis에만 카운트 누적
- PostBatchScheduler 추가: 10분 주기로 Redis의 누적 조회수를 DB에 일괄 반영
- PostRepository: 대량 업데이트를 위한 incrementViewCount 쿼리 추가
3. DB 인덱스(Index) 최적화 적용
- PostEntity: 카테고리별 조회순/최신순 정렬 및 유저별 조회 인덱스 추가 (idx_post_category_view, idx_post_category_date 등)
- PostCommentEntity: 게시글별 댓글 목록 조회를 위한 복합 인덱스 추가 (idx_comment_post)
- PostBookmarkEntity: 내 북마크 목록 최신순 조회를 위한 인덱스 추가 (idx_bookmark_user_date)
4. Service 및 Entity 리팩토링
- PostEntity: 조회수, 댓글수, 북마크수 증감 편의 메서드 추가
- PostService: 댓글 생성/삭제 시 게시글 본문 캐시를 불필요하게 삭제하지 않도록 개선
- Projections.fields 사용 시 기본 생성자(NoArgsConstructor) 부재로 인한 런타임 예외 해결 - 컴파일 시점에 타입 체크가 가능한 Projections.constructor로 변경하여 안정성 확보 - DTO(PostResponse 등)에 QueryDSL 조회용 전체 생성자 추가
1. Service (PortfolioLikeService): - 트랜잭션 내 부모 엔티티(Portfolio) Update 로직 제거 (Lock 회피) - Redis에 실시간 조회용(stats)과 배치 동기화용(delta) 카운트를 각각 업데이트하도록 변경 2. Scheduler (PortfolioBatchScheduler): - syncLikeCounts 메서드 추가 - 10분 주기로 Redis에 누적된 좋아요 증감분(Delta)을 읽어 DB에 일괄 업데이트(UPDATE ... SET count = count + :delta) 수행 3. Repository (PortfolioRepository): - 배치 처리를 위한 updateLikeCount Modifying 쿼리 추가
1. DTO (PostResponse, PostDetailResponse): - commentCount 필드 추가 및 QueryDSL Projections 생성자 매핑 순서 수정. 2. Service (PostService): - 댓글 작성/삭제, 북마크 토글 시 실행되던 부모 엔티티(Post)의 직접 Update 로직 제거 (Lock-Free). - Redis에 실시간 카운트(stats)와 배치용 델타(delta)를 기록하도록 변경. - 상세 조회 시 Redis에 저장된 최신 카운트(조회수, 북마크, 댓글)를 병합하여 반환. 3. Scheduler (PostBatchScheduler): - 기존 조회수 외에 북마크 수, 댓글 수도 주기적으로 DB에 일괄 반영하도록 확장. - Atomic Rename을 활용하여 배치 처리 중 데이터 유실 방지. 4. Repository (PostRepository, Impl): - 배치 처리를 위한 updateCommentCount, updateBookmarkCount 쿼리 추가. - QueryDSL 조회 시 commentCount 필드 매핑 추가.
[Performance Tuning] - 병목 해결 및 리소스 최적화를 위한 HikariCP 최대 풀 사이즈 조정: - portfolio-service: 10 -> 30 (부하 집중 구간 증설) - community-service: 10 -> 20 (부하 집중 구간 증설) - auth-service: 10 -> 5 (저부하 구간 축소) [Refactoring] - 미사용 spring-cloud-starter-openfeign 의존성 제거: - auth-service - portfolio-service - user-service - Application 클래스에서 @EnableFeignClients 어노테이션 제거 - �pplication.yml 내 불필요한 Feign 설정 정리
- PageImpl 역직렬화(Deserialization) 500 에러 해결을 위해 CustomPageResponse Wrapper 도입 - @Cacheable 어노테이션 제거 및 RedisTemplate을 사용한 수동 캐싱 로직으로 변경 (PostService와 동일 패턴 적용) - @CacheEvict 동작 보장을 위해 캐시 키 생성 규칙 변경 ('noticeList:...' -> 'noticeList::...') - JSON 문자열 처리에 최적화된 StringRedisTemplate 적용
- OpenFeign 라이브러리의 SortJsonComponent가 Page 객체의 Sort 필드 직렬화에 간섭하여 발생하는 500 에러(EncodeException) 해결 - 응답 시 Spring Data Page 인터페이스를 직접 반환하지 않고, 순수 POJO인 CustomPageResponse<T> 래퍼 클래스로 변환하여 반환하도록 변경 - PostController 내 목록 조회 API(전체/내 글/북마크) 반환 타입 수정 - 직렬화 전용 CustomPageResponse DTO 추가
[Support Service] - CustomPageResponse: Redis 캐싱 역직렬화 오류(NPE) 수정을 위한 @Setter 추가 - NoticeEntity: 공지사항 목록 조회 성능 개선을 위한 복합 인덱스(isImportant, createdAt) 추가 [Test Data Setup] - Community/Portfolio TestSetupController: 인덱스 효율성 검증을 위해 더미 데이터 생성 시 카테고리 및 직군이 고르게 분산되도록 개선 (Randomize) [k6 Load Test] - Community Workload: 실제 유저 패턴(카테고리 필터링)을 반영하여 인덱스를 정상적으로 타도록 스크립트 수정 - 집중 테스트 스크립트 추가: 서비스별 병목 구간 정밀 타격을 위한 community_load_test.js, portfolio_load_test.js 추가 - 테스트 결과 업데이트 (global_load_test_after) [DB Hikari connections] - 기존 20, 30개였던 connection을 10으로 고정(default 값)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📌 개요
| 이번 PR의 핵심 변경 사항을 한 문장으로 요약하여 작성해주세요.
ex) JWT 기반의 자체/소셜 로그인, 토큰 재발급, 로그아웃 등 핵심 인증/인가 기능을 구현합니다.
📋 작업 내용
| 이번 PR에서 작업한 내용들을 작성해주세요.
ex)
🔗 관련 이슈
| GitHub 이슈 번호가 있다면 Closes #이슈번호 형식으로 태그해주세요.
ex) Closes #15
✅ PR 체크리스트
💬 기타 사항
ex)