J님이 생각하고 있던 문제의 경우는 기존 서비스에서 필요한 부분을 추출하여 신규 서비스에 적용하여 활용할지가 초기에 공유한 고민이었다. 신규로 서비스 제공하려고 하는 것은 국내의 경우 판매 사이트가 없어 영업부서 분들이 Excel, 이메일, 전화를 할용하여 진행되던 것을 서비스화 하여 이를 기존 서비스와 연동하고 또한 이를 제품으로서도 판매하려고 하는 것이었다.

이야기를 나누다 보니 결국 신규로 확장 구현하시는 모듈과 기존의 시스템을 어떻게 연계할 것인가에 대한 고민이 크셨던 것 같다. 특히, 기존 시스템은 회사에서 활용하고 계신 시스템이라 크게 변동이 일어나지 않기를 바라시는 것으로 파악되었다. 그러면서도 신규로 개발되는 시스템과의 효과적인 연동에서 수정이 많이 발생될 것으로 파악하시면서 결국 가장 중요하게 생각하시는 수정 용이성(modifiability)에 집중하시는 것이 중요하다고 생각이 되었다.

논의하면서 J님이 얻는 아키텍처적 결정은 Flux 혹은 MVVM 모델로 가져가는 것이었다. 이는 J님도 알고 계셨던 MVC에서 로직 처리의 흐름을 한방향으로 가져가게 한다는 추가 아이디어를 공유함으로서 많은 에너지를 얻으신 것 처럼 보였다. 기존 서비스와 추가 서비스의 구조와 시나리오를 보았을 때에는 MVC와 같은 구조에 빗대어 보는 것이 이해가 쉬웠다. 신규로 서비스를 추가하려는 것이 기존 서비스를 View가 되고,  신규로 추가하려는 서비스가 Model과 Controller 역할을 하는 것으로 파악되었다. 그렇다면, 기존 서비스는 고정하고 우리 서비스는 계속 변하더라도 영향이 덜 받는 구조로 만들어야 한다고 함께 판단하게 되였다.

Legacy System. 저희 회사에서도 종종 기존의 시스템으로 다루기 어려운 것이라는 느낌이 강하지만, 결국은 담당하고 있는 저희들은 Asset이기도 하다. 하지만, 여기에 숨겨진 Debt가 어떤 것인지 몰라 두려움을 느끼게 하기도 하는 것 같다. 결국은 우리가 집중해야 할 곳이 어디인지 찾고, 그 부분에 대해서 어떻게 대응할 것인지 판단하는 것이 Legacy System을 Asset으로 만드는 방법이라고 아닐까 생각한다.

iOS를 기반으로 사진을 편집하는 기능을 포함하는 앱을 개발하는 D의 사례를 살펴 보자. 이 분은 본인 포함 3명이 개발을 하는 팀인데, 스크럼기반으로 스프린트를 운영하면서 요구 사항들을 지속적으로 앱에 적용하고 있었다. 이미 리팩토링을 통해서 구조를 개선을 하였지만, 여전히 새로운 요구 사항에 대한 중복 코드가 늘고 유연하게 대처 안되고 비즈니스 로직 분리하여 추상화 중복 코드 제거하고 싶어 하였다. 궁극적으로는 시장 릴리즈 이후 품질 이슈나 QA 중 예상치 못한 이슈를 최소화 하시고 싶어했다.

원 포인트 세션 중에 문제를 구체화 하고 날카롭게 하는 것이 필요해 보였다. 이야기 할 수록 이상했던 부분은 어떻게 해야 할지 다 알고 계신 것이 보였다. 문제 중 하나는 Undo/Redo하면서 중복 호출되는 코드의 상세 사항으로 들어 갈 수록 이 부분을 리팩터링하면서 효율화 하고 싶다는 것을 알 수 있었다. 즉, 해야 할일에 대해서는 이미 알고 있어 보였다. 즉, 관련 부분을 추상화하고, 중복 코드도 제거하여 향후 코드 파악이쉽고, 추가 요구사항에 대응이 용이하게 하는 것이다. 하지만, "실행"하는 것이 문제였다. 여러 이야기가 있었지만 본인 포함 3명의 개발자로 신규 요구 사항을 스프린트 내에서 소화하고 이러한 부분을 함께 진행하시는 것에 부담이라는 것이다. 이러한 상황이라면 어떻게 할 수 있을까?

우리는 "작게 해볼 수 있는 것"을 찾아 보게 되었다. 작게 나누어 해볼 수 있는 방법에 대해 이야기 나누었다. 그러면서도, 제품으로 적용되어 진행 될 수 있도록 하는 것이 목표였다. 이렇게 하기 위해서 중복되더라도 작게 개선해 가는 방법에 대해서 상세하게 이야기를 나눴다. 개선해야 하는 객체들이 여러가지가 있었는데, 변경하는 도중에는 개선한 것과 개선하지 않은 객체들이 중복해서 존재하지만 개선이 되어 가는 방법에 대해서 이야기 나누었다. 이렇게 하기 위해서 이 작게 나뉜 리팩터링 작업을 스크럼의 백로그(Backlog)로 만드는 방법에 대해서 이야기 나누었다. 그러기 위해서, 이해 관계자(Stakeholder)와 이를 공유하는 것도 이야기 나누었다. 이러한 논의를 통해 D는 좀 더 자신감을 얻었다. 

상품화 된 소프트웨어 제품을 개선하는 것에 대해서 "달려가는 기차의 바퀴를 바꾸는 일"이라는 비유를 들은 적이 있다. 상황의 어려움도 있지만, 문제와 관련된 다양한 리스크가 많기 때문 일 것이다. 이를 위해서는 우리가 리스크에 대한 걱정을 줄이는 것이 중요하다. 이 부분을 통해 자신감이 높아지는데 도움이 되기 때문이다. 또한, 이렇게 우리가 걱정되는 것이 있다면 작게 시도해 보고 실패하고 계속해서 시도하면서 우리가 개선하는 것에 대해서 학습하는 것이 효과적이다. 수백kg에 해당하는 펀치를 한번에 받아 내는 것 보다는 수백g의 작은 펀치를 여러 번 나눠 맞는 것이 끝까지 살아 남는데는 더 나은 선택이기 때문이다.

요즈음 데이브 스노든의 커네빈(Cynefin) 프레임워크 책[1]을 다시 읽고 있다. 커네빈은 명확(Clear), 복합(Complicated), 혼돈(Chaos), 복잡(Complex)의 네 가지 영역 중 어느 하나에 속할 때 취할 수 있는 적절한 조치가 있다. 이는 아래 그림에서도 잘 설명되어 있다.[2]. 

Vige 버전 커네빈 프레임워크[2]



하지만, 나는 아포리아/혼란(Aporia/Confused) 영역에 대해서는 다른 곳에서 설명을 듣지 못했다. 이부분을 커네빈 책에서는 4개의 커네빈(Cynefin) 영역에서 자신이 어디에 위치해야 할지 모르는 상태로 정의하고, 결정을 내리거나 적절한 조치를 취하기가 어려운 상태라고 한다.
  
커네빈 책[1]에서는 이와 관련해서 2가지 옛날 이야기를 한다. 하나는 곤과 우의 치수 이야기와 도덕경의 무지용(無之用)을 언급하며 설명한다.  
  
중국 고대 신화인 곤과 우의 치수 이야기에서 곤은 10년 동안 강을 따라 정교한 둑 시스템을 구축했다. 곤의 접근 방식은 통제와 통치, 질서를 강조하는 유교적 방식으로 종국에는 황하의 물살을 통제할 수 없었기 때문에 모든 둑은 실패로 돌아갔다. 반면에 곤의 아들 우는 물의 흐름을 엄걱하게 통제하려는 대신 "물을 주인으로 모시고 물의 길"을 따르는 방식으로 접근했다. 즉, 그는 전문가인 농부들과 함께 일하고, 서민들과 함께 자고, 먹으며 그 상황과 풍경을 이해하고자 노력했다. 즉, 하나의 둑 대신 복잡한 관개 수로 시스템을 구축해서 황하와 평행하게 이어지는 많은 제방으로 구성되어 홍수로 범람한 물을 활용할 수 있었다고 한다.  
  
도덕경 11장의 무지이위용(無之以爲用)은 크리스토퍼 알렉산더의 Nature of Order의 15개 속성 중에서 The void와 연결하여 이해할 수 있다. 즉, 없는것/비어 있는 것이 (실용적으로) 사용된다는 의미로 이해할 수 있다. 어렵겠지만, 책에서 무위(無爲)로 받고 치수 이야기로 빗대어 설명한다.
  
데이브 책의 8장에서는 아포리아/혼돈 상태에서 가능한 행동을 무위(無爲)로 언급하는데, "행동하지 않는 행동" 또는 "노력하지 않는 행동"으로 이이기 한다. 다시 물의 흐름을 통제하려 하기보다는 '물의 흐름을 따르는' 자연주의적 접근으로 가장 자연스럽고 수월한 행동이 나타날 수 있도록 의식적인 무위(無爲)라고 설명한다.  
  
어려운 이야기이다. 하지만, 간단히 이야기 하면 행동 계획을 세우기 어려운 상황이면 아무것도 하지 않거나 흘러가는데로 잠시 둘 필요가 있다는 것으로도 해석할 수 있겠다. 앞에 그림에서도 보면 조금더 명확해 지기 까지 낭떨어지를 따라 떨어지거나 태풍을 따라 날아가 볼 수도 있을 것이다. 하지만, 어딘가로 떨어질지 관찰하고 실험해야 할 것이다.   
  
즉, 이러한 상황이라면 무력해 지지 말고, 내가 모른다는 것에 익숙해지고 무위를 실행해야 할 상황임을 인식하고 매듭을 지어 보는, 그리고 비워 보는, 흘러가는데로 두어 보는 접근법도 가능하겠다.  

참고 문헌
[1] Dave Snowden et. al., "Cynefin® - weaving sense-making into the fabric of our world," Cognitive Edge Pte Ltd, Oct. 26, 2020
[2] Vige 버전 Cynefin Framework, https://static1.squarespace.com/static/5c4713ea1137a655bbd36a6b/t/61822121bb1fdd6e8a670005/1635918132167/Cynefin-EBB-Full.png

같이 교육을 받았던 프런트엔드 엔지니어 J의 사례와 연결된 이야기를 해보려 한다. 이 분은 여러  커뮤니티 활동을 하시는 것으로 보였다. 그중 하나의 커뮤니티에서는 참가자들의 만남을 이어주는 여러 이벤트가 있었다. 이 분은 이 만남과 관련된 자동화에 기여하시고 있었다. 이 기능은 Typescript 짠 코드였는데, 당시는 관리자와 본인의 컴퓨터에서 자동화 스크립트로서 동작하였다.

물론 잘 동작하는 코드였지만, 이 코드를 "적절한 설계 없이" 만들었다고 생각하신 듯했다. 그래서, 공유해 준 고민은 "좋은 구조로 만들고 싶다"였다. 나는 이러한 상황을 "구조가 없음"이라고 이해했다. 우리의 이야기는 "이 부분을 어떻게 개선하는가"가 포인트였고, 원 포인트 세션 논의를 통해서 개선 방향을 잡았다. 세션을 하고 난 얼마 후 이야기 나눌 때에도 계속해서 그 방향으로 발전시키고 계셨다. 모듈화를 하였고, 데이터를 원격에서 가져오는 작업, 서버에 스크립트를 채팅 어플의 봇(bot)으로 올리는 계획을 세우고 있었다.

하지만, 이 글에서 이야기하고 싶은 주제는 위에서 이야기한 개선 방향은 아니다. 그것보다는 우선 "구조가 없음"이라는 부분에 대해서 이야기를 해보고 싶다. 왜냐하면 많은 사람들이 간과하지만 "모든 소프트웨어에는 구조가 있기" 때문이다. 여기서 이야기하는 소프트웨어 구조는 동작하는 소프트웨어가 가지고 있는 구조에 대한 것이다. 즉, 개발자가 요구 사항에 따라 고민하고 구현하면 구조는 발생한다. 물론, 객체 지향 프로그래밍(OOP), 디자인 패턴(Design Pattern)과 같은 경험 많은 사람들이 찾아낸 내용들을 포함하는 것이 조금 더 좋을 수 있다. 하지만, 우리가 처리해야 하는 기능을 잘 처리하고 있고 동작하고 있다면 이미 "구조"를 가지게 되는 것이다. 그렇다면, 정말 좋지 않은 구조라면 의미가 없는 것일까?

여기서는 많은 사람들이 좋지 않다고 하지만 실제로는 많이 존재하는 구조 한 가지를 살펴보자. 큰 진흙뭉치(Big Ball of Mud)라고 부르는 구조이다. 이 구조는 소프트웨어가 모듈의 구분 없이 한 덩어리로 되어 있는 경우이다. 위에서 이야기 한 사례의 경우, 소스 코드는 유틸리티 기능을 제외한 코드가 하나로 되어 있었다. 그러므로, 큰 진흙뭉치에 해당한다고 할 수 있겠다. 기능이 동작하게 하는 것이 먼저 여서기 우선 필요한 기능들을 모두 모아서 구현했을 가능성이 높다. 기간도 부족하고 요구 사항도 불분명했을 가능성도 높다. 아마도 구현한 사람 이외에는 문제점을 수정하기 어려워 매우 낮은 유지보수성(maintainability)을 가질 것이다. 또한, 기능을 추가하거나 확장하는 것이 매우 어려워 확장성(extensibility)이 낮을 것이다.

그렇다면, 이러한 구조에서는 단점만 존재할까? 아니다, 이 구조의 장점을 주장하는 사람도 있다. 우선 이와 같이 작은 대상에 유리할 것이다. 이미 잘 동작하고 있고 적은 노력으로 동작하는 소프트웨어를 만들었다. 만일 이 기능이 상용 소프트웨어였다면 회사에서는 이 기능을 구현한 사람을 가능한 계속 채용한 상태로 유지하려고 할 것이다. 즉, 우스개 소리 같지만 개발자 입장에서는 고용이 안정될 수 있을 것이다. 나도 관련된 실제 사례를 들은 적이 있다. 이 사례의 경우는 통신 소프트웨어였다. 일반적으로 통신 소프트웨어에서는 계층화 되어, 레이어 1, 2, 3와 같이 주로 구분을 하는데 HW를 다루는 레이어 1의 경우는 보통 펌웨어로 다루는 경우가 많다. 그러다 보니, 레이어 1은 효율성이 강조가 되고 가독성과 같은 품질 속성은 많이 무시되는 경향이 있다. 이 전체 소프트웨어 개선을 목표로 여러 개발자들이 개선 작업을 한 것을 전해 들었는데, 레이어 2까지는 리팩터링을 했지만, 결국 레이어 1은 손대지 못하였다고 한다. 이 때, 레이어 1 개발팀은 계속 유지되고 있다고 들었다.

나는 애자일리스트로서 동작하는 소프트웨어를 더 존중한다. 그러면서도, 여러 가지 구조에 대해서 장단점이 있다고 생각한다. 심지어 큰 진흙 뭉치에서도 위에서 이야기한 것 같기 배울 점이 있다는 부분이 있다. 우리는 현실에서는 선택해야 한다. 동작하는 소프트웨어를 위해서 말이다.

들어가며

대부분의 사람들이 그렇듯이 자신의 역할이라는 것이 다양하게 있다. 누구의 자녀, 누구의 친구, 누구의 동료, 그리고 누구의 부모. 자신이 하고 있는 업 혹은 회사에서의 역할도 마찬가지다. 나도 그러한데, 이 여러 가지 중 조금 더 애착이 가는 것이 소프트웨어 아키텍트(Software Architect)이다. 나의 공식 직함은 관리자이다. 핸즈온 매니저를 계속하고 싶기는 하였지만, 현실은 그러지 못하고, 내가 필요한 도구 정도 코딩하고, 실제 제품에 포함되는 코드는 리뷰하기도 어려워진 것이 현실이다. 또한, 조금 더 개발자의 업무를 할 수 있는 것이 이 역할이기 때문이기도 하다. 그러면서, 회사 업무를 하며 실무 개발자들과 소프트웨어 아키텍처를 설계를 하는 것이 너무 귀한 기회이기도 하다.

최근에는 외부에서도 알게 된 분들과 함께한 아키텍처 관련 원 포인트 세션, 달리 말해 소프트웨어 문제점 멘토링으로 여러 사례들을 접하게 되었다. 흥미로운 것은 이러한 과정이 소프트웨어 아키텍트인 나에게도 큰 의미가 있지만, 소프트웨어 문제를 가지고 있는 분들에게도 실질적으로 도움이 된다는 사실이다.

우선 이론적으로는 도움을 요청하신 분들 입장에서는 첫 째, 소프트웨어 아키텍처 전문가를 데려다가 활용(How to bring experts)하는 측면에서 도움이 된다. 하지만, 이 부분에 맹점이 있다. 즉, 전문가와 일하되, 조율(Coordination)하고 통합(Integrate)하라는 연구[1]가 있다. 역서도 함정이 있는데, 비협업적으로 일하게 되면 비전문가들이 일하는 것보다 성과가 나쁘다는 내용도 언급되어 있는 것이 매우 흥미롭다. 또 다른 측면에서는 함께 같은 주제에 대해서 살펴보는 것이 페어 프로그래밍(Pair programming)과 같은 효과를 발휘한다. 이에 대한 이론적 배경으로 두 사람이 협력을 통한 추상화(Collaborative Abstraction)를 통해서 다른 시각(perspective)을 받아들일 수 있게 된다고 한다 [2]. 이 두 가지가 원 포인트 세션의 장점이라고 할 수 있겠다.

이와 같이 여러 사람들과 만나서 다양한 이야기를 듣게 되었고 다루는 내용이 현실의 소프트웨어 개발과 관련된 문제들이라는 생각이 들었다. 달리 말해 책에서만 존재하던 있던 내용들이 아니고, 우리가 살고 있는 실제 세상에 있었고 살아 있는 문제들이라는 생각이 들었다. 이 사례들들에 숨어 있는 이 이야기들을 끄집어내어서 내 생각을 조금 더 나누고자 한다.

 

참고 문헌

[1] A. W. Woolley, et al. "Bringing in the experts: How team composition and collaborative planning jointly shape analytic effectiveness." Small Group Research 39.3 (2008): 352-371.
[2] D. L. Schwartz, "The emergence of abstract representations in dyad problem solving", The journal of the learning sciences, 1995

이 책은 에디슨 위슬리 반 버논 시리즈의 여러 책 중의 한 권이다. 특히, 아키텍처 설계와 관련해서 관심을 가지다가 알게 되었고 번역 제안을 받아 진행하게 되었다. 쉽지 않은 과정이었지만, 몇 가지 알게 된 것, 느낀 것 그리고 번역에 대한 나의 짧은 생각을 적어 보려 한다. 

 

반 버논은 도메인 주도 설계(Domain Driven Design, DDD)가 도입되는데 큰 기여를 하고 있다. 특히, 도메인 주도 설계 구현(Implementing DDD)으로 유명하다. 나는 DDD가 요구사항과 구현 사이의 간극을 드라마틱하게 줄여주는 실천법이라고 생각한다. 이를 통해 확보한 요구 사항의 명확한 이해를 기반으로 효과적인 소프트웨어 설계를 수행할 수 있다. 흥미롭게도 비지니스 전문가와 개발자들이 함께 일하는 애자일 원칙과도 맞닿아 있다. 또한 이 책은 반 버논 시리즈의 두 번째 역서이다. 하나는 API 설계 원칙이다. 반 버논의 추천사를 보아도 두 책의 저자들이 상호 보완적으로 글을 썼다고 한다. 이 책에서는 웹 API 설계 원칙의 정렬-정의-설계-구체(Align-Define-Design-Refine) 단계 개념을 패턴에 적용하기도 했다.

 

반버논의 추천사에서 보면 유기적 구체(organic refinement)는 소프트웨어와 관련된 모든 개념이 무생물이 생물체의 측면을 '특성화'한다는 아이디어를 언급한다. 소프트웨어는 구체적인 시나리오를 통해 모델을 논의하거나 아키텍처를 설계하고 단위 테스트와 도메인 모델을 작성함으로써 살아 움직이기 시작한다. 마찬가지로, 건축가이자 패턴 개념을 만든 크리스토퍼 알렉산더는 "Nature of Order"에서 인간 배아(Embryo)의 예를 들며, 분화(Differentiation)에 대해 이야기한다. 이는 유기적 구체와 매우 유사하며 유기적이며 발전하고 성장하는 프로세스를 강조한다. 이러한 관점에서 소프트웨어의 진화는 생물의 발전에 대한 이해와 유사한 맥락에서 이해할 수 있다. 생명체가 환경과 상호작용하면서 성장하고 변화하는 것처럼, 소프트웨어도 사용자와 시스템 사이의 상호작용 속에서 점진적으로 발전하는 것이라 이해할 수 있다.

 

이 책에서 언급하는 패턴의 경우도, 이러한 유기적 구체 혹은 분화 과정에서 발견되는 반복적인 내용들을 잡아 내어 패턴의 커뮤니티에서 키워내고 리뷰하여 만들어 내는 과정을 거친다. 그러므로, 패턴, 유기적 구체, 분화와 같은 것을 이해하고 소프트웨어 구조를 설계할 때 분화의 관점 그리고 소프트웨어가 발전 성장하는 과정에서 패턴을 적용해가는 것이 필요하다는 관점에서 이 책에 접근하는 것을 권한다.

 

개별 언어는 독특한 여러 특징을 가진다. 이로 인해, 각 언어에 내재한 작은 뉘앙스 차이를 다른 언어로 옮기는 일은 매우 어렵다고 생각한다. 이 책에서는 "force"라는 어찌 보면 ""이라고 단순하게 번역할 수 있는 단어의 번역에 고민을 오래 하였다. 소프트웨어 설계에서 "force"는 설계 결정에 영향을 미치는 다양한 요인을 의미한다. 특히 이 책에서는 패턴의 문제-해결 짝과 이후에 상세 설명에서 패턴과 관련된 여러 "중요한 요구 사항"을 가리키는 용어로 등장한다. 이는 서로 상충되는 경우가 많다. 다른 아키텍처 책에서도 이 "force"를 언급하지만 이 책에서 더 자주 언급되어 시간을 들여 고민을 하였다.

 

이 책에서는 한글과 원어를 여러 번 병기하였다. 그 이유는 소프트웨어 개발이나 소프트웨어 개발과 관련된 도메인의 중심이 여전히 미국에 있기 때문이다. 따라서 영어로 쓴 원서나 관련 논문, 인터넷 글을 읽을 기회가 많으므로 원어 용어에 익숙해져야 한다. 따라서 이 책에서도 병기를 충분히 했다. 여러분도 책을 보면서 소프트웨어 아키텍처와 소프트웨어 개발에 관련된 원어 용어에 익숙해졌으면 한다.

 

번역 중 저자들과의 몇 번의 소통이 있었다. 올라프 짐머만과의 몇차례 이메일을 통해서 사소한 오탈자 뿐 아니라 그들이 생각하는 용어 정의와 같은 부분에 대해서도 의견을 나눌 수 있었다. 이러한 과정은 나에게 새로운 경험이었고, 책에 담긴 내용을 조금 더 깊게 이해하는데 도움이 되었다.

 

책의 번역을 마무리하면서 소프트웨어 개발, 설계에 대해 다시금 돌아보며 좋은 학습의 기회였고, 저자와 연락하며 짧지만 전문가들과 이야기 나눌 수 있어서 좋았다. 번역이라는 작업에 대해서도 내 생각을 정리하는 것은 나름 의미가 있었다

문제 해결 방법은 여러가지가 있을 수 있다. 혼자서 열심히 고민하여 문제 해결 하는 방식도 있지만, 팀으로서 협력하는 것은 매우 효과적이다. 하지만, 현실은 늘 항상 들어 맞는 정답은 없다. 그래도, 성공적인 팀-협업적(Collaborative)으로 일하는 팀이 문제를 효과적으로 해결한다.

 

여기서는 김창준님의 함께 자라기[1]에서 이야기하는 소프트 스킬, 협력적 추상화, 그리고 전문가를 어떻게 팀으로 데려와 성공할 수 있는가의 측면에서 살펴 보자

하드 스킬(Hard Skill) vs 소프트 스킬(Soft Skill)

우리는 많은 경우, 특정 도메인에서 일을 한다. 전자 상거래, 소셜 미디어, 멀티미디어 등 여러 가지가 있을 수 있다. 이렇게 한 분야에서 일을 하다 보면 그 분야, 즉 도메인 지식(Domain Knowledge)가 증가한다. 뿐 만 아니라, 개발자라면 컴퓨터 언어, 자료 구조, 알고리즘과 같은 개발과 관련돈 공통된 지식도 증가하게 된다. 이러한 것은 우리가 문제를 해갈 하기 위한 기술 하드 스킬(Hard Skill)이라고 할 수 있다.

 

우리가 혼자서 일한다고 하면 이 하드 스킬만 키우면 문제 없다. 하지만, 우리가 여러 사람들과 일하게 되면 여러가지 다른 기술이 필요해 진다. 즉, 사회 생활을 하는데 도움이 되는 자본과 기술이 필요하다고 한다. 좀 더 구체적으로 이야기 하면 커뮤니케이션과 협업 능력과 같은 소프트 스킬(Soft Skill)이 중요하다. 숙련된 프로그래머/개발자들에게 이야기 들어 보면 이러한 소프트 스킬을 높이는 것도 강조하는 사람이 많다는 것을 알게 된다.

 

이 부분은 뒤에서 문제를 해결하는데 기본이 되는 것이라고 할 수 있다.

협력을 통한 추상화(Collaborative Abstraction)

대니얼 슈와르츠[2]의 연구에서는 한 명이 문제를 푸는 것 보다 두 사람이 문제를 푸는 차이에 대해서 설명하면서 두 사람이 문제를 푸는 경우가 문제 해결에서 추상화를 통해서 새로운 것을 발견하도록 도와 준다고 한다. 이는 둘이서 협력(Pair-work)하면서 다른 시각(perspective)를 받아 들이고, 이를 연결하기 위한 추상화 필요하다고 설명한다.

 

이러한 추상화는 단순히 서로를 이해하게 하기 위한 것 뿐 아니라 문제를 바라 보는 단계를 높인다. [1]에서 언급하듯이 전산학의 소프트웨어 공학나 많은 학문이 그렇듯이 이 추상화를 거쳐서 발전하게 되었다. 그러므로, 우리는 이러한 추상화를 더욱 일어나게 하기 위해서 협업을 해야 한다. 

전문가와 일하는 방법 (How to bring experts)

우리가 특정 분야의 문제를 해결하려면 전문가를 데리고 하는 것이 유리할 것이라는 것은 예측하기 쉽다. 하지만, 여기에는 함정이 있다. 울리의 연구[3]를 보면 전문가와 일하되, 협력적으로 조율(Coordination)하고 통합(Integrate)하라고 가이드 한다. 

 

그의 연구에서는 전문가 혹은 비전문가 팀이 협업을 하는지 하지 않는지를 나누어 비교 연구하였다. 즉, 다음과 같이 그룹을 나누었다.

1. 전문가 협업 개입

2. 전문가 비협업 개입

3. 비전문가 협업 개입

4. 비전문가 비협업 개입

 

어느 팀의 성과가 가장 좋았을까? 그렇다 전문가 협업이 가장 좋았다. 그렇다면, 꼴지팀은 어디였을까? 전문가 비협업이었다는 것이 매우 흥미롭다. [1]에서는 전문가를 데리고 오더라도, 정보를 공유하고 협력을 잘하기 위한 명시적인 도움이 필요하고 소셜 스킬이 뛰어난 제너럴리스트가 있으면 도움이 된다고 조언한다.

 

참고 문헌

[1] 김창준, "함께 자라기- 애자일로 가는 길", 인사이트 · 2018년

[2] D. L. Schwartz, "The emergence of abstract representations in dyad problem solving", The journal of the learning sciences, 1995

[3] A. W. Woolley, et al. "Bringing in the experts: How team composition and collaborative planning jointly shape analytic effectiveness." Small Group Research 39.3 (2008): 352-371.

1만 시간의 재발견[1]으로 알려진 안데르스 에릭슨은 의도적인 수련(Deliberate Practice)으로도 알려져 있다. 자신의 전문성을 키우기 위해 의도적으로 따로 연습하는 방법이라고 볼 수 있다. 개발자 혹은 자신의 전문성을 키우고 싶은 사람으로서 수련하는 방법의 좋은 예로 김창준님의 Facebook 포스트[2]를 보고, 조금 더 추상화 부분을 정리해 보았다. 그리고, 최근 그릿[3]을 읽으면서 알게 된 부분도 같이 붙여 메타인지를 해보자.

 

김창준님개발자의 의도적 수련 활동:

 
관찰하고/책 읽고/비디오 보고,  시도하기: 매우 일반적일 수 있지만 시도하는 것은 조금 더 발전된 부분이다.
* 새로운 도구, 기술, 코드, 기법을 시도해 보고 그 결과를 관찰, 분석해 보기
* 개발 관련된 저널과 잡지, 책을 읽기, 개발 관련해 인터넷을 훑어보기, 관련된 비디오를 보기 등
* 개발 관련 세미나, 워크숍, 교육과정, 컨퍼런스 등에 참석하기
* 다른 동료 혹은 회사 밖의 사람의 코드나 작업물를 구경하거나, 다른 동료(개발자 외에도 QA 담당자라든지)가 일하는 방식을 주의 깊게 관찰해서 새로운 아이디어를 얻기
피드백 찾기(Feedback-seeking): 피드백을 받는 것은 쉽지 않다. 그래서, 그 부분을 찾고 다르게 일해 본다.
* (회사 내외의) 다른 개발자나 도메인 전문가의 의견을 묻기, 남에게 배우기 위해 네트워킹하기, 새로운 도구, 기술 등에 대해 동료와 이야기하기
* 나의 고객(내게 일을 주는 사람 -- 기획자, 운영자, 다른 개발자 등)에게 다가가서 피드백을 달라고 하기, 그 고객들의 니즈에 대해 묻기 등
 
페어 워킹: 다른 사람과 함께 할 것을 찾아 보거나 같이 하면서 배운다. 
* 어디에 개선이 필요한지 다른 직원들과 브레인스토밍 하기
* 사석에서 친구랑, 혹은 배우자나 다른 사람과 개발 일에 대해 이야기하며 새 아이디어를 얻기
* 다른 사람의 업무에 대해 배우기 위해 그 사람을 도와주기
 
회고: 자신의 상태를 점검해 보고 새롭게 해본다.
* 현재 코드의 상태를 점검해서 어디가 장차 문제가 될 수 있는지 확인하기, 코드 품질을 확인해서 개선할 방법을 찾기 등
* 내가 조금전, 오늘 혹은 이번주에 했던 일들을 복기하며 반성해 보고 실수한 것은 무엇인지, 다음에는 어떻게 하면 좋을지 생각하고, 다음을 위한 행동 계획 짜기
 
의도적 수련: 진정한 의도적 수련으로 보인다. 많은 사람들이 하지 못하는 부분이다.
* 이미 개발한 프로그램을 더 잘 만들 요량으로 다른 방법으로 처음부터 다시 개발해 보기
* 이미 개발했고, 기능상 문제가 없지만 리팩터링 등을 통해 코드 구조를 더 개선하거나, 성능상 문제가 없으나 자신만의 더 나은 성능기준을 목표로 개선하기
* 반복되는 작업을 자동화해서 거기에 드는 시간과 노력, 실수여지를 줄이기
 

Grit의 내용

그릿[3]에서는 최고가 되고 싶으면 '의식적인 연습(deliberate practice)' 수천, 수만 시간동안 하면 된다. 그러면서, 전문가들의 연습 방법에 대해 다음과 같이 설명하고 있다.

  1. 도전적인 목표를 설정하고 전체 기술 중에서 아주 일부분에 집중한다. 이미 잘하는 부분 보다는 뚜렷한 약점을 개선하려고 노력한다. 아직 도달하지 못한 과제에 도전하는 것이다.
  2. 도전적인 목표 설정 뒤에는 목표에 도달하기 위해 온전히 집중하고 비상한 노력을 한다. 음악가 같은 경우는 혼자 연습하는 시간이 다른 음악가와 함께 연주하는 시간보다 많다.
  3. 가능한 빠른 피드백을 받고 싶어 한다. 부정적인 내용이 많다. 자신이 잘한 부분 보다 틀린 부분에 관심이 많은 것이다.

이 내용을 조금 더 구체화한 것이 김창준님의 방법이라고 할 수 있겠다.

 

결론은?

앞에서 이야기 한것 처럼 그릿에서 의도적 수련에 대해 정리하고 있다. 개발자의 입장에서는 김창준님의 구체적인 수련 방법을 참고하면 큰 도움이 될 수 있다. 다른 업무를 한다면? 추상적인 것을 통해서 자신의 업무를 대입해보는 것도 좋겠다.

 

 

참고 문헌

[1] 안데르스 에릭슨, "1만 시간의 재발견" 노력은 왜 우리를 배신하는가

[2] 김창준, "개발자의 의도적 수련," https://www.facebook.com/cjunekim/posts/5465539236807932

[3] 앤절라 더크워스, "그릿 GRIT", 비즈니스북스, 2016년 10월

'Technical Leadership' 카테고리의 다른 글

협업적 문제 해결 방법 - 함께 자라기  (0) 2023.07.10
살리고 글쓰기  (4) 2023.03.12
책 읽기: 효과와 효율  (2) 2023.03.05
다니엘 핑크: 후회의 재발견  (0) 2023.02.25
ChatGPT에 대한 짧은 생각  (0) 2023.02.16

애자일 학습을 하면서 기존의 방법을 통해 느끼는 대한 안티패턴을 공유해 봅니다.

 

. 회사의 업무처럼 한다.

저는 회사에서 업무를 할 때, 미리 계획을 세우고 진행합니다. 물론 계획이 필요 없다는 것은 아닙니다. 하지만, 상황이 바뀌더라도 기존에는 그 계획대로 하려는 경향이 있었습니다. 애자일 학습에서도 제가 하려는 활동을 잘 하려고 그렇게 했던 경향이 있습니다.

애자일 해지기 위해서는 상황에 대응(adaptation)하기 위해서 협업을 강조하고 피드백을 중요하게 생각합니다. 그러므로, 빠르게 실패하는 것을 권장하며 실패를 통해서 피드백을 받고 배움을 얻는 것을 중요하게 생각합니다. 이를 위해서 같이 하는 사람들과의 회고 및 추가 활동을 통해서 더 배워야 합니다. 지속적이고 의도적인 연습 및 실행을 통해서 성장을 꾀해야 합니다.

그러므로, 애자일 학습을 하는 동안에는  기존에 하던 것과 같은 방법 혹은 그렇게 하지 못해서 그와 완전히 반대로 한다거나 하기 보다는 애자일하게 하던 방법과 하지 않던 방법을 섞어서 하는 것을 좋습니다. 이러한 학습에서도 업무에 어려움을 반영하여 내 실재 문제를 해결하거나, 배운 것을 업무에 적용해 보는 것도 좋습니다.

 

. 혼자 하려고 한다.

새로운 것을 배울 때 저는 우선 관련된 강의나 책을 먼저 찾았습니다. 특히, 책을 읽고 전문성을 높여서 문제를 해결하려고 했습니다.

하지만, 애자일 학습에서는 책만 읽는 것을 것을 권하지는 않습니다. 애자일적인 접근 방법으로 협력을 탐색해야 한다는 측면에서는 자신이 가지고 있지 않은 그것을 얻기 위해 책을 읽는 방법만 있는 것이 아니기 때문입니다. 것을 잘하는 사람을 찾고, 그 활동을 같이 하기도 하고, 같이하면서 배우고, 배운 것을 연습하는 것을 권합니다. 저도 최근에 새롭게 배운 동기 면담의 경우, 다른 분들과 자주 연습하려고 하고 있습니다.

 

. 중요하다는 것의 관점

최근에 코칭을 받고 있습니다. 애자일 학습을 하시는 분들께서 중요하다고 이야기 해주시는 내용 중에 하나입니다. 또한, 본인에게 중요한 문제를 가지고 코칭 받으라고 합니다.

그런데, 이 중요한 문제의 관점이 달라 졌습니다. 제가 느끼는 감정의 문제, 회사 업무에서의 문제들 중에서 여러 고민을 하고 고르고 골라 코칭을 받았습니다. 하지만, 정작 그 코칭을 통해서 어떻게 도움이 될까라는 문제로 돌아가 보면 선정한 문제가 중요한 문제인가에 대해 다시 질문할 수 밖에 없었습니다. 왜냐하면, 이미 코칭 받았던 문제들이 1년 아니 3~4년에 한 번 발생하는 문제 그리고 분기 혹은 많아야 한달에 한번 있을까 말까 하는 문제였거든요.

코칭 내용을 선정하는 가이드 중에서, 시간적 스펙트럼이 매주, 매일, 매시간에 나를 괴롭히고 있는 것이 무엇인지 묻습니다. 문제가 더 중요한 문제일 수 있다는 것입니다. 즉, 내, 수면, 음식, 건강의 문제, 내 평상시의 루틴한 업무와 관련된 문제가 더 중요할 수 있다는 것입니다. 집중력의 문제, 음주로 인한 에너지 문제, 혹은 음식의 자제가 되지 않아 어려운 다이어트 문제, 아침에 일어났을 때의 에너지 문제가 중요할 수도 있다는 것입니다.

 

. 피드백을 구하지 않는다.

애자일 학습을 하면서 멘토링 그리고 코칭의 기회가 많았습니다. 이 것이 자체로 이미 좋은 피드백이지만 애자일의 측면에서 우리가 학습하는 것들에 대해서 피드백을 찾아야 합니다(Feedback-seeking). 물론 기존에 애자일로 업무를 하는 사람들이 많기 때문에 회고를 가지면서 피드백을 찾는 것이 어느 정도 몸에 배어 있어 보입니다. 하지만, 이 피드백을 통해서 Action Plan이 나오고, 이를 추적하여 개선하는 것까지가 피드백 구하기라고 생각됩니다. 최근에 좋은 모임에 대한 번개에 대해서 진행할 , 쌓기 게임을 하였습니다. 우리 팀은 서로 경쟁해 보면서 누가 잘하는지 비교하기 바빴는데, 잘하시는 분들은 팀원들이 다른 사람 하는 것을 관찰하고 피드백 하던 것을 보았습니다. 우리가 업무에 적용해 본다면 어떨까요

최근에, AC2에서 디버거 활용하여 디버깅을 하신 세션을 공유한 세션을 듣고 나의 생각이 있어 적어 봅니다저는 개발자이고 싶은 관리자(^.^)이기 때문에 사례의 경우 동료들의 같이 하는 고민으로 이해 해주시면 됩니다. Android Phone Framework System Service 주로 개발하는 저와 동료들의 경우도, 요사이 디버깅은 로그 베이스일 밖에 없다는 생각이 들었습니다. 디버깅을 10번한다면, 9 이상이지요. 이유는 번개 때에 지나가듯 이야기 해주시는 부분에 있다고 생각했습니다. 그래서, 빠르게 생각을 정리해 보았습니다.

 

제가 생각하기에 디버거가 예전 같이 많이 사용되지 않는 것은 리눅스와 같은 우선 멀티프로세스(Multi-process) 상황이기 때문이란 생각이 들었습니다. 주로, 디버거로 확인 가능한 것은 하나의 프로세스에서 관련된 심볼(High level language machine language 연결 시켜주는 정보) 읽어와서 보여주며 실행하여야 하기 때문이라고 생각됩니다. 우리가 담당하지 않는 다른 프로세스로 넘어가게 되면 확인이 어려워 집니다. 상황에서 타이밍 이슈가 있는 부분이라면, 로그와 같은 디버깅 코드를 추가하면서 문제가 사라지는 경우도 발생하게 됩니다. 것은 번개에서 언급되었던 것으로 기억합니다. 실재로 동료들과 이야기 나눠 봐도 디버거를 아예 모르는 분도 계시고 경력이 많은 분도 실재 기기에서는  Watchdog 같은 제약도 많아 로그 기반으로 접근한다고 하네요.

 

디버거로 가능한 것들은 어떤 것들일까요? 우선 디버거가 있으면 1. 원하는 코드 부분에서 멈추게 있습니다. 그것만 가능한 것이 아니고 2. 멈춘 후에, 상황에서의 변수들의 값을 확인할 있습니다. 그리고, 3. 함수를 불렸을 , 어떤 함수에서 호출한 것인지(call stack) 있습니다. 그리고 4. Call stack 따라 호출한 시점으로 변수의 (물론 호출하여 관련 변수들이 변경되었다면 최신 상태) 확인해 있습니다. 세션에서도 설명하셨지만, 5. 원하는 코드가 특정 변수의 상태일 멈추게하는 것과 같은 고급 스킬도 가능합니다. 세션에서도 시연을 시도하셨죠.

 

다시 돌아와 디버거를 언제 써야 할까요? 10번에 1번이 될까 말까 하는 기술을 알아 두는 것은 좋을까요? 세션에서 공유해주신 사례에 적절하다고 생각됩니다. 저도 이쪽 도메인을 몰라서 이상한 이야기일 있습니다. 제생각에 방법을 모르셨다면, 사용하시는 Framework 뒤지고 로그를 넣어가며 확인하셔야 했을 가능성이 있어 보입니다. , 우리가 사용하는 모듈의 복잡성이 높은 부분에서 필요한 부분을 적응적으로 찾아 봐야할 때가 디버거를 사용을 고민해야 하는 아닌가 조심스럽게 추측해 봅니다. 저의 요즘 화두인 탐색이 필요하겠다는 생각을 잠시 했습니다. 망치를 쓰는 법을 알았으니, 망치를 쓰는 것이 좋겠다 싶은 곳을 탐색도 하고 연습도 해야죠. 그리고, 여기 저기 망치질을 하고 다니는 아닌가 고민해야 하겠네요.

+ Recent posts