Notice
Recent Posts
Recent Comments
Link
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

KeepHunDev

4년동안 방치된 서비스 아키텍처 개선하기 본문

회고록

4년동안 방치된 서비스 아키텍처 개선하기

keephun 2026. 1. 15. 18:42

시스템 도서 위원회에서 체계가 없어 분산이 되었던 서비스를 새로운 자원 확보를 통한 문제 해결 경험을 회고 합니다.

6WAS 1DB

문제 정의: 4년간 누적된 데이터 및 코드 파편화

시도위 부서는 학생회비 납부 서비스, 사물함 관리 서비스, 야식마차 QR서비스 등 2022년부터 시작되어 지난 4년간 AWS 프리티어 환경 위에 분산되어 존재했습니다. 매년 예산 문제로 인해 통합 서버를 구축하지 못하고, 서비스가 추가될 때마다 새로운 AWS 프리티어 계정을 생성하여 배포하는 것이 반복되었습니다.

  1. 데이터 불일치
    물리적으로 DB를 합칠 수 없는 환경이었기에, 회원 테이블이 서비스마다 각각 생성되었습니다.
  2. 새로운 비즈니스 확장 어려움
    학생회비 납부 데이터는 사물함, 행사 참여, 투표 등 많은 서비스의 선행 조건이었습니다. 하지만 서비스들이 물리적으로 격리되어 있어, 납부 여부 확인을 위해 요청마다 학생회비 납부 확인 서버에 요청하여 IO 비용이 발생했습니다.

 

해결 목표: 온프레미스 제약 속에서 데이터 통합과 시스템 안정성 확보

이전에는 AWS 프리티어 환경에서 개발하다가, 올해부터 단일 온프레미스 서버(Intel Xeon 10 Cores, 32GB RAM)를 확보하였습니다.

7명의 개발팀과 6가지의 서비스에 대해 두 가지 목표를 달성해야 했습니다.

  1. 데이터 통합: 파편화된 데이터베이스를 하나의 데이터베이스로 합쳐 4년간에 파편을 하나의 테이블로 합치기
  2. 서비스 격리: 7명이 동시에 개발해도 형상 관리에 충돌이 없고, 특정 서비스의 장애가 발생해도 전체로 전파되지 않도록 설계하기

 

해결책

기존 6개의 서비스는 그대로 두고, 데이터베이스만 하나의 물리적 데이터 베이스 인스턴스로 통합했습니다.

 

왜 6WAS + 1DB

가장 고민했던 부분은 아키텍처의 구조였습니다. 일반적인 두 가지 선택지를 모두 기각하고 현재 구조를 택한 엔지니어링 근거는 다음과 같습니다.

  1. [기각] 1 WAS + 1 DB
  • 문제점: 7명의 개발자가 하나의 거대한 WAS 코드를 수정해야 합니다. 예를 들어 '기술 토론' 게시판의 사소한 버그 수정이 전체 시스템의 재배포를 유발하며, 메일 발송 로직의 스레드 지연이 로그인 기능까지 마비시키는 단일 장애 지점이 많은 구조였습니다.
  • 결론: 팀 규모와 서비스 안정성을 고려할 때, '배포 독립성'과 '장애 격리'를 보장하기 어렵다 판단하여 기각했습니다.
  1. [기각] 6 WAS + 6 DB
  • 문제점: 여전한 학생 테이블이 분리되어 정합성 문제를 다루고, 전체 사용자가 12,000명이라는 것을 고려했을때, 어플리케이션 레벨에서 JOIN을 할 수 없어서 성능상 느릴 것으로 판단되었습니다.
  • 결론: 현재의 사용자 규모와 트래픽에서는 데이터베이스 분리보다 조회 효율성과 트랜잭션 보장이 훨씬 중요하다고 판단하여 기각했습니다.
  1. [채택] 6 WAS + 1 DB
  • 이유: WAS는 기획된 서비스 6개로 나누어 장애 전파를 차단하고, 배포 유연성을 확보됩니다. 반면 데이터베이스는 정합성 해결 및 JOIN 사용을 위해 1개로 통합하였습니다.

 

아키텍처 선택과 Trade-off

  • 서비스 격리: 6개로 분리된 서비스를 어떻게 독립적인 배포 보장과 격리할 것인가?
  • 데이터 베이스 통합: 7명의 개발자가 하나의 DB에 DDL을 정의할 때 발생하는 충돌을 어떻게 막을 것인가?

 

Multi Repo 도입

6개의 WAS로 서비스가 분리됨에 따라, 소스 코드 관리 및 빌드 전략에 대해 Multi-Module(Mono-Repo) 도입과 Multi-Repo 도입을 고민했습니다.

  1. [기각] Mono-Repo
  • 장점
    • 공통 모듈을 통해 코드 재사용성을 극대화하고, 프로젝트 전체의 데이터 포맷을 일관성 있게 관리하기 유리합니다.
    • Gradle의 빌드 캐시와 증분 빌드를 활용하여, 변경되지 않은 모듈의 빌드 성능을 최적화하기 유리합니다.
  • 문제점
    • 6개의 서비스가 하나의 빌드 스크립트에 묶이게 됩니다. 공통 모듈을 조금만 수정해도 의존하는 모든 서비스가 재빌드되거나, 이를 방지하기 파이프라인을 구현하는 것이 복잡한 오버 엔지니어링이라고 느꼈습니다.
  1. [채택] Multi-Repo
  • 단점: DTO나 Utility 클래스 같은 공통 코드를 각 리포지토리에 중복해서 작성해야 하는 코드 중복 비용이 발생합니다.
  • 장점: 각 서비스가 물리적으로 완벽히 격리되므로, 서로의 빌드 및 배포 일정에 영향을 독립성을 보장합니다.
  • 이유: 앞으로 체계가 잡힌다면 인원은 더 늘어날 것 이고, 서비스별로 인수인계를 나눌 때 레포를 분리해서 관리하는 게 더 효율적이라고 판단했습니다. 또한 공통 코드가 많아진다면 자체적인 라이브러리를 만들어 관리하면 된다고 판단하였습니다.

 

데이터 베이스 형상 관리 하기

7명의 개발자가 하나의 통합 데이터 베이스를 공유하는 구조에서, 우려되었던 점은 개발자들의 JPA ORM 기능으로 인한 의도치 않은 스키마 변경과 변경 이력 추적의 어려움이었습니다. 이를 해결하기 위해 데이터베이스 관리 권한을 제어하는 시스템 체계를 구축했습니다.

  1. ddl-auto: none

편리하다는 이유로 사용되던 JPA의 ddl-auto 옵션을 모든 실제 환경에서 none으로 설정하여 비활성화했습니다.

  • 의도: 애플리케이션 배포 시점이 아닌, 개발자가 명시적으로 의도한 시점에만 DB가 변경되도록 통제했습니다. 이를 통해 실수로 인한 컬럼 삭제나 데이터 유실 사고를 원천 차단했습니다.
  1. Flyway 기반의 형상 관리

DB 스키마 변경 사항을 관리하기 위해 Flyway 전용 리포지토리를 별도로 구축했습니다.

  • 프로세스: 테이블을 수정하려면 누구나 SQL 마이그레이션 스크립트를 작성하여 Pull Request를 올려야 합니다.
  • 코드 리뷰의 대상: "왜 이 컬럼이 필요한가?", "인덱스는 적절한가?"에 대해 팀원들의 리뷰와 승인을 거쳐야만 Merge가 되고, CD 파이프라인을 통해 DB에 반영됩니다.

 

마치며

저의 Core Value는 '나의 무지를 인정하고, 학습으로 최적의 해답을 찾는 것'입니다.

 

처음 문제를 접근할때, 서비스가 많으니까 MSA를 도입해야 하지 않을까?라는 막연한 생각을 했었습니다. 하지만 7명의 팀원, 12,000명의 사용자, 단일 서버라는 현재의 자원을 객관적으로 분석하고 공부하면서 MSA가 우리에게는 오버 엔지니어링임을 깨달은 경험이었습니다.

 

앞으로도 모르는 것을 부끄러워하지 않고, 데이터와 근거를 통해 문제를 해결해 내는 개발자가 되겠습니다.