<리 팩토링 이전에 내 코드는 제대로 된 코드가 아니었다... feat. 1차 프로젝트 리팩토링 후기 1편>

강민수·2022년 1월 12일
0

리팩토링 시리즈

목록 보기
3/8

📌01. 리팩토링의 의미

사실 리팩토링이라는 것을 크게 생각하지 않고 있었다. 그런데 지금 리팩토링 과정을 거치고 나서 보니, 딱 위의 그림과도 같은 느낌이 들었다.

마치 인류가 '오스트랄로피테쿠스'에서 점점 '호모사피엔스'-> '인간'이 되어가는 것 같은....

그래서 이번에는 필자가 리팩토링 이전의 코드와 리팩토링을 하면서 느낀 바를 통해 어떻게 코드가 바뀌었는 지에 대해 한 번 이야기 해 보겠다.

💡02. 발단이라 쓰고 깨달음이라 읽는다.

필자는 1차 프로젝트 당시 회고를 쓰면서 하나 뭔가 의문이 드는 코드가 있었다. 이전 회고에도 적었었는데, 바로 이 코드다.

그때는 구현하기에 사실 급급해서 그냥 넘겼지만, 다시 생각해 보니, 이 초기 값 설정이 너무 비효율적이라는 생각에 다다랐다.

왜?

그렇게 생각했던 가장 큰 이유는 사실 오류와 함께였다. 회고록에도 남겼지만, 당시 이 코드의 초기값은 결국 데이터가 많아지면 많아질수록 수동적으로 개발자가 넣어줘야만 했다.

그런데.... 돌이켜보니, 그건 너무 비효율적이 아닌가? 그래서 이건 꼭 리팩토링하면서 바꿔보자!라는 생각을 가지고 있었다.

🤔03. 코드에 대한 고민.

사실 리팩토링을 기존에도 해 봤지만, 이거 한 줄 바꾸는 데 온갖 고민을 많이 했었던 것 같다. 거의 몇 시간 동안을 적고 또 지우고를 반복했던 것 같다.

그래서 일단, 방향성에 대해 한 번 고민해 보다가 일단 접근을 시작해 봤다.

1. 첫 번째 접근

사실 접근이랄 것도 없는 것이, 그냥 저렇게 반복되는 생성이 싫어서 무한 배열이 생성되는 함수를 생각해 봤다. 그래서 결국 생각은 for문에 이르렀고, 처음에는 for문을 무한대로 돌려보는 것으로 접근했다.

하지만, 수차례 도전을 했지만, 포문을 짜도 뭔가 돌아가지 않았다.

이 마음 가짐으로 계속 도전했지만, 내 머리도 무한루프를 돌고 있었다...

🔫04. 질문에 역공을 당하다.

그래서 필자는 멘토 재준님이 있는 가상 업무 공간인 메타폴리스로 이동하여 질문을 했다.

그에게 해당 문제에 대한 설명과 함께 현실적인 조언을 구했다. 그러자, 되려 왜 컴포넌트 구조가 이런 식이냐고 역공을 당했다.

그때까지만, 해도 왜 이런 반문을 하시는 지 잘 몰랐다.... 하지만, 생각해 보니 그 말이 맞았고, 그는 내게 지역성이라는 주제를 더 공부해 보라고 했다.

지역성? 그게 뭔가 구글링을 해서 공부를 해보니, 결국 지역성이란 말은 해당 컴포넌트가 작용하는 일종의 범위라는 것이다. 예를 들어, 어떤 컴포넌트에서 작용하는 프롭스, 스테이트가 다른 컴포넌트에서는 작용하지 않을 수 있다. 또, 부모 컴포넌트 안의 프롭스와 스테이는 자식 컴포넌트에서 작용 가능하다. 이렇게 모든 컴포넌트에는 지역성이 있음을 그때서야 깨달았다.

🏗 5. 본격 구조 변경 시작.

01. 하나씩 고쳐보자~

01) 카드 컴포넌트 구조 분석~

지역성에 대한 고려를 통한 코드 구성은 조금 뒤로 하고, 재준님은 지금 저 문제 이전에 그 밑에 컴포넌트 구조를 지적하셨다. 바로 밑에 서브 이미지로 존재하는 ProdcutcCard2번 컴포넌트의 구조였다. 왜 저렇게 src로 나눠 놓았냐고 하셨다. 그래서 필자는 그냥 이미지가 2개이기 때문에 이미지 태그 2개로 받는 작업을 했다고 답을 드렸더니, 이걸 바꿔야 한다고 하셨다.

처음에는 왜 이걸 굳이 건드리나 싶었다. 하지만 나중에는 이게 본질이었고 재준님의 큰 그림이었다는 것을 깨달았다. ㅎㅎ

다음으로 바로 컴포넌트 구조를 보여드렸다.

02) 반복성을 무조건 줄여라!

재준님은 내게 동일한 구조는 최대한 반복성을 줄이는 것이 좋다고 말씀하시면서 조언을 아낌없이 해주셨다.

그래서 이걸 간결하게 만드는 구조부터 고려했다.

01. 프롭스의 중복성 제거.

카드 컴포넌트의 반복되는 src 구조를 어떻게 하면 처리할 수 있을 지에 대한 고민부터 시작했다.

반복되는 것은 결국 배열 형태의 데이터를 받아오는 것이고, 이럴 때 대개 처리하는 방식이 맵이었다. 이에 따라 코드 구조를 조금 바꿔봤다.

그리고는 프롭스 받는 것 역시 기존처럼 하지 말고, src 하나로 통일했다. 이 작업을 하기 전에 물론 작업해야 할 것이 한 가지 더 존재했다.

위처럼 분절된 형태의 src1, src2라는 프롭스를 src 하나로 합쳐줘야 했다.

그래서 필자는 src={product.detail}이라고만 src 프롭스를 받아버렸다. 그리고는 저렇게 맵으로 해당 배열을 자동적으로 돌리게 만든 것이다. 화면을 구현해 보니, 여전히 잘 구현되었다. 이를 통해 불필요한 중복 형태의 태그를 다 없앨 수 있었다. 사실 알고보니 맵을 돌면 배열 안의 모든 요소를 돌기때문에 저렇게 프로덕트 카드 2번에는 지정해서 나눠줄 필요가 없었다. 물론 후술하겠지만, 저 위의 프로덕트 카드는 다른 작업이 필요하긴 했다.

02. 함수의 중복 제거!

다음은 저 서브 이미지를 클릭할 경우, 메인 이미지가 변경되게 만드는 함수의 중복을 제거해 줄 필요가 있었다. 보이시는 가? 저 아래 주석되어 있는 불필요한 부분이 단 두 줄로 끝났다.

저렇게 줄일 수 있는 이유는, 당연히 이것도 프롭스와 연관된다.

아까 필자는 분명 위의 그림처럼 컴포넌트의 구조 변경을 했다고 언급했다. 그런데, 여기 잘 보면, onClick 함수 역시 바뀐 것을 볼 수 있다. 자 일단 하나씩 뜯어보면, 온 클릭과 같은 이벤트 처리는 안에 함수 형태만 받는다.

03. 꼬꼬무(꼬리에 꼬리를 무는 질문들)

그렇다면 여기서 의문이 든다.

그냥 함수만 받으면 안 되나?

맞다! 기존에는 필자도 그냥 함수만 받아서 처리하려고 했다. 그런데 그렇게 하면, 저렇게 중복처리 된 함수를 처리할 수 있는 인자인 index를 받아올 수가 없다. 그러면 또 꼬리에 꼬리를 묻는 질문이 나올 것이다. 왜 인덱스를 받는가? 인덱스의 기능을 잘 살펴봐야 한다.

인덱스는 무엇인가? 사실 엄청난 기능을 하는 것은 없다. 그냥 포문을 돌 때, 0부터 시작해서 맵핑을 하는데 구분해 주는 구분자일 뿐이다. 그런데 여기서 다시! 이런 구분자가 없다면 어떻게 되겠는가? 구분자가 없다면 맵을 돌때 그냥 번호 식별없이 전체 데이터를 다 받아올 것 이다. 따라서 이 구분자를 통해 우리는 원하는 데이터만 끄집어 낼 수가 있다.

그래서 저렇게 인덱스로 인자를 받는 함수를 통해 구분자를 만들어 클릭시 다른 인덱스 번호의 메인 이미지가 보여줄 수 있도록 데이터 변경 처리를 해주는 것이다.

04. 아직 하나 더 남았다....

글로 풀자니 이게 또 길어지는데... 다시 클릭 이미지 함수를 보면 안에 setNumber(index)가 있다. 기억이 나시는 가?

setNumber가 있는 이유... 그렇다. 드디어 본질에 거의 다 왔다.


다시 문제의 유즈스테이트를 살펴볼 시간이다. 우리는 기존에 초기값 설정에 있어서 순수하게 배열을 계속 넣어줬다. 하지만 이건 분명 비효율적이고, 데이터가 늘어나면 늘어남에 따라 문제가 생기는 것을 인지 했다. 이제 그 문제를 살펴볼 시간이다.

여기까지 너무 길어진 것 같아 원래 한 페이지에 다 기술하려고 했으나 조금 나눠서 다음 편으로 넘겨야 할 것 같다. 다음 편에서는 이제 유즈 스테이트 변경의 효율성과 더불어 기존에 언급한 컴포넌트의 지역성을 고려한 대 보수공사에 대해 적어보고 필자의 마지막 느낀 점으로 마무리하겠다.

profile
개발도 예능처럼 재미지게~

0개의 댓글