본문 바로가기
기타

리팩토링 스터디 #1 - 첫 번째 예시

by 유세지 2020. 9. 15.

리팩토링 스터디의 첫 번째 시간이 다가왔습니다. 주말 오전부터 시작해서 모두 피곤한 기색이 있었지만 다르게 생각하면 늦잠 자던 시간에 이렇게 개발 이야기를(?) 할 수 있다는게 좋기도 하네요. 잠도 깰 겸 꽤 시원해진 아침 공기를 한 번 마시고 아아메 한 잔과 함께 시작하였습니다.

 

포스팅에는 책 내용을 요약해서 정리하는 것도 좋지만, 스터디 중간중간 나왔던 알고 가면 좋을 것 같은 이야기들도 함께 적어보도록 할게요. 재미있는 이야기들이 많이 나와서 잊어버리기 전에 얼른 적어야겠어요.

 

 

스터디 전 이슈에 적어두었던 기억에 남았던 점

 

스터디 1주차에는 간단하게 Chapter 1까지 읽어보고 중요하다 싶은 부분들을 하나하나 짚어가며 다시 보는 방식으로 진행했습니다. 그 날의 발표자 1명이 주가 되어 스터디를 이끌고, 나머지 참여원들은 발표를 들으며 의견을 개진해갔습니다.

 

첫 번째 챕터의 제목은 Chapter 01 - 리팩터링: 첫 번째 예시입니다. 말로 장황하게 설명하는것 보다 리팩터링의 과정을 직접 보여주며 "리팩터링이란 이렇게 진행된다" 라는 것을 보여주었습니다. 스터디에 참여한 인원이 다양하다보니 사소한 몇 가지 문제가 있었는데, 주로 사용하는 언어가 자바스크립트가 아니다 보니 예시로 적혀있는 코드를 완벽하게 이해하지 못하는 경우가 대표적이었습니다. 코드 자체의 난이도가 높았던 것은 아니었지만 세부적인 문법은 생소할 수 있기에 충분히 일어날 수 있었던 상황이었습니다. 이런 경우 언어의 숙련도가 있는 참여원이 부가적인 설명을 해주기로 하였고, 별 문제 없이 넘어갈 수 있었습니다.

 

이 포스팅은 책의 내용을 요약하는 것보다, 스터디 도중 나왔었던 이야깃거리등에 초점을 맞춰서 작성하려고 합니다. 본 책을 한 번 읽었거나, 또는 읽으면서 포스트도 함께 봐주시면 좋을 것 같습니다. 그럼 시작하겠습니다.

 

 

 

들어가며, 서문, 머릿말을 읽어야 하는 이유

스터디를 시작하며 가장 먼저 나왔던 이야기입니다. 챕터 1의 내용까지 읽어오기로 약속해서 첫 장의 내용은 모두가 한 번 이상은 (비록 완벽하게 이해하지 않더라도) 어느정도 알고 있던 상태였습니다. 그런데 예상 외로 책을 펼쳤을때 가장 먼저 나오게 되는 추천사나, 들어가며... 와 같은 이름으로 시작하는 글을 읽었던 사람은 전체 인원의 절반 정도였습니다.

 

지식 전달을 목적으로 하는 책이니만큼 우리가 구글 검색을 하는 것처럼 필요한 내용을 추려 읽는것도 좋다고 생각하지만, 개인적으로는 자칫 딱딱해질 수 있는 글의 분위기를 주제와 살짝 벗어난 내용으로 부드럽게 풀어주어 글을 읽을 준비를 해주기도 하고, 무엇보다 본문과는 다른 저자의 사담이 재미있다고 느낀적이 많기에 이런 글부터 읽는 습관이 있었기에 자연스럽게 읽게 되었습니다.

 

이전 글이었던 리팩토링 스터디 #0 - 스터디에 들어가며를 작성하며 정리했던 내용이지만, 보통 이러한 서문에는 저자가 이 책을 쓰며 했던 생각들이나 예상하는 독자의 수준, 또는 이 책을 읽는 사람이 어떤 내용을 중요하게 받아들였으면 하는지와 같은 저자의 생각이 많이 녹아있습니다. 이러한 사전 지식을 갖고있는 상태에서 책을 읽게 되면 같은 내용을 읽더라도 더 효율적으로 지식을 습득할 수 있고, 이해가 안가더라도 내가 어느 부분에서 부족한 것인지 찾기가 쉬워집니다.

 

이 부분은 스터디를 이끌어가시는 선배님도 강조하셨던 내용이고, 스터디에 참여하셨던 다른 팀원분들도 공감하셨던 내용이니만큼 앞으로도 이 습관을 유지하는게 중요할 것 같습니다.

 

독서의 시작은 서문부터

 

 

 

테스트 케이스 라이브러리

리팩토링의 저자는 테스트와 커밋을 굉장히 중요하게 생각합니다. 어찌보면 강박적일 정도로 조금의 기능 변화라도 나타나면 컴파일-테스트-커밋 의 과정을 반드시 거칩니다. 변수 이름 바꾸고 커밋, 데이터 추가하고 커밋, 반복문 하나 넣고 커밋... 물론 생산성을 중시하는 리팩토링의 취지에 걸맞게 잦은 테스트를 지향하는것은 알겠지만 사실 실제 개발에서 이렇게까지 하기는 어렵겠지요.

 

스터디에 참여하셨던 프론트엔드 개발자 분들은 백엔드 개발자 분들처럼 테스트의 단위를 끊어내기가 쉽지 않고, 실제로 테스트 케이스를 만들어서 확인해보는 빈도가 적었다는 의견에 어느정도 공감하셨습니다. 물론 프론트에서도 테스트는 중요합니다. 상대적으로 그렇다는거죠!

 

자바스크립트에도 모카(mocha.js)와 같은 테스트 프레임워크나 라이브러리들이 분명 존재하고, 실제로 많이 사용되고 있습니다. 앞으로 FE 개발자를 목표로 한다면 꼭 알아둬야하는 내용이니 따로 공부를 해야한다고 조언해주셔서 언젠가 포스팅으로도 한 번 올릴 예정입니다. 테스트쪽은 저도 공부가 안되어있기 때문에...

 

몇 차례 테스트의 중요성에 대한 이야기가 오가고, 문득 선배분께서 자바에서 가장 널리 쓰이는 테스트 라이브러리가 무엇이냐고 질문하셨습니다. 저를 포함해서 많은 분들이 JUnit을 떠올리셨는데, 이 라이브러리가 만들어진 배경에 대한 이야기가 나와서 기억에 남아 짧게 정리해봅니다.

 

JUnit을 만든 개발자는 켄트 백에릭 감마입니다. 두 분 모두 IT 분야에서 유명한 엔지니어이기에 이름 정도는 들어보셨을지도 모르겠습니다. GoF의 디자인 패턴의 저자라고 하면 아실 수도 있을 것 같네요. (바이블이 된 책이죠!) 두 사람은 강연을 위해 애틀랜타로 가는 비행기에 몸을 싣고서, 우연히 만나게 됩니다. 서로가 알고있는 지식에 관심이 많았던 두 사람은 Java를 써본 적 없는 켄트 백에게는 Java를, 에릭 감마에게는 Smalltalk를 알려주기로 하고 작은 프로젝트를 하나 해보기로 했는데 그것이 바로 켄트 백의 단위 테스트 라이브러리인 SUnit의 Java 버젼이었습니다. 비행기 안에서, 세시간에 걸친 페어 프로그래밍으로 만들어진 한 단위 테스트 자바 라이브러리는 후에 JUnit으로 불리게 되었습니다.

 

한 분은 JUnit을 두 천재의 토이프로젝트였다고 짧게 요약해주셨습니다...

 

이게 왜 진짜인지... / 출처 http://members.pingnet.ch/

 

 

 

인텔리제이의 리팩토링 기능

주류로 사용되는 IDE가 이클립스에서 인텔리제이로 옮겨간데에는 리팩토링을 비롯한 다양한 기능이 있었기 때문이라고 말할 수 있을 것 같습니다. 굉장히 편리하고, 개발자의 생산 효율을 크게 높여주는 이 기능은 프로젝트 규모가 커지면 커질수록 더 큰 힘을 발휘합니다.

 

사용하는 방법도 어렵지 않습니다. 인텔리제이 기반의 IDE에서 소스 코드를 드래그하고 마우스 오른쪽 클릭을 하고 Refactor 항목을 눌러주기만 하면 됩니다. 원하는 리팩토링 기능을 바로바로 사용할 수 있게 구현해 놓은 디테일이 돋보이는 개발 환경입니다.

 

리팩토링도 빠르고 간편하게

 

 

함수 이름 짓기

함수 또는 변수의 이름을 짓는건 사실 굉장히 어려운 일입니다. 이 함수가 수행하는 기능을 간결하고 완벽하게 표현하기에는 우리의 작명센스는 너무나 부족합니다. 실제로 이 책에서도 한 번에 좋은 이름을 붙이려고 노력하지 말고, 우선 적절하게 정해둔 다음 리팩토링 과정에서 다시 변경하기를 권장합니다.

 

스터디 구성원들도 대부분은 고개를 끄덕이며 넘어갔지만, 저자가 책에서 설명한 함수의 이름을 짓는 방식에는 동의하지 않는다는 의견도 있었습니다. 자바스크립트는 강타입 언어가 아닙니다. 따라서 어떤 형식을 갖는지 변수나 이름만 봐서는 명확하지 않을때도 있고, 함수라면 어떤 값을 반환하는지 확실하지 않을때도 있습니다.

 

몇 가지 예를 들어보겠습니다. 책에서 저자는 oApple, sApple, aApple 과 같은 방식으로 변수 이름을 지었습니다. 이는 각각 object, string, a 등을 의미합니다. 오브젝트와 스트링은 알겠는데, a는 무슨 의미일까요?

 

array의 A일 것이다, 라는 추측도 있었지만 결론은 책의 구절을 그대로 인용하면

 

" 매개변수의 역할이 뚜렷하지 않을 때는 부정 관사(a/an)를 붙인다. "

 

개인적인 생각으로는 a가 부정 관사로서 마땅히 정해지지 않았음이라는 의미를 갖는다는 것은 비영어권 국가에서 나고 자란 프로그래머에게는 썩 와닿는 표현은 아닌 듯 합니다. 위 문장의 바로 뒤에 이어진 저자의 말에 따르면 이는 켄트 벡에게 배운 방식이고, 본인이 느끼기에 유용하다는 생각이 드는 일종의 코딩 스타일이라고 하니 굳이 따라가야 할 필요는 없는 것 같습니다.

 

물론 이외의 저자의 이름 선정에도 확실한 기준이 있긴 합니다. 함수의 이름을 동사 (play, make, build 등)로 짓는 경우와 명사로 짓는 경우를 구분지어서 코딩을 하는데, 구체적인 행위를 하는지 하지 않는지에 대한 여부도 생각하며 작명을 합니다.

 

또 논란이 되었던(?) 것이 변수 이름인데, 어떤 함수에서 반환값의 변수 이름은 반드시 result로 바꾸어 준다고 합니다. 스터디에 참여하신 다른 선배님의 말씀을 빌리자면 참을 수 없는 행위라고 느껴지기도 합니다. 사실 간단한 계산 결과 정도야 result로 바꿔주는건 그러려니 하지만 모든 리턴값을 result로 통일하는게 과연 얼마나 효용이 있을지는 잘 모르겠네요.

 

 

 

리팩토링과 성능 개선?

성능 개선에 대한 이야기도 있었는데 이건 개인적으로 신기해서 남겨봅니다.

 

저자는 리팩토링을 통해 가능한 구조를 깔끔하게 정리하려 합니다. 그 과정에서 함수를 추출해내고, 임시 변수를 제거하며 코드 자체의 길이가 늘어나기도 합니다. 그러나 그 과정에서 반복문이 늘어나고, 메모리를 추가적으로 더 사용하는등 성능에 좋은 영향을 미칠 것 같지 않은 요소들이 보였습니다. 저자도 이를 염두하였는지 우선 깔끔하게 리팩토링을 마치면 그 후에 성능 개선의 효율도 높아지기에 리팩토링을 먼저 하고, 그 후에 성능 개선을 하는 순서를 제시합니다.

 

알고리즘 문제를 풀며 메모리와 시간 제한에 쫒기던 기억이 있어서인지 정말 그래도 되나? 하는 생각이 들었지만, 큰 규모의 프로젝트에선 미미한 영향을 끼친다고 하여 그러려니 하고 넘어갔습니다.

 

 

 

원활하고 정확한 커뮤니케이션을 위하여

저자는 리팩토링 과정에 볼드체로 이름을 붙여 강조합니다. 마치 게임이나 애니메이션에서 기술을 사용하며 기술명을 외치는 것처럼 말이죠.

 

함수 추출하기-!!!!!!

 

사실 하나하나 설명하는 것보다는, 의견을 제시하는 쪽에서도 간단하고 듣는 입장에서도 의미 전달이 확실하게 이루어집니다.

 

함수를 새로 만든 다음에 목적에 맞는 이름 붙여주고, 원본 함수에서 복사해서 새 함수에 붙여넣어 준 뒤에 원본에서 지역 변수를 참조하거나 추출한 함수의 유효범위를 벗어나는 변수가 없는지 확인해주고 만약 있으면 매개 변수로 넣어주세요. 그리고 컴파일 부탁해요. 컴파일 끝났으면 원본 함수 부분을 지금 만든 함수의 호출로 대체해주고 단위 테스트 한 번 돌린 다음에 방금 추출한거랑 비슷한 코드 없는지 확인해주세요. 만약 기존 함수가 있으면 그걸로 바꿀지 한 번 논의해봅시다.

 

보다는

 

이 부분 함수 추출하기 해주세요.

 

 

이쪽이 훨씬 간편하지요? 역시 개발자들에게 많은 인기를 끈 책인 이유가 있었나봅니다.

 

 

 

 

스터디를 마치며

우선은 생각나는대로 정리해봤는데 중간에 잊어버린 내용도 있고, 지면상 정리하지 못한 부분도 있는 것 같습니다. 다음 스터디 부터는 진행되는 동안 녹화나 메모를 하면서 듣는 것이 좋겠다는 생각이 드네요.

 

무사히 마칠 수 있도록 끝까지 열심히 참여해야겠습니다.

반응형

댓글