기능 요구사항 명세(Specification)


1. Intro

개발 경력이 많지는 않지만 백엔드 개발을 하며 느낀 분석, 설계, 문서화에 대해 기술한 포스트입니다. 의식의 흐름대로 작성한 내용이라 부족한 부분이 많을 수 있는데 잘 못된 내용이나 수정되어야하거나 추가되어야 할 내용이 있다면 글을 읽고 지적 부탁드리고, 문의를 남겨주시면 최대한 답변드리도록 하겠습니다.

인간은 망각의 동물이다. 본인이 개발을 하더라도 시간이 지난다면 왜 그런식으로 개발을 했는지 잊어버리는 경우가 많다. 본인의 개발을 한 내용에 대해서도 그런데 다른사람이 개발한 내용은 어떠할까? 그 사람이 개발한 내용을 알기 위해 개발한 당사자를 찾아가서 왜 그런식으로 개발했는지, 어떤 이유가 있어서 이런 행위를 하는지 히스토리 확인을 해야된다. 이것도 그 사람과 알고있다는 가정하에 아주 좋은 케이스다. 다른사람에게 물어봤더니 그 사람도 왜 그렇게 했는지 기억해는데 한참이 걸리고, 개발한 당사자에게 물어볼 수 없는 상황이 많다. 이러한 이유때문에 기능개발을 할 때는 그 기능이 어떤 행위를 하는지에 대해 문서로 남겨놔야하고, 그 문서를 통해 본인 혹은 다른 사람들이 그 기능이 어떤 행위를 하는지 알 수 있게 해야한다.

또한, 기능에 대한 문서를 작성하다 보면 그 기능이 해야하는 행위가 더욱 명확해지는 경우가 많다. 기능의 행위가 명확해지면 개발범위에 대해서 파악하는 것이 좀 더 수월해지고, 어떤식으로 개발을 할 지에 대한 설계가 가능해진다. 개발의 설계가 된다는 것은 기능 분리 및 관심사 분리가 가능해지는 것이고, 이는 이러한 과정을 거치지 않은 코드보다 뛰어난 품질의 코드를 작성하는데 도움이 된다.

물론 본인의 기억력에 대해서 엄청난 자신감을 가지고 있고, 다른 사람에게 그 기능이 무슨 행위를 하는지 전달할 필요나 생각이 없는 경우, 문서를 작성하지 않아도 머리속에서 설계가 가능하다면 문서를 작성할 필요는 없다.

이번 포스트에서는 웹 프로그램의 백엔드 기능을 개발하는 과정에서 기능을 분석하고 이를 문서로 남기는 방법에 대해 작성을 한다.

2. 기능 분석 및 설계

개발을 진행하면서 개발하는 기능에 대해서 분석행위를 하지 않는 사람은 없을 것이다. 분석행위를 하지 않는다는 것은 본인이 무엇을 개발하는지도 모르고 기계처럼 다른 사람의 지시에 의해서 타이핑을 하는것이지 개발을 하는것이 아니다.

기획자가 따로 있어서 화면설계서를 보면서 기능개발을 한다고 가정을 해보겠다. 화면에서 어떤 버튼을 클릭하면 어떤 조건에 대해서 검사를 하고, 조건이 만족되면 어떤 결과가 도출된다는 것이 정의되어 있을 것이다. 이때 백엔드를 개발할때는 화면에 대한 생각을 없애야 한다. 화면에서 발생하는 하나의 트리거에 의해서 백엔드에서는 두가지, 세가지 이상의 기능이 실행될 수 있다. 그렇기 때문에 화면을 참고해서 우선 기능분리를 해야된다. 앞의 예를 조금 더 자세하게 해서 사용자가 회원가입을 하기 위해 정보를 입력하고 가입 버튼을 눌렀을 때 아이디 중복검사, 비밀번호 정합성 검사를 거친 뒤 이를 만족하면 회원정보를 저장하고, 저장된 정보를 반환하는 기능을 개발해야된다고 가정을 하겠다. 기능 분석을 하지 않고 그저 화면설계서에 정의된 내용대로 가입 버튼을 눌렀으니 하나의 메소드에서 화면설계서에서 정의된 내용을 모두 하도록 개발을 한다고 가정을 해보겠다. 화면에서 하나의 트리거에 의해 발생했으니 하나로 묶어서 개발을 해서 결과값을 반환하게 된다면 처음 개발은 편할 것이다. 또한 코드가 한곳에 있으니 코드를 추적하기 쉬워보이기도 한다. 하지만 기능이 확장되거나 재사용되는 경우를 생각해보면 분리해서 개발하는 것이 좋다. 비밀번호 수정하는 기능이 추가되어 비밀번호 정합성 로직이 다른데도 필요하다고 생각을 해보자. 그렇다면 이때서야 비밀번호 정합성을 검사하는 로직을 분리해서 구성을 하거나, 최악의 경우 Copy&Paste로 코드를 복사해서 사용할 것이다. 비밀번호 정합성을 검사하는 로직이 그래도 메소드 내부에서 잘 구분되어 있어서 분리하기 쉽다면 좋지만, 다른 부분과 엮여서 분리하기 어려운 경우도 많다. 이 때문에, 최초에 개발을 진행하기 전에 기능에 대한 분석이 필요한 것이다.

기능 분석을 할 때 우선 어떤 기능들이 있는지 기능 리스트업을 해야된다. 앞의 예시에서는 아이디 중복검사, 비밀번호 정합성 검사, 회원정보 저장 이렇게 3가지 기능이 있다. 이 외에도 비기능 요구사항에 의해 실행 로그를 저장한다고 한다면 로그를 저장하는 기능까지 4가지 기능이 필요하게 된다. 기능 리스트업을 하면 상세 기능에 대한 분석이 필요하다. 비밀번호 정합성 검사를 예로들면 어떠한 규칙으로 정합성 검사를 하는지에 대해 분석을 하는 것이다.

기능에 대한 분석이 완료되면 설계를 하게 될 것이다. 회원정보를 저장하는데는 아이디 중복검사와 비밀번호 정합성 검사는 기능 요구사항이므로 기능 실행에 대한 필수 필요조건이 되고 UseCase로 표현하면 include 관계가 된다. 따라서 회원정보를 저장하는 로직에서 아이디 중복검사와 비밀번호 정합성 검사를 호출해서 사용하도록 개발을 할 수 있다. 실행 로그를 저장하는 행위는 비기능 요구사항으로 회원정보를 저장하는 로직에서는 실행 로그가 저장되는지 알 필요가 없다. 따라서 실행로그를 저장하는 행위는 회원정보를 저장하는 로직에 포함되지 않고, 회원정보를 저장하는 로직이 실행는 전 후로 실행되도록 개발을 할 수 있을 것이다. 이런 식으로 기능에 대한 기본 분석 이후에 기능의 호출 관계 및 실행 순서에 대해서 설계를 할 수 있다. 또한 이런식으로 기능을 분석해서 분리해서 개발을 하게 된다면 이후에 동일한 기능을 사용하는 기능이 추가될 때 추가개발범위가 줄어들게되는 이점이 있다.

기능을 분리하는 것은 어려운 일이다. 추가확장의 가능성이 없어서 분리할 필요가 없는데 분리하여 오버스펙이 될 수도 있고, 추가확장의 가능성이 없어서 분리하지 않았지만 뜬금없이 추가확장이 되는 경우도 있다. 이 때문에 기능을 분리할 지 하나로 합칠지에 대해서는 많은 고민이 필요하고 많은 경험이 필요하다.

3. 기능 명세 작성

기능 명세를 작성하는데는 특별한 룰은 없는 것 같다. 분석된 기능의 내용을 상세하게 기록하면 된다. 필자의 경우에는 우선 기능의 기본 기능에 대해 작성을 한다. 기본 기능에 대해서 작성한 이후에는 특이케이스 및 예외사항에 대해 작성을 한다. 그 다음에는 어떤 값을 가지고 이 기능을 실행하면 어떤 결과가 도출되는지에 대해 작성을 한다. 기능 명세는 상세하게 작성하면 할 수록 좋다. 그만큼 기능에 대해서 더욱 명확해지기 때문이다. 이렇게 작성한 명세서는 시나리오별로 잘 분리해서 Test Case로도 사용할 수 있다. 기능분리를 했고, Input/Output에 대한 내용을 정리했고, 특이케이스 및 예외사항에 대해 정의를 했기 때문에 가능한 일이다. 또한, 분석과정에서 기능의 호출관계에 대해서도 분석을 했기 때문에 Mock 대상에 대해서도 명확해지게 된다.

기능 명세를 작성하면서 주의할 점은 백엔드 기능에 대해 정의하는 것이므로 화면에 대한 내용이 들어가면 안된다는 것이다. 백엔드 개발자는 기능분석/설계를 하는 과정에서는 어떠한 경우라도 화면을 배제해야 된다.

4. 결론

기능을 분석하고 명세를 작성하는 것은 매우 어려운 일이라고 생각한다. 초기 개발과정에서는 쓸데없는 일로 오히려 리소스만 더 소모하는 것으로 보여질 수도 있다. 하지만 지금 당장이 아닌 미래를 본다면 충분히 가치있는 행동이고, 꼭 필요한 행동이다. 문서를 작성하다보면 더욱 많은 고민을 하게 될 것이고, 코드 뿐만 아니라 개인에게도 고민을 통해 얻는 이점이 충분히 있다고 생각을 한다. 또한, 기능을 분석/설계하는 행위와 명세를 작성하는 행위는 Test Case를 작성하는것이나 클린코드를 작성하는 것과도 밀접한 연관관계를 가지고 있기 때문에 이에 숙달되면 개발을 하는데 많은 도움이 될 것이라 생각을 한다.

문서를 작성하지 않는 것보다 더욱 위험한 행동은 문서를 업데이트 하지 않는 것이다. 없는 정보는 처음부터 찾아보면 되지만 잘못된 정보는 처음부터 찾아보지 않을 수 있고 이로인해 잘못된 판단을 할 수 있기 때문이다. 문서를 작성하지 않았다면 지금부터라도 문서를 작성하는 것에 습관을 들이고, 문서를 업데이트하는 습관을 들이는 것을 추천한다.