글 작성자: 개발섭

토이프로젝트에 로깅은 필수..

로깅(log)은 프로젝트를 처음 접해본 사람이 아니면, 솔직히 한번쯤은 겪고 가야할 문제이다. 로깅 자체의 구현이 어렵진 않을 것이다. Spring과 같은 Web Framework에서는 이미 로깅 프레임워크를 제공해주기 때문이다. 그중에서 우리는 logback 기능을 활용해서, 서비스를 구현해놓는게 심적으로 편하다. (이미 구현되어있으니까)

로깅 다 좋은데 말야…

로깅이 에러 대응과 같은 역할을 하는게 있고, logback에서는 파일, 콘솔과 같은 툴로 이미 로그를 여러 모습으로 관리를 해주고 있기 때문에, 우리가 이러한 로그 파악에 있어서 파일을 통한 로깅, 혹은 콘솔창에 대한 로그를 통해서 확인을 해줄 수 있다.

문제는 그것이 실시간성으로 확인이 어렵다는 점이다. 왜냐하면, 일단 장애가 발생하면, 클라이언트는 장애를 인지하지만 실제로 서버는 관제를 이용하지 않는 이상 확인할 길이 클라이언트 개발자, 혹은 운영을 통해서 관제를 들어온 케이스를 제외하고는 확인할 길이 없다. (매일 실시간 관제를 하는 방법도 있기야 하겠지만… 비효율적이다)

그렇다면 이러한 에러 발생에 대해서 우리는 최대한 즉각적인 대응, 그리고 문제의 발생의 위치를 로깅을 통해서 찾는게 가장 좋다. 회사 시스템의 경우 금액적인 운영비용도 있으며, 그 운영적인 문제가 발생했을때 회사가 입는 치명적 타격때문에, 관제 시스템을 구성해놓는다.

문제는 토이프로젝트, 사이드 프로젝트에서 과연 운영 관제할 서버를 하나 더 올리는 것이 의미가 있는지에 대해서 곰곰히 생각해보면, 나는 개인적으로는 어렵다고 생각한다. 왜냐하면, 토이프로젝트나 사이드 프로젝트에서 어쨌든 중요한 점은 지속 가능성이고, 지속 가능성을 높이기 위해서는 결과적으로는 서버 운영에 드는 비용이 거의 0에 가까워야 끊임 없이 운영할 수 있다고 생각한다.

Slack을 써보자

결국 관제용 서버를 띄우는 것이 아닌 이상 실시간으로 관제를 받기 위해서 Slack을 활용해서 관제를 할 수 있는 방향으로 관점을 변경했다. 결국 관제의 핵심은 로그 분석과 실시간성인데, 그 둘을 동시에 챙기기 위해서는 Slack에서 제공하는 웹훅 기능을 활용하면 좋다.

Slack 웹훅은 다음처럼 설정가능하다.

1. 내가 설정을 원하는 채널로 접근후 채널 세부 정보

2. 앱 추가

3. Incoming Webhook 등록 >  등록하려는 채널에 등록하기

4.  등록후 나온 웹후크 url 주소를 복사해둡시다. 

이제 이 주소를 아래 Spring boot 설정에서 사용해줄것이다. 

Spring Boot의 옵션들도 추가하자

기본적으로는 빌드옵션에 logback-slack-appender를 추가하고… (22년 7월 기점으로 1.6.1이 가장 최신)

build.gradle.kts

//Logging
implementation("com.github.maricn:logback-slack-appender:1.6.1")

그리고 Spring boot의 application.yaml 파일에 다음과 같이 추가를 해준다음에…

application.yaml

logging:
  slack:
    webhook-uri: #웹훅 주소 삽입
config: classpath:logback-spring.xml

마지막으로 Logback을 활용한 Appender를 통한 추가를 제공해보자.

LogBack의 옵션은 다음과 같이 두개를 추가했다. Slack에서 제공하는 옵션과 Console창에서 제공하는 옵션 두가지를 제공하는 방향으로 바꾸었다. 물론, File 로그도 제공해도 괜찮지만, 실시간 관제 이후 systemd를 통해 로그 분석을 하는 방향으로 가닥을 잡았기 때문에, 옵션을 다른건 주지는 않았다.

그리고 로그 창에서 제공하는 Pattern을 약간 변경점을 주었다.

Logback-Spring.xml

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>

    <springProperty name="SLACK_WEBHOOK_URI" source="logging.slack.webhook-uri"/>
    <appender name="SLACK" class="com.github.maricn.logback.SlackAppender">
        <webhookUri>${SLACK_WEBHOOK_URI}</webhookUri>
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} - %-5le %logger{35} : %msg%n</pattern>
        </layout>
        <username>서버 관제</username>
        <iconEmoji>:hammer_and_wrench:</iconEmoji>
        <colorCoding>true</colorCoding>
    </appender>

    <!-- Consol appender 설정 -->
    <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>

    <appender name="ASYNC_SLACK" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="SLACK"/>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
    </appender>

    <root level="INFO">
        <appender-ref ref="ASYNC_SLACK"/>
        <appender-ref ref="Console"/>
    </root>
</configuration>

이렇게 추가하면 다음처럼 에러 옵션이 모두 실시간으로 관제되는 것이 보인다..

에러는 붉은색 띠로.. Warn은 노란색띠로 노출된다.

추가적으로 개선사항이 있긴한데…

일단 기본적으로, Log Trace가 보기가 은근 불편하다. 이게 붉은 띠와 추가적으로 제공하는 자세히표시와 같이 folding 기능을 제공해주기 때문에 Trace에 대해서 라이브러리가 attachment 로 자동적으로 제공하게 해주는데, 이게 개행과 Indent도 안맞고 하니까 볼때마다 뭔가 좀 짜증난다..

그래서 차라리 이렇게 줄거면, Code Block으로 감싸거나 attachment 가 아닌 일반 메세지 타입으로 전달하는 방향으로 제공하던가해서 처리하는게 좋을거라 생각했다.

이건에 대해서는 Class 확장을 통해서 개선을 해볼까 고민중이니… 차후에 글을 작성하게 된다면 여기에 추가로 링크를 남기도록 하겠다.