선언형 프로그래밍이란?
선언형 프로그래밍(Declarative Programming)은 "어떻게 할 것인가"보다 "무엇을 할 것인가"에 집중하는 프로그래밍 패러다임(문제를 해결하기 위해 코드를 바라보는 기본적인 사고방식)이다.
프로그램이 달성해야 할 결과를 기술하고, 그 과정의 세부 구현은 추상화한다.
명령형(Imperative): 어떻게 할지 하나하나 지시한다선언형(Declarative): 무엇을 원하는지만 표현한다
명령형 프로그래밍 (Imperative)
// 배열에서 짝수만 필터링하고 2를 곱하기
const numbers = [1, 2, 3, 4, 5];
const result = [];
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] % 2 === 0) {
result.push(numbers[i] * 2);
}
}
console.log(result); // [4, 8]- 반복문, 조건문, 변수 할당 등
어떻게동작할지 단계별로 명시한다. - 상태 변화와 제어 흐름이 코드 전반에 드러난다.
선언형 프로그래밍 (Declarative)
const numbers = [1, 2, 3, 4, 5];
const result = numbers.filter((num) => num % 2 === 0).map((num) => num * 2);
console.log(result); // [4, 8]- 짝수를 필터링하고, 각각에 2를 곱한다는 결과를 선언한다.
- 내부 반복, 인덱스 관리 등의 구현은 감춰져 있다.
선언형 프로그래밍의 특징
- 의도 중심: 어떻게가 아니라 무엇을 표현
- 추상화: 내부 구현을 숨기고 결과에 집중
- 부수 효과 최소화: 상태 변경이 줄어듦
- 조합 가능성: 작은 선언들을 연결해 큰 로직 구성
선언형 ≠ 함수형
선언형 프로그래밍과 함수형 프로그래밍은 자주 함께 언급되지만, 완전히 같은 개념은 아니다.
선언형: 무엇을 할지 표현하는 스타일함수형: 함수의 합성, 불변성, 순수 함수 등을 중시하는 패러다임
JavaScript의 map, filter, reduce는 선언형이면서 함수형 스타일을 동시에 제공하는 도구다.
왜 선언형 프로그래밍을 사용할까?
1. 가독성과 유지보수성
// 명령형: 코드를 읽으며 로직을 추적해야 함
let total = 0;
for (let i = 0; i < products.length; i++) {
if (products[i].price > 10000) {
total += products[i].price;
}
}
// 선언형: 의도가 명확함
const total = products
.filter((product) => product.price > 10000)
.reduce((sum, product) => sum + product.price, 0);선언형 코드는 비즈니스 로직에 집중할 수 있어 코드 리뷰나 유지보수 시 의도를 빠르게 파악할 수 있다.
2. 버그 발생 가능성 감소
// 명령형: 인덱스 오류, 변수 변경 등의 위험
for (let i = 0; i <= numbers.length; i++) {
// 버그: <= 사용
}
// 선언형: 내부 구현이 검증된 메서드 사용
numbers.map((num) => num * 2); // 안전함반복문 인덱스 관리, 변수 상태 변경 등의 실수를 줄일 수 있다.
3. 테스트 용이성
const getActiveUsers = (users) => users.filter((user) => user.isActive);
// 테스트 예시 (Jest)
expect(getActiveUsers([...])).toEqual([...]);선언형 코드는 순수 함수와 궁합이 좋아 입력→출력이 예측 가능한 형태로 작성되는 경우가 많다.
실제 개발에서의 선언형 프로그래밍
React에서의 선언형
// 명령형 접근
function updateUI() {
const element = document.getElementById('counter');
element.textContent = count;
if (count > 10) {
element.style.color = 'red';
}
}
// 선언형 접근 (React)
function Counter({ count }) {
return <div style={{ color: count > 10 ? 'red' : 'black' }}>{count}</div>;
}React는 DOM을 직접 조작하지 않고, "이 상태라면 UI는 이렇게 보여야 한다"를 선언한다.
선언형의 한계와 균형
1. 성능 최적화가 필요한 경우
// 선언형: 여러 번 순회
const result = data
.filter(...)
.map(...)
.reduce(...);
// 명령형: 한 번의 순회
for (const item of data) {
// 모든 작업 처리
}대용량 데이터나 성능이 중요한 구간에서는 명령형 접근이 더 효율적일 수 있다.
2. 디버깅의 어려움
선언형 코드는 추상화 레벨이 높아 내부 동작을 추적하기 어려울 수 있다.
이럴 때는 중간 결과를 분리하거나, 필요한 부분만 명령형으로 작성하는 것도 좋은 선택이다.
정리
선언형 프로그래밍은 코드를 짧게 쓰기 위한 기법이 아니라, 의도를 명확하게 드러내기 위한 사고 방식이다.
모든 상황에서 선언형이 정답은 아니지만, 대부분의 UI 로직과 비즈니스 로직에서는 선언형이 더 읽기 쉽고, 수정하기 쉬운 선택이 된다. 중요한 건 패러다임이 아니라, 상황에 맞는 균형이다.