개요
2015년 11월 28일 KSUG(한국 스프링 사용자 모임) 에서 주최 하는 세미나를 다녀 왔습니다.
http://www.ksug.org/seminar/20151128/
세미나의 전체적인 내용은 부제목에 나와 있듯이 도메인 모델(객체지향)과 객체 설계를 통해 애플리케이션을 작성 하면 어떠한 장점이 있는지 결국 이 장점들이 Spring Framework에 다 스며 들어 있어서 결국 Spring Framework를 쓰면 될것 처럼 보였습니다.
첫번째 시간 SK planet 박성철님께서 애플리케이션 아키텍처 안티 패턴이라는 주제로 세미나를 진행해 주셨습니다.
http://www.slideshare.net/gyumee/ss-55616001
우리 업계에서 인식하지 못하는 사이에 학습되어 반복되는 애플리케이션 아키텍처 안티 패턴을 규명하고 이것들이 우리에게 어떤 고통을 주는지, 왜 이런 패턴을 우리 코드에 스며들어 사라지지 않는지 이야기해 봅니다.
안티패턴 총 6가지로 구성되어 있으며 짧게 다루겠습니다.
안티패턴
- 연통 배관(Stovepiping) : 애플리케이션의 각 모듈이 독립적으로 개발되어 다른 모듈과 로직이나 데이터를 공유하지도 않고 상호 작용 하지도 않는다.
- 스마트 DAO : 대부분의 비지니스 로직을 프로그래밍 언어가 아닌 SQL에 담고 프로그래밍 언어는 이 SQL를 준비하고 실행하고 결과를 받는 작업만 수행하는데 사용
- 뒤범벅 아키텍처 : 애플리케이션의 횡적인 설계 요소와 종적인 설계 요소가 혼합되어서 변경에 취약한 아키텍처가 만들어짐
- 긴 공개 메서드 : 클래스에 공개 메서드 뿐, 각 메서드의 크기가 너무 길다.
- 하는 놈 따로, 아는 놈 따로 : OOP 언어를 사용하고 클래스를 만들지만 사실은 여전히 구조적으로 프로그래밍을 하므로 로직과 데이터가 애플리케이션 전체적으로 분리되어 있다.
- 단일 객체 서비스(Single Class Service) : 서비스가 객체 하나로 구성되어 있고 적절하게 분화하지 않음
1. 연통 배관(Stovepiping) : 애플리케이션의 각 모듈이 독립적으로 개발되어 다른 모듈과 로직이나 데이터를 공유하지도 않고 상호 작용 하지도 않는다.
관심사에 따른 계층 설계
관심사 분리 원칙에 따라 계층도 각 계층의 관심사에 따라 설계
같은이름의 Service,Controller,DAO를 생성해서 만드는것보단 관심사로 나누어서 설계하는게 핵심
2. 스마트 DAO : 대부분의 비지니스 로직을 프로그래밍 언어가 아닌 SQL에 담고 프로그래밍 언어는 이 SQL를 준비하고 실행하고 결과를 받는 작업만 수행하는데 사용
중복, 한방 쿼리
재사용 할 수 없는 1회용 (ad-hoc)쿼리 사용으로 로직의 중복이 발생하고 유지보수성이 떨어짐
SQL로 표현되는 비지니스 로직 배제 해야함
1 | SELECT username, secword FROM users WHERE uid = 1; |
1 | SELECT uid, username, secword, firstname, lastname, regidate |
SQL에 모든 로직을 담는건 안좋다고 말씀하셨습니다. 그래서 데이터 가공은 애플리케이션에서 하고 데이터 입출력을 SQL로 쓰는게 좋아 보임
SQL 추상화 기술을 추천 (ORM, Active Record, Query Builder, Table Data Gateway)
3. 뒤범벅 아키텍처 : 애플리케이션의 횡적인 설계 요소와 종적인 설계 요소가 혼합되어서 변경에 취약한 아키텍처가 만들어짐
사용자의 요구사항과 여러 기능에 공통적으로 적용되어야 하는 모듈등에 대해서 괴리감 발생
해법1
파이프 & 필터 패턴 : 여러 단위 처리 모듈(필터)을 순서대로 나열하고 한 필터에 데이터를 입력해 얻은 출력을 그 다음 필터의 입력으로 삼도록 구성하는 아키텍처 패턴(데코레이션 패턴과 비슷)
해법2
관점 지향 프로그래밍(AOP) : 기능에 직교적인 횡적 관심사를 분리해 모듈화 수준을 높이는 기술
4. 긴 공개 메서드 : 클래스에 공개 메서드 뿐, 각 메서드의 크기가 너무 길다.
미미한 기능분화, 낮은 유지보수성, 중복 다량 발생, 단일 책임 원칙 위반
함수 작성법
- 공개 메서드는 이야기(의도, 작업 흐름) 흐름을 나타내라
- 비공개 메서드는 이야기의 의미를 정의하라
- 작게 만들고 한가지만 하라(SRP)
- 함수내 동일한 추상화 수준 유지
- 서술적인 이름 사용
- 명령/조회의 분리
- 조차 함수를 사용함 함수 수준 추상화(람다식)
클린코드 라는 책에서 나온 함수 작성법 이라고 말씀하셨습니다.
자바8의 람다식을 통해 함수도 추상화가 가능하시다고 말씀!
5. 하는 놈 따로, 아는 놈 따로 : OOP 언어를 사용하고 클래스를 만들지만 사실은 여전히 구조적으로 프로그래밍을 하므로 로직과 데이터가 애플리케이션 전체적으로 분리되어 있다.
DB의존적 애플리케이션 : 모든 상태를 DB에만 보관, 상태 조작은 SQL로 처리, 애플리케이션 코드는 단순히 인자와 SQl결과를 전달
이를 해결하기 위해 도메인 모델을 도입
도메인 모델 : 행위와 데이터를 포함하는 비지니스 영역의 객체 모델(ORM사용) 도메인 모델 도입시 메모리에서 관리가 가능함으로 메모리상에서 상태의 영속화 개념으로 바뀜 DB를 거치는것 보다 훨씬 빠른 속도로 처리 가능
6. 단일 객체 서비스(Single Class Service) : 서비스가 객체 하나로 구성되어 있고 적절하게 분화하지 않음
낮은 응집도 높은 결합
코드의 중복이 많고 추상화 수준이 낮아서 코드를 수정함으로서 발생하는 영향을 예측하기 어렵고 단일 요구사항으로 인한 변경 지점이 흩어져 있다.
클래스 추가 공포증으로 부터 벗어나자!
높은 응집도 낮은 결합
- 지역적 변경(SRP)
- 중복 최소화(DRY)
- 로직과 데이터 근거리 보관
- 변경 주기에 따른 응집
- 메시지 = 인터페이스
여기서 말하는 높은 응집도 낮은 결합이란 같은 관심사 끼리 모듈화 해놓고 서로에 대한 연결은 인터페이스로 하라는 뜻인거 같다.
- AOP를 사용해서 종적 관심사와 횡적 관심사 분리
- 조합 메서드를 활용하고 DSL을 개발하라
- 도메인 모델을 도입하라
- 큰 서비스를 작은 클래스로 분해하고 위임하라
- 높은 응집도와 낮은 결합도를 갖도록 설계하라
기타
과잉 일반화(Over Generalizing) : Object, 문자열, Map 같이 지나치게 일반적인 타입의 과용
하나님 객체(God Object) : 과도한 재사용시도, Super~ , 모든 로직이 한 객체에 다 담겨져 있음;;
편의 객체 상속 : 편의 객체를 상속함으로써 소중한 상속의 기회 낭비 인터페이스를 사용하자!
과잉 최신 기술 준수 : 온갖 최신 기술로 도배된 아키텍처, 검증되지 않은 위험한 기술, 교육비용 발생, 고객의 잘못된 요구를 무비판적으로 수용, 프로젝트 수행여력이 부족해짐(왠지 내얘기 인거같기도…)
이상 SK planet 박성철님의 애플리케이션 아키텍처 안티 패턴 이였습니다.