지난 수요일 구름에서 프론트엔드 테스팅과 설계라는 주제로 COMMIT이 열려 다녀왔다.

프로젝트를 몇 번 참여하면서 백엔드 테스트 코드의 중요성은 익히 들어왔고 백엔드에서 테스트를 하는 것을 흔히 봤었는데 프론트엔드에서 테스트 코드를 작성하는 것은 잘 보지 못했다. 프론트엔드에서 비교적 테스트 코드를 잘 적용하지 않는 이유가 있는지 그리고 프론트엔드 테스트는 어떻게 진행하는지 궁금증이 생겨 프론트엔드 테스팅 툴에 대해 조금 공부를 해보고 있었는데, 마침 구름에서 관련 주제로 컨퍼런스가 열렸고 운 좋게 당첨이 되었다!

이번 COMMIT은 프론트엔드에서 테스트를 해야 하는 이유와 테스트를 어떻게 해야 하는지를 중점으로 진행되었고 테스트를 통한 소프트웨어 설계에 대해서도 이야기해 주셨다. 흥미로운 내용이었기에 이곳에서 배웠던 내용을 정리하고 간단한 후기를 남기려고 한다.
테스트란?
테스트는 기준에 따라 여러가지 형태로 정의된다.
분류 기준 | 정의 |
범위 | 단위 테스트, 통합 테스트, 인수 테스트(E2E) |
기능 | 기능 테스트, 비기능 테스트 |
방식 | 명세 기반 테스트(블랙박스 테스트), 구조 기반 테스트 (화이트박스 테스트) |
크기 | 작은 테스트, 중간 테스트, 큰 테스트 |
앞으로 이야기하게 될 주제들은 테스트의 여러 분류 중 단위 테스트, 기능 테스트, 명세 기반 테스트, 작은 테스트를 중심으로 진행된 내용이다.
왜 테스트를 해야 할까?
- 변화하는 코드에 대응
- 코드는 변한다. 제품은 수정되므로 결국 우리가 작성한 코드는 레거시가 된다.
테스트 코드가 있으면 코드를 수정한 후에도 기능이 정상적으로 작동하는지 검증할 수 있어, 자신감있게 코드를 리팩토링 하거나 수정할 수 있다.
- 코드는 변한다. 제품은 수정되므로 결국 우리가 작성한 코드는 레거시가 된다.
- Shift Left
- 오류가 검출될 수 있는 단계를 왼쪽(개발 수명 주기의 시작점)으로 당긴다.
오류를 조기에 발견할수록 발생된 오류를 수정하는 비용을 감소시킬 수 있다. (설계 단계에서 테스트를 고려하여 설계하는 것을 권장한다.)
- 오류가 검출될 수 있는 단계를 왼쪽(개발 수명 주기의 시작점)으로 당긴다.
- 더 나은 설계와 코드를 위해
- 프론트엔드 코드를 경험하는 것은 개발자가 아닌 사용자이다. 하지만 테스트 코드를 작성하면 코드를 사용하는 입장을 경험할 수 있다.
- 테스트 코드를 작성하려고 했을 때 비로소 내가 만든 컴포넌트의 확장 가능성과 인터페이스의 중요성, 코드 모듈의 의도가 보이게 되고 웹 접근성을 고려하게 된다.
- 문서화 커뮤니케이션
- 개발이 진행되다 보면 담당자의 부재가 발생하거나 제품의 맥락이 많아지게 되어 커뮤니케이션이 필요하고 문서들은 점점 많아진다.
- 하지만 문서들은 시간이 지나면 믿을 수 없는 문서가 된다. 누가, 언제 작성한 건지 진실이 보장된건지 알 수 없다. 하지만 테스트 코드는 이를 보장한다. 누가, 언제 작성했는지 알 수 있고 코드를 기반으로 작성되었기에 거짓말을 할 수 없는 문서가 된다.
무엇을 테스트해야 할까?
- 구현이 아닌 기능을 테스트한다.
- 기능을 테스트 하는 과정에서 구현이 드러나면 안된다.
예를 들어, Counter 프로그램을 테스트할 때 테스트 코드는 리액트의 state가 올라가는지 서버의 state가 올라가는지 알 수 없게 작성해야 한다. (기능: 버튼을 누르면 숫자가 올라간다. 구현: 숫자는 리액트의 state로 관리한다.)
- 기능을 테스트 하는 과정에서 구현이 드러나면 안된다.
어떻게 테스트를 해야 할까?
- 테스트 코드가 어려운 이유
- 동작하는 환경의 차이
제품은 브라우저에서 동작하고 테스트코드는 Node.js에서 동작하기에 예상치 못한 상황이 발생할 수 있다. - 외부와의 상호작용과 다양한 상태
프론트엔드는 사용자, 브라우저, 서버 등 외부와 다양하게 상호작용한다. 또한 리액트에서 관리하는 state, 서버에서 관리하는 state, 디바이스에 따른 state 등이 존재하기 때문에 환경과 상황에 따라 작성한 테스트 코드가 깨지기도 한다.
사실 진짜 이유는 테스트 코드를 많이 공부하지 않기 때문이라고 생각한다. 현실적으로 테스트 코드 작성보다는 기능 구현이 우선시 되는 경우가 많고, 테스트 코드를 공부하기보다 새로운 프레임워크를 공부하기 때문에 테스트 코드를 어렵다고 느끼는 것 같다. 그리고 좋은 테스트 코드란 무엇인지 잘 정의하고 있는 자료가 많지 않기도 하다.
- 동작하는 환경의 차이
- 테스트 코드를 작성하는 전략
- 의존성 관리 전략
프론트엔드 애플리케이션 테스트는 브라우저, 서버 등과 의존성을 가지고 있기에 이 의존성들을 잘 구분하여 테스트 코드를 작성해야 한다.- 외부 의존성인가? 인프라인가?
서버, 브라우저의 스토리지, 윈도우 API들은 외부 의존성으로 간주하고 언어(자바 스크립트), 라이브러리(리액트), 라우터 같은 경우는 인프라로 간주하여 전략을 세운다. 방식에 따라 장단점이 존재하기 때문에 본인의 상황이 어떤 방식에 더 적합한지 잘 판단해야 한다.- 외부 의존성 관리: 의존성 주입으로 테스트 코드를 관리한다. 이 방식은 구현이 드러나지 않기 때문에 변경에 내성이 강하다. 하지만 제품의 설계가 많이 바뀔 수 있다.
- 인프라 관리: Mocking으로 테스트 코드를 관리한다. 이 방식은 구현이 드러나기 때문에 테스트가 깨지기 쉽고 변경에 취약하다.(프레임워크를 바꾸면 테스트 코드를 다 바꿔야 한다.)
- 외부 의존성인가? 인프라인가?
- 의존성 관리 전략
따라서 테스트 코드를 작성하는 순서는 아래와 같이 정리할 수 있다.
의존성을 식별하고 어떻게 관리할지 정한다. → 전략에 따라 테스트 코드를 작성한다. →
기능 위주로 테스트 코드를 작성한다. → 발생한 버그는 재현하여 관리한다.
언제 테스트를 해야 할까?
- 아키텍쳐 디자인 단계(제품 설계)부터 테스트에 용이하게 설계한다. 그리고 제품이 안정 궤도에 오르게 됐을 때 테스트 코드를 작성한다.
내가 만든 코드는 내일 수정될 수도 있으며 구현하고 있는 기능이 사라질 수도 있고 제품 자체가 사라질 수도 있다. 이런 불확실한 상황 속에서 무작정 테스트 코드를 도입하는 것은 효율적이지 않다. 따라서 테스트 비용과 효용을 잘 고려해서 도입해야 한다. 가장 이상적인 방식은 개발 초기에 테스트에 용이한 설계가 진행되도록 하는 것이다.
결론
- 테스트 코드는 개발에 도움이 되기 위해, 지속 가능성을 위해 필요하며 테스트 비용 대비 실익이 커야한다.
- 테스트 코드는 의존성 관리 전략을 기반으로 설계되어 기능을 테스트하되 구현이 드러나지 않도록 작성해야 한다.
후기
이번 강연을 듣고 "프론트엔드에서 테스트 코드가 왜 필요한가?"에 대한 나의 대답은 "개발을 위해서 테스트 코드 설계가 필요하다." 이다. 테스트 코드를 작성한다는 것에 초점을 맞추기 보다 테스트 코드 설계에 중심을 두는게 더 중요한 것 같다.
테스트에 용이한 설계를 하려면 제품의 레이어를 잘 나누어야 한다. 이는 자연스럽게 좋은 코드를 작성할 수 있도록 돕는다. 따라서 우리는 개발에 도움이 되는 테스트 코드를 작성할 수 있게 된다.
Q&A 시간에 나온 질문들을 봤을 때 프론트엔드 테스팅을 하지 않는 회사들이 꽤 있어 보였다. 강사님도 테스트 코드를 도입한 계기가 한 기능에 에러가 발생했을 때 겪는 리스크가 너무 크고 배포 시 장애가 자주 발생해서였다는 언급을 해주셨는데, 실무에서는 테스트 코드를 무작정 도입하기보다 테스트 비용 대비 창출할 수 있는 가치를 잘 따져서 도입하는 게 현명하다는 생각이 들었다. 하지만 아직 프론트엔드를 공부하는 학생으로서 학습을 목적으로 진행하는 프로젝트에 테스트 코드를 적용해 볼 생각이다.
좋은 코드를 작성하는 방법 중 하나가 테스팅을 위한 설계를 하는 것이라고 배웠다. 아직 초보 개발자인 나에게 제품의 레이어를 잘 나누어 좋은 설계를 한다는 것이 너무 어렵게 느껴지지만 이제는 어떻게 하는 것이 설계를 잘 하는 것인지 고민하고 공부해 볼 필요가 있다고 생각한다.
지난 수요일 구름에서 프론트엔드 테스팅과 설계라는 주제로 COMMIT이 열려 다녀왔다.

프로젝트를 몇 번 참여하면서 백엔드 테스트 코드의 중요성은 익히 들어왔고 백엔드에서 테스트를 하는 것을 흔히 봤었는데 프론트엔드에서 테스트 코드를 작성하는 것은 잘 보지 못했다. 프론트엔드에서 비교적 테스트 코드를 잘 적용하지 않는 이유가 있는지 그리고 프론트엔드 테스트는 어떻게 진행하는지 궁금증이 생겨 프론트엔드 테스팅 툴에 대해 조금 공부를 해보고 있었는데, 마침 구름에서 관련 주제로 컨퍼런스가 열렸고 운 좋게 당첨이 되었다!

이번 COMMIT은 프론트엔드에서 테스트를 해야 하는 이유와 테스트를 어떻게 해야 하는지를 중점으로 진행되었고 테스트를 통한 소프트웨어 설계에 대해서도 이야기해 주셨다. 흥미로운 내용이었기에 이곳에서 배웠던 내용을 정리하고 간단한 후기를 남기려고 한다.
테스트란?
테스트는 기준에 따라 여러가지 형태로 정의된다.
분류 기준 | 정의 |
범위 | 단위 테스트, 통합 테스트, 인수 테스트(E2E) |
기능 | 기능 테스트, 비기능 테스트 |
방식 | 명세 기반 테스트(블랙박스 테스트), 구조 기반 테스트 (화이트박스 테스트) |
크기 | 작은 테스트, 중간 테스트, 큰 테스트 |
앞으로 이야기하게 될 주제들은 테스트의 여러 분류 중 단위 테스트, 기능 테스트, 명세 기반 테스트, 작은 테스트를 중심으로 진행된 내용이다.
왜 테스트를 해야 할까?
- 변화하는 코드에 대응
- 코드는 변한다. 제품은 수정되므로 결국 우리가 작성한 코드는 레거시가 된다.
테스트 코드가 있으면 코드를 수정한 후에도 기능이 정상적으로 작동하는지 검증할 수 있어, 자신감있게 코드를 리팩토링 하거나 수정할 수 있다.
- 코드는 변한다. 제품은 수정되므로 결국 우리가 작성한 코드는 레거시가 된다.
- Shift Left
- 오류가 검출될 수 있는 단계를 왼쪽(개발 수명 주기의 시작점)으로 당긴다.
오류를 조기에 발견할수록 발생된 오류를 수정하는 비용을 감소시킬 수 있다. (설계 단계에서 테스트를 고려하여 설계하는 것을 권장한다.)
- 오류가 검출될 수 있는 단계를 왼쪽(개발 수명 주기의 시작점)으로 당긴다.
- 더 나은 설계와 코드를 위해
- 프론트엔드 코드를 경험하는 것은 개발자가 아닌 사용자이다. 하지만 테스트 코드를 작성하면 코드를 사용하는 입장을 경험할 수 있다.
- 테스트 코드를 작성하려고 했을 때 비로소 내가 만든 컴포넌트의 확장 가능성과 인터페이스의 중요성, 코드 모듈의 의도가 보이게 되고 웹 접근성을 고려하게 된다.
- 문서화 커뮤니케이션
- 개발이 진행되다 보면 담당자의 부재가 발생하거나 제품의 맥락이 많아지게 되어 커뮤니케이션이 필요하고 문서들은 점점 많아진다.
- 하지만 문서들은 시간이 지나면 믿을 수 없는 문서가 된다. 누가, 언제 작성한 건지 진실이 보장된건지 알 수 없다. 하지만 테스트 코드는 이를 보장한다. 누가, 언제 작성했는지 알 수 있고 코드를 기반으로 작성되었기에 거짓말을 할 수 없는 문서가 된다.
무엇을 테스트해야 할까?
- 구현이 아닌 기능을 테스트한다.
- 기능을 테스트 하는 과정에서 구현이 드러나면 안된다.
예를 들어, Counter 프로그램을 테스트할 때 테스트 코드는 리액트의 state가 올라가는지 서버의 state가 올라가는지 알 수 없게 작성해야 한다. (기능: 버튼을 누르면 숫자가 올라간다. 구현: 숫자는 리액트의 state로 관리한다.)
- 기능을 테스트 하는 과정에서 구현이 드러나면 안된다.
어떻게 테스트를 해야 할까?
- 테스트 코드가 어려운 이유
- 동작하는 환경의 차이
제품은 브라우저에서 동작하고 테스트코드는 Node.js에서 동작하기에 예상치 못한 상황이 발생할 수 있다. - 외부와의 상호작용과 다양한 상태
프론트엔드는 사용자, 브라우저, 서버 등 외부와 다양하게 상호작용한다. 또한 리액트에서 관리하는 state, 서버에서 관리하는 state, 디바이스에 따른 state 등이 존재하기 때문에 환경과 상황에 따라 작성한 테스트 코드가 깨지기도 한다.
사실 진짜 이유는 테스트 코드를 많이 공부하지 않기 때문이라고 생각한다. 현실적으로 테스트 코드 작성보다는 기능 구현이 우선시 되는 경우가 많고, 테스트 코드를 공부하기보다 새로운 프레임워크를 공부하기 때문에 테스트 코드를 어렵다고 느끼는 것 같다. 그리고 좋은 테스트 코드란 무엇인지 잘 정의하고 있는 자료가 많지 않기도 하다.
- 동작하는 환경의 차이
- 테스트 코드를 작성하는 전략
- 의존성 관리 전략
프론트엔드 애플리케이션 테스트는 브라우저, 서버 등과 의존성을 가지고 있기에 이 의존성들을 잘 구분하여 테스트 코드를 작성해야 한다.- 외부 의존성인가? 인프라인가?
서버, 브라우저의 스토리지, 윈도우 API들은 외부 의존성으로 간주하고 언어(자바 스크립트), 라이브러리(리액트), 라우터 같은 경우는 인프라로 간주하여 전략을 세운다. 방식에 따라 장단점이 존재하기 때문에 본인의 상황이 어떤 방식에 더 적합한지 잘 판단해야 한다.- 외부 의존성 관리: 의존성 주입으로 테스트 코드를 관리한다. 이 방식은 구현이 드러나지 않기 때문에 변경에 내성이 강하다. 하지만 제품의 설계가 많이 바뀔 수 있다.
- 인프라 관리: Mocking으로 테스트 코드를 관리한다. 이 방식은 구현이 드러나기 때문에 테스트가 깨지기 쉽고 변경에 취약하다.(프레임워크를 바꾸면 테스트 코드를 다 바꿔야 한다.)
- 외부 의존성인가? 인프라인가?
- 의존성 관리 전략
따라서 테스트 코드를 작성하는 순서는 아래와 같이 정리할 수 있다.
의존성을 식별하고 어떻게 관리할지 정한다. → 전략에 따라 테스트 코드를 작성한다. →
기능 위주로 테스트 코드를 작성한다. → 발생한 버그는 재현하여 관리한다.
언제 테스트를 해야 할까?
- 아키텍쳐 디자인 단계(제품 설계)부터 테스트에 용이하게 설계한다. 그리고 제품이 안정 궤도에 오르게 됐을 때 테스트 코드를 작성한다.
내가 만든 코드는 내일 수정될 수도 있으며 구현하고 있는 기능이 사라질 수도 있고 제품 자체가 사라질 수도 있다. 이런 불확실한 상황 속에서 무작정 테스트 코드를 도입하는 것은 효율적이지 않다. 따라서 테스트 비용과 효용을 잘 고려해서 도입해야 한다. 가장 이상적인 방식은 개발 초기에 테스트에 용이한 설계가 진행되도록 하는 것이다.
결론
- 테스트 코드는 개발에 도움이 되기 위해, 지속 가능성을 위해 필요하며 테스트 비용 대비 실익이 커야한다.
- 테스트 코드는 의존성 관리 전략을 기반으로 설계되어 기능을 테스트하되 구현이 드러나지 않도록 작성해야 한다.
후기
이번 강연을 듣고 "프론트엔드에서 테스트 코드가 왜 필요한가?"에 대한 나의 대답은 "개발을 위해서 테스트 코드 설계가 필요하다." 이다. 테스트 코드를 작성한다는 것에 초점을 맞추기 보다 테스트 코드 설계에 중심을 두는게 더 중요한 것 같다.
테스트에 용이한 설계를 하려면 제품의 레이어를 잘 나누어야 한다. 이는 자연스럽게 좋은 코드를 작성할 수 있도록 돕는다. 따라서 우리는 개발에 도움이 되는 테스트 코드를 작성할 수 있게 된다.
Q&A 시간에 나온 질문들을 봤을 때 프론트엔드 테스팅을 하지 않는 회사들이 꽤 있어 보였다. 강사님도 테스트 코드를 도입한 계기가 한 기능에 에러가 발생했을 때 겪는 리스크가 너무 크고 배포 시 장애가 자주 발생해서였다는 언급을 해주셨는데, 실무에서는 테스트 코드를 무작정 도입하기보다 테스트 비용 대비 창출할 수 있는 가치를 잘 따져서 도입하는 게 현명하다는 생각이 들었다. 하지만 아직 프론트엔드를 공부하는 학생으로서 학습을 목적으로 진행하는 프로젝트에 테스트 코드를 적용해 볼 생각이다.
좋은 코드를 작성하는 방법 중 하나가 테스팅을 위한 설계를 하는 것이라고 배웠다. 아직 초보 개발자인 나에게 제품의 레이어를 잘 나누어 좋은 설계를 한다는 것이 너무 어렵게 느껴지지만 이제는 어떻게 하는 것이 설계를 잘 하는 것인지 고민하고 공부해 볼 필요가 있다고 생각한다.