Computational Design
(1) 데이터 그리고 그 데이터를 프로세스 하는 (2) 알고리즘을 하나로 묶을 수 있을까?
데이터 + 알고리듬 =?
컴퓨테이셔널 디자인을 하다면, 여러분들은 (1) 데이터로 무언가를 만들고, 그리겠죠! 지오메트리 데이터나 혹은 색이나 움직임 데이터가 있다고 가정해 보면, 우리는 각각의 데이터를 수정하고 업데이트하려고 하는 (2) 알고리듬이 필요할 거예요.
만약 데이터와 그에 맞는 알고리듬을 하나로 묶어서 관리할 수 없을까요? 만약 그렇다면 굉장히 효율적이게 코드를 관리할 수 있겠죠?
프로그래밍의 패러다임중 하나인 오브젝트 중심 프로그램(OOP: Object Oriented Programming)의 클래스(Class) 개념을 활용하면, 쉽게 구현할 수 있어요!
Class를 알아보자!
오늘은 쉽게 이해하는 클래스라는 제목으로 이야기를 나누어 보려고 합니다. 컴퓨터공학을 전공하지 않은 디자이너들에게는 좀 생소한 개념일 수 있어요. 일반적으로 생각을 오브젝트 중심으로 하지는 않기 때문이죠. 디자인 전공 학생들이 많이 어려워한 다는 것을 느꼈죠. 어떻게 설명하면 좀 편하게 받아들일 수 있을까 고민을 했었었죠.
결국, 프로그래밍을 한다는 것은, 컴퓨터 프로그래밍 언어를 활용해 어떤 문제들을 수체계로 기술하고 해결해 나가는 것으로 볼 수 있죠. 그런 관점에서 말씀드렸듯이 데이터가 존재하고, 데이터를 처리할 수 있는 하나의 알고리즘과 그 순서도가 필요하죠.
즉, 프로그래밍은, 데이터와 데이터를 프로세스 하기 위한 알고리즘의 인스트럭션(Instruction: 명령서)으로 볼 수 있는 것이죠. 이러한 과정에서 클래스가 무엇인지 어떤 방식으로 프로그래밍을 할 수 있는지 알아보는 시간을 가져 봐요.
데이터(Data)
전투 게임을 만들어봐요. 그럼 먼저 사람을 프로그래밍해야겠죠, 즉, 사람을 표상할 수 있는 데이터들이 필요하겠죠? 예를 들면, 이름, 나이, 키, 몸무게, 출신, 펀치력, 방어력 등등등. 우리가 현실적으로 사람이라는 대상에 부여할 수 있는 모든 형이상학 형이하학적인 내용도, 데이터로 저장할 수 있겠죠. 특별히 우리는 전투 게임이기 때문에 펀치력과 방어력도 가질 수 있게 프로그래밍을 해요. 물론 펀치력도 정해진 숫자로 사용하기보다, 몸무게와 팔 길이 그리고 근력의 변수 혹은 파라미터가 있다면, 그것들의 합과 곱으로 특정 펀치력을 산정할 수 있겠죠. 예를 들면, 아래와 같이 표현할 수 도 있겠죠.
팔 길이 = 300
근력 = 100
몸무게 = 80
훈련도 =2.35
펀치력 = (팔 길이 + 근력 + 몸무게) * 훈련도
알고리듬(Algorithm), 액션(Action, behavior)
데이터를 위에서 정의했으니, 이번에는 그 데이터를 수정할 수 있는 알고리듬, 즉 게임상의 특정 액션 등을 정의해 보죠. 예를 들면 뛰다, 걷다, 쉬다, 말하다, 싸우다 등등이 있겠죠. 이러한 알고리듬의 특징은 어떤 계산이 실행되고 그 과정 혹은 결과로 데이터가 업데이트가 되는 것이죠! 다음과 같이 표현할 수 있겠네요
//..... 함수의 정의
function Eat(weight, food){
if(food == "고기") {
return weight * 1.2; // food가 고기 라면, 1.2를 곱해서 반환
} else {
return weight * 1.05; // food가 고기 아니라면, 1.05를 곱해서 반환
}
}
//..... 함수의 호출
weight = 70
food = "고기"
weight = Eat(weight, food )
설명을 하면, Eat이라는 함수, 즉 큰 의미에서의 알고리즘으로서, 어떤 액션을 정의하는 함수를 선언해요. 그 함수는 두 개의 파라미터를 받죠. food의 값이 "고기"와 같다면, 주어진 첫 번째 파라미터(Parameter))인 weight을 1.2로 곱해서 반환을 하는 것이죠. 그렇지 않으면, 1.05를 곱해서 반환을 하는 것이죠.
함수의 호출로는, weight과 food를 eat의 전달 인자, 즉 아규먼트(Argument))로 전달을 시켜주는 것이죠. Eat함수의 결괏값은 다시 weight에 업데이트가 되겠죠. 우리가 일반적으로 프로그래밍한다고 하면, 변수를 선언하고, 변수를 수정하는 특정 함수를 만들어서 사용한 예 일 수 있어요.
! 매개변수(파라미터:Parameter)와 전달 인자(아규먼트:Argument)- link
Array & List
만약, 사람의 수가 몇 백, 천명이 넘어간다면 어떨까요? 어레이(Array) 혹은 리스트(List)로 여러 명의 사람들을 담으면 돼요! 그리고 Loop를 활용해서 여러 개의 데이터를 처리하면 되겠죠.
더 복잡한 관계성을 계산해야 한다면?
그러나, 단순히, Eat 뿐 아니라, 서로 격투를 통해서 A가 B에게 데이 미지를 입히고 몇 번의 펀치와 킥으로 승리를 했는지, 혹은 토너먼트 상에서 어떤 상대를 어떤 히스토리로 이기고 왔는지 등등을 추적하고, 계산하고 싶다면, 앞의 방식으로 구현을 한다면, 정말 말도 안 되게 복잡하고, 실수도 많아지겠죠.
Class / 클래스
이럴 때, Class를 잘 활용할 수 있어요. 일반적으로 클래스를 선언할 때, 두 가지 정보를 담을 명시 할 수 있죠. (1) 데이터 (2) 함수, 즉 알고리듬이라 볼 수 있어요.
class Person {
int height = 170;
int weight = 70;
string name = "namju";
bool live = true;
eat(weight, food){
if(food == "고기") {
this.weight *= 1.2;
return this.weight;
} else {
this.weight *= 1.05;
return this.weight
}
}
}
자 위에서 처럼, Person이라는 클래스를 선언했죠, 물론 언어마다 실제 이행(Implementation)에 단계에서는 다소 다를 수 있지만 큰 틀과 개념은 같아요. 데이터를 담을 수 있죠. 키와 몸무게, 이름과 살아있는지 아닌지의 여부를 블리언(Boolean) 값으로 담아 놨어요. 그리고, eat이라는 함수를 통해서 내부적으로 가지고 있는 weight을 수정하는 알고리듬도 포함하고 있죠
이제, Person이라는 객체를 만들면 자동으로 그 안의 데이터들이 정의가 돼있고. 그 데이터를 업데이트할 수 있을 뿐 아니라, 그 데이터를 프로세스 할 수 있는 함수도 함께 묶어서 제공된다는 것이죠.
파이썬을 활용한 class 연습, 토넌 먼트 전투 게임의 예를 들면,
Person, History, Round 그리고 Game 클래가 있죠. Person 클래스는 토너먼트의 History를 가지고 있고 각각의 History에서 다른 파이터와의 대결을 Round로 저장하고 있게 되는 것이죠. 이러한 토너먼트의 큰 틀은 Game에서 Person클래스를 조합함으로써 구현한 것이 되는 거죠. 중요한 지점은, 각각의 클래스에서 어떤 데이터와 어떤 함수가 있는지를 참조해 보시면 좋을 것 같아요.
추상화
자동차 클래스를 만들어 볼까요?
class Car {
Vector3 position; // 위지(position) 데이터
Vector3 direction; // 방향 데이터
float speed; // 속도 데이터
go(float speed){
// TODO : 속도에 맞게 포지션 데이터를 업데이트한다
}
stop(){
// TODO : 속도에 맞게 감속하며, 포지션 데이터를 업데이트한다
}
}
포인트(Point) 클래스를 만들어 볼까요?
class Point {
Vector3 position; // 위치 데이터
Color color; // 색 데이터
float radius; // 포인트의 크기
distanceTo(Point other){
// TODO 주어진 다른 포인트와의 거리를 계산 후, 결괏값을 반환(리턴: return) 한다.
}
moveX(float value){
// TODO 주어진 값에 따라, 위치 데이터를 X축에 따라 이동시킨다.
}
moveY(float value){
// TODO 주어진 값에 따라, 위치 데이터를 Y축에 따라 이동시킨다.
}
moveZ(float value){
// TODO 주어진 값에 따라, 위치 데이터를 Z 축에 따라 이동시킨다.
}
}
폴리라인(Polyline) 클래스를 만들어 볼까요?
class Polyline {
Vector3 center; // 폴리 라인의 중심점
Vector3 [] points; // 폴리 라인의 접점들
bool isClosed; // 열린 혹은 닫힌 폴리 라인 상태
addVertex(Vector3 other){
// TODO 주어진 벡터를 폴리 라인의 정점으로 추가한다.
}
getArea(){
// TODO 폴리 라인의 면적을 계산하여 반환한다.
}
closePolyline(){
// TODO 폴리 라인 첫 점과 끝점을 연결하여 라인을 닫는다.
}
}
뿐만 아니라, 그래프(Graph) 혹은 매트릭스 데이터(Pixel or Voxel) 구조 등등 복잡한 디자인을 위한 데이터 구조를 만들 때 저는 항상 클래스를 활용해요. 왜냐면, 추상화시키기가 편하고, 알고리즘 짜기도 훨씬 직관 적 여지거든요. 재활용성도 높아지고, 유지/보수 즉 디버깅에 편할 수 있기 때문이죠.
프로그래밍의 패러다임
물론 클래스를 사용하지 않고도, 거의 모든 것이 구현이 가능하죠, 스스로가 가장 익숙한 방법으로 하는 것이 방법일 수 있어요. 결국, 생각을 쪼개고, 나누어, 계산 가능한 형태로 문서를 인스트럭션을 작성한다는 개념으로는, 스스로가 최고의 실력을 발휘하는 방법으로 하는 것이 맞겠죠. 하지만 프로그래밍에는 다양한 패더 라임이 있고, 각각의 패러다임은 특정 문제들을 굉장히 합리적으로 효율적으로 기술하고 계산에 특화되어 있다고 볼 수 도 있어요.
객체지향 프로그래밍
OOP(Object Oriented Programming) 패러다임이 있어요. 클래스(Class)를 활용하여 객체(Object)와 인스턴스(Instance), 캡슐화(Encapsulation), 추상화(Abstraction), 상속(Inheritance) 다형성(Polymorphism)들의 개념을 활용하며 프로그래밍하는 것이죠. 이러한 객체지향 프로그래밍을 할 때, 오늘 우리가 알아본 클래스(Class)의 이해가 선행돼야 해요. OOP는 더 복잡하고 난해한 계산들을 보다 직관적이고 효율적으로 프로그래밍할 수 있는 여러 가지 패턴과 프로그래밍 구조를 제공/지원하고 있죠. 특별히 디자인 시스템을 구축하고, 복잡한 연산 및 최적화를 디자인하는 경운 데이터가 흐르는 환경을 만들어야 하는데, 이런 경우도 OOP를 잘 이해하고 있어야 해요.
대부분의 모던 랭귀지(Modern programming languages)를 보면, 가령 파이썬 자바 혹은 c#의 경우 주요 데이터들이 클래스(Class)로 만들어져 있다고 보실 수 있어요. 예를 들면, 문자열(String) 하나를 만들더라도 문자 클래스(Class)의 오브젝트(Object)로 / 인스턴스(Instance)로 만들어지는 것이죠. 그리고 많은 라이브러리(Library)도 클래스(class)의 형태로 제공되는 경우도 많아요. 혹은 라이노(Rhino), 마야(Maya), 맥스(3ds max) API를 봐도 클래스 형태로 지원되는 경우도 쉽게 찾아볼 수 있어요. 즉 데이터와, 그에 맞는 알고리듬을 효율적으로 정리하고 제공할 수 있다는 장점이 있기 때문이라고 생각해요.
요약
클래스를 설명할 수 있는 여러 가지 방법이 있겠죠. 이번 시간에는 데이터와 그 데이터를 수정하는 행동으로 나누어, 클래스를 설명을 봤어요.
참조:
파이썬을 활용한 class 연습, 전투 토넌 먼트 게임
파이썬을 활용한 class 연습, Graph 만들기 그리고 시각화
이남주 / NJ Namju Lee / nj.namju@gmail.com
MDes;Harvard, MArch;UCB, B.S;SNUST, Research Fellow; MIT
Architecture design, Computation, Visualization specialist
NaverBlog / GitHub / CodePen / Youtube(eng) / Youtube(kr)