출처: 클린 소프트웨어

 

정적 프록시 모델

프록시 패턴의 구현목적은 Product의 Database접근과 Business logic의 분리를 위하여 사용하는 패턴입니다.

 

그렇다고 마구 사용해서는 안되는 패턴이며, 애플리케이션과 API(혹은 네트워크, 데이터베이스)의 둘중 혹은 하나가 잦은 변화가 생길때 중간 레이어에 프록시를 두어서 사용하길 권장드리는 패턴입니다.

 

위의 그림에서는 Product DB Proxy class가 user가 요청한 data를 Database에 읽거나 직접 쓰는 역할을하며, 그 가져온 data의 Business logic을 처리하는 부분은 Product Implementation 클래스를 delegate하여 사용하게 됩니다.

 

이렇게하면 장점은 Database에서 데이터를 가져오는 부분과 Business Logic부분을 따로 분리하여 관리할 수 있는 강점을 갖게 됩니다.

 

 

예제상황

Proxy클래스 다이어그램

상품에 대한정보도있으며, 이를 주문하는 시스템이 있다고 가정해 봅시다.

위의 그림에서는 상품에 대한 데이터베이스 정보와 비즈니스 로직을 처리하는 부분을 Product 인터페이스의 하위 클래스들로 구현된 클래스 다이어그램입니다.

 

또한, 주문을 처리하는 Order인터페이스가 있으며 Order에 대한 데이터베이스 정보와 비즈니스 로직을 처리하는 부분을 Order 인터페이스의 하위 클래스로 구현된 클래스 다이어그램입니다.

 

참고로 다이어그램에서 -Data로 끝나는 클래스 이름들은 Database에서 받아오는 객체의 정보입니다.

-Proxy로끝나는 하위 클래스들은 직접 Database에 접근 하는 클래스이며, -Impl로 끝나는 클래스들은 비즈니스 로직을 처리하는 부분이라고 보면 됩니다.

 

이 그림은 프록시들간의 관계를 나타내는 좀 더 응용된 프록시 패턴의 클래스 다이어그램으로 보시면 됩니다.

 

Product가 원래 존재하였는데, Order시스템 구현으로 인해서 OrderProxy에서 Order DB정보뿐만 아니라, Product의 데이터와 비즈니스 로직이 필요하여 ProductProxy를 OrderImpl에 주입하여주고, OrderImpl과 멤버필드인 item은 Product 인터페이스들을 통하여 Order와 관련된 비즈니스 로직을 처리할때 필요한 Product정보들을 받아오며 이용하는 것이 이 클래스 다이어그램의 가장 주목해서 보셔야 합니다.

 

 

프록시 요약

프록시는 사용이 간결함과 단순하지 않습니다. 프록시는 사용하기 까다롭습니다.

프록시의 이점

프록시는 매우 까다로운 특성이있습니다. 그럼에도 불구하고 매우 강력한 이점이 한가지 있는데 그것은 '관심의 분리' 입니다.

위의 클래스 다이어그램들을 살펴보시면 비즈니스로직과, 데이터베이스는 완전히 분리되어있습니다.

업무규칙과 데이터베이스 구현부의 분리가 아주 중요한 인스턴스에서는, 프록시가 적용하기 좋은 패턴이 될 수 있습니다.

 

 

 

애플리케이션은 보통 직접적으로 API를 물고 개발되는편입니다. 다만 서드파티의 API를 바로 사용하지않고 중간 레이어를 두어서 보다 추상적으로 사용하는 편이기도합니다.

단 어떤 경우에는 애플리케이션의 종속성으로 인해 레이어와 애플리케이션 관계가 뒤집어져야 하는 경우도 있습니다.

이런 종속성 뒤집기를 할때, 프록시 패턴이 적용될 수 있습니다. 애플리케이션은 프록시에 전혀 의존하지 않게 됩니다.

 

이렇게 애플리케이션과 API 사이의 관계정보는 오직 프록시에 집중되게 됩니다.

이 정보집중은 어찌보면 프록시가 악몽이 된다는 것을 의미합니다. API가 변경될때마다, 프록시도 변경됩니다. 애플리케이션이 변경될때마다 프록시도 변경됩니다. 프록시는 매우 다루기 어려운것이 되어버릴 수 있습니다.

 

차라리 자신의 악몽이 어디에 사는지 알고있는 편이 더 나을 수도 있습니다. 프록시가 없다면, 악몽은 애플리케이션 코드 전체에 퍼질수도 있기때문입니다.

 

단 프록시가 애플리케이션과 API의 철저한 분리가 이로울 때가 있는데, 스키마와 API 둘 모두 또는 어느 한쪽에서 잦은 변화가 발생하는 아주 큰 시스템의 경우는 거의 그렇습니다. 또 다른 많은 데이터베이스 엔진이나 미들웨어 엔진 위에 얹힐 수 있는 시스템도 그렇습니다. (왼쪽에서 2번째와 3번째 그림에 해당하는 말)

 

 

결론

대부분의 애플리케이션에는 프록시가 필요없습니다. 프록시는 아주 무거운 솔루션입니다.

하지만 우리는 프록시가 필요할 것이라는 것은 매우 매력적이라 생각합니다.

그런 필요가 실제로 생기기 한참전에 말입니다.

그러나 이것은 좋은 생각이 아닙니다. 특히 프록시에 대해서는 더욱 그렇습니다.

일단 퍼사드로 시작하고, 필요하면 리팩토링할 것을 권합니다. 그렇게하면 소중한 시간을 아끼고 문제를 줄일 수 있습니다.

 

 

 

유튜브 강의

youtu.be/JEcH5DhRq6U

 

 

참고했던 싸이트들

https://jdm.kr/blog/235

https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9D%EC%8B%9C_%ED%8C%A8%ED%84%B4#%EC%9E%90%EB%B0%94

 

 

의존성 역전 원칙 (DIP, Dependency Inversion Principle)

 

모든 소프트웨어 시스템, 혹은 작은 애플리케이션이라도 Layer가 존재합니다.

어떻게 Layer를 구성하며, 각 Layer마다 의존관계는 어떻게 이루어져야하는지에 대한 원칙이 있습니다.

 

 

큰 원칙으로는

 a. 상위수준의 모듈은 하위수준의 모듈에 의존해서는 안된다. 둘 모두 추상화에 의존해야한다.

 b. 추상화는 구체적인 사항에 의존해서는안된다. 구체적인 사항은 추상화에 의존해야한다.

 

 

여기서 상위수준이란, 정책의사결정과 업무모델을 포함하는 층, 재사용하기 원하는것들, 어플리케이션의 본질을 담는층 혹은, 고객의 요구사항중 내재하는 추상화, 구체적인 것들이 변경되더라도 바뀌지않는 진실의 핵심적인 내용들이 있는 Layer를 상위수준 Layer라고 합니다.

 

이런모듈이 하위모듈을 의존하면 안된다고 합니다.

- 하위모듈은 구체적인 모듈을 의미하며, 하위수준의 구체적인 모듈에 영향을 주어야하는 것은 정책을 결정하는 상위수준 모듈이어야합니다.

- 즉 상위수준의 모듈의 변경이 생겼을때, 하위수준의 모듈이 수정, 확장이 이루어지게 되도록 Layer를 구성해야합니다.

 

 

상위수준의 모듈이 하위수준의 모듈에 독립적이라면 이 상위수준의 모듈은 아주간단히 재사용 될 수 있습니다. 이 원칙은 프레임워크 설계의 핵십입니다.

 

미숙한 Layer 나누기

위의 그림은 정책이 구체적인 Layer들에 의존하여 실패한 Layer 나누기의 예입니다.

이것을 어떻게 수정할 수 있을까요?

 

 

바로 의존성역전원칙을 사용하면 됩니다.

의존성역전원칙을 적용하실때는, 상위수준에서 하위수준에 의존할때 사용하던 메서드들을 인터페이스 뽑은다음, 그 인터페이스를 상위수준에서 의존하게끔 하게 만들면 됩니다. 그리고 그 인터페이스의 구현체는 하위수준Layer에서 구현을 해놓으면 됩니다.

 

 

역전된 레이어

위와같이 의존성이역전되게되면, Utilty Layer의 변화와 Mechanism Layer의 변화가 Policy Layer에게 변화를 안끼치게 됩니다.

 

여기서 명심하셔야 할 것은, 의존성역전의 결과로 인터페이스의 소유권이 어디있는지 주목 해보시기 바랍니다.

인터페이스는 되게 사용하는층에서 가져야 합니다.

대개 한번쯤은 유틸리티라이브러리가 그것의 고유인터페이스를 소유한것으로 생각하지만, DIP가 적용된 경우에는 클라이언트(사용하는쪽)가 추상 인터페이스를 소유하는 경향이있습니다.

 

 

 

DIP가 아직 무엇인지 이해가 안되신다면 추상화에 의존하자! 이 키워드만 꼭 기억하시기 바랍니다.

구체적인 클래스는 추상적인것에 의존할 수록 좋은것이고, 반대로 추상적인클래스가 구체적인클래스에 의존하면 설계가 실패했다고 생각하시면 됩니다.

 

 

 

 

 

이제 간단한 예제2개를 살펴보도록 하겠습니다.

 

 

먼저 Button에서 감지한것을 바탕으로 외부객체에 반응을 내보내는 시스템을 만든다고 가정해보겠습니다.

흔히들 처음 목표는 아래그림처럼 버튼눌렀을때 램프를 켜는 시스템을 만들어주세요! 라고 요청이 왔을 것입니다.

하지만 이러한 요구사항에 앞서서 한번더 상위모듈 (정책, 변하지않는 메타포, 추상화) 을 생각해봅시다.

 

미숙한 Button과 Lamp

추상화를 좀 더 들어간다면, 버튼이라는것이 눌렸을때, 어떤 대상이 되었건 동작이 발생해야한다가 추상적인 개념이며 이 시스템의 상위모듈에 위치해야합니다.

즉 아래처럼 Lamp를 의존성 역전을 시켜서 버튼의 반응이왔을때 그것이 램프든, CCTV든 Motor든 어떤 외부객체라도 호출할 수 있도록 할 수 있습니다.

역시 인터페이스를 하나 만들고, 상위모듈에 두며, 그 인터페이스의 구현체는 하위모듈에 가는 방식으로 Layer가 나뉘게 됩니다.

 

Lamp에 적용된 의존성 역전원칙

 

 

 

 

 또다른 예제를 살펴보겠습니다. 레귤레이터 시스템이 있고, 현재온도에따라 히터를 틀어주거나 끄거나 하는 시스템이 있다고 가정해봅시다. 구체적인 온도계와, 히터는 밑의 하위모듈로 내리고, 상위모듈에서는 추상적인 인터페이스들로 비즈니스로직을 구성하도록하면, 상위모듈은 하위모듈에 영향을 안받게 됩니다.

 

Layer가 잘 나뉘어진 온도시스템 조절기

 

 

 

 

유튜브 강의링크

youtu.be/_uBeQkrV-wg

 

 

개발자들은 각각의 도메인분야의 개발영역이 있고, 주로 특정 도메인분야에 매진을 하는 편입니다.

 

안드로이드 개발자라면 안드로이드 앱을 개발할때 쓰이는 자바와, 안드로이드 API들

 

리눅스 커널 개발자라면 OS에 대한 지식과 디바이스 드라이버 개발 혹은 BSP 등

 

AI개발자라면 파이썬과 딥러닝분야에 대한 학습

 

서버개발자라면 Spring Framework 혹은 node js, 자바스크립트 등등

 

Domain에 따라 사용하는 주언어와 프레임워크, 학습분야 심지어 IDE종류도 천차만별로 달라지게됩니다.

 

심지어 한 평생 한 도메인에만 종사하는 개발자분들도 있으십니다.

 

과연 자기의 도메인에서만 쓰이는 것 만 열심히 갈고 닦는게 맞을까요?

 

물론 회사의 규모와 사정에 따라 한 도메인에 머물거나, 이곳저곳 다양한 도메인을 

경험하는 개발자들이 있는것처럼 개인의 사정에 따라 모두 다르게됩니다.

 

그러나 현대 Software는 점차 빠르게 변화하면서

SW개발자들에게 다양한 Domain 분야 에서의 업무를 요구하는 추세입니다.

 

Domain분야가 바뀐다면 그때 그때마다 당장에 일을 하는데 있어서 필요한 분야를 Study 하며 

따라가는게 중요합니다.

 

하지만, 전역적으로 Domain을 아우를 수 있는 그러한 SW 분야는 없을까요?

 

있습니다. 여기 제목에 쓰여져 있듯이 저는 알고리즘소프트웨어 공학이라고 생각합니다.

 

알고리즘

알고리즘

개발자가 알고리즘을 잘하면 무엇이 좋을까요?

우선 어떤 문제에 대해서 구현하는 것에 대해서는 막힘이 없게됩니다.

또한, 알고리즘 역량을 더 강화시키면, 성능을 최대한 끌어올릴 수 도 있게됩니다.

 

즉 요구사항이 주어질때 막힘없이 구현해내며, 성능을 최대한으로 끌어올려 최적화를 이루어낼 수 있습니다.

 

그렇지만 문제가있습니다.

개발자가 알고리즘역량만 발달되어 있어서 너무 구현과 성능에 치중한 나머지

간단하게는 코드가독성 부터하여 품질 중 변경용이성, 확장성 등을 놓칠 수 있게됩니다.

오히려 유지보수는 더 어려워지며 같이 일하는 동료들도 아무리 기똥찬 알고리즘이지만

이해를 못해서 생산성이 떨어지는 경우도 종종 발생하게 됩니다.

 

그렇기에 알고리즘역량 뿐만 아니라 아래의 소프트웨어공학 분야에 대한 역량역시 필요합니다.

 

소프트웨어 공학

소프트웨어 공학

알고리즘은 다들 무엇인지 아실겁니다. 다만 소프트웨어 공학에 대해서는 처음 들어보시는분들도 심지어 있으실 수 있습니다. 혹은 학창시절에 "소공은 들어선 안되는 과목이야" 라고 어디서 주워들어서 피하신분들도 있으실 수 있습니다 ^^;;

 

위키백과에서는 소프트웨어 공학을 아래와 같이 정의하고 있습니다.

 

-> 소프트웨어의 개발, 운용, 유지보수 등의 생명 주기 전반을 체계적이고 서술적이며 정량적으로 다루는 학문이다

 

아..역시 난해합니다 ㅡㅡ....제가 접하면서 느낀 소프트웨어 공학은, SW를 개발하고, 유지할때 필요한 학문들을 총괄하여 말하는 것 같습니다.

세부적인 분야로는 디자인 패턴, 요구공학, 테스트 프로그래밍, OOAD/UML, 리팩토링 등이 있습니다.

최종적으로 소프트웨어 공학의 학문들을 한번 Study해보시고 현업에 적용하시게되면 소프트웨어 아키텍트로 최종 거듭나실 수 있습니다.

소프트웨어공학분야를 접하게되는 순간, SW 개발할때 처음부터 끝까지 다 관여하실 수 있게 되거든요.

 

처음에는 Stake holder들과 미팅을 가지면서 요구사항들을 다 뽑아내고, 그들이 가장 우선시하는 품질들을 뽑아내어 기능 / 비기능 요구사항을 분리하여 정리합니다.

 

그 이후 설계에서는 어떤 디자인 패턴아키텍쳐를 사용할지 결정하고, 구현을 하게 됩니다.

구현 중간중간에서는 Code Quality를 높이기 위해 열심히 코드리뷰와 code metric을 이용하여 점수를 측정하고 올리기 위해 고민합니다.

또한 테스팅을 위해 어떤 프레임워크를 사용하며, 필수 테스팅 항목들을 뽑아내고 TC를 작성하다가, 

잘못 작성된 구현코드를 다시 수정하는등의 활동도 하게됩니다.

SW가 최종 릴리즈가 되고나서도 유지보수 단계에서 리팩토링이 들어가면서 다시한번 가독성도 올리고 Side effect도 줄일 수 있도록 훌륭하게 바꾸는 활동도 할 수 있습니다.

 

 

다시 정리해보자면 구현능력을 올리기위해선 우선적으로 알고리즘 역량을 쌓는것이 맞습니다.

하지만 SW를 정식 출시하고 유지보수를 좀 더 잘하기 위해서는 소프트웨어공학 역량을 쌓으셔야 합니다.

이 두 가지 분야는 어느 Domain이든 통하기 때문에 학습해놓으시면 SW개발자로 일하시면서 심지어 관리자로 일할때도 도 계속해서 사용하 실 수 있을것입니다.

 

 

Youtube 영상링크

https://www.youtube.com/watch?v=CqwrENwR6UM

+ Recent posts