본문 바로가기

Spring Boot 기반 업무시스템을 운영할 때 고려할 것

배포 중 장애, 로그 분리, 세션과 권한, 외부 연동 실패 격리, 백업. 만든 시스템을 직접 운영하며 반복해서 부딪히는 항목을 체크리스트로 정리했습니다.

만든 뒤가 더 길다

업무 시스템은 오픈이 끝이 아니라 시작입니다. 개발 기간이 3개월이라면 운영 기간은 몇 년입니다. 아래는 Java/Spring Boot로 만든 업무 시스템을 직접 운영하면서 반복적으로 부딪히는 항목을 정리한 것입니다. 프레임워크 기능 설명이 아니라 운영에서 실제로 아픈 지점 위주입니다.

1. 배포 중에 서비스가 깨지지 않게

실행 중인 애플리케이션의 jar 파일을 같은 자리에 덮어쓰면 아직 살아 있는 프로세스가 깨진 파일을 읽어 오류가 납니다. 재시작 직전까지의 요청이 전부 실패할 수 있습니다.

  • 새 파일을 다른 이름으로 올린 뒤, 재시작 직전에 같은 디렉터리에서 이름만 바꾸는 방식으로 교체합니다(원자적 교체).
  • 이름 바꾸기는 디렉터리 항목만 바꾸므로, 기존 프로세스는 열어 둔 파일을 계속 읽습니다.
  • 업로드가 실패하면 교체를 하지 않도록 순서를 지킵니다.
  • 종료 시 처리 중인 요청을 마치고 내려가도록 graceful shutdown을 켭니다.

2. 설정과 비밀값 분리

DB 비밀번호나 외부 서비스 키가 소스에 함께 있으면, 저장소 접근 권한이 곧 운영 접근 권한이 됩니다.

  • 환경별 설정 파일을 분리하고, 운영 설정은 서버에 두고 외부에서 읽도록 합니다.
  • 설정 파일의 권한을 제한합니다(읽을 수 있는 계정을 최소화).
  • 키를 코드나 로그에 남기지 않습니다. 실수로 남는 경로가 대부분 로그입니다.

3. 로그를 성격별로 나누기

모든 로그가 한 파일에 섞이면 정작 필요한 순간에 찾지 못합니다.

  • 업무 로그 / 오류 로그 / 외부 연동 로그를 분리합니다.
  • 외부 연동(문자 발송, 결제, 택배)은 전용 로거로 빼면 장애 추적이 훨씬 빨라집니다.
  • 로그에 개인정보와 인증값이 들어가지 않는지 확인합니다(마스킹).
  • 보관 기간과 용량 제한을 걸어 디스크가 차지 않게 합니다.

4. 외부 연동 실패를 격리하기

가장 흔한 사고 유형입니다. 알림 문자가 안 나가서 주문 등록 자체가 실패하는 식입니다. 부가 기능이 본 업무를 막으면 안 됩니다.

  • 부가 기능 호출은 예외를 밖으로 던지지 않고 내부에서 흡수합니다.
  • 가능하면 큐에 적재만 하고 실제 처리는 분리합니다.
  • 타임아웃을 반드시 지정합니다. 지정하지 않은 호출 하나가 전체 스레드를 잡아먹습니다.
  • 실패한 건은 재처리할 수 있도록 데이터로 남깁니다.

5. 데이터베이스

  • 커넥션 풀 크기는 크게 잡는다고 좋아지지 않습니다. DB가 감당할 수 있는 범위에서 정합니다.
  • 느린 쿼리를 주기적으로 확인합니다. 대개 목록 화면의 검색 조건에서 나옵니다.
  • 로그성 테이블(접속 이력, 발송 내역)은 빠르게 커집니다. 기간 분리나 정리 정책을 처음부터 정합니다.
  • 백업은 복구를 해 봐야 백업입니다. 복구 절차를 한 번은 실제로 돌려 봅니다.
  • 운영 데이터베이스에 테스트를 돌리지 않습니다. 로컬 또는 별도 환경에서만 검증합니다.

6. 세션과 인증

  • 관리자 세션 만료 시간을 업무 특성에 맞게 정합니다. 너무 짧으면 작업 중 끊기고, 너무 길면 위험합니다.
  • 로그인 직후 세션 식별자를 교체해 세션 고정 공격을 막습니다.
  • 민감한 시스템은 비밀번호 외 2차 인증을 고려합니다.
  • 권한 검사는 화면이 아니라 서버에서 합니다.

7. 정적 파일이 어디서 서빙되는지 알기

애플리케이션 앞에 웹 서버를 두는 구성에서는 CSS·이미지가 애플리케이션이 아니라 웹 서버가 디스크에서 직접 내보내는 경우가 있습니다. 이 사실을 모르면 "배포했는데 화면이 그대로"인 상황을 만납니다.

  • 어떤 경로를 누가 서빙하는지 문서로 남깁니다.
  • 정적 파일 변경이 배포 절차에 포함되는지 확인합니다.
  • 가능하면 마크업과 짝을 이루는 스타일은 애플리케이션과 함께 배포되는 위치에 둡니다.

8. 오류 화면과 모니터링

  • 기본 오류 화면 대신 자체 오류 페이지를 둡니다. 스택 트레이스가 사용자에게 보이지 않게 합니다.
  • 예외를 종류별로 나눠 처리합니다(DB 오류 / 없는 페이지 / 그 외).
  • 최소한 프로세스 생존 여부와 디스크 사용량은 확인할 수 있게 해 둡니다.

9. 시간

예약 발송, 정산 마감, 통계 집계는 모두 시간에 의존합니다. 서버 시간대와 데이터베이스 시간대가 다르면 하루 단위 집계가 조용히 틀어집니다. 시간대를 명시적으로 고정하고, 날짜 경계를 다루는 로직은 테스트로 고정해 두는 편이 좋습니다.

정리

운영에서 생기는 문제의 상당수는 기술적으로 어렵지 않습니다. 다만 만들 때는 보이지 않다가 운영에서만 드러납니다. 그래서 직접 운영해 본 경험이 설계에 반영되는지가 차이를 만듭니다. 위 항목들은 대부분 개발 단계에서 하루 이틀이면 넣을 수 있지만, 사고가 난 뒤에 넣으려면 훨씬 비쌉니다.

관련 내용

운영까지 맡길 개발 파트너를 찾고 계신가요?

만들고 끝나는 개발이 아니라 배포·장애 대응·개선까지 이어지는 방식으로 일합니다.
현재 상황을 알려 주시면 필요한 범위를 정리해 드립니다.

개발·운영 상담하기