[사내 세미나] 객체 지향이 무엇인가
2020년도의 첫 정기 세미나는 최범균 개발자를 초대했다. 파킹클라우드의 20년도 1월 세미나 주제는, 객체 지향 이다. 객체 지향은 무엇인지 함께 알아보자!
비용
- 소프트웨어는 적은 비용으로 변화에 대응할 수 있어야 함
- 비용을 낮춰서 빠르게 대응하는 방법이 필요
- 방법
- 패러다임 : 객체 지향, 함수형 등
- 코드, 설계, 아키텍쳐
- 효율적인 프로세스/문화
- 방법
객체
절차 지향 vs 객체 지향: 절차 지향
- 절차 지향: 데이터를 공유하는 모형
- 시간이 지날수록 비용을 증가시킬 수 있음
- 시간이 갈수록 복잡해지고 수정이 어려워지기 때문
- 객체 지향: 객체와 객체가 프로시저를 통해 서로 통신을 하는 형태
- 처음부터 객체 지향으로 구상하는 것이 어려움
- 수정이 쉽고 변경 비용이 낮음
객체란?
그 객체가 내부적으로 어떤 데이터를 가지고 있는냐가 아닌, 실제 어떤 기능을 제공 하느냐로 정의
기능 명세
- 인터페이스: 객체가 제공하는 기능의 명세
- 이름, 입력 ,결과로 구성됌
- 메시지 전달
- 객체에게 기능 실행을 요청(메소드 호출)
캡슐화
- 객체가 내부적으로 기능을 어떻게 구현했는지 감추는 것
- 외부에 영향을 주지 않고 객체 내부의 구현을 변경하게 함
캡슐화를 하지 않으면?
- 변경이 연쇄적으로 퍼짐
객체지향, 캡슐화를 한다면?
- 기능을 제공하고 구현 상세를 감춤
- 내부 구현만 변경됌
캡슐화하는 방법
- 데이터를 갖고 있는 객체가 판단해서 알려달라하기
- 메서드를 연쇄적으로 호출하게 하지 말기
절차지향 방지책
- 메서드 파라미터로 관련 데이터만 받기
- 데이터 전체를 그냥 넘기지 말기
다형성과 추상화
- 여러 모습을 가지는 것
- 모습 -> 타입
- 객체 지향 언어에서는 타입 상속으로 다형성 구현
추상화를 잘하는 개발자가 진짜 잘하는 개발자!
추상화
- 데이터나 프로세스 등을 의미가 비슷한 개념이나 의미있는 표현으로 정의하는 과정
타입 추상화
- 여러 구현 클래스를 대표하는 상위 타입 도출
- 흔히 인터페이스타입으로 추상화
- 추상화 타입과 구현은 타입 상속으로 연결
추상 타입 상속
- 추상 타입은 구현을 감춰서 기능의 구현이 아닌 의도를 더 잘 드러냄
추상 타입 이점
- 유연함 (사용 대상 변경이 쉬움)
추상화 주의점
- 추상화를 하여 추상 타입이 증가하면 복잡도가 증가함
- 실제 요구사항의 변경/확장이 발생할 때 추상화를 시도해야 함
OCP(Open-Closed Principle)
- 개방 폐쇄 원칙
- 확장에는 열려 있고 수정에는 닫혀 있음
- 의존하는 대상은 변경 혹은 확장 가능하지만, 의존 대상을 사용하는 코드는 수정하지 않음
- 객체 지향에서는추상화(다형성, 상속)를 이용함
캡슐화와 다형성/추상화
- 개발 비용을 낮춰주는 객체 지향의 두 가지 특징
- 캡슐화
- 다형성/추상화
기능과 책임 분리
- 기능의 정의
- 입력
- 출력
- 상태 변경
기능 분해
- 기능은 하위 기능으로 분해
- 기능은 곧 책임이므로 분리한 기능을 알맞게 분배해야 함
기능 분해가 제대로 되지 않는다면?
- 큰 클래스, 큰 메서드가 만들어짐
책임 분배/분리 방법
- 패턴 적용
- 계산 기능 분리
- 외부 연동 분리
- 조건별 분기는 추상화
패턴 적용
- 전형적인 역할 분리
- ex) 웹: 컨트롤러, 서비스, Dao
계산 분리
- 계산 기능을 별도 분리
- 분리한 입력과 출력은 다른 코드에 덜 엮이게
연동 분리
- 네트워크, 메시징, 파일 등 연동 처리 코드 분리
조건 분기는 추상화
- 연속적인 if-else는 추상화 고민
알맞은 책임 분리와 테스트
- 테스트가 용이함
- 테스트가 가능한 코드를 만들수록 책임 분리가 잘 될 가능성이 높아짐(TDD)
의존
- 기능 구현을 위해 다른 구성 요소를 사용하는 것
- 결합도(coupling)
- 구성 요소가 서로 의존하는 정도
- 의존은 변경이 전파될 가능성을 의미함
- 의존하는 대상이 바뀌면 다른 무언가도 변경될 가능성이 높아짐(영향력)
- 의존 대상이 적을 수록 변경의 영향이 적음
의존 대상이 많을 때
1. 기능이 많은 경우
- 한 클래스에서 많은 기능을 제공
- 기능 별로 알맞게 분리할 것을 고민할 필요가 있음
2. 묶어보기
- 몇 가지 의존 대상을 단일 기능으로 묶어서 생각해보면 대상을 줄일 수 있음
의존 대상 객체를 직접 생성한다면?
- 생성 클래스가 바뀌면 의존하는 코드도 바뀜
- 추상화에서 언급
- 의존 대상 객체를 직접 생성하지 않는 방법
- 의존 주입
- 서비스 로케이터
- 팩토리
서비스 로케이터 vs DI
- 프레임워크가 지원한다면 DI
- DI가 서비스 로케이터보다 의존 객체 변경에 유연함
- 프레임워크 지원 X 라면, 서비스 로케이터
- 서비스 로케이터 단점
- 의존 관계가 잘 드러나지 않음 등
- 서비스 로케이터 단점
DIP(Dependency Inversion Principle)
- 개발자의 추상화 능력을 높여줌
- 의존 역전 원칙
- 저수준 모듈이 고수준 모듈에서 정의한 추상 타입에 의존해야 함
- 고수준 모듈 관점에서 저수준 모듈을 추상화
고수준 모듈, 저수준 모듈
- 고수준 모듈: 의미있는 단일 기능을 제공
- 상위 수준의 정책 구현
- 저수준 모듈: 고수준 모듈의 기능을 구현하기 위해 필요한 하위 기능의 실제 구현
고수준이 저수준에 직접 의존하는 경우
- 저수준 모듈 변경이 고수준 모듈에 영향을 줌
- 이와 같은 문제로, DIP(의존 역전 원칙)이 필요함
고수준 관점에서 추상화
- 고수준 입장에서 저수준 모듈을 추상화
- 구현 입장에서 추상화하지 말기
DIP의 이점
- 좋은 설계 가능성이 높아짐
- 고수준 모듈의 변경을 최소화함녀서 저수준 모듈의 변경 유연함을 높임
- 처음부터 바로 좋은 설계가 나오지는 않음
- 요구사항 이해가 높아지면서 저수준 모듈을 인지하고, 상위 수준에서 저수준 모듈 추상화를 시도해야 함
정리
- 기능을 알맞은 크기로 잘 나누고 조합하자
- 적절한 추상화로 유연하게 만들자
Q&A
- 리팩토링을 하면 클래스를 어느 패키지에 둬야 하나요?
- 패키지를 어디에 놓느냐는 어떤 패턴을 사용하느냐에 따라 달라질 수 있다. 즉, 규칙에 따라 달라지는데, 도메인 규칙이라면 도메인 패키지에 넣으려고 한다. 업무 흐름상 어플리케이션 로직과 관련된 규칙이라면 보통 서비스 쪽에 넣으려고 한다.
객체 지향에 대해서 깔끔하고 자세하게 설명해주셔서 쉽게 이해할 수 있었고, 중간 퀴즈도 있어서 집중하며 들을 수 있었다. 기능을 알맞는 크기로 나누고 조합하여 멋진 개발자가 되어봅시다!
댓글남기기