Frinee의 코드저장소

프로그래밍 패러다임 (Programming Paradigm)

by Frinee

1. 프로그래밍 패러다임 (Programming Paradigm) 이란?

: 프로그래머에게 프로그래밍의 관점을 갖게 해주는 역할을 하는 개발 방법론을 말한다.

 

프로그래밍 패러다임은 크게 선언형, 명령형으로 나누며

선언형에서는 함수형이라는 하위집합을 갖고

명령형에서는 객체지향과 절차지향으로 나눈다.


2. 선언형과 함수형 프로그래밍

  • 선언형 프로그래밍이란 "무엇을" 풀어내는가에 집중한 패러다임
  • "프로그램은 함수로 이루어진 것이다." 라는 명제가 담긴 패러다임이기도 함

다음은 자연수로 이루어진 배열에서 최댓값을 찾는 로직의 예시이다.

const list = [1,2,3,4,5,6,11]
const ret = list.reduce((max, num) => num > max ? num : max, 0)
console.log(ret) // 11

 

함수형 프로그래밍은 이런 순수함수들을 블록처럼 쌓아 로직을 구현하고 고차함수를 통해 재사용성을 높이는 것이 특징

 

2.1 순수 함수

: 출력이 입력에만 의존하는 것을 말한다.

const pure = (x,y) => {
	return x + y
}

 

  • pure 함수는 매개변수 x,y 에만 영향을 받음.
  • 만약 x,y 외의 다른 전역 변수 등이 출력에 영향을 주면 순수함수가 아님

 

2.2 고차 함수

: 함수가 함수를 값처럼 매개변수로 삼아 로직을 생성할 수 있는 것을 말한다.

 

※ 일급 객체

고차 함수를 쓰기 위해선 해당 언어가 일급 객체라는 특징을 가져야 함.

  • 변수나 메서드에 함수를 할당할 수 있어야 함.
  • 함수 안에 함수를 매개변수로 담을 수 있어야 함.
  • 함수가 함수를 반환할 수 있어야 함.

 

3. 객체지향 프로그래밍 (OOP, Object-Oriented Programming)

  • 객체들의 집합으로 프로그램의 상호작용을 표현함
  • 데이터를 객체로 취급하고 객체 내부에 선언된 메서드를 활용함.
  • 설계에 많은 시간이 소요되며 처리속도가 상대적으로 느림.

아까와 마찬가지로 자연수로 이루어진 배열에서 최댓값을 찾는 로직의 예시이다.

const ret = [1,2,3,4,5,6,11]
class List {
	constructor(list){
    	this.list = list
        this.mx = list.reduce((max, num) => num > max ? num : max, 0)
    }
    getMax() {
    	return this.mx
    }
}

const a = new List(ret)
console.log(a.getMax()) // 11

3.1 객체지향 프로그래밍의 특징

  1. 추상화(abstraction): 복잡한 시스템으로부터 핵심적인 기능 또는 개념을 간추려내는 것, ex) 나 → 공대생 남자
  2. 캡슐화(encapsulation): 개체의 속성과 메서드를 하나로 묶고 일부를 외부에 감추어 은닉하는 것.
  3. 상속성(inheritance):  상위 클래스의 특성을 하위 클래스가 이어받아서 재사용하거나 추가 및 확장하는 것
  4. 다형성 (polymorphism): 하나의 메서드나 클래스가 다양한 방법으로 동작하는 것 ex) 오버로딩, 오버라이딩
  • 오버로딩(overloading): 같은 이름의 메서드를 매개변수,메서드 타입 등으로 구분하여 여러 개 두는 것
  • 오버라이딩(overriding): 상위 클래스로부터 상속받은 메서드를 하위 클래스가 재정의

 

3.2 설계원칙 (SOLID 원칙)

: 객체지향 프로그래밍을 설계할 때는 SOLID 원칙을 지켜야 한다.

  1. 단일 책임 원칙(SRP, Single Responsibility Principle): 모든 클래스는 각각 하나의 책임만을 가져야 한다는 원칙
  2. 개방-폐쇄 원칙(OCP, Open Closed Principle): 유지보수 사항이 생길 때, 코드를 쉽게 확장할 수 있어야 하며 수정할 때에는 닫혀 있어야 한다는 원칙 
  3. 리스코프 치환 원칙(LSP, Liskov Substitution Principle): 프로그램의 객체는 프로그램의 정확성을 깨지 않으면서 하위타입의 인스턴스로 바꿀 수 있어야 한다는 원칙 → "모든 자식 클래스가 부모 클래스의 동작을 적절히 수행해야 한다 ."
  4. 인터페이스 분리 원칙(ISP, Interface Segregation Principle): 하나의 일반적인 인터페이스보다 구체적인 여러 개의 인터페이스를 만들어야 한다는 원칙
  5. 의존 역전 원칙(DIP, Dependency Inversion Principle): 추상화된 상위 인터페이스나 클래스는 세부적인 구현의 하위 계층에 의해 영향을 받아서는 안 된다는 원칙

 

4. 절차형 프로그래밍

  • 로직이 수행되어야 할 연속적인 계산과정으로 이루어져 있음.
  • 일이 진행되는 방식으로 구현하면 되기 때문에 가독성이 좋으며 실행속도가 빠름
  • 하지만 모듈화가 어렵고 유지보수가 어려움
  • 주로 계산이 많은 작업에 사용

또다시 마찬가지로 자연수로 이루어진 배열에서 최댓값을 찾는 로직의 예시이다.

const ret = [1,2,3,4,5,6,11]
let a = 0
for (let i = 0; i < ret.length; i++) {
	a = Math.max(ret[i], a)
} 
console.log(ret) // 11

 

 

5. 결론

     (찡긋)

 

그래서 뭐가 더 좋나요? 라고 물어보신다면 

사실 그런건 없습니다.

하지만 비즈니스나 서비스의 특징에 따라서 더 적합한 개발방법론은 존재하기 때문에

이 개념을 알아두는 것이 좋습니다. 

블로그의 정보

프리니의 코드저장소

Frinee

활동하기