기술 아티클
직접 쓰고 다듬은 기술 글입니다. 학습 일지에서 검증된 내용을 정리해 올립니다.
-
Zero Trust 관점의 관리자 시스템 접근 통제 설계
관리자 시스템은 계정 하나만 뚫려도 전체 데이터와 설정이 넘어가는 곳이라, "VPN 안에 들어왔으니 믿는다"는 경계 모델이 가장 위험하게 작동하는 자리다. 이 글은 Zero Trust 원칙으로 관리자 접근을 신원, 단말, 정책 판정, 권한, 세션, 감사 여섯 겹으로 나눠 설계하고, 각
-
Spring Security에서 IDOR·BOLA 취약점 방어하기
IDOR·BOLA는 로그인한 사용자가 주소의 번호 하나만 바꿔 남의 주문, 남의 신청서, 남의 계좌를 읽거나 고치는 취약점이다. 인증과 역할 검사를 모두 통과한 요청에서 생기기 때문에 Spring Security 설정만으로는 막히지 않고, 객체를 꺼내는 코드마다 "이 사용자의 것인가"를
-
AI Agent의 Context Engineering과 메모리 계층 설계
같은 모델을 써도 어떤 에이전트는 일을 끝내고 어떤 에이전트는 엉뚱한 파일을 고친다. 차이는 대개 모델이 아니라 "이번 호출에 무엇을 넣었는가"에서 난다. 이 글은 컨텍스트 창을 작업대로 보고 지침·절차·장기 기억·외부 지식을 계층으로 나눠 필요할 때만 불러오는 설계, 그리고 실제로 쓰
-
JVM Thread Dump와 Heap Dump로 장애 원인 분석하기
Java 서비스가 멈추거나 느려졌을 때 가장 흔한 대응은 재시작이고, 재시작하는 순간 원인의 증거도 함께 사라진다. Thread Dump는 그 순간 모든 스레드가 무엇을 기다리는지, Heap Dump는 메모리를 무엇이 붙잡고 있는지를 보여 주는 유일한 기록이다. 이 글은 증상별로 어떤
-
망분리 환경의 Maven·npm 의존성 공급망 보안
망분리 환경은 외부 공격이 막혀 있다고 믿기 쉽지만, 개발에 필요한 라이브러리는 결국 인터넷에서 받아 안으로 들인다. 반입 과정에 검사와 기록이 없으면 악성 패키지와 알려진 취약점도 라이브러리와 함께 내부망에 들어오고, 사고가 났을 때 어디에 퍼졌는지조차 답하지 못한다. 이 글은 Mav
-
Outbox·Inbox 패턴으로 연계 데이터 정합성 확보하기
업무 데이터를 DB에 저장하고 다른 시스템에 메시지를 보내는 일을 따로 하면, 둘 중 하나만 성공하는 순간이 반드시 생긴다. 이 틈 때문에 "신청은 접수됐는데 연계 기관에는 안 갔다", "취소했는데 상대 시스템에는 승인으로 남았다" 같은 정합성 사고가 난다. 이 글은 보내는 쪽의 Out
-
AI Agent Eval 파이프라인과 회귀 테스트 자동화
AI 에이전트는 프롬프트 한 줄, 모델 버전, 도구 설명 하나만 바꿔도 전혀 다른 곳이 깨진다. 같은 입력에도 결과가 매번 조금씩 달라서, 사람이 몇 번 써 보고 "괜찮네"로 끝내면 회귀를 놓친다. 이 글은 평가 세트 만들기부터 채점기, 반복 실행, 기준선 비교, CI 게이트, 운영 로
-
Rust와 Java의 메모리 관리 및 실행 성능 비교
Rust와 Java는 둘 다 "메모리 안전"을 말하지만 방법이 정반대다. Java는 실행 중에 가비지 컬렉터가 안 쓰는 객체를 찾아 치우고, Rust는 컴파일할 때 소유권 규칙으로 언제 메모리를 해제할지 정해 둔다. 이 차이가 메모리 사용량, 지연의 예측 가능성, 시작 시간, 개발 속도
-
eBPF를 활용한 Java 애플리케이션 성능 관측
APM과 JFR은 JVM 안에서 일어나는 일을 잘 보여 주지만, 스레드가 왜 CPU를 받지 못하는지, 어떤 시스템 호출에서 오래 기다리는지, 패킷이 재전송되는지는 JVM 밖, 커널에서 일어난다. eBPF는 애플리케이션을 바꾸거나 재시작하지 않고 커널 안에 작은 관측 프로그램을 붙여 이런
-
Linux Process와 Thread의 Kernel 관점 분석
교과서는 프로세스와 스레드를 다른 개념으로 설명하지만, Linux 커널 안에서는 둘 다 같은 구조체 하나task_struct로 표현되는 "태스크"다. 차이는 무엇을 공유하느냐뿐이다. 이 차이를 알면 top에 보이는 숫자, Java 스레드 수와 메모리, 컨텍스트 스위칭 비용, OOM 동작
-
JVM G1 GC와 ZGC의 동작 원리 및 선택 기준
Java 서비스의 P99 지연을 따라가다 보면 결국 GC 멈춤StopTheWorld을 만난다. G1은 JDK 9부터 기본 GC로 대부분의 서비스에 맞게 처리량과 멈춤 시간의 균형을 잡고, ZGC는 힙 크기와 상관없이 멈춤을 1ms 안팎으로 묶는 대신 CPU와 메모리 여유를 더 쓴다. 이
-
공공 웹서비스 파일 다운로드 권한 검증 설계
공공 웹서비스의 파일 다운로드는 가장 단순해 보이는 기능이면서 개인정보 유출 사고가 가장 자주 나는 기능이다. 목록 화면에서는 권한을 확인했는데 다운로드 주소는 파일 번호만 바꾸면 남의 첨부가 내려받아지거나, 경로 문자열을 그대로 받아 서버의 다른 파일까지 읽히는 식이다. 이 글은 다운
-
CUBRID X_LOCK과 장기 트랜잭션 병목 해결
CUBRID를 쓰는 공공 시스템에서 "특정 시간만 되면 화면이 멈춘다"는 장애의 상당수는 오래 열려 있는 트랜잭션이 잡은 배타 락X_LOCK 때문이다. 쿼리는 빠른데 락을 기다리느라 요청이 쌓이고, 결국 커넥션 풀까지 바닥난다. 이 글은 흔한 패턴으로 재구성한 장애 사례를 따라 X_LO
-
P95와 P99가 평균 응답 시간보다 중요한 이유
"평균 응답 시간 0.3초"라는 보고서는 사용자 100명 중 5명이 4초를 기다렸다는 사실을 숨길 수 있다. 응답 시간 분포는 오른쪽으로 긴 꼬리를 갖고, 장애와 민원은 그 꼬리에서 나온다. 이 글은 평균이 왜 사용자 경험을 대변하지 못하는지, P95·P99를 어떻게 재고 합치고 목표로
-
10 TPS에서 250 TPS까지: 성능 개선 사례 분석
처리량이 10 TPS에서 막힌 시스템을 250 TPS까지 올리는 과정은 대개 하나의 묘수가 아니라 다섯 개쯤의 평범한 병목을 차례로 걷어내는 일이다. 이 글은 공공 SI에서 흔히 만나는 병목들로 재구성한 대표 사례를 따라가며, 어떤 지표로 병목을 찾고 무엇을 바꿨을 때 처리량이 얼마나
-
Spring Security JWT 인증과 인가 아키텍처
JWT 인증은 예제 코드만 보면 필터 하나로 끝나 보이지만, 운영에서 문제가 되는 것은 서명 방식, 토큰 수명, 재발급과 폐기, 브라우저 저장 위치, 권한 매핑 같은 설계 결정이다. 직접 만든 JWT 필터는 검증 누락이 생기기 쉽고, 토큰을 한 번 발급하면 되돌릴 수 없다는 점을 놓치기
-
Redis Look-aside Cache 설계와 Cache Stampede 대응
LookasideCacheaside 캐시는 구현이 쉬워서 가장 많이 쓰이지만, 인기 있는 키 하나가 만료되는 순간 수백 개의 요청이 동시에 DB로 몰리는 Cache Stampede를 만든다. 평소에는 DB 부하를 크게 덜어 주던 캐시가 만료 한 번에 DB를 쓰러뜨리는 것이다. 이 글은
-
MyBatis와 JPA 성능 및 유지보수 관점 비교
국내 SI에서 MyBatis와 JPA는 "어느 쪽이 더 빠른가"로 자주 논쟁이 되지만, 실제 성능 차이는 도구보다 쓰는 방법에서 나온다. JPA는 잘못 쓰면 쿼리가 폭증하고, MyBatis는 잘 쓰면 빠르지만 스키마가 바뀔 때마다 고칠 곳이 늘어난다. 이 글은 두 기술을 성능과 유지보수
-
Spring Boot에서 트랜잭션 경계를 잘못 설계하면 발생하는 문제
@Transactional은 붙이기는 쉽지만 경계를 잘못 잡으면 운영에서 가장 찾기 어려운 장애를 만든다. 경계가 너무 넓으면 커넥션 풀이 마르고 락이 길어지고, 너무 좁거나 아예 없으면 절반만 저장된 데이터가 남는다. 이 글은 Spring Boot에서 트랜잭션 경계를 잘못 설계했을 때
-
한 줄 프롬프트로 프로젝트를 생성하는 Project Factory 설계
"프리랜서 실수령액 계산기 만들어줘" 한 줄로 저장소, 코드, 테스트, 배포까지 끝나는 흐름을 Project Factory라고 부르자. 에이전트에게 그냥 시키면 매번 다른 구조, 빠진 테스트, 확인 안 된 배포가 나온다. 공장처럼 같은 품질로 찍어 내려면 해석, 명세, 템플릿, 구현 루