2D 개인 프로젝트는 모작할 것을 선택하고, 구현하고 싶은 거 3가지를 먼저 해보라고 하셨습니다.
오늘의 중요도는 '필수'
자료구조와 더불어 반드시 알아야되는 내용입니다.
회사에 다니기 위해선 필수 덕목입니다.
객체지향 프로그래밍은 확장성이 좋기 때문에 사용이 용이하다.
다형성은 같은 인터페이스를 서로 다른 동작을 할 수 있도록 만들어줄 수 있습니다.
포트폴리오를 작성할 때 잘못 작성하는 것은 캡슐화, 추상화, 다형성, 상속을 썻다. 이렇게 작성하는 것입니다. 왜냐면 객체지향 설계를 잘못하면 오히려 유지보수가 더 어려워지기 때문입니다. 그래서 어떻게 설계를 했는지 작성하는 것이 중요합니다.
결합도가 높다는 것은 코드를 수정할 때 봐야되는 부분이 많다는 것을 의미합니다. 서로 의존 관계가 강하다는 것을 뜻하며, 확장성이 떨어집니다.
그래서 전역변수를 사용하는 것을 지양하는 것도 결합도를 낮추기 위함입니다.
응집도는 하나의 코드를 작성할 때 서로 관련된 것들끼리 잘 있냐를 확인하는 것입니다.
응집도가 높다는 것은 서로 관련된 애들끼리 잘 있다.
응집도가 낮다는 것은 서로 관련된 애들끼리 잘 있지 않다.
God Object는 응집도가 낮습니다.
응집도가 낮다면 확장성이 떨어져 유지보수하기 어렵습니다.
응집도는 높게, 결합도는 낮게 설계된 코드가 잘 작성된 코드라고 할 수 있습니다.
객체지향 프로그래밍은 다형성에 의한 높은 확장성 때문에 주류가 되었습니다. 이외에도 캡슐화를 통해 마치 실세계처럼 직관적으로 모델링 할 수 있다는 장점도 있습니다.
가령 문을 설계한다고 해보겠습니다 .단순화해 모델링 하면 아래와 같습니다.

메소드를 통해 문이 가질 수 있는 기능을 표현하며, 필드는 그 기능을 구현하기 위한 데이터를 표현합니다. 그리고 추상화를 통해 사용자 입장에서 굳이 알 필요가 없는 세부사항을 숨깁니다.
위 내용은 정말 중요한 내용입니다. 개발자라면 반드시 알아야됩니다.

하지만 객체 지향으로 설계한다는 것은 무척이나 어려운 일입니다. 다시 말해 캡슐화, 추상화, 다형성, 상속을 사용했음에도 불구하고 설계를 잘못하여 유지보수가 어려운 때도 있습니다.
그러면 어떻게 해야 최대한 객체지향 프로그래밍의 장점을 누릴 수 있게 설계할 수 있을까요? 여러가지 객체지향 설계 테크닉이 있지만 그 중 책임 주도 설계(Responsibility-driven Design에 대해서 살펴보겠습니다.
책임 주도 설계는 객체가 책임지고 있는 행동과 객체 간 공유하고 있는 정보를 고려해 계악에 초점을 맞추는 것을 말합니다. 문장이 어렵죠?
이 문장의 의미를 깊이 이해하기 위해 하나씩 살펴보겠습니다.
실생활에서 우리는 어떤 문제를 해결하기 위해 협력합니다. 협력은 누군가에게 도움을 요청하는 것과 그 사람의 응답으로 구성됩니다. 그럼 여기서 요청은 누구에게 할까요? 아무에게나 하면 될까요?
아무에게나 요청한다고해서 문제가 해결되지 않습니다. 우리가 요청하는 이유는 그 문제를 해결할 수 있는 역할을 수행하리라 믿기 때문입니다. 그래서 협력에 성공하려면 특정한 역할을 맡은 각 개인이 얼마나 요청을 성실히 이행할 수 있는가에 달려있습니다.
이를 소프트웨어에 빗대어보겠습니다. 객체지향 프로그래밍은 객체를 중심으로 프로그램을 작성하는 것입니다. 따라서 객체는 소프트웨어의 기능을 구현하기 위해 협력한다는 것을 알 수 있습니다.
소프트웨어의 기능은 더 작은 책임으로 분할되고 책임은 적절한 역할을 가진 객체에 의해 수행됩니다. 따라서 객체지향 설계는 적절한 객체에게 적절한 책임을 부여하는 것에서 시작됩니다. 책임은 객체지향 설계의 품질을 결정하는 중요한 요소이며, 역할은 유연하고 재사용 가능한 협력 관계를 구축하는데 중요한 설계 요소입니다.
협력은 요청과 응답입니다. 두가지 조건이 하나라도 성립되지 않으면 그것은 협력이 아닙니다.
기업으로 빗대어 보자면 경영진은 경영을 잘해야하고, 실무자들은 실무를 잘해야하고, 관리자는 관리를 잘해야 기업이 성장하고 돈을 벌 수 있는 것처럼 객체지향 설계 역시 각각의 역할에 맞게 충실하게 실행되어야합니다.
객체지향 프로그래밍에서 말하는 객체(Object)란 흔히 상태(State)와 행동(Behavior)을 함께 지닌 실체*라고 일컬여집니다.
*코드로는 상태를 필드로, 행동을 메소드로 작성합니다.
풀어서 이야기하자면 객체가 협력에 참여하기 위해 어떤 행동을 해야 한다면 그 행동을 하는 데 필요한 상태도 함께 지니고 있다는 것입니다. 그럼 좋은 객체는 어떻게 만들 수 있을까요?
객체는 충분히 협력적이어야 합니다. 다른 객체의 요청을 잘 처리해야하고, 다른 객체에 적극적으로 도움을 요청해야합니다.
하지만 하나의 객체가 여러가지 책임 가지는 것은 좋지 않습니다.
여러 가지 책임(기능)을 가진 전지전능한 객체(God Object)는 내부적인 복잡도에 의해 자멸합니다.
객체는 충분히 자율적이어야 합니다. 요청에 응답하는 방식은 객체가 스스로 판단하고 결정해야 하며 요청에 응할지 여부도 객체 스스로 결정해야 합니다. 객체의 자율성은 객체의 내부와 외부를 명확하게 구분하는 것으로부터 나오는데, 객체의 내부는 스스로 관리하고 외부에서 일체 간섭할 수 없도록 차단해야 하며, 객체의 외부에서는 접근이 허락된 수단을 통해 의사소통을 하게 됩니다.
여러 객체가 동일한 역할을 수행할 수 있다.
역할은 대체 가능성을 의미한다.
각 객체는 책임을 수행하는 방법을 자율적으로 선택할 수 있다.
하나의 객체가 동시에 여러 역할을 수행할 수 있다.
객체가 어떤 행동을 하는 유일한 이유는 다른 객체로부터 요청을 수신했기 때문입니다.
즉, 도움을 요청한 것이고, 객체는 요청을 처리하기 위해 최선을 다해야 합니다. 따라서 요청을 처리하기 위해 객체가 수행하는 행동을 책임이라고 할 수 있습니다.
그래서 소프트웨어를 객체지향으로 설계할 때는 어떤 기능을 수행할 수 있게 여러 책임으로 나누고 각 객체에 부여하여 협력하게 만들어야합니다. 그럼 책임을 어떻게 나눠서 부여해야 할까요?
책임은 객체가 '어떻게' 해야 하는가가 아니라 '무엇'을 해야 하는가를 설명합니다.
책임은 수행 방법을 제한할 정도로 너무 구체적이어도 안되며, 협력의 의도를 명확하게 표현하지 못할 정도로 추상적이어서도 안됩니다.
발사체를 예로 들어보겠습니다.
아래 예를 보겠습니다. ARPG에 사용할 캐릭터를 설계한다고 했을 때, 여기서 '캐릭터는 공격할 수 있다.'라는 기능을 구현하고자 합니다.

타인에게 도움을 요청할 때 다양한 방법이 존재하는 실세계와 달리 객체지향의 세계에서는 오직 한 가지 의사소통 수단만이 존재합니다. 이를 메시지라고 합니다.
다시 말해 객체 지향의 세계에서 협력은 메시지를 전송하는 객체와 메시지를 수신하는 객체 사이의 관계로 구성됩니다.
이때, 메시지를 전송하는 객체를 송신자(Sender), 메시지를 받는 객체를 수신자(Receiver)라고 합니다.
객체는 수신된 메시지를 어떻게 처리할까?
객체가 수신된 메시지를 처리하는 방법을 메소드(Method)라고 부릅니다.
메소드 클래스 안에 포함된 함수를 통해 구현되는데, 메시지를 수신한 객체는 실행 시간에 메소드를 선택할 수 있습니다. 외부의 요청이 무엇인지를 표현하는 메시지와 요청을 처리하기 위한 구체적인 방법인 메소드를 분리하는 것은 객체의 자율성을 높이는 핵심 메커니즘입니다.
메시지를 코드로 표현하면 결국 메소드를 호출하는 것입니다.
그리고 메소드를 호출하려면 인스턴스에 접근할 수 있어야합니다. 인스턴스의 참조를 어떻게 하면 전역 변수로 만들지 않고, 얻을 수 있을지 고민하는 것도 객체지향적으로 설계하는 데 핵심이라고 할 수 있습니다.
서로 다른 객체들이 다형성을 만족시킨다는 것은 객체들이 동일한 책임을 공유하는 것이라고 할 수 있습니다.
- 예를 들어 '공격'은 플레이어도 '공격'을 해야하고, 몬스터도 '공격'을 해야합니다.
즉, 객체들이 동일한 책임을 공유하는 것이라고 할 수 있습니다.
즉, 다형성은 메시지 송신자의 관점에서 동일한 책임을 수행하는 것입니다. 어떤 객체가 어떤 방법으로 처리하던지 송신자는 관심이 없으며 그저 수신자가 메시지를 받을 수 있기만 하면 됩니다.
그렇기 때문에 객체지향 프로그래밍이 다형성을 이용해 협력을 유연하게 만들 수 있어 강력한 것입니다. 메시지는 송신자와 수신자 사이의 결합도를 낮춤으로써 설계를 유연하고, 확장 가능하고, 재사용 가능하게 만듭니다. 따라서 설계의 품질을 높이기 위해서는 훌륭한 메시지를 선택해야 합니다.
인터페이스라는 구성 요소가 나오게 된 이유는 느슨한 협력 관계를 구축하기 위함입니다.
추상 클래스는 어떤 역할을 나타내게 됩니다. 예를 들어 총, 칼 등.
추상 클래스를 '총'으로 만든다면 오직 총만 들어와야합니다. 하지만 인터페이스는 다릅니다.
인터페이스는 동작을 정의하는 용도로 사용합니다. 그렇기 때문에 결합도를 더 낮출 수 있어 유연하게 사용이 가능합니다.

이제까지 배운 내용을 바탕으로 객체지향 프로그래밍에 대해서 정리하자면 아래와 같습니다.
객체지향이란 시스템을 상호작용하는 자율적인 객체들의 공동체로 바라보고 객체를 이용해 시스템을 분할하는 방법입니다.
자율적인 객체란 상태와 행위를 함께 지니며 스스로 자기 자신을 책임지는 객체를 의미합니다.
객체는 시스템의 행위를 구현하기 위해 다른 객체와 협력합니다. 각 객체는 협력 내에서 정해진 역할을 수행하며 역할은 관련된 책임의 집합입니다.
객체는 다른 객체와 협력하기 위해 메시지를 전송하고 메시지를 수신한 객체는 메시지를 처리하는 데 적합한 메소드를 자율적으로 선택합니다.
코드를 담는 클래스의 관점에서 메시지를 주고받는 객체의 관점으로 사고의 중심을 전환해야합니다.
중요한 것은 어떤 클래스가 필요한가가 아니라 어떤 객체들이 어떤 메시지를 주고 받으며 협력하는 가입니다.
객체지향의 핵심은 적절한 책임을 수행하는 역할 간의 유연하고 견고한 협력 관계를 구축하는 것입니다.
SOLID원칙은 클린 아키텍처에서 소개된 객체지향 설계의 바탕이 되는 5가지 원칙을 말합니다. 지금까지 배운 내용을 바탕으로 SOLID원칙을 살펴보도록 하겠습니다.
각 소프트웨어 모듈은 변경의 이유가 하나여야 한다는 원칙으로 위에서 살펴본 '책임'에 대해 명확히 이해하고 있으면 됩니다.
객체는 확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다는 원칙으로 기존 코드를 수정하기보다는 반드시 새로운 코드를 추가하는 방식으로 시스템의 행위를 변경할 수 있도록 설계해야만 소프트웨어 시스템을 쉽게 변경할 수 있다는 것입니다. 캡슐화와 관련이 싶습니다.
하위 타입에 관한 원칙으로 프로그램 P에서 T 타입의 객체 자리에 S 타입의 객체로 모두 치환하더라고 P의 동작이 변하지 않는다면 S는 T의 하위타입이라는 것입니다.
상속과 관련된 법칙이며, is-a 관계를 만족하게 상속 계층도를 구성해야 한다라도고 표현할 수 있습니다.
어떤 타입이 다른 타입에 의존한다고 할 때, 필요한 인터페이스만을 분리해 의존하게 설계하라는 원칙입니다.
다시 말하자면 결합도를 메시지 수준으로 낮추라는 것입니다. 이를 통해 설계가 얼마나 유연해지고, 확장 가능하고, 재사용이 가능한지 우린 위에서 배웠습니다.
고수준 정책을 구현하는 코드는 저수준 세부사항을 구현하는 코드에 절대로 의존해서는 안되며, 세부사항이 정책에 의존해야 한다는 원칙입니다.
다시 말하자면 다형성을 적극적으로 활용하라는 것입니다.
건축가이자 패턴의 아버지, 크리스토퍼 알렉산더는 "각 디자인 패턴은 기존 환경 내에서 반복적으로 일어나는 문제들을 설명한 후, 그 문제들에 대한 해법의 핵심을 설명한다. 똑같은 방법으로 두 번 하지 않고 이 해법을 100만 번 이상 재사용할 수 있도록 말이다."라고 하였다.
이는 객체 지향 설계에도 해당합니다.
즉, 어떤 상황의 문제에 대한 해법이라는 얘기입니다. 따라서 디자인 패턴을 올바르게 적용한다면 손쉽게 책임 주도 설계의 결과를 표현할 수 있습니다.
어떤 문제가 있고, 문제에 대한 해법이 쌍으로 존재합니다.
실무자 입장에선 디자인 패턴을 썼다는게 중요한게 아니라, 올바르게 썼는지를 중요하게 체크합니다.
게임을 만들 때 자주 사용하는 디자인 패턴이 있습니다.
포트폴리오 구성은 어떤어떤 이유로 이런 디자인 패턴을 사용했다. 라고 작성하면 만점입니다.