Development(개발)/개발 Core

[객체지향] 역할과 책임이 헷갈리네요

버터젤리 2025. 4. 15. 14:30

 

01.객체 지향에서 주요한 요소 - 역할, 책임, 협업 이해하기

객체지향 관련 유명한 도서 중 하나인 [객체지향의 사실과 오해]라는 책에서, 객체지향은 역할, 책임, 협업 이렇게 3가지 요소에 의해 만들어졌다고한다. 여기서 항상 헷갈렸던게 역할과 책임이다. 역할과 책임의 차이에 대해 짚어보자

 

역할이 책임아냐? 이건 역할이야 책임에 해당하는거야?뭐야?

이런 생각을 한적이 많다. 

 

내가 이해한 역할과 책임의 차이는 다음과 같다.

02.역할과 책임의 차이는?

역할(Role)

주어가 되는 것, 객체, 행위의 주체를 의미.

행위들의 논리적 단위를  관념적으로 칭하는 것이 역할이다.

 

책임(Responsibility)

동사로 표현되는 행위. DB로 치면 저장된 데이터를 읽는 것, 새로운 데이터로 업데이트 하는것, 입력받은 데이터를 저장하는 것.

'DB관리'가 역할이 되는 것

 

 

처음엔 책임이라고해서 헷갈렸던 것 같다. 책임감이라는 사람의 감정에 연결해서 받아들이면 헷갈린다.

책임 → 맡아서 해야할 임무, 미션, 업무, 행위 라고 받아들이면 감잡기 쉽다.

 

행위들을 몇가지 주제로 모아서, 또는 어떻게 묶을까 세세하게 묶을까, 큰 범위로 묶을까에 따라 역할이 정해지는 것! 

 

 

03.그래서, 이걸 코드짤때 어떻게 적용한다는 건가? 이걸 안다고 뭐가 달라져?

- 아래 예시를 보고 역할,책임을 나눈다는게 어떤 의미인지 알아보자

 

 

❌ 역할을 나누지 않은 엉망 코드 예시

import sqlite3

class MemberController:
    def save_member(self, name, age):
        # DB 연결
        conn = sqlite3.connect('members.db')
        cursor = conn.cursor()

        # SQL 쿼리 작성
        cursor.execute("INSERT INTO member (name, age) VALUES (?, ?)", (name, age))

        # 쿼리 실행
        conn.commit()
        conn.close()
 

여기서 MemberController 클래스는:

  • 데이터를 받는 것
  • DB 연결하는 것
  • SQL 쿼리 작성하는 것
  • 쿼리 실행하는 것

4가지의 책임을 떠맡고 있다. 이렇게 되면, 나중에 데이터베이스 변경이나 다른 기능을 추가하려면 한 곳에서 여러 책임을 수정해야 하기 때문에 코드가 점점 복잡해지고 유지보수가 힘듬.


✅ 역할과 책임을 나눈 좋은 구조 예시

1. VO (Value Object) - 데이터 객체 만들기

class MemberVO:
    def __init__(self, name, age):
        self.name = name
        self.age = age

MemberVO회원 정보만을 담는 역할을 담당.

 

2. DAO (Data Access Object) - 데이터베이스와 연결된 클래스

import sqlite3

class MemberDAO:
    def save(self, member):
        # DB 연결
        conn = sqlite3.connect('members.db')
        cursor = conn.cursor()

        # SQL 쿼리 실행
        cursor.execute("INSERT INTO member (name, age) VALUES (?, ?)", (member.name, member.age))

        # 커밋 후 연결 종료
        conn.commit()
        conn.close()

MemberDAODB에 데이터를 저장하는 책임만 존재.

DB 연결, 쿼리 작성, 실행 등 DB 관련 모든 작업을 이 클래스가 전담하므로, 나중에 DB를 변경해야 할 때도 DAO만 수정하면 됨.

 

3. DTO (Data Transfer Object) - 데이터 전달 객체

class MemberDTO:
    def __init__(self, name, age):
        self.name = name
        self.age = age

MemberDTO데이터를 다른 계층(예: 웹 클라이언트, 서비스 계층 등)으로 전달하는 역할

이 객체를 사용하면 데이터의 일관성을 유지할 수 있고, 각 계층 간에 데이터 전달이 쉬워져.

 

4. Controller - 사용자의 요청을 처리하는 클래스

class MemberController:
    def __init__(self):
        self.dao = MemberDAO()

    def save_member(self, name, age):
        # VO 생성
        member = MemberVO(name, age)

        # DAO를 통해 DB에 저장
        self.dao.save(member)

MemberController는 이제 사용자의 요청을 받아서 필요한 클래스를 호출하는 역할

DB 연결이나 데이터 저장과 같은 구체적인 일들은 MemberDAO에 맡기고, 자기 역할(요청로직)만 관리

비즈니스 로직 등은 따로 구현해서 비즈니스 로직만 수정해야할때 편리함


👉 이걸 알고나면 코드를 보는 시야가 넓어진다!

  1. 각각의 클래스가 하나의 책임만 가지도록 분리했기 때문에, 유지보수나 수정할 때 어디에서 수정해야 할지 쉽게 찾을 수 있다.
  2. 예를 들어, DB를 변경하거나 회원 정보를 전달하는 방식을 바꾸더라도, DAO나 DTO가 어디있지 찾고, 수정하면 된다, 컨트롤러나 다른 부분에 영향을 미치지 않아서 유연한 확장이 가능해.
  3. 역할이 명확해지니까 코드도 더 깔끔하고 이해하기 쉬워지고 퀄리티가 높아짐