fender
8k
2016-11-02 20:22:40.0
16
13826

초보 개발자에게 권장하는 객체지향 모델링 공부 방법


원래 다른 글타래의 답글로 적던 내용인데 다른 분들에게도 혹시 도움이 될까 싶어서 별도 글타래로 옮깁니다. 따라서 다소 맥락이 어색한 부분이 있는 점 양해부탁 드립니다.

아마도 '객체지향 모델링'이라는 표현을 자주 들어보셨을 것입니다. 여기서 이야기하는 '모델링(modelling)'은 흔히 말하는 '3D 모델링'이나 '프라모델' 같은 단어에서 쓰인 뜻과 일맥 상통하는 개념입니다.

즉, 모델링이란 기본적으로 실세계의 어떤 대상을 다른 매체로 옮겨서 표현하는 작업을 뜻합니다.

프로그래밍에서라면, 실세계의 특정 도메인 - 예컨대 백화점의 업무와 관련한 일련의 개념(예컨대 '고객', '상품' 등)이나 동작('구매', '정산' 등)을 코드라는 매체로 옮겨서 표현하는 과정을 모델링이라고 할 수 있고, 특히 이러한 작업을 객체의 단위로 처리하는 경우 '객체지향 모델링'이라고 표현합니다.

따라서, 객체지향 모델링을 하려면 무엇보다 도메인에 대한 이해와 분석이 선행되어야 합니다. 일단 표현하려는 대상이 무엇이고 어떻게 구성되어있는지 알아야 어떻게 이를 코드로 옮길지 따져볼 수 있기 때문입니다.

그래서 보통 객체지향으로 설계를 할 때는 도메인의 핵심 개념과 요구조건을 파악하는 것을 첫 단계로 합니다.

개인적으로 특히 학원 같은데서 이러한 연습이 안된 상태에서 프레임워크를 써서 게시판 같은 걸 만들게 가르치는 것이 매우 안좋은 관행이라고 보는 이유가, 그렇게 배울 경우 보통 개념 추출 단계를 건너뛰고 으례 데이터베이스 테이블부터 생성하고 화면을 붙이려 하기 십상이기 때문입니다.

그렇게 하면 안된다는 법이야 없겠습니다만, 그건 객체지향적인 개발이 아니라 데이터베이스 중심적인 개발이라고 부르는 형태가 되어, 적어도 자바 언어로 개발하는데 있어서 우선 권장할만한 접근은 아닙니다.

그래서 저는 객체지향 모델링을 연습하려면 데이터베이스나 MVC 프레임워크를 사용하는 웹 응용프로그램보다는 터미널이나 단위 테스트로 구동하는 간단한 예제 프로젝트를 하는 것이 훨씬 도움이 될 수 있다고 생각합니다.

예를들어 카드 게임이나 윷놀이, 엘리베이터 시스템 등 도메인 규칙이 충분히 단순한 대상을 골라서 화면없이 관련 개념과 동작을 구현해 보는 것이 좋은 연습이 될 수 있습니다.

만일 포커 게임을 모델링해보겠다면, '카드', '플레이어', '핸드(i.e. 원 페어, 스트레이트, 등등)' 같은 핵심 개념과 '카드를 섞는다', '베_팅을 한다' 등과 같은 동작을 추출할 수 있을 것입니다.

그럼 남은 일은 '카드'를 'Card' 클래스로, '카드를 섞는다'를 'shuffle()'이라는 메서드로 모델링하는 일입니다.

좋은 모델은 주석을 보지 않고도 모델이 나타내는 실세계의 개념에 비추어 자연스럽게 읽히는 형태입니다. 예컨대 'CardDeck'이란 클래스에 'cards: List<Card>'라는 속성이 있고 'shuffle()'이라는 메서드가 있다면 특별히 주석을 달지 않아도, 어떻게 하면 카드덱의 카드를 섞을 수 있는지 직관적으로 알 수 있을 것입니다.

반면 'CardGame.shuffle()' 같은 메서드를 만들었다면 카드를 섞는행위는 카드 게임의 동작이라기 보다는 카드덱이나 플레이어의 동작으로 생각하는 것이 더 자연스럽다는 점을 감안하면 좋지 못한 모델링이 될 수 있습니다.

이런 식으로 어느 정도 기본적인 모델링에 익숙해지면 그 다음에는 일반화, 추상화에 대해 고민을 하는 것이 좋습니다.

예를들어 이렇게 포커 게임을 만들었다면 블랙잭 게임에 같은 코드를 사용한다고 했을 때 어떻게 하면 최소한의 수정으로 같은 코드가 두 가지 경우에 모두 적용되게 할 수 있을지를 고민하는 것이 일반화, 혹은 추상화의 과정입니다.

사실 객체지향이라는 패러다임 자체가 결국 코드를 일반화하고 추상화하는 한 가지 접근 방법이라고 할 수 있습니다.

결국, 실세계의 개념을 모델링하는 과정에서 지나치게 복잡한 부분을 추상화해서 감추고, 서로 다른 개념의 공통점을 찾아 일반화해서 같은 코드로 동작하게 하는 것이 객체지향적 설계의 핵심입니다.

아마도 자바 입문서에서 'extends' 키워드를 사용하면 상속을 할 수 있고 'super' 키워드를 써서 부모를 호출할 수 있다는 등의 내용을 배우셨을 것으로 짐작합니다.

하지만 이는 '어떻게(how)'에 해당하는 것이고, 그런 도구를 언제 '왜(why)' 써야 하는 지가 훨씬 더 중요한 질문이라고 할 수 있습니다.

그리고 만일 포커와 블랙잭의 규칙을 동일한 API로 표현하는 과정에서 'if else'문을 나열하는 대신 상속을 통해 일반화/추상화 하는 방법을 시도해본다면 바로 그런 '왜'에 해당하는 질문에 대한 답을 스스로 터득할 수 있다고 생각합니다.

이런 과정을 거쳐서 상속이나 인터페이스의 사용 같은 객체지향 기본 개념을 체득(단지 어떻게 하는 지만 아는 것이 아니라)했다면 남은 것은 실무에서 경험을 쌓고 디자인 패턴 같은 보다 깊이 있는 내용을 공부하는 것입니다.

디자인 패턴은 결국 앞서 말한 추상화, 일반화의 모범답안 같은 것을 모아 놓은 것일 뿐입니다. 자주 반복되는 문제에 대한 검증된 모델링 기법의 모음이 객체지향 디자인 패턴의 정의입니다.

결론적으로, 전 객체지향 모델링을 공부하려면 무엇보다 직접 간단한 모델링을 시도해보면서 개념을 익히는 것이 최선의 선택이라고 생각합니다.

그리고 그러한 연습 과정에는 어떤 웹사이트를 완성하겠다거나 완전한 GUI를 갖춘 플레이할 수 있는 게임을 만들겠다는 목표 보다는 터미널에 간단한 메시지만 출력되더라도 보다 객체간의 관계가 잘 나타날 수 있는 단순한 주제를 고르는 것이 도움이 될 수 있다고 봅니다.

46
59
  • 댓글 16

  • 영붕
    86
    2016-11-02 20:35:28.0

    정말 감사합니다. 스크랩 해놓고 반복해서 읽으며 객체지향 모델링 공부를 하겠습니다.

    0
  • fender
    8k
    2016-11-02 20:39:34.0

    본문에 빠뜨렸지만, 객체지향 모델링을 하는 한 가지 쉬운 방법을 소개하면, 우선 도메인의 유즈 케이스 - 예를들어, 카드 게임에서 새 카드를 받는 시나리오를 '플레이어가 카드를 뽑는다'와 같이 평이한 문장으로 적어서 나열합니다.

    그 다음에 문장들에서 반복적으로 등장하는 명사를 추려내서 이를 빈 인터페이스로 코딩합니다:

    interface Card {
    }
    
    interface Player {
    }
    
    //...


    한편 명사들 중에는 '카드의 숫자'와 같은 다른 개념에 종속적인 내용이 있을 것입니다. 이런 부분은 앞서 작성한 인터페이스에 속성으로 추가합니다:

    interface Card {
        int getNumber();
    }


    마지막으로 문장에서 동사를 추려내서 적절한 인터페이스의 메서드로 작성합니다. 예컨대 '카드덱에서 새 카드를 뽑는다'라면 다음과 같이 '카드덱'을 나타내는 인터페이스에 메서드를 추가할 수 있습니다:

    interface CardDeck {
        Card draw();
    }

    여기까지 완료되면 남은 것은 해당 인터페이스들이 서로 연계되어 동작할 수 있도록 모양을 만들어 주는 것입니다. 예를들어 다섯장의 카드를 뽑아서 플레이어에게 주어야 한다면 다음과 같이 표현할 수 있습니다:

    for (int i = 0; i < 5; i++) {
        for (player : players) {
            Card card = deck.draw();
            player.receiveCard(card);
        }
    }

    중요한 것은, 여기까지 오면서 실제 인터페이스의 구현에 대해서는 신경을 쓰지 않았다는 것입니다. 좋은 객체지향 설계에서는 구현이 없어도 각 유형의 공용 API만 보아도 어떻게 서로 연관지어서 구동되는 지 이해할 수 있어야 합니다.

    구현을 채워 넣는 것은 이런식으로 추상적인 개념 수준에서 전체적으로 돌아가는 모양의 윤곽이 잡혔을 때 단위 테스트를 작성해가면서 채워 넣어도 늦지 않습니다.

    4
  • 영붕
    86
    2016-11-02 20:45:34.0

    친절한 예시까지 다시 한 번 감사합니다.

    0
  • lifetime20
    -44
    2016-11-02 21:14:24.0

    설명 정말 잘 하시네요 ㅎㄷㄷ 이해가 쏙쏙 잘되는 설명 감사합니다.

    0
  • 훈훈
    311
    2016-11-02 21:59:23.0

    정말 학원에서 배우는 입장에서 공감이 많이 되는 글입니다. java기초문법 -> sql문( select/update/delete/insert)와 join까지 -> java와 jsp를 이용한 게시판 작성 -> mvc패턴으로 게시판 작성 -> -> 자바스크립트 ->스프링 프레임워크 -> 오전 안드로이드/오후 jQuery 현재 안드로이드와 jquery를 배우고 있습니다. 어떤것이든 기초가 튼튼해야 한다고 생각하고 기초를 단련 하려고 하지만 쉽지가 않습니다. 

    강사님이 어느정도 생각할 시간과 직접 코딩할 시간을 많이 주는 편이라곤 생각됩니다만 학원 교육 커리큘럼 자체가 저렇게 짜여져 있는 이상 어느정도의 한계가 있다고 보여집니다. 물론 본인의 노력으로 부족한 부분을 채워나가는게 우선이지만 순수 6개월을 프레임워크를 전혀 사용하지 않고 자바와 DB/ 자바스크립트와 HTML기초 이정도만 알려주는 과정이었다면 더 좋았을거 같습니다. 나머지는 저의 노력으로 해결해 나가야겠죠. 좋은글 감사합니다 fender님 다음 글도 기대하겠습니다 추운데 건강 조심하시길..

    0
  • 기획개발자
    27
    2016-11-02 22:46:09.0

    현재 객체지향 모델링 연습을 위해 프로젝트를 계획 중인데 정말 도움이 되는 글이네요. 乃(1따봉)드립니다.

    0
  • shylock3d
    187
    2016-11-03 09:22:13.0

    넘나 좋은글 매우베리 감사드립니다!

    0
  • 송사리야
    34
    2016-11-03 12:03:27.0

    좋은글 감사합니다!


    0
  • whnam
    2
    2016-11-03 12:53:07.0

    정말 좋은 설명!! 감사합니다.

    0
  • 또이로이
    44
    2016-11-03 15:43:51.0

    정말 초보 입니다..

    어떠한 말씀이신지 대략 짐작이 가는데 도메인 이라는 곳에서 이해가 잘 안되는거 같습니다 ㅠㅠ

    해결해보자고 하는 문제의 영역 이라고 생각하는데 제가 생각하는 뜻이 맞는건가요??

    그리고 현재 자바,sql를 기초 수준으로 공부 하고 있습니다.

    주말에 자바를 좀 더 이해하기 위해 웹 에플리케이션 공부가 도움이 된다고 해서 공부를 할 생각인데 괜찮은 방법 일까요??

    아 그리고 좋은 글 잘 읽었습니다!

    0
  • fender
    8k
    2016-11-03 16:36:26.0

    또이로이 // 네, '도메인'의 뜻은 생각하시는 내용이 맞습니다. '문제 영역(problem domain)', '도메인 객체' 등의 단어에서 사용된 뜻도 다 일맥상통합니다.

    웹 응용프로그램 개발을 공부하시는 건 나쁘지 않습니다, 다만 모든 분야가 그렇듯 기초를 먼저 이해하고 응용을 다룰 수 있도록 주의하시는 것은 권해드리고 싶습니다.

    예컨대 스프링 MVC를 익히기 전에 서블릿의 기본 개념을 공부하는 것이 바람직하다고 생각합니다.

    0
  • 또이로이
    44
    2016-11-04 08:03:41.0

    말씀 하신거 처럼 기초를 먼저 이해하라고 하셨는데


    자바를 주로 쓰는데 어떤 공부로 기초를 다지는게 나을까요?

    0
  • fender
    8k
    2016-11-04 08:48:25.0

     또이로이 // 프로그래밍에서 언어 자체를 아는 것이 가장 기초이고, 해당 언어로 만들어진 특정 프레임워크나 라이브러리를 쓰는 것은 응용의 영역입니다.

    그리고 언어 자체를 안다는 건 기본적으로 해당 언어의 문법과 패러다임을 익힌다는 것인데, 전자는 보통 다들 공부하지만 후자는 우리나라의 경우 현업 개발자들도 제대로 이해하지 못하는 경우가 많으니 후자에 집중하시는 것도 좋은 접근일 듯 합니다.

    현업에서 언어 패러다임을 무시한다는 것은, 단적으로 말해서 무엇이 상속이고 무엇이 인터페이스인지 모르는 개발자는 거의 없겠지만 실무에서 상속이나 인터페이스로 어떤 개념을 구현해본 적이 몇 번이나 되는 지 생각해보면 알 수 있습니다.

    아마도 많은 분들이 인터페이스는 SI에서 널리 쓰는 패턴대로 스프링에 서비스 등록할 때나 써봤지 어떤 개념을 표현하려고 만들어본 적은 거의 없을 것입니다.

    기초가 탄탄한 자바 개발자라면 바로 그런 부분들을 제대로 할 줄 알아야 한다고 생각합니다.

    0
  • gem
    521
    2016-11-04 12:32:14.0

    요새 공부하려고 마음먹은 건데..! 글 올려주셔서 감사합니다 ^^

    0
  • coding8282
    512
    2016-11-26 01:15:45.0

    저도 최근에 객체지향적으로 학습하고 적용하고 있는데, 학교나 학원에서 이런 식으로 배웠으면 좋았을 텐데 아쉽네요. 또 한편 데이터베이스 중심적인 사고가 객체지향을 이해하는데 방해가 되기도 해서 많이 헷갈리곤 하네요. 모델링하다 보면 어느새 쿼리를 생각하고 있으니... 진정한 객체지향이 적용되려면 아직 머나먼 애기인 것 같지만 그래도 이런 류의 글이 자주 보여서 많은 개발자들이 정말로 객체지향에 동참했으면 좋겠습니다..

    0
  • kingbbode
    122
    2016-11-28 23:00:55.0

    크게 배우고 갑니다. 감사합니다.

    0
  • 로그인을 하시면 댓글을 등록할 수 있습니다.