MDC를 활용한 로깅 개선기
·
Spring
문제상황아래 화면은 현재 우리 서버에서 기록되고 있는 로그 일부이다. 회원이 가입을 하면 비동기로 인증 이메일을 발송하는 로직이 동작하는데, 현행 로그 추적 체계에서는 이 요청이 동일한 흐름(즉, 하나의 요청에서 파생된 작업)인지 식별하기가 어렵다는 문제가 있었다.이 때문에 장애가 발생했을 때도 어떤 요청에서 비롯된 문제인지 추적하기 쉽지 않았다.또한 비동기 작업 흐름과 별개로, 어떤 사용자가 보낸 요청인지 식별할 수 없는 점도 불편함을 키웠다. 실제로 사용자 문의 메일을 통해 장애 보고가 접수되더라도, 해당 상황과 관련된 로그를 바로 찾아내기가 어려워 즉각적인 대응이 지연되곤 했다. 물론 타임스탬프를 통해서 어느정도 구분이 가능하지만, 톰캣의 경우 스레드 풀을 재사용하기 때문에 스레드 이름만으로 로그를..
동기 vs 비동기: 통신 패턴의 이해와 아키텍처 설계 트레이드오프
·
운영체제
Synchronous vs Asynchronous서비스 간 통신을 설계할 때, 가장 근본적인 질문 중 하나는 "동기 방식으로 처리할 것인가, 비동기 방식으로 처리할 것인가?"이다. 이 결정은 단순히 기술적인 선택을 넘어 시스템 전체의 구조, 안정성, 운영 방식에까지 영향을 준다. 이 글에서는 동기와 비동기 통신의 차이, 장단점, 실제 사용 시 고려해야 할 요소들을 체계적으로 살펴보고자 한다.Synchronous Communication동작 방식동기 통신은 한 컴포넌트가 다른 컴포넌트에게 요청을 보내고, 그 결과가 반환될 때까지 기다리는 방식이다. 즉, 요청을 보낸 쪽은 응답이 올 때까지 다음 단계로 넘어가지 못한다. 흐름이 직선적이고, 요청-응답 구조가 명확하여 개발자 입장에서 이해하기 쉽다.RESTfu..
서킷 브레이커(Circuit Breaker) 알아보기
·
Etc
외부 연동 서비스에, 장애가 발생했어요!외부 서비스에 과부하가 발생해 응답을 제대로 주지 못하고 있는 상황이라고 생각해보자. 연동 서비스가 정상화되기 전까지는 요청을 보내도 계속 에러만 발생하게 될 것이다. 또한, 읽기 타임아웃이 발생할 때까지 대기하느라 응답 시간도 길어지게 될 것이다.그림과 같은 상황일 때, A 서비스는 B 서비스에 요청을 보내지 않고 바로 에러를 응답하는 것이 낫다. 이렇게 하면 B 서비스의 문제가 A 서비스에 주는 영향(응답 시간 증가, 처리량 감소)을 줄일 수 있다. 또한 사용자 입장에서도 수 초를 대기하다가 에러 화면을 보는 것보다는, 빠르게 에러 화면을 보는 편이 낫다. 즉, 연동 서비스가 장애 상황일 때는, 연동 대신 바로 에러를 응답하고, 정상화되었을 때 연동을 재개하면 ..
모니터링 시스템 구축기
·
Etc
모니터링 시스템이 왜 필요할까?서비스가 정상적으로 운영되고 있을 때는 모니터링 시스템의 필요성을 쉽게 체감하지 못한다. 그러나 예기치 못한 오류나 성능 저하가 발생하면 상황은 급변한다. 사용자로부터 불만이 접수되기 시작하고, 개발자는 “무슨 일이 일어난 걸까?”라는 질문부터 던지게 된다. 이때 모니터링 시스템의 유무는 문제 해결 속도를 결정짓는 중요한 요소가 된다.모니터링 시스템은 단순히 데이터를 수집하고 시각화하는 도구가 아니다. 시스템의 상태를 실시간으로 파악하고, 장애를 빠르게 감지하며, 그 원인을 추적할 수 있도록 도와주는 운영의 필수 구성 요소다. 또한, 장기적으로는 성능 개선과 리소스 최적화에도 기여하여 서비스의 안정성과 신뢰도를 높이는 데 중요한 역할을 한다.메트릭 기반 모니터링: Prome..
효율적인 로그 관리를 위한 Spring Boot + Logback 설정
·
Spring
로깅을 하는 이유?로깅이란 시스템이 동작하는 동안, 그 상태와 동작 정보를 시간의 흐름에 따라 기록하는 행위를 의미한다. 이 과정에서 생성된 로그는 개발자가 애플리케이션의 동작을 파악하고 문제를 진단하는 데 있어 매우 중요한 역할을 한다. 특히 예기치 못한 오류나 예외 상황이 발생했을 때, 로깅은 문제의 원인을 추적하는 실마리를 제공한다.개발 과정에서 뿐만 아니라 운영 환경에서도 로깅은 유용하게 활용된다. 예를 들어, 사용자 행동에 대한 로그는 단순한 기록을 넘어, 서비스 개선을 위한 분석 데이터로 활용될 수 있다. 사용자의 패턴을 파악하고 이를 기반으로 기능을 개선하거나, 성능 병목 지점을 찾아내는 데에도 큰 도움이 된다.하지만 로깅이 무조건 많다고 해서 좋은 것은 아니다. 로깅의 수준(level)이나..
[EduKit] 멀티모듈 도입기
·
Spring
왜 멀티 모듈 구조로 전환을 결심한 계기처음 우리 팀은 하나의 단일 모듈 안에 모든 기능을 밀어넣는 방식으로 개발을 시작했다. MVP 단계에서는 빠르게 기능을 구현하고 결과를 검증하는 것이 우선이었기 때문에, 모듈을 나누는 일은 우선순위에서 밀릴 수밖에 없었다. 하지만 시간이 지날수록 새로운 기능이 추가되고, 코드 베이스가 커지면서 자연스럽게 구조에 대한 고민이 깊어지기 시작했다. 특히 생기부 AI 기능의 1차 개발이 끝나고, 이어서 커뮤니티 서비스와 교사 인증 배치 기능이 순차적으로 개발될 예정이었기에, 기능 간의 책임을 분리하고 테스트/배포 단위를 나눌 수 있는 아키텍처가 필요하다는 판단이 들었다.무엇보다 결정적인 이유는, 이 프로젝트 안에 기술적 성격이 완전히 다른 두 기능이 함께 존재했다는 점이다..
안전하게 토큰 비교하기 - String.equals() vs MessageDigest.isEqual()
·
JAVA
들어가며..Refresh Token 재발급 로직을 구현해 PR을 올렸는데, CodeRabbit으로부터 다음과 같은 피드백을 받았다.처음에는 단순히 문자열 비교를 통해 저장된 토큰과 일치하는지를 판별했지만, 해당 피드백을 보고 나서 타이밍 공격이 무엇인지, 그리고 MessageDigest.isEqual이 어떻게 이를 방지하는지에 대해 알게 되었고 더 깊이 알아보고자 한다.타이밍 공격(Timing Attack)이란?타이밍 공격(Timing Attack)은 암호 알고리즘이 실행되는 데 걸리는 시간을 분석하여 암호 시스템을 공격하는 부채널 공격(side-channel attack)의 일종이다. 컴퓨터의 모든 논리 연산은 수행하는 데 시간이 소요되며, 이 시간은 입력값에 따라 달라질 수 있다. 따라서 각 연산의 ..
이벤트 기반 처리로 구현하는 회원가입 및 이메일 전송 (feat. Thread pool)
·
Spring
요구사항이전 포스팅에서도 언급했듯, EduKit 서비스에는 이메일 인증 프로세스가 존재한다. 사용자가 회원가입 버튼을 클릭하면 인증을 위한 인증 코드가 생성되고, 해당 코드가 포함된 인증 링크가 담긴 이메일이 발송되는 흐름이다. 해당 로직을 구현하면서 고려했던 사항들은 아래와 같다. 1. 회원가입이 성공적으로 완료된 후, 이메일이 발송되어야 한다.즉, 회원가입을 수행하던 도중 어떠한 이유로 오류가 발생하여 롤백되는 경우, 인증 이메일이 발송되는 일은 없어야 한다. 가입 정보는 DB에 존재하지 않는데, 이메일은 발송되었다면 혼란을 줄 수 있기 때문이다. 따라서, 이메일 전송은 회원가입이 성공한 이후에만 실행되어야 한다. 2. 외부 메일 서비스의 장애가 회원가입 로직의 실패로 이어져서는 안된다.현재 우리 서..
안전하고 Thread-safe하게 난수 생성하기
·
JAVA
EduKit 서비스에는 이메일 인증 프로세스가 존재한다. 인증 코드 생성의 보안성을 높이기 위해 고민하던 중, 여러 가지 방법들에 대해서 알게 되었고 특히, Math.Random 메서드 그리고 Random과 SecureRandom 클래스의 차이에 대해 알게 되었다. 먼저 난수가 무엇인지부터 차근차근 살펴보자.난수난수란, 예측 불가능성을 만족하기 위해 무작위하게 생성되는 값을 말한다.난수의 성질무작위성 (Randomness)통계적인 성질을 조사했을 때, 치움침이 없을 경우 무작위하다고 판단한다. 이때, 주의해야할 것이 '무작위하다'와 '예측할 수 없다'는 동일하지 않다는 것이다. 무작위하기 때문에 예측할 수 없다는 것은 불충분 조건이다. 때문에 무작위성만 가지는 난수를 약한 의사난수(Pseudo Rando..
재시도 폭풍에서 서버를 지키는 방법 (feat. 동시성 문제)
·
Spring
들어가며..2025 네이버 신입 공채 1차 면접 때 있었던 일이다. 이제 막 1달 된 따끈따끈한 일이다. 당시의 면접관의 질문과 내 답변을 복기해보면 아래와 같다.👤이력서 써놓은 신 것을 봤는데, 지금 동시성 제어를 낙관적 락으로 해결하셨다고 되어 있네요. 그러면 지금 100명이 동시에 좋아요를 눌렀을 때 발생할 수 있는 문제점이 뭐가 있을까요?️🗣️ 일단 지금 저의 로직으로는, 낙관적 락을 걸었기 때문에 만약 동시에 수정을 하면 버전 충돌로 인해서 자동으로 다시 시도하는 로직이 구현되어 있습니다. 근데 이제 100명이 동시에 시도를 하면 성공한 1명 빼고 나머지 99명은 똑같이 재시도 로직을 돌게 될 텐데 그 재시도를 도는 과정에서 부하가 일어날 수 있을 것 같습니다.👤 네 그 부하라는 거는 어떤..