brunch

실행만 되면 일이 끝나냐?

코드의 정원 가꾸기

by 동그리

"어? 이거뭐야. DB 테이블 누가 바꿨어?"

오후 9시가 넘어가는 사무실. 개발자들은 오늘도 퇴근하지 못한채 야근을 하고 있다.

당장 며칠뒤로 다가온 프로젝트 중간보고에 기능 시연을 해야하기 때문이다.

계획된 일정보다 늦어지고 있고 주요 기능들의 진척율이 너무 낮은건 큰 문제였다.


마음은 급하고 해야할 일은 산더미다.

그러던중 개발을 하고 있는데 프로그램 오류가 발생했다. 분명 잘 동작하던 기능이었다.

오류 메시지를 보니 테이블 구조가 내가 작업 하고 있던 소스코드와 달라서 나는 문제였다.

공유된 설계서와 필드명도, 구조도 다른 테이블이 여러개 발견되었다.

아무래도 다른 파트를 맡고 있는 개발자가 사전에 공유도 하지않고 테이블 구조를 바꾼것 같다.

마음대로 바꿀거면 나에게 설계를 왜 하라고 했는지 모르겠다. 썩 기분이 좋지 않았다.


소스코드 버전관리는 svn으로, 개발용 데이터베이스는 하나를 구축해서 공용으로 사용하고 있었다.

각자 개발을 하면서 소스코드를 변경한 영향은 단위작업이 어느정도 정리될 즈음 커밋한 이후에 일어난다.

하지만 데이터베이스는 실시간으로 같이 사용하고 있기 때문에 영향을 즉시 받는다.

짜증은 나지만 서로 급하고 힘든것을 알기 때문에 당장 눈 앞에 있는 오류 해결에 집중한다.


소스코드상의 키워드 불일치 같은것은 통합개발환경(IDE)에서 쉽게 찾아서 수정할 수 있다.

하지만 별도의 환경인 데이터베이스에서 테이블 등의 데이터 모델이 바뀐것은 이런 도구의 도움을 받을 수 없었다.

요즘은 Java 웹서비스 개발에서도 JPA등의 데이터 모델을 코드에 직렬화 하는 기법을 많이 사용한다.

하지만 아직까지도 대부분의 SI 구축사업에서 사용되는 기술은 예전 기술 그대로를 이어가고 있다.

결국 사람의 눈으로 하나씩 찾아가며 수정해야한다.


우선 데이터베이스 불일치가 해소될까 싶어, svn서버에 반영된 공통 소스코드를 내 환경에 업데이트 했다.

여러건의 수정사항이 내 소스코드에 반영되었다. 하지만 지금 눈앞의 문제는 해결 되지 않았다.

언제까지고 기다릴 수 없으니 직접 문제를 해결하기로 한다. 그런데 더 큰 문제가 발생했다.


"하아... 이건 또 뭐냐."

아까까지만 해도 잘 되던 기능이 안된다.

영향도가 한눈에 파악되는게 아니라 기능을 처음부터 화면기능들을 눌러가며 체크하는 수 밖에 없다.

내가 개발하던 기능에 직접 영향이 가는것도 몇가지 있고, 내가 당장 신경쓸 필요는 없는것도 있다.

눈으로 확인 되지 않은 문제도 많을것이다. 하지만 이 모든걸 검증하기에는 시간이 없다.


결국 다른사람 일은 알아서 하겠지 하고 눈 앞의 일에만 집중하게 된다.

그리고 그 다음날 svn으로 다른 개발자가 작성한 코드와 병합하려니 충돌이 발생한다.

코드를 정상적으로 병합하기 위해서 진땀을 뺀다.

그리고 몇시간뒤 업데이트를 받아보면 내가 작업했던 부분이 사라져있다.

다른 개발자가 svn 충돌이 나는 부분을 병합하면서 주의깊게 보지 않고 자기 작업본을 그냥 서버에 올려버렸다.


이쯤되면 회사 동료가 아니라 원수다.

아까운 내 시간을 이 사람들이 한 일들을 뒷바라지 하느라 쓰고있다.

마음만 급하지 아무리 시간을 들인다한들 작업 진척율이 빠르게 올라갈 일은 없었다.

각자 자기 개발환경에서 잘 실행된다고 일이 끝났다고 착각하고 있는것이다.


결국 목표로한 날짜까지 진척율을 올리지 못해 중간보고는 실제 소프트웨어 기능 시연 없이 이루어졌다.

그리고는 프로젝트 마지막 날짜가 되는날까지 계속되는 야근을 감당해야했다.

네모로 된 바퀴를 단 수레를 끄는것처럼, 낮은 생산성으로 프로젝트를 마무리 하기 위해 달려갔다.

개발이 완료된 소프트웨어가 아니라 컴퓨터앞에 오래 앉아있는것이 우리의 실적이었다.


사람은 일을 잘 하기 위해서 계획을 세운다.

그리고 그 계획에 따라 목표를 이루기 위해 한단계씩 할 수 있는 일을 한다.

하지만 사람의 능력에는 한계가 있기 때문에 계획은 완벽하지 않을 수 있다.

그래서 현실과 맞지 않는 부분은 조금씩 수정해 나가게된다.


소프트웨어도 목표에 따라 기능하도록 앞으로 해야할 일을 계획하는데, 이것을 설계라고 한다.

다양한 지식과 경험을 지닌 전문가가 설계를 하지만 완성된 형상을 예측하는것에는 한계가 존재한다.

그래서 기능을 구현하기 위해 필요한 요소를 추가 및 변경하는 일은 현장에 투입된 개발자의 판단하에 수행한다.


일정을 넉넉히 주는 경우는 드물기 때문에 각자 맡은 일을 쳐내기에도 바쁘다.

그래서 SI 개발 현장에서는 어지간하면 다른 개발자의 코드에 토를 달지 않는것이 불문율이다.

하지만 서로의 일을 방해하고 있는 지경에 이르렀다면 이것은 다른 이야기다.


잘 동작하던 기능이 동작하지 않게 되는 주된 이유는 개발자의 의도와 실제 환경이 다르기 때문이다.

소프트웨어는 말하자면 논리의 집합이다. 논리적으로 이치에 맞지 않으면 제기능을 할 수 없다.

A라는 기능이 동작하기 위해서는 B라는 전제 조건이 필요한데, B가 C로 변경된다면 A는 오류가 발생할것이다.

소프트웨어에 기능을 추가하면서 이런일은 빈번하게 발생한다.

다 지어진 건물의 조경이 마음에 들지 않는다고 건물째로 오른쪽으로 10cm 옮겨달라는 요구는 말도 안된다.

하지만 소프트웨어는 이 정도 부담을 지게되는 대담한 수정이 종종 요구되곤 한다.

그래서 소프트웨어를 최초 구축하거나, 기능을 추가하는 등 여러가지 이유로 오류가 날 수 있다.


손발이 잘 맞는 개발자들끼리 협업을 하면 이런 일이 일어나는 경우는 적어진다.

또는 아예 프론트, 백엔드 등 영역을 나눠서 혼자서 모든걸 감당해버리는게 리스크를 줄이는 방법일지도 모른다.

하지만 업무 영역을 나눠버린다고 해서 이런일이 일어나지 않는다는 보장은 어디에도 없다.

전체 동작을 이해하지 못한 후임자가 최초 개발의도를 무시한 코드를 삽입해서 문제가 생기기도 한다.

결국 개발 시점에 상관없이 여러명의 개발자들의 이해가 충돌하기 때문에 생기는 문제다.


모든 고객은 오류가 나는 소프트웨어를 사용하고 싶어하지 않는다.

그래서 일반적으로 개발자는 사용자에게 배포되는 소프트웨어의 오류를 감추려고 노력한다.

try ... catch 등 오류가 나더라도 무시하고 넘어가는 코드 블럭을 남발하는것이다.

그러다보니 눌러도 반응없는 UI, 팝업되는 알 수 없는 오류 코드, 예상할 수없는 이상한 동작 등 문제가 발생한다.

사용자가 컴플레인을 걸거나 이탈해가는데, 개발자는 오류의 원인을 알지 못해 대처하지 못하고 시간만 간다.


물론 오류가 나지 않게 개발하는것이 가장 좋지만, 모든 미래를 예상해서 개발을 하는건 비현실적이다.

컴퓨터는 실수하지 않는다. 다만 소프트웨어 품질 측면에서 봤을때 컴퓨터는 종종 믿을 수 없을만큼 바보같다.

주요 데이터의 흐름과 관계가 하나라도 어긋나는 순간 전체 소프트웨어가 동작을 멈출수도 있다.

그래서 개발자는 소프트웨어를 이루는 논리가 개발자의 의도대로 잘 구성되어 있는지 검사할 필요가 있다.

오류 복구 및 대응 능력이야말로 소프트웨어 품질을 유지하는데 있어 가장 중요한 요소인것이다.


이런 이야기를 하려면 다양한 주제로 이야기 할 수 있을것이다.

코드를 작성하는데 있어서 클린코드를 유지해야 한다거나, 결합도는 낮추고, 응집도를 높이는 등 객체지향 프로그래밍 원칙을 따라야 유지보수성이 좋아진다거나 하는 이야기를 할 수 있을것이다.

하지만 이러한 주제는 같이 일하는 모든 개발자들이 동참하는 문화가 없다면 아무런 의미가 없다.

누군가는 정리정돈하고 누군가는 어지럽히기만 할 뿐이다.


혼돈스러운 프로젝트를 어떻게든 끌고가기 위한 최소한의 목표는 무엇으로 삼는게 좋을까?

나는 이 모든 소프트웨어 생산성 저해의 문제는 테스트주도개발(TDD)를 하지 않기 때문이라고 확신한다.

테스트를 작성하면서 기능을 개발하고, 수시로 테스트가 정상작동 하는지 검사하는 간단한 개발방법이다.

결과적으로 소프트웨어를 이루는 모든 코드가 개발자의 의도를 벗어나지 않는다는 보장을 할 수 있다.

모든 개발자가 참여하는것을 강제할 필요는 있지만, 그만큼 전쟁터 같은 프로젝트를 헤쳐나가는 힘이 될것이다.


소프트웨어가 정상동작하고 있다는 증거를 쌓으면서 개발하는것은 엄청난 힘이 된다.

테스트가 살아있는 문서가 되어 시간이 흘러 길잃은 후임자가 나타나더라도 나아가야할 방향을 제시해줄것이다.

선대 개발자가 남겨줄 수 있는 최고의 유산이다.


이러한 방식으로 업무를 이어나가다 보면 어느순간 테스트를 작성하지 않으면 불안해서 개발하지 못할것이다.

모든 테스트 확인 요소에 녹색 체크표시가 뜨는것에 희열을 느끼게 된다.

깔끔하게 잘 정돈된 정원을 보는 쾌감과 같다. 프로그래밍을 다시 한번 사랑할 수 있는 동기가 된다.


테스트를 작성하는것은 그만큼 개발하는데 시간을 더 들인다는 의미다.

일정이 바쁜데 쓸데없는짓 한다고 생각할수도있다.

하지만 앞서 이야기 했듯이 마음만 급하다고 진척율은 오르지 않는다.

오히려 테스트가 정상작동 해야한다는 공통된 가치를 서로 이해하고 유지하면 많은 시간을 아낄 수 있다.


개발하는 코드뿐 아니라, 데이터, 서버 환경 등 테스트가 가능한 모든 범위를 포괄하는 테스트를 작성해야한다.

유지관리를 위한 업무 및 비용이 많아지겠지만, 미래를 위한 투자라고 생각하자.

번거롭고 지루한 일을 이겨낸 끝에 소프트웨어 품질이 높아진다면 결국 모든것을 보상 받을 수 있다.


서비스로 급성장한 기업들은 테스트와 클린코드의 중요성을 일찍부터 알아보고 실천하고 있다.

SI 개발사는 그러지 말라는 법이 어디에 있을까?

소프트웨어 품질을 높이는것은 선택사항이 아니다.


과연 당신의 PC에서 코드가 실행되었다고 해서 일이 끝난것일까?


keyword
이전 08화이 화면설계 좀 이상한데요?