본문 바로가기
에러 디버깅 & 리팩토링

간단한 todo 앱 리팩토링 시도기 1편 (Fetch API, 함수 추출하기)

by growingTangerine 2023. 6. 14.

오늘은 원티드 프리온보딩 지원 과제로 만든 todo앱을 리팩토링해보려고 한다. 

 

지원 가산점 데드라인때문에 코드가 아쉬운 부분이 많아서, 제출 기한 이후에 꼭 리팩토링을 시도해보고 싶었다.

또한, 처음 시도해보는 리팩토링이라 리팩토링의 개념부터 기법까지를 미리 공부해보았다. 

 

- 리팩토링이란?

유지보수 생산성 향상을 위해 기능을 변경하지 않고 소스코드를 수정, 보완하는 것. 

내부 구조를 개선하고, 성능 최적화보다는 가독성과 유지보수 향상이 목표이다. 

 

- 좋은 설계는 개발 속도를 향상시켜준다!

팀 프로젝트에서도, 개인 프로젝트에서도 처음 설계를 철저하게 하지 않고 코드를 짜기 시작해서 중간중간 구조를 개선하는데에 시간을 날린 적이 꽤나 많았다. 

초보 개발자들이 흔히 하는 실수겠지만, 이번에 리팩토링을 하면서 "좋은 설계는 무엇일까?" 라는 고민을 더 해보고 싶다.

또한, 가독성이 좋고 유지보수를 쉽게 할 수 있는 코드 구조에 대해서 좀 더 고민하는 시간으로 삼고자 한다. 

 

- 리팩토링 기법

-> 다양하게 정리된 글들이 많았지만, 내 수준에서 이해하기 쉽고 리팩토링의 효과를 체감하는데에 도움을 준 글을 참고했다.

https://cornswrold.tistory.com/550

 

리팩토링(refactoring) 기법

1. 함수 추출하기 (Extract Function) 코드 조각을 찾아 무슨 일을 하는지 파악한 다음, 독립된 함수로 추출하고 목적에 맞는 이름을 붙인다. When? 언제 독립된 함수로 묶어야 할지에 관한 의견이 분분

cornswrold.tistory.com

 

- 집중하고 싶은 부분

1. 함수 추출하기 / 함수명 짓기 

: 본문 코드에 신경쓰지 않고도 호출 부분에서 함수의 역할과 목적을 알 수 있도록 리팩토링하기

2. 변수 추출하기

: 로직 단계에서 해당 변수가 어떤 역할을 하는지 목적을 명확하게 하여 가독성 높이기

3. 컴포넌트 구조 개선

: 반복 사용되는 컴포넌트를 묶어내고, 이 안에서 동작 필요한 로직 또한 묶어내 가독성과 유지보수성 향상하기

4. Fetch API 코드 개선

: Fetch API vs. Axios 글을 작성하면서 공부한 내용을 통대로 Fetch API를 사용한 코드를 좀 더 적절하게 바꾸기

 

 

- 리팩토링 시도기

4. Fetch API 코드 개선

 

로그인, 회원가입에서 fetch POST 요청을 날린 부분의 코드를 개선해보자.

 

- 기존의 코드

아래의 동일한 코드가 localStorage 에 access token 저장하는 부분 빼고는 똑같이 signin, signup 컴포넌트에 작성되어 있었다.

 

- 리팩토링 후의 코드

1. 첫번째 .then 구문에서 status 에 바로 접근하지 않고, .ok 여부를 먼저 확인해주었다. 

 

2. .catch 구문에서는 복잡한 .text, JSON parse 등을 간결하게 변경했다. error를 콘솔에 찍어보니, 회원가입 되지 않은 이메일이면 404 Not found, 가입된 이메일이지만 비밀번호가 일치하지 않을 때에는 401 Unauthorized 가 status 로 찍혔다. 따라서, 이 부분을 간단하게 조건문으로 분기하여 사용자에게 alert로 알리고 input 창을 비우기 위해 페이지를 새로고침해주었다. 

 

3. 페이지 새로고침 또한, url 주소 변경이 아니라 단순 새로고침이므로 그 의미가 더 잘 드러나도록 href 대신 reload 메서드로 변경하였다. 

 

- 회원가입 코드도 리팩토링해주었다.

기존의 코드에서는 .then 구문을 아래처럼 한번만 작성하고 바로 .catch 구문으로 넘어갔다.

 

 

하지만, .then 구문에서 하는 일의 단계를 명확하게 구분하기 위해 이를 리팩토링하였다. 

첫번째 .then에서는 res.ok === true 일 경우, res.json()을 그 다음 .then 구문으로 넘겨주는 역할만 하도록 변경했다.

 

.catch 구문도 로그인때와 동일하게 복잡한 상태라, 이 또한 아래와 같이 리팩토링해주었다. 

 

3. 컴포넌트 구조 개선하기

- 여기서는 개선하고 싶은 코드가 두가지 부분이 있었다.

첫번째는, access_token / 이에 따른 리다이렉트 구문 / baseURL 이다.

두번째는, 반복되는 input과 button을 컴포넌트로 빼서 코드의 가독성을 높이는 것이다. 

 

먼저, 첫번째의 문제부터 개선해보도록 하자!

이렇게 세 부분에 관련된 코드가 모든 페이지 컴포넌트의 최상단에 위치했다.

이 코드를 모두 지워주고, access_token과 baseURL은 상위 모듈인 App.js에서 export 해주어 받아서 사용하도록 수정하고자 한다. 

또한, access_token 여부에 따라 리다이렉트를 하는 코드도 그 역할이 좀 더 잘 드러나도록 하나의 함수로 추출해보려고 한다. 

 

이렇게 App.js에 access_token과 baseURL을 선언해주고, 이를 다른 컴포넌트들에서는 import 해서 쓰도록 만들었다.

 

그런데, 이 부분은 애초에 짧은 코드이고 간단한 todo앱이기 때문에 이렇게 고쳐주는게 유지보수나 가독성 향상에 영향을 미치는지 좀 의문스러웠다. 그래도 우선 서버 측에서 baseURL이 만약 바뀐다면, 코드 한줄만 고쳐주면 되니 유지보수가 수월해지는 효과가 있는듯하다. 또한, 브라우저에서 매번 localStorage.getItem을 새로 해주지 않고, App.js에서 한번만 불러와서 다른 컴포넌트에서는 해당 값을 사용하기만 하면 되는 것이므로, 실제 의도한 구동과도 더 의미가 통하는 코드인듯하다. (하지만 더 적합한 방식이 있을 것 같아, 향후에 더 공부해보면 좋겠다.)

 

이제 리다이렉트 구문을 함수로 추출해보자.

해당 구문은 todo, signup, signin에서 사용된다. 그리고 각 경우에 맞추어 다른 곳으로 리다이렉트 해주어야 한다. 

 

해당 리다이렉트 구문이 하는 일을 하나의 함수로 합쳐보았다.

변수로는 access_token, currentPage가 필요하다. currentPage는 window.location.pathname으로 현재의 경로를 넣어 호출해준다.

 

이 함수를 이제 상위 컴포넌트인 App.js으로 위치를 옮겨주고, 필요한 컴포넌트에만 props로 내려준다. 

비구조화 할당으로 내려준 함수를 내려받아 함수를 호출해주면 끝!

 

이렇게 총 3개의 컴포넌트에서 반복되던 부분이 

3개 컴포넌트 모두에서 한 줄로 줄어들었다! 

그리고 함수 선언을 통해 해당 코드가 무슨 역할을 하는지도 명확하게 보이면서, 함수의 본문은 캡슐화하는데에 성공했다 :) 

 

글이 생각보다 길어져서 나머지 리팩토링 미션은 다음 글에서!