프로그래밍 언어

프로그래밍 언어(programming language)는 컴퓨터 프로그램을 표현하기 위한 인공 언어이다.

프로그래밍 언어는 일반적으로 소프트웨어를 작성할 때 인간이 읽을 수 있는 방식으로 작성할 수 있도록 한다.

프로그램의 실행에는 구현체가 필요하다. 프로그래밍 언어를 구현하는 주요 접근 방식은 두 가지이다. 하나는 프로그램이 미리 기계어로 컴파일되는 컴파일 방식이고, 다른 하나는 프로그램이 직접 실행되는 인터프리터 방식이다. 이 두 가지 극단적인 방식 외에도 일부 구현체는 JIT 컴파일 및 바이트코드 인터프리터와 같은 혼합 방식을 사용한다.

프로그래밍 언어의 설계는 컴퓨터 구조에 의해 강하게 영향을 받았으며, 대부분의 명령형 언어는 보편적인 폰 노이만 구조를 중심으로 설계되었다. 초기 프로그래밍 언어는 컴퓨터 하드웨어와 밀접하게 관련되어 있었지만, 현대 언어는 더 적은 노력으로 더 나은 소프트웨어를 가능하게 하기 위해 추상화를 통해 하드웨어 세부 사항을 숨기는 경우가 많다.

 관련 개념 
프로그래밍 언어는 사람들 사이의 아이디어 소통을 가능하게 한다는 점에서 자연어와 유사점이 있다. 즉, 프로그램은 일반적으로 인간이 읽을 수 있으며 복잡한 아이디어를 표현할 수 있다. 그러나 프로그래밍 언어가 표현할 수 있는 아이디어의 종류는 궁극적으로 계산의 영역으로 제한된다.

컴퓨터 언어라는 용어는 때때로 프로그래밍 언어와 상호 교환적으로 사용되기도 하지만Robert A. Edmunds, The Prentice-Hall standard glossary of computer terminology, Prentice-Hall, 1985, p. 91 일부는 이들이 다른 개념이라고 주장한다. 일부는 프로그래밍 언어가 컴퓨터 언어의 하위 집합이라고 주장한다.Pascal Lando, Anne Lapujade, Gilles Kassel, and Frédéric Fürst, Towards a General Ontology of Computer Programs , ICSOFT 2007 , pp. 163–170 일부는 컴퓨터 언어를 프로그래밍 언어로 간주되지 않는 컴퓨팅에 사용되는 언어를 분류하는 데 사용한다. 일부는 프로그래밍 언어를 추상 기계를 프로그래밍하기 위한 이론적 구성으로 간주하고, 컴퓨터 언어를 유한한 하드웨어 리소스를 가진 물리적 컴퓨터에서 실행되는 것들의 하위 집합으로 간주한다.R. Narasimhan, Programming Languages and Computers: A Unified Metatheory, pp. 189—247 in Franz Alt, Morris Rubinoff (eds.) Advances in computers, Volume 8, Academic Press, 1994, , p.215: "[...] the model [...] for computer languages differs from that [...] for programming languages in only two respects. In a computer language, there are only finitely many names—or registers—which can assume only finitely many values—or states—and these states are not further distinguished in terms of any other attributes. [author's footnote:] This may sound like a truism but its implications are far-reaching. For example, it would imply that any model for programming languages, by fixing certain of its parameters or features, should be reducible in a natural way to a model for computer languages."

존 C. 레이놀즈는 형식 명세 언어가 실행을 위한 언어만큼 프로그래밍 언어라고 강조한다. 그는 컴퓨터의 동작에 영향을 미치는 텍스트 형식 및 심지어 그래픽 입력 형식도 프로그래밍 언어라고 주장하며, 일반적으로 튜링 완전하지 않더라도 프로그래밍 언어 개념에 대한 무지가 입력 형식의 많은 결함의 원인이라고 말한다.John C. Reynolds, "Some thoughts on teaching programming and programming languages", SIGPLAN Notices, Volume 43, Issue 11, November 2008, p.109

 역사 

 초기 개발 
최초의 프로그래밍 가능한 컴퓨터는 1940년대에 발명되었고, 그와 함께 최초의 프로그래밍 언어도 등장했다. 초기 컴퓨터는 1세대 프로그래밍 언어인 기계어(프로세서가 직접 실행할 수 있는 간단한 명령어)로 프로그래밍되었다. 이 코드는 디버깅이 매우 어려웠고, 다른 컴퓨터 시스템 간에 이식성이 없었다. 프로그래밍의 용이성을 향상시키기 위해 어셈블리어(또는 2세대 프로그래밍 언어—2GL)가 발명되어 기계어와는 다르게 인간이 프로그램을 더 쉽게 이해할 수 있도록 했지만, 이식성은 증가시키지 못했다.

초기에는 하드웨어 자원이 부족하고 비쌌지만, 인적자원은 더 저렴했다. 따라서 사용하기 번거롭지만 효율성을 높이기 위해 하드웨어에 더 가까운 언어가 선호되었다. 고급 프로그래밍 언어 (3세대 프로그래밍 언어—3GL)의 등장은 프로그래밍에 혁명을 가져왔다. 이 언어들은 하드웨어의 세부 사항을 추상화하고, 대신 인간이 더 쉽게 이해할 수 있는 알고리즘을 표현하도록 설계되었다. 예를 들어, 산술 표현식은 이제 기호 표기법으로 작성한 다음 하드웨어가 실행할 수 있는 기계어로 번역될 수 있었다. 1957년에는 포트란(FORmula TRANslation)이 발명되었다. 종종 최초의 컴파일된 고급 프로그래밍 언어로 간주되는 포트란은 21세기까지 사용되었다.

 1960년대 및 1970년대 
1960년경, 최초의 메인프레임(범용 컴퓨터)이 개발되었지만, 전문가만이 작동할 수 있었고 비용이 엄청났다. 데이터와 명령어는 천공 카드로 입력되었으며, 프로그램이 실행되는 동안에는 입력할 수 없었다. 따라서 이때 개발된 언어들은 최소한의 상호작용을 위해 설계되었다. 마이크로프로세서 발명 이후, 1970년대의 컴퓨터는 극적으로 저렴해졌다. 새로운 컴퓨터는 또한 더 많은 사용자 상호작용을 허용했으며, 이는 새로운 프로그래밍 언어에 의해 지원되었다.

1958년에 구현된 리스프는 최초의 함수형 프로그래밍 언어였다. 포트란과 달리 재귀와 조건부 표현식을 지원했으며, 힙에 동적 메모리 관리와 자동 쓰레기 수집을 도입했다. 다음 수십 년 동안 리스프는 인공지능 애플리케이션을 지배했다. 1978년, 또 다른 함수형 언어인 ML은 추론된 자료형과 다형성 매개변수를 도입했다.

1958년과 1960년에 알골(ALGOrithmic Language)이 출시된 후, 알고리즘을 설명하는 컴퓨팅 문헌의 표준이 되었다. 상업적 성공은 제한적이었지만, C, 파스칼, 에이다, C++, 자바, C#를 포함한 대부분의 인기 있는 명령형 언어는 직간접적으로 알골 60에서 파생되었다. 이후 프로그래밍 언어에 채택된 혁신 중에는 더 큰 이식성과 문맥 자유, BNF 문법의 첫 사용이 포함되었다. 시뮬라, 객체 지향 프로그래밍(서브타입, 동적 디스패치, 상속 포함)을 지원하는 최초의 언어도 알골에서 파생되었으며 상업적 성공을 거두었다. 또 다른 알골 파생 언어인 C는 21세기까지 인기를 유지했다. C는 다른 현대 언어보다 하위 수준의 기계 작업에 더 많이 접근할 수 있도록 한다. 유연한 포인터 작업을 통해 부분적으로 생성된 C의 강력함과 효율성은 올바른 코드를 작성하기 더 어렵게 만드는 대가를 치른다.

1972년에 설계된 프롤로그는 형식 논리 표기법을 사용하여 컴퓨터와 통신하는 최초의 논리형 프로그래밍 언어였다. 논리 프로그래밍을 통해 프로그래머는 원하는 결과를 지정하고 인터프리터가 이를 달성하는 방법을 결정하도록 한다.

 1980년대부터 2000년대까지 

1980년대에는 개인용 컴퓨터의 발명으로 프로그래밍 언어가 사용되는 역할이 변화했다. 1980년대에 도입된 새로운 언어에는 C 프로그램을 컴파일할 수 있을 뿐만 아니라 클래스와 상속을 지원하는 C의 상위 집합인 C++가 포함되었다. 에이다 및 기타 새로운 언어들은 병행성을 지원하기 시작했다. 일본 정부는 논리 프로그래밍 구성에 병행성 지원을 추가한 이른바 5세대 프로그래밍 언어에 막대한 투자를 했지만, 이 언어들은 다른 병행성 지원 언어들에 비해 성능이 떨어졌다.

1990년대 인터넷과 월드 와이드 웹의 급속한 성장으로 인해 웹 페이지와 컴퓨터 망을 지원하기 위한 새로운 프로그래밍 언어들이 도입되었다. C++를 기반으로 하고 시스템 간 이식성과 보안 강화를 위해 설계된 자바는 이러한 기능들이 많은 인터넷 애플리케이션에 필수적이기 때문에 대규모 성공을 거두었다. 또 다른 발전은 동적 타입 스크립트 언어인 파이썬, 자바스크립트, PHP, 루비의 개발이었다. 이 언어들은 기존 애플리케이션을 조정하는 작은 프로그램을 빠르게 생성하도록 설계되었다. HTML과의 통합으로 인해 서버에서 호스팅되는 웹 페이지를 구축하는 데도 사용되었다.

 2000년대부터 현재까지 
2000년대에는 널리 인기를 얻은 새로운 프로그래밍 언어의 개발이 둔화되었다. 한 가지 혁신은 네트워크로 연결된 구성 요소를 가진 분산 시스템을 활용하도록 설계된 서비스 지향 프로그래밍이었다. 서비스는 객체 지향 프로그래밍의 객체와 유사하지만 별도의 프로세스에서 실행된다. C#와 F#는 명령형 및 함수형 프로그래밍 간의 아이디어를 교차 적용했다. 2010년 이후, 러스트, Go, 스위프트, Zig 및 Carbon과 같은 여러 새로운 언어들이 C가 역사적으로 사용되어 온 성능이 중요한 소프트웨어 분야에서 경쟁했다. 새로운 프로그래밍 언어의 대부분은 정적 타입을 사용하는 반면, Ring 및 줄리아와 같은 소수의 새로운 언어는 동적 타입을 사용한다.Ayouni, M. and Ayouni, M., 2020. Data Types in Ring. Beginning Ring Programming: From Novice to Professional, pp.51-98.

일부 새로운 프로그래밍 언어는 스크래치, LabVIEW 및 PWCT와 같은 시각적 프로그래밍 언어로 분류된다. 또한, 일부 언어는 Ballerina처럼 텍스트 및 시각적 프로그래밍 사용을 혼합한다.Sáez-López, J.M., Román-González, M. and Vázquez-Cano, E., 2016. Visual programming languages integrated across the curriculum in elementary school: A two year case study using "Scratch" in five schools. Computers & Education, 97, pp.129-141.Fayed, M.S., Al-Qurishi, M., Alamri, A. and Al-Daraiseh, A.A., 2017, March. PWCT: visual language for IoT and cloud computing applications and systems. In Proceedings of the Second International Conference on Internet of things, Data and Cloud Computing (pp. 1-5).Kodosky, J., 2020. LabVIEW. Proceedings of the ACM on Programming Languages, 4(HOPL), pp.1-54.Fernando, A. and Warusawithana, L., 2020. Beginning Ballerina Programming: From Novice to Professional. Apress. 또한, 이러한 추세는 구글의 블록리와 같은 새로운 VPL 개발을 돕는 프로젝트로 이어졌다.Baluprithviraj, K.N., Bharathi, K.R., Chendhuran, S. and Lokeshwaran, P., 2021, March. Artificial intelligence based smart door with face mask detection. In 2021 International Conference on Artificial Intelligence and Smart Systems (ICAIS) (pp. 543-548). IEEE. 언리얼 및 유니티와 같은 많은 게임 엔진도 시각적 스크립팅을 지원하기 시작했다.Sewell, B., 2015. Blueprints visual scripting for unreal engine. Packt Publishing Ltd.Bertolini, L., 2018. Hands-On Game Development without Coding: Create 2D and 3D games with Visual Scripting in Unity. Packt Publishing Ltd.

 정의 
언어는 구문(형식)과 의미론(의미)으로 정의할 수 있으며, 종종 형식 언어 사양을 통해 정의된다.

 구문 

프로그래밍 언어의 표면 형식은 해당 구문으로 알려져 있다. 대부분의 프로그래밍 언어는 순전히 텍스트 기반이며, 서면 자연어와 마찬가지로 단어, 숫자 및 구두점을 포함하는 텍스트 시퀀스를 사용한다. 반면에 일부 프로그래밍 언어는 그래픽 언어로, 기호 간의 시각적 관계를 사용하여 프로그램을 지정한다.

언어의 구문은 구문적으로 올바른 프로그램을 구성하는 기호의 가능한 조합을 설명한다. 기호 조합에 부여되는 의미는 의미론(형식적이거나 참조 구현에 하드 코딩된)에 의해 처리된다. 대부분의 언어는 텍스트 기반이므로 이 문서는 텍스트 구문에 대해 논한다.

프로그래밍 언어 구문은 일반적으로 정규 표현식(어휘 구조용)과 배커스-나우르 표기법(문법 구조용)의 조합을 사용하여 정의된다. 다음은 리스프를 기반으로 한 간단한 문법이다.
expression ::= atom | list
atom       ::= number | symbol
number     ::= [+-]?['0'-'9']+
symbol     ::= ['A'-'Za'-'z'].*
list       ::= '(' expression* ')'

이 문법은 다음을 지정한다.
 표현식은 아톰 또는 리스트이다.
 아톰은 숫자 또는 기호이다.
 숫자는 하나 이상의 십진 숫자의 끊어지지 않은 시퀀스이며, 선택적으로 더하기 또는 빼기 부호가 앞에 올 수 있다.
 기호는 알파벳 문자(공백 제외) 중 하나 이상의 문자가 뒤따르는 문자이다.
 리스트는 일치하는 한 쌍의 괄호이며, 그 안에 0개 이상의 표현식이 있다.

다음은 이 문법에서 잘 구성된 토큰 시퀀스의 예이다. 12345, (), (a b c232 (1)).

모든 구문적으로 올바른 프로그램이 의미론적으로 올바른 것은 아니다. 많은 구문적으로 올바른 프로그램은 언어의 규칙에 따라 잘못 구성되어 있으며, (언어 사양 및 구현의 건전성에 따라) 번역 또는 실행 시 오류가 발생할 수 있다. 경우에 따라 이러한 프로그램은 미정의 동작을 나타낼 수 있다. 프로그램이 언어 내에서 잘 정의되어 있더라도, 작성자가 의도하지 않은 의미를 가질 수 있다.

자연어를 예로 들면, 문법적으로 올바른 문장에 의미를 할당할 수 없거나 문장이 거짓일 수 있다.
 "Colorless green ideas sleep furiously"는 문법적으로는 잘 구성되어 있지만 일반적으로 받아들여지는 의미가 없다.
 "John is a married bachelor"는 문법적으로 잘 구성되어 있지만, 참이 될 수 없는 의미를 표현한다.

다음 C 언어 조각은 구문적으로 올바르지만, 의미론적으로 정의되지 않은 연산을 수행한다(*p >> 4 연산은 복소수형 값에 의미가 없고, p->im은 p의 값이 널 포인터이기 때문에 정의되지 않았다).

complex *p = NULL;
complex abs_p = sqrt(*p >> 4 + p->im);

첫 번째 줄의 형 선언이 생략되면, 프로그램은 컴파일 중에 정의되지 않은 변수 p에 대한 오류를 발생시킬 것이다. 그러나 형 선언은 의미 정보만 제공하므로 프로그램은 여전히 구문적으로 올바를 것이다.

프로그래밍 언어를 지정하는 데 필요한 문법은 촘스키 위계에서의 위치로 분류할 수 있다. 대부분의 프로그래밍 언어의 구문은 Type-2 문법, 즉 문맥 자유 문법을 사용하여 지정할 수 있다. Section 2.2: Pushdown Automata, pp.101–114. Perl과 Lisp를 포함한 일부 언어는 파싱 단계에서 실행을 허용하는 구문을 포함한다. 프로그래머가 파서의 동작을 변경할 수 있도록 하는 구문을 가진 언어는 구문 분석을 판정 불가능한 문제로 만들며, 일반적으로 파싱과 실행의 구분을 모호하게 한다.Jeffrey Kegler, "Perl and Undecidability ", The Perl Review. Papers 2 and 3 prove, using respectively 라이스의 정리 and direct reduction to the halting problem, that the parsing of Perl programs is in general undecidable. 일반적인 계산을 포함할 수 있는 Lisp 매크로 시스템과 Perl의 BEGIN 블록과는 대조적으로, C 매크로는 단순한 문자열 대체이며 코드 실행을 요구하지 않는다.Marty Hall, 1995, Lecture Notes: Macros , 포스트스크립트 version 

 의미론 
의미론은 언어의 구문에 따르는 내용의 의미를 나타낸다.

 정적 의미론 
정적 의미론은 표준 구문 형식으로 표현하기 어렵거나 불가능한 유효한 텍스트의 구조에 대한 제약을 정의한다. 컴파일 언어의 경우, 정적 의미론은 본질적으로 컴파일 시점에 확인할 수 있는 의미 규칙을 포함한다. 예를 들어, 모든 식별자가 사용되기 전에 선언되었는지 (그러한 선언을 요구하는 언어의 경우) 또는 case 문의 각 레이블이 고유한지 확인하는 것이 포함된다.Michael Lee Scott, Programming language pragmatics, Edition 2, Morgan Kaufmann, 2006, , p. 18–19 이러한 유형의 많은 중요한 제약 사항, 예를 들어 식별자가 적절한 문맥에서 사용되는지 (예: 정수를 함수 이름에 추가하지 않는 것) 또는 서브루틴 호출에 적절한 수와 유형의 인수가 있는지 확인하는 것 등은 유형 시스템이라는 논리학의 규칙으로 정의하여 강제할 수 있다. 정적 분석의 다른 형태인 데이터 흐름 분석도 정적 의미론의 일부가 될 수 있다. 자바와 C#와 같은 프로그래밍 언어는 각각의 정적 의미론의 일부로 데이터 흐름 분석의 한 형태인 definite assignment analysis를 포함한다.

 동적 의미론 

데이터가 지정되면, 기계는 데이터에 대한 연산을 수행하도록 지시받아야 한다. 예를 들어, 의미론은 표현식이 값으로 평가되는 전략이나 제어 흐름 구조가 문을 조건부로 실행하는 방식을 정의할 수 있다. 언어의 동적 의미론(실행 의미론이라고도 함)은 언어의 다양한 구성 요소가 프로그램 동작을 어떻게 그리고 언제 생성해야 하는지를 정의한다. 실행 의미론을 정의하는 많은 방법이 있다. 자연어는 실제로 일반적으로 사용되는 언어의 실행 의미론을 지정하는 데 자주 사용된다. 프로그래밍 언어의 형식 의미론에 대한 상당한 학술 연구가 진행되고 있으며, 이는 실행 의미론을 형식적인 방식으로 지정할 수 있도록 한다. 이 연구 분야의 결과는 학계를 제외한 프로그래밍 언어 설계 및 구현에 제한적으로 적용되었다.

 특징 
언어는 프로그래머가 소프트웨어를 개발할 수 있도록 기능을 제공한다. 몇 가지 주목할 만한 기능은 아래에 설명되어 있다.

 자료형 체계 

자료형은 허용되는 값 집합과 이 값에 대해 수행할 수 있는 연산이다. 각 프로그래밍 언어의 자료형 체계는 어떤 자료형이 존재하는지, 수식의 자료형, 그리고 언어에서 자료형 등가성과 자료형 호환성이 어떻게 작동하는지를 정의한다.

유형 이론에 따르면, 언어는 모든 연산의 명세가 연산이 적용 가능한 데이터 유형을 정의하는 경우 완전히 자료형이 지정된 것이다. 이와 대조적으로, 대부분의 어셈블리어와 같은 유형 없는 언어는 어떤 데이터에 대해서도 어떤 연산이든 허용하며, 일반적으로 다양한 길이의 비트 시퀀스를 사용한다. 실제로, 완전히 자료형이 지정된 언어는 거의 없지만, 대부분은 어느 정도의 자료형을 제공한다.

다른 유형(예: 정수와 부동소수점)은 값을 다르게 표현하기 때문에, 다른 유형이 예상될 때 한 유형이 사용되면 예기치 않은 결과가 발생한다. 형 검사는 일반적으로 컴파일 타임(런타임 형 검사는 더 비용이 많이 든다)에 이 오류를 표시한다. 강형을 사용하면, 변수가 명시적으로 다른 유형으로 캐스팅되지 않는 한 형 오류는 항상 감지될 수 있다. 약형은 언어가 암시적 캐스팅을 허용할 때 발생한다. 예를 들어, 프로그래머가 명시적인 유형 변환을 하지 않고도 다른 유형의 변수 간에 연산을 가능하게 하기 위함이다. 이러한 형 강제 변환이 허용되는 경우가 많을수록 감지할 수 있는 유형 오류는 줄어든다.
 일반적으로 지원되는 자료형 

초기 프로그래밍 언어는 종종 정수(부호 있는 정수 및 부호 없는 정수) 및 부동소수점(정수가 아닌 실수에 대한 연산을 지원하기 위해)과 같은 내장된 숫자 유형만 지원했다. 대부분의 프로그래밍 언어는 프로그래머가 요구하는 크기와 정밀도에 따라 여러 크기의 부동소수점(종종 float 및 double이라고 불림)과 정수를 지원한다. 정수를 표현하기에 너무 작은 유형에 저장하면 정수 오버플로가 발생한다. 부호 있는 유형으로 음수를 표현하는 가장 일반적인 방법은 2의 보수이지만, 1의 보수도 사용된다. 다른 일반적인 유형으로는 참 또는 거짓인 불리언 자료형과 전통적으로 하나의 바이트인 문자(모든 ASCII 문자를 표현하기에 충분함)가 있다.

배열은 많은 언어에서 단일 유형의 고정 길이를 가져야 하는 요소를 가진 자료형이다. 다른 언어에서는 배열을 다른 곳에 저장된 데이터에 대한 참조로 정의하고 다양한 유형의 요소를 지원한다. 프로그래밍 언어에 따라 여러 문자의 시퀀스인 문자열은 문자 배열 또는 자체 원시 자료형으로 지원될 수 있다. 문자열은 고정 길이 또는 가변 길이일 수 있으며, 이는 저장 공간 증가와 복잡성 증가의 대가로 더 큰 유연성을 가능하게 한다. 지원될 수 있는 다른 자료형으로는 리스트, 키를 통해 접근되는 연관 (비순서) 배열, 데이터가 순서 있는 구조에서 이름에 매핑되는 레코드, 그리고 레코드와 유사하지만 데이터 필드에 이름이 없는 튜플이 포함된다. 포인터는 메모리 주소를 저장하며, 일반적으로 다른 데이터가 저장되는 힙의 위치를 참조한다.

가장 간단한 사용자 정의 자료형은 서수 자료형이며, 종종 열거라고 불리며 그 값은 양의 정수 집합에 매핑될 수 있다. 1980년대 중반 이후, 대부분의 프로그래밍 언어는 추상 자료형도 지원하는데, 여기서 데이터의 표현과 연산은 사용자로부터 숨겨져 있으며, 사용자는 인터페이스에만 접근할 수 있다. 데이터 추상화의 이점에는 신뢰성 증가, 복잡성 감소, 이름 충돌 가능성 감소, 그리고 클라이언트가 코드를 변경할 필요 없이 기본 자료 구조를 변경할 수 있다는 점 등이 있다.

 정적 및 동적 자료형 
정적 타입에서는 프로그램이 실행되기 전에, 일반적으로 컴파일 시점에 모든 표현식의 자료형이 결정된다. 가장 널리 사용되는 정적 타입 프로그래밍 언어는 변수의 자료형을 명시적으로 지정하도록 요구한다. 일부 언어에서는 자료형이 암시적이며, 컴파일러가 문맥을 기반으로 자료형을 추론할 수 있는 형태도 있다. 암시적 타입의 단점은 오류가 감지되지 않고 넘어갈 가능성이다. 완전한 자료형 추론은 전통적으로 하스켈 및 ML과 같은 함수형 언어와 관련되어 있었다.

동적 타입에서는 자료형이 변수에 연결되는 것이 아니라 그 안에 인코딩된 값에만 연결된다. 단일 변수는 다른 유형의 값에 대해 재사용될 수 있다. 이것은 프로그래머에게 더 많은 유연성을 제공하지만, 신뢰성이 낮아지고 프로그래밍 언어가 오류를 확인할 수 있는 능력이 줄어드는 대가를 치른다. 일부 언어는 일반적인 정적 타입 규칙의 예외로, 모든 유형의 값을 할당할 수 있는 공용체 유형 변수를 허용한다.

 병행성 

컴퓨팅에서 여러 명령을 동시에 실행할 수 있다. 많은 프로그래밍 언어는 명령 수준 및 서브프로그램 수준의 병행성을 지원한다. 21세기에는 컴퓨터의 추가 처리 능력이 점점 더 많은 프로세서를 사용하는 데서 비롯되었으며, 이는 프로그래머가 향상된 성능을 달성하기 위해 여러 프로세서를 동시에 활용하는 소프트웨어를 설계해야 한다. 인터프리트 언어인 파이썬과 루비는 여러 프로세서의 동시 사용을 지원하지 않는다. 다른 프로그래밍 언어는 세마포어를 사용하여 주요 명령어의 실행 순서를 제어하거나, 모니터를 통해 공유 데이터에 대한 접근을 제어하거나, 스레드 간의 메시지 전달을 활성화하여 다른 스레드 간에 공유되는 데이터를 관리하는 것을 지원한다.

 예외 처리 

많은 프로그래밍 언어는 런타임 오류에 의해 트리거되는 코드 섹션인 예외 처리기를 포함하며, 이들은 주로 두 가지 방식으로 오류를 처리할 수 있다.
 종료: 프로그램을 종료하고 운영체제에 제어를 넘긴다. 이 옵션은 가장 간단한 것으로 간주된다.
 재개: 예외가 발생한 지점 근처에서 프로그램을 재개한다. 이는 예외 처리기가 예외가 다시 발생하지 않도록 값을 수정할 수 없는 한 예외를 반복적으로 트리거할 수 있다.
일부 프로그래밍 언어는 코드에 도달하기 전에 예외가 발생하는지 여부와 관계없이 실행되는 코드 블록을 지정하는 것을 지원한다. 이를 완료(finalization)라고 한다.

예외 처리 능력을 높이는 것과 성능 저하 사이에는 절충이 있다. 예를 들어, 배열 인덱스 오류는 흔하지만 C는 성능상의 이유로 이를 확인하지 않는다. 프로그래머가 사용자 정의 예외를 포착하는 코드를 작성할 수 있지만, 이는 프로그램을 복잡하게 만들 수 있다. C와 같은 일부 언어의 표준 라이브러리는 반환 값을 사용하여 예외를 나타낸다. 일부 언어와 해당 컴파일러는 오류 처리 기능을 일시적 또는 영구적으로 켜고 끄는 옵션을 제공한다.

 설계 및 구현 

프로그래밍 언어 설계에 가장 중요한 영향 중 하나는 컴퓨터 구조였다. 가장 일반적으로 사용되는 유형인 명령형 언어는 가장 일반적인 컴퓨터 아키텍처인 폰 노이만 구조에서 잘 작동하도록 설계되었다. 폰 노이만 구조에서 주기억장치는 데이터와 명령어를 모두 저장하는 반면, 데이터에 대한 명령어를 수행하는 CPU는 분리되어 있어 데이터가 CPU로 양방향으로 파이프되어야 한다. 이 언어의 핵심 요소는 변수, 대입 및 반복문이며, 이는 이러한 머신에서 재귀보다 효율적이다.

많은 프로그래밍 언어는 처음부터 설계되거나, 새로운 요구 사항을 충족하도록 변경되거나, 다른 언어와 결합되었다. 많은 언어는 결국 사용되지 않게 되었다. 1950년대 프로그래밍 언어의 탄생은 모든 기계와 용도에 적합한 보편적인 프로그래밍 언어를 만들고자 하는 욕구에 의해 촉진되었으며, 다른 컴퓨터용 코드를 작성할 필요가 없도록 했다. 1960년대 초까지 보편적인 언어라는 아이디어는 코드가 작성되는 다양한 목적의 상이한 요구 사항으로 인해 거부되었다.

 절충 
프로그래밍 언어의 바람직한 특성에는 가독성, 작성 가능성 및 신뢰성이 포함된다. 이러한 기능은 언어에서 프로그래머를 교육하는 비용, 언어로 프로그램을 작성하고 유지 관리하는 데 필요한 시간, 코드를 컴파일하는 비용을 줄이고 런타임 성능을 향상시킬 수 있다.
 초기 프로그래밍 언어는 종종 가독성보다 효율성을 우선시했지만, 1970년대 이후 가독성의 중요성이 커졌다. 동일한 결과를 달성하기 위한 여러 연산이 있는 것은 가독성에 해로울 수 있으며, 마찬가지로 동일한 연산자가 여러 의미를 가질 수 있도록 하는 연산자 오버로드도 마찬가지이다. 가독성에 중요한 또 다른 기능은 직교성으로, 프로그래머가 배워야 하는 구성 요소의 수를 제한한다. 쉽게 이해되는 구문 구조와 즉시 명확한 예약어도 가독성을 지원한다.
 작성 가능성은 원하는 문제를 해결하기 위해 코드를 작성하는 사용 편의성이다. 가독성에 필수적인 동일한 기능과 함께, 추상화(클라이언트로부터 세부 사항을 숨길 수 있는 인터페이스) 및 표현성(더 간결한 프로그램을 가능하게 함)은 프로그래머가 코드를 작성하는 데 추가로 도움이 된다. 초기 프로그래밍 언어는 컴퓨터의 기본 하드웨어와 매우 밀접하게 연결되어 있었지만, 시간이 지남에 따라 추상화에 대한 지원이 증가하여 프로그래머가 기본 하드웨어 명령으로의 단순한 번역에서 더 멀리 떨어진 아이디어를 표현할 수 있게 되었다. 프로그래머는 컴퓨터의 복잡성에 덜 얽매이므로 프로그램은 프로그래머의 노력을 덜 들이고 더 많은 계산을 수행할 수 있다.Frederick P. Brooks, Jr.: The Mythical Man-Month, Addison-Wesley, 1982, pp. 93–94 대부분의 프로그래밍 언어는 일반적으로 사용되는 함수의 표준 라이브러리를 제공한다.
 신뢰성은 프로그램이 다양한 상황에서 지정된 대로 작동한다는 것을 의미한다. 형 검사, 예외 처리, 그리고 제한된 별칭(동일한 메모리 영역에 접근하는 여러 변수 이름)은 모두 프로그램의 신뢰성을 향상시킬 수 있다.
프로그래밍 언어 설계는 종종 절충을 수반한다. 예를 들어, 신뢰성을 향상시키는 기능은 일반적으로 성능 저하를 수반한다. 많은 연산자로 인한 표현성 증가는 코드 작성을 더 쉽게 만들지만 가독성을 희생시킨다.

자연어 프로그래밍은 프로그래밍을 위한 특수 언어의 필요성을 없애는 방법으로 제안되었다. 그러나 이 목표는 아직 멀고 그 이점은 논쟁의 여지가 있다. 에츠허르 데이크스트라는 무의미한 구성 요소를 도입하는 것을 방지하기 위해 형식 언어를 사용하는 것이 필수적이라고 주장했다.Dijkstra, Edsger W. On the foolishness of "natural language programming."  EWD667. 앨런 퍼리스도 비슷한 태도로 이 아이디어를 일축했다.

 명세 

프로그래밍 언어의 명세는 언어 사용자와 구현자가 특정 소스 코드가 해당 언어의 유효한 컴퓨터 프로그램인지 여부와, 그렇다면 그 동작이 무엇이 될 것인지에 대해 동의하는 데 사용할 수 있는 인공물이다.

프로그래밍 언어 명세는 다음과 같은 여러 형태를 취할 수 있다.
 언어의 구문, 정적 의미론 및 실행 의미론에 대한 명시적 정의. 구문은 일반적으로 형식 문법을 사용하여 지정되지만, 의미 정의는 자연어(예: C 언어의 경우) 또는 형식 의미론(예: 표준 ML 및 스킴 명세)로 작성될 수 있다.
 언어용 번역기의 동작 설명(예: C++ 및 포트란 명세). 언어의 구문 및 의미론은 이 설명에서 추론되어야 하며, 이는 자연어 또는 형식 언어로 작성될 수 있다.
 참조 구현 또는 모델 구현, 때로는 지정되는 언어로 작성된 (예: 프롤로그 또는 ANSI REXXANSI – Programming Language Rexx, X3-274.1996). 언어의 구문 및 의미론은 참조 구현의 동작에 명시되어 있다.

 구현 

프로그래밍 언어의 구현은 프로그램을 하드웨어에 의해 실행될 수 있는 기계어로 변환하는 것이다. 기계어는 운영체제의 도움으로 실행될 수 있다. 실제 코드에서 가장 일반적인 형태의 인터프리팅은 컴파일러에 의한 것으로, 컴파일러는 소스 코드를 중간 수준 언어를 통해 기계어로 번역하여 실행 파일을 생성한다. 프로그램이 컴파일되면 다른 구현 방법보다 빠르게 실행된다. 일부 컴파일러는 실행 파일이 실행될 때 메모리 또는 계산 사용량을 줄이기 위한 추가적인 최적화를 제공할 수 있지만, 컴파일 시간은 증가한다.

또 다른 구현 방법은 인터프리터를 사용하여 프로그램을 실행하는 것이다. 인터프리터는 각 소프트웨어 라인을 실행 직전에 기계어로 번역한다. 디버깅을 더 쉽게 만들 수 있지만, 인터프리팅의 단점은 컴파일된 실행 파일보다 10배에서 100배 느리게 실행된다는 것이다. 하이브리드 인터프리팅 방법은 부분 컴파일을 통해 컴파일의 이점과 인터프리팅의 이점을 일부 제공한다. 한 가지 형태는 JIT 컴파일로, 소프트웨어가 미리 중간 언어로 컴파일된 다음 실행 직전에 기계어로 컴파일된다.

 독점 언어 
가장 일반적으로 사용되는 프로그래밍 언어의 대부분은 완전히 공개된 명세와 구현을 가지고 있지만, 많은 프로그래밍 언어는 단일 공급업체에서만 구현을 사용할 수 있는 독점 프로그래밍 언어로만 존재하며, 이러한 독점 언어가 자신들의 지적 재산이라고 주장할 수 있다. 독점 프로그래밍 언어는 일반적으로 단일 제품을 위한 도메인 특화 언어 또는 내부 스크립트 언어이다. 일부 독점 언어는 공급업체 내부에서만 사용되지만, 다른 언어는 외부 사용자에게도 제공된다.

일부 프로그래밍 언어는 독점과 공개의 경계에 존재한다. 예를 들어, 오라클은 자바 프로그래밍 언어의 일부 측면에 대해 독점권을 주장하며,See: Oracle America, Inc. v. Google, Inc. 마이크로소프트의 C# 프로그래밍 언어는 시스템 대부분의 부분에 대한 공개 구현을 가지고 있지만, 공통 언어 런타임(CLR)은 폐쇄된 환경이다.

많은 독점 언어는 독점적인 특성에도 불구하고 널리 사용된다. 예를 들어 매트랩, VB스크립트, 울프럼 언어 등이 있다. 일부 언어는 폐쇄형에서 공개형으로 전환할 수 있다. 예를 들어, 얼랭은 원래 에릭슨의 내부 프로그래밍 언어였다.

오픈 소스 프로그래밍 언어는 오픈 사이언스 응용 분야에 특히 유용하며, 재현성 및 코드 공유 역량을 향상시킨다.

 사용 
주로 컴퓨팅 분야에서 수천 가지의 다양한 프로그래밍 언어가 만들어졌다.
개별 소프트웨어 프로젝트는 일반적으로 5개 이상의 프로그래밍 언어를 사용한다.

프로그래밍 언어는 다른 대부분의 인간 표현 방식과 달리 더 높은 수준의 정밀성과 완전성을 요구한다. 자연어를 사용하여 다른 사람들과 소통할 때, 인간의 저자와 화자는 모호하고 작은 실수를 저지를 수 있지만, 의도는 이해될 것으로 기대한다. 그러나 비유적으로 말하면 컴퓨터는 "정확히 지시받은 대로" 작동하며, 프로그래머가 작성하려고 했던 코드를 "이해"할 수 없다. 언어 정의, 프로그램 및 프로그램 입력의 조합은 프로그램이 실행될 때 발생하는 외부 동작을 프로그램 제어 영역 내에서 완전히 지정해야 한다. 반면에 알고리즘에 대한 아이디어는 자연어와 프로그래밍 언어로 작성된 코드를 혼합하는 의사코드를 사용하여 실행에 필요한 정밀성 없이도 인간에게 전달할 수 있다.

프로그래밍 언어는 데이터 조각과 해당 데이터에 대해 자동으로 수행될 수 있는 연산 또는 변환을 정의하기 위한 구조화된 메커니즘을 제공한다. 프로그래머는 언어에 있는 추상화를 사용하여 계산과 관련된 개념을 표현한다. 이러한 개념은 사용 가능한 가장 간단한 요소(프리미티브라고 함)의 집합으로 표현된다. 컴퓨터 프로그래밍은 프로그래머가 이러한 프리미티브를 결합하여 새 프로그램을 작성하거나 기존 프로그램을 새 용도나 변화하는 환경에 맞게 조정하는 프로세스이다.

컴퓨터용 프로그램은 인간의 상호 작용 없이 일괄 처리로 실행되거나, 사용자가 인터프리터의 대화형 세션에서 명령어를 입력할 수도 있다. 이 경우 "명령어"는 단순히 실행이 연결된 프로그램이다. 언어가 컴파일 없이 인터프리터(예: 유닉스 셸 또는 다른 명령줄 인터페이스)를 통해 명령어를 실행할 수 있을 때, 이를 스크립트 언어라고 한다.

 언어 사용 측정 
가장 널리 사용되는 프로그래밍 언어를 결정하는 것은 사용의 정의가 상황에 따라 다르기 때문에 어렵다. 한 언어는 더 많은 프로그래머 시간을 차지할 수 있고, 다른 언어는 더 많은 코드 라인을 가질 수 있으며, 세 번째 언어는 가장 많은 CPU 시간을 소비할 수 있다. 일부 언어는 특정 종류의 응용 프로그램에 매우 인기가 있다. 예를 들어, 코볼은 여전히 기업 데이터 센터, 종종 대형 메인프레임에서 강력하다. 포트란은 과학 및 공학 응용 프로그램에서, 에이다는 항공우주, 운송, 군사, 실시간 및 임베디드 응용 프로그램에서, C는 임베디드 응용 프로그램 및 운영 체제에서 사용된다. 다른 언어는 다양한 종류의 응용 프로그램을 작성하는 데 정기적으로 사용된다.

측정되는 내용에 따라 다른 편향을 갖는 다양한 언어 인기도 측정 방법이 제안되었다.
 해당 언어를 언급하는 채용 공고 수 계산
 해당 언어를 가르치거나 설명하는 책 판매량
 해당 언어로 작성된 기존 코드 라인 수 추정 이는 공개 검색에서 자주 발견되지 않는 언어를 과소평가할 수 있다.Bieman, J.M.; Murdock, V., Finding code on the World Wide Web: a preliminary investigation, Proceedings First IEEE International Workshop on Source Code Analysis and Manipulation, 2001
 웹 검색 엔진을 사용하여 발견된 언어 참조(즉, 언어 이름에 대한 참조) 수.

다양한 인터넷 사이트의 정보를 결합하고 평균을 낸 결과, stackify.com은 가장 인기 있는 프로그래밍 언어 10가지(전체 인기도 순으로 내림차순): 자바, C, C++, 파이썬, C#, 자바스크립트, VB .NET, R, PHP, 매트랩을 보고했다.

2024년 6월 현재, TIOBE 지수에 따르면 가장 인기 있는 프로그래밍 언어 상위 5개는 파이썬, C++, C, 자바, C#이다. TIOBE는 매월 인기도에 따라 상위 100개 프로그래밍 언어 목록을 제공한다.

IEEE 스펙트럼 직원들에 따르면, 오늘날 가장 인기 있는 프로그래밍 언어는 AI 작동 방식 때문에 계속해서 지배력을 유지할 수 있다. 그 결과, 새로운 언어는 코더들이 그 언어로 많은 프로그램을 작성하지 않을 것이기 때문에 인기를 얻기가 더 어려울 것이다.

 방언, 변형 및 구현 
프로그래밍 언어 또는 데이터 교환 언어의 방언은 본질적인 성격을 변경하지 않는 (상대적으로 작은) 변형 또는 확장이다. 스킴 및 포스와 같은 언어의 경우, 표준이 구현자에 의해 불충분하거나 부적절하거나 불법적이라고 간주될 수 있으므로 종종 표준에서 벗어나 새로운 방언을 만든다. 다른 경우에는 도메인 특화 언어용으로, 종종 하위 집합인 방언이 생성된다. 리스프 세계에서는 기본적인 S-표현식 구문과 리스프와 유사한 의미론을 사용하는 대부분의 언어가 리스프 방언으로 간주되지만, 래킷과 클로저처럼 크게 다르다. 하나의 언어에 여러 방언이 있는 것이 일반적이므로, 경험이 없는 프로그래머가 올바른 문서를 찾는 것이 매우 어려울 수 있다. 베이직 언어는 많은 방언을 가지고 있다.

 분류 

프로그래밍 언어는 다음의 높은 수준의, 그러나 때로는 중복되는 분류에 따라 설명될 수 있다.
 명령형
명령형 프로그래밍 언어는 순서 있는 연산의 시퀀스로 인코딩된 논리를 구현하는 것을 지원한다. 가장 일반적으로 사용되는 언어는 명령형으로 분류된다.
 함수형
함수형 프로그래밍 언어는 주어진 매개변수에 함수를 연속적으로 적용하는 것을 지원한다. 많은 연구자들이 그 단순성과 우아함으로 인해 높이 평가하지만, 효율성 문제로 인해 널리 채택되지는 못했다.
 논리형
논리형 프로그래밍 언어는 프로그래머가 아닌 소프트웨어가 명령이 실행되는 순서를 결정하도록 설계되었다.
 객체 지향
객체 지향 프로그래밍(OOP)은 데이터 추상화, 상속, 동적 디스패치와 같은 특징으로 특징지어진다. OOP는 대부분의 인기 있는 명령형 언어와 일부 함수형 언어에서 지원된다.
 마크업
마크업 언어는 그 자체로 프로그래밍 언어는 아니지만, 프로그래밍 언어와의 통합을 지원할 수 있다.
 특수
다른 프로그래밍 언어와 쉽게 비교할 수 없는 특수 목적 언어도 있다.

 같이 보기 
 난해한 프로그래밍 언어

 각주 

 외부 링크 



분류:프로그래밍 언어 분류