본문 바로가기
Java & Kotlin/Java

백엔드 서비스 운영시 고려해야할 점

by heekng 2024. 1. 21.
반응형

지난 한 해 동안 사내에서 신규 서비스를 개발 및 오픈하게 되었습니다.🎉

보통 주니어 개발자는 입사 후 아래와 같은 상황인 경우가 많을 것이라 생각됩니다.

  1. 기존 운영되고 있던 서비스를 운영
  2. 개인(토이) 프로젝트 개발 -> 때에 따라 실제 서비스 오픈 (하지만 서비스 이용자가 많이 없어 배포까지만 완료하는 경우가 많음)
  3. 시니어 개발자가 프로젝트 설정 후 API 개발만을 담당함

저 또한 같은 주니어 개발자 입장이지만

  • 팀 내 프로젝트 개발 표준 구성
  • 데브옵스 & 인프라 구성

를 모두 담당하게 되면서 단순히 API 개발만 했더라면 알지 못하고 넘어갔을 내용들을 정리하여 공유하려 합니다.

Java + Springboot 환경을 기준으로 작성합니다👋


요청 당 로그 트레이싱

서비스를 오픈하고 운영하는 단계 또는 그 이전의 개발 단계에서 서버에 배포된 이후 서버에 요청된 내용은 애플리케이션 내의 로그로 정보를 수집합니다.
다수의 사용자가 요청을 전송했을 때에는 단순한 텍스트만으로 어떤 사용자의 요청인지, 하나의 요청에서 발생된 로그가 어떤 것인지 확인하기 어렵습니다.

하나의 트랜잭션 내에서 발생하는 로그를 한번에 확인하기 위해서 여러 개선 방안이 있습니다.

  1. AOP 또는 Filter 등을 이용해 traceId 부여
  2. Naver Pinpoint (Pinpoint agent) 이용
  3. Sleuth (micrometer-tracing) 이용

핀포인트와 Sleuth(SpringBoot3 부터는 micrometer-tracing-bridge-brave 사용)에서는 들어온 요청에 대해 MDC에 traceId와 spanId를 생성해줍니다.

  • Pinpoint agent
    • [TxId: %X{PtxId}] [SpanId: %X{PspanId}]
  • sleuth
    • [TxId: %X{traceId}] [SpanId: %X{spanId}]

이렇게 설정된 로그 패턴를 통해


위와 같이 로그에서 두개의 요청을 구분할 수 있습니다.
어떠한 요청에 대한 로그만 확인하고 싶을 때에는 traceId 로 검색하여 해당 요청에 대한 로그만 걸러서 볼 수 있습니다.

모니터링 환경 구축 (Pinpoint)

Pinpoint는 네이버에서 만든 대규모 분산 서비스 추적 플랫폼입니다.
개발 서버의 경우 하나의 서버로도 테스트가 가능해 특정 요청에 대해 에러를 찾거나 지연내용을 추적하기 쉽지만
운영되고 있는 서버는 최소 2대 이상, 많으면 수십대 수백대 이상의 서버가 스케일아웃되어 구성됩니다.

서버 모니터링 툴에는 prometheus, zipkin, pinpoint apm 등이 있으며, 운영 초반까지 pinpoint를 주력 모니터링 툴으로 사용했습니다.

핀포인트는 docker 이미지로도 제공되며, pinpoint agent만 API 서버에 설치해 agent 구성으로 쉽게 구축할 수 있습니다.


위처럼 요청을 점으로 찍어 상세한 확인이 가능하고, 서버간 통신을 서버맵으로 시각화해 보여줍니다.
또한 장애 발생시 SQL 확인, Thread dump 확인, exception 발생 위치를 확인할 수 있습니다.

하지만 몇몇 상황시 내가 원하는 정도의 상세한 내용을 확인할 수 없어 zipkin 도입 또한 고려하고 있습니다.

분산환경 로그 수집

서버 배포 방번에는 IDC, EC2, ECS, EKS 등 다양한 방법이 있습니다.
저희 서비스에서는 AWS ECS를 선택했으며, 분산된 서버를 동일한 환경으로 구축할 수 있다는 장점이 있습니다.
관련글 -> AWS ECS + Fargate 를 이용해 애플리케이션 배포하기

현재 저희 신규 서비스는 최소 4대 이상의 서비스가 서버에서 구동되고 있는데요.
기존에 운영되던 서비스에서는 IDC 서버에 8대에서 20대 이상까지 구동되고 있습니다.
서비스 장애 발생 시 iterm에서 창을 나눠 한번에 각각의 서버에 접근해 로그를 찾고는 했는데요.
분명한건 이 과정이 많은 시간을 소용하고 개발자 입장에서 피로를 주고는 합니다.

이럴 때에는 분산로그 수집환경을 구축해 한 곳에서 모든 로그를 한번에 확인하는 방법이 있습니다.
분산 로그 수집 방식에는 대표적으로 ELK 스택을 이용하는 방법과 Loki를 사용하는 등 여러 방법이 있는데요.
이번 서비스에서는 ELK 스택을 이용했습니다.
ELK 스택을 사용해 Springboot 로그 수집하기
ELK 또한 여러 사용자들이 도커 이미지를 제공하고 있으며, Logstash + Logback을 지원해 비동기 방식으로 로그를 전송할 수 있습니다.

하지만 로그 수집만을 위해 사용하기에는 서비스가 과하고, 팀원들이 기능을 사용하는데 있어 어려움이 있어 Loki 도입을 고민중입니다.

로그 수집 환경 구축보다는 Pinpoint를 우선적으로 구축하는 것을 추천합니다.
agent를 기준으로 에러를 잡을 수 있기 때문이죠

멀티모듈 환경 사용

서비스 하나를 개발하면 service-api, admin-api, batch 등 여러 프로젝트가 개발됩니다.
단순한 모놀로식 서비스는 데이터베이스를 하나만 사용하면서 인프라스트럭처+도메인을 하나의 모듈로 만들어 각각의 프로젝트가 해당 모듈을 의존해 개발하는 방식을 사용하고는 하는데요.
개인적인 생각으로는 좋지 않다 생각합니다.
데이터베이스에 하나의 테이블을 예로 service-api 와 admin-api는 같은 도메인과 테이블을 사용하지만, 프로젝트 성격에 따라 도메인이 하는 역할이 크게 달라지는 경우가 대다수입니다.
그럼 service-api에서는 필요하지만 admin-api에서는 불필요한 도메인 기능까지 오픈하게 되어 결합도가 증가됩니다.
성급한 판단일 수 있지만, 멀티모듈을 재사용성 하나로 사용하면 감당하지 못할 모듈화가 진행될거라 생각합니다.
멀티모듈 설계 이야기 with Spring, Gradle 를 참고하면 좋을 것 같습니다.

datasource threadpool 설정

서비스 오픈 직후 요청이 몰리면서 생겼던 문제입니다.
외장 톰캣을 사용하다 springboot의 내장 톰캣을 사용하게 되면서 database connection pool 설정을 놓쳐 커넥션을 획득하지 못해 서비스 장애로 이어졌습니다.
스프링부트 커넥션 설정도 체크하자에서 해당 이슈에 대한 내용을 볼 수 있습니다.

누군가가 설정해 두었기 때문에 API 개발에만 집중하는 것이 아닌 내가 개발하는 프로젝트의 환경 설정도 한번씩 둘러보는 것을 추천합니다.

JWT? SESSION?

많은 분들이 사용자 인증을 당연히 JWT 토큰을 이용해 stateless 하게 구성하고는 하는데요.
JWT는 무조건 사용해야하는 스펙이 아닙니다.
흔히 사용하는 JWT + redis(또는 JDBC)로 토큰을 관리하는 것은 좋은 관리 방법입니다.
하지만 accessToken의 유지 시간을 짧게 설정하고 refreshToken을 사용해 재발급 로직을 구현한다면 문제가 생겼을 때 바로 사용자를 로그아웃처리 할 수 없다는 문제가 생기고
강제 로그아웃 처리를 위해 accessToken도 데이터베이스에 저장하면 세션을 사용하는 것과 별다를 것이 없어집니다.
token 저장만을 위한 redis와 같은 별도의 저장소를 만들어 사용하려 한다면 jdbc-session을 이용해 관리포인트를 줄이는 방법도 괜찮다고 생각합니다.
Spring session 공식문서 참고

서비스 아키텍처

나 혼자서 개발하는 프로젝트가 아닌 팀원과 함께 개발하는 프로젝트일수록 서비스 아키텍처는 중요해집니다.
모든 팀원이 같은 생각을 가지고 개발하는 것이 아니기 때문에 구현 방법도 다양해집니다.
클린 아키텍처, 헥사고날 아키텍처 등 요즘 핫한 아키텍처들도 존재하지만, 팀 구성원이 지금 만드는 서비스에 맞는 아키텍처를 함께 고민하고 코드스타일 등을 맞춰 개발하면 시간이 지나도 덜 지저분한 코드가 작성될 수 있습니다.

완벽하게 깔끔한 아키텍처는 존재하지 않는다고 생각합니다.

캐시

저는 기존 캐시 설정에 대해 redis 캐시만 사용해야한다고 생각했는데요.
서비스 상황과 캐시될 내용에 따라 ehcache 도입도 괜찮은 방법입니다.
별도로 redis를 구축하지 않아도 되고, redis 또한 외부 저장소이기 때문에 조회가 필요합니다.
물론 ehcache의 경우 직접관리가 불가능하다는 단점도 존재합니다.

반응형