Back-End/Spring (SpartaCC)

[Spring] 스파르타코딩클럽 Spring공부(6) - OAuth, 단위테스트, 통합테스트, 예외처리관리

남건욱 2023. 7. 10. 23:58
반응형
카카오 로그인
탄생배경
- 모든 웹 사이트에서 회원가입을 거치는 것은 사용자에게 부담이 된다.
매번 번거로운 회원가입 과정을 수행해야 할 뿐 아니라, 웹사이트마다 다른 아이디와 비밀번호를
기억해야 한다. 또한 웹사이트를 운영하는 측에서도 역할이 부담이 된다. 이런 문제를 해결하기
위해 OAuth를 사용한 소셜 로그인이 등장하게 됐다.

 

 

 

 

OAuth

OAuth는 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로써 사용되는, 접근 위임을 위한 개방형 표준입니다. 사용자가 애플리케이션에게 모든 권한을 넘기지 않고 사용자 대신 서비스를 이용할 수 있게 해주는 HTTP 기반의 보안 프로토콜이다.

 

 

 

 

카카오 로그인 사용 승인받기
https://developers.kakao.com/console/app

위 링크에 들어가서 회원가입 후 본인의 애플리케이션을 등록하면 된다.

사이트 도메인 : http://localhost:8080

Redirect Url : http://localhost:8080/api/user/kakao/callback

카카오에서 보내주는 인가코드를 받는 것 -> Controller

인가코드를 가지고 카카오 로그인 처리 -> Service

로그인 성공 시 redirect -> Controller

 

 

 

 

단위 테스트
서비스 배포후 버그가 생겼을때 버그 발견 시간이 늦어짐에 따라 비용이 기하급수 적으로 커진다.

따라서 테스트 코드를 작성하여 프로그램의 버그를 사전에 발견하면 기하급수적인 비용의 증가가능성을 사전에 방지할 수 있다. 

- 단위테스트는 작은 단위로 쪼개서 각 단위가 정확하게 동작하는지를 검사하는 테스트기법이다.

- 단위테스트는 빠르게 작성할 수 있고 문제 발생 시 어느 부분이 잘못되었는지를 빠르고 정확하게 확인할 수 있다는 장점이 있다.

 

 

 

 

JUnit5
자바 프로그래밍 언어 용 단위 테스트 프레임워크

@BeforeEach : 각각의 테스트코드가 실행되기 전에 수행되는 메서드를 만들어 준다.

@AfterEach : 각각의 테스트 코드가 실행된 후에 수행되는 메서드를 만들어 준다.

@BeforeAll : 모든 테스트 코드가 수행되기 전에 최초로 수행되는 메서드를 만들어준다. (static 메서드로 생성해야 함)

@AfterAll : 모든 테스트 코드가 수행된 후 마지막으로 수행되는 메서드를 만들어 준다. (static 메서드로 생성해야 함)

 

 

 

 

테스트 꾸미기

@DisplayName : 테스트의 내용을 한눈에 알아볼 수 있게 네이밍 해줄 수 있다.

@Nested : 주제 별로 테스트를 그룹 지어 파악하기 좋다.

@Order : 테스트를 메서드 단위로 순서를 매길 때는 @TestMethodOrder(MethodOrderer.OrderAnnotation.class) 애너테이션 설정을 해야 한다. 그다음 원하는 순서에 맞게 메서드에 @Order 애너테이션을 추가하고 () 괄호 안에 순서를 입력한다.

 

 

 

 

테스트 반복하기

 

@RepeatedTest(value = 5, name = "반복 테스트 {currentRepetition} / {totalRepetitions}")
void repeatTest(RepetitionInfo info) {
    System.out.println("테스트 반복 : " + info.getCurrentRepetition() + " / " + info.getTotalRepetitions());
}

@RepeatedTest : 해당 테스트 메서드를 반복할 수 있다. name속성을 사용하여 네이밍을 할 수 있고, RepetitionInfo 값을 피라미터로 넣어서 현재 반복 횟수와 총 횟수값을 확인할 수 있다.

 

 

 

@DisplayName("파라미터 값 활용하여 테스트 하기")
@ParameterizedTest
@ValueSource(ints = {1, 2, 3, 4, 5, 6, 7, 8, 9})
void parameterTest(int num) {
    System.out.println("5 * num = " + 5 * num);
}

@ParameterizedTest : 피라미터를 받아 테스트할 수 있는 메서드를 만들 수 있다. @ValueSource(ints = {1,2,3,4,5,6,7,8,9})를 사용하여 피라미터 값을 전달할 수 있다. 전달되는 피라미터 수만큼 테스트 메서드가 수행된다. int, String 등 여러 타입의 피라미터를 전달할 수 있다.

 

 

assertEquals()

- 첫 번째 피라미터에 예상값을 넣고 두 번째 피라미터에 테스트 결괏값(실제값)을 넣어준다. 예상값과 실제값이 다르면 테스트가 실패한다. 세 번째 피라미터 값에 람다식으로 메시지를 넣어두면 테스트 실패 시 해당 메시지가 출력된다.

 

 

assertions.assertTrue(boolean)

- 해당 피라미터값이 true인지 확인한다.

 

 

assertions.assertNotNull(actual)

- 해당 피라미터 값이 null이 아님을 확인한다.

 

 

assertions.assertThrows(expectedType, executable)

- 첫 번째 피라미터에 예상하는 Exception 클래스 타입을 넣고 두 번째 피라미터에 실행코드를 넣으면 된다.

 

 

 

 

Given - When - Then 패턴
Given-When-Then 패턴은 Test Code 스타일을 표현하는 방식을 뜻한다.

Given : 테스트하고자 하는 대상을 실제로 실행하기 전에 테스트에 필요한 값(상태)을 미리 선언해 둔다.

When : 테스트하고자 하는 대상을 실제로 실행시킨다.

Then : 어떤 특정한 행동(테스트 대상 실행) 때문에 발생할 거라고 예상되는 결과에 대해 예측하고 맞는지 확인한다.

 

 

 

 

 

Mock object (가짜 객체)
이상적으로, 각 테스트 케이스는 서로 분리됭야 한다. 이를 위해 가짜 객체(Mock object)를
생성하는 것도 좋은 방법이다.

Controller만 테스트? 범위 : Controller, Service, Repository

Service만 테스트? 범위 : Service, Repository

Repository만 테스트? 범위 : Repository

 

가짜 객체 (Mock object)를 통한 분리 방법

- 가짜 객체 (Mock object)로 분리한다.

- MockRepository : 실제 객체와 겉만 같은 객체. 실제 DB작업은 하지 않는다.

 

단위 테스트 (Unit Test)

- 하나의 모듈이나 클래스에 대해 세밀한 부분까지 테스트가 가능하다.

- 모듈 간에 상호작용은 검증할 수 없다.

 

통합 테스트 (Integration Test)

- 두 개 이상의 모듈이 연결된 상태를 테스트할 수 있다.

- 모듈 간의 연결에서 발생하는 에러 검증이 가능하다.

 

Spring Boot를 이용한 통합 테스트

- 통합 테스트 : 여러 단위테스트를 하나의 통합된 테스트로 수행. 단위 테스트 시 Spring은 동작되지 않는다.

- @SpringBootTest : 스프링이 동작하게 해주는 애너테이션. 테스트 수행 시 스프링이 동작한다.

 

 

 

 

 

Spring AOP

1. Aspect

- Spring 빈 (Bean) 클래스에만 적용 가능하다.

 

 

 

 

2. 어드바이스 종류

- @Around: 핵심기능 수행 전과 후 (@Before + @After)

- @Before: 핵심기능 호출 전 (ex. Client의 입력값 Validation 수행)

- @After: 핵심기능 수행 성공/실패 여부와 상관없이 언제나 동작 (try, catch의 finally()처럼 동작)

- @AfterReturning: 핵심기능 호출 성공 시 (함수의 Return 값 사용 가능)

- @AfterThrowing: 핵심기능 호출 실패 시. 즉, 예외 (Exception)가 발생한 경우만 동작 (ex. 예외가 발생했을 때 개발자에게 email이나 SMS 보냄)

 

 

 

 

3. 포인트 컷

형태
execution(modifiers-pattern? return-type-pattern declaring-type-pattern? 
          method-name-pattern(param-pattern) throws-pattern?)


예제
@Around("execution(public * com.sparta.myselectshop.controller..*(..))")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable { ... }

- modifiers-pattern : public, private, *

- return-type-pattern : void, String, List <String>, *

- declaring-type-pattern : 클래스명

- method-name-pattern(param-pattern) : 함수명, 피라미터 패턴

 

@Pointcut

- 포인트컷 재사용 가능

- 포인트컷 결합 (combiine) 기능

 

 

 

 

API 예외처리
우리는 웹 애플리케이션의 "예외"에 대하여 다시 한번 인지할 필요가 있다.
웹 애플리케이션에서의 에러를 Client와 Server 모두가 잘 알지 못하면, 서비스하는 환경에서
발생하는 에러에 대해서 제대로 대응 할 수가 없다.

- Response 메시지 : start-line (상태줄). API요청결과 (상태코드, 상태 텍스트)

200 번대 -> 성공을 의미한다

400 번대 -> 클라이언트 에러, 즉 잘못된 요청을 의미

500 번대 -> 서버 에러, 즉 정확한 요청에 서버 쪽 사유로 에러가 난 상황을 의미

 

 

 

 

Spring의 Global 예외처리
사실 예외처리 로직 자체는 공통적이다. 필요한 곳에서 Error를 만들어 던지고, 그 Error를 받는곳이
어디든 (어떤 Controller) 우리는 그 Error내용을 담아서 클라이언트에 보내주면 된다.
Global하게 처리 할 수 있는 방법이 있다.

@ControllerAdvice 사용

- Spring에서 예외처리를 위한 클래스 레벨 애너테이션이다.

- 이 애너테이션은 모든 Controller에서 발생한 예외를 처리하기 위해 사용된다.

- @ControllerAdvice가 붙은 클래스에서는 @ExceptionHandler메서드를 정의하여 예외처리하는 로직을 담을 수 있다.

 

@RestControllerAdvice

- @ControllerAdvice + @ResponseBody

 

 

 

정리

이번 수업은 예외처리를 관리하고 처리하는 부분을 배웠다. 또 새로운 애너테이션이 많이 등장해서 머리가 어질어질했다. 깊게 들어가서 이해하기보단 흐름을 먼저 파악한 후, 나중에 깊게 공부할 일이 생기면 공부하는 게 좋을 것 같다. 이번 수업으로 테스트의 종류 중 단위테스트, 통합테스트 총 2개의 테스트에 대해 알 수 있었고, 필요한 이유와 방법에 대해 알게 되었다. 계속 반복하여 학습하며 머리에 최대한 담도록 노력해야겠다. 

 

반응형
프로필사진

남건욱's 공부기록