#Spring
글 18편 · 학습 노트 4편 포함
-
회사마다 클러스터를 하나씩 통째로 띄운다
kind 로 만드는 멀티테넌시
한 줄로 회사를 하나 만들면, 그 회사 전용 쿠버네티스 클러스터가 통째로 하나 생긴다. 네임스페이스가 아니라 클러스터다. 서버 한 대 위에 kind 클러스터가 회사 수만큼 뜬다. 왜 네임스페이스가 아닌가 보통 멀티테넌시(여러 고객이 한 시스템을 나눠 쓰는 구조)는 네임스페이스로 가...
-
캐시가 아니라 자로 쓴 Redis
통계 API 응답시간을 직접 재기
관리자 화면에 “통계 API 평균 응답시간” 을 띄워야 했다. 통계 API 는 집계 쿼리가 무거워 느려지면 먼저 티가 나는 쪽이라, 지금 얼마나 걸리는지를 화면에서 보고 싶었다. APM 을 붙이는 선택지가 있었지만 그러지 않았다. 알고 싶은 것은 특정 URL 접두사 하나의 평균 이...
-
장부만 지우고 세션은 살려뒀다
동시 접속 기기 제한이 안 걸린 이유
구독 플랜별로 동시 접속 기기 수를 제한하는 기능이다. 무료는 1대, 상위 플랜은 그 이상. Redis 에 사용자별 세션 목록을 두고, 로그인할 때 개수를 세어 넘으면 막는다. 만들고 나서 테스트했더니 제한이 걸리는데도 다른 기기가 계속 쓰였다. 로그인 화면에서는 “기존 기기를 종...
-
예외를 잡았는데도 롤백됐다
rollback-only 마크를 몰랐다
문제: 부가 작업이 실패하면 본 작업까지 사라진다 LCA 승인 기능에 부가 작업이 둘 붙어 있다. baseline 저장 — 승인 시점의 지표를 스냅샷으로 남김 할당 스냅샷 — 같은 성격 둘 다 승인의 전제조건이 아니다. 없어도 승인은 유효하다. 그런데 이게 실패하면 승인 자체가 5...
-
동기 호출과 무엇이 다른가
비동기 메시징 입문
비동기 메시징 이란 서비스끼리 직접 부르지 않고, 중간에 둔 저장소에 메시지를 넣어 주고받는 방식 보내는 쪽은 메시지를 넣고 바로 자기 일을 끝낸다. 받는 쪽이 지금 살아 있는지 신경 쓰지 않는다 받는 쪽은 자기 속도로 꺼내서 처리한다 중간에서 메시지를 맡아 두는 것을 브로커(Br...
-
REST 와 무엇이 다른가
GraphQL 입문
GraphQL 이란 API 를 통해 데이터를 주고받기 위한 쿼리 언어(Query Language, 원하는 데이터를 문장으로 적어 요청하는 문법) 클라이언트가 “무엇이 필요한지”를 직접 적어서 보내면, 서버가 딱 그만큼만 돌려준다 2012년 페이스북이 사내에서 만들어 2015년에 공...
-
트랜잭션을 쪼갰더니 잠들어 있던 버그가 깨어났다
문제: 최악 41시간짜리 단일 트랜잭션 운송 구간의 거리를 외부 API로 받아오는 배치가 있다. 이 배치의 트랜잭션 경계가 잘못돼 있었다. 구조 — resolveAll이 @Transactional 하나로 전량을 감쌈 상한 — run 당 최대 10,000건 외부 API read ti...
-
ddl-auto: update 의 빈틈을 메웠다
보완 DDL 자동화로 채운 것
Flyway를 걷어낸 뒤 남은 숙제 이전 글: Flyway를 도입하고 3주 만에 걷어낸 이야기 걷어낸 뒤 스키마 관리 방식 JPA ddl-auto 사람이 손으로 적용하는 SQL 파일 묶음(db/manual/*.sql) 구멍 두 가지 stg 환경은 ddl-auto: validate ...
-
OCR 파싱에 30초 타임아웃으로는 부족했다
webhook 비동기로 옮기기
30초로는 부족했다 기능: 문서 OCR 파싱 기존 구조: 내부 OCR 서비스에 HTTP 요청 → 결과 수신 → 응답 (동기) 30초 타임아웃에 계속 걸린 원인 두 가지: PaddleOCR 콜드스타트 — 모델 로딩 지연. 유휴 후 첫 요청이 특히 느림 페이지당 처리 지연 — 문서 길...
-
readOnly 에서 write 를 잡아냈다
테스트 가드레일 만들기
조회 API가 매번 write 트랜잭션을 만들고 있었다 발단 — 대시보드 조회 API 응답 지연 확인 결과 — eco-view의 배출원 조회 경로가 lcaStepService.updateStepOnly(write)를 부수효과로 호출 즉 대시보드를 열 때마다 write 트랜잭션 생성...
-
TOCTOU 한 건을 고치는 대신 버그 클래스를 없앴다
문제: SFTP 업로드가 동시에 들어오면 터졌다 프로젝트: 웹 버튼 클릭 → Hyperledger Fabric·Besu 네트워크를 Kubernetes 클러스터에 배포하는 플랫폼 인프라 계층: JSch로 원격 서버에 SSH/SFTP 접속 → bash 스크립트 전송 후 실행 해당 업로...
-
인증 필터가 매 요청 DB를 네 번 때리고 있었다
문제: TPS가 안 나온다 부하 테스트에서 목표 TPS 미달 애플리케이션 로직 자체는 가벼움 조사 방향: 비즈니스 코드가 아니라 모든 요청이 반드시 지나가는 경로 구성: Spring Security + JWT 필터 체인 추적 결과: DB 접근이 겹겹이 누적 지점 하는 일 JwtFi...
-
같은 User인데 권한 검사가 깨졌다
재사용의 숨은 계약
3분 만에 되돌린 최적화 인증 경로에서 DB를 네 번 때리던 걸 걷어낸 이야기는 인증 필터가 매 요청 DB를 네 번 때리고 있었다에 썼다. 감사 로그 비동기화, 커넥션 풀, 인메모리 캐시까지 29분 동안 커밋 여섯 개가 나갔다. 그 글에 안 쓴 게 하나 있다. 여섯 중 하나는 3분...
-
캐싱은 쉬웠고 무효화가 어려웠다
권한 체크를 세션에 올린 뒤
문제 기존 권한 모델: user_level 정수 하나 숫자가 클수록 많은 권한 한계: “조회는 되는데 삭제는 안 되고, 다른 화면에서는 승인 권한이 있다” 같은 요구 → 정수 하나로 표현 불가 새 권한이 생길 때마다 숫자 구간 재해석 필요 그 해석이 코드 여기저기에 분산 결정: 권...
학습 노트
책·강의를 따라 적은 정리 4편. 2026 이전에 쓴 것이다.
-
티켓 원정대 출발!
프로젝트 시작 — 기술 선택과 파트 나누기
프로젝트 시작 TDD 책을 정독하고 읽었던 내용들을 사용해보는 프로젝트를 진행해보려고 한다. 나는 2,3번 프로젝트를 진행해봤는데 결과는 좋지 않았고 이번에는 결과물을 완성하고 싶은 마음이 크다. 설명 100명에게 Ticket을 배포하는 프로그램을 RESTful방식 개발합니다 *신...
-
엔티티 설정
Account 엔티티를 두고 한 고민
고민 과연 Account 객체를 생성할 때 필요한 column명을 찾아서 적어봤다. Account @Getter @Builder @Entity @NoArgsConstructor @AllArgsConstructor public class Account { @Id @GeneratedV...
-
내가 적어보는 Hateoas 정리
DTO 안에 넣을 수 있을까
Hateoas 티켓 프로젝트를 진행하면서 rest(ful?) api 문서화를 만드는 중, 우리는 hateoas를 당장 써서 만들어야 할지 아닐지 고민되었다. 그래서 일단 자료조사를 위해서 hateoas에 대해 알아보려고 한다. Hateoas 란? Wikipedia에서 ‘hateoa...
-
DTO 처리방법
VO·Entity 와 무엇이 다른가
티켓 프로젝트를 진행하다가 다들 DTO에 대한 처리방식이 있었는데 나도 하나 적고 싶어서 DTO에 대한 내용을 찾다가 DTO에 관한 고찰 이분에 대한 내용 글이 재미있어서 읽고 블로그에 정리하고 싶어졌다. DTO 란? Data Transfer Object 로 계층간의 데이터를 교환...