BEST
개발 · 프로그래밍

/

백엔드

Java/Spring 테스트를 추가하고 싶은 개발자들의 오답노트

Spring에 테스트를 넣는 방법을 알려드립니다! 더 나아가 자연스러운 테스트를 할 수 있게 스프링 설계를 변경하는 방법을 배웁니다.

(4.9) 수강평 123개

수강생 1,806명

Thumbnail

초급자를 위해 준비한
[소프트웨어 테스트, Spring] 강의입니다.

이런 걸
배워요!

  • Spring에 테스트를 넣는 방법

  • 테스트에 필요한 개념

  • 자연스러운 테스트를 하는 방법

  • Mockito 없이 테스트하는 방법

  • 의존성과 Testability

  • 헥사고날 아키텍처(Hexagonal Architecture)와 설계

프로젝트 설계를 발전시키는 
테스트의 본질을 짚어드릴게요! 

Spring에 테스트를 넣는 방법으로 시작해, 아키텍처 강의로 끝납니다!

테스트에 대한 올바른 의견을 전달해 드리려면, 결국 아키텍처로 끝나야 한다라는 생각을 했기 때문입니다. 

테스트에 대한 기본적인 개념을 배우고, Spring(스프링)에 테스트를 어떻게 넣어야 하는지 배웁니다. 더 나아가 자연스러운 테스트를 할 수 있게 스프링 설계를 변경하는 방법을 배웁니다.

그래서, 이런 내용을 학습합니다.

테스트가 
필요한 이유 

테스트에 대한 
기본 개념
 

Spring에 
테스트를 넣는 
방법 

Spring 설계를 
진화시키는 
방법 

클린 
아키텍처 

헥사고날 
아키텍처 
 


그런데 혹시, 이런 생각이 들진 않나요?
테스트에 대한 고민과 오해들 

“테스트를 정말 간절히 넣어보고 싶습니다. 그런데...”

다른 회사 다니는 친구는 시대의 요구에 발맞춰서 테스트를 꾸준히 넣어가며 차근차근 성장하고 있습니다. 그런데 우리 회사는 테스트를 넣지 않아요. 뒤처지고 싶지 않습니다. 공부할 의지도 있습니다. 그런데 도저히 이 레거시 시스템에 테스트 코드를 어떻게 넣어야 할지 감이 안 옵니다.

“H2를 이용한 테스트에 신물이 납니다.”

H2를 이용한 테스트는 너무 느리고 DB에 지나치게 종속적입니다. 모든 테스트가 H2를 이용하고 있습니다. 테스트를 돌리기는 부담스럽고, 테스트들이 h2를 공유하다 보니 데이터가 뒤엉켜서 어떨 때는 테스트가 성공하고, 또 어떨 때는 실패합니다.

“테스트의 필요성을 못 느끼겠습니다.”

우리 팀은 사람이 그렇게 많지도 않고, 배포하면서도 그다지 불안함을 느낀 적이 없습니다. 요구사항은 시시각각 변합니다. 근데 TDD를 어떻게 하나요? 테스트는 개발 속도만 늦출 뿐이라고 생각합니다.


테스트, 저도 같은 고민을 했습니다.

시중에 나와 있는 테스트 관련 책이나 세미나를 찾아보면 대부분 그냥 테스트의 장점, 테스트 코드 짜는 법, JUnit, Mockito 정도만 얘기하고 끝납니다. 예제는 딱 입문자의 입맛에 맞을 만큼 간단한 예제 뿐이고요. 그래서 마지막에 가서 책을 덮을 때면 이런 생각이 듭니다.

  • "대체 이걸 현업에서 어떻게 쓰라는 거죠?"
  • "Spring에는 테스트를 어떻게 넣으라는 건가요?"
  • "이건 프레임워크가 없는 상황에서 넣는 테스트니까 쉽게 넣을 수 있는 거 아닌가요?"

혼란스러웠습니다. H2를 이용한 JPA 테스트... 뭐 좋습니다. 그런데 ElasticSearch나 Cassandra처럼 테스트용 DB가 없으면 어떻게 테스트하라는 걸까요? 게다가 H2를 이용한 테스트는 정말 치명적일 정도로 느렸습니다. 하루에도 여러 번 돌리기 부담스러웠고요. 테스트는 자주 깨지고 DB 테이블이라도 변경되는 날에는 관련된 테스트도 싹 다 수정해야 해서 시간 낭비 같다는 생각이 들기 일쑤였습니다.

TDD를 공부하려면, TDD부터 공부하면 안 됩니다.

그러던 중 저의 고민들은 아키텍처와 DDD를 공부하기 시작하면서 모두 해결됩니다. 알고 있습니다. TDD는 항상 핫하죠. 그런데 TDD는 정말 매력적이면서도 어려운 방법론입니다. TDD를 해본 적 없는 조직에서 TDD가 유행이니 이제부터 TDD로 개발하려고 하면 그게 될까요? TDD는 생각보다 시작하기 전에 알아야 할 선수 지식과 공감대를 정말로 많이 필요로 합니다.

그래서 TDD를 공부하려면 TDD부터 공부하면 안 됩니다. 테스트를 먼저 공부해야 합니다. 미적분을 하려면 방정식부터 다룰 줄 알아야 하는 것처럼 말입니다.

테스트에 대한 저의 이야기를 풀어드릴게요!


테스트에 대한 고민을 
명쾌하게 해결해드릴게요.

테스트의 필요성을 못 느끼겠다면

테스트의 필요성이 느껴지지 않는다면, 아직 프로젝트의 규모가 그리 크지 않거나 테스트가 없어도 될 만큼의 훌륭한 개발 능력과 문화를 갖추신 것 같습니다. 테스트는 정답이 아닙니다! 테스트가 없던 시절에도 훌륭한 프로젝트들이 많이 개발되었습니다. 테스트는 좋은 소프트웨어를 얻기 위한 도구이기 때문에 그 자체가 목표가 아닙니다.

테스트로 좋은 설계를 얻는 방법을 모르겠다면

테스트를 하는 방법에만 너무 치중해서 공부하신 것 같습니다. JUnit 사용법, Mockito 사용법, h2를 연동하는 방법을 공부하는 것은 분명 의미가 있는 공부지만 그게 테스트의 본질은 아닙니다. 테스트를 왜 해야하고, 어떤 목표가 있고 그 목표를 달성하기 위해 어떻게 실천해야 하는지를 익혀야 합니다

테스트 프레임워크 없이 테스트하는 방법을 모르겠다면

테스트 프레임워크에 대한 질문 역시 이전 질문과 같은 대답입니다. 만약 여러분이 Typescript + Nest.js를 쓰는 환경에 있다면, 어떻게 테스트하실 건가요? Mockito, H2 같은 테스트 프레임워크 없이도 테스트하는 방법을 익혀야 합니다.


Spring 개발자에게 꼭 필요한 
테스트 넣는 법
을 배워야 합니다.

  • ✅ 실무와 동떨어진 테스트 넣는 방법을 알려드리지 않습니다.
  • ✅ Spring 개발자에게 필요한 테스트 넣는 법을 알려드립니다.
  • ✅ 그러면서 동시에 왜 이렇게 해야 하는지를 알려드립니다.

이 원리를 기반으로 한 지식은 다른 프레임워크에서도 통용되는 지식들입니다. Nest.js를 사용하시던, Swing UI를 사용하시던, Gin을 사용하시던... 어디에서든 적용될 수 있는 지식이라 생각합니다.

종장에 가서는 설계에 대한 강의로 이어집니다. 테스트의 가치를 최대한으로 설명해 드리기 위해선 설계에 대한 내용이 빠져선 안 된다 생각했기 때문입니다. 

적어도 제가 찾아보기론 국내의 스프링에 테스트를 넣는 법을 알려주는 책이나 강의는 못 본 것 같습니다. 모두 @Mock, @Spy 이런 어노테이션을 이용하여 mocking하고 의존성 주입 받아 테스트를 작성합니다. 하지만 만약 이런 Mock 라이브러리가 존재하지 않는 환경이라면 어떻게 테스트 하실 건가요? 본질적으로 이러한 어노테이션이 없어도 테스트하는 방법을 알아야 합니다! 그리고 테스트해야 할 대상이 무엇인지도 구분할 수 있어야 합니다. 


테스트를 테스트답게 추가하는 
방법을 알려드립니다!

테스트의 필요성을 알게 됩니다.

프레임워크 없이도 스프링에 테스트를 넣는 법을 알게 됩니다.

스프링을 사용하는 더 나은 방법을 알게 됩니다.

레이어드 아키텍처에서 헥사고날 아키텍처로 변화하는 방법을 이해하게 됩니다.

오리엔테이션

테스트를 추가하고 싶은 조직에서 TDD를 도입할 때 실패하는 이유를 살펴봅니다. 일반적으로 내가 하는 TDD는 왜 실패하는지 살펴봅니다. 테스트에 대한 제대로 된 이해 없이 테스트를 무작정 넣기 시작했을 때 발생하는 문제점들을 같이 살펴봅니다.

테스트에 대한 이론

기본적인 테스트 지식을 공부합니다. 테스트의 필요성에 대해 공감하고 테스트와 설계의 상관관계를 파악합니다. 테스트를 만들면서 개발자는 어떤 고민을 해야하는지 이해합니다. 최종적으로 자연스러운 테스트를 위해 Testability를 높이는 작업에 대해 같이 살펴봅니다.

1부 - 토이프로젝트 기반 테스트 적용

앞으로 사용할 토이 프로젝트를 같이 살펴봅니다. 그리고 토이 프로젝트에 어거지로 테스트를 넣어보며 최대한 테스트를 넣어 커버리지 100%를 달성해봅니다. 이 과정에서 h2, MockMvc, PowerMock같은 외부 라이브러리들을 사용합니다.

최종적으로 만들어진 테스트들을 같이 살펴보며 회귀 버그만을 커버하기 위한 테스트에는 어떤 문제가 있는지 살펴봅니다.

방향성 탐색

우리의 토이 프로젝트에 테스트를 넣은 게 그다지 좋은 방향이 아닌 이유를 같이 살펴봅니다. 더불어 전통적인 레이어드 아키텍처의 문제점에 대해 같이 살펴봅니다. 그리고 어떤 식으로 개선할 것인지, 강연자의 의견을 들어봅니다.

1부 실기에서 무작정 테스트를 넣기 위해 고군분투했다면, 2부에서는 Mockito 같은 외부 라이브러리 없이도 자연스럽게 Mock하는 방법을 익힙니다. 2부 실기를 위해 미리 어떻게 코드를 바꿀지 같이 살펴봅니다.

2부 - 토이프로젝트 구조 설계 개선

앞선 방향성 탐색을 통해 얻은 인사이트를 우리의 토이 프로젝트에 도입합니다. 이 과정에서 구조적인 변화를 줘가며 설계를 개선합니다. 그리고 이 과정에서 아래와 같은 기법들이 사용됩니다.

  • 패키지 구조 개선
  • 도메인과 영속성 객체를 구분하기
  • 서비스 로직을 도메인으로 가져오기
  • 외부 연동을 의존성 역전하기
  • 테스트를 소형 테스트로 만들기

진화하는 아키텍처

테스트와 설계의 상관관계를 통해 아키텍처를 진화시키는 방법에 대해 같이 살펴봅니다. 레이어드 아키텍처가 어떻게 헥사고날 아키텍처로 변하는지 살펴봅니다. 관심사를 분리하면서 개발자가 도메인에 집중하는 방법을 배웁니다.


개발자로 성장하는 데  
도움을 드리고 싶습니다!

안녕하세요, 김우근입니다! 👋

현재 카카오에서 일하고 있고, 만드는 것을 좋아해서 퇴근 후에도 항상 무언가를 개발하고 있습니다. "거인의 어깨 위에 선 난쟁이"라는 말이 있습니다. 저 역시 한낱 작은 난쟁이일 뿐이지만, 올라탄 거인의 성장에 도움이 될 수 있도록 지식의 대물림을 위해 노력하고 있습니다. 다수의 주니어 개발자 분들을 멘토링한 경험이 있어서 여러분의 성장을 도와줄 수 있을 거예요.


Q&A 💬

Q. JUnit이나 Mockito 사용법은 안 알려주시나요?

네, 아쉽게도 해당 강의는 JUnit과 Mockito 사용법에 대한 내용을 다루지 않습니다. 이유는 아래와 같습니다.

Context) 수강생 개인마다 처한 상황이 다릅니다. 이미 몇 번 테스트를 짜본 사람이 있다면, 라이브러리를 다루는 숙련도가 다를 수 있습니다. 회사에서 사용하고 있는 라이브러리가 JUnit이나 Mockito가 아닐 수도 있고. 버전이 달라서 제공하지 않는 인터페이스가 존재할 수도 있습니다. 대표적인 예로 JUnit4에서는 @ParameterizedTest를 지원하지 않습니다. 게다가 앞서 언급 드린 라이브러리들의 사용법이 그렇게 어렵지 않고 관련된 좋은 자료가 이미 너무 많습니다. 하다못해 Github README 파일을 읽거나 공식 가이드를 읽는 것만으로도 충분히 사용법을 익힐 수 있다고 생각합니다. 따라서 사용법은 중요한 내용이 아니라고 생각했습니다.

Test Design) 특정 라이브러리가 제공하는 특정 기능을 이용하여 테스트하는 법을 익히는 것은 그 라이브러리가 없으면 해당 테스트를 할 수 없다는 의미입니다. 도구나 프레임워크보다 테스트를 어떻게 설계하고, 어떻게 테스트 가능한 구조로 바꾸는지가 더 중요합니다. 따라서 이 강의는 도구에 집중하지 않습니다. 테스트는 개발 프로세스의 한 부분입니다. 그러므로 요구사항 분석, 설계 및 배치, 유지보수 같은 맥락에서 고려되어야 할 점을 점검하는 것이 더 중요하다고 생각했습니다.

Q. 이전 강의와의 차이점은 어떤 것이 있나요?

커리큘럼을 보시면 아시겠지만, 이전 강의와 중복되는 내용이 다소 있습니다. 이래야 한다는 것만 덩그러니 설명해 드리기에는 설득력도 부족하고 맥락을 이해시켜드리지 못하기 때문에, 독립적으로 해당 강의도 수강할 수 있도록 강의를 구성하였습니다. 그러니 반드시 목차를 확인해보시고 겹치는 내용이 있는지 확인해 봐주세요.

솔직한 이야기로 이전 강의를 제대로 이해하셨다면 굳이 중복해서 수강할 필요는 없다고 생각합니다. 이전 강의가 구조적으로 왜 이렇게 되어야 하는지를 설명하는 강의였다면, 이번 강의는 실제로 코드 레벨에서 어떻게 풀리는지를 다루는 강의라고 보시면 됩니다. 

Q. 수강 전 알아야 할 사항이 있나요?

해당 강의는 스프링이나 JPA를 알려드리는 강의는 아닙니다. 수강자가 대략적인 Spring과 JPA를 다룰 수 있다는 것을 전제로 강의를 진행합니다. 아울러 스프링에 테스트를 넣는 법을 알려드리고 있지만 본질적으로는 의존성을 어떻게 풀어내는지에 대해 초점을 맞춰 진행하였고, 꼭 언어나 프레임워크에 구애받는 내용은 아니라고 생각합니다. 덧붙여, 전공 지식은 필요로 하지 않습니다 :)

💾 수강 전 확인해주세요!

  • 강의 내 실습 내용은 가급적 특정 라이브러리나 IDE, 사양에 의존적이지 않게 구성하였습니다. 특정 버전에 있는 특정 기능을 활용한 강의가 되지 않도록 노력했습니다. 그래도 혹시 모르니 강연자의 랩탑 구성이 아래와 같은 환경임을 알려드립니다.
    • PC 사양 및 운영체제: MacBook Pro (16-inch, 2019) 및 macOS Monterey 12.6
    • IDE: IntelliJ IDEA 2021.3.2
    • Java 17, Spring Boot 3.0.1, JUnit 4.13.2, AssertJ 3.23.1
  • 수강생에게는 40페이지 내외의 PPT 자료 12개를 함께 제공합니다.
  • 이 강의는 프로그래밍 언어나 스프링을 다루는 방법 등에 대해 다루지 않습니다.
  • Spring 및 Spring Data JPA를 한 번이라도 다뤄본 사용자를 기준으로 설명합니다.
  • Controller, Service, Repository에 대해 알고 계신다는 전제로 설명합니다.
  • 강의에 사용할 토이 프로젝트를 미리보기 수업으로 풀어두었습니다. 확인해보시고 이해할 수 있는 정도면 괜찮습니다.
  • PPT 일부를 캡처해서 공부한 내용을 블로그에 올리는 것은 허용하나 자료 전체를 개인 블로그에 공유하는 건 금합니다. 양해 부탁드립니다!
  • 이전 강의와 중복되는 내용이 다소 있습니다. 목차를 확인해보시고 겹치는 내용 있는지 확인해 봐주세요. 
  • 데모 프로젝트는 여기를 참고해주세요.

이런 분들께
추천드려요!

학습 대상은
누구일까요?

  • Spring에 테스트를 넣고 싶은 분

  • Spring에 테스트를 어떻게 넣어야 할지 막막하신 분

  • 내가 개발한 Spring 프로젝트가 올바른 설계 구조인지 헷갈리는 분

  • 테스트를 넣어보려 했지만 실패했던 분

  • H2 같은 테스트 DB가 없는 NoSQL에 테스트를 넣고 싶은 분

선수 지식,
필요할까요?

  • Java 코드를 이해하실 수 있으신 분

  • Spring 기본 (Controller / Service / Repository가 무엇인지 아시는 분)

  • JPA를 사용해보신 분

  • (현) 카카오 백엔드 엔지니어
  • (수상) 🏆 공개 SW 개발자 대회 [2020 일반부문 / 금상_정보통신산업진흥원장상] 

 

현재 카카오에서 일하고 있고, 만드는 것을 좋아해서, 퇴근 후에도 항상 무언가를 개발하고 있습니다.

"거인의 어깨 위에 선 난쟁이"라는 말이 있습니다. 저 역시 한낱 작은 난쟁이일 뿐이지만, 올라탄 거인의 성장에 도움이 될 수 있도록 지식의 대물림을 위해 노력하고 있습니다. 다수의 주니어 개발자분들을 멘토링 한 경험이 있어서 여러분의 성장을 도와줄 수 있을 거예요. 

 

깃허브 > https://github.com/kok202
블로그 > https://kok202.tistory.com

커리큘럼

전체

25개 ∙ (6시간 20분)

수업 자료

가 제공되는 강의입니다.

강의 게시일: 
마지막 업데이트일: 

수강평

아직 충분한 평가를 받지 못한 강의입니다.
모두에게 도움이 되는 수강평의 주인공이 되어주세요!