이 글은 미국에서 data scientist이고 machine learning 분야 박사학위자이며 현재 senior software engineer인 유시진(가명)님이 유학을 준비 중이거나 미국에서 IT 업체에 취업을 하고자 하는 개발자들에게 도움을 주고자 글을 작성하여 저에게 보내주신 내용을 제가 정리하여 공유해드리는 글입니다. 

​조금 더 많은 분들에게 도움을 드리고자 새롭게 시작한 브런치의 매거진에도 함께 공유를 합니다. 꼭 가명으로 올려달라고 하셔서 그냥 딱 생각난 이름을 도용했으니 많은 여성분들은 오해 없으시길 바랍니다.




이 글은 미국에서 구직 중이신 분들께 도움을 드리고 싶어서 썼습니다. 제가 그동안 구직 활동을 하면서 경험했던 것들을 정리해서 말씀드리겠습니다. 즉, 제 경험을 바탕으로 한 것이니 주관도 들어갈 수 있습니다. (본 글은 지원자가 미국에서 학교를 다니는 기준으로 하겠습니다.)


미국의 채용 과정(job process)은 다음과 같습니다.


일자리 지원(Job apply) -> 초기 전화 심사(Initial Phone Screen, 채용 담당자, 선택사항) -> 온라인 평가(Online assessment, 선택사항) -> 전화 인터뷰(Phone Interview) -> 현장 인터뷰(Onsite Interview) -> 일자리 제안(Offer)


1. 일자리 지원

회사에 지원하는 방법은 여러 가지가 있지만 제일 좋은 방법은

1.1 본인의 대학에서 열리는 채용 박람회(Career Fair)에 가는 겁니다. 이력서(Resume)를 주고 채용 담당자(Recruiter) 또는 엔지니어(Engineer)와 이야기를 나눌 건데 30초 안으로 자신의 강점을 말하는 게 중요합니다. 보통 회사는 대학 채용 박람회에 올 때 며칠 안으로 인터뷰를 진행하는 경우가 많습니다. 즉, 보다 빨리 채용될 수 있습니다.

1.2 두 번째 방법은 LinkedIn입니다. LinkedIn에서 job tab으로 들어가셔서 지원을 하거나 LinkedIn에 이력서를 상시 업데이트하면 채용 담당자에게서 연락이 자주 옵니다. 또는 본인이 가고 싶어 하는 회사의 엔지니어와 connection 요청을 하시는 것도 좋은 방법입니다. 채용 담당자에게 email로 직접 본인의 이력서와 원하는 job link를 문의하는 것도 좋습니다.

1.3 가장 보편적인 방법은 회사 웹사이트에 들어가서 지원하는 겁니다. 단점은 이 중 가장 시간이 오래 소요됩니다. 이력서가 수시로 들어오기 때문에 채용 담당자가 놓치는 경우가 많습니다.

1.4 제일 중요한 점은 각 팀마다 요구하는 기술사항이 다르므로 한 회사에서도 여러 군데에 본인이 원하는 직군에 이력서를 많이 보내는 게 좋습니다.


2. 초기 전화 심사(채용 담당자, 선택사항)

말씀드렸듯이 이는 선택사항입니다. 채용 담당자가 본인이 이 역할에 잘 맞는지 더 자세히 알기 위해 엔지니어와 인터뷰 전 전화로 이 사람이 업무를 잘 수행할 수 있는가 알아보는 시간을 갖습니다. 이를 통과하면 채용 담당자가 엔지니어 팀에 이력서를 넘기고 보통 팀 매니저가 결정을 합니다. 시간은 보통 10~15분 정도가 소요됩니다. 


3. 온라인 평가(선택사항)

요즘 온라인 평가(테스트)를 채택하는 회사들이 (e.g. Yelp, Amazon) 많습니다. https://www.hackerrank.com/ 사이트를 자주 사용하고요. 문제가 주어지고 본인이 원하는 프로그램 언어(program language)를 선택하신 후 algorithm을 작성하면 자동으로 사이트에서 채점을 합니다. 주어진 시간은 20분 ~ 1시간 정도입니다. Data structure를 공부했으면 그렇게 어렵지는 않지만 한국에서만 정규 교육을 받은 분들에게는 연습이 요구됩니다. 저도 한국에서 학부를 나왔지만 미국은 algorithm 구현하는데 수업을 많이 투자하기 때문에 처음에는 어렵습니다.


4. 전화 인터뷰

아마 가장 많이 접하실 거고 가장 많이 떨어지기도 하는 테스트입니다. 크게 인터뷰는 두 가지로 분류할 수 있습니다. 30분짜리 인터뷰이면 아마 지식 혹은 경험(knowledge) 부분만 물어볼 텐데 꽤 어렵습니다. 1시간짜리 인터뷰가 제일 보편적이고요, 10분 정도 이력서 심사(resume screen)를 하고 바로 코딩(coding) 문제로 들어가거나 지식 혹은 경험(knowledge) 부분을 조금 물어볼 수 있습니다. 코딩 테스트(coding test)를 할 때는 인터뷰어가 문제를 불러주고 본인이 인터넷을 통해 코딩을 하게 되는데 Google doc 같이 실시간으로 본인의 코드를 보게 됩니다. 이 중 주의할 부분은 인터뷰어가 중점으로 두는 사항은 (1) 문제를 잘 이해했는가? (2) 어떻게 문제에 접근하는가? (틀려도 좋습니다. 과정이 중요합니다.) (3) Big O notation에 대해서 잘 이해하는가? (4) Data structure에 대해서 잘 아는가? 를 가지고 판단합니다.

코딩을 할 때는 반드시 코딩만 하지 말고 "당신이 원하는 요구사항은 input이 이럴 때 이러한 output을 원하는가"를 꼭 물어보시고, 코딩을 하면서 "나는 data structure 중 linked list를 사용하겠다. 이유는 ~~~이고 timecomplexity는 이렇게 나올 것이다. 내가 만드려고 하는 algorithm은 대충 이러한 procedure를 가질 것이다"라고 먼저 설명을 한 다음 코드를 짜야합니다. 그리고 코드를 짜면서 꼭 말을 하면서 해야 합니다. 안 그러면 인터뷰어가 이 사람이 뭐하는 건지를 모르겠죠? 말을 하면서 코드를 짜야 본인을 더욱 어필할 수 있습니다. 코딩이 끝난 다음은 디버깅(debugging)을 해야 합니다. input에 어떤 값을 넣고 본인 코드에서 어떠한 일들이 일어나고 output으로 원하는 결과가 나온다는 것을 인터뷰어에게 디버깅하면서 보여주는 게 좋습니다.


말씀드리고 싶은 것이 많지만 간략하게 정리만 해 드리는 게 목적이므로 책을 소개하고 넘어가겠습니다.

https://www.amazon.com/Cracking-Coding-Interview-Fourth-Programming/dp/145157827X/?&&-14&+interview+questions

PDF로 찾으시면 다 나오고요, 다 보실 필요는 없고(1) Arrays and Strings (2) Linked Lists (3) Stacks and Queues (4) Trees and Graphs (5) Sorting and Searching (6) Recursion 정도만 공부하시면 도움이 많이 되실 겁니다.



5. 현장 인터뷰

전화 인터뷰를 잘 보셨으면 당일 ~ 일주일 내에 채용 담당자가 채용 인터뷰 초대를 할 겁니다. 현장 인터뷰는 직접 회사에 가서 시험을 보는 겁니다. 3시간 ~ 5시간 정도 소요되고요, 그 이상을 하는 경우도 있습니다. 비행기표와 호텔비, 식사비는 보통 회사에서 모두 지원을 합니다. 인터뷰는 칠판에 코딩을 하거나 지식 혹은 경험(knowledge)에 대해서 물어보는 식입니다. 코딩은 전화 인터뷰보다 어렵고요, http://www.geeksforgeeks.org/ 또는 leetcode.com에 나오는 문제 수준입니다. 지식 혹은 경험(knowledge) 부분은 아무래도 벼락치기는 상당히 어렵습니다. 저의 경우에 MapReduce를 인터뷰어가 전혀 모른다고 가정을 한 다음 칠판에 설명을 해보라는 식이었습니다. 그리고 시스템을 어떻게 구현할 것인지 아키텍처를 그려보라고도 하고, 아키텍처가 마음에 들면 세부적인(detail) 부분을 물어봅니다. 즉, 현장 인터뷰에서는 본인의 모든 실력을 다 발휘하셔야 합니다.


6. 일자리 제안

이 모든 것을 통과하시면 합격 통지를 받으시게 됩니다.


두서없이 썼네요. 아무튼 도움이 되셨길 바랍니다.



편집자 주 1 : 기고자께서 대부분의 용어를 영문으로 작성하여 주셨으나 가급적 읽기 편하게 한국어로 바꾸었으며, 프로그래밍 용어의 경우는 그대로 영문으로 표기해 었습니다.

편집자 주 2 : knowledge의 경우는 지식이라는 뜻도 있지만 아무래도 개발자의 경험 또한 인터뷰 당시 중요하게 보는 듯하여 '지식 혹은 경험'이라고 번역하였습니다. 

저작자 표시 비영리 동일 조건 변경 허락
신고

설정

트랙백

댓글


 



번역가 : 조인석


현재 중공업 필드에서 원격 플랜트의 주기기 모니터링 및 고장 예측 관련 업무를 수행하고 있다. 인공지능, 머신러닝 기반의 다양한 알고리즘과 인 메모리 기반의 Spark와 같은 빅 데이터 플랫폼 기술에 관심이 많다.

 

원문링크


역자주 : 본 글은 Martin Fowler가 회의록 형태로 작성한 글로써, 세 화자가 나눈 대화를 1인칭 관점에서 작성한 것을, 독자 여러분의 이해와 번역 분량 축소를 위해 대화 형태로 변경하여 번역 하였습니다.

 

 

TDD는 죽었는가?

 

본 글은 Martin Fowler, Kent Beck, David Heinemeier Hansson과 함께 Test-Driven Development (TDD) TDD  소프트웨어 설계에  미치는 영향에 관하여 나눈 대화입니다.

 


어디서부터 시작되었나


우리가 서로의 관점과 경험을 이해하기 위해 대화를 시작하게 된 것은 도발적인 발언과 블로그 포스트 때문이었습니다.

 

본 대화는 David Rails 커뮤니티에 TDD Unit Testing에 대한 언짢은 감정을 드러낸 David’s RailsConf keynote 로 인해 시작되었습니다. 그는 얼마 후에 몇 개의 블로그 포스트로 이어서 그의 견해를 정리했는데, 그 중 첫 번째 포스트가 바로 “TDD 죽었다(TDD is dead)” 입니다.

 

며칠 후, 저는 후속 포스트에 대한 오탈자 내역을 보냈고, 그는 그의 발언과 블로그 포스트에 대해 내가 어떤 생각을 가지고 있는지 알고 싶다고 말하였습니다. 그 후 우리는 Skype를 통해 한 시간 동안 즐겁고 사려 깊은 토론을 하였습니다. David Kent와도 비슷한 토론을 하였고, Kent는 우리 세 명이 함께 토론을 하고 대화 내용을 공개하자고 제안하였습니다. David는 그 생각을 트위터에 올렸고, 많은 사람들이 긍정적인 반응을 보였습니다.

 

우리는 단지 30분씩 6번 정도의 가벼운 대화가 오고 갈 것이라고 생각했었지, 이 시리즈에 대해 별 다른 계획을 하지 않았습니다. 우리는 그저 서로의 경험과 관점에 대해 배우기를 원했기 때문에 이번 일을 시작하였습니다 - 실은 많은 사람들이 우리를 봐주기를 바라는 자아도취에 빠진 사람들 같았죠. 우리는 초반 에피소드에서는 질문을 거의 받지 않았습니다만, 마지막 에피소드에서는 몇 개의 질문에 답변을 주었습니다. 우리는 우리가 이 토론을 진행하는 동안 블로그와 트위터를 통해서도 토론이 지속 되는 것을 즐겼습니다.


비디오 셋업과 행아웃 시간대를 조정해 준 ThoughtWorks Wesley Clock에게 감사의 말씀을 전합니다. 저는 각 에피소드가 끝날 때 마다 토론 내용을 그저 지켜보기 보다는 읽혀지기를 바라는 마음에 회의록을 작성하였습니다.

 

1: TDD와 확신

9 May 2014 / video / audio

우리는 TDD의 흐름에 대한 가지각색의 경험들과 사람들이 TDD와 자가-테스팅 코드를 종종 혼동하는 점에 대해 이야기 하였습니다.

 

회의록

David TDD와 단위테스팅에 대한 3 가지 주요 이슈를 띄우면서 토론을 시작하였습니다: 1) TDD와 단위테스팅의 정의에 대한 혼란, 2) TDD 구조를 준수하기 위해 사용한 mock객체들로 인한 테스트로 인한 손실, 그리고 3) TDD의 붉은색/초록색/리팩토링 사이클이 그에게는 무용지물이라는 것입니다. 저는 이해를 돕기 위해 TDD 등의 기원이 뭔지 아는 게 좋겠다고 의견을 냈는데, 이는 역사를 아는 것이 유용하기 때문이었습니다. 이에 Kent TDD의 기원에 대해 설명해주었습니다. 그는 스몰톡에서 여러 테스트 방식을 실험하기 시작했고 자기 성격에 TDD가 잘 맞았다고 합니다.

 

Martin : 우리가 C3에서 처음 함께 일하기 시작한 때가 생각나는 군요. 우리는 TDD를 사용하지는 않았지만, 각 프로그래밍 에피소드는 코드와 테스트가 함께 제공되었다고 장담합니다.

 

Kent : 프로그래머들은 그들이 작성한 코드가 잘 동작하는 것에 확신을 가져야 마땅하며, TDD가 그렇게 만드는 방법 중 하나(유일하지는 않은)이죠.

 

David : 저는 프로그래머의 행복을 위한 Ruby의 설계 목적을 좋아하고, 테스트 코드를 가지기 전까지는 일이 끝나지 않았다는 개념에는 동의합니다. - 하지만 TDD와 같은 방식으로 테스트 코드를 갖는 것을 선호하지는 않습니다. 사람들은 서로 사고방식이 달라서 서로 다른 기술과 언어를 좋아한다고 생각하고 있으며, TDD를 자가-테스팅 코드에서 얻을 수 있는 확신과 TDD라는 개념이 합쳐지는 것을 좋아하지 않습니다.

 

Kent : 최근 페이스북의 해커톤에서 절반은 TDD가 가능하였으나, 절반은 그렇지 않았었죠. TDD가 가능한 코드에서는 즐겁게 작업을 하고 있다는 것을 느꼈지만, 다른 절반에서는 그렇지 못 하다는 것을 느꼈었습니다. 하지만 non-TDD 파트에서도 여전히 저는 재발(regression) 테스트와 짧은 피드백 루프를 사용하였습니다. 저는 두 스타일을 함께 쓰는 것에 대해 별 다른 문제가 없었으며, 마치 클래식 음악과 재즈 음악을 함께 연주하는 것과 같았죠. TDD는 제가 학창시절에 수학을 어떻게 배웠는지 기억하게 해주었습니다 - 항상 예제가 필요했죠.

 

David : TDD가 잘 적용하여 개발을 한적도 있지만, 대부분의 저의 작업은 TDD가 잘 적용되지 않았습니다 - 제 질문은 “TDD를 적용함으로써 생기는 희생을 기꺼이 감수하는 이유가 무엇인가?”이죠. 많은 사람들이, 특히 무거운 mock객체 생성(mocking)으로 인해 나쁜 트레이드 오프를 합니다.

 

Kent : 다음 질문에 대한 트레이드오프에 대해 얘기 해보죠: 테스트가 가능한 중간 결과를 만들어내는 것이 가치가 있는 가?  컴파일러를 예를 들어보죠, 중간 구문분석-트리가 훌륭한 테스트 지점을 만들어주고, 더 좋은 설계입니다. 하지만 mock 객체에 대한 David의 질문에는 이렇게 대답하고 싶군요. 저는 mock객체를 거의 사용하지 않으며, 테스트는 리팩토링을 더 쉽게 해주는 반면, 목 객체는 종종 리팩토링을 더 어렵게 한다는 점이 좀 걱정 됩니다.

 

Martin : 저는 서로 다른 것이 뒤 섞이는 부분에서 전문 용어로 두 가지 문제점이 있다고 생각합니다.: 1) 첫째, TDD에 대한 David의 비평은 Mock객체를 사용해야 할 적합한 케이스가 아닌데도, 모든 TDD에 무거운 Mock객체를 써야만 한다는 가정을 하고 있습니다.; 2) 둘째, 자가-테스팅 코드와 TDD에는 차이점이 있습니다. TDD는 자가-테스팅 코드를 얻기 위한 한 가지 방법입니다.

 

David : 저의 TDD에 대한 반응은 무거운 mock 객체 스타일의 TDD를 도덕적으로 해야 한다고 말하는 사람들을 보았기 때문이며, 독립적인 단위 테스트를 가능하게 하기 위하여 비효율적으로 설계한 수 많은 코드들을 봤기 때문이죠.


Martin : 미리 정해놓은 시간에 따라 본 세션을 종료하겠습니다. 다음 세션에서는 어떻게 TDD가 손실을 발생시키는지, 진짜 손실인지, 어떻게 손실 유무를 판단 할 수 있는 지에 대해 논의 하겠습니다.

더 읽을 거리

·  이번 논의를 시작하게 된 David의 대화 (RailsConf talk).

·  David의 에세이 중 TDD는 죽었다(TDD is Dead) 와 테스트-유도 설계 손실(test-induced design damage).

·  Martin Flower가 얘기하는 자가-테스팅 코드(self-testing code)TDD의 차이점

·  Martin Flower의 단위테스트의 정의(defining unit tests).

 

2: 테스트로 인한 설계 손실

16 May 2014 / video / audio

David TDD를 사용하는 것이 hexagonal rails 와 같은 것에 도달하게 한다는 것을 느꼈습니다. hexagonal rails라 함은 지나친 간접 참조(indirection)로 인한 복잡성 때문에 테스트로 인한 설계 손실이 발생하는 경우를 말합니다. Kent는 이러한 현상이 TDD로 인한 것이라기 보다는 설계 결정에 대한 품질에 의한 것이라고 생각합니다.

 

본 대화를 보기 전에 David가 염려하는 설계 손실에 대한 예제(the gist David prepared)를 먼저 보십시오. 무척 그리운 Jim Weirich* hexagonal architecture 으로의 시도에 대한 동영상(explores this approach to a hexagonal architecture)도 보는 것을 권장합니다.

* 역자주) Jim Weirich 2014 2월에 타계하신 분이어서 무척 그립다(much-missed)라는 표현이 쓰였습니다.

 

회의록

Martin : , 이 질문으로 토론을 시작해보죠. TDD가 설계 손실을 발생 시킬 수 있나요? 손실이 실제로 손실로 이어 지나요? 어떻게 설계가 손실을 입었다고 판단할 수 있나요?

 

David : 저는 이 코드 예제(the gist he posted earlier)를 통해 답을 드릴 수 있겠네요. 사람들이 수 많은 mock객체를 사용하는 TDD를 쓰기 때문에 도달하게 되는 아키텍처를 예로 들어 보겠습니다. 애플리케이션의 각 레이어는 엄격하게 분리되어 있습니다. 가령, 컨트롤러는 실제 모델, 데이터베이스, 혹은 요청/응답 사이클을 사용 없이 테스트 할 수 있습니다. 그리 구체적인 예제를 보여주지는 않았습니다만, 단독 테스트를 쉽게 만들기 위해 너무나도 많은 불필요한 간접참조와 지나친 복잡도가 필요합니다.

 

Kent테스트-유도 손실을 TDD 탓으로 돌리는 것은 마치 자동차가 옳지 않은 장소에 주차되어 있다고 해서 차를 비난 하는 것과 같습니다. David가 보여준 설계는 TDD 때문이 아니었죠, 실제 이슈는 이러한 간접참조가 경우에 따라서 모두 좋은 트릭이 될 수 있다는 것이며, 우리는 이것이 가치가 있는지 없는지에 대해 이해할 필요가 있습니다.

 

David : 그 부분에 동의하지 않습니다. TDD (혹은 자동차)에 한번 올라 타면, 매번 기괴하고도 흉물스러운 테스트를 하게끔 명확한 길로 인도하고 있어요.

 

Kent : 그 부분은 설계 결정 이죠. TDD는 설계에 점진적인 영향을 줍니다, 사람들은 그들의 테스트 커버리지율이 얼마나 되는지에 대한 사항에 대해서는 호불호가 갈리죠David에게 묻겠습니다. gist 에서 보여준 어떠한 코드들이 시스템 구조를 어렵게 만드나요? (“누군가 신경 쓰는 무언가가 눈 앞에 있다면- 그때가 바로 문제가 되는 설계를 바꾸고 싶은 때입니다.)

 

David : 코드의 크기와 코드 변경 용이성간에는 명확한 상관관계가 있습니다. 이러한 모든 간접참조는 반드시 동기화가 되어야 하며, 10 라인의 코드가 60 라인의 코드보다 이해하기도 쉽고, 변경하기도 쉽죠. 간접참조의 모든 레이어는 높은 비용을 지불해야 합니다. TDD의 붉은색/초록색/리팩토링 흐름은 무척 중독성이 강하고 (Kent는 세상에서 가장 가난한 마약 중개업자임을 밝혔습니다.), 이 중독은 사람들이 좋지 못한 결정을 하게 만듭니다.

 

Martin : 저는 그 의견에 반대합니다. 이러한 상황 (이번 사례는 Rails) TDD 때문에 발생한 것이 아니라 hexagonal architecture의 핵심인 환경으로부터의 고립에 대한 바람에 의한 것이죠.

 

David : 사람들이 고립을 원하는 이유가 바로 TDD입니다. 고립에 대한 다양한 논쟁에 대해 들어왔고, 그 중에 테스팅을 위한 고립만이 의미가 있다는 것이죠. rails 애플리케이션을 커맨드-라인 애플리케이션으로 변경하는 건 터무니 없는 일이라고 생각하며, 비슷한 사례로 인-메모리 저장소와 웹 서비스 호출은 각각의 운영상 특징이 달라서 서로 교환할 수 없는 것과 같은 이치입니다. 이런 교환 가능성에 대한 꿈이 진짜 목적은 아닙니다. - 진짜 목적은 단독 테스팅이죠.

 

Kent : -메모리와 웹 서비스를 같은 걸로 대할 수 없다는 것에 동의합니다. (여러분은 아마도 분리했다고 생각 할 수 있지만, 정말로, 정말로 아닙니다. ) 실패 케이스가 서로 다르기 때문이죠. 요소들간의 경계는 무너지게 마련입니다. 질문은요소들간의 디커플링의 정도를 알아내는 데 얼마나 많은 시간을 할애하고 싶은가?”입니다10 라인 코드 내부의 응집도와 60 라인 코드 내부의 응집도도 서로 다르죠.

 

David : 그 의견에 동의합니다만, 응집도와 결합력은 언제나 대립됩니다. 좋은 응집도를 얻기 위한 결합력 상승의 대가는 대부분 가치가 있죠.

 

Kent : 외부 의존성을 제거하기 위해 다른 방법도 존재하며, 컴파일러와 같이 중간 결과를 활용 할 수도 있습니다. 설계 통찰이 필요한 간접참조는 테스트 하기가 어렵습니다만, 대부분 테스트 가능성을 높여주는 더 나은 설계를 하게 만드는 통찰을 찾는 것이 유용합니다.

 

David : 테스팅이 더 나은 설계를 만들어낼 수 있다는 것에는 동의합니다만, 저의 경험상 그렇지 못 한 경우도 잦았으며, 테스트 하기에는 좋지 않은 설계였습니다.

 

Kent : David 는 스스로에 대한 확신이 부족하군요, 오늘은 통찰을 볼 수 없을지도 모르겠습니다. 그러는 동안에도 앞으로 나아가기 위해 노력해야만 하고요. 하지만 당신의 낙관적인 시각 덕분에 우연히 나마 그러한 통찰들을 찾게 될 것입니다.

 

David : 저는 이런 상황을신앙적인 TDD”라 생각합니다 - 이러한 감정을 종종 느꼈습니다만, 존재하지 않는 이상적인 해결책을 찾지 못 할 때 빠지는 우울한 루프 안에 꼼짝없이 갇혀버렸었죠.

 

Kent : David TDD에 관해서 얘기하고 있지 않고 일반적인 소프트웨어 설계에 관하여 이야기하고 있군요, 당신의 문제는 TDD 때문이 아니라 어떻게 피드백을 받을 수 있느냐에 관한 문제라고 명확하게 말할 수 있습니다. 소프트웨어 설계에 관해 생각 해 봅시다. 좋은 설계 통찰로 인하여 얻을 수 있는 이득은 무척이나 크죠. 이러한 통찰을 얻는 다는 것은 당신의 작업 흐름에 관한 것이 아니라, 언제 일하고 언제 쉬고, 다른 장소로부터의 영향도를 파악하고 다른 사람들과 협업하는 방식에 대해 알아가는 것과 같습니다.

 

우리는 다음 번 주제를 통해 프로그래밍 중에 어떻게 피드백을 찾아낼 수 있는 지에 관한 트레이드오프에 관해 이야기 해보자고 말하면서 이번 세션을 마무리 하였습니다.

 

더 읽을 거리

·  David의 염려하는 설계 손실에 대한 예제(David's gist). gist Jim Weirich에 의한 대화(a talk by Jim Weirich)를 통해 주어진 hexagonal Rails 아키텍처의 탐구에 기초를 두고 있음.

·  David 의 블로그 포스트 중 테스트-유도 설계 손실의 문제점에 대한 소개(introducing the problem of test-induced design damage).

·  "hexagonal architecture" 라는 용어를 만든 Alistair Cockburn의 글(originally coined by Alistair Cockburn), “포트와 어댑터로도 소수 알려져 있음.

·  hexagonal Rails 아키텍처의 출현과 이를 사용하는데 있어서의 트레이드오프에 대한 Martin Flower의 글 (the nature of a hexagonal Rails architecture and trade-offs around using it).

 

3: 피드백과 QA

20 May 2014 / video / audio

우리는 프로그램을 하는 동안 피드백을 받고 QA로써 개발자에게 피드백을 주는 다양한 방법에 대해 토론하였습니다.

 

회의록

Kent : TDD를 수반하는 의사결정은 트레이드오프에 관한 것입니다.  “어떤 이상적인 세계에서는 우리의 프로그래밍 결정에 대하여 즉각적이고 틀림없는 피드백을 받기도 합니다.” … “내가 만든 모든 코드는 배포할 준비가 되었다면, 그 즉시 배포합니다.” 하지만 이러한 이상적인 상황은 현재 불가능하기 때문에, 질문은 바로이런 이상에서부터 얼마나 멀리 떨어져 있는가?” 라는 것이죠. 트레이드오프에 대한 여러 가지 제약 사항들을 나열해 보겠습니다.

·  빈번도: 얼마나 빨리 피드백을 받고 싶어 하나?

·  충실도: 얼마나 정확한 붉은색/초록색 신호를 원하나?

·  오버헤드: 얼마나 지불할 준비가 되어 있나?

·  수명: 이 소프트웨어의 라이프사이클은 어떤가? 시간과의 개연성이 얼마나 되는 가?

4개가 우리가 비교해 볼 필요가 있다고 생각하는 제약사항들입니다. 우리는 서로 동의하기 위해 이 행아웃에 참여하고 있는 것이 아닙니다 - 제 개인적인 목적은 단지 나의 아이디어를 건설적인 방식에서 멀찌감치 몰아내기 위해 준비 되어진 사람들에게 나의 의견을 명확하게 전달함으로써 서로의 트레이오프들에 대해 이해하는 것입니다.

 

Martin : 우리가 피드백을 받기 위해 살펴봐야 할 3가지에 대해 강조하고 싶습니다.

·  소프트웨어가 사용자에게 유용한 무언가를 하고 있나? 급여 계산과 같은 경우에는 테스트가 도움이 되지만, html 렌더링과 같은 경우에는 도움이 되지 않습니다.

·   내가 무언가를 망가뜨렸나? “이 부분에서 만큼은 자가-테스팅 코드는 마치 구세주이죠.” 저는 적어도 한번쯤은 모든 테스트가 실패하는 것을 보고 싶어요.

·  나의 코드-기반이 건강한가? 건강하다면 저는 빠르게 빌드를 계속 할 수 있습니다. 이 부분은 당신의 코드를 누가 인수 할지 명확하지 않을 때 더욱 까다로울 수 있습니다.

 

David : QA를 쓸모 없게 만드는데 TDD가 한 몫 했다는 주제를 제시하고 싶습니다. 많은 회사가 TDD를 택하고 QA을 없앴고, Basecamp 2년 전까지만 하더라도 QA가 없었습니다. 저는 TDD가 프로그래머들이나는 QA가 없다는 것에 대해 무척 자랑스러워라고 생각하게 만들었다고 생각하고 있었습니다. 오래된 모델이 제 기능을 동작하고 있지 못하고 있는 동안에, 시계 추는 너무나도 멀리 흔들리고 있었죠: “저는 당신이 물리적인 품질에 관한 어떤 작업도 수행 할 수 없다고 생각하며, 당신이 아닌 누군가가 테스트 하지 않는 한, 훌륭한 소프트웨어를 만들 수 없을 것이라고 생각합니다.” 저는 QA가 팀에 합류하는 것이 얼마나 강력한 힘을 발휘하는 지 보았기 때문에, 이러한 상황이 실망스러웠습니다.

 

David : 다른 이슈는 트레이드오프에 대해서 이해하려면 비용에 대해 반드시 이해해야 하고, TDD에 대한 모든 이야기는 TDD로 인한 이득에 관한 이야기이라는 것이죠. 이 비용을 고려 하지 않는 것 때문에, 사람들은 테스트로 인한 손실이 있다는 것을 충분히 이해하지 못하는 겁니다. 신뢰성에 대한 비용을 생각해봅시다: 99%에서 99.999%로 가는 것은 99%에 머무르는 것보다 기하급수적으로 많은 비용을 필요로 합니다. 높은 신뢰성은 우주 왕복선이나 레이스의 선두주자들에게나 중요한 이야기지, 실험적인 웹 사이트에게는 필요가 없습니다. 운영환경에서 사용하는 코드는 테스트 코드 없이 작성하지 않는 다는 규칙과 시스템의 중요성과는 상관관계가 없다고 봐야 합니다. (역자주: 시스템이 중요하지 않다고 해서 운영환경의 소스 코드를 테스트 코드 없이 작동해도 된다라는 건 옳지 않다는 뜻이네요.)

 

Kent : QA 에 관한 이슈로 돌아가보죠, QA와의 오래된 관계는 제대로 동작하지 않는 다고 생각합니다. 제 사무실의 페이스북에서 들고 나온 포스터에는페이스북에서는 어떠한 것도 다른 누간가의 문제점이 될 수 없다.”라고 말하고 있으며, 페이스북이 회사의 규모에 비해서 이 말을 잘 지키고 있다고 느끼고 있습니다. 페이스북은 최근까지도 QA가 없었으며 프로그래머는 QA에 대한 책임까지 가지고 있었습니다.  “그럼 무엇과 비교하실 건가요?” 라고 묻는 다면, 효과적인 QA를 가지는 것이 QA가 없는 것 보다는 낫지만, 과거의 제대로 동작하지 않는 관계라면 QA가 없는 것이 낫다고 생각합니다.

 

Martin : ThoughtWorks에서 일할 때 항상 QA가 있었습니다. 저도 역시 90년대와 비교해보면 잘 동작하지 않던 대립적인 관계도 사라졌고, 수작업으로 진행하던 스크립트 기반 테스트도 사라졌다는 것을 느끼고 있습니다. 그리고 스타트업들이 QA 없이 운영할 수 있는 건 그들 마음 이죠.

 

David : 초기 스피드를 위하여 심사숙고한 QA와의 트레이드오프에 대해서는 동의합니다만, 어떤 경우에는 프로그래머의 테스트가 지나칠 정도도 있어 왔으며, 실험적인 테스팅에서 어떠한 가치도 찾지 못 하기도 합니다. 만약 개발자들이 QA 없이도 충분히 높은 품질의 소프트웨어를 만들 수 있다면, 당신의 테스트들은 모두 초록색이겠지만, 운영환경에서의 사용자들은 당신이 예상하지 않았던 행동을 하게 마련이라는 거죠. 무엇보다 나쁜 것은 개발자들이 고객 서비스의 일부분이 아니라는 점입니다. 많은 프로그래머들은 단조롭고 지루하다는 이유로 전화 응대를 하고 싶어 하지 않습니다만, 그 또한 피드백 루프죠. 초록색 테스트를 통과한 코드는 당신이 원하는 범위 내에서는 안정기에 접어들었다고 할 수도 있습니다.

 

Kent : 이 제약사항에 관하여 다시 생각하기 위해 초록색 바 안에 빨간색 픽셀 몇 개를 심어야만 한다고 생각합니다. “전화 응대는 당신이 작성하지 않은 테스트를 가르쳐주기 위한 피드백 루프입니다.” 페이스북 프로그래머들은 전화응대를 해야만 하며, 모두들 그것에 대해 불평하고 있지만, 어느 누구도 전화응대를 피할 수는 없습니다. 당신이 더 이상 실수를 저지르지 않는다고 생각하는 그 순간, 그 것이 바로 실수이며, 당신은 성장 할 수 없습니다. 결국세상은 당신이 아무것도 망치지 않은 척 하게 내버려두지 않을 것입니다.” 저는 이른 새벽 2시에 받은 전화 한 통을 통해 꽤 값진 경험을 하였습니다.

 

Martin : 우리가 테스팅 비용에 관하여 더 이상 얘기하지 않는 것을 확인하고, 이번 세션을 마무리하였고, 다음 기회에 다시 한번 살펴 보자고 제안하였습니다. 또한 같은 주제로 Mike Bland가 제 사이트에 올린 을 보는 것도 좋을 것이라고 언급하였습니다.

 

4: 테스팅 비용

27 May 2014 / video / audio

우리는 테스팅과 TDD에 대한 덜 긍정적인 부분에 대해 토론하였습니다: 당신은 테스팅을 너무 지치게 하고 있지 않은가, 그리고 기능적인 코드보다 테스트에 더 많은 가치를 부여 하는 것이 팀에 문제가 되고 있는가?

 

회의록

David : 트레이드오프에 대해서 얘기하기 위해서는, 결점에 대해서 명확하게 이해하고 있어야만 합니다. 만약 결점이 없다면 트레이드오프도 없기 때문이죠. 저는 TDD가 어떤 것을 강제로 하라고 하지는 않지만, 명확한 방향으로 부추기고는 있습니다. 지나친 테스팅을 첫 번째 이슈로 얘기해보죠. 여러분은 결함 테스트가 없는 코드를 작성하면 안 된다는 얘기를 자주 듣죠, 처음에는 괜찮아 보입니다만, 지나친 테스팅을 하게 만들기도 합니다. 가령, 운영 코드의 매 라인을 위한 4 라인짜리 테스트 코드가 있는 것과 같은 것을 말하죠. 이 말은 당신이 무언가를 변경하려고 하면, 변경할 코드가 더 많아 진다는 뜻 입니다.

 

Kent : 사람들은 테스트 코드를 작성하기 위한 비용을 지불하는 것이 아니라, 충분히 확신을 하기 위해 작성하고 있는 것입니다.

 

David : 그럼 여러분(Kent Martin)은 운영 코드의 각 라인을 작성하기 전에 매번 테스트 코드를 작성하시나요?

 

Kent : 상황에 따라 다르죠, 그리고 이 대답은 흥미로운 질문들에 대한 모든 나의 답변의 시작부분과 같다고 할 수 있습니다. JUnit을 사용하는 운영 코드는 엄격하게 테스트 코드를 먼저 작성하게 되며, 이러한 과정 속에서 모습이 들어나는 자신의 모습(역자주 : 운영코드)으로 인해 무척이나 행복해합니다 - 그렇기 때문에 저는 TDD를 사용할 때 항상 지나친 테스팅을 하게 된다고 생각하지 않습니다.

 

Herb Derby : 델타 커버리지 개념에 대해 언급하고 싶군요 - 이러한 테스트는 중복되지 않는 비율이 얼마나 되나요? 제로 델타 커버리지 테스트는 그들이 의사소통 목적과 같은 것을 제공하지 않는 한, 제거되어야만 합니다. 저는 자주 system-y 테스트를 작성하고, 구현을 하며, 리팩토링을 거치고 나면, 결국 초기 테스트는 버려지게 되고 맙니다. 많은 사람들이 테스트들을 버리는 것에 대해 흥분하지만, 그들이 당신에게 아무것도 사주지 않는다면 당신도 흥분하게 될 것이라고도 했죠. 같은 것이 여러 방식으로 테스트 된다면, 그것이 바로 결합(커플링)이며 결합 비용이 발생합니다.

 

Martin : 지나친 테스트 코드는 분명 존재합니다, ThoughtWorks는 강한 테스팅 문화를 가지고 있기 때문에, ThoughtWorks에서도 발생하죠.  적정 수준의 테스트의 양을 정의하는 건 무척 어렵습니다. 어떨 때는 지나칠 때도 있고, 어떨 때는 적을 때도 있죠. 저는 가끔 지나치게 테스트하기를 원하며, 테스트가 너무 방대하지 않는 한 그렇게 하는 것에 있어 걱정하지 않습니다. 모든 라인의 코드를 테스트 하느냐라는 포인트에 대해서는 제가 다음 질문을 드리죠: “제가 이 코드를 망치는 것이 테스트를 실패하게 만드는 건가요?” 저는 때때로 고의로 코드 라인을 주석처리 하거나 조건을 반대로 바꾸고 나서 실패할 것이 확신한 테스트를 돌려보기도 합니다. 저의 반대쪽 머리의 (Kent로부터 온) 테스트는 그저 실패할 수도 있는 것들을 테스트하는 것입니다. 라이브러리들은 (정말 불안정하지 않는 한) 잘 동작한다고 가정합니다. 제가 라이브러리를 잘 못 사용하고 있는 지와 실수의 결과가 얼마나 심각한지 묻고 싶군요.

 

Kent : 테스트 코드 라인수와 운영 코드 라인수와의 비율은 믿기 어렵습니다. 저의 기억에 남는 경험은 Christopher Glaeser가 컴파일러를 작성하는 것을 보는 것이었으며, 그는 컴파일러 코드의 각 라인을 위한 4라인의 테스트 코드를 가지고 있었습니다. 간단한 시스템은 더욱 낮은 비율을 나타내겠죠.

 

David : 코드의 한 라인을 임시 주석 처리(comment out) 한 것이 눈에 띌 정도면 테스트 커버리지율이 100%라는 것을 의미합니다. 임시 주석 처리로 인한 소스 쪼개기가 어떤 경우에 값지다고 할 수 있는 지 생각해 봅시다. Rails의 선언적 주석문은 가치 있는 테스팅을 위하여 소스를 충분히 쪼개지 않습니다. 그렇기 때문에 저는 100% 이하의 커버리지율에도 충분히 만족합니다.

 

Martin : 만약 당신이 코드를 자신 있게 변경 할 수 없다면, 당신의 테스트는 (혹은 좋은 테스트) 충분하지 못 하다는 것을 의미합니다. 지나치다는 신호는 당신이 코드를 변경할 때, 코드를 변경하는 것 보다 테스트를 변경하는 노력이 더 많이 든다고 느낄 때를 말하는 거죠. 여러분은 Goldilocks zone* 안에 들어가길 원합니다만, 당신 혹은 당신의 팀이 어떠한 실수를 하는 경향이 있는 지와 누가 문제를 일으키지 않는 지에 대해 알아가는 경험과 함께 들어갈 수 있는 거죠. 저는 제가 확신이 없을 때코드의 한 라인을 임시 주석 처리 해도 되나라는 시도를 하는 것을 좋아하며, 그 시도가 시발점이지만, 그 환경에서 더 일하다 보면 더 나은 발견을 하게 됩니다. 

* 역자주> Goldilocks zone은 태양계에서 생명체가 살기 적합한 영역을 말합니다.


David : 이러한 튜닝은 잘 모르는 팀과 함께 코드를 제어하고 더 많은 테스트가 필요로 하는 컨설팅 팀과 상대적으로 더 안정적인 운영팀에게는 서로 다른 것으로 느껴지는 군요.

 

Kent : 테스트 우선 원칙에 대해 배운 것이 좋았으며, 그건 마치 까다로운 개발을 위한 4륜자동차의 저단 기어와 비슷한 거죠.

 

David : 다음 이슈로 넘어가보죠: 많은 사람들이 코드보다 문서화가 더 중요하다고 생각하곤 합니다. 지금 제가 걱정하는 것은 사람들이 기능 코드보다 테스트를 더 중요하게 생각한다는 것이죠. 이 부분은 TDD 사이클의 리팩토링 파트가 강조하는 부분과 연결이 됩니다. 이러한 모든 것들이 코드를 리팩토링하고 깨끗하게 유지 하는 것에 충분하지도 않은 에너지를 쏟아 붓게 만듭니다.

 

Kent : 운영 코드임에도 불구하고 버려졌지만, 테스트를 계속하고 재구현한 사례가 있습니다. 저는 새로운 코드가 잘 동작하고 있다는 것을 알려주는 테스트를 무척이나 좋아합니다.

 

David : 한 가지 흥미로운 질문이 떠오르는 군요: 꽤 많은 코드를 버리고 테스트 코드를 유지한 적이 있나요? 아니면 반대 상황이 있었나요? 각 상황에 맞는 답을 주셨으면 합니다.

 

Kent : 저는 테스트 코드를 읽을 때 코드가 어떻게 동작하는 지 쉽게 이해할 수 있습니다. 둘 중에 무엇이 더 중요하다고 생각하지는 않습니다 - 가장 중요한 포인트는 테스트 코드와 기능 코드가 서로 맞지 않으면, 그 부분에 에러가 있다는 것을 더블 체크 하는 것입니다. 저도 때로는 테스트 코드가 종료를 의미하는 것이기 때문에, 팀들이 사용자를 지원하는 것 보다 테스팅 환경에 더 많은 에너지를 쓰는 좋지 않은 상황을 만들기에 David의 의견에 동의합니다. 저는 코드가 완성되었을 때의 쾌감도 즐기지만, 가장 스릴이 넘치는 부분은 새로운 기능을 추가 했을 때죠, 속임수로 보일 수도 있지만, 코드 작성이 쉬워집니다. 이 모든 것들이 클린 코드에 의한 것입니다만, 코드를 깨끗하게 유지하는 거 하고, 쾌감을 느끼는 것 하곤 차이가 있습니다.


Kent Jeff Eastman를 비유로 설명하였습니다. 지문으로 담기에는 한계가 있군요. 그는 큰 설계 단순화를 설명하기 시작했습니다. 그는 신규 테스트가 동작하게 하는 것의 가치를 설명하는 것은 쉬우나, 설계를 깨끗하게 유지하는 것의 가치를 설명하기에는 어렵다고 말하였습니다.

 

David : 사람들은 정량적인 것들에 집중하기 마련이지만, 설계 품질을 숫자로 표현 할 수 없습니다 - 해서 사람들은 테스트 속도, 테스트 커버리지율, 테스트 비율 등에 대한 것 들은 우선순위에서 밀려나는 거죠. 이러한 것들은 꿀 팁과 같죠, 우리는 이러한 것들의 싸이렌 소리에 귀 기울일 필요가 있습니다. 운영 코드보다 테스팅 환경에 더 신경 쓰게 되는 것에 대하여 생각할 필요가 있습니다. 이는 오로지 비기술적인 이해당사자들에게만 유용한 지표가 될 수 있습니다. TDD를 파는 것이 중요하곤 했지만, TDD는 모든 것을 정복했으며, 우리는 TDD의 단점에 대해 살펴 볼 필요가 있습니다.

 

Martin : 저는 TDD가 지배적인 위치에 있었다고 생각하지 않습니다. 아직도 TDD를 적용하려고 하는 곳도 많거든요.

 

더 읽을 거리

·  측정을 잘못하는 경우의 토픽을 위해서 Pat Kua의 다음 글을 읽어 보세요. an appropriate use of metrics.

·   Martin Flower의 테스트 커버리지율의 사용법과 잘못된 사용법(use and misuse of test coverage).

 

5: Q&A

4 June 2014 / video / audio

우리는 시청자들의 질문에 답변을 주었습니다: TDD의 오픈소스 예제는 무엇인가, 우리가 TDD를 사용하는 방법을 변경하게 만드는 변화가 무엇인가, TDD를 경험하지 못한 개발자에게 TDD를 잘 적용하게 하는 방법은 무엇인가. 우리는 TDD의 건제함에 대한 관점에 대해 정리하면서 마무리 하였습니다.

 

회의록

Martin : 시청자들이 올려 놓은 질문 중 일부에 답변을 드리겠습니다. David Mike Harris “TDD를 활용한 오픈소스 프로젝트는 어떤 것이 있으며, 테스트-유도 설계 손실 혹은 TDD를 잘 활용한 사례가 있는가라는 질문에 답변을 드리는 걸로 본 세션을 시작하겠습니다.

 

David : 좋은 사례를 찾기 쉽지 않으며, 이 또한 논의 해볼만한 문제입니다. 우리에게는 일반적인 상황의 좋은 애플리케이션 사례가 없습니다. 왜냐하면 오픈소스 협력자들은 대개 개인적인 애플리케이션과 오픈소스 공통 프레임워크, 라이브러리들을 대상으로 작업하기 때문입니다. 다른 관점에서 이 논의의 결론을 내자면, 어떤 것이 실제로 의견충돌이 발생하는 것 보다 더 많은 의견충돌을 만들게 하는가에 대한 답이 필요합니다. 사람들은 철학적인 원칙보다는 실제 코드를 가지고 옵니다. 우리의 코드 예제는 사람들이 실제로 작업하고 있는 것에 비해서 그다지 중요하지 않습니다. 해서 당신은 설계 손실 설명을 위해 사용한 Jim Weirich의 예제를 위한 PT자료로 사람들을 이해해야만 합니다. 좋은 Rails 코드는 책에서 보여주는 표준 테스팅 방안에서 찾아 볼 수 있습니다.

 

Martin : 실제 코드를 이해하기 위해서는 많은 노력이 필요합니다. 저도 저희 팀의 코드 기반을 파고 들어가곤 합니다만, 무척 시간이 많이 걸리며, 팀과 일하는 경우 모두 같은 수준으로 이해하지 못합니다.

 

Kent : JUnit TDD를 엄격하게 사용하는 프로젝트 예제이며 잘 동작합니다. 하지만 이 논의의 좋은 예제로 들 수는 없겠군요. 왜냐하면 JUnit TDD를 위한 최고의 방안을 명확한 인터페이스를 통해 제공하기 때문입니다. 우리는 상이한 종류의 애플리케이션에 관해 얘기 하고 있습니다. 만약, 좋은 예제를 가지고 계신 분이 계시면, 꼭 내용을 공유해주시기 바랍니다.

 

David : 우리는 프로그래밍을 과학으로 대할 수 없습니다 - 우리는 기술을 객관적으로 평가 할 수 없습니다. 가치가 없는 논의를 하고 있다는 뜻은 아닙니다. 우리는 완전한 답을 얻을 수 없으며, 이치에 맞게 만드는 작업은 여러분의 몫입니다.

 

Kent : 동의합니다. 우리는 실험을 복제할 수는 없습니다만, 과학적인 사고방식으로 개개인이 바라볼 수는 있습니다. 우리는 우리 스스로 경험에 기반하여 시도해볼 수는 있겠습니다만, 일반적인 답변을 드릴 수는 없겠군요.

 

Martin : 다음 질문으로 넘어가겠습니다. Graham Lee님이 주신 질문입니다: Kent Martin에게 묻겠습니다. 소프트웨어 작성시 TDD를 사용하지 못 하게 하는 혹은 쓸모 없게 만드는 것은 무엇일까요? David에게는 이런 질문을 드리고 싶군요. 어떤 것이 TDD가 유용하게 동작하게 할 수 있을까요?

 

Kent : 제 포스트(RIP TDD post)를 한번 보시죠. TDD는 여러 문제점들을 해결하며, 확신을 갖기 시작하게 만듭니다. 또한 TDD는 문제점들을 작은 단위로 쪼개지게 해주며, 한번에 일반적인 문제를 해결하는 것 없이 구체적인 문제점을 걸고 넘어집니다. 저는 TDD가 단지 어렵다는 이유로 포기할 생각이 없습니다.

 

Martin : 저는 TDD를 쓸모 없게 만드는 것에 대해서 이야기 하기 보다는 다른 관점에서 TDD의 적용 가능성에 대해 말씀 드리겠습니다저는 훌륭한 설계를 우연히 접하였을 때 차분한 '신속한 느긋함'을 이용하여 기계적인 방식으로 TDD를 따르고 있습니다. 근래 대부분의 저의 프로그래밍은 제 웹 사이트 툴체인이며, 조금씩 진전이 있을 때마다 훌륭한 회귀 테스트가 딸려 있죠 - 저는 TDD 적용가능성을 찾지 못하였습니다. 하지만 제가 infodeck 코드를 빌드할 때면, TDD가 효과적이었던 애플리케이션이 있었습니다. 어떤 애플리케이션에서는 TDD가 무척 잘 들어 맞지만, 아닌 경우도 있습니다. 그리고 사람들은 그들의 성격을 애플리케이션에 반영하죠.

 

David : 제 경험도 비슷합니다. 저는 TDD를 통한 테스팅이 좋았고 모든 곳에 적용하려고 노력하였습니다만, MVC 웹 애플리케이션의 많은 영역에서는 TDD가 잘 맞지 않다는 것을 서서히 깨닫게 되었습니다. 이는 TDD가 어떤 상황에 대하여 효과적이 않다고 말씀 드리는 것이 아니고, 단지 제 작업의 작은 부분에 이런 사례가 있었다는 것입니다. 하지만 TDD를 사용하지 않게 되는 것이 자기-테스트 코드를 포기 하고 싶다는 것은 아닙니다 - 이것이 항상 저에게는TDD의 가치라고 생각합니다.

 

Martin : 제가 정확하게 TDD(혹은 어떤 기술)를 받아 들이는 방법을 알려드리겠습니다. 시험해 보고, 남용한 다음에, 여러분에게 잘 들어맞는 방식에 안착하세요. 그리고 조금 더 깊이 들여다보세요. “TDD는 자가-테스팅 코드를 향한 마약의 출입구입니다.”

 

Kent : 사람들은 결국 이러한 프로세스를 수행하는 작업 흐름을 가지게 됩니다. 제가 경험한 TDD David의 경험과는 다릅니다. 제가 개발할 때 어려운 부분을 만나게 되면, 저는 그 부분을 간단하게 만드는 명확한 체계를 가진 객체에 대한 아이디어를 얻습니다. TDD는 그러한 아이디어, 시도 그리고 API의 사용 예제와 구현 방법에 대한 피드백을 신속하게 가져다 주는 메커니즘을 제공합니다. 물론, TDD가 잘 맞지 않는 경우도 있죠. 그런 경우 command-R이 피드백을 받기 위한 좋은 방법인 것을 찾았습니다만, 그러한 순간에도 단순한 객체를 만들고 TDD를 시도하는 것을 원하기도 합니다.

 

Martin : Tudor Pavel님의 질문을 한번 볼까요? "경험이 적은 개발자들에게 TDD는 어떻게 동작합니까?" TDD는 사람들에게 작은 조각에 집중할 수 있게 강요하며, 인터페이스를 구현체로부터 분리하게 도와줍니다.  TDD가 훌륭한 결과를 보장해주지는 않습니다. 왜냐하면 경험 없이는 좋은 설계를 할 수 없기 때문이죠. 대개 경험이 적은 사람들이 TDD를 하는 경우에는 리팩토링을 충분히 하지 않으며, 적당히 최적화된 설계를 하게 마련입니다. 여러분은 경험이 없는 개발자의 산출물과 경험이 있는 개발자의 산출물은 비교할 수 없습니다. 반드시 경험이 없는 개발자가 TDD 없이 작업한 결과물과 비교 해야만 합니다. 비록 측정할 수는 없지만, 이로울 것으로 보이며, 나중에 리팩토링을 통해서 개선하는 것 보다 쉽게 자가 테스트 코드를 만듭니다. 해서, TDD는 여러분에게 좋은 시작점을 제공합니다.

 

David : TDD로부터 얻은 가치에 대해 말씀 드리겠습니다. TDD를 시작할 때, TDD는 훌륭한 학습도구였습니다. (하지만 이번 논의는 충분히 나아가고 있지 않는 듯 하군요.) 저는 사람들이 신규 인력들에게 그대로 따르지 않을지라도, 간단하고도, 직관적이고, 겉만 번지르르한 조언을 달라고 말할 때마다 회의적이었습니다. 이는 제가 가르치는 것에 대한 확신이 부족하다는 것을 보여줍니다.

 

Martin : 저는 그런 독단적인 내용에 대해서는 동의하지 않습니다. 저는 제가 설명하고 있는 것에 반하는 논쟁거리를 찾지 못할 때 의심을 갖게 됩니다. 여하튼, 우리는 신규 인력에게 소개 세션을 반복하고 있습니다. 어떤 사람들은 기초를 반복하는 것일 싫어하거든요.

 

David : 바로 이러한 것들 때문에 우리가 지금 대화를 나누고 있다고 생각합니다. 사람들은 그들의 의견을 기초에 더했다고 말하곤 합니다만, 10년 뒤에는 시작지점 보다 한참이나 내려오게 될 것이며, 좋은 장소에는 있지 못하게 됩니다. 여러분은 리셋 버튼을 누를 필요가 있으며, 대충 무마 하는 것처럼 보이지만, 효율적입니다. 제가 TDD가 죽었다고 말할 때, 저는 현재의 변화에 대해 언급하였습니다 - 우리는 첫 번째 원칙으로 돌아가야만 합니다.

 

Kent : 제가 David의 원래의 키노트에 대한 본능적인 반응을 보인 것이 바로 그 부분입니다. 프로그래머들은 빈번하게 같은 작업을 반복하고, 코드를 지나치게 복잡하게 만들며, 제대로 동작하지 않는 시스템과 씨름을 할 것입니다. 저는 첫 번째 원칙으로 돌아가자는 것에 동의하지만, 지난 10년간 프로그램에 관한 사람들의 기대감의 발전을 잃고 싶지는 않습니다여러분은 반드시 확신을 느낄 수 있어야 하며, 전진하고 있다고 주장 할 수 있어야 하고, 생산적이고 기술적으로 협업 할 수 있어야 합니다. 저는 경력이 시작할 무렵에는 무척 부족하였습니다만, 이제서야 모든 일을 스스로 하고 있다고 느끼고 있습니다.

 

David : TDD, XP 그리고 Ruby는 동시에 우리에게 다가왔습니다. 사람들은 프로그램은 즐거워야만 한다는 말에 비웃었지만, 저는 Rails를 개발하면서 그 말을 계속하고 싶었어요. 제 생각에는 Ruby 세상에서는 그 행복이 찾아온 듯 하군요 - 그 말이 이겼습니다 - 바로 애자일을 가졌기 때문이죠.

 

Martin : 저는 애자일이 이겼다는 것에는 동의할 수 없습니다 - 애자일이라는 라벨이 이긴거죠. 그러나 많은 사람들이 애자일을 한다고 말하지만, 실제로 하고 있지는 않아요. 저는 이런 전형적인 현상을 나타내는 프로세스를 의미적인 유포(semantic diffusion)라고 말합니다. 큰 승리는 오늘날 우리가 애자일을 고객과 공개적으로 할 수 있게 된 점이죠.

 

David : 이러한 재시도 문제점은 다른 것들도 있어요 - 10년 뒤에 여러분은 싫은 것이 많아 질겁니다. 2 가지 맛으로만 시작하였던 Pinkberry를 예로 들어볼까요? 지금은 다른 아이스크림들과 마찬가지로 복잡한 범위의 맛들을 가지고 있죠 - "대부분의 사람들은 좋은 아이디어를 혼자 내버려두지 않으려고 하죠"

 

Kent : 저는 David가 경험한 TDD를 여태 본적이 없어요. 저는 언제나 첫 번째 원칙으로부터 TDD를 적용해왔으니까요. 하지만, TDD에 붙어 있는 따개비들을 떼어내야 한다고 주의를 준 David에게 감사를 표합니다.


David : Rails에서 비슷한 이슈를 본 적이 있습니다. 저는 Rails를 기초적인 폼 안에서 사용해 왔는데, 제가 본 일부 Rails 코드는 충격적이었죠.

 

Kent : XP가 주목 받기 시작할 때의 최초 OOPSLA가 생각나는군요.

 

Jim Rumbauch : David는 앞으로 지난 10년 동안 XP*에 벌어진 일들을 깨닫지 못할 것입니다. (그는 옳았습니다.) TDD는 성공하였고, 다른 대안들은 날아오르지 못했죠기술이 내재하고 있는 어떤 것 때문에 혹은 기술을 잘 못 사용한 것 때문에 나쁜 현상이 벌어지고 있다고 말하는 것은 언제나 어려운 일입니다. 우리가 할 수 있는 건, 기초적인 것과 좋은 교훈을 꾸준히 반복하는 것뿐이죠.

*역자주> XP : eXtreme Programming, SW 개발 방법론 중 애자일 실천 방법 중 하나

 

David : 동의 합니다. 당신은 영웅으로 죽거나 악당이 될 수도 있겠죠. Ruby는 프로그래밍에 관하여 좋은 아이디어의 재시도였습니다. 함수형 프로그래밍은 또 다른 재시도이죠. 이러한 재시도들은 건강합니다. 저는 Rails TDD가 오랫동안 함께 해온 것에 감명 받았습니다. 저는 Rails 이전에는 PHP로 작업을 했어요. 여러분은 잘 만하면 PHP로 좋은 코드를 작성할 수 있으며, 다른 프로그래밍 언어들로도 힘을 북돋아주는 좋은 사례들을 만들 수 있다고 느낍니다. 저는 MVC 기반 웹 애플리케이션에 TDD를 잘 사용하는 것은 깨끗한 PHP 코드를 작성하는 것 보다 어렵다고 생각합니다.

 

Kent : 전 제가 언제든지 TDD를 사용할 수 있다고 믿기 때문에, 그렇지 않은 경우를 찾지 못하겠군요. 저는 언제든지 다른 길로도 TDD로의 탐험을 하길 원합니다. 저는 제 경험과 함께 꾸준히 탐험할 것입니다. 지나치게 많이도 해보고, 충분하지 않게도 해보고, goldilocks zone도 찾아보며, 근본적인 원인을 이해할 것입니다. 저는 명확하게 David의 의견에 반박합니다. TDD는 죽지 않았습니다. 하지만 David TDD에 불을 질렀고, 마치 불사조처럼 튀어 나오게 된 점에 대하여 기쁘게 생각합니다.

 

David : 제가 이 논의를 시작하게 된 이유는 사람들이 TDD가 효과적으로 사용되지 않는 케이스에 대해 이야기 하려고 하지 않았기 때문입니다. 그들은 기분이 좋지도 않았거나 확신이 없었음에도 불구하고 반드시 TDD를 사용해야만 한다고 말하곤 했죠. 저는 타당한 반응에 대한 영역을 열기를 원했고, 이로 인해 우리는 TDD가 적절한 지 아니면 적절하지 않은 지에 대해 논의 할 수 있었습니다. 인터넷의 많은 사람들이 TDD가 얼마나 좋은지 말하고 있지만, TDD가 그들에게 잘 동작하고 있지 않다고 말하는 것을 두려워하고 있었습니다. 저에게 자가-테스팅 코드는 우리가 TDD에 대해 미심쩍어 할 때에도 잃고 싶지 않는 존재입니다.

 

Martin : (처음 시작하기 전부터 기대 했듯이) 우리는 많은 부분에 동의하였습니다. 우리 모두는 자가-테스팅 코드에 많은 가치를 얻고 있으며, 우리 모두 TDD가 어떤 곳에서는 가치가 있지만, 얼마나 많은 곳에서 가치가 있는지에 대해서는 (비록 말하기 어렵지만) 일부 동의하지 못하였죠. 만약, 여러분이 소프트웨어 개발을 하고 있다면, 이 점에 대해 반드시 깊게 생각해야만 한다는 것 그리고 당신과 당신의 팀을 위하여 잘 맞는 사례를 찾아내야 만 한다는 것, 그리고 여러분은 장님처럼 아무 기술이나 가져다 쓰면 안 된다는 것에 의견이 좁혀졌다고 봅니다. 여러분은 TDD를 시도할 필요가 있으며, 사용해야 하며, 남용도 해보고, 여러분과 여러분의 팀에 잘 동작하는 것이 무엇인지 찾을 필요가 있습니다. 우리는 공식으로 뒤덮인 과학 안에 있지 않습니다. 그렇기에 우리 스스로의 경험 기반으로 함께 일을 해야만 합니다.

 

Martin Fowler

 

저작자 표시 비영리 동일 조건 변경 허락
신고

설정

트랙백

댓글


 


번역가 : 송준이

현재 로엔에서 빅데이터 관련 업무를 하고 있다. Hadoop, Elasticsearch와 같은 빅데이터 관련 업무에 관심이 많다.


한글화 프로젝트는 프로그래머의 다양한 지식 습득을 위해 KSUG, JBUG와 지앤선이 함께 하는 프로젝트 입니다.

 

원문링크

 


스타트업이 비행하는 법

The Flight of the Startup. 



최근 반년 동안 스타트업에 대한 고민을 하다가 이상한 점을 발견했다. 나는 농장에서 살기 때문에 하루의 많은 시간을 삽질을 하면서(진짜 삽으로 땅을 파면서) 매일 팟캐스트를 듣는다. 팟캐스트에는 다양한 이야기가 있었는데, 그 중에는 스타트업에 대한 팟캐스트도 있었다. 그리고 해당 팟캐스트를 들으면서 깨달은 점은 1) 갓 시작한 회사임에도 불구하고 정보가 엄청나게 많다는 사실과 2) 이러한 정보들 중 몇 가지는 엄격히 보자면 서로 모순된다는 점이었다.

 

내가 읽고 들은 모든 내용에 공통적으로 드러나는 한 가지 테마는 바로 자본 효율성(capital efficiency)이다. 자본 효율성이란 스타트업이 위험 요소나 불확실성을 헤쳐나갈 때, 스타트업이 각 단계를 더 적은 비용으로 처리한다면 성공가능성이 훨씬 높아진다는 것이다. 스타트업은 너무 많은 불확실성을 내포하고 있으므로, 스타트업에게 가장 중요한 활동은 바로 실험이다. 적은 비용으로 실험을 더 많이 할 수 있다면, 스타트업이 살아남을 수 있는 가능성은 그만큼 더 높아지게 된다.

 

어렵더라도 이해하려고 노력하는 편이라, 서로 모순된 조언들 사이에서 타협점을 찾기 위해 노력했다. 마침내, 스타트업이 뚜렷하게 구분되는 단계들을 거친다고 가정하자 모순된 조언들을 이해할 수 있게 되었다. 팟캐스트에 의하면 각 단계마다 기법, 원칙, 기술, 심지어 가치조차도 변하게 된다. 그러나 그 조언들은 서로 모순된 것이 아니라, 적용되는 단계가 다름에도 불구하고  “스타트업이라는 하나의 단어로 뭉뚱그렸기 때문이었다. 스타트업의 단계는 비행기의 이륙과정에 비유할 수 있다.

 

1.            택시(Taxi) - 자리 잡기

2.            이륙(Takeoff) - 완전히 이륙하기 전까지는 적당한 한 방향을 향해 힘을 쏟기

3.            비상(Climb) - 상승세를 가파르게 유지할 수 있도록 전력을 다하기

4.            순항(Cruise) - 명확한 목표를 향해 조금씩 나아가기

 

이번 글에서는 각 단계를 간략히 살펴보고자 한다. 여기서는 각 단계를 특징짓는 개발 방식의 차이점에 대해 설명하겠다. 그리고 다음 글을 통해 각 단계를 전환하는 방법에 대해서 논의하도록 하겠다.

 

택시

첫 단계는 실질적인 필요성을 찾는 일이다. 이 단계는 몇 년이 걸릴 수 있다. “, 이 정도면 꽤 괜찮은 아이디어 같은데와 같은 감이 오는 단계이며, 전력을 다할만한 가치가 있는지 확인할 필요까지는 없는 단계다.

 

JUnit Max의 경우 택시 단계를 거치는데 11년이 걸렸다. 많은 사람들이 테스트를 작성하고 실행하는 일을 즐겼다. 바로 거기에서 사업으로 이끌어 낼만한 요소가 있을 거라고 확신했다. 수 많은 실험들을 진행했고, 마침내 머리 속에 무언가가번뜩하고 떠올랐다. 그리고 마침내 작년 12, 사람들이 돈을 내서라도 구입할 정도로 절실해 보이는 요구사항을 찾을 수 있었다. 바로, 테스트를 통한 피드백의 시간을 줄여 온전히 코딩하는 데만 집중할 수 있게 해주는 것이다. 광범위한 단위 테스트 속에서 코딩하는 프로그래머에게 이러한 요구사항은 실질적인 요구사항이라고 볼 수 있다.

 

택시 단계에서는 실험의 범위, 속도, 그리고 무엇보다도 실험 비용이 가장 중요하다. 많고 다양한 요구사항들과 관련된 아이디어를 시험해야 한다. 택시 단계에서는 실험결과의 정확도보다는 다양한 실험들을 가능한 많이 진행하는 것이 중요하다. 택시 단계의 위험 요인은 실질적인 요구사항을 찾지 못하는 일이다. 그러므로 위험 요인을 줄이기 위해 가능하면 많은 실험을 진행해야 한다. 이를 위해서는 실험 비용을 낮추는 일이 중요하다.

 

이륙

실질적인 요구사항을 찾았다면, 온 힘을 쏟아야 한다. 이전의 택시 단계에서 실험을 광범위하게 진행했다면, 불필요한 요구사항을 충족시키기 위해 자원이 소모되는 위험 요인은 충분히 모면할 수 있게 된다. 하지만 실질적 요구사항 모두가 사업성을 갖지는 않는다. 이륙 단계는 바로 이러한 사업성을 보장하는 고객을 찾고 수익을 창출하는 과정이다. 비행기의 바퀴가 땅에서 이륙하기 위해선 강한 추진력을 필요로 한다. 이와 마찬가지로, 스타트업의 이륙단계에서도 자력이든 아니면 투자를 유치하든 현금 흐름이 지속적으로 투입되어야 한다.

 

시장도 성숙했고 아이디어도 훌륭하더라도, 고객이 지갑을 열게 하는 기능을 반드시 찾아내야 한다. 이륙 단계에서는 광범위한 아이디어를 빠르게 훑는 조사보다는 주어진 요구사항을 해결할 수 있는 제품에 대한 구체적 연구가 더 중요해진다. 각 실험은 수익을 창출하거나, 또는 수익을 낼 수 없다는 결론이 나야 끝이 난다.

 

열렬한 잠재고객과 실제 비용을 지불하는 고객 사이의 간극은 상당히 크다. 시장이 존재함을 확인할 수 있어야 한다. 이륙 단계에서는 개발 주기 중 일부 시간을 포기해서라도 확신을 가질 수 있게 피드백을 받기 위한 시간을 내야 한다. 이륙 단계의 개발 주기는 가능한 아주 작은 제품을 출시하는 것이다. 이 제품이 구매할 만한 가치가 있는지 확인하기 위해 제품을 사는 사람이 있을 정도의 제품이면 충분하다. (이러한 제품을 규정하기는 어렵지만, 최소 요건 제품(Minimum Viable Product)이라고 부른다).  최신의 소프트웨어 개발과 마케팅 방법을 적용하면 다양한 시도를 통해 위험을 감소시킬 수 있을 정도로 자본 효율성을 충분히 높일 수 있다. Max를 만들 때 내가 따랐던(그리고 이전의 여러 벤처에서는 따르지 않았던) 충고는 “부끄럽지 않은 제품을 내었다면, 실험에 너무 많은 시간을 허비한 것이다.

 

(일부 스타트업 단체에서는 확장이 우선이며, 상품화는 그 다음이라고 주장하기도 한다. 나는 그 방법을 따르기에는 자금도 없었고, 그만큼 훌륭한 아이디어도 없었다. 만약 여러분도 나와 같은 상황이라면, 앞의 내용들에서수익사용처로 바꿔 보기 바란다. 또한 수익을 뒤로 미룰 수 있는 행복한 상황이라면, 스타트업을 어떻게 꾸려나가는지에 대한 여기 조언들이 큰 도움이 되지 못할 것이다.)

 

JUnit Max는 현재 이륙 단계에 있다. 실질적인 필요성을 해결하고 있다고 확신할 정도로는 수익이 나고 있지만, 자체적으로 더 성장하기에는 수익이 충분치 않다. 하지만 위험한 가정들을 검증하는 첫 단계는 이미 넘어섰기 때문에, 동일한 테마를 바탕으로 제품을 지속적으로 실험하고자 한다.

 

비상

제품의 핵심 기능들을 만들어서 수익이 나기 시작했다면, 다음 단계는 제품이 실질적인 수익을 창출하도록 빠르게 비상하는 일이다. 비상 단계에서는 조직에서 기술 파트와 비즈니스 파트가 중요해진다. 마케팅부가 이전 단계에는 테스트를 위해 수백 정도의 사람에게 제품을 전달했다면, 이제는 제품을 십만 명에게 전달해야 한다. 영업부는 이전 단계에서 소량을 판매해도 충분했지만, 이제는 수천 개를 판매해야 한다. 기술 파트에서는 이전에는 적은 수의 사용자를 감당할 수 있을 정도의 소프트웨어를 구축하면 충분했지만, 이제는 사용자 수가 크게 늘어나더라도 감당할 수 있는 소프트웨어를 구축해야 한다. 또한 팀 전체는 수천만 또는 수억이 넘는 간단한 사용자 대화뿐만 아니라 꽤 많은 심도 깊은 대화를 통해 얻은 피드백에서도 배워야 한다.

 

비상 단계에서는 매일 새로운 문제가 발생한다. 따라서 비상 단계에서는 문제가 하나라도 발생하면 문제를 해결한 후 다음 문제를 대비하는 일이 가장 중요한 역량이다(만약 문제를 쌓이도록 방치하면, 결국에는 문제들에 싸여 꼼짝 못하게 된다).

 

비상 단계에서는 자금 효율성 또한 그 의미가 바뀐다. 이 단계에서는 수익이 나거나 또는 투자를 받게 된다. 그리고 돈을 지출하면 문제를 해결할 수 있다. 비상 단계의 자금 효율성은 얼마나 돈을 덜 썼는지가 아니라 얼마나 돈을 효율적으로 썼는지 측정해야 한다. 물론 이 단계에서도 예산은 빡빡하다. 고객수의 자릿수를 한 단계 높이기 위해서 더 적은 돈을 쓸 수 있다면, 고객수의 자릿수를 한 단계 높이는데 걸리는 시간은 더 짧아지게 된다.

 

순항

언젠가는 출근했을 때 새로운 문제가 하나도 없는 단계가 된다. 이제 과거에 한번 발생했던 문제만이 생기게 되고, 이들 문제는 모두 어떻게 해결할지 습득한 상태다. 이러한 상황이 되면 비상 단계에서 순항 단계로 단계가 전환된다. 순항 단계의 목표는 여전히 자본 효율성이지만, 이제는 확장이 아니라 이윤을 추구하게 된다.

 

순항 단계에서는 장기/단기 절충안을 만드는 일이 바람직하게 된다. 이 단계에서는 불확실성이 충분히 가라 앉게 되고, 옵션 가치(Option Value)로 사업 결정을 평가하기 보다는 할인현금 수입 가치(Discounted Cash Flow)가 더 합리적인 사업 평가 기준이 된다.

 

그리고 순항 단계에서는 원가 인하가 수익성을 주도하게 된다. 개발자 테스트와 같은 실천법은 이륙 단계에서는 적당히 유용했고, 비상 단계에서는 생존의 문제였지만, 순항 단계에서는 원가를 절감하여 이윤을 높이는데 도움이 된다.

 

결론

제품이 순항 단계에 접어들면, 새로운 아이디어가 파생하게 되고 작은 규모의 스타트업을 새롭게 비행시켜야 할 순간이 오게 된다. 기법, 기술, 원칙, 가치는 이제 다시 이전의 택시 단계로 전환해서 새로운 싹을 틔워서 살아남을 수 있는 최적의 기회를 모색해야 한다. 놀랍게도(적어도 내가 보기에) 스타트업 비행 모델은 일반적으로 대기업 내부의 프로젝트에서도 유효하다. 이 주제에 대해서는 다음 번에 다루도록 하겠다.

 

(문득 이륙 단계를 위한 효과적인 기술이 없다는 생각이 들었다. 나의 경우, AppEngine처럼 관리가 편하고 스몰토크처럼 유연하며 강력한 기능이 결합된 기술이 필요하다. 그렇다고 너무 방대한 기능을 구현하지 않아도 된다. 초기에 적으나마 매출이 일어날 수 있을 정도로 충분해 보인다. 하지만 이런 제품을 만들려면 스타트업을 새롭게 시작해야 할테고, 그러기에는 너무 바쁜 상황이라…)

 

스타트업에 대한 분명히 모순되는 조언들도 이처럼 4가지 단계로 생각하면 일리가 있다. 페이퍼 프로토타입 아니면 최소 요건 제품? 택시 또는 이륙? 영세함 아니면 빠른 성장? 이륙 또는 비상? 미친 듯이 기능 추가 아니면 무자비한 리팩토링? 이륙 또는 비상? 내일을 위한 투자? 당신은 순항 단계에 접어들었는지? 어떤 조언들도 잘못되지 않았다. 그저 명확하게 기술되지 않았을 뿐이다. 비행 단계 중 어느 단계에 있는지 알고 있다면, 다음 걸음을 내딛는데 도움이 될 것이다. 즐거운 비행이 되기를.



출판사 주: '비상'과 '순항'의 항목에 있는 그림은 원본 링크에서도 더이상 볼 수 없다고 표기되나 다른 항목과의 통일성을 위해 원본과 똑같이 작업 해 두었습니다.

 





저작자 표시 비영리 동일 조건 변경 허락
신고

설정

트랙백

댓글


 


번역가 : 송준이

현재 로엔에서 빅데이터 관련 업무를 하고 있다. Hadoop, Elasticsearch와 같은 빅데이터 관련 업무에 관심이 많다.


한글화 프로젝트는 프로그래머의 다양한 지식 습득을 위해 KSUG, JBUG와 지앤선이 함께 하는 프로젝트 입니다.

 

원문링크

 

테스트 하느냐 마느냐, 그것은 좋은 문제로다.

To Test or Not to Test? That’s a Good Question. 


소프트웨어 개발 분야에서 영구 불변의 진리는 영구 불변하는 것은 없다.’이다. 이는 테스트의 역할에 대해서 이야기할 때도 마찬가지이다.

 

과거에는 테스트는 우리(프로그래머)가 아닌 다른 사람의 몫이라고 생각할 때도 있었다. XP의 등장으로 많은 프로그래머의 생각이 바뀌었다. 테스트는 우리 모두의 일이며, 지속적으로 해야 한다고 믿게 되었다. 그러나 이는 테스트를 작성할 수 있다면 반드시 해야 한다는 테스트 지상주의를 맹신하게 만들기도 했다.

 

나는 테스트를 항상 작성해야 한다고 고집했는데, 이러한 경험을 통해 시간이 허락한다면 무엇이든 테스트를 할 수 있다는 사실을 배울 수 있었다. 또한 테스트는 믿을 수 없을 만큼 기술적, 심리적, 사회적, 경제적 가치가 있다는 사실을 알게 되었다. 하지만 테스트에 대한 이러한 내 전략을 뒷받침하는 가정이 하나 있는데, 이러한 가정이 맞는지는 최근까지도 분명하지 않았다.

 

소프트웨어 개발은 종종 긴 게임이 되곤 한다. 내 생각에 소프트웨어 사업 중 최고는 단연코 MVS PL/1 컴파일러다. 심지어 MVS PL/1 컴파일러는 고작 3명의 직원만으로 매년 300만달러를 벌어들인 때도 있었다는 소문까지 듣기도 했다. 이 정도까지 사업이 번창하려면, 인내심을 가져야 하며, 향후 수십 년 동안 소프트웨어가 유지될 수 있도록 투자해야 한다.

 

테스트에 대한 내 가정을 불분명하게 만드는 것이 바로 이 종종이라는 부분이다. 골프에서도 긴 게임과 짧은 게임이 있고, 각 게임마다 필요로 하는 기술은 서로 관련 있지만 완전히 같지는 않듯이, 마찬가지로 소프트웨어 개발에도 긴 게임과 짧은 게임이 있다. JUnit Max의 경우, 소프트웨어에서의 짧은 게임을 치르고 있다. 이 짧은 게임을 하면서 관련은 있지만 완전히 동일하지 않은 기술이 소프트웨어 개발에서 어떤 의미가 있는지를 깨우치고 있다.

 

두 가지 프로젝트

JUnit은 긴 게임이다. 사용자도 많고, 수입도 안정적이며(0$, !!!), 기능도 한정적이다. 우리는 모두 JUnit에 대해 알고 있다. 또한 사용자를 끌어들이고 유지할 수 있는 부분이 무엇인지도 이해하고 있다. 따라서 천천히 변경되는 요구사항들을 조금 앞서 해결하면 그만이다.

 

JUnit을 만들 때는 XP 실천법들 모두가 유용했다. 항상 테스트 주도로 개발했다. 그리고 가능하면 언제라도 리팩토링을 했으며, 마음에 드는 한가지 방법을 찾기 전에는 서너가지 방법을 시도한 적도 가끔 있었다.

 

JUnit은 지원 비용이 점근적으로는 0에 수렴해야 한다는 사실로 그 성공 여부가 판가름난다. JUnit을 실제로 사용하는 사용자의 숫자는 엄청나게 많았지만, 지원을 위한 예산은 없었기 때문이다. 따라서 성공하기 위한 방법은 명백했다. 천천히 진화시키고, 광범위하게 테스트하며, 릴리즈는 최소한으로 줄여야 했다.

 

JUnit Max를 개발하기 시작했을 때, 규칙이 바뀌었다는 사실을 천천히 깨닫게 되었다. JUnit Max가 살아남기 위한 핵심적인 질문은어떤 기능을 만들어야 비용을 지불할 사용자를 끌어들일 수 있는가?”였다(이다). 당연하게도 이 질문에 대해서는 대답할 수 없다. 만약 JUnit(또는 무료로 배포되는 다른 패키지)이 해당 기능들을 구현한다면, 어느 누구도 Max를 돈을 주면서까지 사용하지 않을 것이기 때문이다.

 

JUnit Max은 그 성공 여부가 자력으로 수입을 만들어내는데 달려 있다. 비용을 지불하는 사용자가 늘고, 사용자당 수익이 증가하며, 입소문을 통한 효과가 높아야 한다. 당연하게도 JUnit Max가 성공하기 위한 방법을 알지 못했기 때문에, 성공할 가능성을 높일 수 있는 방법이 무엇인지 알기 위해서 수많은 실험들을 하고, JUnit Max가 실제로 사용되고 적용된 피드백을 통합하는 것이었다.

 

테스트 하느냐 마느냐.

이러한 피드백 통합을 위한 한가지 방편으로 Max에서 발생한 내부적인 에러 모두를 중앙 서버로 전달했다. 긴 게임의 프로젝트와는 달리, 짧은 게임의 프로젝트의 경우 런타임 에러가 항상 나쁜 점은 아니다(이 주제에 대해서는 다음 글에서 다룬다). 반면 내가 알지 못하는 에러는 확실히 나쁜 점이다.

 

에러 로그를 찬찬히 살펴보면서, 나는 수정할 수 있는 두 가지 에러를 발견했다. 주어진 시간에 맞출 수 있는 실험들이 하나도 없었기 때문에, 두 가지 에러 모두를 고치기 시작했다.

 

첫 번째 결함은 간단했다. 닫힌 프로젝트가 예외를 발생시켰다. 테스트를 작성하는 일도 쉬웠다. 기존의 테스트를 복사한 후, Max를 실행하기 전에 프로젝트 닫도록 수정했다. 아니나 다를까 빨간 불이 떴다. 나중에 2개의 라인을 수정하니, 녹색 불이 떴다.

 

두 번째 결함의 경우, 딜레마에 빠지게 되었다. 문제를 해결할 방법은 알고 있지만, 자동화된 테스트를 작성하는데 필요한 것들을 배우려면 어림잡아 수시간이 걸릴 것 같았기 때문이다. 그래서 결정했다. 고치고 배포하자. 테스트는 없다.

 

나는 두 가지 결정 모두를 지지한다. 두 경우 모두에서 나는 수행할 수 있는 한 최대로 검증된 실험을 진행했다. 첫 번째 결함의 경우 테스트는 소프트웨어가 회귀하는 것을 방지하고, 스스로에게는 자신감을 심어주었으며, 미래에 개발할 작업들을 보완해 준다. 두 번째 결함의 경우 테스트를 작성하지 않았으므로, 새로운 기능을 개발할 시간을 벌어 주었다.

 

쉬운 정답은 없다

Max를 개발하기 시작했을 때 첫 한달 동안 나는 어떤 자동화된 테스트도 작성하지 않았다. 나는 모든 테스트를 수작업으로 진행했다. 몇 명의 초기 후원자가 나타난 후에야, 나는 이전 코드로 돌아가서 기존의 기능들에 대한 테스트를 작성했다. 이 경우도 마찬가지로, 나는 이러한 순서로 개발함으로써 단위 시간에 수행할 수 있는 검증된 실험들을 최대한으로 할 수 있었다고 믿는다. 코드가 없거나 적은 경우, 테스트를 작성하지 않으면 더 빠르게 시작할 수 있다(실제로 첫 테스트를 작성할 때 거의 일주일이나 걸렸다). 작성한 초기 코드가 나중에 유용하다는 판단이 들면(내 친구들 중 몇몇이 소프트웨어를 산다는 기준으로), 테스트를 만들어서 코드에 대해 빠르게 실험하고, 자신감을 얻을 수 있다.

 

자동화된 테스트를 작성하느냐 마느냐를 결정할 때 다양한 요소 사이에서 균형을 이뤄야 한다. 심지어 Max를 만들 때조차도 상당수의 테스트를 작성했다. 만약 테스트를 작성할 수 있는 값싼 방법이 있다면, 나는 모든 기능에 대해 인수 테스트를 먼저 작성했다. 특히 기능을 어떻게 구현할지 마땅한 방법이 떠오르지 않을 경우, 테스트를 작성함으로써 훌륭한 아이디어를 얻을 수 있었다. 반면 Max를 개발할 때 테스트를 작성하느냐 마느냐를 결정하는 기준은 테스트가 단위 시간에 더 많은 실험들을 검증할 수 있도록 돕느냐가 핵심이다. 돕는다면 테스트를 작성한다. 그렇지 않을 경우, 위험을 감수한다. 나는 Max가 순조롭게 출발할 수 있을 정도의 수입을 얻을 수 있는 기회를 최대화하려고 노력한다. 설계에 투자해야 하는지와 관련한 추론도 이와 비슷하게 복잡한데, 이 주제 역시도 다음 글에서 다루고자 한다.

 

언젠가는 Max도 긴 게임의 프로젝트가 될 것이고, 범위도 명확해지며, 오랫동안 지속할 수 있는 비용을 벌어들일 것이다. 유연성을 유지하면서 동시에 비용을 줄이는 것이 새로운 목표로 자리매김할 것이다. 테스트를 작성하는데 들인 시간들도 보상받게 될 것이다. 하지만 그때가 되기 전에는 나는 짧은 게임을 하고 있다는 사실을 잊지 말아야 한다.

저작자 표시 비영리 동일 조건 변경 허락
신고

설정

트랙백

댓글

지앤선에서 2015년 계획하고 있는 교육 중 하나와 비슷한 목적과 방향을 가지고 있는 행사라 먼거리에서 주최되는 것이지만 행사를 기획하신 김영욱 부장님을 졸라 참관 자격으로 다녀오게 되었다.

 

행사에 대한 소개



이번 행사는 한국 MS의 사회공헌팀에서 주최를 하였으며 1 15 MSP를 위한 강의, 116일 기자들을 위한 강의에 이어 진행된 시즌 1의 마지막 행사였다. 행사에 대한 자세한 소개는 김영욱 부장님의 블로그를 통해서 접하길 바란다.

  

사실 처음 시작 전 학생들은 IoT에 대해 잘 모르는 듯했다. 어쩌면 IoT(사물인터넷)에 대한 것은 관심 있는 사람들이나 알고 있는 그들만의 리그가 아닐까란 생각이 들면서 어떻게 해야 학생들에게 즐거운 시간을 만들어 줄 수 있을지 걱정이 되기도 했다김영욱 부장님의 강의로 시작되었는데 언제나처럼 흥미를 유발할 수 있을 정도로 유쾌했으며, 아이들의 눈높이에 맞게 흥미를 유발할 수 있도록 진행되었다.

 

시작할 때의 걱정이 기우라는 것은 강의 시작 10분만에 알 수 있었다. 학생들은 내가 우려했던 것보다 훨씬 적극적으로 행사에 참여했고 즐거워했다. 그 어떤 강의보다도 답변도 호응도 좋았다. 아두이노에 대한 관심, 나아가 프로그래밍에 대한 관심 자체를 어떻게 이끌어주냐에 따라 달라질 수 있다는 확신이 들었다

 

본격적으로 아두이노를 설치하는 시간이 되자 여기저기 시끄러워지긴 했지만 그래도 서로 조금 더 빨리 하려고 도전적으로 하는 모습이 귀엽기까지 했다아두이노 실행을 위해 C언어를 배우기도 했는데, 사실 이 시간은 관심이 없는 학생에게는 지루하게도 혹은 어렵게도 느껴질 듯했지만, 함께 하는 MSP 학생들이 학생 개개인을 2:1로 교육하면서 지루하지 않도록 계속 도와 주어서 하기 싫어하는 아이들은 한 명도 보이지 않았다. 때로 고개를 갸웃거리는 모습을 보자니 외계어 스터디에서의 내 모습 같아서 괜히 입가에 미소가 지어졌다

 

역시 직접 실행을 해 볼 수가 있다는 건 프로그래밍 교육에서 중요한 포인트인 것 같다. 그냥 이론적인 설명만으로는 아무도 흥미를 느낄 수가 없으니... 이번 행사에 참여하고 난 후 어떻게 하면 학생들을 위한 프로그래밍 교육이란 결국 학생들이 흥미를 느껴서 스스로 조금 더 알고 싶고 배우고 싶게 만들어주는 것이 주목이어야 한다는 생각이 더욱 강하게 들었다.

 

무조건적인 교육이 아니라 학생들에게 나침반이 되어줄 수 있는 교육!!! 그렇게 하기 위해서 지앤선에서는 어떤 식으로 진행을 해 나가야 할지 생각을 더 많이 해 봐야 할 것 같다.

 

추신 : 뜻깊은 행사를 주최하고 초대해 준 한국 MS의 사회공헌팀과 김영욱 부장님께 무한 감사를 드립니다

by 앤(&)

 

 

저작자 표시 비영리 동일 조건 변경 허락
신고

설정

트랙백

댓글


티스토리 툴바