효과적으로 TDD, 리팩토링, OOP를 연습하는 방법은?

강의를 하다 보면 개발자들에게 듣는 질문 중의 하나는 “테스트 주도 개발(Test Driven Development, 이하 TDD), 리팩토링(Refactoring), 객체 지향 프로그래밍(Object Oriented Programming, 이하 OOP)을 연습하기 좋은 방법은 무엇인가요?”라는 질문을 종종 듣는다.

이 질문에 대해 지금까지의 경험을 바탕으로 답변을 정리해 봤다.

상당 수의 프로그래머는 프로그래밍을 시작할 때 프로그래밍 언어에 대한 깊이 보다는 웹과 모바일과 같은 응용 프로그래밍에서 시작한다. 시작 단계가 응용 프로그래밍인 것은 괜찮다. 하지만 다음 단계의 역량을 키우기 위해 TDD, 리팩토링, OOP를 학습하는 단계에서 어려움을 겪는다. 어려움을 겪는 가장 큰 이유는 웹, 모바일과 같은 응용 프로그램에서 TDD, 리팩토링, OOP를 연습하기 어렵기 때문이다. 응용 프로그래밍 자체를 구현하는 것도 익숙하지 않은 상태에서 난이도가 있는 또 다른 연습을 병행하는 것은 쉽지 않은 도전이다. 따라서 내가 추천하는 방법은 응용 프로그램에서 시작하는 것이 아니라 순수하게 프로그래밍 언어만으로 프로그램을 구현하는 연습을 하는 것이다.

연습하기 좋은 프로그램은?

나는 TDD, 리팩토링, OOP를 연습하기 좋은 프로그램의 세 가지 조건이 있다고 생각한다.

첫째, 게임과 같이 요구사항이 명확한 프로그램이 적합하다. 요구사항이 명확하지 않은 프로그램을 구현하다보면 TDD, 리팩토링, OOP를 연습하기 보다 명확하지 않은 요구사항을 파악하는데 시간을 허비하는 경우가 발생한다.

둘째, 의존관계(모바일 UI, 웹 UI, 데이터베이스, 외부 API와 같은 의존관계)가 없는 프로그램으로 연습할 것을 추천한다. UI나 데이터베이스와 의존관계를 가지는 코드는 테스트하기 어렵다. 시작은 의존관계가 없는 순수 프로그래밍 언어만을 활용해 연습하는 것이 좋다.

셋째, 약간은 복잡한 로직이 있는 프로그램이어야 한다. 로직이 단순한 프로그램이 적합할 수도 있지만 너무 단순하면 TDD와 OOP의 참맛을 느끼기 어렵다. 약간의 로직은 포함하고 있어야 TDD를 통해 테스트할 코드가 있고, 지속적인 리팩토링 연습이 가능하며, 객체를 추출해 역할과 책임을 분담하고 협력하는 프로그램을 구현하는 경험을 할 수 있다. 만약 요구사항이 너무 복잡하다면 요구사항을 단계별로 나누어 구현하는 것도 좋은 방법이다.

이 같은 기준으로 봤을 때 TDD, 리팩토링, OOP 연습을 시작하기 좋은 몇 가지 예를 들어보자.

  • 로또(단, UI는 콘솔)
  • 사다리 타기(단, UI는 콘솔)
  • 볼링 게임 점수판(단, UI는 콘솔)
  • 체스 게임(단, UI는 콘솔)
  • 지뢰 찾기 게임(단, UI는 콘솔)

위 예를 보면 약간의 로직을 포함하면서 요구사항이 명확한 프로그램임을 알 수 있다. 특히 게임의 경우 규칙이 명확하다는 장점이 있다. 모바일, 웹 프로그래머 역량을 쌓는다 할지라도 위와 같은 게임에서 시작하는 것도 좋은 방법이다. 시작은 콘솔 UI에서 시작해 핵심 로직 구현을 완료한 후 UI를 모바일, 웹 UI로 변경해 보거나, 데이터베이스에 데이터를 저장해 보는 접근 방식도 좋은 연습 방법이다.

위와 같은 프로그램을 통해 기본적인 TDD, 리팩토링, OOP 연습을 했다면 다음은 한 단계 난이도를 높혀 HTTP 웹 서버를 직접 구현해 보거나 프로그래밍에서 사용할 프레임워크와 라이브러리와 같은 도구를 구현해 보는 것도 좋은 경험이다.

어떻게 연습할 것인가?

연습하기 좋은 프로그램을 선택했다면 다음으로 고민할 내용은 어떻게 연습할 것인가이다. 연습 방법을 개인과 그룹으로 나눠 살펴보자.

혼자 연습하는 가장 좋은 방법은 같은 요구사항을 구현하면서 제약사항을 하나씩 추가해 나가는 것이다. 제약사항으로 사용하기 적합한 원칙은 “소트웍스 앤솔러지” 책에서 다루고 있는 객체지향 생활 체조 9가지 원칙을 추천하고 싶다. 객체지향 생활 체조 원칙에 대한 대략적인 설명은 객체지향 생활 체조 총정리에서 참고할 수 있다.

1단계 연습은 메소드(함수)를 분리하는 연습이다. 메소드를 분리하는 연습을 할 때 사용하기 적합한 원칙은 다음과 같다.

  • 규칙 1: 한 메서드에 오직 한 단계의 들여쓰기(indent)만 한다.
  • 규칙 2: else 예약어를 쓰지 않는다.
  • 9가지 원칙에 포함되어 있지는 않지만 “메소드의 라인 수를 10라인을 넘지 않는다.”와 같은 원칙을 추가하는 것도 좋다. 라인 수는 프로그래밍 언어, 자신의 도전 단계에 따라 조정해 나갈 수 있다.

메소드 분리에 대한 자신감이 생겼다면 다음 단계는 객체를 분리하는 연습이다. 객체를 분리하는 연습을 할 때 적합한 원칙은 다음과 같다.

  • 규칙 3: 모든 원시값과 문자열을 포장한다.
  • 규칙 6: 모든 엔티티를 작게 유지한다.
  • 규칙 7: 2개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다.
  • 규칙 8: 일급 콜렉션을 쓴다.

마지막 단계로 객체 지향의 참맛을 느끼고 깔끔한 코드(clean code)를 구현하기 위한 원칙을 연습하는 것에 도전한다.

  • 규칙 4: 한 줄에 점을 하나만 찍는다.
  • 규칙 5: 줄여쓰지 않는다(축약 금지).
  • 규칙 9: 게터/세터/프로퍼티를 쓰지 않는다.

이 9가지 원칙을 지키면서 프로그램을 구현하기 쉽지 않다. 하지만 이 원칙을 지키기 위한 연습을 하다보면 어느 순간 OOP라는 것이 이런 것이구나라는 대략적인 감을 잡을 수 있다. 이 원칙을 지키는 프로그램을 구현해보면 지속적인 리팩토링을 통해 구조를 변경해 나가야 한다. 지속적인 리팩토링을 위한 선수 조건은 자동하된 단위 테스트이다. 따라서 이 원칙을 지키기 위한 노력은 자연스럽게 TDD, 리팩토링, OOP를 연습할 수 있다.

내가 이 9가지 원칙으로 연습할 것을 추천하는 이유는 객체지향 설계를 다루고 있는 대부분의 책이 추상적인 이론을 다루고 있기 때문에 초보 개발자는 몇 번 도전 후에 포기하는 경우하는 경우를 자주 본다. 특히 어려운 점은 소스 코드에서 리팩토링할 부분을 찾는 것이다. 어떻게 리팩토링할 것인지는 그 다음 이슈이다. 개선할 부분을 찾지도 못하는 개발자들에게 아무리 객체지향 설계와 구현과 관련한 이론을 제시해도 무용지물이다.

객체지향 생활 체조 원칙은 추상적인 가이드가 아니라 정략적인 가이드를 제시하고 있다. 따라서 초보 개발자도 코드 중에서 리팩토링할 부분(Bad Smell이 있는 부분)이 있는 코드를 쉽게 찾을 수 있으며, 도전해 볼 수 있다. 예를 들어 “규칙 1: 한 메서드에 오직 한 단계의 들여쓰기(indent)만 한다.”는 원칙은 구체적이다. 코드 중 들여쓰기가 2 이상인 코드가 있다면 그 부분을 어떻게 리팩토링할 것인지 고민하면 된다.

좋은 원칙도 알았지만 혼자 연습하면서 기존에 자신의 스타일을 버리기는 쉽지 않다. 따라서 혼자 연습하는 것보다 그룹으로 연습할 경우 더 빠르게 성장할 수 있다. 혼자 연습하기 보다 스터디 그룹을 만들어 같이 연습할 것을 적극 추천한다.

먼저 서로 코드 리뷰해 줄 스터디 그룹(2, 3명이어도 충분)을 만든다. 앞에서 추천하는 프로그램 중의 하나를 각자 구현하고, 상호 코드 리뷰한다. 다른 사람의 코드에서 힌트를 얻거나, 피드백 받은 내용을 리팩토링한다. 상호 코드 리뷰와 리팩토링 과정을 반복하면서 코드를 개선해 나간다. 몇 개월이 지난 후 똑같은 애플리케이션을 다시 한번 구현한다. 계속해서 다른 프로그램을 구현하는 경험보다 같은 프로그램에 제약사항을 주면서 연습할 것을 추천한다.

TDD, 리팩토링, OOP 연습은 좋은 글쓰기 연습과 같다. 좋은 글을 쓰려면 좋은 글을 많이 읽고, 많이 쓰고, 많이 퇴고하는 방법 뿐이다. 특히 이 단계에서 중요한 연습은 퇴고하는 과정이다. 좋은 코드를 구현하기 위한 방법 또한 같다. 만족스러운 코드를 구현하는 순간까지 지속적인 리팩토링 과정을 거쳐야 한다.

우리는 지금까지 완벽한 설계를 통해 모든 변화에 대응할 수 있는 프로그램을 구현하기 위해 노력해 왔다. 하지만 프로그램은 생물과 같아서 모든 변화를 개발 단계에서 완벽하게 대응할 수 없다. 따라서 “요구사항은 변화할 수 밖에 없다.”는 가정하에 변화가 발생했을 때 빠르게 대응하는 연습에 집중해야 한다. 변화에 빠르게 대응하는 가장 좋은 연습은 TDD와 리팩토링이라 생각한다. 지금 바로 작은 테스트케이스 하나를 추가해 보자.

코드스쿼드 웹백엔드 마스터, 박재성
One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.