본문 바로가기
Today I Learned 2024. 6. 12.

(24.06.12)[9주차] Spring 심화 강의 01

Spring 심화 학습이 시작되면서 OAuth 간편로그인 ,  단위테스트&통합 테스트, Spring  AOP, API 예외처리를 진행하게 된다.

 

강의 내용이 양은 적지만 새로운 개념을 적용을 해야하고 어떠한 구조 및 프레임워크에 관한 내용에 대해 핵심과 이론을 짚어가면서 진행을 하고 있기 때문에 조금 시간이 걸리더라도

 

학습을 한 내용을 나만의 언어로 다시 외우고 정리

 


Spring 심화 강의 간단정리

더보기

OAuth

  • 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로서 사용되는, 접근 위임을 위한 개방형 표준
  • HTTP 기반의 보안 프로토콜
    • 애플리케이션에게 모든 권한을 넘기지 않고 사용자 대신 서비스를 이용
    • ex) 구글 페이스북 네이버 카카오

 

카카오 사용자 정보로 회원가입 구현 EXAMPLE

Kakao USER 정보 가져오기 FLOW

  1. 카카오에서 보내주는 '인가코드' 처리
    1. "인가 코드"로 "액세스 토큰" 요청
    2. 토큰으로 카카오 API 호출 : "액세스 토큰"으로 "카카오 사용자 정보" 가져오기
  2. 인가코드 -> Access Token 요청
    1. 요청 URL 만들기
    2. HTTP 응답 (JSON) -> 액세스 토큰 파싱
  3. 사용자 정보 요청
    1. HTTP Header에 JWT 토큰을 넣어서 생성
    2. HTTP 요청 보내기
    3. 가져온 유저 정보를 Json을 통해서 필요한 부분만 가지고 오기
  4. 로그인 또는 회원가입 진행

카카오 User 를 위한 테이블 (ex. KakaoUser)을 하나 더 생성하는 경우

  • 결합도가 낮아지는 것 : 기존 다른 유저의 변화에 따른 영향이 없어짐
  • 구현 난이도가 높아지는 것 : 기능에 있어서 다른 테이블을 참고해야하는 것을 다시 만들어야함

기존 회원 (User) 테이블에 카카오 User 추가

  • 단순한 구현
  • 기존 회원처럼 로그인이 가능해져 여러가지 구현 기능에 차질이 생길 수 있음

→ kakaoId라는 칼럼을 User에 추가해서 사용

  • 따라서 해당 카카오 회원일 경우 UUID를 사용한 랜덤 비밀번호 지정이 필수가 되어버림 : 기존 회원처럼 로그인을 할 수 없도록 만드는것

단위 테스트 Unit Test

  • 작은 단위로 쪼개서 각 단위가 정확하게 동작하는지를 검사하는 테스트 기법
    • 빠르게 작성, 빠르게 파악을 목적

JUnit5

  • Java에 default로 설정이 되어있는 단위 테스트를 위한 프레임워크
    • annotation으로 작동
  • 테스트 코드 파일에 import org.junit.jupiter.api.*; 꼭 넣을 수 있도록

Before-After

@BeforeEach
@AfterEach
@BeforeAll
@AfterAll

  • 테스트를 각각 / 전부 수행 전/후에 실행되어야하는 메서드를 지정

테스트 꾸미기

@DisplayName

  • 테스트에 관련하여 네이밍, 메서드 이름이나 주석에 신경을 안쓰고 테스트이름을 표시

@Nested

  • 주제별로 테스트트 클래스 단위로 그룹해서 파악

@Order

  • @TestMethodOrder(MethodOrderer.OrderAnnotation.class) 를 @Nested 된 클래슨 또는 클래스에 지정
    • 클래스 안에 있응 @Order(숫자) 로 테스트 메서드를 순서대로 수행할 수 있도록 함

 

테스트 반복하기

@RepeatedTest(value = 횟수, name = “테스트이름”)

  • 메서드를 반복해서 반복 횟수와 네이밍 순서대로 할 수 있음 for 문 처럼 사용

@ParameterizedTest & @ValueSource(소스값들)

  • 테스트에 전할하고 싶은 Parameter을 전달한 데이터를 모두 수행해서 반복하면서 실행

 

검증하기 Assertions

  • import static org.junit.jupiter.api.Assertions.*; 넣어줘서 사용할 수 있도록

.assertEquals(expected, actual)

  • 기댓값과 실제 값을 비교, asserNotEquals 일 경우, 일치하지 않을 경우 성공이라고 판단
  • 특정 오류메시지를 나올 수 있도록 할 수 있음

.assertTrue(boolean)

  • true false 인지 아닌지 검증

.assertNotNull(actual)

  • null 인지 아닌지 검증

.assertThrows(expectedType, executable)

  • exception 던지는 지 검증
    • exception이 제대로 동작을 하는지 확인

 

Given-When-Then 패턴

  • Test Code 스타일을 표현하는 방식 중 하나의 패턴
  • 협업 간 이해하기 쉽도록 하기 위한 패턴
  • When-Then 이 한번에 사용할 수 있음

Given

  • 실행 전 테스트에 필요한 값 선언

When

  • 테스트 대상 실행

Then

  • 테스트 대상이 실행되는 그 행동에 대한 발생 결과가 예상되는 결과인지 아닌지 확인
    • Assertion 활용

 

Mockito

  • 각 테스트 케이스는 무조건 적으로 실제 기능과 분리되어야하므로 가짜 객체 Mock object를 생성해서 사용을 할 수 있어야
    • Service 단에서의 update 메서드가 잘 작동되려면 해당 Service에서 필요한 Repository들이 주입되어야하는 형태로 구성이 되어있지만, update 메서드 자체를 테스트를 할때 해당 Repository를 연결해서는 안되는 상황이 생김
  • 같은 엣지포인트가 갈리는 메써드가 있다면 하나하나 모두 써줘야함

@ExtendWith(MockitoExtension.class)

  • Mock을 사용하기 위해 클래스에 지정하는 annotation

@Mock

  • 가짜로 주입받을 객체에 지정해서 실제 기능에 영향을 끼치지 않는 mock을 만들어서 사용할 수 있음

 


통합 테스트 Integration Test

  • 모듈 / 클래스 단위에서의 테스트를 넘어서 모듈 / 클래스간의 상호작용 검증을 위한 테스트
    • 두 개 이상의 모듈이 연결된 상테를 테스트
    • 연결 간 발생하는 에러 검증

 

Spring Boot의 통합 테스트

@SpringBootTest

  • Spring이 동작되도록 해주는 애너테이션
    • 단위 테스트에서는 Spring이 작동을 하지 않지만, 통합테스트에서는 작동을 할 수 있게됨
    • IoC/DI 기능 사용 가능
      • Repository 까지 한번에 연결되어있기 때문에 Spring 이 동작되어서 통합 테스트 가능
    ex) 신규 상품 등록 → 신규 등록된 관심상품의 희망 최저가 변경 → 회원ID로 해당 회원이 등록된 모든 관심상품조회 이렇게 일련의 과정을 한번에 통합테스트 시킬 수 있음

@TestInstance(TestInstance.Lifecycle.*PER_CLASS*)

  • 단위 테스트일 경우 void test() 테스트 메서드 끼리 서로 영향을 주지 않고 각각 작동이 됨 → 필드를 공유해서 사용할 수 없음(각각 다르게 사용)
  • 이때 필드를 공유하면서 사용할 수 있도록 하는 Annotation

Controller 테스트

  • Security를 사용한다면 까다로울 수 있음
    • ex) JPA가 방해를 하기 때문에 Application에서 JpaConfig로 따로 빼야함

Mock 역할의 Filter를사용

  • 직접 Filter가 구현되어 Mock처럼 가짜 필터를 만드는것

MVC 테스트

@WebMvcTest

  • 테스트할 Controller를 지정
  • 제외할 필터를 설정

 


단위 테스트, 통합 테스트, Controller 테스트 처러 테스트 코드를 작성하는데 있어서 필요한 내용을 학습을 했지만,

테스트 코드의 의의는 빠른 시간내에 빠르게 작성하고 확인을 하는 것을 목표로 하기 때문에 오히려 기능을 구현한 로직 코드보다 작성과 실행하는데 시간이 더 오래 걸리면 안되는 부분이다.

 

실제 사용을 할 수 있는 부분을 임의로 정하는 것을 기본으로 하는 개념이기 때문에 좀더 익숙해질 수 있도록 개인 과제를 완성하면서 실제로 느끼면서 잘 모르는 것은 더블 체크, 자세한 학습을 할 수 있도록 해야할 것이다.