프로그래밍 패러다임
| 프로그래밍 패러다임 |
|---|
프로그래밍 패러다임(programming paradigm)은 컴퓨터 프로그램의 구현을 개념화하고 구조화하는 비교적 높은 수준의 방법이다. 하나의 프로그래밍 언어는 하나 또는 여러 개의 패러다임을 지원하는 것으로 분류될 수 있다.[1]
패러다임은 프로그래밍의 서로 다른 측면에 따라 구분되고 설명된다. 어떤 패러다임은 부작용을 허용할지 여부나 연산의 순서가 실행 모델에 의해 정의되는지 여부와 같은 실행 모델의 함의에 관한 것이다. 다른 패러다임은 상태와 동작을 모두 포함하는 단위로 그룹화하는 것과 같이 코드가 조직되는 방식에 관한 것이다. 또 다른 것들은 구문 및 형식 문법에 관한 것이다.
일반적인 프로그래밍 패러다임의 일부는 다음과 같다(계층적 관계로 표시됨):[2][3][4]
- 명령형 – 코드가 제어 흐름과 상태 변화를 직접 제어하며, 프로그램 상태를 변경하는 명시적인 문을 사용함
- 선언형 – 코드가 원하는 결과의 속성을 선언하지만 계산 방법은 선언하지 않으며, 상세한 상태 변화를 지정하지 않고 수행해야 할 계산이 무엇인지 설명함
- 병행 프로그래밍 – 병행성을 위한 언어 구문을 가지며, 이는 멀티스레딩, 분산 컴퓨팅 지원, 메시지 전달, 공유 자원(공유 메모리 포함) 또는 퓨처를 포함할 수 있음
- 행위자 프로그래밍 – 환경에 반응하여 지역적인 결정을 내리는 행위자들을 이용한 병행 계산(이기적이거나 경쟁적인 동작이 가능함)
- 제약 프로그래밍 – 변수 사이의 관계가 제약 조건(또는 제약 네트워크)으로 표현되어 허용 가능한 해를 유도함(단체법 또는 제약 충족 사용)
- 데이터플로 프로그래밍 – 데이터 값이 변경될 때 공식의 재계산을 강제함 (예: 스프레드시트)
- 분산 프로그래밍 – 컴퓨터 네트워크를 통해 통신하는 여러 자율 컴퓨터들을 지원함
- 제네릭 프로그래밍 – 나중에 지정될 유형으로 작성된 알고리즘을 사용하며, 이후 매개변수로 제공된 특정 유형에 대해 필요에 따라 인스턴스화됨
- 메타프로그래밍 – 다른 프로그램(또는 자기 자신)을 데이터로 작성하거나 조작하는 프로그램을 작성하거나, 런타임에 수행될 작업의 일부를 컴파일 타임에 수행함
- 템플릿 메타프로그래밍 – 컴파일러가 템플릿을 사용하여 임시 소스 코드를 생성하고, 이를 나머지 소스 코드와 병합하여 컴파일하는 메타프로그래밍 방법
- 반영 프로그래밍 – 프로그램이 자기 자신을 수정하거나 확장하는 메타프로그래밍 방법
- 파이프라인 프로그래밍 – 원래 중첩 함수 호출 구문이 없도록 설계된 언어에 이를 추가하기 위한 단순한 구문 변경
- 규칙 기반 프로그래밍 – 지식 베이스를 구성하는 경험 법칙의 네트워크로, 전문가 시스템 및 문제 추론과 해결에 사용될 수 있음
- 시각적 프로그래밍 – 프로그램 요소를 텍스트로 지정하기보다 그래픽으로 조작함 (예: 시뮬링크); 도식적 프로그래밍이라고도 함
프로그래밍 패러다임은 컴퓨터 과학 연구에서 비롯되었으며, 기존 소프트웨어 개발 관행을 연구한 결과물이다.[5] 이러한 연구 결과는 프로그래밍 관행과 프로그램 코딩에 사용되는 언어를 설명하고 비교할 수 있게 해준다. 프로그래밍 언어는 패러다임 측면에서 설명될 수 있다. 일부 언어(스몰토크나 하스켈 같은)는 단일 패러다임만 지원하는 반면, 대부분의 언어(C++, 오브젝트 파스칼, PHP 등)는 다중 패러다임을 지원한다.[6] 다중 패러다임 언어에서는 프로그램이 순수하게 절차적이거나 순수하게 객체 지향적일 수 있으며, 또는 두 패러다임의 측면을 모두 포함할 수 있다.
프로그래밍 패러다임은 소프트웨어 개발의 근본적인 접근 방식을 결정하며, 코드의 구조, 유지보수성, 확장성에 직접적인 영향을 미친다.[7] 각 패러다임은 특정 문제 해결에 적합한 추상화 수준과 방법론을 제공하여 개발자가 복잡성을 관리하고 효율적인 솔루션을 설계할 수 있도록 돕는다. 현대의 많은 프로그래밍 언어는 다중 패러다임 언어로서 여러 패러다임을 지원하며, 개발자가 문제의 특성에 따라 가장 적합한 접근법을 선택할 수 있도록 한다. 자바, C++, 파이썬, 자바스크립트, 스칼라, 코틀린, 스위프트 등이 대표적인 다중 패러다임 언어에 속한다. 특정 패러다임의 선택은 프로젝트의 요구사항, 팀의 숙련도, 성능 요구사항, 유지보수성 등 다양한 요소에 따라 결정된다.[8] 각 패러다임은 고유한 장단점을 가지며, 현대 소프트웨어 개발에서는 여러 패러다임을 조합하여 사용하는 것이 일반화되었다.
개요
[편집]
프로그래밍 패러다임은 기존의 소프트웨어 개발 관행에 대한 컴퓨터 과학 연구에서 비롯되었다. 연구 결과는 프로그래밍 관행과 프로그램을 작성하는 데 사용되는 언어를 설명하고 비교할 수 있게 해준다. 관점의 차이로, 다른 연구 분야에서는 소프트웨어 공학 프로세스를 연구하고 이들을 설명하고 비교하기 위해 다양한 방법론을 기술한다.
프로그래밍 언어는 패러다임의 관점에서 설명될 수 있다. 어떤 언어들은 단 하나의 패러다임만을 지원한다. 예를 들어, 스몰토크는 객체 지향을 지원하고 하스켈은 함수형을 지원한다. 대부분의 언어는 다중 패러다임을 지원한다. 예를 들어, C++, 오브젝트 파스칼, 또는 PHP로 작성된 프로그램은 순수하게 절차적일 수도 있고, 순수하게 객체 지향일 수도 있으며, 두 패러다임 혹은 다른 패러다임의 측면을 모두 포함할 수도 있다.
다중 패러다임을 지원하는 언어를 사용할 때, 개발자는 어떤 패러다임 요소를 사용할지 선택한다. 하지만 이 선택이 패러다임 그 자체를 고려하는 것을 의미하지는 않을 수도 있다. 개발자는 종종 언어가 제공하는 기능을 개발자가 알고 있는 범위 내에서 사용한다. 결과물인 소스 코드를 패러다임별로 분류하는 것은 흔히 사후에 이루어지는 학술적 활동이다.
명령형 패러다임으로 분류되는 언어는 두 가지 주요 특징을 갖는다. 연산이 발생하는 순서를 명시하고 그 순서를 명시적으로 제어하는 구문을 가지며, 특정 시점에 코드 한 단위 내에서 상태를 수정하고 나중에 다른 코드 단위 내에서 다른 시점에 이를 읽을 수 있는 부작용을 허용한다. 코드 단위 간의 통신은 명시적이지 않다.
대조적으로, 선언형 패러다임의 언어는 연산을 실행할 순서를 명시하지 않는다. 대신 시스템에서 사용 가능한 여러 연산과 각 연산이 실행될 수 있는 조건을 제공한다.[10] 언어의 실행 모델 구현은 어떤 연산이 실행 가능한지 추적하고 독립적으로 순서를 선택한다. 자세한 내용은 다중 패러다임 프로그래밍 언어의 비교를 참조하라.
객체 지향 프로그래밍에서 코드는 객체의 코드에 의해 소유되고 (보통) 제어되는 상태를 포함하는 객체들로 조직된다. 대부분의 객체 지향 언어는 명령형 언어이기도 하다.
객체 지향 프로그래밍에서 프로그램은 상호작용하는 객체들의 집합으로 취급된다. 함수형 프로그래밍에서 프로그램은 상태가 없는 함수 평가의 시퀀스로 취급된다. 다수의 프로세서를 가진 컴퓨터나 시스템을 프로그래밍할 때, 프로세스 지향 프로그래밍에서 프로그램은 논리적인 공유 자료 구조에서 작동하는 병행 프로세스들의 집합으로 취급된다.
많은 프로그래밍 패러다임은 지원하는 기술만큼이나 금지하는 기술로도 잘 알려져 있다. 예를 들어, 순수 함수형 프로그래밍은 부작용을 허용하지 않으며, 구조적 프로그래밍은 goto 구문을 허용하지 않는다. 부분적으로 이러한 이유 때문에, 새로운 패러다임은 종종 기존의 것에 익숙한 사람들에게 교조적이거나 지나치게 엄격한 것으로 간주되기도 한다.[11] 하지만 특정 기술을 피함으로써 프로그램의 동작을 더 쉽게 이해하고 프로그램의 올바름에 대한 정리를 증명하는 것이 더 쉬워질 수 있다.
프로그래밍 패러다임은 API만을 사용하여 실행 모델을 호출할 수 있게 해주는 프로그래밍 모델과도 비교될 수 있다. 프로그래밍 모델 또한 실행 모델의 특징에 따라 패러다임으로 분류될 수 있다.
병렬 컴퓨팅의 경우, 언어 대신 프로그래밍 모델을 사용하는 것이 일반적이다. 그 이유는 병렬 하드웨어의 상세한 내용이 하드웨어를 프로그래밍하는 데 사용되는 추상화로 유출되기 때문이다. 이로 인해 프로그래머는 알고리즘의 패턴을 (하드웨어 유출로 인해 추상화에 삽입된) 실행 모델의 패턴에 매핑해야 한다. 결과적으로, 하나의 병렬 프로그래밍 언어가 모든 계산 문제에 잘 들어맞지는 않는다. 따라서 기본 순차 언어를 사용하고 프로그래밍 모델을 통해 병렬 실행 모델에 대한 API 호출을 삽입하는 것이 더 편리하다. 이러한 병렬 프로그래밍 모델은 공유 메모리, 메시지 전달 방식의 분산 메모리, 코드에서 가시적인 장소(place)의 개념 등 하드웨어를 반영하는 추상화에 따라 분류될 수 있다. 이들은 병렬 언어와 프로그래밍 모델에만 적용되는 프로그래밍 패러다임의 일종으로 간주될 수 있다.
프로그래밍 패러다임이라는 개념은 1978년 로버트 플로이드의 튜링상 강연 "The Paradigms of Programming"에서 처음 체계적으로 제시되었으며, 토머스 쿤의 《과학혁명의 구조》에서 사용된 패러다임 개념을 인용하였다.[12] 프로그래밍 패러다임은 프로그래머의 사고 방식과 문제 해결 접근법을 형성하며, 효과적인 프로그래밍 교육을 위해서는 패러다임을 명시적으로 가르치는 것이 중요하다.[13] 프로그래밍 언어의 설계는 해당 언어가 지원하는 패러다임에 크게 영향을 받으며, 언어는 사용자 커뮤니티의 주요 패러다임을 지원해야 한다.[14] 프로그래밍 패러다임은 계층적 관계를 가지며 시간이 지남에 따라 발전해 왔다. 초기에는 명령형 패러다임이 주류였으며, 이후 구조적 프로그래밍, 객체 지향 프로그래밍, 함수형 프로그래밍 등 다양한 패러다임이 등장하였다.[15]
비판
[편집]로버트 하퍼[16] 및 슈리람 크리슈나무르티[17]와 같은 일부 프로그래밍 언어 연구자들은 프로그래밍 언어의 분류로서 패러다임이라는 개념을 비판한다. 그들은 많은 프로그래밍 언어가 하나의 패러다임으로 엄격하게 분류될 수 없으며, 오히려 여러 패러다임의 기능을 포함하고 있다고 주장한다. 다중 패러다임 프로그래밍 언어의 비교를 참조하라.
프로그래밍 패러다임이라는 개념 자체는 1978년 로버트 W. 플로이드의 튜링상 강연 "The Paradigms of Programming"에서 처음 공식적으로 제안되었으며, 이는 토머스 쿤의 과학 혁명의 구조(1962)에서 사용된 패러다임 개념에 기반을 두고 있다.[18]
한편, 폴 그레이엄과 같은 비평가들은 디자인 패턴이 종종 프로그래밍 언어의 기능적 한계를 보완하기 위한 '임시변통의 해결책'(kludge)으로 작용한다고 주장한다.[19] 그레이엄은 "충분히 복잡한 C나 포트란 프로그램은 Common Lisp의 절반에 해당하는 임시변통의, 비공식적으로 명세된, 버그가 많고 느린 구현을 포함한다"는 그린스푼의 제10법칙을 인용하며,[20] 특정 패러다임의 기능이 부족한 언어에서는 개발자들이 패턴을 통해 부족한 기능을 구현해야 한다고 지적한다. 또한 일부 비평가들은 특정 패러다임이 모든 문제에 적합한 것은 아니며, 패러다임의 과도한 적용이나 '망치만 있으면 모든 것이 못처럼 보이는' 상황이 발생할 수 있다고 주장한다.[21] 특히 초보 개발자들이 새로 배운 패러다임을 모든 상황에 적용하려는 경향은 오히려 코드의 복잡성을 증가시키고 유지보수를 어렵게 만들 수 있다.
역사
[편집]프로그래밍에 대한 다양한 접근 방식은 시간이 흐르면서 발전해 왔다. 각 접근 방식의 분류는 그 방식이 처음 개발될 당시에 설명되기도 했지만, 종종 한참 시간이 흐른 뒤에 사후적으로 이루어졌다. 의식적으로 그렇게 식별된 초기 접근 방식 중 하나는 1960년대 중반부터 주창된 구조적 프로그래밍이다. 프로그래밍 패러다임이라는 개념 자체는 최소 1978년 로버트 플로이드의 튜링상 강연인 《프로그래밍의 패러다임》(The Paradigms of Programming)으로 거슬러 올라가는데, 그는 토머스 쿤이 그의 저서 《과학혁명의 구조》(1962)에서 사용한 패러다임의 개념을 인용했다.[22] 초기 프로그래밍 언어들은 명확하게 정의된 프로그래밍 패러다임을 가지고 있지 않았으며, 때때로 프로그램들이 goto 문을 과도하게 사용하여 이해와 유지보수가 어려운 스파게티 코드를 만들어내기도 했다. 이는 goto 문의 사용을 금지하고 더 구조화된 프로그래밍 구문만을 허용하는 구조적 프로그래밍 패러다임의 개발로 이어졌다.[23]
프로그래밍 패러다임의 발전은 1950년대부터 본격화되었으며, 각 시대별로 주요 언어들이 등장했다. 1950년대에는 포트란이 수식 계산과 변수 개념을 도입했고, 알골이 제어 구조 개념을 정립했으며, LISP가 함수형 프로그래밍의 기초를 마련했다.[24] 1960년대에는 코볼이 레코드를 통한 자료 구조 개념을 도입했고, BASIC이 교육용 언어로 보급되었으며, 시뮬라가 최초의 객체지향 프로그래밍 언어로 등장했다.[25] 1960년대 말에는 소프트웨어 위기가 대두되면서 객체지향 프로그래밍이 대응 방안으로 제시되었다.[26] 1970년대에는 C가 시스템 프로그래밍 언어로 등장하여 하드웨어의 세부 사항까지 다룰 수 있도록 설계되었고, 파스칼이 구조적 프로그래밍의 교육용 언어로 널리 사용되었다.[27] 1980년대에는 객체지향 개념이 견고해지고 다양한 언어 표준이 제정되면서 프로그래밍 언어가 대중화되었으며, 이 시기에 C++, 자바, C# 등 현대적인 객체지향 언어들이 등장했다.[28]
언어와 패러다임
[편집]기계어
[편집]기계어는 컴퓨터가 이해할 수 있는 추상화의 가장 낮은 단계에서 동작을 정의하는 명령어 집합으로, 컴퓨터 프로그래밍의 가장 낮은 단계이다. 이는 코드를 작성하는 가장 지시적인 방식이므로 명령형으로 분류된다.
때때로 이를 1세대 프로그래밍 언어라고 부른다.
어셈블리
[편집]어셈블리어는 기계 명령어와 메모리 주소에 대한 니모닉(mnemonics)을 도입했다. 어셈블리는 명령형으로 분류되며 때때로 2세대 프로그래밍 언어라고 불린다.
1960년대에 어셈블리어는 라이브러리 COPY와 매우 정교한 조건부 매크로 생성 및 전처리 기능, 서브루틴 호출(CALL), 외부 변수 및 공용 섹션(전역)을 지원하도록 발전하여, READ/WRITE/GET/PUT과 같은 논리 연산자를 통해 하드웨어 특성으로부터 상당한 코드 재사용과 격리를 가능하게 했다. 어셈블리는 기계가 수행하는 작업에 대해 가장 많은 제어권을 제공하기 때문에 시간적으로 중요한 시스템과 임임베디드 시스템에서 과거에도 사용되었고 지금도 여전히 사용되고 있다.
어셈블리어의 각 명령어는 일반적으로 연산 코드(OPCODE)와 피연산자(OPERAND)로 구성된다. 연산 코드는 수행할 작업을 지정하며, 피연산자는 작업에 사용될 데이터나 데이터의 위치를 지정한다.[29] 어셈블러는 어셈블리어 소스 코드를 기계어로 변환하는 프로그램으로, 니모닉 명령어를 해당하는 기계어 오피코드로 변환하고 심볼릭 이름을 실제 메모리 주소로 해석하는 역할을 한다.[30] 주소 지정 방식은 피연산자의 위치를 지정하는 방법으로, 즉시 주소 지정(상수 값 직접 사용), 레지스터 주소 지정(레지스터 값 사용), 직접 메모리 주소 지정(절대 주소 사용), 레지스터 간접 주소 지정(레지스터가 가리키는 주소 사용) 등 다양한 방식이 존재한다.[31] 어셈블리어는 기계어와 1:1 대응 관계를 가지며, 각 어셈블리 명령어는 특정한 기계어 명령 코드로 직접 변환된다. 이는 하드웨어에 대한 직접적인 제어를 가능하게 하지만 특정 CPU 아키텍처에 종속되는 특성을 가진다.[32] 어셈블리는 기계가 수행하는 작업에 대해 가장 많은 제어권을 제공하기 때문에 시간적으로 중요한 시스템과 임베디드 시스템에서 과거에도 사용되었고 지금도 여전히 사용되고 있다. 특히 운영체제 커널, 장치 드라이버, 부트로더, 성능 최적화가 필요한 핵심 루틴, 리버스 엔지니어링 등에서 중요한 역할을 한다.[33]
절차적 언어
[편집]3세대 프로그래밍 언어라고도 불리는 절차적 언어는 최초로 고급 프로그래밍 언어로 기술된 언어들이다. 이들은 해결하려는 문제와 관련된 어휘를 지원한다. 예를 들면 다음과 같다.
- COmmon Business Oriented Language (코볼) – 파일, move, copy와 같은 용어를 사용한다.
- FORmula TRANslation (포트란) – 수학적 언어 용어를 사용하며, 주로 과학 및 공학 문제를 위해 개발되었다.
- ALGOrithmic Language (알골) – 포트란과 마찬가지로 과학 및 공학 문제를 대상으로 수학적 언어 용어를 사용하면서, 알고리즘을 정의하기에 적절한 언어가 되는 데 집중했다.
- Programming Language One (PL/I) – 포인터를 지원하는 상업적-과학적 하이브리드 범용 언어이다.
- Beginners All purpose Symbolic Instruction Code (베이직) – 더 많은 사람들이 프로그램을 작성할 수 있도록 개발되었다.
- C – 1969년에서 1973년 사이에 AT&T 벨 연구소의 데니스 리치가 처음 개발한 범용 프로그래밍 언어이다.
이러한 언어들은 절차적 패러다임으로 분류된다. 이들은 컴퓨터 프로그램이 따르는 단계별 프로세스를 직접 제어한다. 따라서 이러한 프로그램의 효능과 알고리즘 효율성은 프로그래머의 기술에 크게 의존한다.
객체 지향 프로그래밍
[편집]절차적 언어를 개선하려는 시도로 시뮬라, 스몰토크, C++, 에펠, 파이썬, PHP, 자바, C 샤프와 같은 객체 지향 프로그래밍(OOP) 언어들이 만들어졌다. 이러한 언어에서 자료와 자료를 조작하는 메서드는 객체라고 불리는 동일한 코드 단위 안에 있다. 이러한 캡슐화는 객체가 데이터에 접근하는 유일한 방법이 데이터를 포함하는 객체의 메서드를 통하는 것임을 보장한다. 따라서 객체를 사용하는 코드에 영향을 주지 않고 객체의 내부 작동 방식을 변경할 수 있다.
알렉산더 스테파노프, 리처드 스톨먼[34] 및 다른 프로그래머들은 절차적 패러다임 대비 OOP 패러다임의 효능에 대해 논쟁을 제기해 왔다. 모든 객체가 연관된 메서드를 가져야 할 필요성 때문에 일부 회의론자들은 OOP를 소프트웨어 블롯과 연관시키기도 하며, 이러한 딜레마를 해결하려는 시도는 다형성을 통해 이루어졌다.
대부분의 OOP 언어는 3세대 언어이지만, 객체 지향 어셈블러 언어를 만드는 것도 가능하다. High Level Assembly(HLA)는 초기 기원에도 불구하고 고급 데이터 유형과 객체 지향 어셈블리어 프로그래밍을 완전히 지원하는 사례이다 – . 따라서 서로 다른 프로그래밍 패러다임은 한 단계에서 다음 단계로의 발전을 반드시 나타낸다기보다는, 옹호자들의 동기 부여적인 밈과 같은 것으로 볼 수 있다. 경쟁하는 패러다임들의 효능에 대한 정확한 비교는, 유사한 엔티티와 프로세스에 적용되는 새롭고 상이한 용어들과 언어 전반에 걸친 수많은 구현 차이로 인해 종종 어려움을 겪는다.
객체 지향 프로그래밍은 네 가지 핵심 원칙을 기반으로 한다: 캡슐화(Encapsulation), 상속(Inheritance), 다형성(Polymorphism), 추상화(Abstraction). 캡슐화는 데이터와 이를 처리하는 메서드를 하나의 단위로 묶어 외부에서의 직접적인 접근을 제한하는 것을 말하며, 상속은 기존 클래스의 속성과 기능을 새로운 클래스가 물려받아 재사용성을 높인다. 다형성은 같은 인터페이스가 상황에 따라 다른 방식으로 동작할 수 있는 능력을 의미하며, 추상화는 복잡한 현실을 핵심적인 개념만 추출하여 단순화하는 과정이다.[35] 객체 지향 프로그래밍의 개념은 1960년대 시뮬라 언어에서 처음 등장했으며, 1970년대 스몰토크 언어에서 본격적으로 발전되었다. 시뮬라-67은 최초로 클래스와 객체 개념을 도입한 언어로 알려져 있으며, 주로 시뮬레이션 프로그래밍을 위해 개발되었다. 스몰토크는 앨런 케이가 팰로앨토 연구소(PARC)에서 개발한 최초의 순수 객체 지향 언어로, GUI 환경과 통합 개발 환경을 최초로 제공했다.[36] 1980년대에는 C++와 Objective-C가 등장하면서 객체 지향 개념이 주류 프로그래밍에 본격적으로 확산되었고, 1990년대에는 Java와 C#이 등장하여 엔터프라이즈 개발에서 널리 사용되기 시작했다.[37] 현대 객체 지향 프로그래밍은 다양한 패러다임과 결합되고 있다. Java와 C#은 함수형 프로그래밍 요소를 도입했으며, Python과 JavaScript는 다중 패러다임 언어로 발전했다. 또한 객체 지향 설계 원칙으로 SOLID 원칙이 널리 사용되며, 디자인 패턴을 통해 반복적인 설계 문제에 대한 검증된 해결책을 제공한다.[38]
선언형 언어
[편집]선언형 프로그래밍 프로그램은 문제를 해결하는 방법이 아니라 문제가 무엇인지를 설명한다. 프로그램은 따라야 할 절차가 아니라 예상 결과에서 찾고자 하는 속성들의 집합으로 구조화된다. 데이터베이스나 규칙 집합이 주어지면 컴퓨터는 원하는 모든 속성과 일치하는 해를 찾으려고 시도한다. 선언형 언어의 전형적인 예로는 4세대 프로그래밍 언어인 SQL과 함수형 언어 및 논리형 프로그래밍 가족이 있다.
함수형 프로그래밍은 선언형 프로그래밍의 하위 집합이다. 이 패러다임을 사용하여 작성된 프로그램은 수학적 함수처럼 동작하도록 의도된 코드 블록인 서브루틴을 사용한다. 함수형 언어는 대입을 통한 변수 값의 변경을 지양하고, 대신 재귀를 많이 사용한다.
논리형 프로그래밍 패러다임은 계산을 지식체에 대한 자동화된 추론으로 본다. 문제 도메인에 관한 사실들은 논리식으로 표현되며, 프로그램은 문제에 대한 답을 찾거나 공식 집합이 모순임을 증명할 때까지 추론 규칙을 적용하여 실행된다.
선언형 프로그래밍의 주요 특징으로는 불변성, 순수 함수, 참조 투명성 등이 있다.[39] 이러한 특징들은 코드의 예측 가능성을 높이고 테스트 용이성을 향상시키며, 병렬 처리 환경에서 안정성을 보장한다.[40] 선언형 프로그래밍의 대표적인 장점으로는:
- 가독성 향상: 코드가 무엇을 하는지에 집중하므로 의도를 명확히 표현할 수 있다
- 테스트 용이성: 부수 효과가 없어 단위 테스트가 간단하다
- 디버깅 용이성: 상태 변경이 제한되어 버그 추적이 용이하다
- 병렬 처리 지원: 불변 데이터 구조로 인해 경쟁 조건이 발생하지 않는다
함수형 프로그래밍에서는 고차 함수를 활용하여 코드의 재사용성을 높인다.[41] 예를 들어, 배열 처리 시 명령형 방식의 for 루프 대신 map, filter, reduce 같은 고차 함수를 사용한다.
선언형 프로그래밍의 대표적인 예로는 SQL (데이터베이스 질의), HTML (웹 마크업), Prolog (논리 프로그래밍), 하스켈 (순수 함수형 언어) 등이 있다.[42] 이러한 언어들은 "어떻게" 수행할지보다 "무엇을" 원하는지에 집중하여 개발자의 의도를 명확히 표현할 수 있도록 한다.
기타 패러다임
[편집]심볼릭 프로그래밍은 공식과 프로그램 구성 요소를 데이터로 조작할 수 있는 프로그램을 설명하는 패러다임이다.[4] 따라서 프로그램은 효과적으로 자기 자신을 수정하고 "학습"하는 것처럼 보일 수 있어, 인공지능, 전문가 시스템, 자연어 처리 및 컴퓨터 게임과 같은 응용 분야에 적합하다. 이 패러다임을 지원하는 언어로는 리스프와 프롤로그가 있다.[43]
미분 가능 프로그래밍은 프로그램 전체에서 보통 자동 미분을 통해 미분이 가능하도록 프로그램을 구조화한다.[44][45]
문학적 프로그래밍은 명령형 프로그래밍의 한 형태로서, 하이퍼텍스트 에세이와 같이 인간 중심의 망(web)으로 프로그램을 구조화한다. 문서화가 프로그램의 필수적인 부분이며, 프로그램은 컴파일러의 편의가 아니라 산문 설명의 논리에 따라 구조화된다.
프로그램이 자기 자신을 참조할 수 있게 하는 반영 프로그래밍(리플렉션)과 같은 심볼릭 프로그래밍 기법 또한 프로그래밍 패러다임으로 간주될 수 있다. 그러나 이는 주요 패러다임들과 호환되므로 그 자체로 독립적인 진정한 패러다임은 아니다.
같이 보기
[편집]각주
[편집]- ↑ “Multi-Paradigm Programming Language”. 《Mozilla Developer Network》. 모질라 재단. 2013년 6월 21일. 2013년 8월 21일에 원본 문서에서 보존된 문서.
- ↑ Nørmark, Kurt. Overview of the four main programming paradigms. Aalborg University, 9 May 2011. Retrieved 22 September 2012.
- ↑ Frans Coenen (1999년 10월 11일). “Characteristics of declarative programming languages” (미국 영어). 《cgi.csc.liv.ac.uk》. 2014년 2월 27일에 원본 문서에서 보존된 문서. 2014년 2월 20일에 확인함.
- 1 2 Michael A. Covington (2010년 8월 23일). “CSCI/ARTI 4540/6540: First Lecture on Symbolic Programming and LISP” (PDF). University of Georgia. 2012년 3월 7일에 원본 문서 (PDF)에서 보존된 문서. 2013년 11월 20일에 확인함.
- 1 2 Peter Van-Roy; Seif Haridi (2004). 《Concepts, Techniques, and Models of Computer Programming》. MIT Press. ISBN 978-0-262-22069-9.
- ↑ Krishnamurthi, Shriram (2008년 11월). “Teaching programming languages in a post-linnaean age”. 《ACM SIGPLAN Notices》 43 (11): 81–83. doi:10.1145/1480828.1480846.
- ↑ “왜 지금 멀티패러다임 프로그래밍인가?”. 한빛미디어. 2026년 4월 10일에 확인함.
- ↑ “프로그래밍 언어”. Unisquads Wiki. 2026년 4월 10일에 확인함.
- ↑ Peter Van Roy (2009년 5월 12일). “Programming Paradigms: What Every Programmer Should Know” (PDF). info.ucl.ac.be. 2014년 1월 27일에 확인함.
- ↑ “Programming paradigms: What are the principles of programming?” (미국 영어). 《IONOS Digitalguide》. 2020년 4월 20일. 2022년 6월 29일에 원본 문서에서 보존된 문서. 2022년 5월 3일에 확인함.
- ↑ Frank Rubin (March 1987). 《'GOTO Considered Harmful' Considered Harmful》 (PDF). 《Communications of the ACM》 30. 195–196쪽. doi:10.1145/214748.315722. S2CID 6853038. 2009년 3월 20일에 원본 문서 (PDF)에서 보존된 문서.
- ↑ Robert W. Floyd (1979년 8월 1일). “The paradigms of programming”. 2026년 4월 10일에 확인함.
- ↑ Robert W. Floyd. “The Paradigms of Programming - 1978 Turing Award Lecture” (PDF). 2026년 4월 10일에 확인함.
- ↑ “Robert W. Floyd - A.M. Turing Award Laureate”. Association for Computing Machinery. 2026년 4월 10일에 확인함.
- ↑ sith-call.dev (2021년 8월 3일). “프로그래밍 패러다임의 개요(1) : 논문 정리”. 2026년 4월 10일에 확인함.
- ↑ Harper, Robert (2017년 5월 1일). “What, if anything, is a programming-paradigm?”. 《FifteenEightyFour》. Cambridge University Press.
- ↑ Krishnamurthi, Shriram (November 2008). 《Teaching programming languages in a post-linnaean age》. 《ACM SIGPLAN Notices》 43 (ACM). 81–83쪽. doi:10.1145/1480828.1480846. S2CID 35714982..
- ↑ Floyd, R. W. (1979). “The paradigms of programming”. 《Communications of the ACM》 22 (8): 455–460. doi:10.1145/359138.359140.
- ↑ Graham, Paul. “Revenge of the Nerds”. 2026년 4월 10일에 확인함.
- ↑ Graham, Paul. “Revenge of the Nerds”. 2026년 4월 10일에 확인함.
- ↑ “패턴에 대한 비판”. 2026년 4월 10일에 확인함.
- ↑ Floyd, R. W. (1979). 《The paradigms of programming》. 《Communications of the ACM》 22. 455–460쪽. doi:10.1145/359138.359140.
- ↑ Soroka, Barry I. (2006). 《Java 5: Objects First》. Jones & Bartlett Learning. ISBN 9780763737207.
- ↑ “프로그래밍 패러다임의 개요(1) : 논문 정리”. 2026년 4월 10일에 확인함.
- ↑ “01_언어의 등장 및 발전 원리”. 2026년 4월 10일에 확인함.
- ↑ “프로그래밍 패러다임의 개요(1) : 논문 정리”. 2026년 4월 10일에 확인함.
- ↑ “01_언어의 등장 및 발전 원리”. 2026년 4월 10일에 확인함.
- ↑ “모든 프로그래밍 언어의 간략한 역사”. 2026년 4월 10일에 확인함.
- ↑ “컴퓨터 구조 명령어 코드, OP Code, Mode, Operand”. 2026년 4월 10일에 확인함.
- ↑ “시스템프로그래밍 Assembler: 어셈블리 언어로 작성된 프로그램을 기계어 코드로”. 2026년 4월 10일에 확인함.
- ↑ “컴퓨터 구조 명령어의 구조와 주소 지정 방식”. 2026년 4월 10일에 확인함.
- ↑ “기계어와 어셈블리”. 2026년 4월 10일에 확인함.
- ↑ “42서울 교육과정 3서클 libasm 학습 노트”. 2026년 4월 10일에 확인함.
- ↑ “Mode inheritance, cloning, hooks & OOP (Google Groups Discussion)”.
- ↑ “객체 지향 프로그래밍의 4가지 특징”. 2026년 4월 10일에 확인함.
- ↑ “스몰토크 - 위키백과”. 2026년 4월 10일에 확인함.
- ↑ “객체 지향 프로그래밍 - 나무위키”. 2026년 4월 10일에 확인함.
- ↑ “객체 지향 4대 원칙”. 2026년 4월 10일에 확인함.
- ↑ “선언형 프로그래밍과 함수형 프로그래밍의 심층 이해”. 2026년 4월 10일에 확인함.
- ↑ “순수 함수와 불변성”. 2026년 4월 10일에 확인함.
- ↑ “선언형 VS 함수형 프로그래밍”. 2026년 4월 10일에 확인함.
- ↑ “명령형 vs 선언형 프로그래밍”. 2026년 4월 10일에 확인함.
- ↑ “Business glossary: Symbolic programming definition”. 《allbusiness.com》. 2014년 7월 30일에 확인함.
- ↑ Wang, Fei; Decker, James; Wu, Xilun; Essertel, Gregory; Rompf, Tiark (2018), Bengio, S.; Wallach, H.; Larochelle, H.; Grauman, K. (편집), “Backpropagation with Callbacks: Foundations for Efficient and Expressive Differentiable Programming” (PDF), 《Advances in Neural Information Processing Systems 31》 (Curran Associates, Inc.), 10201–10212쪽, 2019년 2월 13일에 확인함
- ↑ Innes, Mike (2018). 《On Machine Learning and Programming Languages》 (PDF). 《SysML Conference 2018》. 2018년 9월 20일에 원본 문서 (PDF)에서 보존된 문서. 2019년 2월 13일에 확인함.