본 글을 제가 아래 원본을 읽고 나서 남겨놔야 겠다 싶어 번역한 글입니다. 혹시나 번역이 잘못되었거나 이렇게 번역하는 게 올바르지 않은 것이라면 말씀해주세요. 조치하겠습니다!
http://www.yegor256.com/2015/11/10/ten-mistakes-in-specs.html
This blog is the translation of "10 Typical Mistakes in Specs" from www.yegor256.com.
If this blog violates copyrights or something else, please let me know.
============================================================================
Karl Wiegers가 쓴 Software Requirements라는 유명한 책이 있다. 흠, 소프트웨어 요구사항 정리에 관해서는. 개인적인 의견으로는, 소프트웨어 엔지니어들에게는 필수 서적이라 생각된다. 그 책에서 말하고자 하는 것을 여기서 반복할 필요는 없을 것 같고, 실전에서 소프트웨어 명세서를 보면 꾸준히 반복되고 있는 몇 가지 실수들이 있다. 나는 그런 실수들을 자주 보아 왔기 때문에 한 번 정리해야 겠다고 결심했으며 그래서 여기, 명세서를 읽는 프로그래머의 입장에서 가장 흔하고 결정적인 실수들을 적어본다.
유명한 표준안인 IEEE 830-1998의 챕터 4.3에 의하면, 좋은 명세서는 반드시 일관성 있게 정확하고 명확하며 완전하고 우선 순위가 명시되어야 하며 증명 가능하고 출처가 명확하며 수정이 가능해야 한다. (correct, unambiguous, complete, consistent, ranked, verifiable, modifiable, and traceable) 종합적으로 위 8가지가 만족되어야 한다고 하면서 표준안은 하나 하나 꽤 쉽게 설명해 놓았다. 하지만 우리가 이 지루한 표준안을 읽을 시간을 가지고 있었던가? 그것들은 대학 교수나 검정 위원회를 위한 것이다. 생각해봐라, 우리는 ... 기술자들(practitioner)이란 말이다! ... 하하, 농담이다...
프로젝트의 규모가 얼마인지, 우리가 얼마만큼 실행할 수 있을지는 상관없이, 무엇이 실행되어야 하는지 설명하는 문서는 항상 존재한다. 그리고 그것은 아마도 "소프트웨어 요구사항 명세서" 또는 "명세서"라고 불릴 것이다. 물론, 명세서에도 약간의 창작을 위한 공간이 있을 수 있다. 하지만 우리는 예술가가 아니라 엔지니어다. 원활한 의사소통을 위해 우리는 반드시 규칙과 표준을 지켜야 한다.
자, 이제 본격적으로 들어가보도록 하겠다.
나는 그 동안 위의 8가지 요건들을 위배하는 명세서들을 줄곧 봐왔으며 아래는 그러한 문서들이 어떻게 8가지들을 위배했는 지에 대한 요약이다. 참고로, 아래 모든 예제들은 실제 상업 소프트웨어 프로젝트에서 실제 명세서로 부터 나온 것들임을 알아주길 바란다.
(역주: 각각의 카테고리들과 예제들은 해석과 예제를 함께 남깁니다.)
용어 설명이 없거나 의미 파악이 어려운 용어
(No Glossary or a Messy One)
아래 예제를 보자:
UUID는 2개의 동일한 계정 번호가 생기지 않도록 하기 위해 하나씩 증가하며 설정되어야 한다.
(UUID is set incrementally to make sure there are no two users with the same account number)
UUID와 계정 번호의 차이가 무엇일까? 같은 것인가? 같이 보이긴 한다, 그렇지 않나? 아니면 아마도 다를 수도 있을 것인데...UUID가 무엇을 의미하는 지 아는 것이 최선일 것 같다. 아마도 "unique user ID" 혹은 "unified user identity descriptor"가 아닐까 하는데, 모르겠다. 그저 이 문서를 작성한 사람(이하 작성자)을 당장 찾아가서 조그마한 복수를 하고 싶은 마음 뿐이다.
나는 이미 최악의 기술 명세서는 용어 설명따위 하지 않는다. 라는 글을 쓴 적이 있다. 내 경험에 비추어 볼 때, 이것은 모든 명세서의 가장 큰 문제점 이기도 하다. 명세서는 문학이 아니며 러브레터는 더더욱 아니다! 단지 기술 문서일 뿐이다. 우리 모두는 단지 재미를 위해 단어 맞추기를 할 시간이 없다. 그리고 우리를 표현하기 위해서 제품 명세서를 사용하는 것도 안 된다. 우리는 독자에게 감명을 주기 위해서가 아닌, 이해시키기 위해서 문서를 작성하는 것이다. 그리고 룰은 '당신이 더 나은 기획자일 수록, 당신의 그림은 심플하다.'에서 언급한 바와 같다: 만일 내가 이해하지 못했으면 그것은 당신 잘못이다.
위 예제를 한 번 바꿔보자:
UUID는 사용자 고유 아이디이며, 4-바이트 0보다 큰 정수이다.
UUID는 2개의 동일한 UUID가 생기지 않도록 하기 위해 하나씩 증가하며 설정되어야 한다.
(UUID is user unique ID, a positive 4-bytes integer.
UUID is set incrementally to make sure there are no two users with the same UUID)
더 낫지 않은가?
따라서, 가장 첫번째로 흔한 문제는 멍청한 용어 사용과 의미가 명시되지 않는 단어의 사용이라고 할 수 있겠다.
질문, 토론, 제안, 의견
(Questions, Discussions, Suggestions, Opinions)
아래는 내가 최근 제품 명세서에서 본 명세 사항이다.:
저는 여러 버전의 API가 지원되야 한다고 생각합니다. 어떤 방법들이 있을까요? URL로 관리하는 것도 괜찮을 것 같습니다.
당신의 의견이 있다면 주저 말고 남겨주세요.
(I believe that multiple versions of the API must be supported.
What options do we have? I'd suggest we go with versioned URLs. Feel free to post your thoughts here.)
그렇다, 위 문장이 요구사항 문서에 그대로 적혀 있었다. 차근히 따져보면, 먼저 작성자는 제품에 대한 그의 의견을 표현하였다. 그러고 나서 나에게 어떠한 방법이 가능할 지 물어보았고, 또한 의견을 이야기할 수 있다는 것을 알려 주었다.
인상적이지 않은가? 단언컨대, 작성자는 매우 창의적인 성격을 가졌임이 틀림없다. 하지만 우리는 이러한 사람을 프로젝트 문서를 작성할 때는 다분히 배제시켜야 한다. 요구사항 문서 작성과는 어울리지 않기 때문이다. 우리도 물론 창의성을 지향한다. 하지만 아래 4가지는 반드시 금지되어야 하지 않을까 싶다: 질문하기, 토론하기, 제안하기, 그리고 의견 묻기
명세서 자체는 명세사항들에 대해 질문을 가질 수 없다. 질문이 있다면 누가 이러한 질문들을 해결할 것인가?
우리, 프로그래머? 우리가 소프트웨어의 기능을 예상하고 질문에 답해야 할까? 나는 작성자와 브레인스토밍을 하고 싶지 않을 뿐더러, 내가 명세서에 바라는 것은 나에게 어떤 기능이 있어야 되는지 말해주는 것 뿐이다. 작성자는 명세서를 작성하기 전에 모든 질문의 답을 찾아야 한다. 그것이 그 사람이 월급을 받는 이유니까. 만일 작성자가 답을 찾지 못한다면, TBD("to be determined")라도 적어야 한다. 질문을 하면 우리는 더 화가 날 뿐이다.
요구사항 문서는 토론 게시판이 아니다. 명세서의 독자로써, 나는 "아마도"나 "바뀔 수도 있다"가 없이 정확히 어떠한 기능이 필요한 지 볼 수 있기를 바란다. 물론, 문서를 완성하기 전에는 이러한 이슈들을 토론할 수 있다. 하지만 다른 곳에서 해야하지 않을까? 예를 들면, Skype나 Slack, 이메일 같은 곳에서 말이다. 만일 작성자가 문서 파일에서 토론하길 원한다면, 버전 추적(version tracking)을 이용해서 Google Docs나 Word를 이용할 수도 있다. 하지만 토론이 끝났을 때에는 토론했던 히스토리를 모두 지워야 한다. 남아있는 히스토리들은 단지 프로그래머를 혼란에 빠뜨릴 뿐이니까.
요구사항에는 제안 역시 있을 필요가 없다. 단지 어떠한 기능이 구현되어야 하며 어떻게 해야 소프트웨어가 잘못 구현됐다는 두려움을 없앨 수 있는지만 말해주면 된다. 일반적으로, 사람들은 직설적으로 말하기 두려울 때 제안을 한다. "그 앱은 반드시 안드로이드 3.X 이상 버전에서 작동이 되어야 합니다." 대신에, "나는 안드로이드 3.X 이상에서도 이 앱이 호환될 수 있도록 만드는 것을 제안합니다."와 같이 말이다. 차이가 느껴지나? 두 번째 문장에서는 작성자가 개인적인 책임을 피하려고 한다. 그는 "정확히 안드로이드 3.X 버전"이라고 말하지 않는다. 단지 제안할 뿐. 겁쟁이가 되면 안 된다; 그냥 말해라. 만일 당신이 실수한다면, 우리가 정정해 줄 수 있다.
그리고 물론, 의견을 물어보는 것도 전혀 타당하지 않다. 명세서는 친구에게 보내는 편지가 아니다; 이것은 프로젝트에 포함될 정식 문서이다. 몇 달 혹은 몇 주 이후에는 당신이 프로젝트에서 빠지겠지만 다른 누군가가 작업하기 위해 당신의 문서를 읽을 것이다. 명세서는 프로젝트 스폰서와 팀의 계약서와 같다. 작성자의 의견 따위 계약에 어떠한 영향력도 없다. "자바가 속도 면에서 더 빠를 것이기에 자바로 구현하길 권한다."라고 쓰는 대신에 "자바가 더 빠르다, 그러므로 우리는 자바를 써야한다."라고 적어주길 바란다. 당신이 그렇게 생각했다면 명확하게 적는 게 낫다. 그러나 일단 한번 그렇게 적혀있으면, 프로그래머는 누가 그렇게 제시했는지 이러한 문제에 대해 당신이 어떻게 생각하는지는 관심없다. 프로그래머를 더 혼란스럽게 만들 정보가 있다면 건너 뛰고 사실만 적어라, 의견이 아니라.
오해하지는 마시길, 나는 창의성을 지양하지 않는다. 프로그래머는 조용히 문서가 하라는 대로 구현만 하는 로봇이 아니니까. 하지만 혼란을 야기하는 문서는 창의성과는 관련이 없다. 만일 당신이 내가 창의적이길 바란다면, 어느 정도선까지 내 의견을 반영해도 되는지를 제시해주길 바란다.
예를 들면:
여러 버전의 API가 지원되야 한다. 정확히 어떻게 버전이 관리되는 지는 중요하지 않다.
(Multiple versions of the API must be supported. How exactly that is done doesn't really matter.)
위 예제가 바로 당신이 프로그래머에게 창의성을 발휘할 수 있도록 제시할 수 있는 방법이다. 나는 제품의 사용자가 버전 관리 메카니즘에 관해서는 딱히 기대하거나 정해놓은 것이 없다는 것을 알게 되었다. 고로, 여기에 관해서 나는 마음대로 할 수 있는 것이다. 좋아, 내 맘대로 하겠어.
다시 한 번 말하지만, 요구사항 명세서는 토론 게시판이 아니다.
기능 명세와 품질 명세의 혼합
(Mixing Functional and Quality Requirements)
아래 예제를 보자:
사용자는 프로필 내 이미지 목록을 부드럽고 빠르게 스크롤할 수 있어야 한다.
(User must be able to scroll down through the list of images in the profile smoothly and fast.)
내가 지금까지 봐온 모든 명세서에서 전형적으로 일어나는 실수이다. 여기서 우리는 기능 명세("이미지를 스크롤한다")와 품질 명세("스크롤이 부드럽고 빠르다.")가 함께 있는 것을 볼 수 있다. 이것이 왜 나쁘냐고? 흠, 이건 지극히 기본적인 부분에서의 실수이지 않을까...
위와 같은 요구사항은 증명하거나 테스트하기 어려우며 구현하는 것도 어렵다. 프로그래머로써, 나는 어떠한 것이 중요한 것인지 확신할 수 없다: 문제 없이 스크롤되는 것인가 아님 빠른 스크롤링인가?
또한, 위와 같은 문장은 수정하기도 어렵다. 만일 내일 우리가 또다른 기능 명세를 추가한다고 해보자 - 예를 들면, 친구 목록을 스크롤할 수 있어야한다.(scrolling a list of friends) - 고객은 이 기능 또한 부드럽고 빠르게 구현되길 바랄 것이다. 그러면, 며칠 후에, 우리는 "빠름"이 의미하는 것이 10 밀리초 정도의 반응 속도인지 궁금할 수도 있겠다. 그러면 이러한 정보에 대해 위 2개의 기능 명세 사항에 중복하여 빠름의 의미를 넣어야 하는 것이다. 궁극적으로, 요구사항 문서가 점점 혼란에 빠지게 되는 것이 보이는가?
따라서, 나는 당신이 기능과 품질 명세를 명확히 분리하여 문서를 작성하기를 강력히 추천한다.
요구사항과 추가 문서의 혼합
(Mixing Requirements and Supplementary Docs)
여기 위에서 언급했던 문제와 비슷해 보이는 예제가 있다:
사용자는 모든 처리 내역이 담겨있는 PDF 형식의 보고서를 다운로드할 수 있다. 각 처리 내역은 ID, 날짜, 설명, 계정 그리고 총 지불이 표시된다.
보고서에는 또한 요약본과 사용자 계정 정보가 담겨 있다.
(User can download a PDF report that includes a full list of transactions. Each transaction has ID, date, description, account, and full amount.
The report also contains a summary and a link to the user account.)
이것은 명백히 하나의 문단에 2개의 명세 사항을 적시한 것이다. 먼저 첫 번째는 사용자가 PDF를 다운로드 받을 수 있다는 것이고 PDF 문서는 어떻게 구성되야 하는 지가 두 번째인 것이다. 첫 번째는 기능 명세이며 두 번째는 추가 문서(혹은 부록)에 적혀있어야 하는 것이다.
일반적으로, 기능 명세는 매우 짧아야 한다: "사용자가 다운로드한다.(user downloads)", "사용자가 저장한다(user saves)" 혹은 "클라이언트가 요청하고 응답받는다(client requests and receives)"와 같이. 만일 당신의 문장이 길어진다면, 그건 뭔가 잘못된 것이다. 이럴 땐, 길어진 문장을 쪼개서 추가 문서에 옮겨보시길.
측정할 수 없는 품질 요구사항
(Un-measurable Quality Requirements)
내가 말하고 싶은 것은 이것이다:
신용카드 번호는 암호화되어야 한다.
(Credit card numbers must be encrypted.)
앱은 2초 이내에 켜져야 한다.
(The app should launch in less than 2 seconds.)
각 웹페이지는 500 밀리초 이내에 보여야 한다.
(Each web page must open in less than 500 milliseconds.)
사용자 인터페이스는 요청에 반응해야한다.
(User interface must be responsive.)
지난 몇 년동안 해온 수 많은 프로젝트에서 위와 비슷한 예제들을 훨씬 더 많이 찾을 수 있었다. 그것들은 모두 같은 문제를 가지고 있었는데, 바로 실질적으로 테스트하고 측정하기 매우 어렵다는 것이다.
맞다, 어렵다. 그리고 어렵다는 것은 대부분 많은 요소에서 확인된다. 위 예제를 다시 보자: "앱은 2초 이내에 켜져야 한다.(The app must launch in 2 seconds.)" 어느 기기에서? 사용자 프로파일 안의 데이터를 얼마 만큼 읽으면서? "켜지다(launch)"의 의미가 무엇인가; 프로파일 로딩 시간까지 포함되어 있는 것인가? 만일 켜질 때 문제가 발생한다면? 시간은 어떻게 카운팅하는가? 이 같은 질문들이 수도 없이 나올 수 있다.
만일 질문한 것에 모두 답한다면, 명세사항 하나로 페이지 하나를 다 채울 수도 있을 것이다. 아무도 그것을 바라지 않지만, 측정할 수 없는 요구사항을 가지고 있다는 것은 페이지 하나를 다 채우는 것보다 더 큰 문제가 될 수도 있다는 것을 명심하길 바란다.
다시 한 번 말하지만, 쉬운 것은 아니다. 하지만 필요하다. 모든 품질 명세사항에 대해 모호하지 않도록 확신할 수 있어야 한다.
구현 지시
(Implementation Instructions)
아래 예제는 아주 흔한 문제점을 보여준다:
사용자는 페이스북 로그인 버튼을 통해 인증 받으며 우리는 사용자 이름, 아바타 그리고 이메일을 데이터베이스에 저장합니다.
(User authenticates via Facebook login button and we store username, avatar, and email in the database.)
이것은 미관관리(micromanagement)이며 요구사항 분석가가 프로그래머에게 절대 해서는 안되는 것이기도 하다. 당신은 기능이 어떻게 구현되어야 하는지 프로그래머에게 말해서는 안 된다. 사용자가 페이스북을 통해 로그인할 수 있길 원하는가? 그럼, 그렇다고 적어라. 당신은 버튼을 클릭했을 때 어떤 일이 벌어지는 지에 정말로 관심이 있는가? 정말로 데이터베이스에 무엇을 저장할 것인지가 궁금한가? 만일 데이터베이스 대신 파일을 쓰면? 그것이 당신에게 그토록 중요한가?
나는 그렇게 생각하지 않는다. 아주 아주 드문 경우에 중요할 수도 ... 하지만, 대부분의 경우에는 미관관리일 뿐이다.
요구사항 명세서는 제품을 위해서 어떠한 것이 이루어져야 하는 지만 명시되어야 한다. 나머지는 우리, 프로그래머의 몫이다. 어떤 데이터베이스를 쓰며, 버튼이 어디에 위치에 있고 어떤 정보를 저장할 것인지는 우리가 결정할 일이다.
만일 당신이 특정 제약들 때문에 신경을 써야한다면, 그렇다고 적어라. 하지만, 프로그래머에게 어떻게 구현하라는 지시 없이 차라리 아래와 같이 품질 명세 사항으로 말해주길 바란다.
로그인 페이지는 아래와 같이 보여야 한다.(사진 첨부)
우리는 추후 사용을 위해 이메일 정보를 저장해야 한다.
(Login page must look like this (screen attached).
We must store user email locally for future needs.)
요구사항 명세에 관해서는 나는 뭐라 할 수 없다, 하지만 구현 지시에는 강력히 반대하는 바이다.
사용자 관점 부족
(Lack of Actor Prospective)
아래 예제를 보자:
PDF 보고서는 요청될 때 생성된다. 보고서는 다운로드하거나 계정에 저장할 수 있어야 한다.
(PDF report is generated when required. It is possible to download a report or save it in the account.)
여기서의 문제는 "누가" 하는지가 없다는 것이다. 기능 자체는 깔끔하게 설명되어 있지만, 누가 하는 지는 명확하지 않다. 주어는 어디에 있는가? 어디에서 어떤 것이 일어나는 스토리란 말인가? 정작 기능이 구현되기 위해서 프로그래머에게 진짜 필요한 것이 빠져버린 것이다.
기능을 설명하는 가장 좋은 방법은 사용자 스토리(User Stories)이다. 그리고 좋은 사용자 스토리는 항상,...흠..추측컨대, 사용자를 가지고 있다. 그것은 항상 뒤에 동사가 따라오는 "사용자는.."으로 시작한다. 사용자는 다운로드한다, 사용자는 저장한다, 사용자는 클릭한다, 인쇄한다, 삭제한다 등등.
사용자가 꼭 사람일 필요는 없다. 시스템일 수도, RESTful API Client일 수도, 데이터베이스일 수도 있다. 하지만 항상 주체는 있다. "... 다운로드할 수 있다.(It is possible to download...)"는 사용자 스토리가 아니다. 근데, 누가 다운로드할 수 있는 건가?
필요없는 말, 잡음
(Noise)
아래 예제는 어떤가:
우리의 가장 큰 관심은 성능과 유저 인터페이스이다.
(Our primary concern is performance and an attractive user interface.)
이것은 잡음이다. 이 문서의 독자로써, 나는 투자자도 사용자도 아니다. 우리는 프로그래머이다. 나는 당신의 "주요 관심"은 신경쓰지 않는다. 프로그래머의 일은 기능을 구현하는 것이며 그럼으로써 요구사항 명세와 제품을 일치시키는 것이다. 만일 성능이 당신의 주요 관심이라면, 측정 가능하고 테스트 할 수 있는 명세 사항을 작성해주길 바란다. 나는 제품이 해당 명세 사항을 만족할 수 있도록 구현하겠다. 만일 그러한 명세 사항을 작성하지 못하겠다면, 부디 우리와 관련없는 정보로 스팸은 자제해주길.
나는 당신의 걱정, 믿음 혹은 의도를 공유하고 싶지 않다. 그건 당신 일이다. 그리고 그러한 것들을 측정할 수 있고 테스트 가능한 명세 사항으로 번역하는 것이 바로 당신이 돈을 받는 이유이기도 하다. 만일 당신이 이걸 못하겠다면, 그건 당신 문제이고 당신 잘못이다. 나까지 끌여들이지 말아주시길.
사실, 아주 자주 ... 잠깐, 아주아주 자주 일어나는 일이다. 아닌가, 거의 항상인가. 잠깐만, 그냥 항상이다! 그렇다, 요구사항 명세서는 항상 필요없는 말로 가득차 있다. 그 중 몇몇은 좀 덜 할 수도 있지만, 몇몇은 매우 심하다. 나는 이것이 게으르고 프로페셔널하지 않은 작성자들의 증상이라고 믿는다. 대부분, 그냥 게으른 것이지만.
그들은 기능 명세에 대한 그들의 걱정, 생각, 의견, 의도 그리고 주관을 생각하고 적시하길 원하지 않는다. 그들은 단지 그것들을 문서에 넣고 프로그래머가 알아서 해결책을 제시해주길 희망한다. 좋은 프로그래머는 무엇이 좋은 성능을 의미하는 지 알아야 한다, 그렇지 않은가? 자, 그들에게 성능은 우리에게도 관심사라고 말해주고, 그들이 이해할 수 있도록 해줘야 할까?
노우! 그러면 안 된다. 당신의 일을 똑바로 하고 프로그래머가 그대로 할 수 있도록 문서를 작성해 달라고 해야한다.
그리고 우리, 프로그래머는 이런 문서를 절대 용납해서는 안 된다. 우리는 그들에게 거부 의사를 밝히고 문서를 다시 작성하여 잡음을 없애주길 요청해야 한다. 나는 만일 잡음이 많은 요구사항 명세서를 가지고 있다면 일을 시작조차 하지 않을 것을 추천한다.
작동할 것이다, 작동할 필요가 있다, 작동해야 한다.
(Will Work, Needs to Work, Must Work)
여기 또다른 매우 흔한 실수가 있다.:
API는 JSON과 XML을 지원할 것이다. 두 포맷은 모든 데이터 항목을 지원해야 한다.
XML은 XSD 스키마에 의해 검증되어야 한다.
(The API will support JSON and XML. Both formats must fully support all data items.
XML needs to be validated by XSD schema.)
혼란스럽지 않은가? 위 예제에는 3가지의 서로 다른 관점이 존재한다, 심지어 그 어느 것 하나도 요구사항 명세서와는 어울리지도 않는다. 명세서는 마치 실제로 존재하는 것처럼 제품을 묘사해야 한다. 명세서는 마치 메뉴얼, 튜토리얼 처럼 읽혀야 한다.
여기 다시 쓰여진 것을 보자:
API는 JSON과 XML을 지원한다. 두 포맷은 모든 데이터 항목을 지원한다.
XML은 XSD 스키마에 의해 검증된다.
(The API supports JSON and XML. Both formats fully support all data items.
XML is validated by XSD schema.)
차이점이 보이는가? 모든 "해야한다.", "필요하다." 그리고 "할 것이다."는 단지 문서에 대한 의심만 더 할 뿐. 이 문서의 독자에게 "API는 지원될 것이다.(the API will support)"는 "언젠가, 아마도 다음 버전에서, 지원될 것이다."와 같이 읽힌다.
이것은 당신이 의도한 것이 아닐 것이다, 그렇지 않은가? 확실하다면, 확실하게 적어라. API는 지원한다.(The API supports).
--------------------------------------------------------------------------------------------------------------------------------
여기에서 중요한 것을 놓쳤을 수도 있지만, 위에 제시한 것들은 확실히 우리, 프로그래머들을 화나게 하는 것들이다...
나는 우리 시스템 분석가에게 간단한 가이드로서 이 글을 보여줄 것이다.
댓글 없음:
댓글 쓰기