Feature Flag 패턴이란?
·
Etc
Feature Flag는 왜 필요할까?서비스를 운영하다 보면 코드를 배포하는 일과 기능을 사용자에게 공개하는 일을 항상 같은 시점에 하고 싶지는 않다. 기능 개발은 끝났지만 아직 전체 사용자에게 열기에는 부담스러운 경우가 있다. 내부 계정이나 특정 조직에만 먼저 열어보고 싶은 기능도 있다. 반대로 이미 배포된 기능에서 문제가 생겼을 때, 코드를 다시 배포하지 않고 기능만 빠르게 끄고 싶은 경우도 있다.이런 문제를 해결하기 위해 사용하는 방법 중 하나가 Feature Flag다. Feature Flag는 배포된 코드의 동작을 런타임에 바꿀 수 있게 해주는 방법이다. Feature Flag의 핵심은 “코드를 다시 배포하지 않고 동작을 바꿀 수 있다”는 점이다. Feature Flag를 사용하면 기능 공개 시..
mTLS에 대해 알아보자
·
Computer Science/네트워크
mTLS란?TLS 기반인 HTTPS를 떠올리면, 클라이언트가 서버를 신뢰할 수 있는지 검증하는 구조를 떠올린다. 브라우저가 특정 사이트에 접속할 때 서버는 인증서를 제시하고, 브라우저는 해당 인증서가 신뢰할 수 있는 인증기관, 즉 CA에 의해 발급되었는지 확인한다. 이 과정을 통해 사용자는 내가 접속한 서버가 진짜 브라우저가 맞는가를 검증할 수 있다.하지만 서버 입장에서는 반대 방향의 검증이 필요할 때가 있다. 즉, "이 요청을 보낸 클라이언트가 정말 허용된 시스템인가"를 네트워크 연결 단계에서 확인하고 싶은 경우이다. 이때 사용하는 방식이 mTLS이다. mTLS(상호 TLS)는Mutual TLS의 약자로, 말 그대로 상호 TLS 인증을 의미한다. 일반 TSL가 주로 클라이언트가 서버를 검증하는 구조라면..
Hibernate Envers - 간편하게 엔티티 변경 이력 관리하기
·
JPA&JDBC
들어가며최근에 코드를 실행하다가 신기한 상황을 발견했다. 서비스 로직에서 A 테이블의 데이터를 update하고 있었는데, 트랜잭션이 끝난 뒤 확인해보니 A의 히스토리 이력을 저장하는 B 테이블에도 데이터가 자동으로 쌓이고 있었다. 때문에 나는 당연히 아래와 같은 코드를 찾기 시작했다.historyRepository.save(...)그런데 아무리 찾아봐도 B 테이블에 위와 같이 명시적으로 직접 저장하는 로직은 없었다. 도대체 어떻게 이 데이터를 저장하는 걸까?결론부터 말하면, 애플리케이션 서비스 코드가 히스토리를 직접 저장한 것이 아니었다. 해당 엔티티에 @Audited가 붙어 있었고, Hibernate Envers가 Hibernate의 flush 과정에 끼어들어 변경 이력을 자동으로 저장하고 있었다.Hi..
[Spring Batch] Spring Batch 아키텍쳐와 전체 흐름 이해하기
·
Spring
Spring Batch는 무엇을 해결하려는 기술일까?애플리케이션을 운영하다보면 사용자의 요청에 즉시 응답하는 API 처리와는 조금 다른 종류의 작업이 필요해진다. 매일 새벽 주문 데이터를 정산하거나, 대량의 회원 데이터를 읽어서 상태를 갱신하거나, 외부 시스템에서 받은 파일을 검증한 뒤 데이터베이스에 적재하는 작업들을 예시로 들 수 있다. 이러한 작업들은 보통 대량의 데이터를 처리해야 하고, 일정한 주기로 반복 실행되며, 실패했을 때 어디까지 처리했는지 추적할 수 있어야 한다. Spring Batch는 이런 배치 작업을 안정적으로 만들기 위한 프레임워크다. 공식 문서에서도 Spring Batch를 대량 데이터 처리를 위한 경량이면서 포괄적인 배치 프레임워크로 설명하고 있다. 다만, Spring Batc..
JpaPagingItemReader의 transacted 옵션
·
JPA&JDBC
JpaPagingItemReaderSpring Batch에서 대용량 데이터를 처리할 때 가장 먼저 부딪히는 문제는 “데이터를 어떻게 안정적으로, 그리고 효율적으로 읽어올 것인가”이다. 이때 등장하는 대표적인 Reader가 바로 JpaPagingItemReader다. 이름 그대로 JPA를 기반으로 데이터를 페이징 방식으로 나눠서 읽어오는 Reader다.조금 더 쉽게 말하면, 데이터베이스에 있는 데이터를 한 번에 전부 가져오는 것이 아니라, 일정 개수씩 끊어서 가져오는 역할을 하는 컴포넌트다. 예를 들어 100만 건의 데이터를 처리해야 한다고 했을 때, 한 번에 전부 메모리에 올리는 것이 아니라 1000건씩 나눠서 가져오는 방식이다. 이렇게 하면 메모리 사용량을 안정적으로 유지하면서도 대용량 처리가 가능해진..
2026 카카오그룹 신입 공채 합격 후기
·
끄적끄적
들어가며9월부터 시작되었던 카카오그룹 신입 공채가 드디어 12월 17일을 기점으로 끝이 났다!!이번 카카오그룹 신입 공채에는, 총 6개의 그룹사가 참여하였다. 그 중 지원자는 1개의 그룹사를 선택해서 지원해야하는 형식이었고 각 그룹사마다 서류 문항이나 진행 일정들에서 살짝씩 차이가 존재했다. 서류 작성 -> 1차 코딩 테스트 -> 2차 코딩 테스트 -> 1차 면접 -> 2차 면접 -> 입사카카오 그룹의 신입 공채 전형은 굉장히 긴 편이다. 심지어 다른 회사들과 달리 코딩 테스트가 무려 2번이나 존재한다. 전체적인 전형 과정의 틀 자체는 모든 그룹사가 동일했지만 세부적인 부분에서는 각각의 그룹사 별로 상이했다. (심지어 최종 합격 발표 시간도 다 상이했다..!)많은 고민 끝에 나는 카카오페이에 지원하였고,..
B+Tree
·
Computer Science/자료구조&알고리즘
B-TreeB-Tree는 하나의 노드에 여러 데이터가 저장될 수 있다. 따라서 같은 노드 내에서 데이터를 탐색할 때는 포인터를 따라가는 방식이 아니라, 디스크(또는 메모리)에 연속적으로 저장된 인덱스를 순차적으로 확인하는 방식으로 탐색이 이루어진다. 이때, 특정 노드의 데이터(key)가 K개라면, 자식 노드의 개수는 K+1개여야 한다.특징예를 들어, 위의 B-Tree 구조에서 33이라는 값이 존재하는지 확인한다고 가정해보자. 루트 노드에는 20, 40이 저장되어 있는 상태이기 때문에 루트 노드에는 해당 값이 존재하지 않아 자식 노드를 가리키는 포인터의 존재 유무를 확인한다. 20과 40 사이의 범위에 해당하는 자식 노드를 가리키는 포인터가 있는 것을 확인했다면, 포인터를 따라가 자식 노드에 도달한다. 자..
커스텀 메트릭으로 AI 응답 품질 판별 기준을 만들어보자
·
Observability
문제 상황Edukit 서비스는 교사들을 위해 AI를 활용하여 학생부 작성 업무를 돕는 서비스다. 하지만 이 서비스를 만드는 구성원은 현직 교사가 아닌 개발자 3명이었기 때문에, AI가 생성하는 응답의 품질을 명확하게 판단하기 어려웠다. 이를 보완하기 위해 설문조사를 통해 만족도를 수집했지만, 운영 서버에 새 기능을 배포할 때마다 질문을 초기화해야 하는 번거로움이 있었고, 사용자 수에 비해 응답률도 높지 않아 한계가 있었다. 이러한 상황이 반복되면서 서비스 개선 과정에서도 응답 품질에 대한 확신을 점점 잃게 되었다.그러던 중 소마 전담 멘토링을 통해 커스텀 메트릭이라는 개념을 알게 되었고, 이를 활용하면 실제 사용 패턴을 기반으로 AI 응답 품질을 정량적으로 확인할 수 있지 않을까? 라는 생각을 하게 되었..
SELECT ... FOR UPDATE 동작 파헤치기
·
Computer Science/데이터베이스
들어가며이전의 글들에서 트랜잭션 격리 수준에 따라 데이터 일관성이 어떻게 관리되는지 살펴보았다. 특히 Repeatable Read 격리 수준에서 Undo Log를 활용하여 어떻게 데이터 일관성을 보장하는지에 대해 다루었는데, 설명이 다소 간략해 아쉬운 부분이 있었다. 이번 글에서는 그 내용을 보완하여, InnoDB가 Consistent Read와 Read View를 통해 일관성을 유지하는 과정을 좀 더 자세히 살펴보고자 한다. 실습 환경은 아래 그림과 같다. 데이터베이스에는 users 테이블과 wallet 테이블, 총 두 개의 테이블이 존재하며 각각의 테이블에 3개의 데이터가 저장되어 있다.단일 트랜잭션 상황먼저 기본적인 단일 트랜잭션 상황을 가정해보자.하나의 트랜잭션에서 wallet 테이블의 Money..
메시징 패턴 (feat. Pub/Sub, Queue, Event Stream)
·
Observability
메시징이란메시징은 발신자와 수신자를 분리하는 방법이다. 메시징 시스템은 가장 단순하게 말하면 시스템의 한 부분에서 다른 부분으로 정보를 전달하는 것을 의미한다. 생산자가 메시지를 보내면, 브로커가 이를 저장하고 라우팅하며, 소비자가 가져가서 필요한 작업을 수행한다. 이 과정에서 서비스는 다른 서비스가 작업을 완료할 때까지 기다리지 않는다. 단지 메시지를 전달하고 곧바로 다음 일을 진행한다. 메시지는 브로커에 안전하게 저장되며, 수신자는 준비가 되었을 때 메시지를 처리한다. 만약 수신자가 실패하더라도 메시지는 대기 상태로 남아 있다. 하지만 모든 메시징 시스템이 동일한 동작 방식을 제공하는 것은 아니다. 이번 글에서는 자주 나타나는 3가지 주요 패턴에 대해 살펴 보고자한다.핵심 개념생산자, 소비자, 브로커..