관심사의 분리와 SRP, Custom Hook

HIHI JIN·2023년 7월 7일
0

react

목록 보기
19/19
post-thumbnail

Clean Code

좋은 코드를 쓰는 것은 중요합니다. 아니, 나쁜 코드를 쓰지 않는 것은 중요합니다. 왜냐하면 코드는 결국 소프트웨어를 이루는 근간이기 때문입니다. 소프트웨어가 나쁜 코드로 구성되어 있으면 결국 해당 소프트웨어는 망가지고 맙니다. 망가지고 만다는 말은 더이상 기능을 확장해나가거나, 수정할 수 없게 된다는 의미입니다.

간혹 개발자들은 당장의 기능 구현이 급해서 좋은 코드를 포기하고자 하는 상황이 생깁니다. 그리고 그 결정은 십중팔구 안좋은 결과로 이어지게 됩니다. 실제로 프로그램의 복잡도가 올라갈수록 코드 한줄을 입력하거나 수정하는데 드는 시간은 점점 늘어납니다. 시간을 아끼기 위해서 좋은 코드를 포기했는데 결국 더 많은 시간을 들이게되는 경우는 드문 일이 아닙니다.

그리고 대부분의 경우 기능 구현이 급해서 시간을 아끼기 위해서 좋은 코드를 포기하기보다는 좋은 코드를 고민하고 찾아보려는 노력을 점점 덜 하게 되어서 나쁜 코드로 나아가게 됩니다. 그리고 나중에 “프로젝트 완성이 더 급하니까, 기능 완성이 더 급하니까 어쩔 수 없었어”, “출시하고나서 나중에 다시 고칠거야”라는 마음가짐을 하게 됩니다. 하지만 나중에 다시 고칠거라는 코드를 다시 볼 수 있는 여유가 생기는 경우, 또 여유가 생겨도 다시 보는 일은 대부분 일어나지 않습니다.

물론, 여기서 말하는 나쁜 코드는 “나중에 봤을 때 나쁜 코드”를 의미하는 것은 아닙니다. 때로는 그때는 최선이었던 방법이 시간이 흐름에 따라서 현재에는 적합한 방법이 아닐 수 있습니다. 이런 이유로 레거시 취급을 받는 코드도 분명히 존재합니다. 하지만 그때의 최선이었던 코드는 비교적 마이그레이션하거나, 개편하기 쉽습니다, 하지만 애초에 나쁜 코드는 이러한 작업들을 불가능에 가깝게 만듭니다.

따라서, 개발자는 반드시 좋은 코드, 깨끗한 코드를 작성하기 위해서 노력해야 합니다. 그리고 개발자의 실력을 평가하는 기준이 되는 여러 중요한 요소 중 하나가 바로 이 좋은 코드, 깨끗한 코드를 작성할 수 있는지에 대한 여부입니다.

좋은 코드를 작성하기 위해서는 좋은 코드의 기준이 무엇인지, 그리고 방법이 무엇인지를 고민하고 연구해야 합니다. 그리고 개발 업계에서는 학습한 내용을 공유하는 문화 덕택에 좋은 개발자들이 지금껏 연구해놓은 수많은 좋은 코드를 작성하기 위한 원칙과 방법들이 존재합니다.

관심사의 분리

개발에는 관심사의 분리(Seperation of Concerns)이라는 용어가 있습니다.

이는 좋은 코드를 짜기 위한 가장 기본적인 원칙이며, 더 좋은 애플리케이션을 만들기 위한 여러 디자인 패턴, 기법, 아키텍쳐 등은 결국 모두 이 SoC를 가장 기본적인 원칙으로 삼고 있습니다.
관심사의 분리를 알아보기 위해 먼저 “관심사"라는 단어에 대해 알아보겠습니다.

“관심사"를 간단히 말하면 하나의 모듈이 수행하고자 하는 목적입니다, 여기서 모듈이란 함수, 클래스 등의 단위로 해석할 수 있습니다.

따라서, 관심사의 분리란 각 모듈들이 한번에 여러 관심사를 처리하려고 하지 않고, 하나의 관심사만 처리하도록 분리하는 것을 의미합니다.

관심사를 분리하는 이유

그렇다면 왜 관심사를 분리해야 할까요? 하나의 모듈에서 여러 기능을 할 수 있으면 얼핏 좋아보이는 것 같은데 왜 하나의 모듈은 하나의 관심사만 처리해야 할까요?

관심사를 분리하면 하나의 모듈은 하나의 목적만 가지게 됩니다. 하나의 목적만 가지게 된다는 말을 조금 다르게 해석해보면, 이제 이 코드가 수정될 이유는 한가지만 존재하게 된다는 의미입니다.

소프트웨어는 계속해서 변화합니다. 하드웨어(hardware)는 물리적인 실체가 있는 제품들을 의미합니다. 반면 소프트웨어(software)는 코드로 구성된 무형의 제품들을 의미합니다. 물리적인 실체가 있는 제품들에 hard라는 용어가 붙은 의미는 수정하기가 힘들기 때문입니다. 하드웨어를 수정하기 위해서는 실제로 부품을 생산하고 교체하는 과정을 거쳐야하기에 많은 공수가 듭니다. 반면, 소프트웨어는 상대적으로 수정하기 쉽습니다. 코드로 이루어져있기 때문에 소프트웨어를 수정하기 위해서는 단순히 코드의 일부만 수정하면 소프트웨어의 동작을 변경할 수 있습니다. 이말은 곧 진정한 의미의 소프트웨어는 변화에 유연하게 대응할 수 있어야한다는 의미입니다. 실제로 소프트웨어가 잘못 설계되어서 변경하기 힘든 상황이라면 이는 하드웨어와 다를 바 없어지는 것입니다.

위의 이유로 인해서 소프트웨어에서의 변화는 필연적이며, 좋은 소프트웨어 일수록 기존의 기능을 수정하는 것과, 기능을 확장하는 것을 잘 할 수 있어야 합니다. 이를 우리는 흔히 “유지보수"라고 부릅니다.

본론으로 돌아와, 관심사를 분리하는 이유는 소프트웨어의 특정 부분이 변경되는 이유를 한가지로 제한하기 위해서입니다. 만약 여러 모듈들이 여러 관심사를 동시에 다루고 있다면 특정분야에 대해서 수정을 해야 할 때 관련된 모든 모듈을 수정해야 할 것입니다.

예를 들어, 애플리케이션 내에서 인증&인가에 대해서 모든 모듈들이 관여하고 있다면, 추후 인증&인가의 동작을 수정해야 할 경우에는 모든 모듈들을 일일이 돌아다니며 수정을 해야 할 것입니다.

하지만, 인증&인가를 다루는 핵심 모듈을 한가지로 제한해두고 나머지는 이 모듈을 사용하는 형식으로 설계되어 있다면 추후 인증&인가의 동작이 변경되었을 경우에는 해당 모듈만 수정하면 되기에 변화에 유연하게 대응할 수 있게 됩니다.
이처럼 관심사의 분리는 소프트웨어를 만드는 프로그래밍에서 가장 기본이 되는 원칙입니다. 기본이 되는 원칙이기에 비슷한 개념을 표현하는 여러 많은 단어들과 프로그래밍 격언들이 생겨났습니다.

  • 단일 책임 원칙(Single Responsibility Principle): 관심사의 분리와 유사한 개념이지만, 관심사란 표현 대신 책임이란 용어를 사용합니다. 각 모듈들은 책임(수행해야 하는 동작)을 가지고 있으며 각기 하나의 책임만을 가져야 한다는 원칙입니다.
  • KISS(Keep It Simple, Stupid): 각 모듈들은 간단하고, 단순하게 만들라는 의미로서 여러 기능을 포함시키면서 복잡하게 만들면 유지보수가 힘들어지기에, 하나의 기능만 수행하도록 하라는 의미입니다. SoC, SRP등의 원칙과 유사한 의미를 가지고 있습니다.

Custom Hook

React v16.8에서 Hook이 발표되고 난 후 React에서 컴포넌트를 선언하는 방법의 대세는 클래스 컴포넌트에서 함수 컴포넌트로 옮겨왔습니다. 많은 사람들이 익숙하고, 이미 기존에 많은 코드들이 작성된 방법인 클래스 컴포넌트에서 함수 컴포넌트로 옮겨온 이유중에는 함수 컴포넌트의 문법이 더 단순하고, 교착상태로 인한 버그가 발생하지 않는다는 장점도 있지만, Custom Hook의 편리함과 유용성도 큰 비중을 차지하고 있습니다.

React의 관심사

앞서, 관심사의 분리에 대해 학습했습니다. 그렇다면 리액트가 가진 관심사는 어떤 것들이 있을까요?
리액트는 UI를 구축하기 위한 라이브러리입니다. 따라서 리액트가 가진 핵심적인 관심사는

  1. UI
  2. 로직 (UI를 변경시키는 부분)

위 두가지로 나눌 수 있습니다.

이 중 UI는 실제 코드상에서는 JSX라는 형태로 표현됩니다. 그리고 로직은 유저의 입력에 반응하고, API를 호출하고, 스크린의 변화에 반응하는 등 여러 동작들을 통해서 UI에 영향을 미치는 행위라고 할 수 있습니다.

React에서 관심사를 분리하는 법: Presentational - Container

리액트를 활용하는 개발자들은 리액트의 관심사는 UI와 로직이란 것을 파악하고 이를 분리하기 위해서 여러 기법들을 연구하게 됩니다.

그 중 처음으로 유명해진 기법은 Presentational - Container 패턴입니다.

Presentational - Container 기법은 컴포넌트를 크게 두 계층으로 분리하는 방법입니다.

Container는 로직들을 다루는 부분으로 UI에는 관여하지 않고 오로지 UI를 구성하고 변화하기 위한 로직에만 집중하는 컴포넌트입니다.

Presntational은 반대로 로직은 상관하지 않고 UI가 어떻게 구성되어야 하는지에만 집중하는 컴포넌트입니다.

이렇게 컴포넌트를 두 계층으로 나누어서 Presentational을 Container로 감싼 후, 필요한 정보들과 로직을 모두 props로 전달해주는 형태로 설계하는 방법이 Presentatinal - Container 패턴입니다.

이 패턴은 그 효용을 인정받아 Hook이 등장하기 전까지는 관심사를 분리하는 표준 패턴으로 사용되었습니다.

하지만 Hook이 등장한 후에는 더이상 Presentational - Container 패턴을 많이 사용하지 않습니다.

왜냐하면 Custom Hook이란 기법이 발명되었고, 이것이 더 효율적으로 관심사를 분리할 수 있다고 판단되었기 때문입니다.

React에서 관심사를 분리하는 법: Custom Hook

커스텀 훅은 리액트가 기본적으로 제공해주는 훅들을(useState, useEffect 등) 이용해서 만든 함수입니다.

로직은 UI를 변경시키기 위함이고, 함수형 컴포넌트에서 로직은 대부분 useState, useEffect 등의 Hook을 통해서 구현됩니다.

훅을 통해서 편리하기 state를 선언하고 effect를 발생시킬 수 있게 되었지만, 컴포넌트 내부에 많은 로직들이 들어가게 되면 컴포넌트가 복잡해지고, 무엇보다 동일한 로직들을 여러 컴포넌트에 걸쳐서 재사용하기 힘들다는 단점이 있었습니다.

일적반으로 동일한 로직이 보일경우 함수로 추출하듯이, 리액트에서도 Hook들을 이용한 동일한 로직들을 별도의 함수로 추출해서 여러 컴포넌트에 걸쳐서 사용하고자 하는 시도가 있었고 결국 커스텀 훅이란 기법을 만들게 됩니다.

커스텀 훅의 조건은 아래와 같습니다.

  1. React의 Hook들을 호출하는 함수여야 한다.
  2. 함수의 이름은 use로 시작해야 한다.

Custom Hook - Example - CodeSandbox

profile
신입 프론트엔드 웹 개발자입니다.

1개의 댓글

comment-user-thumbnail
2024년 6월 24일

정리해주신 글 잘 읽었습니다 🙇‍♂️
React에서 관심사를 분리하는 법: Custom Hook 섹션의 4번째 문단에 오타가 있네요
일적반으로 동일한 -> 일반적으로 동일한

답글 달기