Programming/Computer Science Fundamentals

[프로그래밍 언어론] 3. 프로그래밍 언어 패러다임

Sujin Lee (Daisy) 2021. 9. 9. 13:31

 

1. 프로그래밍 패러다임

 - 프로그램을 작성하는 전형적인 방식.

 - 특정 언어에 종속적인 것이 아닌, 프로그래머가 추구하는 프로그램 작성 방식. 

 

2. 프로그래밍 패러다임의 변화 : 함수형 --> 논리 --> 객체지향 

 - 데이터가 저장된 메모리를 관리하는 것이 어려운 문제로 대두

   --> 함수형 프로그래밍 패러다임 등장 

 - 계산 절차를 문제의 조건으로 명시하는 규칙으로 생각

   --> 논리 프로그래밍 패러다임 등장 : 선언적 프로그래밍 패러다임의 한 종류 

 - 같은 데이터에 대해, 다른 처리 절차를 여러 개 명시해야 하는 경우가 흔히 발생

   --> 객체지향 프로그래밍 패러다임 등장 

 

3. 프로그래밍 패러다임 변화의 배경

 1) 응용 도메인의 변화

   - 요구사항의 변화

   - 계산분야 --> 다양한 응용 분야

 2) 프로그램 구성 방식의 변화

   - 명령어 나열 --> 존재하는 모듈의 조합

 3) 계산 모델의 변화

   - 튜링기계 모델 --> 새로운 방식의 계산 모델 

 

4. 프로그래밍 패러다임 vs 프로그래밍 언어 패러다임

 - 프로그래밍 패러다임 : 프로그램을 작성하는 방식이나 스타일

 - 프로그래밍 언어 패러다임 : 해당 프로그래밍 언어가 지원하는 프로그래밍 패러다임

    ㄴ 일반적으로 하나의 프로그래밍 언어는 여러 프로그래밍 패러다임을 지원함. 

 

5. 주요 언어의 프로그래밍 패러다임 

 

6. 프로그래밍 패러다임의 양립성 

 - 다양한 프로그래밍 패러다임은 서로 양립 가능함. 

 - 새로운 패러다임의 등장으로, 이전에 있던 패러다임이 더욱 공고히 완성됨.

 - 주류 프로그래밍 패러다임이 바뀜에 따라서 이를 언어가 수용하는 방식으로 변화됨. 

   ex) Python : 명령형 패러다임, 절차형 패러다임 지원

         ---> 함수형 패러다임, 객체지향 패러다임을 포함.

 

 

7. 여러 패러다임 프로그램의 예시 

 

1) 명령형 프로그래밍 

 - 프로그램 : 일련의 명령어를 나열한 것. ===> 프로그램 = 명령어의 나열  

   ㄴ 단순히 명령어를 쭉 나열해서 코딩.... --> 이해하기 쉬움. 

 - 장점 : 프로그램을 쉽게 이해할 수 있음. 

 - 단점 : 프로그램이 복잡한 경우, 효과적으로 다룰 수 없음. 

    ex) BASIC 

HOME
INPUT "Enter A: ";A : INPUT "Enter B:";B
IF A < B THEN C = A : A = B : B = C
REM C = A MOD B (A modulo B)
LET C = A - INT(A/B)*B
LET A = B : B = C
IF B > 0 GOTO 40 // 40줄로 감 (4번째 줄) 
// 명령형에서는 GOTO를 사용해서 여기저기 점프해서 사용 가능 :) 
// 하지만 기본적으로는 한 문장 한 문장, 순서대로 처리됨 
PRINT "GCD is ";A
END

   실행결과) 

    Enter A : 126

    Enter B : 312

    GCD is 6 

※ GCD (최대공약수) 구하는 법 : 유클리드 호제법

   --> 이 예시들에서는 '유클리드 알고리즘'을 각각의 언어로 표현하였음. 

  참고) 유클리드 호제법 

 

 

2) 절차형 프로그래밍 

 - 프로그램 : '서브루틴'이라는 절차의 집합  ===> 프로그램 = 절차들의 모임. 

   ㄴ 앞서봤던 명령형 프로그래밍처럼 매번 명령어들을 하나하나 작성하는 것이 아니라,

       미리 만들어진 절차가 있으면 그것들을 잘 가져다 써서 프로그래밍 가능. 

   ㄴ 서브루틴을 잘 활용하면 재귀호출이 가능. --> 간단하게 프로시저를 만들 수 있다. 

 - 장점 : 재귀호출을 사용하여 프로시저를 간단하게 정의 

    ex) Algol  

// PROC : 프로시저. ===> 즉, gcd라는 프로시저(절차)를 하나 만들어냄. 
PROC gcd = (INT a, b) INT: ( 
	IF b = 0 THEN
    	a
	ELSE
    	gcd(b, a MOD b) // 재귀호출 
    FI
);

main:(
	INT a = 126, b = 312;
	printf(($x"The gcd of"g" and "g" is "gl$,a,b,gcd(a,b)))
)
// 이전에 만들어놓은 gcd라는 절차(프로시저)를 사용해서 간단하게 코딩 가능! :)

  실행결과) 

  The gcd of +126 and +312 is +6 

 

 

3) 구조화 프로그래밍 

 - goto 없이 프로그램을 작성하는 방법

   ㄴ 구조화 프로그래밍이 발생하게 된 계기는, 사실 'goto 없이 만들어보자.'고 해서 발명되었음...

       goto 계속 쓰다보니까 헷갈려서. ㅎㅎ 꼬이게 되는 경우가 발생하기 때문에... 그걸 막아보기 위해서.. 

      ==> structure를 만들어서 언제나 A부터 Z까지, '나는 이 틀안에서만 움직일거야.' 이런 식으로 동작.... 하게끔...

   ㄴ (1강) 구조화 : 어떤 틀을 잘 만들 수 있어서 그 한 덩어리들을 잘 모으고,

                             그것들을 통해서 전체적으로 구조화된, 잘 정의된 프로그램을 만드는 것. 

 - 블록과 서브루틴을 이용

 - 구조화된 제어문을 사용 

    ㄴ 앞서봤던 BASIC에서는 IF문을 보고 필요하면 GOTO해서 어디로 가 버렸음. 

        구조화 프로그래밍에서는 이게 아니라, 구조화된 제어문이란 '중첩된 구조문'이라고 표현하는데, 

        예를 들어 IF문이 있으면 이 조건이 맞으면 IF 중괄호가 시작하는데부터 끝나는데까지, 이 조건문 자체를 중첩시켜서 

        IF문 안에 다른 문장을 넣을 수 있는 것. 즉, IF 안을 수행하도록 하는 것... ==> 구조화 프로그래밍. 

   ex) C

#include <stdio.h>

int main() {
	int a, b, c;
    
    printf("Enter a and b: ");
    scanf("%d %d", &a, &b);
    do {
    	c = a % b;
        a = b;
        b = c;
    } while (b > 0);
    printf("gcd: %d\n", a);

	return 0;
}

 실행결과) 

  Enter a and b : 126 312

  gcd : 6

 

 

4) 객체지향 프로그래밍 

 - 프로그램 : 서로 통신할 수 있는 객체(object)의 집합. ===> 프로그램 = 객체의 집합. 

 - GUI 개발에 큰 획(Smalltalk)

 - 프로그램 재사용 편의로 S/W 생산성에 크게 기여  

 - 객체의 개념

    ㄴ 객체 : 상태를 유지하며 외부의 요청에 반응하는 데이터 

    ㄴ 하나의 객체 안에는, 1) 상태: 필드(멤버변수)  2) 반응 : 메소드(멤버 함수) 가 필요함. 

        ==> 이 둘이 묶여서 하나의 객체가 됨. 

    ㄴ 상태는 외부에 숨기고, 메소드는 외부에 공개! 

   ex) Smalltalk 

// igcd 객체 정의 
igcd := [ :a :b |
	|u v|
    u :=a. v:=b.
    [ v > 0 ]
    	whileTrue: [ |t|
        	t := u.
            u := v.
            v := t rem: v
		].
	u abs // u값은 외부에 노출되지 않고 객체 내부에 잘 가지고 있음. 
].

(igcd value: 126 value: 312) printN1.
// igcd 객체를 사용할 것인데, 첫번째 값은 126, 두번째 값은 312를 주겠다. 
// (igcd ~~~ ) : 이게 객체임.
// u값은 외부에 노출되지 않고 객체 내부에 잘 가지고 있음 
// ===> (igcd ~~~ ) 이 객체를 printN1을 통해서 마지막 값을 출력해줄 수 있음.

  실행결과) 

  6 

 

 

5) 함수형 프로그래밍 

 - 데이터는 값으로, 명령어는 함수로 취급. ==> 명령어가 데이터를 바꿀 수 없음

   ㄴ 세부설명)

       데이터를 어떤 장소에 두는 데 개의치 않고, 그냥 오직 값으로만 봄. 

       함수에 값을 던져주면 함수가 뭔가 작업을 한 다음에 결과값을 돌려줌. 

       ==> 데이터는 항상 값으로 처리하게 되고, 그 값을 처리하는 명령어들은 다 함수로 취급함. 

       즉, 함수는 결과값만 얻을 수 있는 것이지 그 함수에 들어간 인자를 건드릴 수는 없다. 

       ==> 함수형 프로그래밍에는 대입연산자가 없음. ==> 반복문도 불가. (카운트 자체가 불가...) 

               대입과 반복문이 없고 대신에 재귀호출로 처리함. 

 - 대입문과 반복문 없음

 - 함수 자체도 값으로 취급 가능. 

   ㄴ 자기 자신, 즉 함수 자체도 값으로 취급함. 

  ex) Haskell - 함수와 인자가 괄호 없이 연속해서 나열된다. ex) igcd a 0 = abs a 

module Main (main) where // Haskell에서는 module 단위로 코딩함. 

main :: IO () // IO 라는 결과값을 되돌려줌 
main = putStrLn (show (igcd 126 312)) // main은 이 일을 한다 

// igcd를 정의 
// 괄호가 없음. 함수형 프로그래밍에서는 함수 이름과 인자가 일렬로 나열됨. 
igcd a 0 = abs a // 입력값이 0이 되면 그것을 최대공약수로 보내면 된다. 
igcd a b = igcd (abs b) (a 'mod' (abs b)) // 0이 아닌 두 값이 들어오면, 두번째 값하고 첫번째 값을 두번째로 나눈 나머지 값을 인자로 해서 또 igcd한다...

 

 

6) 선언적 프로그래밍과 논리 언어 

 - 프로그램 : 논리식 집합

 - 논리식은 명제나 술어로 나타냄.

    ㄴ 술어는 인수를 받을 수 있음. 

    ㄴ 상세설명) 

        명제 : 딱 주어진, 정해진 틀만 가능. 

        술어 : 변수 개념. 

        ex) 모든 x에 대해서 x는 뭐다.

              x가 뭐라면 참이 되고, x가 또 다른 값이라면 거짓이 된다. ...  --> 이런 식으로 술어논리...

        논리언어에서는 명제 혹은 술어를 다 표현할 수 있음. 

   ex) Prolog 

// [논리형 언어는 어떤 방식으로 작동하는가] 
puppy(happy). // 술어논리 : 'happy라고 하는 것은 강아지이다.' (정의) 
safe(happy). // 'happy란 안전하다.' (정의) 
pet(X) :- puppy(X), safe(X). // 애완동물(pet)이 뭔지 정의 : 
// X라고 하는 것이 애완동물이 되려면, X는 강아지여야 되고, 그 X는 안전해야 한다 는 조건을 만족해야함.

  실행결과) 

   ? - pet(X).     // 애완동물 중에 뭐가 있는지, X로 어떤 것이 가능한지 알려달라. 

   X = happy.    // X로는 happy가 가능하다.  (앞서 정의된 것을 바탕으로 참인 것을 가르쳐줌) 

   // happy는 강아지이기도 하고, 안전하기도 하니까, happy는 애완동물(pet)이 맞다. 

// 최대공약수 계산 - gcd 함수 정의 
gcd (U, 0, U).  // 어떤 값하고 0이 들어오면, 어떤 값 하나를 최대공약수라고 알려주면 됨.  
gcd(U, V, X) :- V > 0, Y is U mod V, gcd(V, Y, X). // 0이 아닌 두 가지 값이 나오는 경우에는 
// 최대공약수가 X라고 정의해야하는데, 누가 X가 될 수 있느냐? 
// 유클리드 알고리즘에서 U하고 V가 들어왔으면 두 U,V의 최대공약수란 
// V하고, U를 V로 나눈 나머지 값 Y,
// 이 둘의 최대공약수와 같다는 것을 활용.

 실행결과)

 ? - gcd(126, 312, X).    // gcd라는 함수를 쓸건데, 126과 312 값을 줄테니까, 그걸 만족하는 최대공약수 X가 뭔지 알려줘.

 X = 6     // 논리에 따라 그것을 만족하는 최대공약수 X는 6이다.  ==> 논리를 통해서 계산이 가능하다 :) 

?- gcd(126, 312, X).
X = 6

 

 

8. 프로그래밍 패러다임의 특징

1) 객체지향 패러다임 : 객체 사이의 통신을 통해 계산을 표현 

2) 함수형 패러다임 : 함수의 적용을 통해 계산을 표현 

3) 논리 패러다임 : 논리식의 진위를 증명하는 과정을 통해 계산을 표현 

반응형