
그러면 선언적인 개발을 하기 위해서 “추상화”라는 단어를 뗄 수 없습니다.
필요 없는 디테일을 숨기고, 필요한 것만 드러내는 것
Toss에서는 이렇게 말합니다.
“토스에서는 선언적인 코드가 항상 좋은 것이 아니라, 앞으로의 제품이 어떻게 변화할지, 비즈니스 요구사항이 어떻게 되는지에 따라 달라질 수 있다고 생각합니다. 앞으로의 코드의 어떤 부분이 수정될지 예측하고, 이에 따라 적절한 선언 레벨을 따르는 코드를 작성할 필요가 있습니다.”
그럼 추상화 레벨이 뭘까?
한 문장으로 말하면 “얼마나 WHAT에 가깝고, 얼마나 HOW에 가깝냐”의 정도입니다.
동일한 기능에서 다른 추상화 레벨에 대한 예시입니다.
if(user){
setIsLoggedIn(true);
} else {
setIsLoggedIn(false);
}
const authStatus = getAuthStatus(user);
아하! 그럼 선언적인 개발이 추상화 레벨을 높여 함수로 감싸서 내부 로직이 보이지 않게 하는 행위를 말하는구나!! 라고 생각하였습니다.
과연 이게 선언적인 개발일까요?
정답은 반은 맞고 반은 틀렸다 입니다.
단순히 함수를 감싸는 행위 자체가 “선언적”인것은 아니지만, 함수를 통해 “어떻게(HOW)를 숨시고” 무엇을(WHAT)만 남겼다면 그것은 선언적인 코드로 나아가는 방법이 맞습니다.
하지만 많은 분들이 착각하는 부분이 있습니다.
많은 개발자들이 function 키워드나 화살표 함수로 코드를 감싸기만 하면 추상화가 일어났다고 생각합니다. 하지만 함수 내부가 “A를 먼저 하고, 그 다음 B를 해”라는 단계별 지시 사항으로 되어 있다면 그것은 추상화가 아닌 ‘이름표가 붙은 명령형 코드’일 뿐입니다.
map(applyTax) 처럼 비자니스 로직의 이름을 전달함많은 개발자가 놓치는 부분인데 items.map(item → {… 복잡한 로직…})은 사실 for 루프를 map이라는 이름으로 바꾼 것에 불과할 떄가 많습니다.
즉 선언형은 문법이 아니라 “로직의 책임 위치”을 옮기는 작업이라 할 수 있습니다.
JSX의 선언적 특성은 어떻게(How)가 아닌 무엇(What)을 표현하는 데 있습니다.
명령형 방식
function createUserProfile(user) {
const container = document.createElement('div');
container.className = 'user-profile';
const nameElement = document.createElement('h2');
nameElement.textContent = user.name;
container.appendChild(nameElement); // 순서가 중요!
const emailElement = document.createElement('p');
emailElement.textContent = user.email;
container.appendChild(emailElement); // 순서가 중요!
return container;
}
이 코드는
라는 절차적 단계에 집중하고 있습니다.
선언적 방식
function UserProfile({ user }) {
return (
<div className="user-profile">
<h2>{user.name}</h2>
<p>{user.email}</p>
{user.avatar && <img src={user.avatar} alt={`${user.name}의 아바타`} />}
</div>
);
}
이 코드는 “UserProfile은 이름, 이메일, 아바타로 구성된다”는 최종 구조만 선언합니다.
DOM 조작 순서는 리액트가 알아서 처리합니다.
JSX의 진짜 장점은 데이터의 모양이 곧 UI가 된다는 점입니다.
const TodoList = ({ todos }) => (
<ul>
{todos.map(todo => (
<TodoItem
key={todo.id}
text={todo.text}
completed={todo.completed}
/>
))}
</ul>
);
이 코드를 보면
todos 배열 → <ul> 리스트todo 객체 → 각 <TodoItem> 컴포넌트라는 1:1 대응 관계가 한눈에 들어옵니다.
이 코드를 명령형으로 작성하면
function createTodoList(todos) {
const ul = document.createElement('ul');
for (let i = 0; i < todos.length; i++) {
const li = document.createElement('li');
li.textContent = todos[i].text;
if (todos[i].completed) {
li.classList.add('completed');
}
ul.appendChild(li);
}
return ul;
}
데이터 순회, 요소 생성, 조건 처리, DOM 추가 등이 섞여있어 전체 로직을 읽고 실행해봐야 최종 구조를 파악할 수 있습니다.
JSX가 선언적인 이유는
이번 아티클 작성을 하면서 선언적인 개발 사고가 앞으로 AI 시대에 중요한 개념이라는 생각이 들었습니다.
지난 수십 년간 개발의 정석은 문법을 외우고 알고리즘을 짜는 것이었습니다.
하지만 이제 최고의 프로그래밍 언어는 영어입니다.
개발자는 코드를 치는 사람이 아니라 스펙을 정의하는 사람, 즉 프롬프트가 코드가 되고 문서가 소프트웨어가 되는 세상입니다.
HOW에 집착하는 기술에서 WHAT을 만들지 결정하는 설계자
그래서 저는 선언적인 사고 방식이 더욱 중요하며 앞으로 개발자로서 뒤쳐지지 않고 성장하는데
필수적인 개념이라고 생각하였습니다.