1999~2001년 EJB로 금융 시스템을 개발하는 벤처에서 일 한 적이 있다. 99년에는 Remote Debug도 안 되는 때였고, 2000~2001년 사이에 JDWP 사용할 수 있었던 것 같다. 1999년 2000년 초에는 EJB 코드를 디버깅하는 유일한 방법은 System.out.println을 코드에 추가하고, 빌드, 패키징, EJB 서버 배포하고 브라우저로 추가한 코드가 실행되도록 하여 콘솔에 메시지가 나오게 하는 것이었다. 코드 추가에서 확인 가능한 수준까지는 최소 10분 정도가 소요되었다. 엄청 비효율적인 개발 환경이었다.
2003~2004년 경에 spring을 알게 되고는 큰 충격을 겪었다. 그냥 Eclipse에서 테스트 코드를 실행할 수 있다니!!! 엄청난 충격이었다. 이로 인해 spring이 제공하는 test(integration)에 심취하여 spring을 공부하고 사용하게 되었다. Kent Beck의 "Test Driven Development: By Example"을 보고는 spring test로 기능을 구현하는 것이 TDD를 실천하는 것이라 생각했다. 여기서 좀 더 발전해서는 Chris Richardson의 "POJOs in Action"을 보며 mocking library 몇 가지를 공부하며 TDD를 익혔고 TDD를 할 수 있는 상태가 되었다고 생각했다(지금 생각하니 엄청 조급하고, 미숙한 판단이였다).
하지만 실제 사무실에서 일정에 쫓기여 개발을 할 때는 TDD가 잘 안 되는 것을 발견하게 되었다. 나도 모르게 Test에서 시작을 했다가도 쉽게 Production 코드에 묻혀서 나오지 못하고 있는 나를 발견했다. 일정이 있기 때문에 이런 상황이 되면 일정에 맞춰 기능을 구현하고 오픈을 하고, 이후에 나오는 버그, 요구사항 변경을 대응하곤 했다. 그리고 레거시가 된 코드를 변경하기 위해 테스트를 추가하려면 매우 복잡한 의존 관계로 인해 테스트를 추가하기 너무 힘든 상황을 많이 겪었다. 한두 줄 테스트하기 mocking에는 10~20줄이 필요한 상황...ㅠㅠ
Clean Coders 비디오를 팀내에 세미나 하던 것을 바탕으로 사내에서 몇 차례 Clean Code 강의를 하였다. 강의를 할 때 라이브 코딩이 효과적이라 생각하여 강의 중에 refactoring, TDD에 대한 라이브 코딩을 넣었다. 실제 강의 중에 실수 없이 진행을 하기 위해서는 거의 외우는 수준으로 연습을 해야 했다.
그리고 시간이 지나 지금은 Daum Cafe 서비스를 하고 있는데, 최근에 REST API 서버 개발을 맡아서 하는 기회가 있었다. 이때 기능의 완전성, 작업 진행 정도를 측정하기 위해 모든 기능에 대한 Integration Test를 만드는 것으로 시작했다. 모든 Integration Test가 성공하면 나는 개발을 완료한 것이었다.
spring-boot를 사용하여 REST API 서버를 만드는 것에는 테스트를 철저하게 해야 할 복잡한 로직은 거의 없었다. 따라서 대부분의 경우는 Integration Test면 충분했다.
하나의 Set과 다른 Set의 Difference를 구한다든지, URL 파싱 등 몇 가지 기능만이 테스트가 필요한 정도였다. 이때 XXXTest.java에서 조금씩 코드를 작성하고 실행시키며 작업을 하고 있는 나를 발견했다. 자연스럽게 Production 코드보다 Test 코드를 먼저 작성하고 있고, 이것이 아무 때고 실행시켜 볼 수 있어서 편안했다.
긴박한 일정으로 돌아가는 현업에서 나는 TDD를 하고 있는 것이였다.
모든 사람들이 그렇지는 않겠지만 나를 포함해서 많은 사람들이
자신이 알기 시작한 것을 할 수 있다고, 또 하기 시작한 것을 하고 있다
고 오해하는 것 같다.
내가 강의한 TDD, Refactoring 관련 강의를 들은 분들 중에 자신이 새로운 프로젝트를 하려고 하는데 TDD로 진행하겠다고 알려오시며 조언을 부탁하는 분들이 있었다. 내가 TDD를 알기 시작한 시기에는 한번 해 봐라 혹 도움이 필요하면 도와주겠다라고 답변을 했었다. 하지만 지금은 누가 TDD로 새로운 프로젝트를 처음 진행하겠다고 하면 대부분의 경우는 반대한다. 강의를 듣고 공부를 해서 알 수는 있지만 실전에 적용하려면 내가 그런 것처럼 연습하는 시기를 충분히 가져야 한다. 그래야 현업에서도 부드럽게 구사하게 된다. 연습을 충분히 해야 하게 되는 것이다.
나는 초등학생 시절 다른 많은 아이들처럼 태권도를 배웠다. 1품까지 했다. 하지만 그 시절 내가 친구들과 치고받고 싸울 때 나의 태권도 기술이 싸움에 나온 적은 없었다. 나는 그때 태권도는 싸움에 도움이 되지 않는 기술이라고 생각했었다. 하지만 지금 생각해 보니 긴박한 순간(싸움)에 내가 알고 있고, 할 수 있다고 생각한 품새가 나오지 않은 이유는 충분히 연습이 안되었기 때문이었다. 충분히 연습이 되었다면 어떠한 순간에서라도 내 품새가 나왔어야 했다.
회사에 "블리자드 박종천"씨가 오셔서 강연을 한 적이 있다. 박종천 씨는 팀 리더이신데 팀원들과 면담을 하면 대부분의 팀원들은 Visual C++를 잘하고 싶다고 한다고 한다. 그럼 박종천 씨는 그를 위해 어떠한 노력을 하고 있냐고 묻는다고 했다. 그럼 팀원들은 집에서 공부를 하고 있고, 공부한 것을 업무 시간에 적용해 보려 노력하는데 잘 안된다고 했다. 그때 박종천 씨가 팀원들에게 한 말이 "연습을 해야 한다"는 것이었다고 한다. 책을 보는 것에 끝내지 않고, 상황을 만들어서 집에서 코딩 연습을 해야 사무실에서 구사할 수 있다는 것이었다. 내가 생각하는 연습과 비슷한 의견인 것이다.
개가 훈련을 하면 두발로 걸을 수 있다. 하지만 급하면(업무 시간에 일정에 쫓기면) 나쁜 옛날 버릇(네발로 걷기)이 나온다. 정말로 늘 두발로 걸으려면 훨씬 더 많은 연습을 해야 하는 것이다(개가 꼭 두발로 걸어야 하는지는 모르겠다).
"1만 시간의 법칙"이라는 말을 가지고 누군가 한 가지를 1만 시간을 하려면 하루 4시간씩 주 5일씩 실행한다면 10년이 걸린다고 한 이야기를 들었다. 또 TDD 책을 보고 알 것은 같은데 잘 안된다, 너무 어렵다, 현실적이지 않은 것 아니냐는 말도 많이 들었다.
지금 책에서 본 것을 몇 번 해보고 안 되는 것은 당연한 일이다. 책을 보고 안 것을 실전(현업)에서 바로 사용하려고 하면서 안된다고 할 것이 아니라 연습장에서 충분히 연습을 해야 한다.
책을 보고 (간신히) 아는 것, 실험실 같은 여유 있고 좋은 환경에서 할 수 있는 것, 전쟁과 같은 현업 환경에서 하는 것
이 세 가지는 완전히 다른 것이다.