본문 바로가기
Spring/experience

CI/CD 잦은 배포에 대한 불안감 떨쳐내기

by include_hoany 2025. 10. 21.

Gpt가 만들어준 이미지

불안감 떨쳐내기 두 번째 이야기입니다. 첫 번째 불안감 떨쳐내기의 방법으로 테스트코드 작성과 Spock 테스트 프레임워크(https://include-hoany.tistory.com/79)에 대해 이야기 했었습니다.

 

오늘 저의 불안감을 떨쳐내게 해 준 두 번째 방법에 대해 이야기해보려 합니다.

 

요즘은 워낙 CI/CD 자동화가 잘되어있기에 백엔드 프로젝트도 그렇고 프론트 프로젝트도 그렇고 하루에 여러 번 배포를 하기도 합니다. 다만 한정된 시간 내에 기능을 개발하고 단위테스트, QA 테스트 까지 한다고 해도 우리가 생각지 못한 엣지케이스들이 있을 수 있다는 불안감은 늘 항상 존재했었습니다. 또 알파, 베타 환경과는 다른 운영서버에서 발생할 수 있는 엣지케이스들도 있죠..

 

그러면 모든 인스턴스들의 로그를 보면서 오류가 발생하는지 확인해야 하나 하지만 직관적이지도 않을뿐더러 트래픽이 많으면 수천 개의 텍스트가 매트릭스처럼 지나가는 로그를 본다는 건 정말 불가항력이죠..

 

그래서 사용한 솔루션은 Sentry입니다. Sentry는 APM 솔루션으로 성능 모니터링, 에러 트래킹 등등을 지원합니다. 제가 Sentry를 선택한 이유는 Spring 서버를 기준으로 봤을 때 상세한 에러트레킹이 가능했고 오류가 발생할 경우 Slack과 같은 메신저로 실시간으로 개발자에게 알림을 보낼 수 있는 기능을 지원하기 때문입니다. 하지만 그 무엇보다 오픈소스 무료버전이 있기 때문에 직접 서버에 설치하여 사용이 가능합니다! 저 또한 센트리를 도커 컨테이너로 구동하여 사용하였습니다.

 

오늘은 센트리 사용법이 아니기에 상세한 설정은 생략하도록 하겠습니다. Spring 서버 에러트레킹을 할 수 있도록 프로젝트를 설정합니다.

Sentry에서 프로젝트를 설정한 후에 dsn을 발급받습니다.

 

build.gradle

// 센트리 의존성 추가
implementation 'io.sentry:sentry-spring-boot-starter:6.34.0'

Spring Boot에 Sentry의존성을 추가한 후

 

application.yaml

sentry:
  dsn: http://e2771aa230ead3430633f6d8e36a874f@192.168.1.236:9000/2
  environment: local
  send-default-pii: true
  traces-sample-rate: 1.0

yaml 파일에 Sentry에서 발급받은 dsn을 입력해 줍니다. 실제 개발 프로젝트라면 local 프로파일에서는 Sentry로 에러정보를 전송하지 않도록 제한해야 하지만 현재는 간단하게 설명하므로 local 환경에서도 전송하도록 설정하였습니다. 이로서 간단하게 설정이 끝났습니다.

 

    public static BoardResponseDto of(Board board) {

        throw new IllegalArgumentException("보드 팩토리 메소드 오류 발생");

//        return BoardResponseDto.builder()
//                .boardId(board.getBoardId())
//                .title(board.getTitle())
//                .author(board.getAuthor())
//                .description(board.getDescription())
//                .commentCount(board.getCommentCount())
//                .updateAt(board.getUpdateAt())
//                .createAt(board.getCreateAt())
//                .build();
    }

of 팩토리 메서드에서 오류가 발생하는 환경을 구성하였습니다.

 

@RestControllerAdvice
public class GlobalExceptionHandler {

    // 일반적인 예외 처리
    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<String> handleRuntimeException(RuntimeException ex) {
        Sentry.captureException(ex);
        return ResponseEntity
                .status(HttpStatus.BAD_REQUEST)
                .body("Something went wrong: " + ex.getMessage());
    }

}

of 팩토리 메소드에서 오류가 발생하면 @RestControllerAdvice가  에러를 핸들링할 때 Sentry가 해당 Exception을 캡처하도록 구성합니다.

 

Spring 서버에서 Exception을 캡처하게 된다면 Sentry에서 해당 오류를 확인할 수 있습니다. 여기서 오류가 발생한다면 Slack로 메세지를 보내도록 설정할 수도 있습니다.

 

 

Sentry 대시보드를 통해 해당 오류가 어떻게 발생했는지 Stack Trace도 확인할 수 있습니다. 서버로 요청한 Client 정보도 확인할 수 있습니다. Sentry를 구성하면 빠르게 우리 서버에서 어떤 오류가 발생하는지 실시간으로 알림을 받을 수 있고 에러가 발생한 소스코드 라인확인하고 빠르게 롤백을 할지 아니면 핫픽스를 나갈지 빠르게 결정할 수 있습니다. 비록 에러가 날지라도 빠르게 에러를 확인하고 대처할 수 있다면에서 조금이라도 저는 배포에 대한 불안감을 떨쳐낼 수 있었습니다.

 

실제로 회사에서 서비스 중인 서버는 Sentry를 클라우드로 금액을 지불하고 사용하였는데  실제 Sentry 오픈소스를 도커 환경에 직접 올리니 생각보다 무거웠습니다.... Sentry self hosted 컨테이너만 72개.. 적어도 16gb 램은 되어야 원활하게 구동할 수 있을 것 같습니다! 그럼 잦은 배포에 대한 불안감 떨쳐내기 에러트레킹에 대한 이야기는 마무리하도록 하겠습니다. 감사합니다!