카테고리 없음

명령형/선언적 프로그래밍

노엠디엔 2024. 10. 12. 15:00

명령형 프로그래밍 (Imperative Programming)

프로그램의 상태를 변경하는 명령문의 시퀀스로 구성된다.

어떻게(How) 구성할지에 초점을 맞추어 목표를 달성하기 위한 각 단계를 기술한다.

C, Java의 절차적 부분, 저수준코드

  • 고수준 언어(High-Level Language): 고수준 언어는 프로그래밍 언어가
    영어와 한국어와 같은 인간의 언어에 가깝게 작성되어,
    사람이 이해하기 쉬운 형태로 구성됩니다.
    Python, JAVA, JavaScript와 같은 언어가 고수준 언어에 해당합니다.
  • 저수준 언어(Low-Level Language): 저수준 언어는 컴퓨터가 직접 이해하는
    더 기술적인 언어를 뜻함 저수준 언어는 기계어(컴퓨터의 언어)와 매우 유사하며,
    컴퓨터의 메모리와 프로세서를 직접 제어한다.
    어셈블리 언어와 대표적인 저수준 언어에 해당합니다.

선언적 프로그래밍 (Declarative Programming)

원하는 결과를 명시하고 그 결과를 얻기 위해 구체적인 단계는 추상화여 설계

무엇(What)을 할지에 초점을 맞춘다.

프로그램의 로직을 직접 기술하지 않고, 원하는 결과를 설명한다.

SQL, HTML 함수형 프로그래밍 언어 

  • 함수형 프로그래밍(Functional Programming)은 프로그래밍 패러다임 중 하나로,
    프로그램의 로직을 함수로 구성하고,
    데이터를 변경하지 않으며 순수 함수(Pure Function)를 사용하는 방식을 강조한다.
    • 불변성 (Immutability) :함수형 프로그래밍에서는 데이터가 변경되지 않습니다.
      모든 데이터는 불변 객체로 간주되며, 데이터의 변경이 필요한 경우
      기존 데이터를 복사하여 새로운 데이터를 생성합니다.
    • 고차 함수 (Higher-Order Function):함수를 인자로 받거나 함수를 반환하는 함수를 말합니다.
      고차 함수는 코드를 더 추상화하고 재사용성을 높입니다.
    • 부작용 없음 (No Side Effects):함수가 외부 상태를 변경하지 않기 때문에
      함수의 실행이 프로그램의 다른 부분에 영향을 주지 않습니다. 
    • 일급 객체로서의 함수 (First-Class Function):함수가 일급 객체로 취급되며, 변수에 할당되거나
      다른 함수의 인자로 전달될 수 있습니다.

리액트에서는 선언형 프로그래밍으로 컴포넌트 작성하는 것을 권장하고 있다.

밑에 예시로 알아보자.

import React, { useState } from 'react';

function ImperativeComponent() {
  // 상태 및 로직을 컴포넌트 내부에서 모두 처리
  const [items, setItems] = useState(['Item 1', 'Item 2', 'Item 3']);

  const addItem = () => {
    setItems([...items, `Item ${items.length + 1}`]);
  };

  return (
    <div>
      <h3>Item List</h3>
      <ul>
        {items.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
      <button onClick={addItem}>Add Item</button>
    </div>
  );
}

export default ImperativeComponent;
 

 

위코드는 상태와 버튼에 대한 함수와 UI처리까지 한 번에 처리하는
명령형 프로그래밍 방식에 코드로써

어떤 절차를 통해 결과를 도출할지에 대해 집중하여 아이템을 추가하는 방법과 UI를 어떻게 업데이트할지에 집중

  • 명시적 절차: addItem 함수는 새로운 아이템을 배열에 추가하기 위해 명시적으로 배열을 복사하고,
    새로운 아이템을 추가함
  • UI 갱신: map() 함수는 아이템 리스트를 그리기 위해 모든 아이템을 순회하며 직접
    그리는 방법을 명시합니다.

재사용성을 중요시하는 리액트에서는 위코드와 같은컴포넌트는
재사용하기 힘들고 상태나 함수가 변할시 해당컴포넌트 전체가 재렌더링되므로
이러한 프로그래밍 방식은 권장하지 않는 것 같다.

import { useState } from 'react';

// 커스텀 훅: 아이템 관리 로직을 담음
function useItemManager(initialItems) {
  const [items, setItems] = useState(initialItems);

  const addItem = () => {
    setItems([...items, `Item ${items.length + 1}`]);
  };

  return {
    items,
    addItem,
  };
}
import React from 'react';
import { useItemManager } from './useItemManager'; // 커스텀 훅 불러오기

// 개별 아이템을 렌더링하는 컴포넌트
function ListItem({ item }) {
  return <li>{item}</li>;
}

// 아이템 리스트를 렌더링하는 컴포넌트
function ItemList({ items }) {
  return (
    <ul>
      {items.map((item, index) => (
        <ListItem key={index} item={item} />
      ))}
    </ul>
  );
}

// 버튼을 렌더링하는 컴포넌트
function AddItemButton({ onAdd }) {
  return <button onClick={onAdd}>Add Item</button>;
}

// 상위 컴포넌트 - 비즈니스 로직을 커스텀 훅에서 가져옴
function DeclarativeComponent() {
  const { items, addItem } = useItemManager(['Item 1', 'Item 2', 'Item 3']);

  return (
    <div>
      <h3>Item List</h3>
      <ItemList items={items} />
      <AddItemButton onAdd={addItem} />
    </div>
  );
}

export default DeclarativeComponent;

위코드는 선언적 프로그래밍 방식으로 작성한 컴포넌트로써 비니지스 로직은
커스텀훅으로 분리,컴포넌트는 UI를 보여주는 역할만 수행하게 된다.

컴포넌트마다 무엇을해야할지에 초점을 맞춰 하나의 역할만 할 수 있게 단일책임 원칙에 집중한다. 

 

 

  • 커스텀 훅 (useItemManager):
    • 아이템 목록 관리 및 추가 로직을 담당
    • items와 addItem을 반환하여 컴포넌트에서 쉽게 사용할 수 있게 함.
  • 컴포넌트 (DeclarativeComponent):
    • 비즈니스 로직이 커스텀 훅으로 분리되었으므로, items와 addItem을 커스텀 훅에서 가져와 사용.
    • 상태 관리, 비즈니스 로직에 대한 코드를 별도로 작성할 필요 없이, 뷰만 관리