운영 핵심 — @Transactional · Spring Security
운영 핵심 — @Transactional · Spring Security
🎯 이 lesson 을 읽고 나면
이 lesson 을 다 읽고 나면 아래 3가지를 자신 있게 할 수 있습니다.
- ▸✅ Spring Security Filter Chain 그림 + JWT 인증 필터 위치
- ▸✅ @PreAuthorize 로 메서드 레벨 권한 제어
- ▸✅ BCryptPasswordEncoder 가 표준인 이유 (MD5/SHA-1 금지)
학습 목표를 체크리스트로 두고 다 답할 수 있게 되면 lesson 을 닫으세요.
@Transactional — *Spring 의 가장 강력한 한 줄*
핵심 한 줄
@Transactional 어노테이션 한 줄이 해당 메서드를 DB 트랜잭션 안에서 실행합니다. 예외 발생 시 자동 롤백, 성공 시 commit. 송금·결제처럼 원자성이 중요한 작업의 표준.
가장 단순한 사용
DB 의 BEGIN·COMMIT·ROLLBACK 를 Spring 이 자동 으로 감싸줍니다. 깜빡 잊을 일 없음.
프록시 기반 — 외부 호출만 적용
Spring 의 @Transactional 은 AOP 프록시 로 동작합니다. 메서드 외부에서 호출 될 때만 트랜잭션이 적용됩니다.
같은 클래스 안에서 메서드 호출은 프록시를 우회 → 어노테이션 무시.
해결:
- ▸다른 Bean 으로 분리
- ▸또는
AopContext.currentProxy()로 자기 프록시 호출
전파 (Propagation) — 트랜잭션 안에서 또 트랜잭션
이미 트랜잭션 안인데 또 @Transactional 메서드를 호출하면 어떻게 될까요? 전파 옵션 으로 결정됩니다.
가장 흔한 사용: 기본 REQUIRED. 단, 로그·감사 기록 처럼 부모 롤백돼도 기록은 남아야 할 때는 REQUIRES_NEW.
롤백 규칙 — RuntimeException 만 자동
기본: RuntimeException 과 그 자손 (Unchecked) 만 자동 롤백. IOException 같은 Checked 예외는 commit 됩니다.
이게 Java 만의 특이한 디자인 — 다른 언어엔 거의 없는 구분. 영문 모르고 데이터 손상 사고가 잦습니다.
해결:
모든 예외에 롤백. 보통 이게 안전한 기본값. Kotlin·최근 Spring 코드는 거의 항상 명시.
readOnly = true — 읽기 전용 최적화
조회만 하는 메서드라면 readOnly=true. JPA 가 변경 감지를 건너뛰어 성능 향상. Hibernate FlushMode 도 자동 NEVER.
클래스 단위:
CQRS 패턴과 자연스럽게 맞닿습니다.
흔한 함정 5가지
1. 내부 호출 — 위에 설명. 같은 클래스 메서드 호출은 트랜잭션 무시
2. Checked 예외 commit — rollbackFor = Exception.class 명시
3. private 메서드 — 프록시 적용 X. public 이어야
4. 트랜잭션 안에서 외부 API 호출 — DB 락이 외부 응답 시간만큼 잡힘. 트랜잭션 밖 에서 호출 권장
5. 너무 큰 트랜잭션 — 전체 메서드 감싸면 락 오래. 최소 범위 로
한 번 정리
- ▸
@Transactional한 줄로 자동 트랜잭션 - ▸프록시 기반 → 외부 호출만 적용
- ▸전파 옵션 으로 중첩 동작 제어
- ▸기본은 RuntimeException 만 롤백 →
rollbackFor = Exception.class권장 - ▸읽기 메서드는
readOnly = true
Spring Security — *인증과 인가*
인증 vs 인가
자주 혼동되는 두 단어:
- ▸인증 (Authentication) = 너 누구야? 신원 확인 (로그인)
- ▸인가 (Authorization) = 너 할 수 있어? 권한 확인 (관리자 페이지 접근)
Spring Security 는 둘 다 처리합니다.
최소 설정 (Spring Security 6 / Spring Boot 3)
URL 별 권한, 세션 정책, JWT 필터 등록 — 모두 한 chain 에서.
로그인 흐름 — 가장 흔한 패턴
1. 비번 검증 (Authentication Manager)
핵심: bcrypt 로 비번 해시 비교. 절대 평문 X.
2. JWT 발급 + 응답
- ▸Access Token — 15분, API 호출마다 헤더
- ▸Refresh Token — 7일, httpOnly 쿠키 (XSS 방어)
3. 이후 요청 — JwtAuthenticationFilter
매 요청마다 토큰 검증 → SecurityContext 에 사용자 정보 저장 → 다른 곳에서 @AuthenticationPrincipal 로 접근.
메서드 단위 인가
URL 단위가 아닌 메서드 단위 권한. SpEL (Spring Expression Language) 로 복잡한 규칙 표현 가능.
활성화: @EnableMethodSecurity 클래스에.
OAuth 2.0 — 소셜 로그인
직접 구현 X, Spring Security OAuth2 Client 사용:
Spring 이 전체 OAuth 흐름 (리다이렉트·토큰 교환·사용자 정보 조회) 을 처리. 콜백에서 우리 DB 의 사용자 와 매핑만.
흔한 보안 함정
1. CSRF disable 남용 — REST API + JWT 면 OK. 세션 쿠키 기반이면 enable 필요
2. CORS 너무 관대 — * 금지. 명시적 origin 리스트
3. 비번 평문 저장 — 사고 직전. bcrypt·argon2 필수
4. JWT secret 노출 — 환경변수, 절대 하드코딩 X
5. SQL Injection — JPA·Parameterized query 항상
한 번 정리
- ▸Spring Security = 인증 + 인가의 표준
- ▸JWT 가 모던 트렌드 (Stateless·모바일 친화)
- ▸비번 bcrypt, JWT secret 환경변수, CSRF·CORS 적절히
- ▸메서드 단위 권한은
@PreAuthorize - ▸소셜 로그인은 OAuth2 Client 한 줄
Spring Security Filter Chain · JWT 필터 구현
Security 의 핵심 — 필터 체인
Spring Security 는 수십 개의 필터를 체인으로 연결 합니다. HTTP 요청이 들어오면 순서대로 모든 필터를 통과 한 뒤 컨트롤러로 도착.
JWT 인증을 추가하려면 체인에 우리 필터를 끼워넣어야 합니다.
JWT 필터 — OncePerRequestFilter 상속
OncePerRequestFilter 는 한 요청당 한 번 실행 보장. Spring 의 forward·include 로 중복 실행 방지.
SecurityFilterChain 등록
.addFilterBefore(...) 로 원하는 위치에 필터 삽입.
메서드 레벨 권한 — @PreAuthorize
SpEL (Spring Expression Language) 로 복잡한 권한 조건 표현 가능. "본인 아니면 ADMIN 만" 같은 패턴이 한 줄로.
정리
- ▸필터 체인 — 요청 처리 파이프라인
- ▸OncePerRequestFilter — JWT 같은 커스텀 필터의 표준 베이스
- ▸@PreAuthorize — 컨트롤러·서비스 레벨 권한 제어
- ▸BCryptPasswordEncoder — 비밀번호는 무조건 bcrypt
면접에서 "Security 어떻게 적용해보셨어요?" 라고 물으면 이 4가지를 언급 할 수 있어야 합니다.
🤖 AI 에게 이렇게 요청해보세요
이 lesson 의 개념을 알면 AI 에게 구체적으로 지시할 수 있습니다. 막연한 "고쳐줘" 가 아니라 어휘를 가진 요청 — 그게 토큰 절약의 출발점입니다.
- ▸"이 SecurityConfig 에 JWT 인증 필터 (OncePerRequestFilter) 추가해줘"
- ▸"이 메서드를 @PreAuthorize('hasRole(ADMIN)') 로 보호해줘"
- ▸"BCryptPasswordEncoder 를 Bean 으로 등록해줘"
왜 이게 토큰을 줄이나
개념을 모를 땐 AI 답변을 받고도 "그게 뭐예요?" 를 다시 물어야 합니다. 그 "다시 물음" 이 토큰을 잡아먹습니다. 개념 한 번 익혀두면 대화가 한 번에 끝납니다.