클린코드

프로그래밍 패러다임

프로그래밍 패러다임은 크게 명령형(Imperative)과 선언형(Declarative) 두 가지로 나뉘며, 그 아래 다양한 하위 패러다임이 존재합니다.

명령형 : 어떻게,
선언형 : 무엇을 해야 하는지라고 생각하시면 됩니다.

javascript 기준으로 첨언을 하자면 express와 같은 프레임워크는 미들웨어 방식으로 선언형 프로그래밍의 하위개념인 함수형 프로그래밍 스타일을 따릅니다. 비동기 패턴, map, reduce, filter와 같은 고차함수를 활용한 데이터 처리 방식이 많기 때문입니다.

하지만 데이터 모델링이나 MVC패턴으로 아키텍쳐 패턴을 설계할 때, typescript 나 nest 를 사용할 때는 필요에 따라 명령형 프로그래밍의 하위개념인 객체지향 프로그래밍이 종종 사용됩니다.


1. 명령형(Imperative) 프로그래밍

컴퓨터에게 "어떻게(how)" 해야 하는지를 명령하는 방식

상태(variables, memory)를 변경하며 프로그램을 수행 절차적으로 실행됨 (순차적 흐름) 과정을 세부적으로 기술하는 느낌의 프로그래밍 방식이에요.

1-1. 절차형(Procedural) 프로그래밍

프로그램을 함수(Procedure) 단위로 구조화하는 방식 변수, 조건문, 반복문을 이용해 프로그램을 작성
대표 언어: C


#include <stdio.h>

// 전역 변수 (잔액 저장)
double balance = 0.0;

// 함수 선언
void deposit(double amount);
void withdraw(double amount);
void checkBalance();

int main() {
    int choice;
    double amount;

    while (1) {  // 무한 루프 (사용자가 종료할 때까지 반복)
        // 메뉴 출력
        printf("\n=== 은행 계좌 관리 프로그램 ===\n");
        printf("1. 입금 (Deposit)\n");
        printf("2. 출금 (Withdraw)\n");
        printf("3. 잔액 확인 (Check Balance)\n");
        printf("4. 종료 (Exit)\n");
        printf("선택하세요: ");
        scanf("%d", &choice);

        // 사용자 선택 처리
        switch (choice) {
            case 1:  // 입금
                printf("입금할 금액을 입력하세요: ");
                scanf("%lf", &amount);
                deposit(amount);
                break;
            case 2:  // 출금
                printf("출금할 금액을 입력하세요: ");
                scanf("%lf", &amount);
                withdraw(amount);
                break;
            case 3:  // 잔액 확인
                checkBalance();
                break;
            case 4:  // 종료
                printf("프로그램을 종료합니다.\n");
                return 0;
            default:
                printf("잘못된 입력입니다. 다시 선택하세요.\n");
        }
    }

    return 0;
}

// 입금 함수
void deposit(double amount) {
    if (amount > 0) {
        balance += amount;
        printf("입금 완료! 현재 잔액: %.2lf\n", balance);
    } else {
        printf("올바른 금액을 입력하세요.\n");
    }
}

// 출금 함수
void withdraw(double amount) {
    if (amount > 0 && amount <= balance) {
        balance -= amount;
        printf("출금 완료! 현재 잔액: %.2lf\n", balance);
    } else if (amount > balance) {
        printf("잔액이 부족합니다!\n");
    } else {
        printf("올바른 금액을 입력하세요.\n");
    }
}

// 잔액 확인 함수
void checkBalance() {
    printf("현재 잔액: %.2lf\n", balance);
}

1-2. 객체지향(Object-Oriented) 프로그래밍 (OOP)

  • 객체(Object)와 클래스(Class) 를 기반으로 설계
  • 캡슐화(Encapsulation), 상속(Inheritance), 다형성(Polymorphism) 등의 개념을 활용
  • 프로그램을 데이터와 그 데이터에 대한 동작(method)으로 구성
  • 대표언어 : java

import java.util.Scanner;

// 은행 계좌 클래스 (BankAccount)
class BankAccount {
    private double balance; // 계좌 잔액 (private으로 캡슐화)

    // 생성자
    public BankAccount(double initialBalance) {
        this.balance = initialBalance;
    }

    // 입금 메서드
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            System.out.println("입금 완료! 현재 잔액: " + balance);
        } else {
            System.out.println("올바른 금액을 입력하세요.");
        }
    }

    // 출금 메서드
    public void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            System.out.println("출금 완료! 현재 잔액: " + balance);
        } else if (amount > balance) {
            System.out.println("잔액이 부족합니다!");
        } else {
            System.out.println("올바른 금액을 입력하세요.");
        }
    }

    // 잔액 확인 메서드
    public void checkBalance() {
        System.out.println("현재 잔액: " + balance);
    }
}

// 메인 클래스 (BankApp)
public class BankApp {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 계좌 생성 (초기 잔액 0)
        BankAccount account = new BankAccount(0.0);

        while (true) {
            // 메뉴 출력
            System.out.println("\n=== 은행 계좌 관리 프로그램 ===");
            System.out.println("1. 입금 (Deposit)");
            System.out.println("2. 출금 (Withdraw)");
            System.out.println("3. 잔액 확인 (Check Balance)");
            System.out.println("4. 종료 (Exit)");
            System.out.print("선택하세요: ");

            int choice = scanner.nextInt();

            // 사용자 입력 처리
            switch (choice) {
                case 1:
                    System.out.print("입금할 금액을 입력하세요: ");
                    double depositAmount = scanner.nextDouble();
                    account.deposit(depositAmount);
                    break;
                case 2:
                    System.out.print("출금할 금액을 입력하세요: ");
                    double withdrawAmount = scanner.nextDouble();
                    account.withdraw(withdrawAmount);
                    break;
                case 3:
                    account.checkBalance();
                    break;
                case 4:
                    System.out.println("프로그램을 종료합니다.");
                    scanner.close();
                    return;
                default:
                    System.out.println("잘못된 입력입니다. 다시 선택하세요.");
            }
        }
    }
}

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

"무엇(what)"을 해야 하는지를 설명하는 방식

프로그램의 실행 흐름을 직접 명시하지 않음 데이터와 로직을 기술하는 방식에 집중

결과 중심적인 프로그래밍이라고 생각하면 됩니다.

2.1 함수형(Functional) 프로그래밍

  • 순수 함수(Pure Function)와 불변성(Immutability) 을 강조
  • 고차 함수(Higher-Order Function)의 개념 활용
  • 대표적인 map, filter, reduce 함수 사용
  • side effect 최소화

대표 언어: JavaScript (ES6 이후)

// 초기 계좌 상태 (불변 객체)
const createAccount = (initialBalance = 0) => ({
  balance: initialBalance,
})

// 입금 함수 (불변성 유지)
const deposit = (account, amount) =>
  amount > 0 ? { ...account, balance: account.balance + amount } : account

// 출금 함수 (불변성 유지)
const withdraw = (account, amount) =>
  amount > 0 && amount <= account.balance
    ? { ...account, balance: account.balance - amount }
    : account

// 잔액 확인 함수
const checkBalance = (account) => `현재 잔액: ${account.balance}`

// 함수형 스타일의 실행 (순차적으로 함수 적용)
let myAccount = createAccount(1000) // 초기 잔액 1000원
console.log(checkBalance(myAccount)) // 현재 잔액: 1000원

myAccount = deposit(myAccount, 500) // 500원 입금
console.log(checkBalance(myAccount)) // 현재 잔액: 1500원

myAccount = withdraw(myAccount, 300) // 300원 출금
console.log(checkBalance(myAccount)) // 현재 잔액: 1200원

myAccount = withdraw(myAccount, 2000) // 잔액 초과 출금 (거부됨)
console.log(checkBalance(myAccount)) // 현재 잔액: 1200원

2.2 선언형 데이터 조작(SQL)

  • 관계형 데이터베이스에서 데이터를 어떻게 처리할지(How) 가 아니라 무엇을 처리할지(What) 에 집중
  • 대표 언어: SQL
selet name, age from users where age > 30;
Previous
기능명세서