본문 바로가기

리팩터링 스터디 1주차 (Ch.1)

 

 

본 포스트는 마틴 파울러의 리팩터링 2판(2020, 한빛미디어)를 기반으로 진행한 사내 스터디에서 배운 점과 기억하고 싶은 점을 개인적으로 정리한 글입니다.

진행한 챕터

01 리팩터링: 첫 번째 예시 (1.1 ~ 1.10)

 

팀에서 모집한 사내 스터디에 참여하게 되었다 🥳

마틴 파울러님의 리팩터링 2판을 기반으로 리팩터링에 대해 앞으로 공부하는 시간을 가질 것이다.

 

오늘은 그 첫날로, 챕터 1인 구체적인 실예시코드에 앞으로 배울 리팩터링 방법을 적용하여 어떻게 코드를 개선하는지에 대한 전반적인 소개를 읽고 그 감상과 자유토론하는 시간을 가졌다.

 

오늘 나눈 대화에서 기억하고 싶은 키워드, 자세를 기록하기로 하였다.

글쓴이 포함 총 4명이서 나눈 대화로, 지금부터 개발자 A, B, C, 글쓴이라고 지칭합니다 😊

 

1. 테스트에 대하여

개발자 A. 책에서 리팩토링 단계를 적용할 때마다 컴파일 -> 테스트 -> 커밋 단계를 반복하는 것이 인상깊었습니다. 앞으로 코드를 작성할 때 테스트 코드 작성을 고려할 것입니다.

 

개발자 B. 테스트 코드 작성할 때 시각적인 변화를 검증해야 할 때와 로직을 검증해야 할 때도 있는데 이 둘 모두 테스트하는 코드 작성이 햇갈릴 때가 있습니다.

 

글쓴이. 이전에 세미나에서 프론트엔드 테스트는 시각적, 기능적 테스트로 나뉘며 어떤 사례에서 시각적인 테스트는 스토리북을,  기능적 테스트는 e2e 테스트 툴인 cypress를 활용하여 테스트하는 것을 소개한 걸 보았었습니다. 저희도 앞으로 다양한 테스트 도구 도입을 고려해보는 것이 어떨까요?

 

개발자 C. 테스트 코드 작성 목적에 대해 명확하게 하면 시각적 테스트, 기능적 테스트 모두 고려할 수 있을 것입니다. 리액트는 특히 가상 dom에서의 컴포넌트가 반환하는 엘리먼트 객체 내 state, props 비교를 통해 뷰의 변화 여부를 파악할 수 있습니다. jest의 스냅샷 기능을 활용할 수 있습니다. E2E TEST의 경우, 전직장에서는 각 페이지의 url에 접속하여 정상적으로 로드되는지에 대한 여부만을 검사하는 로직을 구현한 사례를 보았었습니다.

 

"리팩터링하기 전에 제대로 된 테스트부터 마련한다.

테스트는 반드시 자가진단하도록 만든다."

이 책의 저자, 마틴 파울러의 블로그 중 테스트 관련 글을 모은 테스팅 가이드 URL

 

2. 최적화 vs 리팩터링

글쓴이. 책에서 리팩터링 기법을 단계적으로 해나가는 것을 보면서 중간 단계에서는 리팩터링이 되는걸까? 싶은 부분도 있었습니다. 특히 for문 내부에서 한번에 수행하던 로직을 모듈로 분리하여 결과적으로는 같은 리스트에 대해 for문을 두 번 돌리게 되는것을 보고 성능적으로 괜찮을까 싶었는데 책에서 저자는 성능보다는 쉽게 수정할 수 있는 코드를 만드는 것이 중요하다고 하는 것이 인상깊었습니다.

 

개발자 C. 네, 책에서 특별한 경우가 아니라면 성능 최적화는 우선 무시하라고 합니다. 실제로 성능 최적화는 거대하고 오래 걸리는 로직을 최적화할 때 70% 이상의 성능 최적화 효과를 볼 수 있는 경우가 많습니다. 반복문을 적게 순회하는 등의 미미한 성능 향상보다는 시스템의 느린부분을 개선하는게 성능향상의 핵심입니다. 계산과정이 하나 더 추가되는 것보다는 전체 흐름을 파악하기 쉽게 작성하는 것이 우선되어야 합니다.

 

"리팩터링으로 인한 성능 문제에 대한 내 조언은

'특별한 경우가 아니라면 일단 무시하라'는 것이다."

 

3. 리팩토링 경험 공유

개발자 A. 리팩토링이 필요한 경우를 많이 보았지만 실제로 사용되는 서비스이고 멀쩡히 돌아가는 코드에 대해 리팩토링할 기회를 얻기가 쉽지 않았습니다.

 

개발자 B. vim 프로젝트에서 기존의 MVC(MVP였나) 구조를 MVVM 구조로 리팩터링한 경험이 있습니다.

 

글쓴이. 한 모듈로 작성되어 1000줄 이상되었던 코드를 모듈로 쪼개서 리팩토링하였습니다. mocha로 테스트코드를 작성하면서 진행했음에도 불구하고 커버리지가 부족하여 실 서비스에서 예상치 못한 사이드이펙트를 발견하여 결국 기능을 롤백한 적이 있습니다.

 

개발자 C. 리팩터링을 진행할 때 변경이 잦은 기능과 변경이 거의 일어나지 않는 기능을 분리하면 기존 기능에 영향을 거의 미치지 않고도 기능을 확장하고 리팩터링할 수 있습니다. 즉, 변화의 속도에 따른 기능 분리로 테스트 코드가 다소 부족하더라도 변경이 빈번한 기능을 다른 코드와 격리하여 향후 확장성과 변경 가능성을 더욱 쉽게 적용하고 파악할 수 있습니다.

"좋은 코드를 가늠하는 확실한 방법은

'얼마나 수정하기 쉬운가'이다."

 

4. 함수 분리, 변수명 짓기

글쓴이. 책에서 playFor 함수처럼 작은 단위의 기능또한 함수로 분리하였는데 사실 저는 굳이 함수로 분리할만한 것인지 생각되었습니다.

function playFor(aPerformance) {
  return plays[aPerformance.playID]
}

 

개발자 C. 함수 분리는 의미가 있다면 분리하고, 미래에 필요할것 같으면 지금하지 말라는 원칙에 따라 분리하지 않기도 합니다.

 

글쓴이. 변수명은 다들 어떤 기준으로 정하시는지 궁금합니다. 개인적으로는 변수는 명사로, 함수는 동사로 시작하고 있습니다.

 

개발자 B. 저는 영문법적으로 맞는 표현을 쓰려고 노력합니다. 그러나 간혹 팀에서 로딩 State명을 [isLoading, setIsLoading] = useState(false) 으로 사용하는 것처럼 문법적으로 어색한 표현이더라도 팀 내 코드 컨벤션에 맞추는 걸 우선시하고 있습니다.

 

개발자 C. 저도 팀 내에서 일맥상통한 단어를 쓰려고 합니다. 더 나아가 개발자들 간 뿐만 아니라 기획자, 디자이너들과 함께 의사 소통하는 데 혼동이 없는 단어를 고릅니다.

*글쓴이 첨언 : 프로젝트 하다보면 용어 정의나 공통적으로 사용하는 단어가 있으면 해당 단어로 모듈명, 변수명을 정하는 게 좋음

 


이외에도 인라인 변수, 지역 함수 등 더 논의한 부분들이 많지만 추후 스터디를 진행해가면서 재차 논의할 부분이라 나중에 기록하기로 하였다 😀

 

좋은 코드를 작성한다는 것은 고쳐야 할 곳을 쉽게 파악하고 오류없이 빠르게 수정이 가능한 코드를 만드는 일임을 늘 기억하기로 하였다.