[오라일리] 프로그래밍의 규칙 – 더 나은 코드를 작성하는 21가지 개발 비법

“한빛미디어 < 나는리뷰어다 > 활동을 위해서 책을 제공받아 작성된 서평입니다.”

회사를 다니는데 하나의 프로젝트를 혼자서 계속 하는 경우는 드물지도 모른다. 보통은 하나의 프로젝트를 여럿이서 나눠 하면서 각자 맡은 부분을 작성하고 있을 거다. 당연히 GIT 같은 형상관리툴도 쓰고, GitHub 같은 걸 통해 코드리뷰도 진행할 것이다. 페어 프로그래밍을 하는 경우도 있을 것이고… 심지어 ChatGPT를 통해 작성된 코드를 참고해서, 아니면 수정해서 사용하는 경우도 있을 것이다.

그렇게 작업을 하다보면, 나의 코드와 남의 코드 사이에 발생하는 괴리감을 느낀다. 명시적인 코딩 컨벤션이 있다면 그 정도는 덜할 텐데, 암시적인 코딩 컨벤션이 존재하고, 그걸 철저히 준수하지 않아서, 이전 코드와 지금 코드 간의 괴리감도 많이 느낄 것이다. 또한 리뷰어의 성향에 따라 철저하게 코딩 컨벤션을 준수하라고 할 수도, 자신의 스타일을 은근슬쩍 강요할 수도, 이도 저도 아니고 알아서 하라고 할 수도 있을 거다.

누군가가 초기에 세팅해둔 툴 덕분에 코드 컨벤션 일부는 강요되므로 준수해나가는 경우도 있을 것이고, 남이야 어떻든 내 코드는 내 스타일대로, 남의 스타일은 맘에 안 들어서, 무시하고 계속 작성해 나갈 수도 있을 것이다. 남의 코드 수준이 자신보다 떨어지는 것 같아, 내 식대로 다 바꿔버리는 경우도 있다. 그러다가 다른 걸 작업하게 되어 작업하던 프로젝트를 다른 사람이 맡아서 또 바꾸고 하다보니, 어느 순간인가 코드 베이스에 여러 스타일이 넘쳐나서 당최 뭐가 어떻게 돌아가는지 알 수가 없는 경우도 생긴다.

이를 테면, 응답값에서 snake case를 쓰고 있었는데 난데없이 camel case를 쓰는 경우도 있었다. 덕분에 호출하는 쪽에서 일괄적으로 응답값을 관리할 수 없어 경우에 맞게 작성하느라 애를 먹기도 하는데, 또 이걸 이어 받아 작업하던 개발자가 이 사정을 제대로 파악하지 못해 수정했다가 버그가 발생하기도 했다.

여러 사람들과 협업하는 것은, 소통 문제도 문제지만, 결국 결과물이 나오는 것도 문제가 많아질 수밖에 없다. 이걸 해결하기 위한 게 표준이다.

가령 우리가 늘상 사용하는 화장실에서 수도꼭지가 표준을 따르지 않는다고 한다면 어떤 일이 생길까? 뭐 기본적인 사용을 할 때는 문제가 되는 줄도 모를 테지만, 어딘가 고장이 나서 고쳐야 하는 상황이 발생하면 문제가 복잡해진다. 맞는 부품을 구하는 것도, 교체하는 방법도, 표준에 벗어나기 때문에 훨씬 더 많은 비용을 지불해야만 한다.

프로그래밍도 마찬가지였다. 정말 상식적이라고 생각하는 부분은 표준을 따를지도 모르겠지만, 실제 작업하는 영역에 들어오면 이 표준이 있냐 없냐에 따라 결과물이 확연히 달라진다.

20년이 넘는 개발을 해오면서 저자가 말하는 실수를 사실 지금도 하고 있다. 안타까운 것은, 어쩌다보니 십수 년째 한 프로젝트를 혼자하는 경우가 너무 많았다는 거다. 그러다보니 이러한 점을 지키는 게 의외로 암묵적으로 진행하고 있었다. 그래서 팀원이 가끔 생길 때마다 이걸 조율하는 게 쉽지가 않았다. 사실 누구나 자신만의 스타일을 갖고 있다보니 자기가 편한대로 개발하고 싶어 했다. 그런 이유로 어느 순간 굉장히 기본적이 굉장히 명확한 부분은 어느 정도 서로 인정하는 표준을 따르게 되는데, 그게 보통은 해당 언어가 보편적으로 따르게 다소 강제하는 부분이라거나, 사용하는 lint 툴의 가이드라인대로 진행하는 거다. 이건 언어 측면의 표준 정도일 뿐이고.

좀더 고차원으로 올라가면, 경험칙만 있다. 몇 년 동안 나보다 고수 개발자들한테 귀동냥으로, 때로는 코드 리뷰를 받으며 깨지고, 또는 작업했던 코드가 버그를 유발해서 그에 대한 반성으로 등 다양한 방면에서 얻은 그 경험칙들이다. 이걸 문자로 남기는 건 제대로 하지 못했는데, 이 책에서 상당히 많이 볼 수 있었다. 아쉬운 점이라면 저자가 비디오 게임 개발자여서, 게다가 C++ 개발자여서, 알려주는 점과 예제 코드가 이해는 되지만, 완전히 와닿지 못하는 점이 있다는 아쉬움은 있다. 하지만 대체적으로는 내가 완전히 수긍하고 또 역으로 배워서 써먹을 점이 많은 부분이 있음을 부정할 순 없다.

제일 와닿는 규칙을 몇 개 나열해보면 아래와 같다.

규칙 01. 최대한 단순하게, 그러나 너무 단순하지 않게
규칙 02. 버그는 전염된다
규칙 03. 좋은 이름은 최고의 문서다
규칙 08. 실행되지 않는 코드는 작동하지 않는다
규칙 13. 산사태를 일으킨 조약돌을 찾으라
규칙 15. 잡초를 뽑으라

그외 규칙은 조금 이해가 되거나 잘 납득할 수 없는 규칙들이다. 틀렸다고 말하고 싶은 게 아니라, 어딘가 나한테는 맞지 않는다거나 공감할만한 경험을 해보지 않은 게 아닐까 싶다.

팀원이 있던 시절, 그 팀원에게 한 얘기가 규칙 01이다. 그 전에 나도 어렴풋이 알고 있었다가 코드 리뷰를 받으면서 리뷰어에게 들은 말이기도 하고, 실제 그렇다는 걸 코드로 증명까지 해봤기 때문에 가장 가치 있는 규칙이다.

내가 리뷰를 하는 날인데, 코드가 무척 장황하게 만들어 왔더랬다. 불필요한 코드도 잔뜩 들어 있고 결론에 이르는 과정이 꽤나 복잡하기도 했던 그런 코드였다. 그래서 간단하게 말한 내용이다.

“코드가 길면 무조건 버그가 있는 겁니다.”

그걸 저렇게 잘 풀어내면 규칙 01. 최대한 단순하게, 그러나 너무 단순하지 않게, 가 된다. 그러면 그 팀원은 어떻게 했을까? 다시 작업해서 딱 필요한 내용만 남기고 정리해 왔다. 결론은? 잘 동작했고, 오히려 단순하게 했기 때문에 코드 상으로만 봐서는 알 수 없는 오류를 잘 파악할 수 있어서 코드 보완이 수월했다. 외부 입력값이 문서나 경험을 벗어나는 값으로 전달 받아서 버그가 발생할 수밖에 없었던 상황이었기 때문이다.

규칙 02. 버그는 전염된다. 이거 부정할 수 있는 사람 있을까? 버그는 무조건 다른 버그를 유발한다. 사용자에게 잘못된 행동을 유발시키든, 화면 처리를 요상하게 하도록 잘못된 코드를 양산시키든, 해당 버그를 가진 코드를 호출해서 내가 잘못된 결론을 내고 엉뚱한 코드를 작성하든, 아무튼 한 번으로는 안 끝는다. 그 여파는 지속되어 최악의 경우 잘못된 데이터를 생성해 DB 데이터까지 요염시킨다. 그러면 그 오염된 데이터 때문에 데이터팀이든, CS팀이든 개발팀 내 다른 팀원이든 그들의 업무를 대폭 늘리게 된다. 그러니 버그는 전염이 맞다.

규칙 03. 좋은 이름은 최고의 문서다. 이걸 부정하는 개발자가 있을까? 일을 하다보면 다소 근시안적인 접근을 하는 개발자, 기획자가 은근 많다. 지금도 변수 이름 하나, 함수 이름 하나 정할 때마다 어려움을 겪곤 한다. 이름 한 번 잘못 정하면 두고두고 그 뜻을 이해하느라 애를 먹는다. 보통은 당장의 그 시점만 고려하는 경우가 많다. 하지만 한 번 쓰고 버릴 코드가 아니라면 이걸 사용하기 시작하는 시점과 이를 중간에 다시 쓰는 시점 등 다양한 시점을 고려해야 하는데, 상상력 부제인 건지, 당장의 문제만 해결하면 된다는 건지, 지금 당장만 통하는 경우만으로 이름을 정한다. 그러면 지금은 의미가 있을지 모르지만, 시간이 지나면 십중팔구 문제를 일으키기 쉽다. 이걸 이해하려면 경험이 쌓여야 하는 것 같다. 아니면 백날 얘기해도 이해하지 못할 게 뻔하니까.

규칙 08. 실행되지 않는 코드는 작동하지 않는다. 와… 이건 뭐 말해 뭐해, 느낌이다. 실행되지 않는 코드를 누가 건드리겠는가? 변화가 있을 때 관련 코드를 건드리고 테스트 하지 않는다면 이건 무조건 문제가 생긴다. 안 쓰는 코드는 버리는 게 맞다. 지금 안 쓰면 나중에도 안 쓸 확률이 매우 높다. 어쩌다가 다시 쓴다? 저자도 git에서 다시 되살리면 되지 않느냐 하는데, 내 경험으로는 그러는 경우는 사실 없다고 봐도 무관할 것 같다. 이걸 되살리는 경우는 지우지 말아야 하는데 지워서 원복하는 경우 말곤 솔직히 못봤다. 삭제됐던 코드가 정상 작동한다고 보장할 수도 없고, 어차피 되살려봐야 이해하고 고쳐야 할 점을 찾는 게 더 비용이 큰 것 같다. 그냥 현재 요구사항에 맞는 내용으로 재작성하는 게 더 빠르더라.

규칙 13. 산사태를 일으킨 조약돌을 찾으라. 지금도 옆에서 그런 모습을 많이 본다. 경력이 많은 이들은 정말 열심히 파고 들어서 증상을 직접적으로 일으키는 점 뿐만 아니라, 이를 유발한 조약돌까지 찾아 근본적인 해결을 하려고 든다. 그런데 대충 경력이 얕거나 경력이 많아도 그렇게까지 하기 귀찮은 사람들은 증상만 해결하고 끝낸다. 그러면 보통은 당장 해당 순간은 넘어가는데 머지 않아 더 큰 문제를 만나 더 큰 비용을 지불하고 해결해야 한다. 그 동안 고객은 회사에 실망하고 이탈하는 데 말이다. 조금만 더 신경쓰면 서로 윈윈했을 텐데 말이다.

규칙 15. 잡초를 뽑으라. 아… 저자는 예제로 주석문 얘기를 했지만, 내가 이 규칙을 읽었을 때 머릿속에 떠오는 건 바로 며칠 전에 회사 동료에게 했던 말이었다. 뭔가를 수정하고 빌드를 진행하고 있었는데, 그 동료가 컴파일이 오래 걸린다고, 레거시 시스템이라 그렇다는 말을 했다. 하지만 나는 그게 왜 그렇게 오래 걸리는 줄 알고 있다. 내가 담당하지 않아서, 당장 다 뒤집을 수 없어서 몇 번 언급만 했었던 것이지만, 역시 일이 커지고 하기 싫은 일이다보니 해결이 안 됐던 부분이었다. 바로 컴파일러가 내뱉는 경고 문구들 때문이었다. 2, 300여 개의 경고문을 출력하느라 컴파일 속도가 느린 것이다. 이걸 한 번 테스트 삼아 정리했고 10개 내외는 정말 없앨 방법이 없어서 남겨뒀었는데, 컴파일 속도가 확연히 달라졌었다. 그래서 이 점을 인지하고 알렸는데, 저자 말처럼 못질하고 싶지 않은 사람이 훨씬 많았던 터였다. 회사 초창기에는 팀장이 경고 무시하지 말고 무조건 해결하라고 했었는데, 지금은… 안타깝다.

공감되는 내용과 더 노력해야 할 내용들을 읽게 되어서 상당히 많은 도움이 되었다. 내가 완전히 공감하지 못하는 부분들에 대해서는 내 나름대로의 방향을 정리하는데 가이드라인으로 사용할 법하다. 내용을 차분히 읽어보면 이야기꾼 면모가 보이는 것 같다. 번역을 깔끔하게, 맛깔나게 잘 하셔서 더 그런 것 같다. 번역투도 아니고, 실제로 저자가 한 말을 잘 이해해서 우리말로 잘 옮겨놓았다. 그래서 품질이 좋다. 그러다보니 저자가 하고자 하는 내용도 잘 이해되는 효과도 있고.

예제 코드를 단발성으로 사용하지 않고, 점진적 개선을 통해 저자가 하고자 하는 내용들을 증명하며 전개해 나가서, 코드를 읽을 수 있는 개발자라면 확실히 도움이 될만한 팁이 많다. 개인적으로는 규칙 19. 평행 재작업 부분이 덜 이해가 되어서, 이 부분을 다시 보면서 파봐야한다. 왜냐하면 이 내용이 현재 내가 겪고 있는 어려움과 직접적으로 연관된 내용이기 때문이다. 낡은 코드, 문제가 되는 코드들을 개선해야 하는데, 건드릴 때마다 문제가 많이 생겨서 애를 많이 먹고 있기 때문이다. 이걸 잘 풀어보면 해결 실마리를 얻을 수 있지 않을까 기대해본다.

뭔가 본인의 개발 틀을 잡고 싶다면 이 책은 강추하고 싶다. 초심자가 이 책에서 얼마나 많은 걸 얻어갈 수 있을진 모르겠지만, 적어도 이런 점이 있다는 걸 인지하고 있으면, 앞으로 개발 업무를 해나갈 때 선임의 말이나 코드를 이해하는 데 많은 도움이 될 거라고 믿는다.

원래 조언처럼 말해주는 건 당시에는 이해하기 어려운 법이다. 내 생각이 너무 강해서 그렇다. 그래서 겪어봐야 아는 것이지만. 결국 이렇게 말할 테니까. “그때 그 말대로 했어야 했는데!”