개발자로 일하다 보면 선언형 프로그래밍과 명령형 프로그래밍에 대한 질문을 많이 듣게 된다. 특히 신입 개발자들에게 면접 질문으로 하는 경우가 많은 것 같은데, 이번 기회에 제대로 공부해보자. (면접에서 제대로 대답 못 했으니 이번 기회에라도 공부를…!)
우선 선언형 프로그래밍과 명령형 프로그래밍에 대해 알아보기 전에 ‘프로그래밍' 그 자체에 대해서 알아보자.
프로그래밍이란 컴퓨터 프로그래밍(영어: computer programming) 또는 간단히 프로그래밍(programming, 문화어: 프로그램 작성) 혹은 코딩(coding)은 하나 이상의 관련된 추상 알고리즘을 특정한 프로그래밍 언어를 이용해 구체적인 컴퓨터 프로그램으로 구현하는 기술을 말한다. 프로그래밍은 기법, 과학, 수학, 공학, 심리학적 속성들을 가지고 있다.
여기서 주목해야 할 부분은 특정한 프로그래밍 언어를 이용해 구체적인 컴퓨터 프로그램으로 구현하는 기술이라는 점이다.
즉, 선언형 프로그래밍과 명령형 프로그래밍 모두 프로그램을 구체화하는 방법인 것이다.
다만 두 방법이 다르게 불리는 이유가 있을 것 같은데, 구체적으로 무엇이 다른 걸까?
우선은 선언형 프로그래밍에 대해서 알아보자. 선언형 프로그래밍이란 프로그램이 무엇과 같은지 설명하는 방식을 말한다.
즉, 어떤 방법으로 해야 할 지 구체적으로 알려주는 것이 아니라 목표를 명시하는 방법인 것이다.
그러면 궁금해질 것이다.
“아니, 구체적으로 알려주는 게 아니면 어떻게 코딩을 해?”
하지만 생각보다 우리는 선언형으로 코드를 작성해왔다. 바로 아래처럼 말이다.
위의 두 코드는 둘 다 동일한 기능을 한다. 둘 다 array라는 숫자 배열에서 22보다 큰 숫자 배열을 반환하는 점에서는 동일하지만, 그 방식이 다르다.
첫 번째 코드는 for 반복문을 통해 아이템을 하나하나 돌면서 각 요소가 22보다 큰 지 검사해준다. 이는 프로그래머가 컴퓨터에게 무슨 행동을 해야 할 지 명시적으로 알려준 것이다.
두 번째 코드는 array의 내장 메소드인 filter를 사용하였다. 프로그래머는 filter안의 내용이 어떻게 구성되어 있는지 모른다. 다만 filter를 이용하면 array의 요소를 하나씩 확인할 수 있으며, 조건에 맞는 요소들만 뽑아서 새로 배열을 만들 수 있다는 건 알게 된다. 위의 반복문을 사용할 때와 하는 일은 똑같지만, 프로그래머가 한 것은 컴퓨터에게 무엇을 할 지 명확하게 알려준 것이다.
여기까지 읽었으면 짐작했을 것이다. 첫 번째 방식으로 작성된 것이 뒤에서 살펴 볼 명령형 프로그래밍이고, 두 번째 방식으로 작성된 것이 선언형 프로그래밍이다.
정리하자면 이렇다. 선언형 프로그래밍은 구체적인 알고리즘을 프로그래머가 작성하는 것이 아니라, 고도로 추상화된(캡슐화된) 명령으로 무엇을 할 지만 명시해주면 된다.
즉, 선언형 프로그래밍 내부는 명령형으로 작성이 되어 있지만 그것은 추상화(캡슐화)되어 있어서 프로그래머는 그 내부 로직에 신경을 쓰기 보다는 무엇을 구현할 지에만 집중할 수 있게 된다.
위에서 선언형 프로그래밍에 대해서 알아 봤으니 이번에는 명령형 프로그래밍에 대해서도 알아보자. 위키의 정의에 따르면, 명령형 프로그래밍은 자료 처리를 수학적 함수의 계산으로 취급하고 상태와 가변 데이터를 멀리하는 프로그래밍 패러다임의 하나이다.
무슨 말인지 모르겠으니 바로 코드부터 보도록 하자!
선언형 프로그래밍에서도 다루었던 코드이다. 앞서 말했듯 첫 번째 코드가 명령형으로 작성된 코드인데, 조금 더 자세히 보자.
for문을 보면 array의 길이만큼 반복문을 돌고, 그 내부 로직은 조건문을 통해 요소 하나하나가 22보다 큰 지 검사하고 있다. 그리고 만약 해당 조건에 포함된다면(22보다 크다면), result 배열에 하나씩 넣어준다.
해당 코드는 무엇을 하는지가 명확히 보인다. 그리고 하나씩 절차적으로 진행되고 있다. 반복문을 돌면서 조건을 탐색하고, 조건에 일치한다면 액션(여기서는 result 배열에 요소를 넣는 것)이 발생하는 것이다.
다만 해당 코드가 어떻게 동작할 지는 프로그래머가 구체적으로 작성해주어야 한다. 반복문이 어디서부터 어느 범위까지 돌 것인지, 조건에 해당한다면 어떤 액션이 발생할 지 등 말이다. 두 번째 코드에서 filter 내장 메소드를 쓰는 것과는 확연히 다르다.
우리는 filter 메소드를 사용할 때, filter의 내부가 어떻게 동작하는지 구체적으로 알 필요는 없다. 그저 filter 메소드의 인자로 들어온 callback 함수가 true일 때, 해당 값들이 새로운 배열로 반환된다는 것만 알면 된다.
즉, 명령형 프로그래밍은 무엇을 해야 할 지 컴퓨터에게 알려주는 것이 아니라, 프로그래머 스스로 컴퓨터가 수행할 명령을 순서대로 작성하는 방법인 것이다.
지금까지 선언형 프로그래밍과 명령형 프로그래밍에 대해서 알아보았다. 개인적으로 선언형 프로그래밍이 좀 더 모던한 느낌이 있는데(javascript의 3대 라이브러리 중 하나인 react 역시 선언형으로 작성되어서 더 그런 것 같기도 하다.), 그렇다고 해서 두 개념이 우월 관계에 있는 것은 아니다.
프로그래밍이 발전되어 온 역사를 이해하고, 상황에 맞게 적재적소에 사용한다면 좋을 것 같다.