공학/에세이

쉽게 설명하는 '객체지향 프로그래밍(OOP)'

카카루1331 2020. 8. 17. 09:53

먼저 뻔한 흐름으로 글을 시작해보겠습니다.


객체 지향 프로그래밍이란 무엇인가?

Object Oriented Programming 줄여서 OOP.

객체지향 프로그래밍이란 기존 절차지향 방식에서 벗어나 프로그램을 객체 단위로...

사전적 정의는 틀리지 않았습니다.
하지만 맞는 말인데 멍멍이 소리이기도 합니다.
왜냐구요? 독자는 저 말을 이해할 백그라운드가 없어요.
그러니 멍멍이 소리로 들릴 수밖에요.
처음부터 저거 읽고 객체지향이 뭔지 알면 천재죠.

조금 다른 방식으로 접근해봅시다.
저는 어떤 개념을 이해하는 효과적인 방법이 있다고 생각합니다.
그 방법 중 하나는 해당 개념의 역사를 살피는 것이라 생각합니다.
등장 배경이라든지 부상하게 된 계기 같은 것들이요.


프로그램의 부품화

 

#include <stdio.h>

int main() {
  int i;

  for (int dan = 1; dan <= 9; dan += 3) {

    for (i = 1; i <= 9; i++) {
      printf("%d * %d = %-2d	%d * %d = %-2d	%d * %d = %-2d\n", 
        dan, i, (dan*i), dan+1, i, (dan+1)*i, dan+2, i, (dan+2)*i);
      }
      
      printf("\n");
  }
}

 

처음 프로그래밍을 할 땐 일단 돌아가는 걸 만드는 게 목표입니다.
그러기 위해 메인 함수에 명령어를 주욱 적어 내려갑니다.
이런 방식이 처음에는 괜찮습니다.
하지만 프로그램은 점점 규모가 커지기 마련입니다.
이에 따라 메인 함수는 해독이 불가능한 지경에 이르게 됩니다.

여기에 대한 솔루션이 있습니다.

 

"기능 별로 코드를 분리하자!"

 

#include <stdio.h>

void gugudan(int, int);

int main() {
  gugudan(4, 12);
}

void gugudan(int dan_start, int dan_end) {
  int i;

  for (int dan = dan_start; dan <= dan_end; dan += 3) {

    for (i = 1; i <= 9; i++) {
      printf("%d * %d = %-2d	%d * %d = %-2d	%d * %d = %-2d\n", 
        dan, i, (dan*i), dan+1, i, (dan+1)*i, dan+2, i, (dan+2)*i);
      }
      
      printf("\n");
  }
}

프로그램을 부품화 함으로써 얻을 수 있는 이점은 아래와 같습니다.

1. 코드의 길이가 줄어듭니다.
무려 한 줄!

2. 코드의 재사용성이 올라갑니다.
gugudan 함수는 매개변수 두 개를 받습니다.
이렇게 함으로써 구구단 출력 범위를 조정할 수 있습니다.
전에는 1~9단 고정이었는데 반해서요.

3. 코드의 의미가 분명해집니다.
두 번째 프로그램은 의미 파악이 쉽습니다.
함수 이름이 행위의 단서를 제공하기 때문입니다.


이에 반해 첫 번째 프로그램은 의미 파악이 어렵습니다.
좀 더 구체적으로는 그것을 이해하는데 자원이 소모됩니다.
프로그래머의 인지 자원이 말이지요.


for 문이 나오고 그 안에는 또 for 문이 나옵니다.
"이걸 왜 이렇게 썼을까? 또 뭐 때문에 썼을까?"
라는 물음에 답하기 위해선 코드를 일일이 읽어야 합니다.

 

행위 하는 객체가 있다

그러나 함수만으로는 표현하기 어려운 것들이 있습니다!
예를 들어 '사람'을 표현해야 한다고 해봅시다.
이름은 char, 나이와 신장은 int...
표현할 게 많을수록 변수를 관리하는데 힘이 듭니다.

"구조체를 쓰면 되지 않나요?"


맞습니다. 구조체를 써도 됩니다.

한편 사람은 동적인 존재입니다.
이름, 나이, 신장 등의 상태 외에도 행위를 합니다.
숨을 쉬거나 요리를 하는 것처럼요.


요컨대 객체는 상태+행동입니다.
변수+함수 라고도 할 수 있겠네요.
뭔가 구조체 + 함수를 깔끔하게 담을 순 없을까요?

객체와 행동의 관계를 코드로 담을 수 있으면 좋을 거예요.
언어 차원에서 이러한 관계를 명시적으로 나타낼 수 있다면 더더욱 좋겠어요!
이를 맛보기 위해 자바로 넘어갑시다.


클래스: 행위와 상태를 모두 담다

사칙연산 함수를 만든다고 가정해보죠.
우리의 관심사는 구현이 아닙니다.

이것을 관리하는 것에 있어요.
네 가지 행위를 무언가 하나의 틀에 묶고 싶은 겁니다.
클래스는 이런 우리의 관심사를 도와줍니다.


Calculator 클래스 내부에 메소드를 만들면 되거든요.

이렇게 계산기 담당 설계도를 미리 만들어 두고,
해당 기능이 필요할 때에는 메소드를 가져다 쓰기만 하면 됩니다.

 

public class Calculator {
	
	public static int addNum(int num1, int num2) {
		return num1 + num2;			
	}
	
	public static int subNum(int num1, int num2) {
		return num1 - num2;
	}
	
	public static int mulNum(int num1, int num2) {
		return num1 * num2;
	}
	
	public static int divNum(int num1, int num2) {
		return num1 / num2;
	}

}

 

클래스는 객체와 행위를 담는 틀입니다.
일종의 설계도라고 할 수 있습니다.
미리 설계도를 만들어 놓고 사용할 때는 인스턴스, 즉 객체를 만듭니다.
그 객체에 담긴 정보(상태)를 이용하거나 위에 코드처럼 객체의 행위를 이용할 수도 있습니다.

 

public class CalculatorMain {

	public static void main(String[] args) {
		System.out.println(Calculator.addNum(10, 5)); // 15
		System.out.println(Calculator.subNum(10, 5)); // 5
		System.out.println(Calculator.mulNum(10, 5)); // 50
		System.out.println(Calculator.divNum(10, 5)); // 2
	}
	
}

그래서 객체지향이 뭡니까!

객체지향이요?

객체 지향 프로그래밍(영어: Object-Oriented Programming, OOP)은 컴퓨터 프로그래밍의 패러다임의 하나이다. 객체 지향 프로그래밍은 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러 개의 독립된 단위, 즉 "객체"들의 모임으로 파악하고자 하는 것이다. 각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다.
출처: 위키백과


(체력 방전으로 글쓴이 도주..!)


저는 처음에 이딴 거 왜 배우나 싶었어요.
(모르면 무식하다고 하잖아요... 아, 동어반복인가?)
하지만 돌아보니 제가 어리석었단 생각을 해요.
객체지향은 충분히 값어치 있는 개념입니다.

중요한 건 객체지향으로 코드를 짜는 게 아니었던 거 같아요.
객체지향을 배우면서 알게 되는 이쪽 진영의 역사
코드를 분리하는 번뜩이는 방법론
마지막으로 생각하는 방식을 생각해 볼 수 있었다는 점?

객체지향이든 함수형이든 뭐든 좋아요!
아하하~