[개발 리포트] Monew 프로젝트

1. 프로젝트 개요

  • 서비스 명: Monew (관심 뉴스 구독 및 커뮤니티 서비스)
  • 목적
    • 사용자 맞춤형 관심사 기반 뉴스 수집/제공 및 활동 내역 조회 및 알림 시스템 구축
  • 주요 기능
    • 관심 키워드 기반 뉴스 수집 및 구독 기능
    • 관심 뉴스 등록 및 좋아요 알림 서비스
    • 활동 로그 기반의 마이페이지 통계 및 내역 관리

2. 담당 작업

  • 알림 관리 API: 이벤트 기반 알림 아키텍처 설계, 알림 조회 및 벌크 업데이트 구현
  • 배치 처리: 확인 알림 자동 삭제 배치 구현 (Spring Batch)
  • 인프라 및 CI/CD: AWS ECS 환경 구축, Docker Multi-stage 빌드 최적화, GitHub Actions 파이프라인 구성
  • 성능 및 테스트: Locust 기반 부하 테스트 시나리오 작성, Testcontainers 기반 통합 테스트 환경 표준화

3. 기술적 성과

  • 이벤트 기반 알림 시스템: Spring Event와 TransactionPhase.AFTER_COMMIT을 활용하여 메인 로직 성공 시에만 알림이 저장되는 안정적인 비동기 구조 확립
  • 배치 작업 최적화: Native Query와 Limit 절을 조합한 분할 삭제 방식을 도입하여 배치 실행 시 DB 락(Lock) 경합 최소화
  • 품질 관리 지표: Jacoco를 활용한 엄격한 테스트 관리로 최종 테스트 커버리지 85% 달성(TDD 도입)
  • AWS Lambda 함수 사용: 로그를 직접 S3 버킷에 백업하지 않고 Lambda와 이벤트 스케줄러를 사용하여 서비스 외부에서 자동화
  • CI/CD 배포 파이프라인: ECS Task Definition을 json으로 정의하여 IaC로 배포 파이프라인 구축

4. 문제 해결 과정

[문제 1] 알림 내역 조회 성능 저하 (복합 인덱스 활용)

  • 상황
    • 사용자 알림 내역 조회 시 데이터 누적에 따른 응답 속도 저하 발생
  • 분석
    • user_id, is_confirmed, created_at 등 여러 조건이 혼합된 쿼리에서 풀 스캔 발생
  • 해결
    • 최적의 복합 인덱스(Composite Index) 설계 및 쿼리 튜닝
  • 결과
    • 대량 데이터 환경에서도 일정한 수준의 알림 조회 성능 확보 및 서버 리소스 절감
  • 관련 PR 및 이슈

[문제 2] 통합 테스트 환경 개선 (Testcontainers 활용)

  • 상황
    • 테스트에서 사용하는 H2 환경과 실제 운영 환경(PostgreSQL)의 문법 및 제약 조건 차이로 인한 테스트 일관성 보장 X
  • 분석
    • 인메모리 DB의 한계로 인해 실제 DB 전용 쿼리나 제약 사항 검증 불가 → 테스트 결과가 매번 바뀜
  • 해결
    • 통합테스트에서 Testcontainers 라이브러리를 도입하여 도커 컨테이너 기반의 독립적인 테스트 환경 구축
  • 결과
    • 실제 서비스 환경과 동일한 상태 유지 및 CI/CD 환경에서도 테스트 정합성 보장
  • 관련 PR 및 이슈

[문제 3] 멀티 스레드 환경에서 동일 시간 배치 작업 기록 실패 (격리 수준 변경)

  • 상황
    • 동일 시간에 실행되는 배치 작업의 경우(정각-뉴스수집, 특정 정각시간-삭제 작업) 한 개의 작업이 실패하는 문제 발생
  • 분석
    • 로그 분석 결과 데이터베이스에 배치 작업 기록 시도 시에, SERIALIZE 설정으로 하나의 작업만 성공하고 나머지 실패
    • 데이터베이스 배치 작업 테이블의 격리 수준 확인 결과, READ_COMMITTED 으로 테이블 문제가 아닌 것을 확인
    • 기존 BatchConfig에서 기본 스프링 배치 설정 사용으로 인해 SERIALIZE 설정 적용인 것을 확인
  • 해결
    • BatchConfig가 DefaultBatchConfiguration를 상속받도록 하고 getIsolationLevelForCreate() 을 오버라이딩하여 격리 수준을 READ_COMMITTED으로 변경
  • 결과
    • 멀티 스레드로 동시에 여러 배치 작업이 실행되어도 데드락 발생 X
  • 관련 PR 및 이슈

[문제 4] 관심사 이름 순 정렬 실패 (COLLATE “ko-KR-x-icu” 설정)

  • 상황
    • 관심사 이름으로 정렬 시, 한글에서 정렬 순서가 꼬이는 문제 발생
  • 분석
    • Postgres의 기본 COLLATE 설정이 영어로, 한글 정렬이 제대로 반영 X
    • 전체 DB에 “ko-KR-x-icu” 설정을 위해서는 처음 생성 시 적용 필요하나 이미 서비스가 운영 중
  • 해결
    • 관심사 테이블에만 정렬 조건 적용(한글 정렬이 필요한 유일한 테이블임으로)
      ALTER TABLE interests
      ALTER COLUMN name TYPE VARCHAR(100) COLLATE "ko-KR-x-icu";
    
  • 결과
    • 한글 정렬 성공
  • 관련 PR 및 이슈

5. 협업 및 피드백

  • 한글 정렬 문제
    • 데이터베이스를 새로 생성하고 기존 데이터를 옮기는 방식 대신 서비스 코드에서 해당 열 조회 시 쿼리문에 “ko-KR-x-icu” 조건을 넣는 것 고려하고 담당자가 진행하였으나, 단위 테스트에서 h2를 사용하여 해당 쿼리문이 유효하지 않아 테스트 검증이 실패하는 문제 발생

      → sql 문으로 해결 → 기존 sql 스크립트에 반영

6. 코드 품질 및 최적화

1) TDD 방식 도입

  • 상황
    • TDD 방식을 도입하여 개발을 진행
  • 결과
    • RED-GREEN-REFACTOR 과정에서 발생할 수 있는 예외를 미리 처리함으로써 코드의 안정성 향상
    • 다른 도메인과 연결된 경우에도 테스트 코드에서 여러 상황을 가정하여 작성하여 오류 발생 X
  • 관련 PR 및 이슈

2) Dev Branch PR Convention

  • 상황
    • Dev 브랜치 PR 시 자동으로 테스트가 실행되도록 워크 플로우를 구성하고 CodeCov 설정을 추가하여 새로운 PR 내역의 커버리지의 테스트 조건을 70%를 넘길 것을 강제
    • 초기 개발 이후 전체 커버리지 70% 이상을 달성하고, 전체 커버리지 조건 추가
  • 결과
    • 최종 커버리지 90% 달성
  • 관련 PR 및 이슈

7. 향후 개선 사항

  • 대량의 관심 기사 등록 알림 처리를 위한 Spring Batch 전환 및 벌크 인서트 적용
  • CI/CD 배포 파이프라인에서 ACCESS KEY 인증 방식에서 Role 기반의 OIDC 방식으로 전환
  • 일부 기능에 캐시를 도입하여 서비스 성능 개선
  • K6와 같은 다른 종류의 부하테스트 도구 활용
  • Grafana 또는 Prometheus 활용
  • 도메인 중심 패키지 구조로 변경

Leave a comment