지난 Rebecca Wirfs-Brock의 Nature of Order I를 이어 그 다음 이야기를 진행하고자 합니다.  혹시 이전 내용을 못 읽으신 분은 링크를 따라  한번 읽어보시길 권해드립니다.

워낙 방대한 내용이라, 섣불리 글이 써지지 않더군요. 철학과 생명체, 사물 (Thing)의 구성 원칙들을 기술하는 것이다 보니, 농업 / 생명 / 건축등 다양한 것을 예로 들어 설명하고 있습니다.  게다가 너무 철학적이어서, 개발자가 읽기에는 지루할수도 있죠. 아직 책을 다 읽지 못했지만, PLoP에서 정리한 노트내용과 NOO를 SW 설계에 빚대어 설명한 논문들 그리고 저의 부족한 경험을 합쳐서 용기를 내어 써 봅니다.

항상 경청하는 자세로 여러분의 피드백을 받겠습니다. 부족한 부분은 말씀해주시고, 더  좋은 의견을 주시면 관련 자료를 더 찾고 공부해서 NOO 데이터를 계속 업데이트할 욕심은 있습니다.

Alexandar가 말하는생명체가 가지는 15개의 속성

  • Levels of Scale
  • Strong Centers
  • Boundaries
  • Alternating Repetition
  • Positive Space
  • Local Symmetries
  • Good Shape
  • Deep Interlock and Ambiguious
  • Contrast
  • Gradients
  • Roughness
  • Echoes
  • The void
  • Simplicity and Inner calm
  • Not-Separateness

이전 글에서는 8 개의 속성에 대해서 다루었습니다. 이번 포스트는 남아 있는 7개의 속성을 다루려고 합니다.

CONTRAST

한 시스템에 서로 반대되는 Force들을 생성하고, 정의하는 핵심이 되는 균형점(balance points) 이 있습니다.  이것이 Contrast입니다.

여러분 시스템을 구축할때, 무엇이 Center (NOO 2원칙 – Strong Center)인지 아닌지  그리고 어디까지가 경계(3원칙 – Boundaries)인지 명확한 Contrast(Interface나 Namespace)를 만들어야 된다는 얘기입니다.

또한 작게는 객체의 Role을 정할때  Input-Output , Producer-Consumer, Transmitter-Receiver 처럼 명확히 나눌수 있는 부분을 나누는 것이 Constrast를 지키는 좋은 예가 됩니다.  (리펙토링을 할때 패턴이 아주 유용하게 쓰이는 이유가 여기 있습니다. 이미 유사한 문제들의 해결책으로 객체들을 역할별로 잘 나누어 놓았고, 이것들이 어떻게 상호작용하는지 까지 잘 설명해 놓았기 때문이지요.  Contrast의 좋은 예라고 생각이 듭니다.)

제가 몇몇 후배들을 멘토링할때, 다들 객체 지향의 핵심이 재 사용이라고 수업을 들어서 그런걸까요? 너무나 과도하게 재사용에 초점을 맞추어서, 오히려 하나가 변경되면 여기 저기 변화가 전파되는 거미줄과 같은 객체들의 지도를 만든 것을 종종 보았습니다. 즉 Contrast가  명확하지 않는 시스템을 만든 것이죠.

좋은 시스템을 구축하기 위해서는  큰 그림자 부터 작은 그림자 까지 다 보아야 합니다.  즉 크게는 Layer – Namespace로,  작게는 Object  – Function 까지,  더 작게는 변수, 상수의  Naming까지 신경써서 명확한 Contrast를 만들어야 합니다.

그래서 후배들의 코드를 멘토링할대, 시스템의 큰 카테고리를 Namespace로 구분하고, 이들 Namespace들을 적절히 Layer화 하는 작업등을 진행했습니다 (Layer화 하는 이유는 객체와 객체가 바로 호출하는 Direct-Call을 없애기 위해서죠 ) . 그리고 Layer를 구축하면서 Dependency 문제를 신경써야 합니다. (Circular Dependency를 막기 위해 하위 Layer에서 상위 Layer로 호출하는 Up-Call, 또는 Layer의 인터페이스를 거치지 않고 바로 객체간에 콜하는 Direct-Call 등을 막고 제어할 필요가 있습니다. )

저의 경험으로는 Tightly Coupling 되어 있는 시스템을 나누기 위해서는 여러가지 Testing 기법이 전방위적으로 사용되어야 하지만, 잘 시작하기 위해서는 전체 지도를 볼수 있는  Dependency Structure Matrix, Code Metrics 와 같은 다양한 View가 필요합니다.   (이 문장이 이해가 가시지 않으시면 일전에 기고했던 “어디가 꼬여 있는거야? 누가좀 가르켜줘 – Dependency Structure Matrix” 를 참고하시면 도움이 될듯 합니다. )

GRADIENTS (점진적인 변화)

급격한 변화보다는 점진적인 변화가 쉽게 이해할 수 있고, 제어하기도 용이합니다.

바로 점진적인 변화의 중요성을 언급하는 원칙입니다.

산을 올라가면, 서서히 추워지고, 기압 역시 저기압으로 바뀝니다.  고산지대(NOO에서는 히말라야를 예로 듭니다)를 생각해 봅시다.  산 아래에는 나무들과 여러 생명체들이 많이 살지만 , 중턱에는 풀과 바위만 있고, 결국 정상에 가까워 지면 결국 바위 눈, 얼음만 남아있게 됩니다.  이러한 것이 자연이 추구하는 점진적인 변화의 좋은 모습이라고 NOO에서는 언급하고 있습니다.

이러한 점진전인 변화를 지키지 못해 불편함을 느낀 경험이 있으신가요?  Component간에 데이터를 주고 받을 때, 너무 상이한 구조로 되어 있어서, 데이터를 변환해서 전달하고 있지는 않으신지요?  만약 특정 컴포넌트를 호출하기 위해 너무나 많은 데이터를 여기저기 가져와서 만들어 줘야 한다면, 이것은 Gradients 원칙을 잘 준수하지 못한 것입니다.  Software 시스템간에 데이터가 부드럽게(smooth) 전달되어야, 쉽게 요구사항들을 추가, 변경, 확장 할수 있습니다.

이러한 부드러우면서 점진적인 변화는 프레임워크 여기저기에서 볼수 있습니다. Framework 사용자의 Learning Curve를 줄일때 중요한 척도가 됩니다.  예룰 들어  Text 포멧의 파일을 쉽게 처리한 경험으로,   Binary , XML 등 여러 포멧들을 쉽게 다룰수 있다면 ,  점진적인 변화를 잘 따른 것이죠. Gradients 원칙을 잘 준수하기 위해서 추상화를 어떻게 적절히 하느냐가 관건이 됩니다.  많은 분들이 공통적인 요소를 뽑아 추상화를 하는 방법도 있지만, 사용자가 기존에 익숙히 써오던 형태로  새로운 시스템을 잘 Wrapping하여 쉽게 쓸수 있게 만드는 것이 매우 중요하다고 볼수 있습니다.

이때 우리 설계자들이 추상화 또는 캡슐화를 할때 종종 하는 실수가 있습니다.  바로 너무 과도한 추상화/캡슐화는 하는 것이지요.   노출해야 할 것은 적절히 노출해 주는 것 역시 중요합니다. 여러분이 만든 설계이 산물 (Framework나 Library)들이 사용자들이 사용하기 위해  내부 구조를 다 파헤쳐야 한다면, 잘 설계된 것은 아니겠죠. 적절한 균형을 잡는 것은 항상 어려운거 같습니다.  🙂   도메인과 사용자에 대한 풍부한 경험이 있어야만 가능한거 겠죠.

ROUGHNESS (다듬어 지지 않은)

소프트웨어 에서의 견고함이란 무엇일까요? 우리는 견고하다면 돌로 된  거대한 성이나, 아니면 튼튼한 금고를 생각할수 있을 겁니다. 하지만 Nature of Order에서는  견고함을 다르게말하고 있습니다.

예측하지 못한 사건/사고로 인해 시스템이 정지되지 않고,  그 충격을 흡수할 수 있는 것이 견고한 시스템이며, 이러한 시스템은 작은 변화들을 흡수할 수 있는 느슨함 (Slack)을 가져야 된다고 말하고 있습니다.   마치 뿌리깊은 단단한 나무보다, 잘 휘는 갈대가 더 견고하다고 말할수 있습니다.

  • Egoless Way (비이기적인 , 즉 객관적인 방식) / Non-Mechanical  (비기계적인.)

주어진 환경에 맞게 자연적으로 외부 변화/충격에 적응하기위해 어떤 요소가 중요시 되는 것이 아닌 Egoless way (비자아적인/비이기적인 방법) 으로 구축되어야 하며, 자연적으로 생성, 진화하기 위해서 체계적인 정교함(non-mechanical)이 아닌 올바른 위치와 형태를 찾아 자리를 잡을 수 있게 하는 것(고려하는 것)을 의미합니다.  이것은  Gerald Weinberg의 The Psychology of Computer Programming (역서 – 컴퓨터 프로그래밍의 심리학) 에서 언급하는 Egoless Programming과 일맥 상통합니다.  프로그래머라면 누구나 자신이 만든 컴포넌트/모듈/프로그램에 대한 애정을 가지고 있는데, 이러한 애정때문에 피드백/평가/비판을 받기 거부한다는 것입니다.    이러한 감정이 투여된적이 많으실겁니다. 저도 그러한 사람중에 하나구요. 🙂

마찬가지로 소프트웨어 특정 요소가 주어진 환경에 맞게 변화를 흡수할수 있어야 하는데,  직급, 정치 적인 구조로 A에서 바꾸어야 할 내용을 다른데서 바꾸는 경우를 종종 봅니다. Network Middleware에서 바꾸면 쉽게 바꿀수 있는데,  직급, 정치, 담당자가 바쁘다는 이유로 인해 전혀 다른 곳에서 바꾸기 시작하면 바로 아키텍쳐는 무너지고, 이상한 괴물을 만들기 시작하죠.

그래서 코딩스타일 가이드라인등을 정해 모두의 동의를 구하고, 지켜지지 않으면 Static Analysis Tool로 컴파일도 안되게 막아 버리기도 하죠.   하지만 이러한 강제성보다는  이기적인 감정을 버릴 수 있는 팀원들로 구성될수 있는 문화를 만들어야, 좋은 소프트웨어가 나올수 있을겁니다.

결국 비이기적인 팀원들로 구성되어 있어야, 비이기적인 즉 합리적인 소프트웨어가 나올수 있음을 의미합니다.  많은 SI 프로젝트에 발주되는 제품들이, 고객의 요구사항에 맞게 다시 한번 최적화, 기능 추가, 다듬는 작업을 합니다.  이러한 것을 hand-crafting이라고 부를수 있는데, 전형적인 Roughness의 원칙을 따른 경우라 볼수 있습니다.  결국 고객의 요구사항을 미리 정확히 알수없기에, 완제품을 만들수 없고,   이러한 방법을 취할수 밖에 없지요.

ECHOES(서로 반복되면서 발생되어 진다)

우리가 안소니 홉킨스같은 배우를 볼때 정말 연륜과 따뜻함이 느껴지는 얼굴을 볼수 있습니다.  어렸을때 우리가 봤던 할아버지의 따뜻함은 어디에서 나올까요?

원래 인자하시기도 하시지만, 그분들의 주름과 너털웃음이 너무 잘 어울려서 그런건 아닐까요?  만약 주름이 눈가에만 있다면, 인자하게 보였을까요? 주름이 얼굴 여기저기서 반복되어 나타나고, 이것이 삶의 고된 나날과 경험들이 모여 연륜이라고 느껴지게 하는 것이지요.

Echoes는 복잡한 시스템이라고 하더라도, 공통된 원칙, 주제, 가이드라인이 크기의 차이가 있을수 있지만, 이것들이 반복되어 이루어 짐으로써, 그 시스템을 더욱 안정되고, 견고하게 만듭니다.  물론 원칙을 적용한 크기나 범위가 각각 다를수 있지만, 원칙/가이드라인들이 일관성있게 적용되어지고, 서로  연계성을 가지고 상호작용을 한다면 좋은 시스템이 될 것입니다.

Rebecca는 SW에서 Echoes 원칙에 의해, 반복되어지는 사례들을 언급했습니다.

  • Interface – 인터페이스를 통한 유연성확보
  • metaphor – 메타포어를 적용해, 시스템을 좀더 쉽게 이해하고 사용할수 있게 만든다.
  • Intentional names – 미리 서로 약속하여, 잘 정한 네이밍들.  (즉 coding standard, code convention)
  • Relationship – 연관 관계를 어떻게 구성하느냐? (Level of Scale에서 언급한 것처럼, Scale이 다른 시스템을 어떻게 연동할 것이냐?)
  • Responsibility를  나누는 방법 ( helper/holder method, classes, component, services)
  • 어떻게 exception과 error들을 handling 할지..

이러한 원칙들이 잘 수립되어 있고, 시스템 전반에 걸쳐, 일관성있게  반복되어 적용되어져야, 견고한 ( 변화에 유연한) 시스템을 구축할 수 있습니다.

THE VOID (성장을 위해 공백이 필요하다.)

NOO의 원칙들이 동양철학과 매우 유사성이 있는거 같은데, VOID는 더욱 그러한거 같습니다.   흔히 우리가 말하는 “여백의 미”가 바로 VOID의 의미입니다.  여백이 있어야  시스템이 확장가능하고 성장할 수 있음을 말합니다.

우리가 운전을 할대 앞에 있는 차와 안전 거리(공간)를 유지하는 것은  어떠한 돌발 상황이 앞에서 발생할지 모르기 때문입니다.  다른 말을 하자면, 어떠한 변화가 발생할지 모르다는 것이지요.

즉 시스템이  요구사항을 계속 받아들이고, 성장하기 위해  어떠한 변화를 흡수할수 있게 확장할 수 있는 공간들을 구성해 두어야 합니다. 그래서 인터페이스 지향적인 프로그래밍을 하는 것이고,  또한 Parameter Object를 이용해  Signature가 변경되지 않게 변화를 흡수하는 기법들을 이용하는게 VOID의 좋은 예입니다.

전, NOO 첫번째 포스트에 언급했던 Strong Center가 바로 이 VOID의 원칙과 맞불려 있음을 깨달았습니다. 위에 있는 소용돌이 그림을 보면,  소용돌이 중심은 텅 비어 있습니다.  마치 태풍의 눈 처럼 중심 부분(Strong Center)는 비어있지만, 그 주위는 굉장히 강력한 힘을 발휘하죠.

즉 Feature와 같은 Boundary 단위마다 Strong Center가 존재하고, 이 Strong Center는 강력한 힘을 발휘하기 위해 많은 모듈을 다 호출하는 모습이 되어서는 안된다는 것입니다.   오히려 전체적인 흐름을 제어하기 위해,  잘 추상화되어 있어야 된다는 것 (즉 변화를 흡수할수 있도록, 확장성있게 되어 있어야)을 의미합니다.

이것은 저희 사람의 관계에서도 자연스럽게 들어납니다.  자신의 부족함을 알고 자신의 것을 비워야, 다른 사람의 생각과 의견들을 받아들여야 성장할 수 있습니다.   자신의 생각이 맞다고 주장하면서 다른 사람의 의견을 무시하고 배척하는 사람은 성장하기 힘든 이치와 같습니다.

비움의  미학을 깨닫게하는 큰 원칙인것 같습니다.

SIMPLICITY AND INNER CALM (간결함과  고요한 내부)

 

Simplicity and Inner Calm 은 가능한 시스템을 간결(simple)한 상태로 계속 유지하는 것을 의미합니다.  시스템이 Goal과 요구사항을 달성하기 위해 부합하는 필수적인 요소들로만 구성되어 있어야 함을 의미합니다.  이렇게 하면 자연스럽게 구성요소들이 하모니를 이루면서 Inner Calm(내부가 고요해짐)하게 되어진다는 것입니다.

간결함의 중요성은 소프트웨어 업계뿐만 아니라, 여러 곳에서 계속 언급되어 왔습니다.   대표적인 원칙으로 아래와 같은 것이 있습니다.

간결함을 유지하기 위해서, 끊임없이 System을  관리해야 합니다. 요구사항이 변경, 확장됨에따라,  새로운 것을 추가하고, 사용하지 않는 요소들은 버려야 된다는 것입니다. 새로운 것을 추가할때, 시스템의 아무런 가치도 주지않는 구성 요소를 추가하지 않는지, 시스템에 더이상 필요하지 않는 것인데 계속 나두고 있는 것은 아닌지, 지켜봐야 한다는 것입니다.

  • 개발자 입장에서는 Refactoring과 Clean Code를 만들기 위해 노력을 해야 겠죠. 몇몇 개발자의 취향을 만족시키는  특수한 기능들을 남용해서  사용하면 안됩니다.  왜냐면 그것으로 인해 전체 시스템의 조화가 깨질수도 있기 때문이죠.
  • 아키텍트 입장에서는  이러한 상태를 유지하기 위해  DSM, Code Metrics와 같은 다양한 지표를 통해, 특정 Feature가 과도하게 커지거나, Dependency 관계를 잘 제어해야 합니다.

또한 “소프트웨어 아키텍트가 알아야할 97가지”에 Simplicity에 대한 좋은 조언으로,  “간단한 것은 간단하게 해라” 라는 조언이 있습니다. 핵심을 말하자면, “간단한 문제를 복잡한 해결책으로 풀지 말라”라는 이야기입니다.     미래에 일어날 일 때문에  정작 필요하지 않는  설계/리소스/정책들을 넣어두지 말라는 것입니다.   간단한 위젯 프로그램을 만들면서, 동적으로 모듈을 변경하기 위해 과도한 계층화를 쓰는 우를 범하지 말라고 조언하고 있습니다.

제가 이 원칙을 보면서, 너무나 과도한 Simplicity는 경계해야 된다는 생각이 들었습니다. 일전에 “추상화를 한다는 것은 복잡한 것을 다 감추는 것이 아니다.  적절하게 노출한 부분을 적당히 노출하는 것이 중요하다 “라고 언급한 것 처럼, 시스템을 사용하는 사용자의 입장에서 Simplicity를 유지해야지, 너무 과도한 Simplicity를 추구하다 보니, 확장성이나, 변화를 줄수 있는 여지까지 없에서는 안되겠죠.  Simplicity의 기준은 해당 도메인의 사용자가 적은  Learning Curve로도  쉽게 사용할수 있음이 아닐까요?

Not-Separateness (나뉘어 지지 않는다.)

실 세계의 시스템중 완벽히 독립적인 시스템은 없다는 것입니다.  어떤 시스템이라도 작든 크든, 더 큰 시스템 또는 더 작은 시스템과 연결되어 있음을 의미합니다. 우리가 한개의 레벨에만 초첨을 맞추면, 전체적인 Goal이 무너지므로, 시스템 전체과 일관성을 유지하여 구축되어야 함을 의미합니다.

즉 설계자는  관계(연관성)에 초점을 맞추어 살펴볼 필요가 있다는 것입니다.

이것은 바로 Pattern Languages의 철학과 일맥 상통합니다.  Fault Tolerant Pattern의 저자인 Bob Hanmer가 언급했던 특정 문제를 해결하기 위해 패턴을 적용하다 보니, Side Effect가 발생해 그 문제를 해결하기 부수적인 패턴 또는 Idiom(링크의 Problem/Solution 섹션 참조)이 생길수도 있습니다.  당연히 여러가지 요구사항들이 결합되어지면, 여러가지 패턴들또는 설계가 서로 결합되겠죠.

시스템들간의 관계들을 전체적으로 관리/감시하고, 가이드를 주는 것이 설계자의 역할일 것입니다. 설계자가 모든 코드를 일일이 다 볼수도 없을 것이며, 그렇다고 Architecture Diagram만으로 시스템이 제대로 구축되고 있는지 판단할수 없을 것입니다. 그래서 필요한게 1000 피트의 뷰 (원문은 링크를 참조)입니다.

Erik Doernenburg 는 1000피트 뷰를 다음과 같이 설명했습니다.

많은 이들이 UML로 그려진 아키텍처 다이어그램을 사용합니다. 하지만 아키텍처 다이어그램에서 작은 상자들은 전체 시스템을 나타내며 상자 간의 선은 시스템 간의 의존성, 데이터 흐름, 버스와 같은 공유자원 등 모든 것이 될 수 있습니다.  마치 비행기에서 보는 풍경과 같은 30,000피트 뷰입니다. 너무나 추상화되어 있는 관점이죠.

반면에 0피트, 즉 바닥 레벨의 뷰를 보기도 합니다. 즉 소스 코드를 보는 것이지요. 바닥 레벨의 뷰는 연관 있는 몇 개의 객체 구조도 보지 못할 정도로 너무나 많은 정보를 제공합니다.  즉 이 두 뷰는 소프트웨어 품질에 대한 많은 정보를 제공하지 못한다는 것이지요. 그래서 0피트와 30,000피트 사이에 적절한 뷰가 필요합니다.

바로 1,000피트의 뷰입니다. Dependency Structure Metrics로 모듈 간의 의존성을 파악할 수 있으며 Code Metrics를 이용해 클래스의 크기를 파악할 수 있습니다.  특정 클래스가 거대하다는 것은 너무나 많은 책임(역할)을 가지고 있다는 의미죠.

이러한 다양한 지표들(클래스 팬아웃, 메소드 개수, Circular Dependency 등)을 지원하는 사용 툴들(NDepend, XDepend, JDepend)을 이용하면 됩니다.

제가 계속 언급해오던 DSM, Code Metrics 이야기입니다. 이것으로 시스템의 전체 지도를 살펴보고, 특정 지역 (모듈, 네임스페이스등..)에 문제가 발생하면 코드 레벨까지 내려가서 살펴보아야 겠죠.

어떻게 보면 최종의 결과물이자, 어떻게 보면 시스템을 파악하는 가장 좋은 지표가 바로 “관계”가 아닐까 쉽네요.  현재 국내의 실정은 QA 팀에서 DSM을 보면서, Circular Dependency, Backward Depedency가 발생하면,  문제가 있으니 개발자에게 고치세요 라고 말을 해주는 곳까지는 본적이 있습니다. 하지만 어떻게 해야 이것이 그 상황에 맞게 나쁜 의존성을 끊고 관계를 잘 맺을수 있는지 가이드를 주는 분이 별로 없는 상황이죠.

Kent Beck이 이 Relationship (Relating)에 대해서 정말 깊은 고찰을 해주셨습니다. 그때는 크게 와 닿지 않았는데, 정말  NOO를 보고 더 깊이 와 닿네요. (저의 무지함에 고개를 떨굽니다. )

Kent Beck 은 Relating을 할때, 어떠한 Benefit이 있는지 초점을 맞추어 설계를 하고 한 적이 있습니다.  결국 수많은 관계중에 상황에 맞게 어떠한 Benefit에 초점을 맞추어 관계를 정할지를 결정해야 되는게 설계자의 역할인거 같습니다.

옷장수님의 블로그에 보면 Responsive Design에 대한 후기가 나와 있는데. 관계에 대해 많은 것을 생각해 볼수 있습니다.

  1. Coupling
  2. Cohesion
  3. Safe Steps
  4. Clear Stages – Leap/Parallel / Stepping Stone /Simplification
  5. Bi-Directional
  6. Isolate Changes
  7. Interface or implementation

Kent Beck 님의 블로그에 Responsive Design 카데고리를 보시면 조금 더 깊은 생각을 음미하실 수 있을 것 같습니다.

맺으며..

정말 저에게 힘들면서도, 때로는 지치면서도, 기나긴 포스팅을 마칩니다.  여러분에게 정말 도움이 되셨는지 모르겠네요.

조금이나마 설계를 하시는 분들에게 도움이 되길 바라며, 생각할 거리를 던져 드리는 계기가 되었으면 합니다. 아직 저 역시도 많이 부족한 사람이라 글 곳곳에 부족함이 보입니다.  좋은 피드백이든 나쁜 피드백이든 달게 받겠으니 주시고, 큰 일을 끝냈으니 이제 좀더 자유롭게 짧은 Posting으로 자주 뵙도록 하겠습니다.

다만 인식 공격성의 글이나, 상처가 주는말은 자제해주시고, 많은 분의 깊은 가르침 부탁드리겠습니다.

Join the conversation! 3 Comments

  1. 오전 개인 시간을 이 글을 읽는데 모두 썼는데도 전혀 아깝지 않은 글이네요.
    마지막에 쓰신 글을 보니 짓꿎은 분들이 꽤 있으신가 보네요. 아무것도 하지 않고 비난만 하는 사람에게는 관심도 아까운 법이니 적당히 외면하시라능;;

    개인적으로 이 주제에 대해 좀더 파고들어 보고 싶어지네요. 좋은 글 감사합니다.

    답글
    • 도움이 되셨다니 정말 기쁘네요..
      너무 심오한 주제가 아닐까 걱정을 많이 했지만, 긍정적인 피드백을 주시니 posting을 한 보람이 크네요.
      정말 감사합니다. 🙂
      이런 저런 후기나 깨달음, 새로운 시각들을 공유해주시면 더욱 고맙겠습니다. ㅋㅋㅋ

      답글

댓글 남기기

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.

카테고리

Alexandar, My Thinking, News, Pattern, Software Architecture, Software Engineering

태그

, , , , , , , , , , , , , , , ,