테스트 자가격리 시키는 법

지인호·2022년 7월 27일
12

MSA시리즈

목록 보기
1/1
post-thumbnail
post-custom-banner

EP00. TL;DR

  • 외부 요소의 변화가 내부요소에게 영향을 미치지 않도록 격리해야한다.
  • 이는 테스트 환경 또한 마찬가지이다.
  • 테스트 환경에서 네트워크 장애라는 외부요소를 격리시키는 방법으로서는 LocalServer, Mocking, Embeded 등이 있다.

EP01. 끔찍한 일

어느날, 개발중인 교내 프로젝트의 회원가입API 테스트중, 끔찍한 일이 발생했습니다...

교사 회원가입 API호출에 10.42초의 지연이 발생한 것 인데요.
고작 10개 미만의 정책을 검사하고, 회원가입 로직을 구성하여, DB에 추가시키는 로직이 10초나 걸린다니요.
심지어 서버는 Webflux를 사용해 개발한데다, BlockHound로 검사했을떄도 blocking되는 비즈니스로직을 찾을 수 없었다고요!
반쯤 멘탈이 나간 상태로, 2시간동안 원인을 분석하고 나서야, 너무나도 단순한 문제였음을 알게 되었습니다.

EP02. 최초의 버그도 나방이었다.

원인은 바로 와이파이 지연이었는데요.

테스트환경에서 AWS의 RDS를 통해 구축한 DB서버를 사용하자, DB서버와의 통신과정에서 지연이 발생한 것 이었습니다...
Blocking으로 인한 문제도, Loop로 인한 문제도 아니고, 고작 와이파이 지연이라니요!
원인을 찾고나서는 수십초간 멍하니 모니터만 바라보며 KT를 저주하고 있었습니다.

EP03. 지금 사직서내러 갑니다.

그런데 이 문제가 회사에서 일어났다면 어땠을까요?

여러분, 상상해보세요!
여유롭게 음악을 들으며 문서화작업을 하던 도중, Slack으로 맨션이 오는거에요.

00씨! 이번에 개발하신 회원가입API말인데요. QA팀에서 10초의 지연이 발생헀다고해요. 혹시 지금 시간 되시나요? 😀

아마 마지막에 붙인 😀조차 😈으로 보이지 않을까요?

하지만 네트워크 빵빵한 여러분의 노트북으로는 아무리 재시도해봐도 10ms이상의 지연이 발생하지 않았습니다.
머리를 100가닥정도 쥐어뜯었을 때쯤, PM에게서 다시 맨션이 왔네요.

아까 말한 회원가입API 지연문제 말인데요. QA팀에 네트워크 지연으로 발생한거라 하네요!🤣

한 3초정도 헛웃음과 함께 안도하고선, 잠시 뒤 QA팀을 욕하기 시작할겁니다.

그런데 이게 과연 QA팀이나 회사 네트워크의 문제일까요?
(테스트 종류에 따라 다르겠지만) 아니오. 테스트를 네트워크 상태에 의존적이게 만든 당신의 잘못입니다.

EP04. 컴퓨터에 방충망을 설치하는 법

사실 이 문제의 가장 쉬운 해결책은 네트워크를 정상화시키는 것입니다.

네트워크가 정상화된다면 다른작업 없이, 지연시간이 원래대로 돌아올테니까요.

그런데 다음에 또 네트워크 장애가 발생한다면요? 이번엔 네트워크가 아예 끊기면 어쩌죠?

설마 또 사직서를 준비하실 생각은 아니죠?

이 문제의 근본적인 해결책은 테스트환경을 네트워크 상태로부터 격리시키는 것입니다.

그럼 지금부터 테스트환경을 외부요소로부터 격리시키기 위한 기술들에 대해 알아볼까요?

Mockito로 속 빈 강정만들기!

Mocking을 통한 외부요소 격리방법
SpringBoot 환경에서 테스트코드를 작성하다보면, 테스트하려는 비즈니스 로직에서 사용하는 Repository나 Util이 필요한 경우가 생깁니다. 하지만 그렇다고해서 단위테스트에서 SpringBootTest를 쓰긴 부담이 될 때가 있죠.

또는 아직 Database 서버를 만들지 않아, Repository생성전에 오류가 발생하는 경우도 있습니다.

비즈니스로직의 테스트가, Database서버 같은 외부환경에 의존하는 상황이죠.

그렇다면 Repository의 구현체를 직접 만들어버리는건 어떨까요? 비즈니스로직에서 사용하는 findById 만 구현한채로요.

이렇게, 속이 빈 인스턴스들을 만들어 테스트를 외부환경에서 격리시키는 방법을 Mocking이라고 합니다.

Mockito는 JVM진영에서 자주 사용하는 Mocking 라이브러리이구요.

자세한 내용은 해당 링크를 참고해주세요!

HashMap보단 낫잖아요 :) Embeded Component

Embeded Component를 통한 외부요소 격리방법
만약, Database를 구성할 때, LocalServer를 쓰기엔 부담스럽고, Repository에 대한 Mock 객체를 쓰자니 테스트 서버자체를 돌려야 한다면 무엇을 써야할까요? DummyRepository 라도 만들어야할까요?

이럴 때 여러분이 사용하실 수 있는 방법이 H2같은 Embeded(내장된)Database입니다!

Embeded 방식은 서버 가동시, 해당 인스턴스 내부에서 또다른 컴포넌트를 구동하는 방식인데요.

Embeded Tomcat은 서버 인스턴스 내부에서 가동되는 Tomcat이고, EmbedDatabase는 서버 인스턴스 내부에서 가동되는 DB라고 생각하시면 됩니다!

이러한 Embeded기술을 통한 유명한 Database기술로 H2가 있습니다!

자세한 내용은 해당 링크를 참고해주세요!

그외에도, DB서버를 Local로 돌리는 등의 여러 방법들이 존재합니다!

EP05. 탓 하는 개발자

글을 적으면서 개인적으로 든 생각 = 뻘글

개발을 하다보면, 종종 무언가를 하곤 합니다.

  • 내부 컴포넌트를 이상하게 짜놨어요.
  • 공식문서가 너무 불친절해요;;
  • 잉크(카페인)가 없으니 코드를 출력하지 못해요

같이 말이죠..

단어를 조금 바꾸어볼까요? 저희의 개발은 위와같은 상황에 "의존"합니다.
밥아저씨가 답답해하는 모습이 그려지지 않으신가요?

60-70년에 활동하던 프로그래머들...2022년으로 데려와도 5분이면 적응하겠다...!~~

실제로 저런말투나 의미로 말씀하신건 아닙니다

어떻게보면 개발자는, 코드간의 의존성도 떨어뜨려야 하지만,

코드와 외부요인(infra)의 의존성도 떨어뜨려야 진정한 개발자가 아닐까요?

내부 컴포넌트가 이상하다면, 컴포넌트의 연결부를 추상화하여 개발하는 부분과의 결합도를 떨어뜨리고,
커피를 못마시면 개발이 힘들 지경이라면, 오히려 커피를 끊고서도 개발할 수 있도록 노력하는게 더 바람직하지 않을까요?

지금까지 긴 글 읽어주셔서 감사합니다! 😍

profile
테오의 스프린트 17기 퍼실리테이터
post-custom-banner

0개의 댓글