전체 글 176

[JPA] N+1 문제와 Fetch/Lazy 설명 with Batch Fetch Size

들어가며JPA를 사용하다 보면 피할 수 없는 성능 문제 중 하나가 바로 N+1 문제입니다. 이 글에서는 N+1 문제가 무엇인지, 왜 발생하는지, 그리고 어떻게 해결할 수 있는지를 실제 예시와 함께 살펴보겠습니다.1. N+1 문제란?1.1 예시 상황다음과 같이 주문(Order)과 고객(Customer) 엔티티가 N:1 관계를 맺고 있다고 가정해봅시다.@Entity@Builderpublic class Order { @Id @GeneratedValue private Long id; private String productName; private Integer amount; @ManyToOne @JoinColumn(name = "customer_id") pri..

[LeetCode][JAVA] 4.median-of-two-sorted-arrays

💡 문제median-of-two-sorted-arrays (https://leetcode.com/problems/median-of-two-sorted-arrays/)자세한 문제 설명과 입출력 예는 링크를 참고해주세요. 📝 선행 개념정렬된 두 배열의 중앙값(Median of Two Sorted Arrays) 문제는“정렬된 두 배열을 병합하지 않고 중앙값을 찾는” 고전적인 이진 탐색 문제입니다.전체를 합치지 않아도,“왼쪽 파티션의 최대값 ≤ 오른쪽 파티션의 최소값”이 되는 경계 지점만 찾으면 중앙값을 바로 계산🤓 문제 풀이두 개의 정렬된 배열 nums1, nums2가 주어질 때,두 배열을 하나로 합쳤을 때의 중앙값(median)을 구하라.단, 전체를 병합하지 않고 O(log(m+n)) 시간 복잡도 내에..

MyBatis Generator 실전 가이드 - IntelliJ에서 AutoMapper 생성하기

MyBatis Generator 실전 가이드 - IntelliJ에서 AutoMapper 생성하기 목차1. [MyBatis Generator란?](#mybatis-generator란)2. [프로젝트 초기 설정](#프로젝트-초기-설정)3. [generatorConfig.xml 작성법](#generatorconfigxml-작성법)4. [IntelliJ에서 실행하기](#intellij에서-실행하기)5. [동작 원리 이해하기](#동작-원리-이해하기)6. [실전 예제](#실전-예제)7. [트러블슈팅](#트러블슈팅) MyBatis Generator란?개요MyBatis Generator(MBG)는 데이터베이스 테이블 구조를 분석하여 자동으로 다음 파일들을 생성해주는 코드 생성 도구입니다.- Java Model 클래스 ..

객체지향 프로그래밍 (OOP) 1장 - 실무 관점

들어가며개발 4년 차가 되어서야 비로소 객체지향 프로그래밍(OOP)의 진짜 의미를 이해하게 되었습니다. 입사 초반에는 그저 "캡슐화, 상속, 다형성, 추상화" 네 가지 특징을 외우는 데 그쳤지만, 레거시 코드와 끝없는 리팩토링, 그리고 "왜 이렇게 설계했나요?"라는 질문 속에서 OOP가 단순한 이론이 아니라 '유지보수 가능한 코드'를 위한 철학이라는 걸 깨달았습니다. 이 글에서는 그동안의 실무 경험을 바탕으로 OOP를 어떻게 바라봐야 하고 실제 프로젝트에서 어떻게 적용해야 하는지를 이야기하려 합니다.1. 객체지향 프로그래밍이란?📌 정의의 재해석교과서적 정의는 이렇습니다."컴퓨터 프로그램을 명령어의 목록이 아닌, 독립된 객체들의 모임으로 파악하는 프로그래밍 패러다임" 하지만 실무적 관점에서는 이렇게..

[도서] 마이크로서비스 패턴을 읽고 - 온프레미스 MSA 환경의 현실적인 개선기

들어가며우리 회사는 온프레미스 환경에서 MSA(Microservices Architecture)를 운영하고 있다. 하지만 초기 구축 과정에서 일부 핵심 패턴들이 누락되거나 미흡하게 적용되어 있었고, 이로 인해 실무에서 여러 문제들을 마주하게 되었다. 현재 우리가 직면한 문제들:서킷 브레이커 미적용: 한 서비스의 장애가 연쇄적으로 전파되어 전체 시스템 장애로 확대SAGA 패턴 부재: 분산 트랜잭션 관리가 어렵고, 데이터 정합성 문제 발생오케스트레이션 패턴 미흡: 서비스 간 복잡한 비즈니스 플로우를 관리하기 어려움왜 완벽하게 적용하지 못할까?1. 조직적 장벽학습 곡선이 높고 팀 전체의 이해가 필요레거시 시스템과의 통합 부담"일단 돌아가는 것"이 우선순위2. 기술적 복잡도SAGA 패턴의 보상 트랜잭션(Comp..

도서 2025.10.10

JPA 일대다 단방향 매핑의 함정과 @MapsId를 활용한 해결

들어가며회원 관리 시스템을 개발하던 중, 회원(Member)과 회원 상세 정보(MemberDetail)를 일대다(1:N) 관계로 설계해야 하는 요구사항이 있었다. 한 회원이 전화번호, 주소, SNS 계정 등 여러 타입의 상세 정보를 가질 수 있어야 했기 때문이다.초기에는 간단하게 일대다 단방향 매핑으로 구현했는데, 이게 생각보다 큰 성능 문제를 일으켰다. 100명의 회원을 등록하는 배치 작업에서 쿼리가 200개나 발생하는 것을 발견했다. INSERT 쿼리 100개는 이해가 되는데, 그 뒤에 UPDATE 쿼리가 또 100개씩 따라붙는 것이다.이 문제를 해결하는 과정에서 @MapsId라는 생소한 어노테이션을 만났고, 그 과정을 공유하고자 한다.문제 상황: 불필요한 UPDATE 쿼리비즈니스 요구사항과 테이블 ..

Java 테스트 데이터 생성기 Faker 완전정복 — 정의, 선택 가이드, 실전 사용 패턴

애플리케이션을 개발하다 보면 테스트를 위해 더미데이터가 꼭 필요합니다. 간단히 하드코딩된 문자열을 넣어도 되지만, 현실과 동떨어진 데이터는 실제 케이스를 충분히 검증하기 어렵습니다. 테스트 케이스를 직접 하나하나 만들 수도 있지만, 사람이 생각해낼 수 있는 경우의 수에는 한계가 있죠. 이럴 때 유용한 도구가 바로 Faker입니다. “그럴듯한 더미 데이터”를 빠르게 생성해주어, 이름·주소·상품명·문장·날짜 같은 데이터를 무작위로 뽑아낼 수 있습니다. 저는 최근 더미데이터를 대량으로 생성하는 작업을 하다가 Faker를 활용하게 되었고, 생각보다 다양한 기능과 실무에서 쓸만한 포인트가 있어 공유 차원에서 정리해보았습니다. 테스트는 보통 사람이 설계한 유한한 케이스에 의존합니다. 그러나 현실 세계의 데이터는 다..

Apache Kafka 설치와 Client(Producer/Consumer) 간 Message 송수신 가이드

목차Kafka 4.x 소개 및 KRaft 모드로컬 환경 설치 (macOS)Kafka 서버 실행토픽 생성 및 관리Producer/Consumer 메시지 송수신 테스트Java Client 예제 (실전 코드)트러블슈팅1. Kafka 4.x 소개 및 KRaft 모드Apache Kafka 4.0부터는 ZooKeeper가 완전히 제거되고 KRaft(Kafka Raft) 모드가 기본이 되었습니다. KRaft는 Kafka 자체의 합의 프로토콜을 사용하여 메타데이터를 관리하므로, 별도의 ZooKeeper 클러스터 없이도 Kafka를 운영할 수 있습니다.주요 특징ZooKeeper 의존성 제거: 아키텍처 단순화Java 17 필수: Brokers/Connect/Tools는 Java 17 이상 필요Combined 모드: 로컬 ..

운영/Kafka & MQ 2025.09.17

[Apache Kafka] 주요 개념과 구성 요소 Deep Dive

오늘날 기업 시스템은 더 이상 단일 데이터베이스와 단일 애플리케이션에 의존하지 않습니다.실시간 데이터 스트리밍과 분산 처리가 기본이 되었고, 사용자 이벤트, 주문, 결제, 로그 데이터는 밀리초 단위로 쏟아져 들어옵니다. 이러한 데이터 흐름을 안정적이고 확장 가능하게 처리하기 위해 많은 기업이 선택하는 기술이 바로 Apache Kafka입니다. Kafka는 단순한 메시지 브로커를 넘어서, 이벤트 스트리밍 플랫폼이라는 새로운 패러다임을 제시합니다. 이번 포스팅에서는 Kafka를 처음 접하거나 기본 개념을 다시 정리하려는 분들을 위해, 다음 세 가지 주제를 중심으로 Kafka를 살펴보겠습니다.Kafka의 주요 특징 – Kafka가 다른 메시지 큐와 차별화되는 이유Kafka의 핵심 구성 요소 – Cluster,..

운영/Kafka & MQ 2025.09.17

JVM 가비지 컬렉션(feat. Parallel, CMS, G1)과 운영 트러블슈팅 사례

백엔드 시스템을 운영하다 보면, 코드 수준의 최적화만으로는 해결되지 않는 성능 병목을 마주하게 됩니다.특히 자바(Java) 기반 서버는 JVM 메모리 관리와 Garbage Collection(GC) 정책에 따라 서비스 안정성과 응답 속도가 크게 달라집니다. 운영 환경에서 트래픽이 급증하면, 예상치 못한 Full GC, OutOfMemoryError, 커넥션 풀 고갈과 같은 문제가 한꺼번에 발생하며 서비스 전체가 지연되거나 중단될 수 있습니다.저는 특정 외부 연동 서버 운영 중 실제로 이러한 문제를 경험했습니다. 순간적으로 API 응답이 수 초 단위로 지연되고, 504 Gateway Timeout이 동시다발적으로 발생했으며, TCP 연결이 100%까지 포화되는 상황이 반복되었습니다.이 과정에서 JVM 메모..

[LeetCode][JAVA] 200. Number of Islands

💡 문제200. Number of Islands (https://leetcode.com/problems/number-of-islands/)자세한 문제 설명과 입출력 예는 링크를 참고해주세요. 📝 선행 개념 그래프 관점의 격자(Grid as Graph): 각 칸을 정점으로 보고, 상하좌우 4방향으로 간선이 있다고 보면 연결된 ‘1’들의 묶음이 곧 섬이다.BFS/DFS로 영역(Connected Component) 세기: 방문하지 않은 육지(‘1’)를 발견할 때마다 탐색을 시작해 연결된 모든 칸을 방문 처리하고, 시작 횟수가 섬의 개수다.방문 처리 방식: visited 배열을 별도로 쓰거나, 입력 그리드를 직접 수정(‘1’→‘0’) 하여 재방문을 방지한다. 🤓 문제 풀이그리드를 순회하며 ‘1’을 만나면 ..

[LeetCode][JAVA] 560. Subarray Sum Equals K

💡 문제560. Subarray Sum Equals K (https://leetcode.com/problems/subarray-sum-equals-k/submissions/1763406903/?source=submission-noac)자세한 문제 설명과 입출력 예는 링크를 참고해주세요. 📝 선행 개념Prefix Sum(누적합): prefix[i] = nums[0] + ... + nums[i]구간합 공식: sum(l..r) = prefix[r] - prefix[l-1]해시맵 카운팅: 지금까지 등장한 누적합 값의 빈도를 Map로 관리🤓 문제 풀이인덱스 r까지의 누적합을 prefix라 하면, 합이 k인 서브어레이 (l..r) 존재 조건은prefix[l-1] = prefix[r] - k.따라서 현재 pre..

[LeetCode][JAVA] 347. Top K Frequent Elements

💡 문제347. Top K Frequent Elements (https://leetcode.com/problems/top-k-frequent-elements/submissions/1763392089/)자세한 문제 설명과 입출력 예는 링크를 참고해주세요. 📝 선행 개념빈도 집계(Frequency Count): Map로 원소별 등장 횟수 계산.버킷 정렬(Bucket Sort): 빈도 f별로 리스트를 두어, 높은 빈도부터 꺼내면 Top K를 빠르게 구할 수 있음.최소 힙(Min-Heap) 대안: (빈도, 값)을 크기 k의 힙으로 유지해도 됨(시간 O(n log k)).🤓 문제 풀이정수 배열 nums에서 가장 자주 등장한 원소 k개를 반환한다(순서는 무관).O(n)로 풀고 싶다면 버킷 정렬이 깔끔하다:해시..

[LeetCode][JAVA] 238. Product of Array Except Self

💡 문제238. Product of Array Except Self (https://leetcode.com/problems/product-of-array-except-self/description/)자세한 문제 설명과 입출력 예는 링크를 참고해주세요. 📝 선행 개념 Prefix/Suffix 누적곱: 각 인덱스 i에서의 답은 “왼쪽 모든 원소의 곱 × 오른쪽 모든 원소의 곱”.공간 최적화 트릭: 출력 배열을 왼쪽 누적곱으로 먼저 채우고, 뒤에서 앞으로 오른쪽 누적곱을 곱해주면 보조 배열 없이 해결 가능.나눗셈 금지: 문제 제약상 division 없이 O(n)에 처리. 🤓 문제 풀이정수 배열 nums가 주어질 때, 각 위치 i에 대해 nums[i]를 제외한 나머지 모든 원소의 곱을 구한다.ans[i] ..

[LeetCode][JAVA] 33. Search in Rotated Sorted Array

💡 문제33. Search in Rotated Sorted Array (https://leetcode.com/problems/search-in-rotated-sorted-array/description/)자세한 문제 설명과 입출력 예는 링크를 참고해주세요. 📝 선행 개념 이진 탐색(Binary Search): 정렬 배열에서 O(log n)으로 탐색.회전된 정렬 배열의 성질: 중복이 없으면 임의의 mid에서 좌/우 절반 중 하나는 반드시 오름차순이다.구간 선택 불변식: 매 반복, “정렬된 절반”을 판별 → 타겟이 그 정렬 구간 범위에 포함되면 그쪽으로, 아니면 반대쪽으로 탐색 구간을 절반으로 줄인다. 🤓 문제 풀이오름차순 정렬 배열이 어떤 피벗 k에서 회전된 상태에서, 주어진 target의 인덱스를 ..

[LeetCode][JAVA] 167. Two Sum II – Input Array Is Sorted

💡 문제167. Two Sum II - Input Array Is Sorted (https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/description/)자세한 문제 설명과 입출력 예는 링크를 참고해주세요. 📝 선행 개념투 포인터(Two Pointers): 정렬된 배열의 양 끝에서 시작해 합계를 비교하며 포인터를 안쪽으로 이동.단조성 활용: 배열이 오름차순 정렬(non-decreasing)이므로, 합이 작으면 왼쪽 포인터 증가, 크면 오른쪽 포인터 감소.🤓 문제 풀이정렬된 정수 배열 numbers(1-indexed)와 target이 주어질 때, 합이 target인 두 원소의 1-기반 인덱스를 반환한다.배열이 정렬되어 있으므로 투 포인터로..

[LeetCode][JAVA] 76. Minimum Window Substring

💡 문제76. Minimum Window Substring (https://leetcode.com/problems/minimum-window-substring/submissions/1763182670/)자세한 문제 설명과 입출력 예는 링크를 참고해주세요. 📝 선행 개념슬라이딩 윈도우(Sliding Window): 포인터 L(left), R(right)을 사용해 윈도우를 확장/축소하며 조건을 만족하는 최소 길이를 탐색.빈도 카운팅(Frequency Counting):need[c] = t에 필요한 각 문자의 총 개수win[c] = 현재 윈도우에 포함된 각 문자의 개수만족도 트래킹(formed/required):required = 필요 문자 종류 수(need[c] > 0인 문자 개수)formed = 현재 ..

[LeetCode][JAVA] 3. Longest Substring Without Repeating Characters

💡 문제3. Longest Substring Without Repeating Characters (https://leetcode.com/problems/longest-substring-without-repeating-characters/description/)자세한 문제 설명과 입출력 예는 링크를 참고해주세요. 📝 선행 개념슬라이딩 윈도우(Sliding Window): 두 포인터 left, right로 현재 고려하는 부분 문자열(윈도우)을 나타내며, 조건을 만족하도록 윈도우를 확장/축소한다.중복 추적(최근 위치 인덱싱): Map에 각 문자의 가장 최근 등장 인덱스를 저장해, 중복이 감지되면 left를 건너뛰며 점프시킨다.불변식: 매 반복에서 [left, right] 구간은 “중복 없는” 부분 문자열이..

macOS에서 nvm 설치 시 command not found: nvm 오류 해결기

1. 문제 상황Homebrew로 nvm을 설치하고, 다음과 같이 설정을 추가했음에도 불구하고export NVM_DIR="$HOME/.nvm"[ -s "$(brew --prefix nvm)/nvm.sh" ] && . "$(brew --prefix nvm)/nvm.sh"터미널에서 확인하면 nvm 명령어가 인식되지 않았다.local@MacBookPro ~ % nvm -vzsh: command not found: nvm2. 케이스 별 원인중복된 환경 변수 선언export NVM_DIR를 여러 번 선언해 혼란이 생겼음.zsh 초기화 파일 문제설정을 ~/.zprofile이나 다른 파일에 넣어서, 실제로는 ~/.zshrc가 로드되지 않았음.nvm 디렉터리 미생성~/.nvm 디렉터리가 없으면 nvm이 정상 동작하지 않..

[오픈소스] 오픈소스 기여 모임 9기 후기

올해 9월, 저는 오랫동안 관심만 두었던 오픈소스 기여를 실제로 실행에 옮기기로 결심했습니다.회사 프로젝트, 학업, 이직 준비까지 병행하는 상황에서 “할 수 있을까?”라는 고민도 있었지만, 그보다 더 크게 다가온 감정은 “지금 이 열정이 식기 전에 꼭 시작해보자”는 마음이었습니다.제가 오픈소스에 기여하려는 목적은 명확했습니다.기술력 향상: 실제 사용 중인 기술 스택(Spring, Redis, Kafka 등)과 맞닿은 프로젝트에 직접 기여하며 실전 경험을 쌓고 싶었습니다.커리어 & 포트폴리오: 단순히 학습에 그치지 않고, PR·커밋 로그·이슈 히스토리를 통해 객관적인 실적을 남기고자 했습니다.커뮤니티 경험: 메인테이너와 개발자들과 소통하며 코드 리뷰를 받고, 협업 과정을 직접 체감하고 싶었습니다.이를 위해..

오픈소스 기여 2025.09.09

Spring에서 Connection Pool 누수 에러의 진짜 원인과 해결 방법

1. 들어가며실무에서 HikariCP 로그에 Connection is not available, request timed out 이 찍혔습니다. 처음엔 @Transactional이나 Spring 설정 문제라고 생각했는데, 조사해보니 전혀 아니었습니다... 실무에서 Connection Pool 누수(Connection Leak) 는 흔히 마주치는 골칫거리 중 하나입니다.로그에 찍히는 메시지는 다양합니다.HikariCP:Connection leak detection triggered for ...Commons DBCP:DBCP object created ... was never closedTomcat JDBC Pool:Connection has been abandoned많은 개발자가 이 로그를 보면 “@Tr..

프론트 정렬로는 못 푸는 문제, 서버 알고리즘으로 풀다: Pin & Slice

왜 이걸 했나....검색/정렬/페이징이 섞인 목록에서 “매칭된 항목(is_matched=1)은 무조건 최상단”이라는 UX 요구가 있었다. 프론트에서 정렬만 하면 매칭 항목이 31번째에 있을 때 1페이지(30개)에는 절대 못 나온다. 이건 페이징 레이어의 책임이다. 데이터가 페이지로 잘리기 이전에 순서가 결정돼야 한다.1) 문제 정의: 왜 프론트 정렬로는 안 되는가사용자 요구: “매칭된 항목(is_matched=1)은 항상 1페이지 최상단에 노출되어야 한다.”일반적으로 프론트에서 정렬만 수행하면 서버가 이미 page_size=30으로 데이터를 잘라 보냈을 때, 31번째 위치의 매칭 항목은 2페이지에 묻혀 1페이지에 올 수 없습니다.즉, 정렬 → 페이징의 순서가 서버에서 보장되어야 합니다.2) 제약과 설계 ..

[자료구조] 단순 연결 리스트(Singly Linked List) 개념과 문제 예제 정리

단순 연결 리스트(Singly Linked List)자료구조의 기본이자, 면접 단골 주제인 단순 연결 리스트(Singly Linked List)!이번 포스팅에서는 단순 연결 리스트의 구조와 특징부터,자주 등장하는 구현 예제 및 실전 응용 문제까지 하나하나 정리해보았습니다.📚 자료구조를 공부하면서 리스트 관련 핵심 개념을 정리해둔 글로,Java와 Kotlin 코드 예제를 함께 작성하며 복습 겸 블로그 기록으로 남깁니다.🧩 1. 단순 연결 리스트란?연결 리스트(Linked List)는 배열과 달리 메모리 공간을 동적으로 할당하며 데이터를 연결해 나가는 자료구조입니다.그중 단순 연결 리스트(Singly Linked List)는 한 방향으로만 노드가 연결되는 구조입니다. 리스트는 배열과 달리, 원소 간의 '..

네트워크 관리사 2급 2025년 필기&실기 합격 후기(+공부법)

1. 들어가며: 왜 이 시험을 준비했는가?개발자로서 실무를 하다 보면, 서비스 장애나 트래픽 이슈의 원인을 추적하는 과정에서 반드시 네트워크에 대한 이해가 필요하다는 걸 체감하게 됩니다. 특히, 로드밸런싱 이슈나 포트 포워딩 설정 문제, DHCP 서버 구성 오류와 같은 상황을 직접 겪으면서 백엔드 개발자에게도 인프라 지식은 선택이 아닌 필수라는 확신이 들었습니다.그동안 "코드만 잘 짜면 된다"는 생각에서 벗어나, 서비스가 실제로 어떻게 전달되고 라우팅되는지, TCP/IP 수준에서 무슨 일이 벌어지는지 더 깊이 알고 싶었습니다. 그래서 이론과 실무 모두를 아우를 수 있는 입문형 자격증인 네트워크 관리사 2급에 도전하게 되었고, 회사 업무와 병행하며 필기와 실기까지 한 번에 합격하게 되었습니다.공부하면서 단..

자격증 2025.07.06

실시간 번역 상태 처리 시스템: Spring 기반 Redis Pub/Sub, SSE Emitter 트래킹, 구조 비교까지

앞서 큐 기반 구조 설계 및 Redis Pub/Sub 확장을 통해 실시간 상태 처리 문제를 해결한 내용을 공유했습니다. 이 글에서는 그 확장 내용을 다음 3가지로 나누어 심화 정리합니다Spring 기반 Redis Pub/Sub Listener 설정SSE Emitter 등록 및 해제, 메모리 누수 방지단건/다건 SSE 처리 구조의 기술적 차이 및 도식화1️⃣ Spring에서 Redis Pub/Sub Listener 설정Spring에서 Redis를 통한 Pub/Sub 구현은 다음과 같이 구성합니다.✅ RedisMessageListenerContainer 설정@Configurationpublic class RedisPubSubConfig { @Bean public RedisMessageListene..

실시간 번역 상태 처리를 위한 큐(Queue) 자료구조 아키텍처와 Redis 확장기

💡 실시간 번역 상태 처리를 위한 큐 기반 아키텍처와 Redis 확장기1. 도입 – 왜 이 기능이 필요했는가?법령 번역 비교 서비스에서는 AI 기반 번역 요청 후, 번역 완료까지의 시간이 수초에서 수분 이상 소요되며, 프론트엔드는 SSE(Server-Sent Events)를 통해 사용자에게 실시간 상태를 반영해야 합니다.그러나 다음과 같은 실무적 요구사항과 문제가 발생했습니다:다건 작업 트래킹: 여러 작업을 동시에 처리 중인 사용자가 각 작업별 상태를 실시간으로 받아야 함진행률 상태 역주행 이슈: 이전에 전송된 진행률보다 낮은 값이 수신되는 경우 사용자 혼란 야기SSE 전송 누락/지연: 순차 처리 없이 push할 경우, 병렬 작업 간 race condition 발생수천 개의 법령 작업에 대한 상태 정합..

[운영] 특정 요청만 504 Gateway Timeout?

API Gateway 구조와 동작 원리로 본 근본 원인 분석대규모 서비스에서 간헐적인 504 Gateway Timeout은 흔한 장애 유형 중 하나입니다. 특히 “특정 요청만” 실패할 때, 많은 개발자들이 Gateway의 부하나 단순 네트워크 문제로 치부하고 넘어가기 쉽습니다.하지만 Gateway 구조를 면밀히 들여다보면, 원인은 서비스 간 라우팅 구조, 인증/플러그인 처리 흐름, 그리고 타임아웃 설정 간 mismatch로 좁혀질 수 있습니다. 이번 포스팅에서는 API Gateway의 구조적 원리를 기반으로, 왜 특정 요청만 실패하고, 어떤 조건에서 지연이 발생하는지에 대한 기술적 원인을 탐색합니다. 1. API Gateway의 기본 구조- Reverse Proxy로서의 역할 API Gateway는 클라..

Network 2025.05.11

[504의 교훈] APISIX 전환으로 겪은 장애, 그리고 우리가 준비하지 못한 것들

1. 장애의 시작: Gateway를 바꾸면 모든 게 나아질 줄 알았다기존에 Go 기반 자체 Gateway(이하 Go Gateway)를 사용하고 있었다.필요한 라우팅 로직만 얹어 경량화된 구조였지만, 다음과 같은 한계에 부딪혔다. 동적 라우팅 관리의 부재인증/권한/로깅 플로우 중복버전 관리가 힘든 직접 코드 관리 구조 이러한 요구사항을 해결하기 위해 우리는 Apache APISIX로 전환을 시도했다.APISIX는 오픈소스 고성능 API Gateway로서 Nginx + Lua 기반, 플러그인 시스템을 제공하며레이트 리밋, 인증, 서비스 디스커버리, 로깅 등 다양한 기능을 유연하게 다룰 수 있었다. 기능만 놓고 보면 “완벽한 선택”이었다. 2. 그러나, 우리는 너무 빨랐고 느렸다전환 초기, APISIX는 문제..

운영 2025.05.11

[인프런] Simple Design: 25년차 개발자가 전하는 깔끔한 코드의 본질

좋은 코드의 기준, 정말 '주관적'일까요?좋은 코드의 기준이 있을까요? 깔끔한 코드? 읽기 쉬운 코드? 아름다운 코드?좋은 코드의 기준이 이런 주관적인 것 밖에 없을까요?팀장과 나의 코드 기준이 다른가요?동료들의 코드를 리뷰할 때 나는 어떤 이야기를 해줄 수 있을까요?본 밋업에서는 코드의 품질을 좀더 객관적으로 판단할 수 있는 기준들을 제시합니다.그러나, 그 기준을 단순히 제시하는 것에 그치기보다는, 그 기준을 이끌어내기 위해 어떤 질문들을 던졌는지어떤 사고 과정을 거쳤는지를 공유하고 각자가 스스로 고민하고 판단할 수 있는 기회를 제공하고자 합니다.그래서, 각자가 다른 사고 과정을 거치더라도 보편적인 기준에 도달할 수 있다는 것을 함께 경험하기를 바랍니다.사실 이 밋업을 듣는다고 해서 갑자기 매일 좋은 ..

스터디 2025.05.06

Elasticsearch 색인(Index) 구조

Elasticsearch 색인(Index) 구조 완전 정복 1. 서론 – Elasticsearch를 이해하려면 Lucene부터Elasticsearch는 강력한 분산 검색 엔진이지만, 그 핵심에는 Apache Lucene이라는 라이브러리가 있습니다. Elasticsearch는 데이터를 검색하기 위해 Lucene을 내부적으로 사용하며, 색인(index)과 검색(search)과 관련된 대부분의 기능은 Lucene의 구조 위에 구축되어 있습니다.따라서 Elasticsearch의 동작 원리를 정확히 이해하려면 Lucene이 데이터를 어떻게 색인하고 검색하는지를 먼저 알아야 합니다.2. Lucene의 색인 구조와 Elasticsearch 내부 동작2.1 문서 색인과 Flush문서가 색인될 때, Lucene은 해당 ..