728x90
반응형

분류 전체보기 113

[HTTP] HTTP 메서드 멱등성

DELETE 메서드는 멱등해야한다.HTTP DELETE 메서드는 원칙적으로 멱등(Idempotent) 해야 한다. 즉,“같은 DELETE 요청을 여러 번 보내도 서버의 최종 상태는 동일해야 한다.”예를 들어 /todos/1/managers/10 을 삭제할 때:첫 번째 요청 → manager 정상 삭제두 번째 요청 → 이미 삭제된 상태지만서버의 최종 상태는 동일(삭제됨)실패가 아니라 성공처럼 처리내가 받은 피드백의 핵심 - 두 번째 DELETE 요청이 실패하면 UX가 깨진다다음과 같은 피드백을 받았다.ManagerController delete 메소드의 인증된유저 처리 문제 에서 HTTP Method중 DELETE는 멱등성을 준수합니다. 제공하는 기능에 따라 멱등성을 준수하지 않도록 만들어야 할 수 도 있..

Network./Server. 2025.12.10

[Spring] Spring Security + JWT로 로그인 기능 구현

전체적인 흐름 클라이언트가 /auth/login 으로 이메일/비밀번호 전송서버에서 사용자 검증 후 JWT 발급이후 요청들은 Authorization: Bearer token헤더에 JWT를 담아서 호출커스텀 JwtAuthFilter가 토큰을 검증하고 userId를 꺼냄@AuthUser 파라미터로 컨트롤러에 userId를 바로 주입→ 컨트롤러/서비스는 JWT 구조를 모른 채 로그인된 사용자 ID만 다룸설계JwtUtil - JWT 생성 및 검증역할토큰 생성토큰 검증Claims / subject 추출설계 기준subject에는 userId를 넣음 (주 식별자)claim으로 email 정도만 추가validate()는 예외 캐치로 단순 처리@Componentpublic class JwtUtil { @Value(..

Dev./Spring 2025.12.09

[Spring] Transactional 사용시 자가호출(Self-Invocation)이슈

문제다음과 같은 코드에서,한 메서드 안에서 다른 @Transactional 메서드를 호출하면나는 REQUIRES_NEW가 적용되어 별도 트랜잭션이 만들어질 것이라고 기대했다.그러나 실제 동작은 전혀 달랐다.@Service@Slf4j@RequiredArgsConstructorpublic class OrderService { private final StockService stockService; private final PaymentService paymentService; private final PaymentRepository paymentRepository; private final OrderRecordService orderRecordService; @Transaction..

Dev./Spring 2025.12.08

[Spring]왜 Security 의존성을 추가하면 API 호출시 401이 뜰까

기존에 잘 돌아가던 demo 프로젝트에 Security 의존성을 추가하니 모든 API 호출시 401에러가 떴다. 왜 의존성 추가 하나만으로 잘 돌아가던 서버가 에러를 뱉는걸까?Security의 기본 보안 정책 자동 활성화Spring Security는 의존성 추가만으로도 다음 설정을 자동 적용 모든 요청은 인증 필요인증되지 않은 요청은 → 401 UnauthorizedForm 로그인 페이지가 자동 생성됨기본 사용자 계정이 자동 생성됨 (username=user, password=콘솔에 출력)즉 security가 추가되며 모든 요청을 가로막은 것이다.Security를 추가한 후의 동작 흐름왜 401일까?Spring Security가 요청을 Controller로 보내기 전에 차단하기 때문 , 컨트롤러에 도달하..

Dev./Spring 2025.12.06

[Nbcam] Level6 정의하고 해결한 문제

1. ManagerController delete 메소드의 인증된유저 처리 문제문제기존 deleteManager 메서드 에서는컨트롤러가 JWT 구조를 알고있음Authorization Header를 직접 읽고 jwtUtil을 직접 사용 @DeleteMappingpublic void deleteManager( @RequestHeader("Authorization") String bearerToken, @PathVariable long todoId, @PathVariable long managerId) { Claims claims = jwtUtil.extractClaims(...); long userId = Long.parseLong(claims.getSubject());}Contr..

카테고리 없음 2025.12.05

[Nbcam] 심화 주차 Level5 AOP를 활용해 특정 API 로깅 구현

Interceptor 또는 AOP를 활용하는 부분이라 나는 AOP 구현을 선택했다.조건AOP를 사용하여 구현하기어드민 API 메서드 실행 전후에 요청/응답 데이터를 로깅합니다.로깅 내용에는 다음이 포함되어야 합니다:요청한 사용자의 IDAPI 요청 시각API 요청 URL요청 본문(RequestBody)응답 본문(ResponseBody)@Around 어노테이션을 사용하여 어드민 API 메서드 실행 전후에 요청/응답 데이터를 로깅합니다.요청 본문과 응답 본문은 JSON 형식으로 기록하세요.로깅은 Logger 클래스를 활용하여 기록변경 파일 상세 설명AccessCheckAOP역할어드민 전용 API 접근 시점에 실행되는 AOP요청 정보 수집 로그로 기록컨트롤러/서비스 로직과 로깅 관심사를 명확히 분리Pointcu..

카테고리 없음 2025.12.04

[Spring] AOP 정리

AOP란AOP (Aspect Oriented Programming) 는 여러 곳에 반복되는 공통 관심사를 비즈니스 로직과 분리해서 한 곳에서 관리하기 위한 프로그래밍 기법AOP가 왜 필요할까?예를들어 기획자가 개발자님 성능 측정을 위해 모든 메서드에 시작 시간과 종료 시간을 남기는 기능 추가해주세요라고 요청을 했을 때public void save() { log.info("start"); // 비즈니스 로직 log.info("end");}다음과 같은 코드가 모든 서비스 메서드마다 중복되면 로깅, 트랜잭션, 권한 체크 코드가 모든 메서드에 흩어짐수정하려면 전체 코드를 다 건드려야 함비즈니스 로직이 더러워짐AOP 도입 후에는 시간 측정은 AOP가 알아서 처리한다.AOP는 어디에 적용되는걸까?..

Dev./Spring 2025.12.03

[Spring] Interceptor 정리

Interceptor란Spring MVC에서 컨트롤러(Controller) 호출 전·후에 요청을 가로채서 공통 로직을 수행하는 도구JWT 기반 인증이 끝난 후, 인증된 사용자 정보(SecurityContext)를 활용해자원 소유자 검증역할 기반 접근 제어API 사용 제한등의 부가 검증 수행Spring MVC 요청 흐름[사용자 요청] ↓[JwtFilter] ↓[SecurityContextHolder에 인증 저장] ↓[Interceptor] ↓[인증 사용자 검증] ↓[Controller]Interceptor가 왜 필요할까?예를 들어 컨트롤러 마다 다음과 같은 코드가 반복된다면if (!isLogin(request)) { throw new UnauthorizedException(..

Dev./Spring 2025.12.02

[Design pattern] 정적 팩토리 메서드 패턴

정적 팩토리 메서드란객체 생성을 생성자 new가 아니라 클래스의 static 메서드를 통해 수행하는 방식이다. 단순히 new를 안쓰는 문법이 아니라 객체 생성의 의미와 책임을 코드로 드러내기 위한 패턴이다.일반 생성자 방식의 한계new User(email, password);new User(email, encodedPassword);생성 의도가 보이지 않는다같은 타입의 파라미터가 섞이면 의미가 불변명 해져 호출하는 곳에서는 차이를 알 수 없다정적 팩토리 메서드의 기본적인 형태public class User { private User(String email, String password) { this.email = email; this.password = password; ..

[Git] merge 진행 과정

merge를 이해하기Git에서 협업 할 때 내가 가장 중요하다고 생각하는 것은내 작업 브랜치는 어떤 dev를 기준으로 만들어졌는가?이다. dev는 공용 개발 브랜치이며 모든 feature 브랜치는 dev의 특정 시점에서 분기된다. 문제는 dev는 계속 변한다는 것인데 본질을 이해하고 넘어가면 실수할 일이 줄어든다.그래서 merge의 본질은 내 브랜치를 최신 dev 기준으로 다시 맞추는 과정이라고 생각한다.merge의 기준점은 항상 devdev를 항상 최신으로 만든 뒤작업 브랜치에 dev를 mergefetch와 pull의 역할git fetch형상 확인용, 정보 동기화용git fetch origin원격 저장소의 최신 상태를 복사만 해옴origin/dev가 업데이트됨내 로컬 브랜치에는 아무 변화 없음 git ..

Dev./Git 2025.11.30
728x90
반응형