내가 느낀 추상화와 선언적 프로그래밍

imzzuu·2023년 8월 27일
0
post-thumbnail

음…추상화가…뭐예요…?

개발을 하다보면, 좋은 코드란? 클린 코드란? 과 같은 질문들을 스스로에게 하게된다.
그럴 때, 인터넷에 찾아보면 “추상화”, “관심사 분리”, “낮은 결합도”, “낮은 의존성” 등과 같은 단어들을 마주하게된다.
다른 단어들은 대충 유추가 가능하다.
코드들의 관심사에 따라 분리하고, 더 나은 유지보수성을 위해 결합도와 의존도가 낮은 코드를 작성해라!
하지만 추상화는….? 말만 들어서는 코드를 어떻게 추상화하라는거지? 라는 생각이 든다.
적어도 나는 그러했다….추상화…? 이름도 모호해….

그렇게 와닿지 않은 채로 개발을 하던 중, 어느 날 선언적 비동기 처리 포스팅을 보게 되었다.
선언적 프로그래밍, 명령형 프로그래밍,,,, 단어와 개념은 알겠는데, 선언적 프로그래밍이라는 것을 어떻게 코드로 구현할 수 있을지 너무나도 모호했던 지난 과거의 내가 생각났다.

이참에 개념에 대해 다시 공부해보자! 싶어서 관련 글들을 찾아보는데 추상화 라는 단어가 함께 나오는 것이 아닌가!
그런데 그렇게 이해가 안되던 개념들이 그냥 자연스럽게 이해가 되더라….참으로 신기하고…기특해서 얕은 지식이지만 적어보려한다.

그래서 추상화란?

말그대로 추상적이라는 단어를 생각해보자.
우리가 “음.. 좀 추상적인데 구체적으로 예시를 들어서 설명 해주라! “ 라는 말은 해본 적이 있을 것이다.
무언가 모호하고, 형태는 알겠는데, 안의 내용이 잘 보이지 않는 느낌! 바로 그 느낌이다!

const pig = animals.filter((animal) => animal.species === "pig")

위 코드를 보면, “animals" 배열 중에서 종이 "pig" 인 것을 골라내! 라는 것은 알 것 같다.
그런데, "filter" 메서드에서 어떻게 "pig" 인 것만 골라내고 있지? 라고 한다면, 내부 로직은 보이지 않는다.
이런 느낌을 추상화라고 할 수 있을 것 같다.

그렇다면 선언적 프로그래밍이란?

앞서 추상화를 하게되면, 큰 형태는 보이지만, 내부에서 어떻게 돼지를 골라내고 있는지에 대해는 자세히 나타내지 않게 된다고 했다.

const pig = animals.filter((animal) => animal.species === "pig")

위 코드는 “내가 이제 돼지를 필터를 할거다!" 라는 목적을 선언하고 있다.
이러한 코드 작성 방식을 선언적 프로그래밍이라고 할 수 있다.

“동물 배열을 하나씩 돌면서 종이 돼지인 것만 return한다 ”라는 어떻게 보다
“나 이제 돼지 필터 한다!” 라는 목적만을 명시해서 코드의 가독성이 높아졌다.

그런데 여기서 나는 의문을 느꼈다.
그러면 결국 filter 라는 메서드를 구현하기 위해서는
명령형 프로그래밍이 어딘가에 존재해야하는 거 아닌가? 라고 말이다.

어떻게 돼지를 필터할건데? 라는 아래와 같이 명령형 로직은 사실상 필요한 것이 사실이다.

function filterPig(arr) {
  const result = [];
  
  for (let i = 0; i < arr.length; i++) {
    if (arr[i].species === "pig") {
	     result.push(arr[i])
    }
  }
  
  return result;
}

이러한 명령형 로직은 네이밍을 통해 어느정도 목적성을 띌수는 있지만, 가독성이 비교적 떨어지고,
다른 종에 대한 대응이 유연하지 못하여 재활용성도 떨어지게된다.
그렇다면, 다른 종에 대해서도 유연하게 반응할 수 있는 형태의 customFilter는 아래처럼 작성할 수 있을 것 같다.

function customFilter(arr, callback) {
  const result = [];
  
  for (let i = 0; i < arr.length; i++) {
    if (callback(arr[i])) {
      result.push(arr[i]);
    }
  }
  
  return result;
}

이 처럼 어떠한 arr와 조건을 담는 callback 함수를 넘겨받아 유연성을 높혔고,
모듈화 시켜 내부로직으로 따로 관리하며, 필요한 곳에서 꺼내서 목적성과 재활용성이 높게 사용가능하다.
선언형으로 말이다! (아래 코드는 메서드지만,,,)

const pig = animals.filter((animal) => animal.species === "pig")

내가 이해한 선언형을 한 문장으로 표현한다면, 아래와 같이 이해했다.

명령형으로 작성되는 내부 로직을 숨기고, 목적만을 나타내는 코드의 추상화 형태이다

profile
FrontenDREAMER

0개의 댓글