Skip to content

Latest commit

 

History

History
198 lines (141 loc) · 13.6 KB

note.md

File metadata and controls

198 lines (141 loc) · 13.6 KB

주제

발표자

  • 양유성

참여자

  • 김라희, 김주원, 안소현, 양유성, 이상아, 이소윤

내용

1. OOP

OOP는 Object Oriented Programming의 약자이며, 한국어로는 객체 지향 프로그래밍이라고 부를 수 있다. OOP를 이해하기 위해서는 우선 두 가지에 대한 개념을 이해할 필요가 있다. 객체지향이다.

지향이란 무엇인가?

객체에 대해 얘기하기 전에 지향에 대해 얘기해보자한다. 사전적으로 지향이라는 단어는 어떤 목표로 뜻이 쏠리어 향함. 또는 그 방향이나 그쪽으로 쏠리는 의지.(출처)를 의미한다.

프로그래밍에서의 지향 또한 다르지않다. 여러분 스스로가 추구하는 개발적 목표가 있다면 여러분은 이미 무엇인가에 대한 지향적 프로그래밍을 하고있는 것이다. 코드를 짤 때 대소문자를 어떻게 작성할 것인지, 함수별 구현 범위를 어디까지로 할 것인지, 클래스를 사용할 것인지, 이 모든 것들이 결국에는 여러분이 지향하는 무엇인가에서 파생되는 것이다. 다만, 모든 일에는 효율이 있다. 여러분이 추구하고 있는 방식이, 어쩌면 가장 효율적이지 않은 방식일지도 모른다. 따라서 우리 나보다 더 많은 것을 배운, 더 똑똑한 개발자의 지향을 따라 배워볼 필요가 있다.

오픈 소스 생태계에서는 수 많은 개발자가 스스로 생각하는 지향적 관점을 공유하고 있다. 그렇게 공유된 다양한 지향적 관점 중 하나가 객체 지향적 관점이다. 도대체 객체 지향은 무엇이길래, 개발자들이 이토록 원하는 것일까? 그 이유를 알아보기전에 객체가 무엇인지부터 알아보도록 하자.

객체란 무엇인가?

당연하게도 객체 지향적 프로그래밍을 위해서는 객체를 알아둘 필요가 있다. 우스개로 객체 지향 프로그래밍을 배울 때, 붕어빵과 붕어빵 틀에 대해서 많이들 듣는다고 한다. 과연 이 예시가 객체 지향을 이해하는데 좋은 예시가 될 수 있을까? 나는 아니라고 생각한다. 객체 지향적 프로그래밍에서는 객체간의 유기적인 관계가 중요한데, 붕어빵은 우리가 먹으면 없어지는 단 하나의 객체일 뿐이다.

객체는 말하자면 어떠한 물체나 개념을 추상적으로 표현한 것이다. 어려워 보이는 표현이다. 그렇지만 어떻게보면 가장 우리에게 친숙한 방법이 바로 추상화다. 가령 걷는다라는 행위에 대해서 생각해보자. 이 행위는 인간 뿐 아니라 코끼리, 기린 등 다른 동물에게도 적용될 수 있다. 즉 우리는 코끼리가 걸을 때나, 사람이 걸을 때나 혹은 어던 동물이 걸을 때나, 이 모든 상황에서 걷는다 라는 단어로 대상의 행위를 표현한다. 이런 예시에서 우리는 걷는다라는 행위가 모든 다리 달린 동물에 대해서 추상화 되어있다고 표현할 수 있다. 이것을 코드로는,

person.walk();
giraffe.walk();
elephant.walk();

위와 같이 표현할 수 있다.

그렇다면 walk()라는 함수로 표현되는 행위는 객체가 될 수 있을까? 그렇다. 그럼 person, giraffe, elephant라는 물체도 객체가 될 수 있을까? 물론 그렇다. 그런데 생각해보면 행위야 추상적인 개념이 될 수 있다쳐도 물체는 실제로 존재하는 것인데 어떻게 추상화할 수 있는지 의문이 들 수 있다. 사실 이 물체 혹은 인스턴스야 말로 진정한 추상화의 집합이라고 할 수 있다.

인스턴스

나는 방금 인스턴스라는 단어를 썼다. 그렇다면 인스턴스란 무엇이고, 그 인스턴스는 어떻게 생성되는걸까?

홍길동이라는 사람이 있다고 가정해보자. 홍길동은 어떠한 정보를 지닐 수 있는가? 이름, 나이, 생일, , 몸무게 등을 지닐 수 있을 것이며, 문화, 지역마다 고유한 특성 또한 지닐 수 있을 것이다. 예를들어 홍길동이 한국인이라면 주민등록번호를 가질 수 있다. 생각해보면 나이, 생일, 주민등록번호라는 개념은 세상이 만들어질 때 함께 존재하던 개념이 아니다. 이는 사람이 삶을 더 편리하게 살아갈 수 있도록 만든 추상적인 개념이다. 즉, 홍길동은 사람이 가질 수 있는 추상적인 개념으로 이루어진 정보를 지니고 태어난 것이다.

그렇다고해서 추상적 개념에 대한 값이 오직 수치로 표현될 수 있는 값만을 가르키는 것은 아니다. '객체란 무엇인가?'에서 설명하였듯, 어떠한 행동 또한 추상적 개념이 될 수 있다. 만약 홍길동이 걷는다, 잔다 등의 행위를 할 수 있다면, 그 행동 또한 추상적 개념이 될 수 있기에, 우리는 홍길동이라는 인스턴스가 단순한 수치적 값인 속성(=Attribute) 뿐만 아니라 비수치적인 값인 명령(=Function) 또한 지닐 수 있다는 걸 알 수 있다.

따라서, 홍길동은 추상적 개념(나이, 몸무게 등)에 대한 값(18살, 55kg)이나 정의된 명령(잔다, 걷는다 등)을 지닐 수 있는 어떠한 물체, 즉, 인스턴스(=Instance)라 할 수 있다.

클래스

위에서 설명하였듯이, 인스턴스는 어떻게 보면 실질적인 존재라 할 수 있다. 하지만 우리가 알다시피, 모든 사람은 홍길동이라는 인스턴스와 유사하거나 같은 Attribute와 Funtion을 가질 수 있다. 즉 우리는 사람이 지닐 수 있는 특정 값들을 미리 정의해둘 필요가 있다. 미리 정의해둔다면, 적어도 우리가 사람에 해당하는 인스턴스를 만들 때, 정의해둔 코드를 활용하여, 재사용성을 높힐 수 있기 때문이다. 이는 다음과 같은 코드로 표현될 수 있다.

사람 홍길동 = new 사람();
사람 원빈 = new 사람();

사람이라는 클래스를 따르는 홍길동, 원빈 인스턴스를 만드는 예제이다.

예시) 붕어빵 틀과 붕어빵?

많은 사람들이 붕어빵 틀과 붕어빵을 클래스와 인스턴스에 각각 비유하곤 한다. 하지만 이는 틀린 비유라 할 수 있다. 다음 코드를 보자.

붕어빵틀 붕어빵 = new 붕어빵틀();

해당 코드는 마치 붕어빵틀이 가질 수 있는 Attribute와 Function을 붕어빵이 가질 수 있는 것처럼 작성되어있다. 하지만 그 둘은 엄연히 다른 속성을 지녀야한다. 애초에 붕어빵 틀은 먹을 수도 없으니까.

위 코드는 아래처럼 고쳐질 수 있을 것이다.

붕어빵 크림붕어빵 = new 붕어빵("크림");
붕어빵 초코붕어빵 = new 붕어빵("초코");

이제 클래스와 인스턴스에 대해서 어느정도 이해가 가는가?

다시, 객체란 무엇인가?

위 문단에서 나는 객체를 어떠한 물체나 개념을 추상적으로 표현한 것라고 표현했다. 이를 조금 더 개발 용어처럼 표현하자면, 어떠한 값을 추상적 Attribute와 Function을 통하여 표현한 것이라고 말할 수 있겠다(또, 보편적으로 객체는 인스턴스와 같은 의미로 쓰이곤 한다).

상속과 생성

이제 우리는 클래스가 무엇인지 알고, 인스턴스(혹은 객체)도 무엇인지 안다. 이것만 알면 상속과 생성도 크게 어렵지 않을 것이다.

상속은 말 그대로 상위 클래스의 attribute나 function을 그대로 이어받는 것이다. 사람과 강아지는 크게 동물이라는 클래스로 묶일 수 있다. 동물이기에 심장(attribute)이 있고, 움직(function)일 수 있다. 즉, 사람과 강아지 클래스 모두, 동물이라는 클래스를 상속받는다고 할 수 있다.

생성은 클래스에 기반하여 새로운 인스턴스를 만드는 행위다.

사람 홍길동 = new 사람();

위 코드에서 홍길동은 사람이라는 클래스에 기반하여 생성된 인스턴스라고 할 수 있다.

왜 객체 지향 프로그래밍을 써야하는가?

사실 이렇게 설명해도 아직까지 객체에 대한 개념을 확실히 잡긴 어려울지 모른다. '아니 그러면 우리가 코드를 짤 때 모든걸 우리 주변에 있는 것처럼 생각하고 짜야해요? 이미 그러고 있잖아요!' 라고 말하고 싶을 수도 있다. 하지만 여러분의 코드를 다시 한 번 들여다보면, 절대 코드 우리 주변에 있는 것처럼 작성하고 있지 않다는 것을 알게될 것이다. 예를들어, 엑셀과 브레이크를 사용할 수 있는 자동차가 있다고 가정하고, 자동차가 최대 속도인 180km/h까지 속도를 올리고 브레이크를 밟는 코드를 작성한다고 해보자.

class Car{
    int speed=0;
    int maxSpeed=180;
}

Car car1 = new Car();
car1.speed = 0;

for (int i = 0; i < 180; i++) {
	car1.speed = i;
}

while(car1.speed != 0) {
	car1.speed -= 1;
}

물론 예시를 위해 일부러 코드를 이상하게 짜긴 했지만, 충분히 존재할 수 있는 코드다. 이제 이걸 조금 더 객체 지향적으로 바꿔보자.

class Car{
    int speed=0;
    int maxSpeed=180;

    void accelToMaxSpeed() {
    	while (speed < maxSpeed) {
    		speed += 1;
    	}
    }

    void break() {
		while (speed > 0) {
    		speed -= 1;
    	}
    }
}

Car car1 = new Car();
car1.accelToMaxSpeed();
car2.break()

이렇게 위와같이 바꾼다면 코드의 유지보수나 클래스의 재사용성이 훨씬 좋아질 것이다.

2. FP

함수형 프로그래밍에서의 함수

함수란 일종의 블랙박스다. 어떠한 값을 넣으면 내부가 어떻게 돌아가는지는 모르지만 특정 결과값이 나온다는 뜻이다. 조금 더 수학적으로 풀어 설명하자면, 정의역 집합 A와 공역 집합 B가 있을 때, 정의역의 값에 일대다로 대응되는 치역 집합 C를 나타내주는 연산의 집합이라고 할 수 있다.

함수형 프로그래밍에서의 함수는, 이런 수학적 함수의 의미와 더불어 순수 함수의 의미를 지니고 있기도 하다. 순수 함수란 무엇일까?

순수 함수란?

순수 함수가 있다면 순수하지 않은 함수도 있을까? 당연하다. 순수 하지 않은 함수는 비순수 함수라 불린다. 이때 순수하다는 것은 크게 두 가지 기준으로 분류될 수 있는데, 먼저 외부의 변수의 값 변경하지 말아야하며, 같은 인자에 대해서는 항상 같은 값을 반환해야한다.

예시를 들어보도록 하겠다.

덧셈 함수 add()를 생각해보자.

public int result = 0;
int a = 3;
int b = 5;

void add(int a, int b) {
	result = a + b;
}

위 함수 add()는 순수함수가 아니다. 외부 변수인 result의 값을 바꾸었기 때문이다. 따라서 순수 함수를 만들기 위해서 위 코드를 아래와 같이 수정할 수 있다.

int a = 3;
int b = 5;

int add(int a, int b) {
	return a+b;
}

int result = add(a,b);

위 함수 add()는 외부의 값을 바꾸지 않았고, 인자 값(a, b의 값) 또한 바꾸지 않았기 때문이다. 그렇다면 객체의 값 변경에 대해서는 어떻게 시도할까? Object라는 객체 안의 val 값을 바꾸는 코드를 생각해보자.

Object obj1 = new Object(6); // val 값을 6으로 지정

void change(Object obj, int val) {
	obj.val = val;
}
change(obj, 5);

위 코드에서 change()는 obj의 값을 바꾸었기 때문에 순수 함수가 될 수 없다. 따라서 순수 함수로 바꾸려면,

Object obj1 = new Object(6); // val 값을 6으로 지정

Object change(Object obj, int val) {
	return new Object(val);
}
obj1 = change(obj, 5);

이렇게 바꿀 수 있다.

위 코드에서 change()는 obj의 값을 직접적으로 바꾸지 않고 참조만 헀다. 따라서 이 때, change()는 순수 함수가 될 수 있는 것이다.

왜 함수형 프로그래밍인가?

가장 마지막 코드를 보면 되게 비효율적으로 보인다. 하지만 결국 함수형 프로그래밍의 궁극적인 장점은 바로 모듈화와 재사용성이다. 함수형 프로그래밍에서의 함수는 어떤 변수의 값이 인자로 들어와도 항상 기대한 값을 반환한다. 외부의 상황에 따른 변인을 고려하지 않아도 된다는 뜻이다. 이는 곧, 프로그래머의 디버깅 작업 및 유닛 테스트 작업 과정을 훨씬 쉽게 만들어주며, exception에 대해서도 훨씬 자유로울 수 있다는 의미다.

3. Prototype

Prototype이란, class 기반의 객체 지향 언어가 아닌 자바스크립트에서, 객체 지향적 관점의 프로그래밍을 할 수 있도록 도와주는 개념이다. class 기반의 객체 지향 언어는 상속과 생성을 통해 클래스와 인스턴스를 활용했다. 하지만 자바스크립트에는 클래스라는 개념이 존재하지 않는다. ES6 이후 생기긴 했지만, 이것은 문법적으로만 class라고 표현되지 기존의 클래스와는 조금 다른 의미를 지닌다. 따라서 자바스크립트는 class와 상속 대신 prototype과 위임이라는 개념을 추가했다. prototype은 간단히 말해 객체가 지닐 수 있는 속성들의 집합을 의미한다. 우리가 새로운 객체 A를 만든다고 했을 때, A는 최상위 객체인 Object로부터 prototype 값을 가져와서 새로운 객체를 만들 때 활용한다.

추가적인 예시는 다음 주차 스터디에 포함되어있다.