아래 글은, 어떠한 논리적인 근거없이 작성된 개인적인 의견임을 먼저 명확히 명시합니다.

"부자 3대 못간다."라는 말이 있다. 비슷하게 회자되는 말로 "재벌 3세때 문제가 생긴다 - 3세 위기론"라고들 한다. 정말 그러한가? 잘 모르겠다. 첫 줄에 미리 언급한 바와 같이 어떠한 관련 근거도 찾아본 바 없다. 하지만, 그런 말들이 많이 회자 되는 것은 사실인 것 같다.
이 명제가 그럴 듯 하다고 가정하고, 이제부터 이유를 찾아 보려고 한다.

출처가 어딘지는 불문명하다, 이런 말을 들은 적이 있다. "창업주는 본인의 손으로 고생하면서 사업을 일으켰다. 2세는, 그 어려움을 보고 또 일부는 함께 하면서 자라서, 사업의 힘들고 어두운 면을 잘 안다. 하지만 3세는, 처음부터 안정적인 상태에서 큰 어려움 없이 자라서, 사업의 다양한 면을 알지 못하고 위기 대응 및 극복 능력이 떨어진다. 그래서 보통, 3세부터 문제가 생긴다."
어떤가? 설득력이 있게 들리는가? 물론, 이 말의 전제는, "창업주가 사업을 일으키고, 2세가 사업을 확장 및 안정시켜서, 3세에게 넘겨주는" 경우 - 사실 대한민국의 많은 재벌이 이 경우를 따른다 - 를 가정하고 있다. 나도, 이 말에 공감해 왔다. 하지만, 근래들어 새로운 관점이 생겨서 이에 대해서 이야기 하고자 한다.

먼저, 옛날 "군주"와 재벌의, 소위 "회장"은 어떠한 차이점이 있을까? 만약, 두 위치가 거의 비슷하다면, 어째서 "3세 위기론"을 옛 세습왕정국가에 적용하는 사례는 많지 않은가? 이 둘의 가장 큰 차이점은, "끊임없이 '왕좌'에 대한 위협이 존재하는가?" 라고 생각한다. 옛 왕국은 "장자세습"이 제도화 된 이후에도, 음모, 모략 등으로 인해 장자승계가 무난하지 않는 경우가 많았다. 승계서열 1위는 끊임없이 목숨의 위협을 느껴야 했다. 심지어 군주가 된 이후에도, 왕좌가 안정화 될때까지는 많은 시간이 소요되었다.
하지만, 현대 재벌들은 이러한 위협이 많지 않다. 목숨의 위협은 더더욱 없다. 특히 아들이 "하나"인 경우, 대부분의 경우 문제없이 승계가 이루어진다 - 대한민국의 경우, 지금은 많이 달라졌지만, 지금까지는 "남성", "장자" 우선 승계였다. 즉 위협 및 경쟁이 없다. 있다고 하더라도 아주 약하다. 난 이것이, 과거 "군주"와 현재 "회장"의 가장 큰 차이라고 생각한다. 그리고 이 차이가 "재벌의 수명"와 "왕국의 수명"의 차이 - 3세 위기론 - 를 만든다고 생각한다.

그럼, 구체적으로 이것이 어떠한 차이를 만들어내는 것일까? 앞서 이야기한, "어려움을 겪은 세대"와 "그렇지 않은 세대"의 차이일가? 좀 더 구체적으로, 이것이 무슨 차이를 만들어내는 것일까?
난, 이 모든 것에서 비롯된 "'사람 보는 눈'의 차이"가 근본적인 요인라고 생각한다. 어려움 없이, 처음부터 승계가 확정된 사람의 주위에는 다양한 종류의 인간 군상이 그 속내를 들어낼리가 없다. 사람은 관계가 변하면서 그 다면적인 모습을 드러내게 된다. 소위 "갑"을 대하는 "을"의 자세와, "을"을 대하는 "갑"의 자세는 다를 수 밖에 없다. 항상 "갑"의 위치에 있는 사람은 "을"일때 드러나는, 그 사람의 "단면"만을 보게 된다. 이것만으로 사람을 제대로 판단하는 것은 쉽지 않다.
앞서 이야기한 "어려움을 겪는" 다는 것은, 그 속에서, 다양한 역학관계를 가진 인적 네트워크를 경험하게 된다는 뜻이다. "갑"이 되었다가, "을"이 되기도 하고, 누군가를 믿어야만 하기도 하고, 배신을 경험하기도 한다. 이런 과정 속에서 믿고 신뢰할만한 사람을 찾게 되고, 사람을 보는 눈을 기르게 된다. 하지만, 항상 "절대 갑"의 위치에만 있었던 사람이라면 어떨까? 과연 그런 사람이 인간 군상의 다양한 면을 알고, 사람을 판단하는 "눈"을 가질 수 있을까?
결국 "군주"나 "회장"의 자리는 "사람을 쓰는 자리"이다. "인사가 만사"다. 물론 "의사결정"능력도 중요하지만, 본인이 모든 의사결정을 할 수는 없다. 때문에 "의사결정을 잘 할 수 있는 사람을 쓰는 일"이 가장 중요하다. 그런데 사람보는 눈이 없다면? 이것이 "3세 위기론"의 근본 문제라고 생각한다.

개요

벌써 좀 오래전 일이긴 하나, 경험의 기록 차원에서 남겨 둔다.

진행 환경

  • : 기획을 주도하는 사람 한명을 중심으로, 전부 완전히 수평적인 관계의 5명 (나이도 비슷).
  • 프로젝트: 대략적인 방향에 대해서만 동의된 상황에서 1년간 진행.
  • 상황: 프로젝트 성공 여부에 따라서, 인사 평가가 결정.

진행

초기

  • 프로젝트 진행방향을 구체화하는 과정에서, 서로 의견충돌이 발생.
  • 의사결정권자가 없으므로, 의견충돌이 중재되기 힘듦.
  • 어느 정도 서로 감정을 건드리는 상황도 종종 발생.

중기

  • 서로 의견충돌이 발생할 만한 종류의 이야기는 언급을 피함. 그러다 보니, 중요한 의사결정이 제대로 내려지지 않음.
  • 기획방향에 동의하지 않는 사람은 업무에 적극적으로 참여하지 않음.
  • 생산성에 비효율이 발생.

말기

  • 프로젝트 결과물이 기대에 미치지 못함.

요약

  • 책임과 권한이 비슷한 여러사람이 이끄는 조직을 성공시키는 것은 쉽지않다. 이것이 일한사람이 이끄는 조직보다 더 나은지 아닌지는 모르겠으나, 고려해야할 사항이 좀더 많아 보인다.
  • 한명이 의사결정권(책임과 권한)을 가지는 형태의 조직이 일반적으로 사용되는 것은 이러한 경험의 축적에서 비롯된 것으로 생각된다.

어제(23일) 노회찬 의원님이 세상을 등지셨다.

노무현 전 대통령 서거때 느꼈던 아련함이 다시금 다가 온다.

이런 저런 긴 말들을 쓰고 싶지 않다. 내가 느끼는 답답함을 글로 표현하기에는 글 실력이 너무 부족하다.

다만, 내 마음 속에 자꾸 "악화가 양화를 구축한다." 라는 그레샴의 법칙이 자꾸 떠오르는 것은 왜일까... 슬픈 하루다...

기본적으로, 팀원 들의 팀장 에 대한 평가는 긍정적이기가 어렵다.

자신을 평가하고, 업무를 지시하는 사람에게는 당연히 불만이 생기게 되니... 어찌보면 인지상정이고 당연하다할 수 있다.

그렇다고, 팀원들이 팀장을 전부 안좋게 평가하는데, 이걸 자연스러운 현상이라고 무시할 것인가? 그것도 아닌 것 같다...

그래서 이 부분에 대해서, 개인적인 경험에 비추어 해석의 지표(?) 같은 것을 적어보고자 한다.


일단, 팀원들의 팀장에 대한 평가를 4가지로 분류한다.


적극적인 긍정(적긍)

소극적인 긍정(소긍)

소극적인 부정(소부)

적극적인 부정(적부)


'적극적'과 '소극적' 의 기준이 명확할수는 없으나, 의미는 통할 것이라고 생각한다.


개인적인 경험으로는...


"적부(< 40%) + 소부" <= 60%


까지는 정상적인 범위가 아닐까 한다. 즉 적부 가 40%정도까지, 적부 + 소부 가 60% 정도까지이다.

만약 이 수치가 60%~70% 정도라면, 좀 애매하다...


그리고,


"적부(> 50%) + 소부"  > 80%


라면, leader에게 뭔가 문제가 있다고 볼 수 있을 것 같다.


위의 수치들은 어떠한 근거도 없다. 그냥 내 경험 + 일반화 를 통해 만들어낸 수치일 뿐이다.


수치 자체보다는


"팀장에 대한 팀원의 평가는 좋기가 어렵다"는 것을 전제로, 그 정도가 지나치게 심할 경우는 확인이 필요하다.


정도로 요약하고 싶다.





기본 기능은 거의 같으나, 일부 customization이 필요한 module이 있을 경우를 가정하자.
이 경우, 소프트웨어 공학적으로 보면, 기존 module에 melt-in해서 넣는게 좋다.(코드 중복은 가능하면 피해야 한다.)
하지만, 대부분의 일반적인 회사에서, 많은 경우, code를 fork하거나, 비슷한 다른 모듈을 만들게 된다.
왜 그럴까? 내 생각에는 조직논리가 가장 큰 이유로 보인다.

SW 코드에는 여러가지 철학적인 가치판단이 반영되기 마련이다.(변수 명, 함수 명, 코드 설계 방식 등.)
그런데, 하나의 코드를 여러 조직이 관리하게 될 경우, 의사결정시 조율해야 하는 것들이 많아진다.
하나의 조직 혹은 극단적으로 한명이 코드를 관리하면 이런 문제가 없거나, 있더라도, 조직의 leader에 의해 쉽게 조율된다.
그러나, 여러 조직이 엮이는 경우, 의사결정을 위한 협의 과정을 거쳐야 하는데, 이건 거의 모든 개발자들이 피하고 싶어한다.
그러니, 이리저리 논란에 엮이는 것 보다는 코드를 fork하고, 자체 관리를 하는 방향을 택하게 되는 것이다.

즉, 코드 유지보수 비용 vs. 조직간 communication / 조율 비용. 에서 내가 경험한 대부분의 회사에는 개발자들이 후자를 택하게 된다.

그런데, 향후, fork된 코드간 Gap이 커지고, 다양한 fork가 추가적으로 계속해서 이루어지는 과정이 진행되게 마련이다.
그리고 어느 순간, 각 개발자들 입장에서는 여전히 위의 선택(code fork)이 유효하겠지만, 조직(회사) 전체로 놓고 보면 코드 유지 보수 비용이 조직간 조율을 위한 비용을 현저하게 넘어서게 된다.
이때가 되면, 문제를 인지하고, 코드를 정리하는 과정을 거치게 되는데, 이미 refactoring debt 로 인해 상당한 비용을 지불해야할 상황이 된다.

위와 같이, 별도의 조치가 없다면, 결국 조직 혹은 협업의 문제로 인해, 코드 중복은 자연스럽게 발생하게 된다.
그리고, 대부분의 경우, 뒤늦은 refactoring으로 인해 많은 비용을 지불하게 된다.(refactoring debt)

이 문제를 해결하기 위해서는, 결국 중앙 집중적인 의사결정 기구 및 monitoring 기구가 필요하게 되는데, 이 역시 쉽지 않다.
신속하고, 때로는 강력하게 의사결정을 해 나가더라도, 다른 개발자들이 이를 존중해 줄 수 있어야 하는데... 이게 쉬울 리 없다...ㅜ.ㅜ

이상이, 내 개인적인 "문제에 대한 진단" 이다.
해결책은... 각 회사/조직/집단 의 상황에 맞게 알아서 잘~~~



여기서 <뛰어난> 이란, 아~주 특출나게 뛰어난 경우가 아닌, 상위권 수준으로 뛰어난 사람을 뜻한다.

<뛰어난 사람>
* 기술적인 성과를 이루었다.
=> 대단한 일이 아니라고 생각한다. 왜나햐면, 자기 자신에 비추어 생각해 보면, 이건 그리 어려운 일이 아니였으므로...

<평범한 사람>
* 기술적인 성과를 이루었다.
=> 자기 자신에 비추어 봤을 때, 대단한 성과라고 생각하므로 적극 홍보/자랑 한다.

그런데, 보통, senior manager group은 기술의 세부적인 내용에 대한 이해가 부족하다.
그리고, 대부분의 경우, 성과를 판단하는 요소에, 실제 기술적인 성과는 상당히 많이 간략화 되기 때문에, 홍보/포장 이 많은 비중을 차지하게 된다.

물론, 기술 자체는 그 활용성이 없다면 의미가 없다. 하지만... 기술적인 성과는 차후 개선의 밑바탕이 될 수 있으므로, 여전히 중요하다.
-------------

극단적인 생각이긴 한데... 이런 모습이 조직에서 종종 보이는 것 같다.
다시 말하지만, 극단적이다. 그렇지만, "위와 같은 모습이 종종 보이더라..." 라는 것 자체도 언급할 가치가 있지 않을까?

Code refactoring의 어려운 점은 이미 잘 알려진 바와 같다.
하지만, 그 문제의 복잡성 측면에서 보면, 작은 규모의 refactoring - file 혹은 class 단위 변경 - 은, 대규모 - 특히 코드의 구조 혹은 설계를 바꾸는 정도 - refactoring 에 비할 바가 못된다.

legacy 코드의 구조가 한계에 부딫혀, 재설계->재구현 을 고민할 정도의 상황을 가정해 보자.
이때, 가장 많이 고민하는 것은 아마도 "SW 재작성" vs "대규모 refactoring"일 것이다.
그리고, 어떠한 이유에서든, "refactoring"을 하기로 결정한 상황이라면 어떨까?
(실제, SW를 처음부터 새로 작성하는 것에 대한 Risk는 많이 언급되어 지고 있다.)

필자의 경험에 따르면, 이때 가장 중요한 것은
- refactoring의 단위를 적당히 작은 단계(step)로 분류하고,
- 각 step에서는 그 목적에 해당하는 refactoring만 수행
하는 것이다.

정말로 간단하고, 쉬워보이지 않는가?
하지만, 이게 정말 쉽지 않다.

Refactoring을 주제로 하는 많은 이야기들은, '좋은 구조', 'refactoring 시점' 등등 기술적인 측면을 다루고 있다.
그런데, 막상 필자가 실제로 heavy하게 사용되고 있는 SW를 refactoring하는 경험을 해보니, 정작 문제는 앞서 언급했던 두 가지에 있었다.

보통, 대규모 refactoring은 아래의 단계를 거쳐서 진행될 것이다.
- 현재 SW의 문제점 논의
- Refactoring의 범위 결정
- 새로운 SW구조에 대한 설계 철학 공유
- SW의 최종 형태 공유.
- 각 주제별로 refactring 시작.

하지만, 이런식의 진행은 'legacy SW의 상태'와 '최종 SW의 상태' 사이에 큰 차이가 있기 때문에, 그 끝이 좋지 못한 경우가 많다.
많은 양의 변화를 한꺼번에 진행하면, refactoring과정에서 발생한 오류를 찾아내기 너무 힘들어서, 결국 refactoring 코드를 버리거나, 아니면 SW 재작성에 버금가는(혹은 그 이상의) 노력이 들어가게 된다.
이론적으로는 이런 내용들을 대부분의 개발자들이 잘 알고 있지만, 실제로는 어떨까?

예를 들어, class간의 관계를 재 설정하는 refactoring진행 중, code의 context와 맞지 않는 변수 이름을 발견했다면? 혹은 code style이 잘못된 곳을 발견했다면?
대부분의 경우, 아주 작은 수정이므로, 겸사겸사 같이 수정하면서 진행할 것이다.
이것은, 마치 "거실 바닥 정리"라는 과정 중 "벽에 작은 얼룩을 발견"한 경우, 그냥 지나치지 못하고, 잠깐 시간내어서 얼룩을 지우는 것과 같다.
혹은, SW의 "Feature creep"과도 일맥상통해 보인다.
이런 식의 작은 side-refactoring들이 모여서, 한 step의 복잡성을 증가시키고, 결국 해당 step을 포기하고 처음부터 다시 진행하도록 만든다.

따라서, refactroing을 계획할 때는 앞서 언급한 것처럼, 그 단계를 잘게 나누어야 한다.
물론, 각 단계별로, "새로운 구조" + "legacy 구조" 의 형태를 지켜 내기 위한 overhead가 필요하므로, 너무 잘게 분리할 경우, 이 overhead 비용이 너무 커질 수 있으므로 주의해야 한다.


외부에 service를 제공하는 모듈 (예를 들면, library)일 경우, 잘못된 사용을 원천적으로 막는 것은 상당히 어려우면서도 중요하다.(모듈의 사용성과도 밀접한 관계가 있다.)

그런데, module의 instance가 생성되고 나서, 초기화 작업 이후에는 다시 setting될 필요가 없는 값들의 경우, 되도록이면, final (혹은 const)로 선언하는 것이, 코드의 이해도를 높이기도 좋고, 잘못된 사용을 막기도 좋다.


이때, default argument 값을 사용할 수 있는 언어의 경우(C++, Python 등)는 별 문제 없는데, 그렇지 않는 경우(ex, Java)는 사용성을 위해서 module constructor를 overloading해야 한다.(대부분의 경우, default 변수가 사용될 경우, 굳이 매번 이 값들을 argument로 전달해야 하는 것은 상당히 번거롭다.)


예를 들면,  'name', 'numArms'와 'numLegs' 세개의 final 변수를 가지는 'Person' module의 경우


class Person {
    private final String mName;
    private final int mNumArms;
    private final int mNumLegs;

    public Person(String name, int numArms, int numLegs) {
        mName = name;
        mNumArms = numArms;
        mNumLegs = numLegs;
    }
    public Person(String name, int numArms) {
        this(name, numArms, 2);
    }
    public Person(String name) {
        this(name, 2, 2); // 2를 default value로 사용. 대부분의 사람은 팔 다리가 2개... 
    }
}

와 같이 작성된다.

그나마 argument가 3개인 경우가 저정도고, argument가 많아지면, 사용성을 높이기 위해서 overloading되는 생성자도 많아진다.

이 문제를 builder pattern으로 해결할 수 있다.

예를 들면.

class PersonBuilder <T extends PersonBuilder > { // Generic type T 를 사용하는 이유는, 이 Builder를 상속받는 builder를 위함이다.
    private final String mName;  // name은 default가 없으므로 생성시 외부에서 반드시 argument로 받아야 한다.
    private int mNumArms = 2;  // 대부분의 사람은 팔, 다리가 2개...
    private int mNumLegs = 2;

    public PersonBuilder(String name) {
        mName = name;
    }
    public T
    setNumArms(int numArms) {
        mNumArms = numArms;
        return (T)this;
    }
    public T
    setNumLegs(int numLegs) {
        mNumLegs = numLegs;
        return (T)this;
    }

    public Person
    create() {
        return new Person(mName, mNumArms, mNumLegs);
    }
}


그렇지만, 역시 해당 class를 상속받는 경우, 긴 argument를 가진 생성자를 상속해야 하는 불편함은 여전하지만, 이 문제 역시, builder를 상속받는 방법으로 해결할 수 있다.


class OldPerson extends Person { ...}

class OldPersonBuilder<T extends OldPersonBuilder> extends PersonBuilder<T> {
    public OldPersonBuilder
    create() { ...}
}


Generic을 사용했기 때문에, 아래와 같은 용법이 가능하다.

OldPersonBuilder<OldPersonBuilder> bldr = new OldPersonBuilder<OldPersonBuilder>("MyName");
bldr.setNumArms(2).setNumLegs(2);

대략 정리해 보면, 이와 같은 pattern을 사용할때는


Module에서 final. Default값 존재 X => Builder에서도 final

Module에서 final. Default값 존재 O => Builder에서 NOT final.


이정도일려나?


제목 그대로다.

"멤버가 하고 있는 일, 노력 그리고 성과 등을 정확하게 파악하는 일"은 관리자가 해야할 일 중요한 일 중 하나이다.

왜냐하면, 멤버의 성과를 결국 평가해야하기 때문이다.

그렇지만, 그것만큼 중요한 건 "멤버들이, 내가 관리받고 있고, 관리자가, 나의 일, 성과 그리고 노력을 정확하게 파악하고 있다."라고 인식하게 하는 것이다.

사실 실제로 관리자가 "얼마나 '정확히' 파악하고 있나?"와는 별개로, 멤버들이 "자신들이 관리받고 있다."라고 느끼고 있다면, 나태해 지지 않고, 또 자신의 성과를 터무니없이 과장하는 등의 문제도 줄어들게 된다.


물론 관리자의 가장 중요한 역할은 "팀원들이 자신의 업무/생활에 만족하면서, 팀 전체가 최상의 성과를 낼 수 있도록 이끌어 가는 것."이라는데는 변함이 없다.

Let's assume that a engineer is working at same domain for a long time.

Then, based on my experience, relation among those three is something like this.


<Performance/Productivity> = <Talent> * <Time> ^ <Attitude>


What this means?


At early stage, Talent dominates Performance.

But, after all, Attitude dominates Performance.


Then, what is attitude means for engineer?
In my opinion, good attitude of engineer, is
    - studying continuously.
    - trying to establish strong knowledge base for domain.
    - trying to understand as many / deep as possible regarding his/her task and domain.
    .. .and so on.


Let's see below graph.



Y-axis : Performance / Productivity
X-axis : Time

Red line : Talent value = 1, Attitude value = 4
Green line : Talent value = 10, Attitude value = 2



At this graph, there is special period (0 < Time < 1).

At this period, Attitude hinders Performance.

My interpretation is, engineer who has great attitude, always tries to understand nature and fundamental knowledge of tasks.

So, during this period, in terms of so-called output, he/she may be worse than other engineers.

But, based on this strong knowledge and understanding, he/she accelerates productivity (Time > 1)

And finally, his/her performance overcome talent.


This is my opinion based one only my experience.

Reader may or may not agree with it.
But, I strongly believe this. :)




+ Recent posts