ex
프로그래밍 패러다임을 나누자면 이렇게 나눌 수 있다.
HOW, 어떻게 해야 하는가
컴퓨터가 해야 할 일을 정확하게 지시하기 때문에 ‘명령형’ 이라고 한다.
프로그램이 작동하는 방식을 단계별로 설명하는 것에 중점
주요 초점은 목표를 달성하는 방법 (결과가 아니라 방법!)
여기서 상태란?
시스템이 이전 이벤트 또는 사용자 상호작용을 기억하도록 설계된 경우, 기억된 정보를 시스템의 상태라고 한다. 컴퓨터 프로그램은 메모리의 저장 위치를 나타내는 변수에 데이터를 저장하고, 프로그램 실행의 특정 시점에서 이 위치의 내용을 프로그램의 상태 라고 한다.
const nums = [1,4,3,6,7,8,9,2]
const result = []
for (let i = 0; i < nums.length; i++) {
if (nums[i] > 5) result.push(nums[i])
}
console.log(result) // [ 6, 7, 8, 9 ]
// nums의 index를 1씩 늘려가는 방법으로 nums를 하나씩 순회하면서
// 항목 값을 5와 비교하고 5보다 크면 result에 넣으세요~
WHAT, 무엇을 해야 하는가
컴퓨터에게 작업을 실행하는 방법에 대한 지침을 제공하는 것이 아니라,
어떤 결과가 필요한지에 대한 지침을 제공 (방법이 아니라 결과!)
목표 달성을 위해 수행하는 작업 방법보다는 수행해야 하는 작업에 초점
const nums = [1,4,3,6,7,8,9,2]
console.log(nums.filter(num => num > 5)) // Output: [ 6, 7, 8, 9 ]
//nums에서 5보다 큰 항목 거른 결과 출력.
Procedural
명령형 프로그래밍에서 파생된 것으로, 명령들을 각 절차 단위로 묶어버렸다.
즉, 함수 기능(절차, 서브루틴)을 추가한 것이다. 최종 기능을 달성하기 위해 방법을 지시하는 것은 같지만, 큰 기능(목표)을 처리하기 위해 작은 기능(프로시저)를 구조화한다.
절차적 프로그래밍이라 해서 처음에는 순서대로 명령하는 방식인가? 싶었다.
나도 이 부분에서 헷갈렸는데, 한글화의 부작용인가보다! 프로시저 프로그래밍이라 생각하면 쉬웠다. (프로시저 : 절차적으로 처리하고자 하는 명령어들의 집합)
//흔한 자바스크립트로 케이크 만드는 방법 by 절차적 프로그래밍 (출처는맨밑)
function pourIngredients() {
// - Pour flour in a bowl
// - Pour a couple eggs in the same bowl
// - Pour some milk in the same bowl
}
function mixAndTransferToMold() {
// - Mix the ingredients
// - Pour the mix in a mold
}
function cookAndLetChill() {
// - Cook for 35 minutes
// - Let chill
}
pourIngredients()
mixAndTransferToMold()
cookAndLetChill()
Functional
함수형 프로그래밍에서의 함수는 단순한 함수가 아니다.
변수에 할당바인딩
되고 인수로 전달콜백함수
되며 심지어는 함수가 함수를 뱉어낸다합성함수
.
특별한 일급 시민(일급 객체)이 되는 것이다.
여기서 일급 객체란?
first-class citizen
,first-class object
다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체
또 염두에 두어야 할 점은 순수 함수라는 것이다. 순수 함수는 결과를 생성하기 위해 입력에만 의존하는 함수이다. 동일한 입력이 주어지면 항상 동일한 결과를 생성하며, 함수 외부의 환경을 변경하지 않는다.
let x = 10;
function addnum(y){
return x+y;
}
let x = 10;
function addnums(y, z){
x = y;
return x+y+z;
}
일급 객체 / 순수 함수 개념 + 함수형 프로그래밍에서는 대부분 함수로 작성된 프로그램을 장려한다. 위에서 작성한, 5 보다 큰 요소만 걸러내는 코드를 함수형 프로그래밍으로 바꾸면?
function filterNums(nums){
return nums.filter(num => num > 5);
}
console.log(filterNums([1,4,3,6,7,8,9,2]));
특히 여기서 쓰인 내장 함수 filter !
순수함수 개념에 아주 적합한 함수이다. 배열의 불변성을 보장하기 때문이다. 부 환경을 변경하지 않는다. map, filter, reduce 와 같은 내장함수가 주목을 받게 된 이유라고 한다.
이렇듯 함수형 프로그래밍 방식은 외부 환경을 변경하지 않기 때문에, 사이드 이펙트가 없고 프로그램을 예측하기가 쉽다 = 유지보수성도 좋다고 생각한다.
하지만, 데이터 불변성을 보장하기 위해 단점이 생기기도 한다.
데이터를 변경하려면 원본 데이터 구조를 변경하지 않고 복사본을 만들어서 작업해야 한다.
예를 들면 spread operator 를 사용하는 경우이다. 이걸 다른 관점에서 생각하면.. 쓸데 없는 메모리 사용이다.
Object-Oriented
OOP.. 많이 들어봤다. 그만큼 가장 널리 사용되는 프로그래밍 패러다임 중 하나라고 한다.
객체 지향 프로그래밍은 기능과 논리가 아닌, 데이터와 객체를 중심으로 프로그램을 설계하는 방법이다. 즉, 객체를 조작하는 데 필요한 논리가 아니라 개발자가 조작하려는 객체 자체에 중점을 둔다.
여기서 객체란, 현실에 있는 것을 추상화한 것이다. 현실에 있는 것을 특정 관점에서 바라보고 객체로 만든다.
객체 지향 프로그래밍에서는 빠짐없이 클래스가 등장하는데, 클래스는 개별 개체(entity), 특성 및 메서드에 대한 틀 역할을 하는 데이터이다. 클래스에서 생성된 개체가 인스턴스.
글로만 정리하려니 어려웠는데, 아래 케이크로 이해할 수 있었다.
// 흔한 자바스크립트로 케이크 만드는 방법 by OOP
class Cook {
constructor (name) {
this.name = name
}
mixAndBake() {
- Mix the ingredients
- Pour the mix in a mold
- Cook for 35 minutes
}
}
class AssistantCook {
constructor (name) {
this.name = name
}
pourIngredients() {
- Pour flour in a bowl
- Pour a couple eggs in the same bowl
- Pour some milk in the same bowl
}
chillTheCake() {
- Let chill
}
}
const Frank = new Cook('Frank')
const Anthony = new AssistantCook('Anthony')
Anthony.pourIngredients()
Frank.mixAndBake()
Anthony.chillTheCake()
Cook, AssistantCook 개체를 만드는 틀인 class 가 있고, 이 틀에 찍혀 탄생한 Frank 와 Anthony 는 인스턴스이다. Frank는 mixAndBake할 책임이 있고, Anthony는 pourIngredients하고 chill할 책임이 있다.
이렇듯 OOP는 책임을 명확하게 분리하여 프로그램을 쉽게 이해할 수 있으며, 코드 재사용과 유지보수가 쉽다는 장점이 있다. 그렇지만, 설계가 쉽지 않다. 예를 들면 설계 시 조작하려는 개체들을 수집하고 서로 어떻게 관련되어 있는지 식별하는 데이터 모델링 단계가 필요하다.
자바스크립트는 일급 함수를 지원하는, 프로토타입 기반, 멀티 패러다임, 단일 스레드, 동적 언어이다. 여러개의 프로그래밍 패러다임을 제공하는 프로그래밍 언어를 멀티 패러다임 언어라고 한다. 함수형, 명령형, 프로토타입의 객체지향 프로그래밍을 지원한다.
하지만. 자바스크립트에서의 OOP
자바스크립트는 초기에 클래스, 추상화, 캡슐화와 같은 복잡한 개념들을 끌고 오기 보다는 브라우저에서 가볍게 동작할 수 있는 언어로 만들어진 것이라 한다. 따라서 클래스 기반 객체지향 프로그래밍에서 얻을 수 있는 상속, 추상화와 같은 특성이자 이점들은 모두 객체, Object 로 구현되도록 하였다.
그래서 위의 짤…
All I have are objects.
객체와 생성자 함수를 활용하여 객체지향 프로그래밍을 구현할 수 있다. 또한 프로토타입을 통해 상위 객체를 참조하고, 객체를 이용해 새로운 객체를 만드는 상속을 따라할 수 있다.
function Parent(name){
this.name = name;
};
Parent.prototype.getName = function(){
return this.name;
}
function Child(name){
Parent.apply(this, arguments); // 부모에게 상속 받을 속성!
}
Child.prototype = new Parent();
const child = new Child("cszzi");
console.log(child.getName()); // cszzi
기쁘게도.. 현재는 class 표현식도 생겼고 TypeScript 로 interface 도 정의할 수 있으며, 심지어 ES2019에서는 해시(#) prefix 로 private 필드도 선언할 수 있다.
class Parent {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
};
class Child extends Parent{
sayHello() {
console.log(`${this.name} Hello!`)
}
}
const child = new Child("cszzi");
console.log(child.getName()); // cszzi
child.sayHello(); // cszzi Hello!
이렇게 .. 자바스크립트는 진정한 멀티 패러다임 언어라고 할 수 있다.
이 내용들을 공부하면서, 제목과 같이 ‘JavaScript로 프로그래밍을 어떻게 해야할까’ 에 대해 고민을 거듭하였다. 영어로 원문들을 검색해보기도 하고, 뭐가 좋은 방법일까 고민했지만 아직 공부중인 내 경험상에서는 쉽사리 답이 내려지지 않았다.
그 중 이 아티클에서 큰 도움을 받을 수 있었는데, 패러다임을 잘 선택해서 좋은 코드가 만들어 지는 것이 아니라 좋은 코드(가독성, 유지보수, 간단한 구조, 문법의 장점 활용)를 따라가면서 패러다임을 적절히 취해야 한다는 생각의 틀을 잡을 수 있었다.
패러다임을 잘 선택한다고 좋은 코드가 탄생하는게 아니다 ! (?)
특히 자바스크립트는 멀티 패러다임 언어이기 때문에, 좋은 코드를 위해 여러 패러다임을 취하는 것이 가능하다. 공부를 더 해서 이러한 언어적 이점을 잘 써먹어야겠다!
Programming Paradigms – Paradigm Examples for Beginners
What is Object-Oriented Programming (OOP)?
이 글만 잘 봐두면 면접 때, 막힘이 없을 것 같아요~👍