728x90
반응형

Backend/Spring 22

[Spring] 화이트리스트(Whitelist)를 활용한 XSS 공격 철벽 방어하기

XSS란? XSS와 CSRF 개념 및 차이점 정리 XSS와 CSRF 차이점 정리신입 시절, 기술 면접을 준비하거나 보안 관련 문서를 읽을 때마다 항상 헷갈리던 두 단어가 있었습니다.바로 XSS와 CSRF입니다.둘 다 웹 해킹 기법이라는 건 알겠는데, 막상 "정확히 뭐가 달라?"라show5116.tistory.com 웹 애플리케이션을 개발할 때 빼놓을 수 없는 보안 위협 중 하나가 바로 XSS(Cross-Site Scripting)입니다.악의적인 사용자가 웹 페이지에 악성 스크립트를 삽입해 다른 사용자의 정보를 탈취하거나 비정상적인 동작을 유발하는 공격이죠. XSS를 막기 위해 같은 위험한 태그를 막는 블랙리스트(Blacklist) 방식을 종종 사용하지만, 우회 기법이 끊임없이 발전하기 때문에 완벽한 방..

Backend/Spring 2026.04.02

[Spring] P6Spy로 일관된 쿼리 로깅 환경 구축하기

실무에서 프로젝트를 진행하다 보면 JPA만 단독으로 쓰기보다는, 복잡한 통계 쿼리를 위해 QueryDSL을 섞어 쓰거나 레거시 코드로 인해 MyBatis, JdbcTemplate 등을 한 서비스 안에서 혼용하는 경우가 꽤 많죠.저도 이런 환경에서 개발하다 보니, 각 기술마다 쿼리가 찍히는 로깅 포맷이 달라서 디버깅할 때마다 로그 읽기가 너무 고통스럽더라고요.그래서 이 파편화된 로깅 방식을 한 번에 통일해서 잡아주는 P6Spy를 도입하게 되었고, 그 과정과 실무 적용 팁을 공유해 보려고 합니다.1. 왜 P6Spy를 도입해야 할까요?하나의 프로젝트에서 JPA, MyBatis, JdbcTemplate 등을 함께 사용하면 어떤 문제가 발생할까요?JPA(Hibernate): spring.jpa.show-sql=t..

Backend/Spring 2026.03.06

[Spring] 커스텀 어노테이션 4편: Lombok은 어떻게 코드를 만들어낼까? (AST 조작)

어느덧 커스텀 어노테이션 시리즈의 마지막 편입니다!1편의 기본 개념을 시작으로, 2편에서는 런타임에 메소드를 가로채는 AOP를, 3편에서는 클래스 정보를 동적으로 읽어오는 Reflection을 다루었죠. 오늘은 어노테이션 활용의 끝판왕이자, 우리가 숨 쉬듯 사용하고 있는 Lombok(@Getter, @Setter)의 동작 원리인 AST(Abstract Syntax Tree) 조작에 대해 이야기해 보려 합니다. 솔직히 말씀드리면, 4년 차인 저도 실무에서 AST를 직접 조작하는 코드를 구현하지는 않습니다.유지보수도 까다롭고 구현 난이도도 너무 높기 때문이죠.하지만 우리가 매일 쓰는 도구의 원리를 아는 것과 모르는 것은 문제 해결 능력에서 큰 차이를 만듭니다.가벼운 마음으로 "아, 롬복이 이렇게 일하는구나!..

Backend/Spring 2026.03.04

[Spring] 커스텀 어노테이션 3편: 리플렉션(Reflection)으로 메일 폼 자동 생성기 만들기

지난 2편에서는 AOP를 이용해 메소드 앞뒤에 공통 로직을 끼워 넣는 방법을 배웠습니다.하지만 가끔은 메소드 호출을 가로채는 것만으로는 부족할 때가 있습니다."객체 안에 어떤 필드가 있는지 런타임에 다 훑어서, 특정 어노테이션이 붙은 값들만 뽑아낼 수 없을까?" 하는 고민이죠. 저도 실무에서 메일 발송 기능을 구현할 때 비슷한 고민을 했습니다.메일 폼에 들어갈 데이터가 매번 달라지는데, 그때마다 수동으로 Map에 담아주는 게 너무 번거로웠거든요. 오늘은 이 문제를 리플렉션(Reflection)으로 우아하게 해결한 경험을 공유해 드릴게요.1. 리플렉션(Reflection)이란?리플렉션은 구체적인 클래스 타입을 알지 못해도 컴파일된 바이트 코드를 통해 클래스의 메소드, 필드, 어노테이션 정보를 들여다보고 조..

Backend/Spring 2026.03.03

[Spring] 커스텀 어노테이션 2편: AOP로 실행 시간 측정 기능 만들어보기

지난 포스팅에서는 어노테이션의 개념과 동작 원리 3가지를 알아봤습니다.오늘은 그중 실무에서 가장 빈번하게 사용되는 AOP(Aspect Oriented Programming)를 이용해, 우리가 만든 어노테이션에 실제 기능을 불어넣어 보려고 합니다."이 메소드 수행 시간이 얼마나 걸리지?"라는 질문을 받을 때마다 모든 메소드 시작과 끝에 로그를 찍고 계셨나요?이제 @TrackTime 하나로 그 고민을 끝내보겠습니다.1. 왜 AOP인가요?지난 글에서 언급했듯, 어노테이션 자체는 이름표일 뿐입니다.누군가는 이 이름표를 보고 "어? 이거 실행 시간 재야 하네?"라고 판단한 뒤 로직을 끼워 넣어야 하죠.Spring AOP는 타겟 메소드(Target)가 실행될 때 이를 가로채서(Intercept) 앞뒤로 공통 로직을..

Backend/Spring 2026.03.01

[Spring] 커스텀 어노테이션 1편: 어노테이션의 기본 개념과 3가지 동작 원리 이

Spring으로 개발하다 보면 수많은 어노테이션을 만납니다.코드 위에 @ 하나만 붙였을 뿐인데 트랜잭션이 걸리고, JSON으로 변환되는 모습을 보면 가끔은 '마법 같다'는 생각이 들기도 하죠.저도 연차가 쌓이면서 반복되는 로직을 줄이고 싶을 때 "이걸 내가 직접 만들어서 자동화할 순 없을까?"**라는 고민을 하게 되었습니다.오늘부터 시작할 시리즈는 그 마법의 정체를 파악하고, 우리만의 지팡이(커스텀 어노테이션)를 만드는 과정을 담았습니다.그 첫 번째 시간으로 어노테이션의 본질과 이를 동작하게 만드는 3가지 방법에 대해 깊이 있게 다뤄보겠습니다.1. 어노테이션(Annotation)이란 무엇인가?사전적 의미로 어노테이션은 '주석'입니다.하지만 우리가 코드에 쓰는 // 주석과는 결이 다릅니다.일반 주석이 개발..

Backend/Spring 2026.02.27

[Spring] WebClient 동기 처리 시 필수! TCP & Block 이중 타임아웃으로 안정성 확보하기 (RestClient 못 쓸 때)

최근 운영 중인 서비스에서 등에 식은땀이 흐르는 경험을 했습니다.잘 돌아가던 Quartz 스케줄러 Job이 어느 순간부터 로그 하나 없이 '멈춤' 상태가 되어버린 것이죠.에러 로그도 없고, 스레드는 살아있는데 작업이 진행되지 않는 좀비 상태였습니다.원인을 파헤쳐 보니 범인은 WebClient의 block() 메서드였습니다.외부 API 통신 중 예상치 못한 네트워크 이슈가 발생했는데, 타임아웃 설정이 제대로 되어 있지 않아 스레드가 무한 대기 상태에 빠진 것이었죠."WebClient는 비동기인데 왜 block을 써?"라고 하실 수 있지만, 레거시 시스템이나 비즈니스 로직상 반드시 동기 처리가 필요한 경우가 있잖아요?게다가 Spring 버전 문제로 최신 RestClient를 도입할 수도 없는 상황이었습니다...

Backend/Spring 2026.02.12

[Spring] @Controller vs @RestController 차이점과 REST API 구축 시 선택 가이드

pring Boot로 개발을 하다 보면 가장 먼저 마주치는 어노테이션 중 하나가 바로 컨트롤러 관련 어노테이션입니다.처음 공부할 때는 책이나 강의에 나오는 대로 Controller를 썼다가, 어느 순간부터 RestController를 자연스럽게 쓰게 되는데요."그냥 요즘은 다 RestController 쓰는 거 아니야?" 라고 생각하고 넘어가기엔, 이 둘의 동작 방식에는 꽤 중요한 차이가 숨어 있습니다.특히 View(화면)를 렌더링 할지, Data(JSON)를 반환할지에 따라 명확하게 구분해서 사용해야 하죠.오늘은 실무에서 API를 개발할 때 왜 @RestController를 사용하는 것이 표준이 되었는지, 그리고 내부적으로 어떤 마법(?)이 숨어있는지 정리해 보려고 합니다.1. 전통적인 강자, @Con..

Backend/Spring 2026.02.03

JPA 대량 데이터 동기화 성능 최적화: Bulk Update

현재 진행 중인 프로젝트에서 'Product(상품)' 데이터를 'Section(규칙)' 정보와 비교하여 동기화(Sync)하는 배치 작업을 구현하고 있었습니다.초기 로직은 단순했습니다.JPA로 Product와 Section 데이터를 모두 조회한다.Java 애플리케이션 메모리 상에서 비교 로직을 수행한다.변경된 데이터는 saveAll(products)로 저장한다.하지만 데이터 양이 늘어나면서 심각한 성능 저하가 발생했습니다.🚨 주요 원인JPA의 N+1 쿼리 발생: saveAll()을 호출해도 내부적으로는 merge()가 동작하면서, 각 엔티티마다 DB에 존재하는지 확인하는 SELECT 쿼리가 발생했습니다. 그 후 UPDATE 쿼리가 건건이 나가는 최악의 상황이었습니다.비효율적인 문자열 파싱: 비교해야 할 ..

Backend/Spring 2026.02.01

[Lombok] @NonNull 완벽 가이드: 필드 vs 파라미터 적용 차이와 빌더 패턴 활용법

우리는 보통 null 체크를 위해 코드를 짤 때 if (param == null) 같은 조건문을 수없이 반복하곤 하죠.코드는 길어지고, 가독성은 떨어지고요.오늘은 이 문제를 깔끔하게 해결해 주는 Lombok의 @NonNull 어노테이션에 대해 이야기해 보려 합니다.특히 필드에 붙일 때와 메서드에 붙일 때의 차이점, 그리고 @Builder 패턴과 함께 사용할 때의 시너지를 실무 관점에서 정리해 보겠습니다.1. Lombok @NonNull이란?Lombok의 @NonNull은 말 그대로 "이 값은 절대 Null이어서는 안 돼!"라고 선언하는 것입니다.단순히 "Null이 아니면 좋겠어"라는 표시(Marking)만 하는 것이 아니라, 컴파일 시점에 자동으로 Null Check 로직을 생성해 줍니다.주의: org...

Backend/Spring 2026.02.01