운영의 고단함과 배경
애플리케이션을 직접 운영하면 로그로 문제를 빨리 파악하고 서버·클러스터 구성을 세밀히 다룰 수 있지만, 운영 전문 조직이 아닌 개발자가 밤낮으로 모니터링과 장애 대응에 시달리게 된다. 사용자가 늘수록 커진 피로도를 어떻게 줄일지, 자동화 관점에서 이야기를 풀어간다.
메모리가 점점 차 OutOfMemory와 잦은 GC로 응답이 느려지는 죽음의 소용돌이 상황에서, 헬스체크로 프로세스 상태를 감지해 힙 덤프를 남기고 자동 재시작하거나 로드밸런서에서 아웃시키는 구성을 만든 과정을 설명한다. OOM 원인 분석과 옵션 튜닝 경험을 공유한다.
쿠버네티스의 kubelet과 readiness·liveness probe 개념을 빌려, 단순 메모리가 아니라 해당 서버가 실제 요청을 처리할 수 있는 상태인지로 판단하도록 개선했다. 커넥션 풀·Redis 연동 등 주요 의존성 상태까지 체크해 미숙한 재시작으로 인한 2차 장애를 막는다.
메일 시스템처럼 게이트웨이-백엔드-정책관리 서버로 이어진 구조에서, 한 서버가 느려지면 스레드풀이 소진되며 앞단으로 장애가 연쇄 전파되는 문제를 분석한다. 스케일 아웃·서킷브레이커 등 후보를 검토하고 각 방식의 한계를 따져본 과정을 공유한다.
일정 처리량으로 무조건 컷하는 방식은 실제 서버 부하를 반영하지 못한다고 보고, Tomcat threads busy·config max 지표로 연계 서버 상태까지 반영해 과부하 시 429로 요청을 거부하도록 구현했다. 재시도 가능하고 상호작용 없는 멱등 api만 대상으로 선정했다.
정적이거나 잘 안 바뀌는 응답을 매번 다시 계산하지 않도록 백엔드 간 통신에 HTTP 캐시를 도입했다. ETag와 If-None-Match, 304 Not Modified, must-revalidate로 변경 여부만 확인하고, ehcache 등 캐시 스토리지로 상당량을 304로 응답해 비즈니스 로직을 건너뛴 사례를 든다.
소켓 서버가 처음엔 잘 돌다 갑자기 응답이 느려지는 원인이 채널 아웃바운드 버퍼 폭증임을 분석하고, thread sleep으로 임시 대응하던 방식의 한계를 짚는다. Netty의 high·low 워터마크로 쓰기 가능 여부를 판단해 스레드 슬립 없이 쓰로틀링 문제를 해결했다.
성능과 안정성 보장을 위해 RFC 문서와 프레임워크 내부까지 파고든 경험을 돌아보며, 이런 운영 자동화·장애 대응 기법이 결국 팀의 편안한 휴식 시간을 지켜준다는 메시지로 발표를 마무리한다.