프로젝트 / ORBIT

ORBIT

기관의 구매요청부터 결재, 예산 관리까지 한곳에서 처리하는 통합 구매 관리 시스템

기간
2025.02.24 ~ 2025.03.27
인원
4명 (기능 단위로 나눠 각자 백엔드·화면 모두 개발)
담당
구매요청 · 결재선 · 예산 검증 · 실시간 알림 · CI/CD
기술
Spring BootSpring SecurityJPAJWTOAuth2JUnitRedisWebSocket (STOMP)MariaDBReactRedux ToolkitMUIViteGitHub ActionsAWS EC2AWS RDSNginxSwagger
링크
GitHub시연 영상

개요

사업 유형마다 입력 폼이 달라지고, 예산 동시성 검증, 결재선 구성, 상태 전이 같은 복잡한 업무 규칙이 얽힌 구매 업무를 디지털화한 시스템입니다.

구매요청, 결재와 결재선, 프로젝트, 공통코드, 품목, 대시보드, 로그인, CI/CD 등 핵심 기능 전반을 맡아 백엔드와 화면을 함께 설계하고 개발했습니다.

맡은 일

  • 구매요청 관리
  • 결재·결재선 관리
  • 프로젝트 관리
  • 공통코드 관리
  • 품목 관리
  • 대시보드
  • 로그인·회원가입
  • CI/CD

핵심 성과

동적 폼
사업 유형별로 달라지는 입력 항목에 맞춰 폼을 그리는 구조
예산 검증
트랜잭션 안 SELECT FOR UPDATE 로 예산 동시성 문제 해결
결재 상태머신
Enum 기반 상태 전이로 승인·반려 흐름을 명확하게
실시간 알림
WebSocket + Redis Pub/Sub 기반 결재 알림
자동 배포
GitHub Actions 로 CI/CD 를 구성하고 EC2 에 자동 배포

문제와 해결

문제 1
실시간 알림이 빠지거나 두 번 가던 문제
문제
결재 승인 때 WebSocket·메일·SMS 알림이 중복되거나 누락됨
원인
알림을 한 줄로 이어 보내 하나가 실패하면 뒤가 모두 멈췄고, 구독 경로가 사용자 단위가 아니라 여러 곳에서 로그인하면 중복 전송됨
해결
채널마다 실패 범위를 따로 나누고, 구독 경로를 사용자 기준(/user/{username}/queue)으로 바꿈
결과
QA 에서 누락·중복이 사라졌고, 장애가 나도 원인을 찾기 쉬워짐
문제 2
병렬 결재 뒤 화면이 '대기'로 남던 문제
문제
실제로는 승인됐는데 화면에는 '대기' 상태로 남음
원인
상태를 저장하기 전에 화면 실시간 전송이 먼저 나감
해결
상태 변경을 트랜잭션 안으로 옮기고, 실시간 전송은 @TransactionalEventListener 로 커밋 뒤에만 실행
결과
트랜잭션 일관성을 지키고 화면 잔류 현상이 사라짐
문제 3
반려 뒤에도 다음 결재선이 남던 문제
문제
반려됐는데 뒤 단계 결재선이 여전히 PENDING
원인
반려 흐름에 남은 단계를 끝내는 로직이 빠져 있었음
해결
남은 결재선을 모두 REJECTED 로 바꾸는 단계를 따로 만들어 분기 처리
결과
상태 흐름 오류와 반려 뒤 승인 혼선이 사라짐

회고 및 개선 방향

아키텍처 전환
모놀리식으로 빠르게 시작했지만 도메인 결합도가 커졌다. 구매요청·결재·입찰·계약 단위로 나누고 Kafka 같은 메시지 큐로 이벤트를 주고받는 구조를 생각했다
성능 최적화
결재·상태머신의 복잡한 쿼리와 트랜잭션을 쿼리 분석, 인덱스, 트랜잭션 분리로 다듬고, 정확성과 성능의 균형을 더 찾아보고 싶다
테스트 체계
워크플로 중심 서비스인데 테스트가 부족했다. 상태 변경·롤백·비동기 이벤트를 중심으로 단위·통합 테스트를 갖추려 한다
운영 지표
결재 지연 시간, 평균 승인 횟수 같은 지표를 모아 관리자 대시보드로 보여 주고 싶다