본문 바로가기

Back-end15

Oracle + Quartz Batch 환경에서 PK Duplicate가 발생하는 이유 — 그리고 왜 이것을 “문제”가 아니라 “받아들여야 할 결과”로 봐야 하는가1. 문제 상황현재 운영 중인 시스템은 Quartz Scheduler를 사용하고 있으며,2개의 애플리케이션 인스턴스가 클러스터링된 환경에서cron trigger 기반으로 배치 작업이 실행되고 있다.quartz.properties 설정을 살펴보면 다음과 같은 클러스터링 관련 설정이 존재했다.org.quartz.jobStore.isClustered = truemisfire 관련 설정 등이로 인해 처음에는 다음과 같이 인식하고 있었다.“Quartz가 클러스터링 환경에서동일한 Job이 동시에 실행되지 않도록 제어해주고 있을 것이다.”그러나 운영 로그를 분석한 결과,동일한 배치 Job이 두 개의 인스턴스에서 동시에 실행된 흔적이 발견되었다.. 2025. 12. 23.
@Transactional 사용 시 주의해야 할 7가지 사항 1. @Transactional의 우선순위@Transactional은 적용되는 위치에 따라 다음과 같은 우선순위를 가진다. 구체적인 메소드에 가까울수록 우선순위가 높다.클래스 메소드 -> 클래스 -> 인터페이스 메소드 -> 인터페이스 순으로 적용된다.2. @Transactional의 작동 모드 (Proxy vs. Aspect)@Transactional의 모드에는 Proxy Mode와 Aspect Mode가 있으며, 기본값(Default)은 Proxy Mode다.Proxy Mode (기본 모드)이 모드는 Public 메소드에 적용해야 한다. Protected나 Private 메소드에 선언해도 트랜잭션이 작동하지 않는다.@Transactional은 프록시 객체 외부에서 접근해야만 AOP(Aspect-Orie.. 2025. 12. 1.
배치가 밀릴 때 발생할 수 있는 락(Lock) 이슈와 해결 방안 데이터가 누적되어 배치가 지연되면 단순히 처리가 늦게 끝나는 문제에 그치지 않는다. 트랜잭션을 길게 점유하면서 운영 DB(OLTP)를 마비시키는 락 상황이 발생할 수 있다. 이에 대한 원인과 해결책을 정리했다.1. 문제 원인: 락 발생 메커니즘일반적인 배치는 조회(READ), 가공(PROCESS), 저장(WRITE)의 흐름을 가진다. 여기서 병목과 문제를 유발하는 단계는 주로 저장(WRITE) 단계다.Row Lock (행 잠금) 배치가 데이터를 수정(UPDATE)하거나 삭제(DELETE)하는 순간, 해당 행들은 커밋되기 전까지 잠긴다. 만약 데이터가 밀려 1만 건을 한 번에 업데이트한다면 트랜잭션이 끝날 때까지 1만 건의 데이터가 잠겨 있게 된다. 이때 실제 사용자가 그중 하나의 데이터를 조회하거나 수정.. 2025. 12. 1.
[Security] 내 security filter chain 구조 이번에 간단한 팀 프로젝트로 인증을 맡게 되었다.정말 많이 배울 수 있었는데, 앞으로도 많은 걸 해야하는 것이구나라고 깨달을 수 있어서 더 의미있는 경험이었다 생각한다. 현재 이 security filter chain에 대한 대략적인 구조도를 기록하고, 나아갈 방향들을 적으려 한다. 1. 구조도 Client에서 요청이 오면 먼저 필터를 거치게 되는데, 내가 설계한 필터 순서는 다음과 같다. 1. logging filter: 거쳐서 들어오는 모든 요청들과 응답들을 찍을 수 있게 하여 디버깅할 때 도움을 줄 수 있도록 함.2. ratelimit filter: bucket4j를 redis에 연결하여서 login 등 인증 api 접근 시 버킷을 차감하여, 정책 상 정해 놓은 상한선을 넘을 시 429 에러를.. 2025. 6. 22.
[Security] refresh token rotation 방식을 쓰는 이유 PREV. 서론refresh token rotation 방식을 도입하게 되면서 첫 번째 구조로서 refresh token을 redis에 access token을 http-only cookie에 두어서 해결하려 했다. 하지만 만료된 access token으로도 user를 식별할 수 있는 로직 설계에서 어렵다는 생각을 하였고, 또한 세션 기반 인증 방식에 가깝다는 생각이 들었다.그러한 생각의 대안으로 OIDC,OAuth 2.1의 흐름에 따라, Refresh Token을 쿠키로 내리는 정책으로 진행했다. 토큰 자체에 상태가 담겨있고, Redis는 단지 대조,회전만을 목적으로 하여 jwt 방식과 비슷하다고 생각하였다. 1. Refresh Token Rotation이란 무엇인가?정의Refresh Token Rot.. 2025. 6. 3.
[Security] JJWT 적용.... 결론적으로 이번 프로젝트에서는 JWS만 사용하여서 관리할 것 같다. 무결성을 보장하는 정도로도 충분할 것 같으며, 애초에 userId, 이름 정도만 claim에 들어갈 것이기 때문에 연산, 키 관리 시의 연산량 측면을 고려해봤을 때 JWS로도 충분하다고 생각했다. 현재 공식 페이지에서 제공하고 있는 종속성은 다음과 같다.또한 다음과 같이 runtime 종속성으로 부여한 이유를 설명하고 있다. 💡JJWT는 애플리케이션에서 사용하도록 명시적으로 설계된 API에만 의존하도록 설계되었으며, 경고 없이 변경될 수 있는 기타 모든 내부 구현 세부 사항은 런타임 전용 종속성으로 분류됩니다. 안정적인 JJWT 사용과 지속적인 업그레이드를 위해서는 이 점이 매우 중요합니다.dependencies { impleme.. 2025. 5. 24.