MySQL DB 인덱싱을 통한 모듈 조회 성능 최적화
·
[프로젝트] Modulo
1. 문제 상황1.1 성능 측정회원별 모듈(프로젝트, 경력, 교육 등) 조회 시 603ms의 응답시간주요 원인: member_id 기반 조회 시 테이블 Full Scan 발생1.2 문제 분석SELECT * FROM project p WHERE p.member_id = ?위 쿼리 실행 시 인덱스 없이 전체 테이블 스캔다수의 연관 엔티티에서 동일 패턴 발생2. 해결 방안2.1 인덱스 설계@Entity@Table(indexes = @Index(name = "idx_project_member", columnList = "member_id"))public class Project extends BaseTimeEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColu..
JPA N+1 문제 해결과 성능 최적화: Fetch Join 적용으로 성능 개선 (9s -> 6s, 48s -> 15s)
·
카테고리 없음
1. 문제 상황이력서 관리 시스템을 개발하면서 다음과 같은 성능 이슈가 발생했다:이력서 조회 시 연관된 섹션과 콘텐츠를 가져오는 과정에서 N+1 문제 발생여러 개의 @OneToMany 연관관계에 대한 fetch join 시도 시 Hibernate의 MultipleBagFetchException 발생도메인 구조Resume (1) --- (*) ResumeSection (1) --- (*) SectionContent2. 성능 테스트 결과=== 단일 이력서 조회 성능 테스트 ===기존 방식 실행 시간: 9.149166ms기존 방식 쿼리 수: 3분리 쿼리 실행 시간: 6.0795ms분리 쿼리 수: 2=== 회원별 이력서 목록 조회 성능 테스트 ===기존 방식 실행 시간: 48.222042ms기존 방식 쿼리 수:..
MySQL 데이터베이스 마이그레이션하기
·
[프로젝트] Modulo
배경 Modulo 프로젝트는 사용자가 이력서를 간편하게 작성하고 조합할 수 있도록 하는 것이 주요 목적이었다. 프로젝트 진행 중 "README 작성이 없어서 아쉽다"는 피드백을 받았으나, README를 추가하는 것은 '간단한 이력서 작성'이라는 원래 취지에서 벗어난다고 판단했다. 대신 이력서 테마 기능을 추가하여 사용자 경험을 개선하기로 결정했다. 하지만 이 과정은 테이블을 수정해야 하는 일이였기에 바로 운영서버에서 테이블을 바꾸는것보다는, 개발 서버에서 먼저 테스트를 해본뒤에 운영서버에 적용하는 것이 나을 것이라고 생각하여 운영환경의 RDS 데이터를 개발 환경 Docker Container의 MySQL로 마이그레이션하여 테스트하기로 결정하였다.데이터 마이그레이션 과정1. RDS에서 데이터 덤프운영 환경..
Spring Boot Global Exception Handler 로깅 개선: X-Forwarded-For vs X-Real-IP
·
[프로젝트] Modulo
Spring Boot에서 예외 처리와 보안 설정 개선하기배경Spring Boot 애플리케이션에서 Global Exception Handler를 구현했으나, 운영 환경에서 유의미한 로그 수집에 어려움을 겪었다. 특히 NoResourceFoundException이 발생했을 때, 어떤 클라이언트가 어떤 경로로 요청했는지 파악하기 어려웠고, 보안 설정도 최적화가 필요했다.초기 상태와 문제점1. 로깅 시스템처음에는 다음과 같이 최소한의 정보만 로깅됐다:2025-01-13T03:35:42.369Z ERROR 1 --- [io-8080-exec-10] c.e.M.g.e.GlobalExceptionHandler : Class: NoResourceFoundException, Status: 500, Message: 내부 ..
Redis Cache 불일치 해결과 Cache Eviction 전략 개선
·
[프로젝트] Modulo
배경Modulo의 원활한 운영을 위해 Redis Cache를 도입했으나, 실제 운영 과정에서 캐시 동기화 문제가 발생했다. 이는 데이터베이스만 사용했을 때는 발생하지 않던 문제로, Redis Cache 도입 이후 Cache Eviction 이슈였다.Google Form 응답Q: Modulo 사용 중 불편했던 점이나 개선이 필요한 부분을 알려주세요.A: 이력서 모듈(프로젝트, 학력 정보 등)을 수정한 후 이력서 페이지로 돌아갔을 때 변경된 내용이 바로 보이지 않고 이력서에서 삭제 후 다시 추가를 해야 반영됩니다!요구사항 분석마주한 과제는 다음과 같았다:Cache 키 포맷 일관성 확보Cache Eviction 전략 개선연관 캐시 동기화 구현업데이트/삭제 시 일관된 캐시 처리Cache 키 포맷 통일모든 ..
Redis 캐시 도입을 통한 이력서 관리 시스템 성능 최적화: 응답 시간 87% 감소, 처리량 413% 향상 - Redis Template API vs Lua Script
·
[프로젝트] Modulo
1. 도입 배경이력서 관리 시스템 'Modulo'의 성능 테스트 중 여러 모듈(기본 정보, 경력, 학력, 프로젝트 등)의 데이터를 조합하는 과정에서 API 응답 시간 지연이 발생했다. 특히 SavedModule과 Resume 조회 시 여러 서비스의 데이터를 조합하는 과정에서 성능 저하가 두드러졌다. 캐시 도입 전 k6 성능 테스트 결과는 다음과 같다:# 캐시 적용 전 k6 테스트 결과✓ basic_info_get_all_duration....: avg=17.128329 min=13 med=15 max=232 p(90)=18 p(95)=21 ✓ resume_get_all_duration........: avg=43.515738 min=36 med=40 max=365 p(90)=47..
운영환경, 개발환경 분리하기
·
[프로젝트] Modulo
배경1월 7일 최종 테스트를 앞두고, 개발 환경과 운영 환경을 분리할 필요성이 생겼다. 기존의 개발 환경을 운영 환경으로 전환하고, 비용 효율적인 새로운 개발 환경을 구성하기로 했다.요구사항 분석팀에서 마주한 과제는 다음과 같았다:기존 개발 환경을 운영 환경으로 전환비용 효율적인 새로운 개발 환경 구성운영/개발 환경의 데이터 분리배포 자동화 구성현재 시스템은 EC2에서 애플리케이션이 실행되고 있었으며, 별도의 EC2에서 Nginx가 리버스 프록시 역할을 수행하고 있었다.운영 환경 구성기존 개발 환경을 운영 환경으로 전환하면서 다음과 같이 설정했다:spring: jpa: hibernate: ddl-auto: validate properties: hibernate: ..
MAU 측정하기(비관락, 낙관락, Write back)
·
[프로젝트] Modulo
배경1월 7일에 최종 테스트를 하고, 1월 8일에 정식으로 Modulo를 배포하기로 하였다. 1월 5일인 현재 모든 API 연동이 완료되었고, 실배포하기 전에 MAU를 측정을 구현하기로 했다.요구사항 분석팀에서 마주한 과제는 다음과 같았다:일별 활성 사용자(DAU)를 측정하고, 이를 월 단위로 집계하여 MAU 산출AOP를 활용한 사용자 활동 자동 측정실시간성 필요 없음. 익일에 확인 가능하면 됨데이터 정확성 보장시스템 확장성 확보현재 사용자 인증은 Spring Security를 사용하고 있었으며, SecurityContext의 ThreadLocal에서 사용자 ID를 가져오고 있었다:public class SecurityUtil { private static Long getCurrentMemberId..
[프로그래머스] 불량 사용자
·
Algorithm
https://school.programmers.co.kr/learn/courses/30/lessons/64064?language=cpp 프로그래머스SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프programmers.co.kr #include #include #include using namespace std;bool isEqual(string user_id, string banned_id){ if(user_id.size()!=banned_id.size()) return false; for(int i=0;i& user_id, vector& banned_id, vector& visited, set& result) { ..
[프로그래머스] 두 큐 합 같게 만들기
·
Algorithm
https://school.programmers.co.kr/learn/courses/30/lessons/118667?language=cpp 프로그래머스SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프programmers.co.kr  #include #include #include using namespace std;int solution(vector queue1, vector queue2) { queue q1, q2; long long total1 = 0, total2 = 0; for(int i = 0; i total2) { int val = q1.front(); q1.pop(); ..
kwon-record
kwon-record 님의 블로그