이 시리즈는 저만의 FE 컨벤션, 코드 스타일 등을 만들고자 Toss의 SLASH 영상과 기술 블로그 등을 참고하여 만들었습니다.
Toss 테크 블로그에 박서진님께서 작성해 주신 "선언적인 코드 작성하기"를 분석하였습니다.
React 생태계에서 웹 서비스를 개발하다 보면, 선언적인 코드에 대해 고민하게 됩니다. 토스 프론트엔드 챕터에서는 선언적인 코드를 “추상화 레벨이 높아진 코드”로 생각하고 있습니다.
sum([1, 2, 3]);
function sum(nums: number[]) {
let result = 0;
for (const num of nums) {
result += num;
}
return result;
}
⇒ 주어진 배열의 합을 구하는 함수 sum
은 for
문으로 구현할 수 있다.
배열이 가지고 있는 각각의 원소를 순회하면서 결괏값에 더하는 작업을 추상화합니다. 덕분에 sum
을 다루는 사람은 복잡한 제어 흐름을 이해할 필요 없이, “배열의 합을 구한다”라고 하는 동작에 집중하여 함수를 사용할 수 있습니다.
“왼쪽으로 10걸음 걸어라”
그렇다면, 선언적인 코드는 항상 좋은 것일까요?
토스에서 좋은 코드를 판단하는 제1원칙을 “수정하기 쉬운 코드”라고 생각합니다. 비즈니스 요구사항은 항상 빠르게 변하기 때문에, 개발자가 기민하게 대응하는 것이 중요하기 때문입니다.
<SignUpForm
onSubmit={result => {
/* 회원가입 결과에 따라서 특정 동작 수행 ... */
}}
/>
위 컴포넌트는 회원가입 로직을 하나의 컴포넌트로 추상화했기 때문에 선언적인 컴포넌트로 볼 수 있습니다. 이 코드는 과연 수정하기 쉬울까요?
화면마다 SignUpForm
이 조금씩 다르다면, 공통화된 것이 오히려 코드의 복잡함을 가져올 수도 있습니다.
<SignUpForm
signUpOrder={['sns', 'normal']
title="사이트에 어서 오세요"
subtitle="먼저 회원가입을 해주세요."
primaryButtonColor={colors.blue}
secondaryButtonColor={colors.grey}
/* 많은 Prop 들 ... */
onCancel={/* ... */}
onSubmit={result => {
/* 회원가입 결과에 따라서 특정 동작 수행 ... */
}}
/>
위와 같이 바뀔 부분이 많다면, 내부 구현과 인터페이스도 복잡해지고, 쓰는 쪽에서도 불편할 것입니다.
이렇게 선언적인 코드가 항상 좋지 않다는 것을 알게 되었고 앞으로 코드의 어떤 부분이 수정될지 예측하고, 이에 따라 적절한 선언 레벨을 따르는 코드를 작성할 필요가 있습니다.
또한, “추상화”를 무작정 높이는 것이 좋은 코드가 아닐 수도 있다는 것을 알게 되었습니다.