본문 바로가기
CS/Computer Basic

[CS/Basic] 좀 더 나은 프로그램을 위해, 프로그래밍 패러다임

by iosdevlime 2022. 12. 26.

프로그래밍 언어, 3번째 포스팅입니다.

슬슬 그 끝이 보이기 시작합니다..? 👀

 

종류 및 특징 중, 이제 패러다임과 관련된 이야기를 나눠볼까 합니다.

  • 패러다임
  • 방법 혹은 목적 (저 수준/고 수준)
  • 빌드(Build)유무 (컴파일 / 인터프리터)
  • 자료형 지정 유무

 

프로그래밍 패러다임과 관련된 내용은

다소 철학적이고, 단번에 이해하기 어려운 개념이므로

 

본 포스팅에서는 예시를 활용하여 보다 쉽게 다뤄보도록 하겠습니다.

 

 

 


 

 

 

프로그래밍 패러다임(programming paradigm)이란? 

특정 관점접근 방식에 따른 개발자의 코딩방식

 

 

패러다임(Paradigm)의 사전적 정의는 다음과 같습니다.

 

한 시대의 사람들의 견해나 사고를 근본적으로 규정하고 있는 인식의 체계.
또는 사물에 대한 이론적인 틀이나 체계. 즉, 일종의 '틀'
(출처 : Oxford Languages)

 

프로그래밍 분야에서 이를 적용해 보자면..

 

개발자는 프로그래밍과 관련된 이론적 체계 혹은 틀(패러다임)에 따라

'어떻게 프로그래밍을 할 것인가' 란 의문을 스스로 던지고,

특정 관점과 방식을 바탕으로 '프로그래밍'을 실시하게 되는 셈입니다.

 

 

상당히 철학적인 이야기가 아닐 수 없네요.

 

 


 

 

프로그래밍 패러다임의 변화

  • 통상, '프로그래밍 패러다임'이라 하면 아래 3가지를 의미합니다. 
    • 절차적 프로그래밍 (PP, Procedure Programming)
    • 객체지향 프로그래밍 (OOP, Object Oriented Programming)
    • 함수형 프로그래밍 (FP, Functional Programming)
  • 해당 분류는 각 패러다임이 프로그래밍 분야에서 각광받은 시점과도 동일합니다.
    • 다만, 등장 순서는 이와 정 반대로 함수형 ➟ 객체지향 ➟ 절차적 입니다. 

구글에서 '프로그래밍 패러다임'을 검색하면 단골로 나오는 예시(호머심슨) 이미지
구글에서 '프로그래밍 패러다임'을 검색하면 단골로 나오는 예시(호머심슨) 이미지

 

  • 그러므로, 프로그래밍 패러다임은 단순히 진화론적 관점에서 우열을 판단할 수 없습니다.
    • 프로그래밍 패러다임은 '접근 방식''사용 환경'에 따라 유동적으로 활용됩니다.
    • 각각의 프로그래밍 패러다임은 장단점이 존재하며, 이에 상호 보완적 특성을 가집니다.

 


 

 

프로그래밍 패러다임의 분류

  • 앞서, 3가지 주요 프로그래밍 패러다임은 [방법/목적]에 따라 재 분류됩니다.
    • 명령형 프로그래밍(Imperative Programming)
      • 절차형, 객체지향적 프로그래밍
    • 선언형 프로그래밍(Declearative Programming)
      • 함수형, 논리형 프로그래밍

방법 및 목적에 따른 프로그래밍 패러다임
방법 및 목적에 따른 프로그래밍 패러다임

 


 

 

 

명령형 프로그래밍 vs 선언형 프로그래밍 

어떻게(How) 할것인가, 무엇(What)을 할 것인가?

 

프로그래밍 메인 스트림 패러다임인 선언형 / 명령형 프로그래밍에 대하여

각각의 정의와 차이를 살펴보기 위해 2가지 예시를 들어보도록 하겠습니다.

 

 

 

 

예시1. 가공된 큐브 치즈를 생산하는 공장

  • 당신은 치즈를 생산하는 공장의 관리자입니다.
  • 오는 7월의 치즈 생산을 위해 직원들에게 다음과 같이 지시합니다.

명령형 접근(HOW)과 선언형 접근(WHAT)
명령형 접근(HOW)과 선언형 접근(WHAT)

명령형 접근(HOW)을 통해 치즈를 생산할 경우, 
공통의 목표와 주의사항을 설정 ➟  세부 공정과정(우유살균, 응고 및 숙성 등)을 관리 ➟ 생산을 완료합니다.

선언형 접근(WHAT)
을 통해 치즈를 생산할 경우, 
목표(기간, 수량)만을 던져주고 ➟ 생산을 지시 ➟ 생산을 완료합니다.

 

  • [명령형 접근]은 치즈를 생산하는 과정(HOW)에 대해 포커스를 집중합니다. 
    • 따라서, 해당 과정마다 구체적인 임무를 제시하고 일부 참고사항까지 제시합니다.
  • 이와 반대로, [선언형 접근]은 단순히 치즈의 생산(WHAT)만이 유일한 관심사입니다.
    • 임무의 세부 지시사항과 절차를 미리 레시피로 학습 한 상태라고 추상화, 즉 가정한 상태입니다.
    • 결과적으로, 공장관리자는 '지시'만 내리는 행위만으로도 결과물(OUTPUT)을 도출합니다.
  • 즉, [선언형 접근]을 위해 명령형 단계가 이미 추상화되어 있다는 가정이 뒷받침 되어야 한다는 점입니다.

 


 

 

예시2. 배열 내 각각의 값을 제곱하는 함수 만들기

  • 명령형 프로그래밍을 통한 예시 코드는 다음과 같습니다.
    • multiply란 명칭의 함수가 동작하고, 값을 반환하기 위해 총 3개의 단계를 거칩니다.
    • 빈 배열을 생성하고 ➟ 조건문을 사용해 제곱기능을 만들고 ➟ 요소가 담긴 배열 반환
func multiply(number: [Int]) -> [Int] {
    
    var someNum: [Int] = [] // 1. someNum이란 빈 배열을 만들어 주고
    
    for i in 0..<number.count {
        someNum.append(number[i] * number[i])
    }
    // 2. for 조건문을 통해 각각의 배열의 요소가 해당 값의 제곱값으로 변환되어 포함될 수 있도록 하고
    
    return someNum // 3. 그 결과를 요소로 담아 새로운 배열을 반환한다.
}

multiply(number: [1,2,3]) // [1,4,9]

 

 

  • 반면에, 선언형 프로그래밍을 통한 동일한 기능의 코드는 다음과 같습니다.
    • 상당히 단순하게 바뀌었습니다!
    • 'map' 고차함수는 Swift Framework 에 이미 내장되어 있는 기능입니다.
    • map 또한 이미 명령형 프로그래밍 방식으로서 코드의 기능이 작성되어 있습니다.
      (단지, map이란 명칭으로서 추상화, 전제되어 있는 것입니다) 
func multiply2(number: [Int]) -> [Int] {
    return number.map {$0 * $0 } // map 고차함수를 활용
}

multiply2(number: [1,2,3])

 

 

 


 



프로그래밍 패러다임 첫 번째 포스팅이 마무리 되었습니다.

 

다음 포스팅에서는 아직 자세히 다루지 못한

절차적 / 객체지향적 / 함수형 프로그래밍 에 대해

하나씩, 차근차근 살펴보도록 하겠습니다.

 

 

댓글