개발 일지/Spring 44

[Spring WebFlux] Reactive Programming

리액티브 프로그래밍(Reactive Programming)은 비동기적인 데이터 스트림을 다루는 프로그래밍 패러다임 중 하나로, 이벤트 기반(event-driven) 또는 데이터 흐름(data-flow) 프로그래밍 모델에서 사용된다. 데이터의 처리 및 변환을 이벤트 기반으로 수행하며, 데이터의 상태 변화에 따라 비동기적으로 반응(react)한다. 리액티브 프로그래밍에서는 데이터가 지속적으로 발생하는 것 자체를 데이터에 어떤 변경이 발생함을 의미하며, 이 변경 자체를 이벤트로 간주하고 이벤트가 발생할 때마다 데이터를 계속해서 전달한다. 리액티브 프로그래밍은 높은 성능과 확장성을 갖는 시스템을 구현하기 위해 사용되며, 모바일 애플리케이션, IoT 기기, 클라우드 네이티브 애플리케이션 등 다양한 분야에서 사용되..

[Spring WebFlux] Reactive System

리액티브 시스템(Reactive System)이란, 비동기적인 시스템에서 발생하는 문제를 해결하고 확장성과 반응성을 높이기 위해 만들어진 시스템이다. 리액티브 시스템의 가장 큰 특징은 '반응성'이다. 즉, 시스템이 빠르게 요청에 응답하고 실패를 적극적으로 처리하여 사용자에게 최상의 경험을 제공하는 것이다. 이를 위해, 시스템에서 발생하는 모든 이벤트를 비동기적으로 처리하고, 이벤트에 따라 적절한 반응을 취한다. 리액티브 시스템에서는 비동기적으로 발생하는 이벤트를 처리하기 위해 다양한 기술과 패턴을 사용하는 데, 대표적으로는 스트림 처리 방식이 있다. 이는 데이터를 처리할 때 일부분씩 처리하는 것이 아니라 모든 데이터를 순차적으로 처리하면서 새로운 데이터가 추가되는 경우에도 지속적으로 처리할 수 있는 방식..

[Spring Security] 토큰 기반 인증 절차

토큰 기반 인증 절차는 크게 다음과 같은 단계로 이루어진다. 클라이언트가 ID / Password를 서버로 전송하여 로그인 요청을 한다. 서버는 ID와 Password를 검증하고, 유효한 사용자인 경우 Access Token과 Refresh Token을 발급한다. Refresh Token을 이용해 새로운 Access Token을 생성할 것이므로 두 종류의 토큰이 같은 정보를 담을 필요는 없다. 토큰을 클라이언트에게 전송하면 클라이언트는 토큰을 저장한다. 저장하는 위치는 Local Storage, Session Storage, Cookie 등이 될 수 있다. 클라이언트는 인증이 필요한 API 요청 시, HTTP Header(Authorization Header) 또는 쿠키에 이전에 발급받은 Access T..

[Spring Security] JWT

JWT(JSON Web Token)는 데이터를 안전하고 간결하게 전송하기 위해 고안된 JSON 기반의 웹 표준 인증 방식이다. 인증과 권한 부여를 위해 사용되며, URL과 HTTP 통신을 사용하는 웹 애플리케이션에서 사용된다. JWT 구조 // Header.Payload.Signature xxxx.yyyyyy.zzzz JWT는 Header, Payload, Signature로 이루어져 있다. Header에는 토큰의 타입 및 해싱 알고리즘 정보, Payload에는 서버와 클라이언트 간에 교환할 정보(사용자의 정보), Signature는 Secret Key를 이용하여 Header와 Payload의 내용이 변경되지 않았는지 확인할 수 있는 값이 담겨 있다. 각 부분은 Base64로 인코딩 되어 하나의 문자열로..

[Spring Security] 권한 부여 처리 흐름

권한 부여 처리는 Spring Security에서 가장 중요한 기능 중 하나이다. 인증에 성공했다고 해서 애플리케이션 리소스를 마음대로 이용할 수는 없기 때문이다. 따라서, 인증에 성공한다면 다음과 같이 사용자가 시스템에서 수행할 수 있는 작업을 결정하는 권한 부여(Authorization) 과정이 수행된다. Spring Security Filter Chain에서 URL을 통해 사용자의 액세스를 제한하는 권한 부여 Filter는 AuthoriztionFilter이다. AuthorizationFilter는 먼저 SecurityContextHolder로부터 Authentication을 획득한다. (Authentication 객체로부터 Principal을 추출하여 사용자의 정보를 얻을 수 있다.) Author..

[Spring MVC] Spring Security

Spring Security는 Spring MVC 기반 애플리케이션의 인증(Authentication)과 인가(Authorization) 기능을 지원하는 보안 프레임워크이다. Spring Security는 다양한 보안 기능을 제공하며, 사용자 인증, 접근 제어, 보안 이벤트 관리 등을 처리할 수 있다. 보안이라는 주제 자체가 소프트웨어 세계에서 어려운 주제 중 하나이기 때문에 직접 보안 강화를 위한 솔루션을 개발해서 구축하는 것은 쉽지 않을 것이다. 따라서, 잘 검증되어 신뢰할만한 Spring Security를 사용하는 것이 어쩌면 현명한 선택이라고 생각된다. Spring Security는 다양한 애플리케이션에서, 스프링 프레임워크의 다양한 모듈과 통합하여 사용할 수 있고 개발자가 보안 관련 기능을 쉽게..

[Spring Security] 인증 처리 흐름

가장 일반적으로 사용되는 인증 방식인 ID/Password의 인증 처리 흐름은 다음과 같으며, 이러한 과정을 통해 Spring Security는 사용자 인증 및 권한 처리를 수행한다. Spring Security는 매우 유연한 보안 프레임워크이기 때문에 '아래의 인증 처리 흐름이 모든 상황에 적용되는 것이 아니며' 필요에 따라서 여러 방식을 조합해서 사용할 수 있다. 사용자가 로그인 페이지에 접근하여 ID와 Password를 포함한 request를 Spring Security가 적용된 애플리케이션에 전송한다. 사용자의 로그인 요청이 Spring Security의 Filter Chain까지 들어오면 UsernamePasswordAuthenticationFilter가 해당 요청을 전달받는다. Username..

[Spring] @AllArgsConstructor /@RequiredArgsConstructor

@AllArgsConstructor와 @RequiredArgsConstructor는 롬복 라이브러리에서 제공되는 애너테이션으로 필드에 대한 생자를 자동으로 생성해주는 역할을 한다. @RequiredArgsConstructor는 필요에 의한 생성자를 만들어주는데 그럼 @AllArgsConstructor를 쓸 필요가 있나?? 라는 생각이 들어 찾아보니 두 애너테이션에 차이점이 있었다. @AllArgsConstructor는 '모든' 필드에 대한 생성자를 자동으로 생성해준다. 즉, 클래스의 모든 필드를 매개변수로 받는 생성자가 자동으로 생성된다. @RequiredArgsConstructor는 초기화 되어 있지 않은 'final' 필드나 @NonNull 애너테이션이 붙은 필드에 대한 생성자를 자동으로 생성해준다...

[Spring Data JPA] No default constructor for entity

Spring Data JPA에서 Entity 클래스에 @NoArgsConstructor를 작성하지 않는 경우 No default constructor for entity라는 에러가 발생한다. 정확하게는 findById() 같은 API를 사용해서 데이터를 조회할 때 에러가 발생하는 것이라고 한다. Entity 클래스에서 @NoArgsConstructor 애너테이션을 추가하는 이유를 찾아봤다. Spring Data JPA에서는 Entity 클래스를 사용해서 데이터베이스랑 매핑한다. 이때, 데이터베이스에서 조회한 데이터를 Entity 객체에 매핑할 때 Reflection을 통해 객체를 생성하고 getter / setter 메서드를 통해 데이터를 할당한다. Reflection이란 실행 중인 자바 프로그램 내부의..

[Spring Data JPA] Auditing 기능

관계형 데이터베이스 테이블을 매핑할 때 공통적으로 도메인들이 가지고 있는 필드가 있다. Spring Data JPA에서는 생성일자나 수정일자와 같이 시간에 관련한 데이터를 자동으로 넣어주는 auditing 기능을 제공한다. public class Member { @Column(nullable = false) private LocalDateTime createdAt = LocalDateTime.now(); @Column(nullable = false, name = "LAST_MODIFIED_AT") private LocalDateTime modifiedAt = LocalDateTime.now(); } 위의 코드는 직접 LocalDateTime.now()를 통해서 초기화를 시켜주지만 JPA에서 제공하는 기능..