요즘 개발 커뮤니티에서는 소위 금지어(?)로 불리는 몇 가지 키워드가 있는 것 같다.
"클린 코드", "DDD", "MSA", "헥사고날" 등등....
나도 저런 키워드들 중 제대로 마스터(?)한 것들이 한 개도 없지만, 공통적으로 느껴지는 것은 있다.
저들의 공통 목적은 결국 많은 사람이 하나의 프로젝트로 협업할 때, 더욱 생산성을 높이며 빠르게 개발할 수 있도록 도와주는 친구들인 것 같다.
코드가 클린하지 않고 짠 사람만 알아볼 수 있는 코드라면, 당장 그 기능을 수정하거나 확장해나갈 때 코드 분석부터 시작해야 한다.
하지만 가독성이 좋은 코드라면 더욱 빠르게 기존 코드에 요구 사항을 반영할 수 있을 것이다.
DDD나 MSA 역시 각 도메인별로 모듈과 DB를 분리하여, 독립적으로 개발함으로써 각각의 요구 사항들을 빠르게 쳐내면서 성장한다.
뭐 물론 트랜잭션 관리나 기타 고려해줘야 할 머리 아픈 내용들이 많겠지만, 이건 잠시 미뤄두고 싶다.
헥사고날도 마찬가지로 유스 케이스는 공통적으로 사용함으로써 다양한 외부 환경에 맞게 어댑터를 자유롭게 갈아 끼워 사용하기 좋은 아키텍처다.
따라서 유스케이스와 어댑터 간의 의존성을 분리하여 서로 간의 인터페이스만 정의해준다면 내부 로직들은 따로따로 각개전투(개발)가 가능하다.
결론적으로는 회사에서 가장 중요한 요소는 생산성이기 때문에, 개발 속도를 높이기 위한 여러 가지 방법들을 사용하는 게 아닐까 싶다. 스타트업 같은 경우에는 빠르게 변화에 대응하는 것이 곧 생존과 직결될 테니...
본론으로 들어가자면 어떤 회사에서 프로젝트를 처음 시작한다고 했을 때, 정말 뛰어난 개발자들이 킥오프 시점부터 참여해서 정말 좋은 아키텍처와 설계를 해놓는다면 더할나위 없이 좋겠지만, 웬만한 곳은 그렇지 못할 것이다.
그렇다면 기존 코드를 계속해서 리팩토링해 나가야된다는 것인데, 별다른 안전 장치 없이 곧바로 리팩토링에 들어간다면... 아마 이곳 저곳에서 사이드 이펙트가 많이 날 것이다. (경험담)
또한 위의 키워드들처럼 모듈을 분리하는 경우에도, 별다른 안전 장치가 없다면 참.. 막막할 것이다.
그럼 이 안전 장치를 어떻게 해놓는 것이 좋을까?
백엔드 기준으로 생각해보겠다.
Spring MVC로 구성된 백엔드 API 애플리케이션은 프론트와 분리되어 있는 상태이다.
즉 클라이언트와 서버 간의 약속을 기반으로 각자 각개전투로 개발하는 것이다. 여기에서 약속을 우리는 HTTP 프로토콜이라고 부른다.
그럼 백엔드 기준에서 어떠한 값들로 요청이 들어올 때 약속된 결과값만 문제 없이 내려온다면, 우리는 사이드 이펙트로부터 한결 편해지지 않을까?
물론 약속된 결과값이 반환된다고 해도, 내부적인 동작이 의도한 대로 돌아가는지는 당연히 확인해야겠지만 그건 일단 이후 문제다.
모든 요청에 대한 응답 값이 테스트 코드로부터 보장된다면, 즉 외부 보호 장벽이 둘러싸여 있다면 우리는 더욱 마음 편히 내부를 지지고 볶으면서 리팩토링을 진행할 수 있을 것이다.
이 외부 보호 장벽을 인수 테스트가 해줄 수 있다.
단 여기서 말하는 인수 테스트는 특정 범위와 구현 방법이 딱히 정해져 있기보다는, 테스트 의도에 따라 달라지는 것 같다.
내가 주로 사용하는 인수 테스트는 블랙박스의 성격을 가진 테스트로 내부 구현이 어떻게 돌아가는지는 관심 없고 단지 가장 끝 단에서 요구 사항에 정확하게 동작하는지 확인하는 테스트이다.
그 요구 사항은 프론트엔드와의 약속이 될 수도 있고, PM의 기획서 기반이 될 수도 있고, 업체의 실제 요구 사항 기반이 될 수도 있다.
우리가 만드는 프로그램은 요구사항만 완벽히 동작한다면, 일단 1차적으로는 안심일 테니 말이다.
참 주저리주저리 말이 많았지만, 하고 싶은 말은 다음과 같다.
마지막으로 아래는 ATDD과정의 마지막 주차인 "테스트 리팩터링"이라는 주제를 학습하며 정리해놓은 글이다.
@ExtendWith
@ExtendWith(MockitoExtension.class)
@Mock
)LineRepository lineRepository = mock(LineRepository.class)
로는 Extension 없이도 사용 가능@ExtendWith(SpringExtension.class)
@MockBean
도 주입해서 사용 가능@SpringBootTest
@SpringBootApplication
을 통해 실행하는 서버의 환경과 동일한 설정@WebMvcTest
@DataJpaTest
@DataJdbcTest
, @DataRedisTest
)@SpringBootTest
보다 @ExtendWith(SpringExtension.class)
로 선언하고 필요한 빈들만 따로 주입해서 사용하는 방식이 많이 쓰이나요??@ExtendWith(SpringExtension.class)
를 사용하면 훨씬 속도가 빠르긴 하겠지만, 실제로 서비스 테스트를 진행한다고 했을 때 일반적으로 5~6개의 빈들에 의존을 하기 때문에 @SpringBootTest
를 사용하는것이 좀 더 편할 수도 있다Test 실행 → 문서 조각(Snippets) 발생 → 템플릿에 맞게 스니펫들이 끼워맞춰짐 → 문서로 전환