etc.

[Programming Paradigm] 선언형, 함수형, 객체지향, 절차형 프로그래밍

mooni_ 2025. 4. 9. 11:26

개발 방법론 정리

프로그래밍에는 다양한 패러다임(Paradigm)이 존재하며, 각각의 철학과 구현 방식이 다릅니다. 이번 글에서는 대표적인 개발 방법론들을 간단한 코드 예제와 함께 정리해보았습니다.

 

1. 선언형 프로그래밍 (Declarative Programming)

  • 정의: “프로그램은 함수로 이루어진 것이다” 라는 철학이 담긴 프로그래밍 패러다임입니다.
  • 특징: 무엇을 할 것인지를 설명합니다. 어떻게 할지는 중요하지 않습니다.

 

2. 함수형 프로그래밍 (Functional Programming)

  • 선언형 프로그래밍의 일종입니다.
  • 순수 함수를 조합하여 로직을 구성하고, 고차 함수를 통해 재사용성과 추상화를 극대화합니다.
  • JavaScript에서는 함수가 일급 객체이기 때문에 함수형 스타일을 유연하게 적용할 수 있습니다.
const list = [1, 2, 3, 4, 5, 11, 12]
const ret = list.reduce((max, num) => num > max ? num : max, 0)
console.log(ret)
reduce()는 배열의 값을 누적해 하나의 값으로 줄이는 순수 함수입니다.

 

 

💡 주요 개념

순수 함수(Pure Function)? 출력이 오직 입력값에만 의존하고, 부작용이 없는 함수

const pure = (a, b) => {
  return a + b
}

 

고차 함수(Higher-Order Function)? 함수를 인자로 받거나, 함수를 반환하는 함수

 

일급 객체(First-Class Citizen)? 함수를 변수에 할당하거나, 인자로 넘기거나, 반환할 수 있습니다.

 

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

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

  • 프로그램을 객체의 집합으로 표현하며, 객체 간의 상호작용을 통해 로직을 구성합니다.
  • 객체 내부의 데이터와 메서드를 하나로 묶어 처리합니다.
const ret = [1, 2, 3, 4, 5, 11, 12]
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())

 

 

💡 객체지향의 4대 특징

  • 추상화 (Abstraction) : 복잡한 시스템으로부터 핵심 개념만 간추립니다.
  • 캡슐화 (Encapsulation) : 데이터와 메서드를 하나로 묶고, 내부 구현을 숨깁니다.
  • 상속성 (Inheritance) : 상위 클래스의 기능을 하위 클래스가 물려받아 사용하거나 확장합니다.
  • 다형성 (Polymorphism) : 동일한 메서드가 다른 방식으로 동작할 수 있습니다.
    • 정적 다형성: 오버로딩
    • 동적 다형성: 오버라이딩

 

오버로딩(Overloading)?

class Person {
    public void eat(String a) {
        System.out.println("I eat " + a);
    }

    public void eat(String a, String b) {
        System.out.println("I eat " + a + " and " + b);
    }
}

public class CalculateArea {
    public static void main(String[] args) {
        Person a = new Person();
        a.eat("apple");
        a.eat("tomato", "phodo");
    }
}
메서드 이름은 같지만, 매개변수의 개수나 타입이 다릅니다. 컴파일 시점에 결정됩니다.

 

 

오버라이딩(Overriding)?

class Animal {
    public void bark() {
        System.out.println("mumu! mumu!");
    }
}

class Dog extends Animal {
    @Override
    public void bark() {
        System.out.println("wal!!! wal!!!");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog d = new Dog();
        d.bark();
    }
}
상속받은 메서드를 재정의하여 동작을 바꿉니다. 런타임 시점에 결정됩니다.

 

객체지향 설계 원칙 (SOLID)

  • SRP(단일 책임 원칙) : 클래스는 하나의 책임만 가져야 합니다.
  • OCP(개방-폐쇄 원칙) : 확장에는 열려 있고, 변경에는 닫혀 있어야 합니다.
  • LSP(리스코프 치환 원칙) : 하위 클래스는 상위 클래스의 기능을 대체할 수 있어야 합니다.
  • ISP(인터페이스 분리 원칙) : 하나의 일반적인 인터페이스보다는 여러 개의 구체적인 인터페이스로 분리해야 합니다.
  • DIP(의존 역전 원칙) : 고수준 모듈이 저수준 모듈에 의존하지 않도록 합니다.

4. 절차형 프로그래밍 (Procedural Programming)

  • 프로그램을 순차적인 명령어의 흐름으로 작성하는 방식입니다.
  • 모듈화가 어렵고, 유지보수가 힘든 단점이 있습니다.
const ret = [1, 2, 3, 4, 5, 11, 12]
let a = 0
for(let i = 0; i < ret.length; i++) {
  a = Math.max(ret[i], a)
}
console.log(a)

 

 


 

마무리

프로그래밍 패러다임은 단순한 문법을 넘어서 문제 해결 방식에 대한 철학입니다.

실무에서는 하나의 패러다임만 사용하는 경우보다, 상황에 따라 적절히 조합하여 사용하는 경우가 많습니다.