고급 프로그래밍 언어(High Level Programming Language)
컴퓨터 과학에서 high-level programming language는 컴퓨터의 세부 사항으로부터 강한 추상화를 가진 프로그래밍 언어입니다. low-level programming language와 대조적으로, 이는 자연 언어 요소를 사용할 수 있고, 사용하기 더 쉬울 수 있으며, 메모리 관리와 같은 컴퓨팅 시스템의 중요한 영역을 자동화하거나 (심지어 완전히 숨기기도 하여) 프로그램 개발 과정을 더 단순하고 이해하기 쉽게 만듭니다. 제공되는 추상화의 양이 프로그래밍 언어의 "high-level" 정도를 정의합니다.
1960년대에는, 컴파일러를 사용하는 high-level programming language를 일반적으로 autocode라고 불렀습니다. Autocode의 예로는 COBOL과 Fortran이 있습니다.
컴퓨터용으로 설계된 최초의 high-level programming language는 Konrad Zuse가 만든 Plankalkül이었습니다. 하지만 이 언어는 그의 시대에는 실제로 구현되지 않았습니다. 제2차 세계대전으로 인해 Zuse의 업적은 다른 개발자들과 공유되지 못했고, 그의 Plankalkül은 그 당시에는 크게 알려지지 않았습니다. 그럼에도 불구하고, Plankalkül은 나중에 Heinz Rutishauser의 "Superplan" 언어와 ALGOL에 어느 정도 영향을 주었습니다.
최초로 크게 보급된 high-level language는 IBM의 초기 Autocode 시스템의 기계 독립적 발전인 Fortran이었습니다. ALGOL은 1958년에 정의된 ALGOL 58과 1960년에 유럽 및 미국의 컴퓨터 과학자들로 구성된 위원회에 의해 정의된 ALGOL 60이 있으며, 이는 재귀와 lexical scope 하의 중첩된 함수들을 도입했습니다. ALGOL 60은 또한 값과 이름-파라미터 및 해당 의미론 간의 명확한 구분을 가진 최초의 언어였습니다. ALGOL은 또한 while-do 및 if-then-else 구조와 같은 여러 structured programming 개념을 도입했으며, 그 문법은 Backus–Naur form (BNF)으로 최초로 기술되었습니다. 대략 같은 시기에 COBOL은 records (structs라고도 불림)을 도입했으며, Lisp는 프로그래밍 언어에서 최초로 완전한 일반적인 lambda abstraction을 도입했습니다.
Features
"High-level language"는 기계어로부터 더 높은 수준의 추상화를 의미합니다. 레지스터, 메모리 주소, 호출 스택을 다루는 대신, high-level 언어는 변수, 배열, 객체, 복잡한 산술 또는 불리언 표현, 서브루틴 및 함수, 루프, 스레드, 락 및 기타 추상적인 컴퓨터 과학 개념을 다루며, 최적의 프로그램 효율성보다는 사용성에 중점을 둡니다. 저수준 어셈블리 언어와 달리, high-level 언어는 기계의 네이티브 코드로 직접 변환되는 언어 요소가 거의 없거나 전혀 없습니다. 문자열 처리 루틴, 객체 지향 언어 기능, 파일 입출력과 같은 다른 기능들도 있을 수 있습니다. High-level 프로그래밍 언어에 대해 주목할 점은 이러한 언어들이 프로그래머를 기계로부터 분리하고 분리되도록 허용한다는 것입니다. 즉, 어셈블리나 기계어와 같은 저수준 언어와 달리, high-level 프로그래밍은 프로그래머의 지시를 확대하고, 프로그래머가 알지 못한 채 많은 데이터 이동을 트리거할 수 있습니다. 명령을 실행하는 책임과 권한이 프로그래머에서 기계로 넘어간 것입니다.
Abstraction penalty
High-level 언어는 일반적인 작업을 표준화하고, 풍부한 디버깅을 허용하며, 아키텍처 독립성을 유지하는 기능을 제공하려 합니다. 반면, low-level 언어는 특정 시스템 아키텍처에 맞게 최적화되어 더 효율적인 코드를 생성하는 경우가 많습니다. 추상화 페널티는 고급 프로그래밍 기술이 성능 최적화나 특정 하드웨어 사용을 하지 못해 발생하는 비용입니다. 이는 특정 저수준 아키텍처 자원을 활용하지 못하기 때문입니다. High-level 프로그래밍은 더 일반적인 데이터 구조와 연산, 런타임 해석, 중간 코드 파일 등의 기능을 가지고 있으며, 이는 종종 필요 이상의 많은 연산을 실행하고, 더 높은 메모리 소비와 더 큰 바이너리 프로그램 크기를 초래합니다. 이러한 이유로, 특히 빠르고 효율적으로 실행되어야 하는 코드는 high-level 언어가 코딩을 더 쉽게 만들어도 low-level 언어를 사용해야 할 수도 있습니다. 많은 경우, high-level 언어로 작성된 프로그램의 중요한 부분을 어셈블리 언어로 직접 코딩하여 훨씬 빠르고 효율적이며 신뢰성 있는 최적화 프로그램을 만들 수 있습니다.
그러나 현대 마이크로프로세서 아키텍처의 복잡성이 증가함에 따라, 고급 언어용 잘 설계된 컴파일러는 대부분의 low-level 프로그래머가 수작업으로 생성할 수 있는 코드와 비교할 만한 효율성을 가진 코드를 자주 생성합니다. 또한, 높은 추상화는 특정 환경에서 low-level 언어보다 더 나은 전체적인 결과를 제공할 수 있는 강력한 기술을 사용할 수 있게 합니다. High-level 언어는 특정 컴퓨팅 시스템 아키텍처에 독립적으로 설계되었습니다. 이는 그러한 언어로 작성된 프로그램이 Interpreted 또는 JIT 프로그램을 위한 호환 가능한 지원이 있는 모든 컴퓨팅 시스템에서 실행될 수 있도록 합니다. High-level 언어는 설계자가 개선을 개발함에 따라 향상될 수 있습니다. 다른 경우에는 새로운 high-level 언어가 기존의 인기 있는 구성 요소를 새로운 또는 향상된 기능과 결합하려는 목표로 하나 이상의 언어에서 발전합니다. 예로 Scala는 Java와의 하위 호환성을 유지하며, 이는 프로그래밍 팀이 Scala로 전환하더라도 Java로 작성된 프로그램과 라이브러리를 계속 사용할 수 있음을 의미합니다. 이는 전환을 더 쉽게 만들고 이러한 high-level 코딩의 수명을 무기한으로 만듭니다. 반면, low-level 프로그램은 작성된 시스템 아키텍처를 벗어나기 위해 대규모 수정 없이 잘 살아남지 못합니다. 이것이 '추상화 페널티'의 엔지니어링 '트레이드오프'입니다.
Relative meaning
오늘날 활발히 사용되고 있는 고급 프로그래밍 언어의 예로는 Python, JavaScript, Visual Basic, Delphi, Perl, PHP, ECMAScript, Ruby, C#, Java 등이 있습니다.
고급 언어와 저급 언어라는 용어는 본질적으로 상대적입니다. 몇십 년 전만 해도 C 언어와 유사한 언어들은 표현식 평가, 파라미터가 있는 재귀 함수, 데이터 타입과 구조체 등의 개념을 지원하였기 때문에 "고급"으로 간주되었습니다. 반면, 어셈블리 언어는 "저급"으로 여겨졌습니다. 오늘날 많은 프로그래머는 C 언어를 저급으로 언급할 수도 있는데, 이는 C가 사이즈가 큰 런타임 시스템(예: 가비지 컬렉션 등)이 없고, 기본적으로 스칼라 연산만 지원하며, 직접 메모리 주소 지정이 가능하기 때문입니다. 따라서 C 언어는 어셈블리 언어와 CPU 및 마이크로컨트롤러의 기계 수준과 잘 어우러집니다. 또한, Brian Kernighan과 Dennis Ritchie가 저술한 "The C Programming Language" (두 번째 판)의 서문에서 C 언어는 "매우 고급은 아닌" 언어로 설명됩니다.
어셈블리 언어 자체도 상수, (제한된) 표현식, 때로는 변수, 절차, 데이터 구조와 같은 개념을 지원하기 때문에 기계 코드의 고급 표현으로 간주될 수 있습니다. 기계 코드는 많은 프로세서 내부에서 사용되는 마이크로코드 또는 마이크로 연산보다 본질적으로 약간 높은 수준에 있습니다.
Execution modes
현대 고급 언어의 실행 모드는 일반적으로 세 가지가 있습니다:
인터프리트 방식
프로그래밍 언어로 작성된 코드가 인터프리트될 때, 그 문법은 컴파일 단계 없이 직접 읽고 실행됩니다. 인터프리터라는 프로그램이 각 프로그램 명령문을 읽고, 프로그램 흐름을 따라가면서 무엇을 할지 결정하고, 그 일을 수행합니다. 인터프리터와 컴파일러의 하이브리드는 명령문을 기계어로 컴파일하여 실행한 다음, 기계어를 버리고 명령문이 다시 실행될 때 새로 해석합니다. 인터프리터는 여기 나열된 다른 두 가지 변형과 비교할 때 언어의 동작을 구현하는 가장 단순한 방법입니다.
컴파일 방식
프로그래밍 언어로 작성된 코드가 컴파일될 때, 그 문법은 실행 전에 실행 가능한 형태로 변환됩니다. 컴파일에는 두 가지 유형이 있습니다:
- 기계어 생성
일부 컴파일러는 소스 코드를 직접 기계어로 컴파일합니다. 이것이 원래의 컴파일 방식이며, 이 방법으로 직접 완전히 변환되는 언어는 진정한 컴파일 언어라고 할 수 있습니다. 어셈블리 언어를 참조하십시오. - 중간 표현
언어로 작성된 코드가 중간 표현으로 컴파일될 때, 그 표현은 최적화되거나 소스 파일을 다시 읽지 않고 나중에 실행하기 위해 저장될 수 있습니다. 중간 표현이 저장될 때, 바이트코드와 같은 형태일 수 있습니다. 그런 다음 중간 표현은 실행되기 위해 해석되거나 추가로 컴파일되어야 합니다. 바이트코드를 직접 실행하거나 추가로 기계어로 변환하는 가상 머신은 중간 표현과 진정한 컴파일 언어 사이의 명확한 구분을 흐리게 했습니다.
소스-투-소스 번역 또는 트랜스컴파일
언어로 작성된 코드는 네이티브 코드 컴파일러가 이미 흔한 저수준 언어의 용어로 번역될 수 있습니다. JavaScript와 C 언어는 이러한 번역기의 일반적인 대상입니다. CoffeeScript, Chicken Scheme, Eiffel 등의 예를 참조하십시오. 특히, 생성된 C 및 C++ 코드는 EiffelStudio IDE를 사용할 때 Eiffel 언어에서 생성된 경우, 모든 컴파일된 Eiffel 프로젝트의 EIFGENs 디렉터리에서 볼 수 있습니다. Eiffel에서 번역 과정은 트랜스컴파일 또는 트랜스컴파일된 것으로 언급되며, Eiffel 컴파일러는 트랜스컴파일러 또는 소스-투-소스 컴파일러로 언급됩니다.
언어는 엄격하게 인터프리트 언어나 컴파일 언어가 아닙니다. 오히려 언어 동작의 구현이 인터프리팅 또는 컴파일링을 사용합니다. 예를 들어, ALGOL 60과 Fortran은 모두 인터프리트된 적이 있지만 (더 일반적으로 컴파일되었지만) 이러한 레이블을 언어가 아닌 구현에 적용하려는 어려움을 보여줍니다. Java도 마찬가지로 이러한 레이블을 언어에 적용하려는 어려움을 보여줍니다. Java는 바이트코드로 컴파일되며, 이는 인터프리팅 (Java 가상 머신(JVM)에서) 또는 컴파일링 (보통 HotSpot과 같은 즉시 컴파일러를 사용하여 JVM에서)로 실행됩니다. 또한, 컴파일링, 트랜스컴파일링, 인터프리팅은 컴파일러 산출물(바이너리 실행 파일 또는 IL 어셈블리)의 설명에만 제한되지 않습니다.
언어는 엄격하게 인터프리트 언어나 컴파일 언어로 나뉘지 않는다는 점을 유의해야 합니다. 오히려 언어 동작의 구현이 인터프리팅 또는 컴파일링을 사용합니다. 예를 들어, ALGOL 60과 Fortran은 둘 다 인터프리트된 적이 있지만 (더 일반적으로는 컴파일되었지만) 이러한 레이블을 언어에 적용하는 것이 아니라 구현에 적용하려는 어려움을 보여줍니다. Java도 마찬가지로 이러한 레이블을 언어에 적용하려는 어려움을 보여줍니다. Java는 바이트코드로 컴파일되며, 이는 인터프리팅 (Java 가상 머신(JVM)에서) 또는 컴파일링 (보통 HotSpot과 같은 즉시 컴파일러를 사용하여 JVM에서)로 실행됩니다. 또한, 컴파일링, 트랜스컴파일링, 인터프리팅은 컴파일러 산출물(바이너리 실행 파일 또는 IL 어셈블리)의 설명에만 엄격히 제한되지 않습니다.
High-level language computer architecture
대안으로, 고급 언어가 컴퓨터에 의해 직접 구현될 수도 있습니다. 즉, 컴퓨터가 고급 언어 코드를 직접 실행하는 것입니다. 이를 고급 언어 컴퓨터 아키텍처라고 합니다. 컴퓨터 아키텍처 자체가 특정 고급 언어를 대상으로 설계된 것입니다. 예를 들어, Burroughs 대형 시스템은 ALGOL 60을 목표로 한 머신이었습니다.
List of programming languages by type
고급 프로그래밍 언어(high-level programming language)를 사용하는 이유는 여러 가지가 있습니다. 아래에 그 주요 이유들을 설명하겠습니다.
1. 사용자 친화성:
• 초기 컴퓨터 프로그래밍은 기계어(0과 1로 이루어진 바이너리 코드)나 어셈블리어(기계어와 유사하지만 좀 더 인간이 이해하기 쉬운 언어)로 작성되었습니다. 이러한 저급 언어는 사람에게 매우 어려웠고 실수를 유발하기 쉬웠습니다. 고급 언어는 인간이 이해하기 쉬운 문법과 구조를 제공함으로써 프로그래밍을 훨씬 더 직관적이고 접근하기 쉽게 만들었습니다.
2. 생산성 향상:
• 고급 언어는 복잡한 작업을 더 적은 코드로 표현할 수 있게 해줍니다. 이는 프로그래머가 같은 시간 내에 더 많은 기능을 구현할 수 있도록 도와줍니다. 예를 들어, Python과 같은 언어는 복잡한 알고리즘을 몇 줄의 코드로 작성할 수 있게 해줍니다.
3. 유지보수 용이성:
• 고급 언어로 작성된 코드는 더 읽기 쉽고 이해하기 쉬워서 코드 유지보수가 용이합니다. 이는 팀 프로젝트에서 특히 중요합니다. 여러 사람이 같은 코드를 관리할 때, 이해하기 쉽고 명확한 코드는 협업을 원활하게 합니다.
4. 이식성:
• 고급 언어는 특정 하드웨어에 종속되지 않고 다양한 플랫폼에서 실행될 수 있도록 설계되었습니다. 예를 들어, Java는 "Write Once, Run Anywhere"라는 철학을 가지고 있어, 한 번 작성한 코드를 여러 운영 체제에서 실행할 수 있습니다.
5. 추상화:
• 고급 언어는 하드웨어와의 직접적인 상호작용을 추상화하여 프로그래머가 복잡한 하드웨어 세부 사항에 신경 쓰지 않고 논리와 알고리즘에 집중할 수 있도록 합니다. 이는 프로그래머가 더 창의적이고 생산적으로 작업할 수 있게 해줍니다.
6. 표준화 및 라이브러리:
• 많은 고급 언어는 광범위한 표준 라이브러리와 프레임워크를 제공합니다. 이는 프로그래머가 공통적인 작업을 더 쉽게 수행할 수 있도록 도와줍니다. 예를 들어, Python의 표준 라이브러리는 파일 입출력, 네트워킹, 데이터베이스 연결 등을 매우 간단하게 처리할 수 있게 해줍니다.
고급 프로그래밍 언어의 개발과 발전은 프로그래밍을 더 접근하기 쉽게 만들고, 생산성을 높이며, 소프트웨어 개발의 효율성을 크게 향상시켰습니다. 이러한 이유들 때문에 고급 언어는 현재 소프트웨어 개발의 주류가 되었습니다.