WEB
단위 테스트 - Controller (feat. 추가적인 단위 테스트의 방향성)
[사용 스택]- Spring Boot 3.x- Java 17- Spring data JPA- H2- Junit 5- mockito 이번 글에서는 Controller의 단위테스트를 작성한 방법을 소개하겠습니다.들어가기에 앞서서,저는 Rest Controller를 사용하여 REST API를 만들었습니다. Controller컨트롤러의 역할은 HTTP 요청에 대한 비즈니스 로직 호출과 적절한 응답을 해주는 것입니다.저는 RestControllerAdvice를 사용해서 전역에서 발생된 예외에 맞게 응답 데이터를 생성해 주도록 했습니다.따라서, 제가 작성한 컨트롤러에서는 성공적인 응답만을 반환해줍니다.또한, 통일된 응답 데이터를 만들기 위해서 ResponseDTO 를 만들어 두었습니다.@AllArgsConstru..
단위 테스트 - Service (feat. 테스트 더블)
[사용 스택]- Spring Boot 3.x- Java 17- Spring data JPA- H2- Junit 5- mockito 레포지토리 테스트에 이어서 서비스에서 단위 테스트를 작성한 방법을 소개하겠습니다. Service서비스의 역할은 레포지토리를 사용하여 데이터를 요청하고 가져온 데이터로 비즈니스 로직을 수행하는 것입니다.서비스를 테스트하기 위해서는 레포지토리를 주입받아야 하는데,이 레포지토리가 실제 의존성을 주입받아 사용된다면,서비스를 테스트하는 단위 테스트라고 말하기 어렵습니다.(오히려 서비스와 레포지토리 모두를 한 번에 테스트하는 통합 테스트라고 생각합니다.)그렇기 때문에 레포지토리의 의존성을 줄여줄 필요가 있습니다.이를 위해 테스트 더블(Test Double)을 사용할 것입니다!! 테스트 ..
단위 테스트 - Repository (feat. 테스트 픽스쳐)
[사용 스택]- Spring Boot 3.x- Java 17- Spring data JPA- H2- Junit 5- mockito 기존에 진행했던 프로젝트를 혼자서 리팩터링 하기로 했습니다.리팩터링을 진행하면서 기존의 비즈니스 로직을 헤치는 일이 생기지 않도록테스트 코드를 작성할 필요가 있었습니다.또한, SpringBootTest를 사용하는 것은 전체를 부팅하면서 시간이 오래 걸린다는 단점이 있어서 단위 테스트에는 적합하지 않다고 생각하고 다른 것들로 대체해서 사용했습니다.테스트 코드를 작성하는 순서는 다른 클래스들과의 의존성이 가장 낮은 레포지토리부터서비스, 컨트롤러 순으로 했습니다. Repository레포지토리 테스트는 @DataJpaTest 를 사용했습니다.이를 사용하면 Jpa 테스트에 필요한 빈..
Service의 메서드들이 중복해서 사용하는 로직을 테스트하기
[사용 스택]- Spring Boot 3.x- Java 17- Junit 5- mockito 개발이 끝난 기존의 프로젝트에 테스트를 추가하고 있는 도중에 이 문제를 찾게 되었습니다.특정 서비스의 메서드들이 하나의 중복된 로직을 수행하고 있었고그 로직을 같은 클래스 내부에 메서드로 추출해서 사용하고 있습니다.모든 메서드에서 그 로직을 테스트하는 것은 효율적이지 않으며 불필요하다는 판단을 했습니다. 해결방안1. 해당 메서드를 외부 클래스로 추출하기일단 역할에 맞게 해당 메서드를 새로운 클래스로 추출하는 방법이 가장 와닿았습니다.이렇게 하면 각 역할에 맞는 클래스로 올바르게 사용될 수 있다고 생각했습니다.또한, Mocking을 통해 테스트를 독립적으로 수행할 수 있습니다. 하지만, 이렇게 하려면 기존의 코드..
RestControllerAdvice로 전역에서 발생된 예외 처리하기.
기존에 진행하는 프로젝트에서는 Spring Boot로 REST API를 구현하면서 Service들에서 발생하는 여러 예외를 Controller의 메서드들에서 try/catch 문을 만들어 처리해 줬습니다이렇게 만들어두니 Controller는 복잡해지고 중복되는 코드들이 생겼으며,예외가 발생될 때마다 해당 예외에 대한 자세한 메시지를 작성해주어야 해서 관리가 어려웠습니다.이렇게 예외에 따른 처리를 Spring Boot에서 @RestControllerAdvice를 활용해 처리해 주는 방법을 정리해보고자 합니다! 기존 코드@RestController@RequestMapping("/api/v1/posts")@RequiredArgsConstructorpublic class PostController { pr..
Spring Security 프레임워크로 로그인에 성공하면 JWT 발급하기
지난 글에서 OAuth2를 통해 로그인을 구현했습니다. 이번 글에서는 로그인에 성공했을 때 사용자에게 Refresh 토큰을 발급해 주고, Refresh 토큰으로 Access 토큰을 발급받아 사용하도록 구현해보겠습니다. JWT 발급 전략 구현하기에 앞서 제가 선택한 JWT 발급 전략에 대해서 설명해보겠습니다. OAuth2 로그인을 시도할 때 CORS 설정이 허용된 애플리케이션 서버에서 요청을 하기 위해서 사용자가 하이퍼링크로 서버의 url에 접근했었습니다. 이로 인해서 주체는 백엔드가 되었고, 클라이언트 페이지로 돌아오기 위해서 리디렉션을 해야 합니다. 따라서 요청과 응답 객체에 토큰을 포함할 경우 사용이 불가능하다는 문제가 생깁니다. 저는 이를 해결하기 위해서 Access 토큰 재발급을 위한 Refres..
Spring Security 프레임워크로 OAuth2 로그인
기본적인 이론을 모두 정리했으니 직접 구현해봅시다. Spring Security에서 제공하는 로그인 기능이 아닌 OAuth2를 사용하는 로그인 기능을 구현해보겠습니다. ( form 로그인 방법도 노션에 정리는 해뒀지만,,, OAuth2 보다 작성할 내용이 많아 추후에 하겠습니다. ) 구현할 로그인 과정의 대략적인 순서는 다음과 같습니다. - 클라이언트에서 Spring Boot 서버로 로그인을 요청합니다. - 클라이언트에게 OAuth2 로그인 redirect url을 전달하여 로그인을 시도합니다. - 로그인에 성공하면 OAuth2 리소스 서버에서 사용자의 정보를 가져와 Refresh JWT 를 발급합니다. - 발급된 Refresh JWT를 Redis 에 저장하여 관리하고, 클라이언트에게 쿠키(Http on..
OAuth2가 뭐죠?
OAuth2 (Open Authorization 2.0) 는 인증을 위한 개방형 표준 프로토콜입니다. 이 기능을 통해서 Naver, Kakao, Google 등에 로그인하는 방법으로 간편한 소셜 로그인을 구현할 수 있으며, 서버 혹은 클라이언트에서는 로그인된 해당 애플리케이션에서 사용자의 정보를 받아와 사용할 수 있습니다. OAuth2 를 구성하는 역할을 소개하고 OAuth2를 사용해 로그인하는 과정을 순서대로 정리해보겠습니다. 구성 OAuth2 를 구성하기 위해서는 리소스 소유자(사용자), 클라이언트(애플리케이션 서버), 권한 서버, 리소스 서버가 필요합니다. 리소스 소유자는 로그인을 하는 주체입니다. 즉, Naver, Google 등에 로그인을 시도 할 사용자입니다. 클라이언트는 소셜 로그인을 통해 ..