우선, 두 프로그래밍 패러다임의 차이점을 이해하기 전에 각각의 프로그래밍에 대한 개념을 이해하고자 한다.
명령형 프로그래밍 (Imparative Programming)
컴퓨터 과학에서 명령형 프로그래밍(命令型 프로그래밍, 영어: imperative programming)은 선언형 프로그래밍과 반대되는 개념으로, 프로그래밍의 상태와 상태를 변경시키는 구문의 관점에서 연산을 설명하는 프로그래밍 패러다임의 일종이다. 자연 언어에서의 명령법이 어떤 동작을 할 것인지를 명령으로 표현하듯이, 명령형 프로그램은 컴퓨터가 수행할 명령들을 순서대로 써 놓은 것이다.
글들을 읽다보면, 이해가 갈법하면서도, 잘가지 않는다. 가장 이해하기 쉽게 생각하면, 명령형 프로그래밍은 "HOW"를 제시한다.
우선 예시 코드를 보자.
// 배열을 파라미터로 받으며, 각 요소에 1을 더해서 새로운 배열을 반환해주는 함수
function addOne (arr) {
let results = [];
for(let i=0; i<arr.length; i+=1){
results.push(arr[i]+1);
}
return results;
}
위의 코드는 다음과 같이 말한다.
"나는 addOne 이라는 함수로, arr 배열을 파라미터로 받을꺼야. 우선, results라는 새로운 배열을 선언 한 뒤, arr의 배열 원소들에 1을 더해서 results 배열에 push, 그리고 그 값을 리턴할꺼야"
위의 설명을 보면, 정말 어떻게 할꺼구나! 라는 것을 더욱 느낄 수 있다. 어떤 인자를 어떻게 요리할 것 인지, 그 요리한 값이 어떻게 나오는지.... 가벼운 생각으로 보다보면, '이렇게 하는 코딩 말고 또 뭐가 있는데...?' 란 생각이 들기도 했다.
그렇다면 두번째, 지향하고자 하는 프로그래밍 방식인 선언형 프로그래밍에 대해 알아보자.
선언형 프로그래밍 (Declarative Programming)
위키백과는 두가지의 정의를 제시하였다.
한 정의에 따르면, 프로그램이 어떤 방법으로 해야 하는지를 나타내기보다 무엇과 같은지를 설명하는 경우에 "선언형"이라고 한다. 예를 들어, 웹 페이지는 선언형인데 웹페이지는 제목, 글꼴, 본문, 그림과 같이 "무엇"이 나타나야하는지를 묘사하는 것이지 "어떤 방법으로" 컴퓨터 화면에 페이지를 나타내야 하는지를 묘사하는 것이 아니기 때문이다. 이것은 전통적인 포트란과 C, 자바와 같은 명령형 프로그래밍 언어와는 다른 접근방식인데, 명령형 프로그래밍 언어는 프로그래머가 실행될 알고리즘을 명시해주어야 하는 것이다. 간단히 말하여, 명령형 프로그램은 알고리즘을 명시하고 목표는 명시하지 않는 데 반해 선언형 프로그램은 목표를 명시하고 알고리즘을 명시하지 않는 것이다.
또 다른 정의에 따르면, 프로그램이 함수형 프로그래밍 언어, 논리형 프로그래밍 언어, 혹은 제한형 프로그래밍 언어로 쓰인 경우에 "선언형"이라고 한다. 여기서 "선언형 언어"라는 것은 명령형 언어와 대비되는 이런 프로그래밍 언어들을 통칭하는 것이다. -위키백과
위의 설명을 읽어보면 가장 중요한 점은 명령형 프로그래밍 언어와 대비된다 라는 점과, 프로그래머가 실행될 알고리즘을 명시 해주어야 한다, 라는 것이다.
즉 앞선 명령형 프로그래밍은 "HOW" 였다면, 선언형 프로그래밍은 "WHAT"이라는 것이다.
위와의 비슷한 예제를 살펴보자.
// 배열을 파라미터로 받으며, 각 요소에 1을 더해서 새로운 배열을 반환해주는 함수
function addOne (arr) {
return arr.map((i) => i+1);
}
사실 여기서부터 고개를 갸웃뚱 했다... javascript의 내장형 함수로 바꿔쓰고, 단순히 이걸 선언형 프로그래밍이라고 칭한다고?
하지만 다시 생각해봐야 할 것이 있다. 내장형 함수로 바꿔쓰며 무엇이 바뀌었는가? 정답은 추상화이다.
즉 가장 중요하게 생각해야 할 점은, 선언형 프로그래밍은 명령형 프로그래밍의 추상화(Abstraction) 란 것 이다.
위 코드를 보면, 어떤 과정들을 통해 내가 원하는 것에 도달하는지(HOW)가 중요한 것이 아니다. 무엇(WHAT)이 일어날지에만 자바스크립트 내장함수 map 내부에 집중함으로 (map함수가 어떻게 이루어지는지 관심을 끌 수 있자나?) 상태 변경에 대한 직접적인 간섭이 없다.
개인적인 생각 한 스푼...
위는 몇몇의 레퍼런스를 찾다보면 쉽게 접할 수 있는 개념이다. 그렇다면 결국 왜 사용하는 것일까? 우선 추상화란 다음과 같다.
추상화 : 우리가 객체를 만드는 과정은 현실 또는 가상의 존재를 프로그램 내에서 사용할 용도에 맞게 적절하게 설계하는 과정.
즉 용도에 맞게, 적절하게 설계하는 과정 속에서 우리가 중요하게 생각해야할 것은 WHAT이다. 아직도 HOW가 중요하다고 생각하거나, 그 HOW속에서 필요한 효율성과 알고리즘적, 프로그래밍적 지식은 내가 생각하는 낭만이 아닐까?
내가 중간에 어떠한 서비스 팀에 들어가, 코드를 리뷰하는 와중에, 모든 함수 하나하나에 대한 HOW를 읽고 있으면, 매우 화날 것 같다... 더 쉽게 생각했을 때, 외부 라이브러리나 API를 사용 할 때 필요한 WHAT이 중요하지, HOW가 중요한가?(중요하다 물론... 각 서비스 환경에 알맞은지 확인하는 절차도 당연 필요하니까)
One of the strengths of declarative programming is its ability to describe problems more briefly and succinctly than imperative languages. https://www.ionos.com/digitalguide/websites/web-development/declarative-programming/
선언형 프로그래밍을 사용하는 방식이 문제를 더욱 가독성있게 효율적으로 전달한다는 점을 잘 기억하자!
다음 포스트는 선언형 프로그래밍 방식 중 하나인 함수형 프로그래밍과 순수 함수에 대한 부분을 적고자 한다.
'Software Engineering' 카테고리의 다른 글
Git 브랜치 전략, Git-flow (0) | 2022.09.03 |
---|---|
성능을 위한 프론트엔드 설계와 코드 - 1 (0) | 2022.08.28 |
Quality Assurance (QA: 품질보증) (0) | 2022.08.26 |
함수형 프로그래밍 (Functional Programming) (0) | 2022.08.21 |
리팩토링(Refactoring) 이란? (0) | 2022.08.14 |