리팩토링에 대한 회고

Author Avatar
Jong-Ho Jeong Sep 10, 2019

작년, 학교를 졸업하고 처음으로 스타트업에 프론트엔드 개발자로 입사했다. 입사 전 들었다시피 이커머스, 온라인PT 두가지의 서비스를 운영하고 있었고, 서버는 Python의 Django, 프론트는 React와 jQuery를 사용하고 있었다. 내가 입사했을 때 프론트개발자는 나까지 이제 막 두명이 되었다.

입사 후 며칠정도 내가 개발/유지보수해야하는 코드를 읽었다. 나는 실무경험이 부족한 신입 개발자였고, 당연히 실제 회사에서 서비스하고 있는 코드를 한번도 제대로 본적이 없었다. 내가 읽어본 다른사람의 코드라고는 깃헙에 Todo App따위로 구현되어 있는 Best practice와 라이브러리 공식 문서의 데모, 그리고 가끔 어떻게 구현되어있나 궁금해서 들여다 본 오픈소스의 코드 조각이 전부였다. 그랬기에 이 서비스의 코드베이스는 꽤나 충격적이었다. 내가 예상했던 "몇만명이 이용하고있는 실서비스의 코드"와는 많이 달랐기 때문이다. 경험없는 신입개발자인 나는 좀 더 견고한 코드를 기대하고 있었다. 학교에서 배운 디자인 패턴과 자료구조등이 맞물려 아름답게 돌아가고, 배포 한번 한번이 신중한 테스트를 거쳐서 이루어질것이라고 생각했다. 하지만 내 앞에 놓인 코드는 "현재"에 치중한 코드였다. 위에서 아래로, 많은것이 한곳에, 생각의 흐름대로 짜여있었다. 그래서 적잖이 당황했다.

나는 항상 수많은 경우의 수가있음을 고려하는 성향이 있다. 그리고 개발의 세계에는 내가 이해하지 못하는 깊은 수들이 없이 존재하기 때문에, 단순해보이는 코드에도 뭔가 깊은 뜻이 숨어 있을 수도 있다고 생각했다. 그래서 많은 부분을 질문했다. "왜 이렇게 되어있어요?"는 내가 입사한 달에 가장 많이 했던 질문이었다. 개중에 내가 너무 부족해서 모르는것이라고 생각하고 넘긴 부분도 많았다. 이렇게나 많은 사람들이 사용하는 서비스를 유지보수하는것도, 내 옆에 앉아있는 사람이 짠 코드를 읽는것도, 그 코드에 관해 구글이 아닌 누군가에게 물어보는 것도 처음이었다. 그래서 나는 "왜 이렇게 되어있어요?"라고 질문하면 모두들 "제가 처음이고 경험이 없어서 잘 모르겠는데, 혹시 이 코드를 구현한 방식에서 의도된 바가 있을까요?"라고 받아들일줄 알았다. 나는 정말 그저 why가 궁금했던건데, 누군가에겐 "왜 이렇게?"가 "왜 이따위로?"로 인식 될 수도있음을 나중에서야 알게되었다.

어느정도 코드를 읽고난 뒤, 이 서비스의 프론트엔드 전반이 리팩토링이 필요하다고 판단했다. 그래서 우선 리팩토링을 해야하는 이유를 정리해서 팀장님께 메일로 보냈다. 그 이유는 크게 다음과 같았다.

  • Container와 Component를 구분하지 않고 있다
    리팩토링을 결정했던 가장 큰 이유이다. 컨테이너 컴포넌트와 프레젠테이션 컴포넌트를 나누어, 관심사의 분리와 재사용성을 높이는 패턴은 리액트를 사용한 프로젝트에서 거의 필수적으로 사용되다시피하는 유용한 패턴이다. 하지만 레거시 코드는 한 페이지당 한 컴포넌트로 이루어져있었다. 그러다 보니 파일하나하나가 길어지고 기능하나를 수정하기 위해 모든 곳을 읽어야했다.

  • Redux를 마치 전역변수처럼 사용하고있다.
    Redux 스토어에 object가 아닌, primitive가 저장되고있어서 많은 효율적이지 못한 참조가 있었다.

  • 라이브러리가 구버전에 머물러있는것이 많다.
    React는 그때 막 대격변의 v16이 나오고 있었기때문에 프로덕션에 적용하기는 이른 상황이었지만, React router3와 Webpack1 은 빠르게 업데이트가 필요했다. 특히 Webpack4의 사용은 트리셰이킹과 minify 때문이었는지, 모듈업데이트만으로 프로덕션 번들사이즈가 절반이상줄었다.

  • 코드 컨벤션이 없다.
    Linting이나 fomatting이 없어서 버전관리와 코드 일관성 유지가 어려웠다.

이 외에도 로직의 반복이나 사용하지 않는 코드가 주석으로 남아있는 등의 이슈가 있었다.

모든 입사자들은 3개월간의 수습기간을 통해 평가받고, 또한 반대로 회사를 평가하는 제도가 있는데, 나는 이 리팩토링을 통해 평가받고 싶었다. 그리고 회사가 리팩토링에 대해 어떻게 생각하는지를 통해 회사를 평가하고 싶었다. 내가 작성한 코드가 다른사람을 설득할 수 있는지 궁금했다. 3개월을 목표로했던 이 리팩토링 프로젝트를 17개월동안 하게될것이라는걸 그때는 알지못했다.

처음 한달정도는 서비스를 파악하는데 많은 시간을 들였다. 정리된 명세가 없었기 때문에 이것저것 눌러보고 바꿔보며 파악할 수 밖에 없었다. 프로젝트를 셋팅하고, 스캐폴딩을 한 뒤, 페이지별로 작업을 시작했다. 하지만 마냥 리팩토링에만 집중할 수는 없었다. 서비스가 두개인데 프론트엔드 개발자도 두명이었기 때문이다. 또한 대부분의 스타트업과 마찬가지로 업무요청 프로세스도 어설펐기때문에 실시간으로 들어오는 이슈를 처리하는데 많은 시간을 쏟았다.

하지만 이렇게 불안한 환경이었어도, 아니 어쩌면 불안한 환경이었기에 하루하루가 재미있었다. 서비스의 관점에서 모든 회사의 구성원이 깊이 고민하고 성장을 위해 노력하는 조직이었다. 기술적으로는 어떨지 몰라도, 서비스 측면에서는 구성원 모두 많이 고민하며 발전해 온 느낌이었다.

그렇게 나는 몇개월동안 혼자하는 공부로는 할 수 없는 것들을 경험했다. 내가 만든 버튼을 하루에도 몇천명이 눌렀다. 하지만 버튼을 잘못만들어서 몇천만원이 왔다갔다할 정도의 부담감은 아닌 적당한 긴장감을 가질 수 있는 규모. 첫 회사로 나쁘지않았다. 그리고 다행히 회사도 내가 핏이 맞는다고 생각했는지, 수습 3개월, 그리고 정규직으로서 4개월, 5개월이 정신없이 흘렀다.
그렇게 시간이 가면서 회사는 조금씩 흔들리며 성장했다. 그에 따라 점점 리팩토링에 들이는 시간은 줄어들고 새로운 기능, 버그수정에 투자하는 시간이 늘어났다. 심지어 연말부터는 회사에서 “프론트엔드 개발자” 라는 포지션이 나 혼자가 되었다. 이때부터는 사실상 리팩토링 작업은 하지 못했다.

리팩토링 코드의 라이브가 계속해서 미뤄진 가장 큰 이유이자 변명은 스타트업이 생존해나가면서 부딪히는 현실적 요건이다. 코드의 설계나 가독성보다 버튼의 색을 변경하거나 이미지 하나를 교체하는게 회사의 “현재”에 더 중요했다. 모든걸 하기엔 너무 벅찼다. 이전의 개발자도, 나도, 나중에 들어올 개발자도, 우리 모두가 그때그때 바뀌는 요건을 재빠르게 수용하면서 머리속으로는 코드의 설계와 확장까지 고려할 수 있는 슈퍼개발자는 아니기 때문이다.
또한 다듬어진 테스트 프로세스가 없었다. Quality Assurance라는 직무가 없었기 때문에 테스트는 개발자 주도하에 여러 포지션의 실무자가 적당히 진행했다. 꼼꼼한 개발자는 꼼꼼하게, 그렇지 못한 개발자는 그렇지 못하게 테스트를 하다보니, 기능의 품질이 일정치 못했다. 테스트 코드가 필요한 이유가 와 닿았다. 리팩토링 코드가 최소한 비즈니스로직 선에서는 잘 동작할 것이라는걸 보장할 수 있었다면 좀 더 빠르게 라이브할 수 있었을것이다. 그리고 처음에는 데드라인도 찍지 않고 대충 이쯤 라이브 할 것이다 정도로 놓고 작업했다. 리팩토링이 필요한 이유에 대해 다른 팀원들을 설득하려 하지않았고, 잠수함라이브를 하려고 했던것 같다. 그러다보니 리팩토링의 우선순위는 항상 가장 밑에 있었고, 기간이 길어지면서 리팩토링에 리팩토링이 반복되었다.

그렇게 엉금엉금 레거시의 버그수정도 따라가기 벅찰때쯤, 새로운 프론트개발자분이 입사했고, 그 분이 업무에 적응할 때 쯤, 약간은 무리해서 여러사람들의 도움(사람이 하는 테스트)을 받아 리팩토링 코드를 라이브했다. 사실상 모든 로직을 다시짰으며, 배포프로세스도 완전히 바꿨다.
17개월전에 짜기 시작한 코드가 우여곡절끝에 드디어 유저에게 도달한것이다.

webpack-analyzer

경험부족한 개발자이기에, 긴 리팩토링 후에 여러가지를 느낄 수 있었다.

  • 리팩토링은 끝이없다
    기술은 빠르게 발전하고, 요구사항은 더 빠르게 바뀐다. 개선이 필요한 부분이 보이지 않는다면 성장하지 못하고있기 때문일것이다.

  • 마일스톤을 정하자
    끊고가는것이 필요하다. 이번 스텝에 어디까지 가져갈건지를 정해야한다. 그렇지 않으면 끝이 없다.
    한번에 전체 서비스를 리팩토링하려고 했기때문에 테스트의 범위가 커지고, 작업량이 많았다. 가능하다면 리팩토링은 부분적으로 하는것이 좋다. 그러기 위해선 최소한 부분적으로 손댈 수 있는 코드를 짜야한다.

  • 테스트코드의 중요성
    테스트는 이제 선택이 아닌 필수다. 서비스의 형태가 점점 더 복잡해지면서 더 이상 테스트를 일일이 해볼 수 없게되었다. 휴리스틱한 테스트로는 내가 만든 기능이 대다수의 유저에게 잘 동작하고 있음을 보장할 수 없다. 테스트환경을 만들고 자동화해야 한다.

  • 혼자 할 수 없다
    리팩토링은 새로운 기능이 아니다. 고객들은 코드가 달라졌다고 상품을 더 구매하지 않는다. 그렇기 때문에 회사는 리팩토링을 위해 시간을 쓰는 개발자를 언제까지나 기다릴 수 없다. 리팩토링을 위한 시간을 위해선 필요한 이유를 비개발팀원들에게 설명하고 설득해서 그것을 위한 시간을 마련해야한다. 리팩토링에 너무 치중해도 안되지만 유구한 설득에도 회사를 설득하기 힘들다면 깔끔하게 포기하는게 좋을지도 모른다.(리팩토링 혹은 회사를…)

17개월동안의 리팩토링을 일단락 했지만 여전히 수정하고 싶은것들이 많이 남아있다. 타입스크립트를 도입해야 하고, 상태관리도 좀더 구조화가 필요하고 최적화도 고려할 부분이 많다. 하지만 회사에서 만들고 싶어하는 기능은 여전히 많고 앞으로는 더더욱 많아질것이다. 그에따라 분명 팀원의 수도 늘어날것이다. 손 하나보단 손 두개가 분명 더 많은 기능을 만들 수 있을테니까. 하지만 최근에 읽은 글 중 “빨리 가는 유일한 방법은 제대로 가는 것이다” 라는 로버트 C. 마틴의 글을 보고 회사 생각이 많이났다. 우리는 그렇지 않다고 부정하지만, 생각 깊은곳에 자리 잡고 있는 “우선 동작할 수 있는 기능을 만들자” 의 마인드가 어쩌면 “개발자의 수가 늘었는데 과연 생산성도 그만큼 늘었는가?” 라는 질문에 대한 힌트일지 모른다. 모든 개발자들은 회사에서 놀지 않는다.


일개 주니어 개발자의 얘기를 듣고 전체 서비스의 리팩토링을 결정한다는건 쉽지않은 일이라는 걸 알기에 의견이 받아들여졌음에 감사한다. 덕분에 귀중한 경험을 해 볼 수 있었다.

지금은 회사의 두 서비스중 나머지 하나를 리팩토링하고있다. 어쩌면 내가 개발자라는 Role에서 해야하는일은 회사가 하고싶어하는 수 많은 기능개발과 좀 더 아름다운 코드 사이를 조율하는 역할일 수도 있다. “기능개발”이 회사가 지금 생존하는데 더 중요하다는건 부정할 수 없지만, 당장을 위한 코드는 회사의 성장을 빨리 지치게 만들것이다. 앞으로는 회사의 성장과 개인의 성장을 위해서라도, 타이핑하는 시간보다 생각하고 고민하는 시간이 좀 더 많아졌으면 좋겠다.