Community

객체란 무엇인가?

필자의 블로그 [커리어리 글을 작성하는 것이 다소 익숙하지 않기에, 아래 블로그로 가면 가독성이 더욱 좋을 것 입니다.] https://blog.naver.com/PostView.naver?blogId=gomets_journey&logNo=223303360487&parentCategoryNo=&categoryNo=26&viewDate=&isShowPopularPosts=false&from=postList 우선 이 얘기부터 하고 싶다. 흔히 우리는 객체지향을 현실의 세계를 모방하여 만들었다라고 배운다. 하지만 잘 생각해보면 그렇지 않다는 것을 알 수 있다. 현실에서 차용하여 객체지향 패러다임으로 변환된 것이라고 나는 생각한다. 객체는 자신의 상태와 행동, 즉 책임을 결정하고 알게 된다. 이는 메시지가 송신자로부터 올 때 수신자가 메시지를 받고 자신의 책임을 수행하는 것으로 나타난다. 하지만 현실에서 객체는 모두 이렇게 동작하지는 않는다. 현실에서는 자의식을 가진 객체들에 한해서만 그런 방식으로 동작한다. 즉 일부 객체들만 자율적으로 행동하는 반면, 다른 객체들은 외부 요인에 의해 행동한다. 다만 처음 객체에 대해 배울 때 상대적으로 친숙하고 학습하기 쉽기때문에 그렇게 예시를 드는 것이 아닌가 생각이든다. 예를 들어, 가방이라는 객체를 생각해보자. 가방 객체는 자기가 물건을 담는다는 행동을 스스로 결정짓지 않는다. 다른 객체(사람)이 물건을 담아주는거다. 하지만 객체지향에서의 가방 클래스는 그 자체로 수납, 꺼내기 등의 행동을 수행할 수 있는 메서드를 가질 수 있다. 나는 이것이 객체지향에서의 캡슐화라고 생각한다. 객체지향의 세계에서는 객체가 자율성을 가지고 자기의 책임을 자유롭게 표현한다라고한다. 이러한 객체들의 협력 이 객체지향의 핵심이다. 즉 객체는 자율의지를 갖고 있다고 할 수 있다. 다시 현실로 돌아가보면 가방은 자율의지가 없으므로 타인이 행동을 결정짓게 된다. 자 이제 내가 캡슐화라고 생각한 이유를 말해보려한다. 캡슐화는 객체의 상태와 행동을 외부로부터 숨기고, 외부에서는 객체 내부에 직접 접근하지 않고 제공된 인터페이스를 통해 상호작용 하는 것을 의미한다. 현실에서의 가방 역시 외부에서 직접적으로 내부에 접근하는 것이 아니라, 가방이 제공하는 수납 공간에 물건을 넣거나 꺼낼 수 있다. 이제 메시지에 대한 내용에서 조금 더 이야기해보자. 메시지(Message) 메시지는 객체 간 통신을 위한 개념으로, 객체가 다른 객체에게 요청을 보내는 방법을 의미한다. 메시지는 객체 간 상호작용을 위해 사용되며, 한 객체가 다른 객체에게 어떤 작업을 수행하도록 요청할 때 사용된다. 메시지는 메서드를 호출하는데 사용되며, 이는 객체 간의 상호작용을 유발하고 프로그램의 동작을 제어하는 기본적인 수단이다. 메서드(Method) 메서드는 객체가 수신한 메시지를 처리하기 위한 코드 블록이나 함수로, 객체가 요청을 수행하는 방법이다. 메서드는 특정한 객체에 속하며, 객체의 행동을 정의하고 실행한다. 메서드는 클래스에 정의되어 있으며, 해당 클래스의 인스턴스(Object)가 메시지를 받으면 이를 처리하기 위해 메서드가 호출된다. 정리하자면, 객체는 메시지를 받고 그에 대응하는 메서드를 호출하여 요청된 작업을 수행한다. 메시지는 객체 간 통신을 위한 개념이며, 메서드는 해당 메시지를 받아들여 실제 동작을 수행하는 코드 조각이다. 송신자는 메시지를 요청한다. 이때 해당 메시지를 처리할 수 있는, 즉 본인이 처리할 메시지임을 아는 객체가 책임을 지고 메시지를 응답한다. 송신자는 수신자가 누가인지에 대해 신경쓰지 않고, 오로지 메시지를 올바르게 처리하면 되는 것이다. 즉 송신자 입장에서는 수신자가 메시지를 잘 처리만 해주면 되는 것이다. 나는 이것이 다형성이라고 생각한다. 자유롭게 누가되었든 그 메시지만 잘 처리해줘 누군지는 신경쓰지 않을게가 송신자이다. 또한 이러한 메시지를 모아놓은 것을 인터페이스라 하는데, 이 인터페이스를 구현한 클래스들 중 어떠한 클래스가 수행할 지는 송신자는 전혀 신경쓰지 않는다. 즉, 송신자가 객체의 실제 유형에 대해 신경쓰지 않고, 오직 메시지를 제대로 처리할 수 있는지에만 관심이 있는 것을 의미한다. 이런 관점에서 송신자가 메시지를 보내면서 누가 수행할지 신경쓰지 않고, 메시지를 잘 처리해주기만을 기대하는 것이 개념에 의해서 다형성이 여기서 나온다고 생각한다. 또한 객체는 자율의지를 갖고 있다고 위에서 언급했다. 이에 메시지에는 What(무엇)에 대한 내용만 있는 것이 How(어떻게)까지 있는 것보다 이상적이다. 송신자가 How를 지정하면 객체의 자율성이 제한되고, 두 객체간의 연결성 강해지게 된다. 이는 재사용성이 감소할 수 있는 결과를 초래한다. 그렇기에 객체의 자율성을 강화하기 위해 What에 해당하는 부분만을 메서드로 사용하고, How에 해당하는 부분은 수신자가 처리함으로써 객체의 자율의지를 강화시켜준다 할 수 있다. 이는 객체의 캡슐화를 강화하고, 유연하고 재사용 가능한 코드를 작성하도록 도와준다. 메시지에는 무엇(What)에 대한 내용이 주로 포함되어 있으며, 객체가 받은 메시지를 처리하는 방법(How)은 개체가 자율적으로 결정하는 것이 이상적이다. 이를 통해 객체는 자신의 내부 동작을 캡슐화하고, 메시지를 처리하는 방법에 대한 구현 세부사항을 외부로부터 숨길 수 있다. 송신자가 How에 대한 세부적인 구현을 메시지에 명시하게 되면, 수신자의 자율성이 제한되고 두 객체 간의 결합도가 높아지며, 재사용성이 감소할 수 있다. 이는 객체 간의 결합이 강해지고 변경이 발생할 때 유연하게 대처하기 어려워질 수 있다는 것을 의미한다. 나는 이러한 것이 객체지향의 세계이며, 이것을 좀 더 분명하게 설계하는 원칙 중의 하나가 앞서 설명하였던 SOLID라고 생각한다. 그리고 객체의 특징을 잘 살리면서 구현하는 방법이 책임주도설계, 디자인패턴, 테스트주도개발이다. 이제 책임주도설계에 대해 좀 더 이야기해보고자 한다. 책임주도설계는 객체가 수행해야 하는 책임을 중심으로 설계를 진행하는 개념이다. 이 설계 방식에서는 객체들 간에 어떤 책임을 할당하고, 적절한 행위를 수행할 수 있도록 구조화하는 것이 중요시된다. 객체가 자신의 책임을 수행하는 것을 강조함으로써 객체 간의 결합도를 줄이고, 응집도를 높이며, 재사용성과 유연성을 향상시킬 수 있다. 이것에 대척점이 데이터주도 설계이다. 데이터주도설계는 객체의 상태나 데이터에 초점을 맞춰 설계하는 것을 의미한다. 이 방식은 객체의 상태를 중심으로 설계되어 객체들 간의 상태를 공유하거나 상태에 의존적인 설계를 유도할 수 있다. 이는 설계가 statefull해진다고 볼 수 있다. 이로 인해 객체 간의 결합도가 높아지고, 캡슐화가 약화되며, 재사용성과 유연성이 감소할 수 있다. 나는 이러한 것이 절치자향과 객체지향의 차이라고 생각한다. 이제 인터페이스와 상속, Inner Class에 대해서 이야기해보고자 한다. 1. 인터페이스와 메시지 구성 * 인터페이스는 클래스 간의 계약이라고 볼 수 있다. 즉, 특정한 메서드나 동작을 제공함으로써 해당 인터페이스를 구현하는 클래스는 이러한 동작을 보장한다. * 객체 간 상호작용을 위해 메시지를 통해 행동이 결정된다. 이 메시지들은 인터페이스르 통해 전달되며, 이를 구현한 클래스들은 그에 맞게 행동한다. 2. 상속과 역할 부여 * 상속은 새로운 클래스에게 기존 클래스의 특성을 물려주는 개념이다. 이를 통해 코드 재사용성을 높일 수 있지만, 종종 불필요한 복잡성을 초래할 수도 있다. * 역할 모델링은 상속과는 다른 관점에서 클래스 간의 관계를 바라보는 것이다. 클래스가 특정 역할을 수행한다는 개념에 중점을 두어 설계한다. 즉, 해당하는 메시지들로만 구성되어 있을 경우에 인터페이스를 사용하고, 이러한 상태를 종속한 추가적인 역할 혹은 의미를 부여하고자 한다면 상속을 이용한다고 생각한다. 3. 클린 아키텍처와 인터페이스 * 클린 아키텍처에서 인터페이스는 의존성 역전 원칙을 따르는 설계를 지원한다. 이는 상위 수준의 모듈이 하위 수준의 모듈에 의존하지 않도록 하고, 둘 다 추상화된 인터페이스에 의존하도록 하는 것이다. 이는 시스템을 유연하게 만들어 변경을 용이하게 하며, 테스트와 유지보수를 쉽게 한다. 즉, 인터페이스란 절차지향적인 설계방법 즉 탑다운적인 설계를 역전시켜준다라고 생각한다. 4. Inner Class와 상속 * Inner Class는 외부 클래스 안에 선언된 클래스로, 상속과는 다른 개념이다. Inner Class를 사용하면 외부 클래스의 멤버 변수 및 메서드에 더 쉽게 접근할 수 있다. 이를 사용하여 관련 있는 클래스를 그룹화하거나 캡슐화할 수 있다. * Inner Class의 경우, 해당 객체가 속한 외부 객체의 상태에 접근할 수 있지만, 이로 인해 외부 클래스와의 결합도가 높아질 수 있다. * 예를 들어, A 객체에서 사용하는 Inner Class가 외부 클래스의 상태에 의존하고 있다면, B 객체에서 이 Inner Class를 사용하더라도 외부 클래스의 변경이 영향을 미칠 수 있다. 그렇기 때문에 Inner Class를 사용할 때에는 외부 클래스와의 결합도와 재사용성을 고려해야 한다. 5. Inner Class와 재사용성 * Inner Class를 사용할 때 주의할 점은, 내부 클래스의 재사용성이 외부 클래스와 긴밀하게 연결될 수 있다는 것이다. Inner Class는 외부 클래스의 상태에 종속적일 수 있으며, 이로 인해 외부 클래스의 변경이 Inner Class에 영향을 미칠 수 있다. 따라서 어떤 경우에는 인터페이스를 사용하여 다형성을 강조하고, 객체 간의 관계를 유연하게 유지할 수 있다. 반면에 상속은 클래스 간의 계층 구조를 만들거나 코드 재사용을 위해 활용된다. 내부 클래스는 특정한 그룹화나 캡슐화를 위해 사용되지만, 외부 클래스와의 결합도 및 재사용성을 고려해야 합니다. 사용 사례와 상황에 따라 이러한 개념들을 적절하게 선택하여 프로그램을 설계하는 것이 중요하다.

알림

알림이 없습니다