프로그래밍 언어이론(PLT): 1. 프로그래밍 언어의 기초와 함수형 프로그래밍

Serendipity·2024년 4월 3일

2024  LeSN

목록 보기
9/10
  • 프로그래밍 언어 이론의 중요성, 함수형 프로그래밍의 기본 원리와 장점.
  • 프로그래밍 언어의 기본 개념과 함수형 프로그래밍의 핵심적인 특징을 이해
  • 이러한 패러다임이 소프트웨어 개발에 어떤 영향을 미치는지 알 수 있음

💻 프로그래밍 언어의 기본 구성 요소

프로그래밍 언어 이론은 컴퓨터 과학에서 핵심적인 분야로, 프로그래밍 언어의 디자인, 구현, 분석 및 사용에 대한 원리를 다룹니다. 이 이론은 추상적인 개념을 실제 구현으로 연결하는 데 필요한 중요한 지식을 제공하며, 프로그래밍 언어의 구조적 및 기능적 측면을 이해하는 데 중추적인 역할을 합니다.

(프로그래밍 언어 이론 및 연구에 관심 있으신 분들께 드리는 정보)
https://sigpl.or.kr/notice/
https://sites.google.com/view/lesn-lab



TIOBE Index 24년 2월 프로그래밍 언어 순위


TIOBE Index에서는 Python, C, C++, Java, C#이 가장 인기 있는 언어 5개로 선정되었다
[티오베 인덱스, 2024년 2월 프로그래밍 언어 순위 TIOBE Index]



프로그래밍 언어의 구문(Syntax)

프로그래밍 언어의 구문은 해당 언어의 문법적인 구조를 말합니다. 이는 사람이 이해할 수 있는 코드를 컴퓨터가 처리할 수 있는 명령으로 변환하는 데 필요한 규칙을 정의합니다. 예를 들어, C++에서의 함수 선언은 다음과 같은 구문을 따릅니다:

int add(int a, int b);

여기서 int add(int a, int b);는 C++ 컴파일러가 이해할 수 있는 구문입니다. 이 구문은 add라는 이름의 함수를 선언하며, 두 개의 int 타입 매개변수를 받고 int 타입의 값을 반환한다는 것을 명시합니다. 구문은 프로그램이 어떻게 구성되어야 하는지에 대한 규칙을 제공하지만, 그 자체로는 프로그램이 실제로 무엇을 하는지에 대한 정보는 포함하고 있지 않습니다.



프로그래밍 언어의 의미론(Semantics)

의미론은 프로그래밍 언어의 구문이 실제로 컴퓨터에게 무엇을 지시하는지를 정의합니다. 의미론은 프로그램의 동작과 프로그램이 실행될 때 무슨 일이 발생하는지를 명확히 설명합니다. 위의 함수 선언에 이어서 구현 부분을 살펴보면:

int add(int a, int b) {
    return a + b;
}

이 코드는 add 함수가 정수 ab를 더해서 그 결과를 반환한다는 실제 동작을 나타냅니다. 즉, 두 매개변수의 합산 결과를 반환합니다. 여기서 의미론은 add 함수가 어떠한 상태 변화나 부작용 없이 입력받은 두 매개변수의 값을 단순히 더하는 순수한 연산을 수행함을 명확히 합니다.


프로그래밍 언어 이론에서는 이러한 구문과 의미론을 정확하게 이해하고 정의하는 것이 매우 중요합니다. 이는 프로그래밍 언어가 단순히 명령의 나열이 아니라, 컴퓨터와 프로그래머 간의 소통을 가능하게 하는 복잡한 체계라는 것을 인식하게 합니다. 또한, 이 이론은 프로그래머가 코드를 작성할 때 예상치 못한 오류를 방지하고, 효율적이고 안전한 프로그램을 구현할 수 있도록 도와줍니다.


프로그래밍 언어론 구문과 의미론 정리

출처: https://blog.naver.com/bh5kks/220508718803, https://www.slideshare.net/slideshow/pl-1/40637561




함수형 프로그래밍으로 넘어가면, 이러한 개념들은 한층 더 발전하여, 함수의 부작용을 최소화하고, 불변성을 유지하는 등의 개념으로 확장됩니다. 함수형 프로그래밍에서는 프로그램의 상태

변화를 피하고, 입력이 같으면 결과도 반드시 같아야 한다는 원칙을 중시합니다. 이를 통해 프로그램의 동작을 보다 쉽게 예측할 수 있고, 병렬 처리와 같은 복잡한 컴퓨팅 문제를 더욱 효과적으로 처리할 수 있습니다.

프로그래밍 언어 이론과 함수형 프로그래밍의 이해는 컴퓨터 과학 학생들에게 소프트웨어 개발의 근본적인 이해를 제공하며, 실제 프로그래밍 언어를 사용하는 데 있어 강력한 기초를 마련해 줍니다. 이 지식은 알고리즘 설계, 시스템 아키텍처 구축, 그리고 성능 최적화에 있어서 중요한 지침과 원칙을 제공합니다. 이는 복잡한 소프트웨어 시스템을 개발, 분석, 그리고 유지보수하는 데 있어서 핵심적인 역할을 수행합니다.



중요성

이론을 통해 프로그래머들은 프로그래밍 언어를 보다 효율적으로 사용하고, 더 견고하고 안전한 소프트웨어를 개발할 수 있습니다. 프로그래밍 언어의 구문과 의미론을 이해함으로써, 개발자들은 코드가 예상대로 동작하도록 보장하고, 오류를 줄이며, 유지보수가 용이한 소프트웨어를 구현할 수 있습니다.

함수형 프로그래밍과 같은 특정 프로그래밍 패러다임의 이해는 이 이론적 토대 위에 구축됩니다. 함수형 프로그래밍은 부작용을 피하고, 코드의 재사용성과 모듈성을 향상시키며, 병렬 처리와 같은 복잡한 문제를 보다 쉽게 해결할 수 있는 방법을 제공합니다.

프로그래밍 언어 이론은 단순히 코드를 작성하는 방법을 넘어서, 왜 그런 방식으로 코드를 작성해야 하는지에 대한 근본적인 이해를 제공합니다. 이는 컴퓨터 과학 학생들이 보다 능숙한 소프트웨어 개발자로 성장하는 데 필수적인 지식입니다.




참고: 프로그래밍 언어의 역사


프로그래밍 언어의 역사 (출처 : 알렌 터커의 ‘프로그래밍 언어’)




💻 함수형 프로그래밍

함수형 프로그래밍(Functional Programming, FP)은 프로그래밍 패러다임 중 하나로, 순수함수와 불변성을 강조합니다. 이는 강력하고 효율적인 소프트웨어를 구축하는 데 필요한 중요한 패러다임입니다.



함수형 프로그래밍의 특징

순수 함수(Pure Functions)

순수 함수는 주어진 입력에 대해 항상 동일한 결과를 반환하고, 전역 상태를 변경하지 않는 함수입니다. 예를 들어, Haskell의 순수 함수 예시는 다음과 같습니다:

-- 두 수의 합을 반환하는 순수 함수
sum :: Int -> Int -> Int
sum a b = a + b

이 함수는 어떤 상태도 변경하지 않으며, 동일한 입력 ab에 대해 항상 같은 출력 값을 반환합니다.

불변성(Immutability)

불변성은 데이터가 생성된 후에 변경될 수 없다는 원칙입니다. 이는 함수형 프로그래밍에서 중요한 역할을 합니다. 예를 들어, 한 번 생성된 리스트는 변경되지 않습니다. 새 요소를 추가하고 싶다면, 기존의 리스트를 변경하는 대신 새로운 리스트를 생성합니다.

고차 함수(Higher-order Functions)

함수를 일급 시민으로 취급함으로써, 함수를 다른 함수의 인자로 전달하거나, 함수에서 다른 함수를 반환할 수 있습니다.




🧠 왜 함수형 프로그래밍을 배워야 하나?


"일반적인 프로그래밍은 그냥 생각하면 되는 것이고, 함수형 프로그래밍은 기존과 다르게 생각하는 방법을 알려줄 것이다. 그러므로 당신은 아마도 예전 방식으로 절대 돌아가지 않을 것이다."

  1. 부작용 최소화: 함수형 프로그래밍은 부작용(side effects)을 최소화합니다. 부작용은 프로그램의 상태를 변경하거나, 예측하지 못한 방식으로 프로그램 외부와 상호작용하는 것을 의미합니다. 부작용을 피함으로써, 프로그램의 동작을 더 쉽게 이해하고 예측할 수 있습니다.
  2. 코드의 재사용성과 모듈성: FP에서 함수는 '일급 객체' 로 취급되므로, 다른 함수에 인자로 전달되거나, 함수에서 반환될 수 있습니다. 이는 고차 함수를 가능하게 하고, 코드의 재사용성과 모듈성을 크게 향상시킵니다.
  3. 병렬 처리와 동시성: 순수 함수는 독립적인 단위로서, 다른 순수 함수와의 상호작용 없이 실행될 수 있습니다. 이는 병렬 처리와 동시성을 구현하는 데 있어 매우 중요한 특성입니다.

함수형 프로그래밍의 활용

함수형 프로그래밍이 제공하는 추상화의 수준은 개발자들이 더 높은 수준에서 문제를 해결할 수 있게 만들며, 이는 특히 다음과 같은 분야에서 그 가치가 드러납니다:

  • 데이터 과학과 머신 러닝: 대량의 데이터를 처리하고, 변환하는 데 있어서 함수형 프로그래밍의 접근 방식은 코드의 간결성과 효율성을 크게 향상시킵니다. 함수의 조합과 불변성은 복잡한 데이터 파이프라인을 명확하고 이해하기 쉬운 방식으로 구성할 수 있게 합니다.
  • 웹 서버와 애플리케이션 서버: 요청을 순수 함수로 처리함으로써, 각 요청이 독립적으로 처리될 수 있게 하고, 이는 스케일링과 유지보수성을 향상시킵니다.
  • 분산 시스템과 클라우드 컴퓨팅: 병렬 처리와 동시성은 분산 시스템의 핵심 문제입니다. 함수형 프로그래밍의 순수 함수는 이러한 시스템에서의 복잡성을 관리하고, 오류 가능성을 줄이며, 성능을 최적화하는 데 도움을 줍니다. 빅 데이터 처리와 병렬 연산이 요구되는 곳에서 특히 그 가치가 높습니다. 예를 들어, Apache Spark와 같은 빅 데이터 처리 프레임워크는 함수형 프로그래밍 개념을 기반으로 하고 있습니다.

함수형 프로그래밍의 특성은 특히 병렬 처리와 오류 처리에서 빛을 발합니다. 순수 함수는 독립적인 계산을 의미하기 때문에, 다른 계산과 동시에 실행될 수 있습니다. 이는 병렬 처리가 가능한 시스템에서 효율적인 실행을 가능하게 합니다. 오류 처리는 불변 상태와 예측 가능한 함수 동작 덕분에 간단해집니다. 예외가 발생하더라도 시스템의 나머지 부분에 영향을 주지 않고, 오류를 격리시킬 수 있습니다.




명령형 프로그래밍과의 비교


명령형 프로그래밍은 컴퓨터에게 '어떻게' 일을 수행할지를 알려주는 절차적인 접근 방식입니다. 상태 변경과 순차적인 계산을 중심으로 합니다.
반면, 함수형 프로그래밍은 '무엇을' 수행할지를 선언하는 방식으로, 변하지 않는 데이터와 상태 변경이 없는 순수 함수를 중심으로 작동합니다.



🛠️ 실제 코드 비교 (1)

다음은 리스트의 모든 요소를 두 배로 만드는 동작을 명령형 프로그래밍과 함수형 프로그래밍으로 구현한 코드입니다.

명령형 프로그래밍 (Python 예시):

numbers = [1, 2, 3, 4, 5]
doubled_numbers = []
for number in numbers:
    doubled_numbers.append(number * 2)

함수형 프로그래밍 (Haskell 예시):

doubled_numbers = map (*2) [1, 2, 3, 4, 5]




위의 Python 코드는 numbers 리스트를 반복하면서 각 요소를 두 배로 만들어 doubled_numbers 리스트에 추가합니다. 이는 상태 변경(리스트에 요소 추가)이 일어나는 절차적 접근입니다.

반면 Haskell 코드는 map 함수를 사용하여 리스트의 모든 요소에 대해 곱하기 2를 수행하는 순수 함수 (*2)를 적용합니다. 여기서는 중간 상태가 존재하지 않고, 부작용이 전혀 없는 선언적 접근입니다.




🛠️ 실제 코드 비교 (2) 피보나치 수열

함수형 프로그래밍의 핵심 원리 중 하나인 불변성과 순수 함수를 보여주는 예시를 들어보겠습니다.

피보나치 수열은 각 숫자가 바로 앞 두 숫자의 합인 수열로, 수학과 컴퓨터 과학에서 자주 등장하는 예시입니다. 함수형 프로그래밍에서는 이러한 수열을 생성하는 것을 순수 함수를 사용해 매우 간결하게 표현할 수 있습니다.

함수형 프로그래밍 (Haskell 예시):

Haskell 예시:

fibonacci :: Int -> [Int]
fibonacci n = take n fibs
  where
    fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

이 Haskell 코드는 fibonacci 함수를 정의합니다. 이 함수는 정수 n을 입력받아 피보나치 수열의 처음 n개 요소를 리스트로 반환합니다. 여기서 zipWith 함수는 두 리스트의 각 요소를 주어진 연산(+)으로 결합합니다. fibstail fibs의 각 요소를 더하여 무한 피보나치 수열을 생성하고, take n을 사용하여 이 수열의 처음 n개 요소만을 취합니다.

이 예시에서 중요한 점은 fibs 리스트가 불변성을 유지하며, 함수가 어떠한 부작용도 발생시키지 않는다는 것입니다. 이는 프로그램의 동작을 예측 가능하게 만들며, 병렬 처리나 다른 최적화를 안전하게 적용할 수 있게 합니다.

명령형 프로그래밍 (Python 예시):

비교를 위해, 동일한 작업을 Python을 사용한 명령형 프로그래밍으로 구현한 예시는 다음과 같습니다.

def fibonacci(n):
    fibs = [0, 1]
    for i in range(2, n):
        fibs.append(fibs[-1] + fibs[-2])
    return fibs[:n]

Python 코드는 fibonacci 함수를 정의하고, 반복문을 사용하여 n번째까지의 피보나치 수열을 생성합니다. 여기서 상태 변경이 일어나며(리스트에 요소를 추가하는 동작), 함수의 실행은 입력값 n에 따라 리스트 fibs의 상태를 변경함으로써 부작용을 발생시킵니다.


함수형 프로그래밍은 이와 같이 간결하고, 명확하며, 부작용이 없는 코드를 작성하도록 장려합니다. 데이터의 불변성과 순수 함수를 통해, 프로그램의 동작을 보다 쉽게 이해하고, 더 견고한 소프트웨어를 구축할 수 있습니다. 이는 프로그래머가 복잡한 시스템을 더 잘 관리하고, 오류를 줄이며, 멀티코어 프로세서와 분산 시스템의 이점을 최대화할 수 있도록 도와줍니다.




🔍 참고하면 좋은 사이트

프로그래밍 언어의 간단한 역사 https://www.itworld.co.kr/insight/213089
프로그래밍 언어 순위 2022 및 종류 https://elice.io/ko/newsroom/kind_of_programming_language#2022-tiobe-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%96%B8%EC%96%B4-%EC%88%9C%EC%9C%84
처음하는 C언어 https://jeongorithm.tistory.com/2
C 프로그래밍: 현대적 접근 https://wikidocs.net/book/2494

profile
I'm an graduate student majoring in Computer Engineering at Inha University. I'm interested in Machine learning developing frameworks, Formal verification, and Concurrency.

0개의 댓글