[ CS ] 객체지향 프로그래밍이란?

혜빈·2024년 9월 6일

보충내용

목록 보기
22/38

기본 배경

  • C, Assembly 등 소수를 제외한 오늘날의 프로그래밍 언어들은 모두 객체지향 프로그래밍 개념과 기능을 포함하고, 소프트웨어 개발의 기본적인 구성 요소로 자리잡고 있음

절차지향 프로그래밍

  • 어떤 소프트웨어를 개발하는 일을 중세의 성을 쌓는 일에 비유하면,
    개발자는 성주이고, 그는 인부들에게 내릴 명령을 문서로 작성해 성을 건축해야함
  • 여기에서 명령 문서 = 프로그래밍 코드 , 인부 = 컴퓨터의 자원임
  • 만약 명령 문서에 처음부터 끝까지 모든 내용을 다 작성하게 되면 코드는 중복되며 비효율적이고, 추후에 분석하고 수정하는 일도 어려움
  • 이를 개선하기 위해 일정 단위의 작업들을 하나로 묶을 수 있는데, 이를 함수라고 부름

  • 이렇게 만든 함수들을 필요한 만큼 재사용하여 보다 간결하고 효율적인 코드 작성 가능
  • 이렇게 하면 함수 단위로 명령을 내릴 수 있음
  • "나무 컴포넌트 작업 해줘", "모래 컴포넌트 작업 해줘"
  • 여기까지는 절차지향 프로그래밍에 해당됨
  • 함수를 사용하여 코드의 재사용성과 효율성을 높였지만,
    소프트웨어 규모가 커지면 이것으로는 코드의 복잡성을 관리하는데 한계가 있음

객체지향 프로그래밍

클래스(Class)

  • 역할 정의하기
  • 역할은 객체지향 프로그래밍에서 '클래스'라고 불림
  • 성을 건축할 때 목수, 석공, 대장장이, 기술자 등의 클래스가 동원됨
  • 즉, 직업을 정의하는 것과 비슷함

속성(attribute)

  • 클래스에는 '역할'을 맡은 인부들이 저마다 가질 데이터와
    구사할 수 있는 함수들이 정의되어 있음
  • 이를 속성(attribute), property, field라고 부름
  • 속성은 인부들 각각이 가지고 있는 '상태'임
  • 클래스에 속한 함수는 인부들이 할 수 있는 '행동'이고, 메소드라고 부름
  • 예를 들어, 목수라는 역할에는
    목수가 사용하는 도구, 그 도구들을 만들어주는 전담 대장장이가 속성으로
    목수가 하는 일인 '목재 부품 만들기'가 메소드로 정의되어 있음
  • '속성'들은 이 책임을 수행하기 위해 필요한 데이터일 뿐이고,
    핵심이 되는 것은 '메소드'임
  • 각 역할을 맡은 인부들은 이 '행동'을 취할 '책임'을 갖게됨
  • 석공들은 석재를 쌓는 책임, 대장장이들은 도구를 만드는 책임, 기술자들은 설계/시공하는 책임이 메소드라 불리는 함수의 형태로 주어져있음
  • 이처럼 객체지향 프로그래밍에서는 시작하기 전에 '역할'들과 '책임'을 먼저 설계하고 정의함
  • 그리고 나서 인부들에게 "너는 석공이야", "너는 목수야"와 같이 역할을 배정한 후 일을 시킴
  • 처음 방식처럼 그냥 명령을 내려서 일을 시키는 것 보다
    이처럼 역할부터 정한 뒤 인부들에게 할당하는 방식이 훨씬 체계적이고 관리가 용이한 방법
  • 객체지향 프로그래밍의 코드는 보통 이와 같이 각 클래스별로 모듈화 되어 있음
  • 즉, '클래스'라는 단위로 나눠져 있음
  • 프로그램을 수정할 일이 있으면 해당하는 클래스만 찾아 수정 가능하고,
    하나의 클래스를 여러 프로그램에서 재사용하는 것도 가능함

인스턴스(instance) 또는 객체(object)

  • '클래스'라고 부르는 역할을 배정받은 인부들이라고 생각하기
  • 자신의 역할대로 부여받은 속성들과 메소드에 대한 데이터를 갖고 있는 데이터 덩어리임
  • 객체에 속성같은 데이터들이 담기기 때문에 객체를 데이터를 넣는 용도의 주머니라고 오해할 수 있는데,
    '책임'에 중점을 두고 생각하면 객체는 일정한 메모리 자원에 클래스가 부여되어 책임을 가진 존재로 만들어진 결과임

정리 그림


객체지향 프로그래밍 특징

Encapsulation (캡슐화)

  • 클래스들은 보통 혼자 일하지 않음
  • 다른 클래스와의 '협력'을 통해 복잡한 작업을 수행함
  • 예를 들면, 목수 객체들은 속성으로 전담 대장장이 객체를 가지고 있고,
    대장장이 객체의 메소드(도구제작 = 대장장이 객체의 책임)를 호출하여 사용할 도구들을 주문함
  • 중요한 점은 목수 객체는 대장장이 객체가 '도구제작'이라는 책임을 어떻게 수행하는가에는 관심을 갖거나 참견하지 않음
  • 속성들은 private 상태로 외부로부터 감춰져 있기 때문에 어떠한 간섭도 받지 않음 (다른 클래스의 객체가 이 데이터를 읽거나 수정하지 못함)
  • 이를 캡슐화라고 함
  • 대장장이가 어느 온도의 불을 사용하고, 어떤 도구를 사용하는지에 대해서 아무도 간섭하지 못함
  • 목수는 단지 대장장이에게 필요한 도구를 주문하고,
    대장장이는 자기 방식대로 이를 만들어 건네줄 뿐임
  • 이처럼 각 클래스가 자기가 맡은 책임에만 관심을 갖도록 함으로써
    코드의 복잡성을 줄이고 유연성을 확보할 수 있음
  • 각 클래스는 보통 특정 메소드만을 외부에 공개해서 이를 다른 클래스와의 소통 창구로 삼음
  • 목수 객체는 대장장이가 외부로 공개한 도구제작 메소드를 호출하기만 하면 됨
  • 이후에 대장장이의 메소드를 실행하는 메커니즘이 변경되더라도, 다른 클래스의 객체가 이를 호출하는데에는 아무런 지장이 없음

Inheritance (상속화)

  • 작업이 복잡해지고 커질수록 필요한 역할의 종류도 늘어나게 됨
  • 예를 들면, 기존에는 목수, 석공만 필요했다고 하면 목재 구조물을 건설하는 '건설목수'가 필요해지거나 '석조 조각가', '벽돌공' 등이 필요해질 수 있음
  • 이때, 목수와 석공을 정의한 것처럼 각각 별개의 클래스로 정의하게 되면 코드가 길어지고, 공통분모를 가진 클래스들 간에 아무런 연관성이 만들어 지지 않는다는 단점이 발생함
  • 예를 들면, 건설목수 클래스는 기존 목수 클래스의 속성과 메소드에 자신의 메소드를 더한 클래스이기 때문에 중복되는 코드가 발생함
  • 중복 내용을 다시 작성하면 효율적이지 않고, 이후 공통 기능에 수정사항이 있을 때 변경하기 번거로움
  • 여기에서 상속화 개념이 유용하게 사용됨
  • 클래스는 다른 클래스에게 속성과 메소드를 물려줄 수 있음
  • 건설 목수 클래스가 목수 클래스로부터 확장하도록 설정하면
    자식 클래스인 건설목수 클래스는 부모 클래스인 목수 클래스의 속성과 메소드를 상속 받게 됨
  • 개발자는 이 관계를 설정한 다음, 건설목수 클래스가 추가로 가질 속성이나 메소드를 작성해주면 됨
  • 이렇게 하면 코드의 양이 훨씬 줄어들게 됨
  • 만약 벽돌공이 석공의 '돌쌓기' 메소드를 상속받게 되면, 석공은 일반 돌을 쌓지만 벽돌공은 벽돌을 쌓게 됨
  • 이처럼 특정 메소드를 다른 방식으로 실행할 목적으로 자식 클래스를 만들기도 함
  • 이와 같이 부모의 메소드를 자식의 방식으로 덮어씌우는 것을 '오버라이딩(overriding)이라고 함'
  • 상속은 특정 속성이나 메소드를 추가한 클래스를 만들기 위해서도,
    특정 메소드의 실행방식을 수정한 클래스를 만들기 위해서도 할 수 있음
  • 부모 클래스는 자식 클래스들을 한데 묶는 카테고리의 역할을 할 수도 있음
    (석공이 들어갈 자리에 벽돌공, 석조 조각가가 들어갈 수 있음)
  • 카테고리는 특정 자리에 어떤 클래스들이 들어가 사용될 수 있는지를 정하는 기준으로 작용할 수 있음
  • 카테고리가 되는 것만을 목적으로 하는 클래스도 있음
  • 기술자 클래스는 추상 클래스로, 그 자체로 인스턴스(객체)를 만들 수 없음
  • 이 클래스에는 '설계 / 시공'이라는 메소드가 있지만 이름만 있을 뿐 정확히 무엇을 하는지는 정의되어있지 않음
  • 배수기술자, 방어시설기술자 클래스는 이 '기술자' 추상 클래스의 자식 클래스임
  • 인부들은 구체화된 자식 클래스들의 객체로서 역할을 부여받을 수 있음

참고 : 얄코님 유튜브

profile
최강 개발자를 꿈꾸는 병아리

0개의 댓글