ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 소프트웨어 엔지니어의 개발 전 체크리스트
    소프트웨어 엔지니어링 2019. 3. 28. 14:15

    소프트웨어 엔지니어로서 나는 잠재적인 버그를 예방하기 위한 개발 프로세스에 대해 생각할 수밖에 없다. 세상에 버그가 없는 코드란 없지만, 최대한 버그가 나지 않게 하기 위해 항상 노력해야하는 것이 소프트웨어 엔지니어의 운명이라고 생각한다. 또 버그뿐만 아니라 어떻게 하면 유지보수가 쉽고 확장 가능한 소프트웨어를 만들 수 있는지 항상 고민해야 한다. 팀 단위에서는 Waterfall/Agile 같은 프로세스가 적용되고 이 프로세스 상에서 대부분의 문제가 드러나게 된다. 이런 문제 중에서는 빠르게 해결할 수 있는 것도 그렇지 못한 것도 있다. 특히 빠르게 해결할 수 없는 것들은 개발 당시에 우리가 생각도 못했던 것들 일 때가 많다.

    이번 포스트에서는 내가 어떤 이슈(일)을 받았을 때, 일을 시작하기 전 생각하는 것들에 대해서 이야기해 보도록 하겠다. 이는 내가 개발 시작 전 디자인 단계에서 좋은 품질의 소프트웨어를 만들기 위해 개인적으로 반드시 체크하고 넘어가는 사항들이다. 누가 시켜서 또는 검사받기 위해 적용하는 프로세스가 아닌, 오로지 내 코드의 질을 향상하고자 체크하는 것들이다.

    참고!

    좋은 품질의 소프트웨어를 만들기 위해서는 어떤 절차를 따라야 하는데, 이를 소프트웨어 개발 프로세스(Software Development Process)라고 한다. 이런 소프트웨어 개발 프로세스의 예로는 Waterfall이나 Agile 등이 있으며, 최근에는 Agile 개발 방법 중 하나로 Scrum이 많이 사용되고 있다. 이런 소프트웨어 개발 프로세스는 보통 팀 단위에서 적용된다. 그리고 보통 코드 리뷰(Code Review)나 테스팅(Testing) 단계에서 많은 버그가 잡힌다.

     

    [개인용 소프트웨어 디자인 프로세스]

    나는 일을 할당받으면 업무용 노트에 해당 일을 트래킹하기 위한 문서를 만든다. 그리고 그다음으로 하는 것이 바로 위의 템플릿을 복사 붙여 넣기 하는 것이다. 그리고 코딩에 들어가기 앞서 체크리스트의 각 항목을 답한 후 시작한다. 아래에서 각 체크리스트가 무엇을 의미하고 왜 이를 체크하는지에 대해 알아보도록 하겠다.

    요구사항 파악(Requirement Gathering)

    Trello툴에서 가져온 개인용 이슈 중 하나. '원단위절사'라고만 써있고 어디서 뭘 절사하란건지 하나도 적혀있지 않다.

    내가 가장 처음으로 하는 것은 요구사항 파악이다. 보통 프로젝트 관리 툴로 일이 할당되는데 해당 이슈의 설명이 없거나 미비한 경우가 대부분이다. 따라서 가장 처음으로 해당 이슈를 작성한 사람과 논의를 거쳐 해야 할 일이 무엇인지 파악하는 것이 우선이다. 요구사항 파악을 못하면 어차피 개발을 못하기 때문에 반드시 해야 할 일이지만, 전체 요구사항을 기록 해 놓고 나중에 테스팅할 때 쓰기 위해 체크리스트 아래에 문서화해놓는다.

    테스팅 방법과 출시 전략(Testability and Release Strategy)

    어떤 일을 받으면 새 일에 대한 기대감과 불안감에 어떻게 이 일을 해결할 것인가(코드를 어떻게 짤 것인가)에 대해 초점을 맞추는 경향이 있다. 그래서 어떻게 테스팅할 것인가 어떻게 릴리즈/롤백을 할 것인가는 나중으로 미루는 경향이 있다. 하지만 개발을 다 마쳤는데 테스트가 불가능 하다거나, 호환성(Backward Compatibility)때문에 릴리즈를 할 수 없다거나, 어떤 문제가 있어 롤백(Rollback)을 해야하는데 나의 코드가 롤백이 불가능하게 작성되어 있다면 개발을 다시해야 하는 불상사가 발생 할 수도 있다. 따라서 테스팅 방법가 출시 전략의 체크리스트를 통해서 개발 전에 이런 사항들을 짚고 넘어간다.

    이 기능(feature) 또는 버그(bug)를 어떻게 테스팅 할 것인가?

    기능 테스트의 경우 위의 요구사항 파악에서 명시한 것들을 그대로 복사 붙여 넣기 한 후, 각각의 요구사항을 어떻게 테스팅 할 것인지 설계한다. 특히 팀이 관리하는 프로젝트의 규모가 너무 커 로컬 환경에서 프로그램을 실행시키지 못하는 경우 어느 환경에서 어떤 값들을 가지고 테스팅을 할 것인지 명시한다.

    버그의 경우 개발 시작 전 해당 버그를 재생산(Reproduce) 해야 한다. 일반적인 방법으로 버그를 발생시키는 게 불가능하다면 해당 버그를 발생시킬 수 있는 코드를 임의로 집어넣어 개발 시작 전 해당 버그를 확인한다. 예를 들어 최근 데드락을 일으키는 코드를 고치는 업무를 받았는데, 데드락은 부하가 높은 프로덕션(production) 환경(서버)에서 주로 발생하고 테스팅 환경(서버)에서는 잘 발생하지 않는다. 그래서 일부러 데드락을 발생시키기 위해 무한 루프를 넣는다거나, 퍼미션을 제거하는 등 편법으로 일단 버그를 확인한다. 그리고 개발 후 동일한 방법으로 테스팅을 다시 했을 때 올바르게 동작한다면 테스팅을 성공적으로 마친 것이다.

    출시(Release)를 어떻게 할 것인가?

    특히 임팩트(Impact)가 큰 변경사항 일 수록 릴리즈에 유의해야 한다. 만약 해당 릴리즈에 포함된 코드에 버그가 있을 경우 많은 고객 또는 유저들이 영향을 받을 수 있다. 따라서 나의 코드(서비스)가 임팩트가 크다면 Whitelisting 또는 일부 프로덕션만 Release (또는 Canary 릴리즈)하는 방법으로 임팩트를 줄일 수 있다. 이후 코드에 대한 확신이 들면 모든 유저에게 릴리즈 하면 되는 일이다. 

    참고!

    • Whitelisting - 해당 코드(서비스)를 특정 유저만 사용 가능하게 만드는 것이다. 예를 들어 유저 아이디 abcde만 이 코드를 사용 가능하게 만드는 것이다. 
    • Canary Testing - 카나리라고 불리는 특별한 프로덕션 환경을 만들고 이 환경에 먼저 릴리즈를 하는 것이다. 아주 적은 트래픽만 카나리 프로덕션으로 가게 하고 며칠간 문제없이 동작하는지 테스팅한 후 모든 프로덕션 서버로 릴리즈 하는 방법이다. 

    쉽게 롤백할 수 있는가? 어떻게 디자인해야 롤백이 쉬울까?

    롤백(Rollback)이란 릴리즈 이후 어떤 이유로 이전 버전으로 다시 돌아가는 것을 의미한다. 보통 릴리즈 후 심각한 문제가 발견되면 롤백을 한다. 릴리즈는 일정 기간 내에 개발된 코드를 한꺼번에 세상에 내보내는 것이기 때문에, 내 코드에 버그가 있어서 롤백을 할 수도 있지만, 다른 사람의 코드에 버그가 있어서 롤백하는 경우도 많다. 따라서 어느 이슈이든 '롤백을 하는' 상황에 처할 수 있다. 이때 프로덕션 환경에서 문제가 발생해서 롤백을 하려는데, 나의 코드가 롤백이 불가능한 코드라면 우리는 앞으로 갈 수도, 뒤로 갈 수도 없는 상황이 된다. 롤백이 된다면 롤백 후 릴리즈 된 코드에서 문제를 찾을 때까지 시간을 벌 수 있지만, 롤백이 불가능하다면 버그를 찾아서, 고치고, 테스팅하고, 다시 릴리즈하는 과정을 아주 빠르게 해야 한다. 따라서 어떻게 해야 롤백을 쉽게 할 수 있는지, 또 롤백을 어떻게 테스트해야 하는지(세 번째 체크박스)에 대해 생각해 보고 넘어간다.

    테스트 기반 개발 방법(Test Driven Development)

    테스트 기반 개발 방법은 Agile개발 방법 중 하나로 개개인이 적용하기에 아주 좋은 개발 방법이다. 방법은 다음과 같다. 요구사항의 각 사항들을 기능 단위로 쪼개고 해당 기능이 들어갈 클래스/메서드의 껍데기를 만든다. 이후 바디(body) 부분을 구현하기 전에 유닛 테스트(Unit Test)를 먼저 작성한다. 이 단계에서 모든 유닛 테스트는 Fail 할 것이다. 그러고 나서 바디 부분을 구현하기 시작한다. 한 기능 구현 후 해당 기능에 해당하는 유닛 테스트를 돌려 원하는 Pass 하는지 확인한다. 나머지 기능들도 마찬가지이다.

    이런 방법을 택한 이유는 첫 번째로 테스트 기반 개발을 하기 위해서는 설계에 충분한 시간을 들여야 하기 때문에다. 또한 나의 경우 유닛 테스트가 가능하도록 코드를 짜는 것이 중요하기 때문이다. 내 현재 팀은 소프트웨어가 너무 커 로컬 환경에서 돌리지 못한다. 따라서 테스팅 환경에서 테스트하기 전까지는 내 코드가 잘 돌아갈지 아닐지는 유닛 테스트로만 확인이 가능하다. 이런 상황에서 유닛 테스트를 작성하는 것은 내 코드에 대한 자신감을 올려준다. 

    위에서도 말했듯이 처음 이슈를 받았을 때는 이 일을 어떻게 해결할 것인가에 대해 생각하느라 유닛 테스트나 릴리즈와 같은 다른 중요한 사항들을 복합적으로 생각하지 못할 때가 있다. 이런 템플릿과 개발 프로세스를 개개인의 레벨에서 적용하는 것이 나에게는 큰 도움이 된다. 이 프로세스 덕분에 맨 처음 이슈를 받았을 때의 디자인과 이 체크리스트 적용 후의 디자인이 달라질 때도 많고, 간단하게 생각했던 이슈도 실제로는 복잡하다는 것을 깨달을 때가 많다.

    이번 포스트에서는 개발 전에 체크하는 사항들에 대해 이야기해 보았다. 예상할 수 있겠지만 개발 후에 체크하는 사항들은 또 따로 있다. 언젠가 이 블로그에서 소개해 보도록 하겠다.

    모든 팀과 모든 소프트웨어 엔지니어들에게 똑같은 프로세스가 적용될 수는 없겠지만, 이번 포스트를 통해서 자신의 팀 환경에 맞춰 자신이 적용할 수 있는 작은 프로세스를 만들고 자신의 코드 퀄리티를 높이는 데 사용하면 팀에도 많은 기여가 될 것이라 생각한다.

     

    댓글

f.software engineer @ All Right Reserved