레거시 시스템 고도화 디비피아원 누리미디어 테크블로그

레거시 시스템 고도화 디비피아원

누리미디어 테크블로그

about 1

레거시 시스템 고도화 디비피아원

안녕하세요. 누리미디어 백엔드 파트 개발자입니다. 이번에 누리미디어에서 서비스하는 디비피아원 서비스를 고도화를 진행하게 되었는데요. 이번 글에서는 고도화를 진행하게 된 이유부터 과정과 결과까지 안내드리려 합니다. 디비피아원은 누리미디어 디비피아 원스탑 내에 제공되는 온라인 논문 투고 시스템 입니다. 디비피아원은 2016년도에 개발된 시스템으로, 학술 자료를 제공하는 플랫폼의 일환으로 다양한 고객사의 요구를 충족시키기 위해 설계되었습니다. 그러나 7년이 넘는 시간 동안 시스템은 점차 레거시화되었고, 기술적 부채와 함께 성능 및 안정성에 대한 요구가 높아졌습니다. 특히, 서버 이중화와 세션 관리, 데이터베이스 분리 및 성능 최적화와 같은 작업이 절실히 필요한 상황이었습니다. 이에 따라 최근 디비피아원 시스템을 고도화하는 프로젝트를 진행하며 여러 가지 문제를 해결하고, 성능과 안정성을 동시에 향상시키기 위한 노력을 기울였습니다. 이번 글에서는 디비피아원의 고도화 과정에서 겪었던 도전과 이를 해결하기 위한 기술적인 접근 방식을 공유하고자 합니다.

제목없음

제목없음

1. 프로젝트 배경 디비피아원의 역할과 기존 시스템의 한계 디비피아원은 2016년에 개발된 이후로 지속적인 기능 추가와 환경 변화에 적응하는 과정에서 기술적인 부채가 누적되었습니다. 초기 설계 당시에는 단일 서버와 공유 데이터베이스를 기반으로 운영되었지만, 시간이 지나면서 다음과 같은 한계점이 발생했습니다. 1. 트래픽 부하 문제 - 디비피아원이 사용하는 데이터베이스가 다른 프로젝트와 공유되고 있어, 특정 프로젝트에 트래픽이 몰릴 경우 디비피아원도 부하를 받는 구조였습니다. 이는 안정적인 서비스 제공에 큰 장애 요인이 되었습니다. 2. 확장성 부족 - 단일 서버 아키텍처로 인해 서버 부하가 증가할 경우 적절한 확장성이 부족했습니다. 이로 인해 고가용성과 안정성을 보장하기 어려웠습니다. 3. 성능 저하 - 시간이 지나면서 데이터 양이 급격히 증가했고, 데이터베이스와 쿼리 성능 문제가 서비스 속도 저하로 이어졌습니다. 7년 이상 운영된 디비피아원은 레거시 시스템으로 분류되었으며, 기술 스택의 노후화로 인해 유지보수가 점점 어려워지고 있었습니다. 특히, 다음과 같은 문제가 고도화의 필요성을 더욱 부각시켰습니다. 1. 기술 스택의 제한 - 디비피아원은 오래된 기술 스택으로 개발되어 현대적인 기술 적용에 제약이 있었습니다. 2. 복잡한 코드 구조 - 초기 개발 당시의 설계가 이후 추가된 기능들로 인해 복잡해지면서 유지보수 비용이 점점 증가했습니다. 3. 고객 요구 증가 - 고객사들의 서비스 안정성과 성능에 대한 요구가 점점 증가하면서 기존의 인프라로는 이를 충족시키기 어려운 상황이 되었습니다. 이러한 문제를 해결하고 디비피아원을 보다 안정적이고 효율적인 시스템으로 거듭나게 하기 위해, 고도화 프로젝트가 시작되었습니다. 이번 프로젝트는 서버 이중화와 Redis를 이용한 세션 관리, 데이터베이스의 RDS 이전, 그리고 쿼리 튜닝과 같은 주요 작업들을 중심으로 진행되었습니다.

제목없음

제목없음

2. 서버 이중화 및 세션 관리 서버 이중화 분리 작업의 기술적 접근 디비피아원 시스템은 단일 서버 아키텍처로 운영되고 있었기 때문에, 서버 장애 발생 시 서비스 전체가 중단될 위험이 있었습니다. 이러한 단일 장애점(Single Point of Failure)을 제거하고 고가용성을 확보하기 위해 서버 이중화 작업을 진행했습니다. 1. 이중화 환경 설계 - AWS 환경에서 Application Load Balancer(ALB)를 활용하여 다중 서버를 구성했습니다. ALB는 요청을 두 대 이상의 서버로 분산 처리하며, 서버 중 하나에 문제가 발생해도 다른 서버가 서비스를 지속적으로 제공할 수 있도록 설정되었습니다. - ALB의 Health Check 기능을 통해 장애가 발생한 서버를 자동으로 감지하고 요청 분배에서 제외시키도록 구성하였습니다. 2. 세션 유지 문제 해결 - 기존에는 단일 서버에서 세션을 관리했기 때문에 서버가 분리되면 세션이 각 서버에 독립적으로 저장되는 문제가 있었습니다. 이를 해결하기 위해 Redis를 활용하여 세션 데이터를 중앙에서 관리하도록 설계하였습니다. Redis를 활용한 세션 관리 도입 배경 및 구현 과정 서버 이중화로 인해 세션 관리 방식에도 변화가 필요했습니다. 기존에는 서버 내 메모리에 세션을 저장했지만, 이중화된 환경에서는 이를 사용할 수 없었습니다. 따라서 Redis를 활용한 세션 관리로 전환하게 되었습니다. 1. 도입 배경 - 세션 공유 문제 해결: 분산된 서버 간에 세션 데이터를 공유하여 사용자가 어떤 서버로 라우팅되더라도 동일한 세션 상태를 유지할 수 있도록 하기 위해 Redis를 선택했습니다. - 성능과 확장성: Redis는 메모리 기반 저장소로, 빠른 읽기/쓰기 성능과 확장성을 제공하여 세션 데이터를 관리하기에 적합합니다. - TTL 지원: Redis의 TTL(Time To Live) 설정을 통해 일정 시간 동안만 세션 데이터를 유지하도록 하여 불필요한 데이터를 자동으로 정리할 수 있었습니다. 2. 구현 과정 - Spring Session Integration: Spring Session과 Redis를 연동하여 세션 데이터를 관리하도록 설정했습니다. 이를 통해 세션 데이터를 Redis에 저장하고, 서버 간 세션 공유가 가능해졌습니다. - Redis Sentinel 구성: 고가용성을 위해 기존 DBpia 에서 사용하고 있던 Redis Sentinel을 활용하여 Redis 클러스터를 구성했습니다. 이를 통해 Redis 장애 발생 시 자동으로 복구할 수 있는 환경을 마련했습니다. - TTL 설정: 세션 유효 기간을 2시간으로 설정하여, 일정 시간이 지나면 세션 데이터가 자동으로 삭제되도록 하였습니다. - RedisTemplate 설정: 세션 데이터를 JSON 형식으로 직렬화/역직렬화하기 위해 GenericJackson2JsonRedisSerializer를 활용하여 RedisTemplate을 커스터마이징했습니다. 3. 성과 - 세션 관리의 안정성과 효율성이 크게 향상되었으며, 이중화된 서버 간에 세션 데이터를 일관되게 유지할 수 있었습니다. - Redis Sentinel 구성으로 인해 Redis 장애에도 서비스를 지속적으로 운영할 수 있게 되었습니다. - 이중화를 구성하게 되며, 서비스 중단 없이 배포를 할 수 있게 되었습니다.

메인

3. DB RDS 이전 및 성능 최적화 기존 DB 구조와 문제점: 공유 DB의 트래픽 부하 디비피아원은 초기 설계 당시 여러 프로젝트가 하나의 MS SQL Server 데이터베이스를 공유하는 구조로 구축되었습니다. 이러한 구조는 단기적으로는 유지보수가 용이했지만, 시간이 지남에 따라 여러 문제를 초래했습니다. 1. 트래픽 부하 분산 실패 - 특정 프로젝트에 과도한 트래픽이 발생하면 디비피아원도 영향을 받아 성능 저하가 발생했습니다. 이는 고객사 요구에 신속히 대응하지 못하는 주요 원인이 되었습니다. 2. 독립성 부족 - 디비피아원의 운영 환경이 다른 프로젝트의 변경 사항에 영향을 받으면서 안정적인 서비스 제공에 어려움을 겪었습니다. 3. 확장성 한계 - 점점 증가하는 데이터와 트랜잭션 수요를 처리하기에는 기존 환경이 비효율적이었습니다. 쿼리 튜닝을 통한 성능 최적화 - RDS 이전의 효과를 극대화하기 위해 주요 쿼리와 Stored Procedure를 대상으로 튜닝 작업을 진행했습니다. 1. 주요 튜닝 사례 - 복잡한 Stored Procedure에서 중복된 서브쿼리를 제거하고, 필요 없는 인덱스를 정리했습니다. - 적절한 인덱스 설계와 실행 계획 분석을 통해 테이블 스캔을 최소화하고, 효율적인 인덱스 탐색이 가능하도록 최적화했습니다. 2. 성능 개선 지표 및 결과 - 쿼리 실행 속도: 주요 쿼리의 실행 속도가 평균 30~50% 개선되었습니다. - 트랜잭션 처리량: 데이터베이스의 초당 처리 트랜잭션 수(TPS)가 기존 대비 약 40% 증가했습니다.

프로시저 쿼리 튜닝 작업 요약 1. 인덱스 추가 2. 중복된 서브쿼리 제거- 문제점: 프로시저 내부에서 동일한 서브쿼리가 여러 번 호출되어 성능 저하가 발생. - 해결 방법: 서브쿼리를 WITH 구문(Common Table Expression)으로 추출하여 재사용. - 결과: 쿼리 실행 속도 약 20~30% 개선.

-- 개선 이전 쿼리SELECT A.COL1, A.COL2, (SELECT COUNT(*) FROM TABLE_B WHERE TABLE_B.ID = A.ID) AS COUNT1, (SELECT COUNT(*) FROM TABLE_B WHERE TABLE_B.ID = A.ID AND TABLE_B.TYPE = 'X') AS COUNT2FROM TABLE_A AWHERE A.STATUS = 'ACTIVE'; -- 개선 후 쿼리WITH CTE AS ( SELECT ID, COUNT(*) AS TOTAL_COUNT, SUM(CASE WHEN TYPE = 'X' THEN 1 ELSE 0 END) AS TYPE_X_COUNT FROM TABLE_B GROUP BY ID)SELECT A.COL1, A.COL2, C.TOTAL_COUNT, C.TYPE_X_COUNTFROM TABLE_A ALEFT JOIN CTE C ON A.ID = C.IDWHERE A.STATUS = 'ACTIVE';

3. 임시 테이블 활용 - 문제점: 복잡한 조인을 포함한 쿼리에서 실행 시간이 길어지는 문제. - 해결 방법: 중간 결과를 임시 테이블에 저장하여 여러 번 참조하는 경우 성능 개선. - 결과: 전체 프로시저 실행 시간이 약 30% 단축.

-- 개선 이전 쿼리SELECT A.ID, SUM(B.AMOUNT)FROM TABLE_A AJOIN TABLE_B B ON A.ID = B.IDWHERE B.STATUS = 'COMPLETE'GROUP BY A.IDHAVING SUM(B.AMOUNT) > 1000; -- 개선 후 쿼리-- 임시 테이블 활용SELECT ID, SUM(AMOUNT) AS TOTAL_AMOUNTINTO #TEMP_TABLEFROM TABLE_BWHERE STATUS = 'COMPLETE'GROUP BY ID; SELECT A.ID, T.TOTAL_AMOUNTFROM TABLE_A AJOIN #TEMP_TABLE T ON A.ID = T.IDWHERE T.TOTAL_AMOUNT > 1000;

프로시저 쿼리 튜닝 결과 요약

최종 성과 이번 프로젝트를 통해 디비피아원 시스템은 다음과 같은 성과를 얻었습니다. - 고가용성 확보: Redis와 AWS 기반의 서버 이중화로 인해 장애 상황에서도 안정적인 서비스 제공. - 성능 최적화: 쿼리 튜닝과 세션 데이터 관리 개선으로 응답 속도와 트랜잭션 처리 속도가 크게 향상. - 운영 효율성 향상: 불필요한 데이터와 자원 낭비를 줄이고, 유지보수와 확장성을 개선. 디비피아원 시스템의 고도화 프로젝트는 기술적 도전과 성과를 동시에 경험할 수 있는 중요한 여정이었습니다. 이번 프로젝트를 통해 얻은 교훈을 기반으로, 앞으로도 지속적인 개선과 기술 도입을 통해 디비피아원을 더욱 안정적이고 유연한 시스템으로 발전시킬 예정입니다.

people

채용 공고 보러가기 ↗︎

img

homepage logo image
누리미디어
문화
블로그
채용