Imperative programming is HOW you do something, and declarative programming is more like WHAT you do.
즉,
명령형(절차적) 프로그래밍 : 일을 '어떻게' 할 것인가에 관한 것.
선언적 프로그래밍 : '무엇을' 할 것인가에 관한 것.
아래는 코드가 아닌, real life 예시.
1/ Red Lobster 레스토랑
< 상황 >
- 당신은 JavaScript가 주는 피로함과 씨름하느라 많은 시간을 써, 남편과 근사한 데이트를 하기로 결정했습니다. Red Lobster에 도착하여 프론트데스크에 가서 다음과 같이 말하였습니다.
[ 명령형 접근형(HOW) ]
I see that table located under the Gone Fishin' sign is empty. My husband and I are going to walk over there and sit down.
저기 "Gone Fishin"이라고 적힌 표지판 아래에 있는 테이블이 비어있네요. 우리는 저기로 걸어가서 저 테이블에 앉도록 하겠습니다.
→ 명령형 방식은 내가 실제로 자리에 '어떻게' 앉을지에 관심이 있다. 이를 위해 나는 내가 어떻게 테이블을 잡아서 자리에 앉을지에 관해 필요한 단계들을 하나하나 나열해야한다.
[ 선언형 접근형(WHAT) ]
Table for two, please.
2명 자리 주세요.
→ 반면, 선언형 방식은 오로지 내가 '무엇을' 원하는지에 관심이 있다.
2/ Wal-mart
< 상황 >
- 친구가 우리집에 집들이를 오기 위해 Wal-mart에서 선물을 구매하였습니다. 친구는 지금 Wal-mart 바로 옆에 있고, 우리집에 어떻게 오는지 저에게 전화로 물어봅니다.
[ 명령형 접근형(HOW) ]
"주차장 북구 출구로 나와서 좌회전을 해. 12번가 출구에 도착할 때까지 I-15 북쪽 도로를 타고 와야한다. 거기서 IKEA에 가는 것처럼 출구에서 우회전을 해. 그리고 거기서 직진하다가 첫번째 신호등에서 우회전을 해. 그 다음에 나오는 신호등을 통과한 후에 좌회전을 하면 돼. 우리집은 #298이야"
[ 선언형 접근(WHAT) ]
"우리집 주소는 298 West Immutable Alley, Eden, Utah 84310 이야"
Q. '그럼, 자리에 앉는 방법은 누가 알지?', '주소는 아는데, 집에 가는 방법은 누가 알지?'
이에 대한 대답은, 선언적 방식의 접근을 위해서는 명령형 방식으로 '어떻게 접근하는가'에 관한 내용이 먼저 '추상화'되어있어야 한다는 것.
→ Red Lobster 직원에게 사용했던 선언형 접근('2명 자리 주세요')에서는, Red Lobster 직원이 '테이블에 어떻게 앉는가'에 관한 모든 명령형(절차적) 단계들을 알고 있다는 가정이 뒷받침 되어있다.
→ Wal-mart에서 친구에게 우리집의 주소를 알려주는 선언형 접근방식에서도, 친구가 우리집에 어떻게 올 수 있는가 에 관한 명령적 절차들을 모두 알고있는 GPS같은 것을 가지고 있다는 전제로 한다.
즉, 많은 선언적(Declarative) 접근 방식들의 기반에는 일종의 '명령적(Imperative) 추상화'가 존재한다.
'선언적 프로그래밍 언어'와 '명령적 프로그래밍 언어'에는 어떤 것들이 있는지 간단히 살펴보자.
- 명령적 언어 : C, C++, Java
- 선언적 언어 : SQL, HTML
- 둘다: JavaScript, C#, Python
전형적인 SQL 코드와 HTML 코드를 한번 살펴보자.
SELECT * FROM users WHERE country='Mexico';
<article>
<header>
<h1>Declarative Programming</h1>
<p>Sprinkle Declarative in your verbiage to sound smart</p>
</header>
</article>
위 SQL, HTML 코드를 보면 둘다 선언형이다. '어떻게' 할것인지 보다는 '무엇을' 원하는지와 관련이 있다.
'무엇을' 얻을 것인가에 대해 묘사하고 있고, '어떻게' 얻는 것인지는 가르쳐주고 있지 않다.
Mexico에 사는 모든 유저들을 어떻게 select하는지는 추상화되어있다.
어떻게 웹브라우저가 <article>요소를 파싱하고 화면에 구현하는지는 다루지 않는다.
여기서 WHAT은 오직 SQL문에서는 Mexican users, HTML코드에서는 header, paragraph 이다.
이제 좀 더 실용적인 JavaScript 예시를 보자.
# 명령형 프로그래밍 예시
아래에 3가지 인터뷰 질문이 있고, how에 포커스를 맞춰 명령적(Imperative)으로 대답을 해보자.
Q. 숫자로 된 배열을 받고, 모든 원소의 두배인 새로운 배열을 return하는 'double'이라는 함수를 작성해라.
A.
function double(arr) {
let results = [];
for(let i = 0; i < arr.length; i++) {
results.push(arr[i] * 2);
}
return results;
}
Q. 숫자로 된 배열을 받고, 모든 원소를 더한 결과를 return하는 'add'이라는 함수를 작성해라.
function add(arr) {
let result = 0;
for(let i = 0; i < arr.length; i++) {
result = result + arr[i]
}
return result;
}
무엇이 이 코드들을 명령적으로 만드는지 알기 위해서는, 이 코드들에서 공통점을 뽑아내야한다.
1. 가장 명백한 공통점은 '어떻게' 하는지를 묘사해놓고 있다는 것.
각 예시에서 명시적으로 배열을 반복하고 있거나(for문),
우리가 원하는 기능을 수행하기 위한 단계들을 명시적으로 나열하고 있다.
2. (만약 명시적으로 또는 구체적으로는 함수적인 방법으로 생각하는게 익숙하지 않다면 명백하지 않을수도 있지만), 각 예시들은 상태(state)의 일부를 변경한다.
results라는 변수를 만들어 계속해서 수정하고 있다.
3. 약간 주관적이지만, 가독성이 떨어진다.
코드를 언뜻 보고 이해가 잘 가지 않는다. 나의 뇌가 마치 인터프리터처럼 코드의 문맥을 고려하면서 하나하나 살펴봐야한다.
# 선언형 프로그래밍 예시
이제 선언적 예시들을 보자. 여기서 목적은 위의 세가지 문제를 모두 고치는것이다.
그래서 각 예시들은 '무엇이' 일어나는지에 관해 묘사해야하고, 상태(state)를 변경해서는 안되며, 한눈에 파악할 수 있어야한다.
1. 숫자로 된 배열을 받고, 모든 원소의 두배인 새로운 배열을 return하는 'double'이라는 함수를 작성해라.
function double(arr) {
return arr.map((item) => item * 2);
}
2. 숫자로 된 배열을 받고, 모든 원소를 더한 결과를 return하는 'add'이라는 함수를 작성해라.
function add(arr) {
return arr.reduce((prev, current) => prev + current, 0);
}
자바스크립트의 내장함수인 map, reduce 함수를 쓴 두 예시를 주목해보자.
우리가 위에서 봤던
'가장 효율적인 선언적 프로그래밍 방법은 명령적으로 작성된 코드를 추상화하는 것이다' 라는 것에 관한 내용이다.
여기 예시들은 '어떻게' 보다는 '무엇을' 일어나게 하기를 원하는지 묘사하고 있다.
(우리는 어떻게 map, reduce 함수가 실행되는지 모르고, 또한 알 필요가 없다.)
그리고 어떠한 상태(state)도 변경하지 않는다.
모든 변경들은 map과 reduce 안에서 추상화된다.
또한 더욱 가독성이 있다.(물론, map, reduce 함수에 익숙하다면)
선언적 프로그래밍의 또다른, 덜 알려진 장점 중에 하나는
우리 프로그램이 context-independent해질 수 있다는 것이다. (전체적인 맥락, 상황에 좀 더 독립적이다.)
선언적 코드들은 최종적인 목표가 무엇인지에 대해서만 관심이 있다.
해당 목표를 이루기 위한 세부적인 단계들(해당 목표에 의존적인 과정들)에는 관심이 없다.
그래서 동일한 코드들이 다른 프로그램에 쓰이더라도 정상적으로 동작할 수 있다.
위 함수들은 우리가 만들고자 하는 어떤 프로그램에서도 사용 가능하다. 어떤 프로그램에 속해있는가 하는것에 전혀 구속받지 않는다.
명령적 코드들은 그러지 못한 경우가 많은데, 왜냐하면 명령적 코드는 현재 상태의 문맥에 의존적이기 때문이다.
참조
https://iborymagic.tistory.com/73
https://ui.dev/imperative-vs-declarative-programming
'Computer Science' 카테고리의 다른 글
CSR vs SSR (2) | 2024.02.03 |
---|---|
'빌드'란? (0) | 2023.12.08 |
Virtual DOM(가상돔) (0) | 2023.11.26 |
네이티브 앱 vs 크로스플랫폼 앱 vs 모바일웹앱 vs 하이브리드 앱 (0) | 2023.11.25 |
컴파일러 vs 인터프리터 (0) | 2023.11.24 |