/// <summary>
/// Nomad Coder - 클린코드 챌린지 - 14~15 / 21
/// @author : CloudD
/// @last update : 2025. 06. 06.
/// @update
/// - 2025. 06. 06 : 최초 작성. (8장. 경계 ~ 9장. 단위 테스트)
/// </summary>
/// Nomad Coder - 클린코드 챌린지 - 14~15 / 21
/// @author : CloudD
/// @last update : 2025. 06. 06.
/// @update
/// - 2025. 06. 06 : 최초 작성. (8장. 경계 ~ 9장. 단위 테스트)
/// </summary>
오늘은 8장 “경계”와 9장 “단위 테스트”를 읽었습니다.
읽는 동안 인상 깊었던 내용과 기억하고 싶은 문장들을 정리해 봅니다.
8장. 경계
"Map 과 같은 경계 인터페이스를 이용할 때는 이를 이용하는 클래스나 클래스 계열 밖으로 노출되지 않도록 주의한다. Map 인스턴스를 공개 API 의 인수로 넘기거나 반환값으로 사용하지 않는다."
우리는 종종 외부 코드를 그대로 사용합니다. 패키지나 에셋을 구매하고, 오픈 소스를 가져다 쓰며, 작성자가 제공한 ‘사용법’ 문서를 참고해 그대로 적용합니다.
그러다 외부 코드가 업데이트되면, 사용 방법이 조금만 바뀌어도 우리의 코드가 제대로 동작하지 않을 때가 있습니다.
그러다 외부 코드가 업데이트되면, 사용 방법이 조금만 바뀌어도 우리의 코드가 제대로 동작하지 않을 때가 있습니다.
작가가 예시처럼 “외부 코드가 변경되더라도 우리의 코드에 영향이 미치지 않도록 작업해야 한다” 는 것을 다시 한번 숙지할 수 있었습니다.
학습 테스트 : 간단한 테스트 케이스를 작성해 외부 코드를 익히는 방법
어떤 버그가 발생했을 때, 이 버그가 우리 코드에서 발생한 버그인지 외부 코드에서 발생한 버그인지 찾느라 오랜 시간을 소모하곤 합니다. 그만큼 외부 코드를 익히기도 어렵고, 외부 코드를 통합하기도 어렵습니다.
작가는 이 지점에서 또 다른 접근을 제안합니다. 테스트 코드를 통해 통제된 환경에서 외부 API를 익히는 방식입니다.
학습 테스트라고 부르는 이 방식을 통해 외부 코드가 예상대로 도는지 검증하고, 우리 코드와 호환되는지 확인합니다. 외부 코드가 수정되고 버전이 업데이트 되어도 학습 테스트를 통해서 새로운 위험을 미리 확인할 수 있습니다.
이 테스트 방식은 비용이 거의 들지 않으며, 오히려 필요한 지식만 빠르게 확보할 수 있는 효율적인 방법입니다.
”통제가 불가능한 외부 패키지에 의존하는 대신 통제가 가능한 우리 코드에 의존하는 편이 훨씬 좋다. 자칫하면 오히려 외부 코드에 휘둘리고 만다.”
외부 코드는 결국 우리가 통제할 수 없는 영역입니다. 그 안에는 우리가 예상하지 못한 위험이 숨어 있을 수도 있습니다.
작가의 예시처럼 새로운 클래스로 감싸거나, Adapter 패턴을 사용해 우리가 원하는 방식으로 사용하면 외부 코드에 대한 의존성도 줄일 수 있을 것 같습니다. 그리고 코드 가독성도 올릴 수 있고, 외부 코드를 사용하는 일관성도 높아지며, 외부 코드가 변했을 때 우리가 변경할 코드도 줄어듭니다.
소감
외부 코드를 사용하는 것만 생각하다가 제 코드가 엉망이 되었던 경험이 있습니다. 이 책을 읽다 보면 과거의 내가 저질렀던 실수들이 하나씩 떠오릅니다.
다음 프로젝트에서 외부 코드와 통합하는 부분에 대해 더 깊게 고민하고 사용해야겠습니다. 오늘 배운 것들을 잘 활용하면 같은 실수를 하지 않을 것 같습니다.
9장. 단위 테스트
TDD 법칙 세 가지
- 실패하는 단위 테스트를 작성할 때까지 실제 코드를 작성하지 않는다.
- 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다.
- 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다.
이 세 가지 규칙을 따르면, 개발과 테스트가 약 30초 단위로 교차하면서 진행됩니다. 테스트 코드와 실제 코드가 거의 동시에 작성되는 흐름이 만들어지는 것이죠. 그렇게 계속 코드를 짜다보면, 실제 코드와 맞먹을 정도로 방대한 테스트 코드가 쌓이게 됩니다.
하지만 이렇게 방대한 테스트 코드는 심각한 관리 문제를 유발하기도 합니다. 그래서 테스트 코드 또한 실제 코드처럼 깨끗하게 유지해야 합니다. 깨끗하게 유지하지 못하면 방대해진 테스트 코드는 개발자에게 더 큰 부담감을 안겨주게 됩니다.
작가는 코드에 유연성, 유지보수성, 재사용성을 제공하는 버팀목이 단위 테스트라고 이야기 합니다. 테스트 케이스가 있으면 코드를 변경하는게 두렵지 않기 때문입니다. 테스트 케이스 없는 코드는 어떤 버그가 잠재되어 있는지 알 수 없습니다.
깨끗한 테스트 코드를 만들기 위해 중요한 것은 가독성입니다. 가독성을 높이려면 명료성, 단순성, 풍부한 표현력이 필요합니다. 테스트 코드는 최소의 표현으로 많은 것을 나타내야 하기 때문입니다.
F.I.R.S.T
- F (Fast) : 빠르게. 테스트는 빨리 돌아야 한다.
- I (Independent) : 각 테스트는 서로 의존하면 안된다. 독립적으로 동작해야 한다.
- R (Repeatable) : 테스트는 어떤 환경에서도 반복 가능해야 한다.
- S (Self-validating) : 테스트는 bool 값으로 결과를 내야 한다. 성공 아니면 실패.
- T (Timely) : 테스트는 ‘적시에’, 즉 테스트하려는 실제 코드를 구현하기 직전에 작성해야 한다.
결론
테스트 코드는 실제 코드만큼, 아니 어쩌면 더 중요할지도 모릅니다. 테스트 코드는 실제 코드의 유연성, 유지보수성, 재사용성을 보존하고 강화하기 때문입니다. 테스트 코드가 방치되어 망가지면 실제 코드도 망가집니다. 테스트 코드를 깨끗하게 유지합시다.
소감
저는 TDD를 몇 년 전에야 겨우 접하게 되었고, 아직도 익숙하지 않아 좋은 습관으로 만들기 위해 꾸준히 노력 중입니다. 이번 장을 읽으며, 내가 노련하지 못했다는 것을 많이 느꼈습니다.
TDD 법칙 세 가지와 깨끗한 테스트를 위한 다섯 가지 규칙 (F.I.R.S.T) 를 숙지하고, 더 좋은 프로그래머가 되기 위해 TDD 라는 좋은 습관을 하루 빨리 만들어야겠습니다.
TDD 법칙 세 가지와 깨끗한 테스트를 위한 다섯 가지 규칙 (F.I.R.S.T) 를 숙지하고, 더 좋은 프로그래머가 되기 위해 TDD 라는 좋은 습관을 하루 빨리 만들어야겠습니다.