블로그


Youngrok Pak at 10 years, 5 months ago.

블로그 태그를 붙인 글을 최신 순으로. 좀더 개인적인 글은 일기장에. 블로그 글 전체 목록은 내 글 모음에.


QuickAndDirty

난 예전에 프로그래머에게 필요한 피드백이라는 글에서 TDD, 리팩토링 등의 기법의 목적은 프로젝트를 더 빨리 완료하는 것이며, clean code니까 빨리 개발할 수 있다는 주장을 펼친 바 있다. 이번엔 이 주장을 한발짝 더 깊게 들어가되, 약간 다른 관점으로 풀어보려고 한다.

린 스타트업과 quick & dirty

에릭 리스의 린스타트업에 보면 이런 스토리가 나온다. 처음에 스타트업을 할 때는 애자일의 주요 기법들을 잘 적용하면서 기술적으로 훌륭한 프로젝트를 했는데 아무도 쓰는 사람이 없어서 망했고, 나중에 다시 창업해서 수많은 버그가 있는 제품을 그냥 출시했는데 흥했더라. 매우 인상적인 이야기다. XP 기법들의 신봉자라면 좀 충격을 받을 수도 있을 것이다. 켄트 벡이 품질은 타협 대상이 아니며, 품질을 타협하면 오히려 프로젝트는 느려진다고 그랬는데 품질이 개판인 프로젝트는 돈을 벌고, 품질이 좋은 프로젝트는 망했다고?

오해를 덜기 위해 명확히 해두자면, 여기서 말하는 품질은 제품의 품질이 아니라 기술적인 품질이다. 그러니까, 에릭 리스의 이야기는 기술적인 품질이 낮은 프로젝트가 성공했다는 것이다. 그래서 그는 나중에 고객 관점에서의 품질을 이야기한다. 고객이 없으면 품질도 없다는 것.

아뭏든, 여기서 우리는 clean code를 위한 노력이 사실은 성공에는 도움이 안되는 게 아니었을까 하는 의심을 품게 된다. 합리적 의심이다. 린 스타트업을 읽고도 그런 생각이 안 들었다면 오히려 그게 더 이상할 것이다.

나도 스타트업은 quick & dirty를 해야 한다고 생각한다. 하지만, 이것이 clean code의 추구에 반하는 이야기는 아니다. 그러니까, 나는 모순처럼 보이는 quick & dirty와 clean code가 모순이 아니라고 주장을 하고 있는 것이다. 심지어, 이 주장은 옳기 때문에 따로 근거도 대지 않고, 이 글의 진짜 주제, 스타트업이 어떻게 quick & dirty를 할 것인가로 넘어갈 것이다. 만약 이 주장에 대한 논증을 보고 싶은 사람이 있다면 맛있는 점심 한 번으로 다 펼쳐보여주겠다.

Quick & Dirty How-to

진짜 주제로 넘어가기 전에 잠시, clean code에 도달하는 가장 훌륭한 방법인 TDD의 사이클을 복습해보자.

  1. 제대로 동작하는지 확인할 수 있는 테스트를 작성한다.
  2. 실행 가능하게 만든다. 다른 무엇보다도 중요한 것은 빨리 초록 막대를 보는 것이다. 빨리 초록 막대를 보는 것은 모든 죄를 사해준다. 하지만 아주 잠시동안만이다.
  3. 올바르게 만든다. 이제 시스템이 작동하므로 직전에 저질렀던 죄악을 수습하자.

린 스타트업은 말하자면 TDD를 조금 더 큰 스케일로 하는 것이다.

  1. 가설을 수립하고, 가설을 확인할 수 있는 지표를 설정한다.
  2. 가설을 검증할 수 있는 MVP를 만든다. quick & dirty!
  3. 가설이 검증되었다면 완성도를 높여간다.
  4. 가설 검증 결과가 틀린 것으로 나온다면 새로운 가설을 수립한다.

2와 4분의 3 승강장

문제는 바로 2와 4분의 3 승강장 2와 3 사이에 있다. 린 스타트업은 개발자를 위한 책이 아니라 스타트업을 위한 일반적인 방법론이므로, 2와 3 사이에 TDD 사이클의 3번 과정을 따로 시간을 할애해서 적어놓지 않은 것이다. 이게 바로 행간을 읽는다는 것이야. 가설 검증에 성공한 스타트업이 이 2.5 리팩토링을 놓치게 되면 바로 이어 등장하는 추격자들에게 자리를 내주게 된다. 추격자들은 모범 답안이 있으니 빠른 속도로 MVP를 만들 게 아니라, 처음부터 완성품을 보고 달려도 되므로, 완성품에 더 빨리 도달할 수 있다. MVP까지는 quick & dirty로 빠르게 만들 수 있지만, 완성품을 만드는 것은 clean code 없이 속도를 낼 수 없다.

하지만, 설령 개발자가 2와 3 사이에 숨겨진 2.5를 인지한다고 해도 문제는 간단하지 않다. CEO는 quick & dirty로 가설을 검증해냈기 때문에 이미 quick & dirty에 맹신이 생긴 상태이고, 앞으로도 쭉 quick & dirty로 해나가면 된다고 생각한다. 그래서, 계속 같은 속도로 움직일 수 있을 거라고 생각한다. 이런 CEO에게 코드를 정리할 시간이 필요하다고 말하는 것이 먹힐 가능성은 매우 낮다. 설령 말로는 동의해도 이후에 액션들은 2.5 작업을 할 수 있도록 내버려 두지 않는다. proof of concept 이후에도 쭉쭉 뻗어나가는 스타트업과, 경쟁에 뒤쳐지는 스타트업에는 결정적인 차이가 바로 이것이다.

뛰어난 엔지니어가 CEO이거나, 혹은 뛰어난 엔지니어가 어떻게 일하는지를 이해하는 CEO라면 2.5를 이해한다. 하지만 대부분의 CEO는 2.5를 받아들이지 못한다. 고속성장을 하다가 경쟁자에게 따라잡히는 스타트업들은 대체로 CEO가 엔지니어링에 대한 마인드가 부족하다. 국내에도 좋은 사례가 있다. 최근 2~3년 간 스타트업을 가장 떠들썩하게 했던 분야 두 개를 떠올려보라. 그리고, 그 두 개의 선두 업체였던 두 회사의 2년 전과 지금을 비교해보라. 하나는 지속적으로 새로운 성장 동력을 발굴해내며 성장을 가속하고 있지만 다른 하나는 외형적인 성장만 해오다가 그마저도 경쟁사에 따라잡혔다. 물론 차이를 만든 이유는 여러 가지가 있고, 여러가지 분석이 있겠지만, 결정적인 차이는 엔지니어링에 대한 마인드의 차이였다는 것이 내 판단이다.

MVP의 조건

물론 위의 이야기는 어쨋든 다 행복한 스토리다. 내가 창업한 이후 5년 간 직간접으로 관련이 있었던 30여개의 스타트업 중 proof of concept에 성공한 스타트업은 단 둘 뿐이니까 말이다. 그럼 대부분의 스타트업에서는 개발자들이 고민해야 할 clean code는 2.5 단계가 아니라 2단계다. 2단계에선 그럼 무작정 quick & dirty를 하면 되는가? PHP라도 상관 없는가? (그건 물론 안됨) 여기서 quick & dirty를 어떻게 할 것인가를 이야기하기 전에 하나 더 짚고 넘어갈 게 있다. 개발이 아니라 MVP에 대한 조건이다.

MVP는 박병호가 아니고, Minimum Viable Product다. 아니, Minimum Viable Product다. 이게 대부분의 스타트업에서 잘못하는 것 중 하나다. MVP는 충분히 작아야 한다. 이베이의 첫번째 제품은 웹사이트에 중고 물품을 등록하는 기능과 열람하는 기능 두 개 밖에 없었다. 거래는 이메일로 하고 수수료는 우편으로 보내는 원시적인 웹사이트였다. 이런 제품에 버그가 많으면 얼마나 많겠으며 코드가 지저분해봐야 얼마나 지저분하겠는가. MVP가 충분히 작다면 quick & dirty로 매우 빨리 만들어도 그 과정에서 쌓는 기술 부채는 얼마 되지 않는다. 가설 검증이 되면 바로 갚을 수 있다.

하지만 대부분의 스타트업들은 Minimum은 커녕 Maximum을 만들기 위해 노력한다. 뭔가 기능이 없어서 고객이 안 온다고 생각한다. 그래서 점점 비대하게 제품을 확장해나간다. 가설 검증도 안되었는데. 그럼 quick & dirty로 인한 기술 부채는 점점 감당할 수 없을 만큼 쌓여간다. 가설 검증이 된다면 기술 부채는 별 거 아니다. 어차피 돈 벌고 있으니까, 혹은 돈 벌 예정이니까, 뛰어난 개발자 채용하고 시간 들여서 기술 부채를 갚으면 된다. 2.5 단계를 진행하면 되는 거다. 근데, 가설 검증이 안된 상태에서 quick & dirty로 개발한 제품이 점점 커져가면 점점 속도가 느려져서 어느 순간 아무 것도 할 수 없는 상태가 온다. 그리고, 이런 상태가 되면 개발자가 도망가거나, 도망은 안 가도 백기를 들곤 한다. 이렇게 된 스타트업에 헬프하러 간 게 몇 번인지 셀 수 없다.(사실은 셀 수 있다, 여덟 번)

그리고, 설령 어찌어찌 가설 검증이 되더라도, 그 사이 quick & dirty로 만든 제품이 이미 너무 비대하다면, 나중에 뛰어난 개발자를 데려와도 어찌할 수 없는 경우도 생길 수 있다. 2번도 통과했고 2.5번도 할 자세가 충분히 되어 있는데, 2.5를 할 수 없는 상황이 될 수 있는 거다.

그래서, 스타트업은 MVP를 만들 때 극도로 절제해야 한다. 가설-검증의 사이클을 활용하고, 가설의 성공/실패 여부가 가려지지 않았을 때 기능 추가하는 것이 결과적으로 성공 확률을 깎아먹는다는 것을 이해할 필요가 있다. 기술 부채를 통제할 수 있는 선에서 MVP를 만들어야 한다. 기술 부채도 부채이므로 많아지면 파산한다.

Quick & Dirty로 개발하기

그럼 이제부터 본론(?) quick & dirty로 개발하는 방법에 대해 들여다보자. 이 방법들의 목적은 clean code의 궁극을 추구하는 것이 아니라, 기술 부채로 인해 파산할 수 있는 위험을 아주 작은 노력들로 막는 것이다.

추상화하지 말 것

좋은 코드는 좋은 추상이다. 그러므로, 개발자는 좋은 추상화를 하기 위해 노력해야 한다. 하지만, 잘못된 추상화만큼 코드를 재앙으로 이끄는 것도 없다. 초기에 좋은 추상을 발견할 시간이 부족하다면, 추상화를 하지 말고 미루라.

Do not extract method

조금 더 구체적으로 말하자면, Do not extract method다. 트위터에도 언젠가 설명 없이 저 문구만 쓴 적이 있는데, 이런 맥락에서 한 말이다. 우선, 함수는 그 자체로 GotoConsideredHarmful을 극복한 것이 아니다. Goto의 문제는 코드를 읽다가 흐름의 점프가 일어난다는 것이며, 함수도 그 문제를 똑같이 갖고 있다. 간혹 이 문제를 네이밍의 문제로 보는 관점도 있는데, 네이밍이 물론 중요한 것은 사실이지만, Goto도 라벨을 붙여서 라벨로 점프하니까 라벨만 잘 붙이면 되는가? 아닐 것이다. 라벨을 잘 붙여도 여전히 Goto는 해로우므로, 함수 역시 이름 잘 붙인다고 그 해로움을 피해가는 것은 아니다.

진짜로 Goto의 해로움을 피해가려면 관련된 변수들의 scope를 잘 정의하는 것이 중요하다. Goto에서 정말 피하기 어려운 것은 전역 변수를 써야 한다는 것이다. 그러니까 코드에서는 물리적으로 다른 공간에 점프를 했는데, 머리 속에는 여전히 여러 변수들의 상태를 담고 있어야 코드를 계속 추적할 수 있기 때문에 문제가 되는 것이다. 함수가 좋은 것은 변수를 지역적으로 제한시키기 쉽다는 것이다. 함수의 이런 장점이 오히려 OOP에 오면서 무분별한 멤버 변수 사용으로 퇴색되는 감이 있는데, OOP를 잘 활용하려면 메서드 역시 변수의 scope를 엄격하게 관리하는 게 중요하다. 그러면 함수는 점프를 한 부분만 따로 이해하는 것이 가능하다. 설령 그 전 코드를 잊어버렸더라도 함수를 이해하고 다시 돌아와서 볼 수 있다. 그런데 만약에 함수나 특히 메서드에서 변수 scope를 제대로 관리하지 않아서 기억해야 하는 상태가 많다면 goto랑 별 다를 바가 없는 것이다.

이런 고민 없이 그냥 extract method를 하게 되면 결국 goto와 같은 문제를 발생시키게 된다. 이렇게 되느니 차라리 1000라인 짜리 메서드가 나중에 리팩토링하기는 더 좋다. 그래서, 좋은 extract method가 떠오르지 않는다면, 그냥 하지 않는 게 더 낫다는 것이다.

상속 계층을 만들지 말 것

마찬가지로, 상속 계층도 되도록 안 만드는 게 좋다. 상속 구조야말로 OOP에서 가장 잘하기 어려운 부분이고, 다형성에 대한 완벽한 이해가 없다면 좋은 상속 구조를 만들어낼 가능성은 거의 없다. 만약 스스로 OOP를 잘한다고 생각하지 않는다면, 상속은 전혀 쓰지 않기를 권한다. 다형성에 대해서는 OOP는 조건문을 줄이는 것을 참조하라. 참고로 나는 저 글에 완전히 동의하지는 않는다. Field Encapsulation도 여전히 OOP의 핵심이며 이건 앞서 Do not extract method에서 했던 이야기와 관련이 있는데 언젠가 다시 한 번 글을 쓸 예정이다.

중복은 한 파일에 몰아라

리팩토링을 한 마디로 요약한다면 중복을 제거하고 의도를 드러내는 것이다. 그런데 중복을 제거하려면 결국 뭔가 추상화를 하게 되고 어렵다. 그러니까, 중복을 당장 제거하지는 말고, 일단 물리적으로 한 파일에 몰아 넣어라. 한 곳에 모여 있는 중복 코드는 나중에 손쉽게 리팩토링할 수 있다. 그러나, 중복이 여러 파일에 걸쳐 퍼지기 시작하면 감당할 수 없는 상황이 온다. 특히 조건절의 중복 코드는 전염되는 경향이 있다. 이런 코드에 대한 정답은 다형성이지만 다형성이 손에 익은 사람이 아니면 그리 쉽게 되진 않을 것이다. 그럼 그냥 한 파일에만 몰아두어라. 나중에 내가 가서 해결해주겠다.

Cyclomatic Complexity를 늘리지 말 것

자세한 건 구글링을 해보시고, 쉽게 말하면 분기의 depth를 늘리지 않는 것이다. indent가 깊게 안 들어가게 해야 한다고 이해해도 좋다. 다른 건 리팩토링을 하지 않더라도 이것만은 꼭 해놓아야 한다. if문을 줄일 수 있는 다형성을 쓰지 말라고 해놓고 이제와서 if문을 줄이라고? if문을 줄이라는 건 아니다. if문을 flatten하라는 것이다. 예를 들면 GuardClause 같은 것. 

  public Foo merge (Foo a, Foo b) {
    Foo result;
    if (a != null) {
      if (b != null) {
        // complicated merge code goes here.
      } else {
        result = a;
      }
    } else {
      result = b;
    }
    return result;
  }

위와 같은 코드보다는 아래와 같은 코드가 낫다.

 

  public Foo merge (Foo a, Foo b) {
    if (a == null) return b;
    if (b == null) return a;
    // complicated merge code goes here.
  }

그리고 조건문도 자세히 보면 중첩 if로 된 것을 풀 수 있는 경우가 많다. 되도록 다 풀어두는 게 좋다. 물론 중첩 if를 풀면 중복이 더 많이 발생할 수도 있다. 하지만 그래도 괜찮다. 중복 코드는 나중에 쉽게 발견하고 리팩토링할 수 있지만, cyclomatic complexity가 높은 코드는 이해하는데 시간이 더 많이 걸린다. if가 나타났다고 그걸 다형성으로 대체하려고 하지는 말고, 그냥 그 if들이 중첩되지 않도록 하는 것만 신경 써도 충분하다.마찬가지로 SQL을 작성하더라도 FROM 절의 sub query depth가 깊어지는 것보다는 적절히 join으로 처리하거나, 정 안되면 성능이 좀 떨어지더라도 쿼리 여러 번 하는 게 좋다. 이런 것들은 리팩토링에 큰 에너지를 쓰지 않고 작은 노력으로 큰 효과를 볼 수 있는 것들이다. 

이름 규칙 정하기

quick & dirty는 리팩토링도 대충하는 만큼, 네이밍도 그렇게 열심히 할 필요는 없다. 다만, 네이밍 룰은 잘 정해두는 게 좋다. 특히 각 언어의 코드 관례을 지키지 않으면 나중에 다른 개발자가 왔을 때 실제보다 더 코드가 저평가 받게 된다. 언어의 코드 관례는 존중하도록 하자.

이미지 파일의 이름 규칙도 꽤 영향이 크다. 이 규칙이 잘 정해져 있으면 개발할 때 디렉토리에서 다시 파일명을 확인하지 않아도 된다. 물론 Jetbrains처럼 이미지 파일명까지 추천해주는 IDE를 쓸 수 있는 경우도 있지만, 안 그런 경우도 많으니까. 이를테면 나는 이미지 이름을 붙일 때, artifactname_type_extra.png 같은 방식으로 쓴다. login_button_small.png, content_bg.png, table_header_bg_white.png 이런 식. 마찬가지로 CSS의 class명, 태그의 id 등도 이름 규칙이 잘 지켜지면 이득이 많다.

안 쓰는 코드, 파일 삭제

나중에 레거시가 될 운명인 코드이니만큼, 나중에 이 코드를 만날 개발자들에게 중요한 것 중 하나는 봐야 할 코드량이다. 그런데 쓰지도 않는 코드 때문에 시간을 낭비해야 한다면 얼마나 끔찍할까. 나중에 리팩토링하다가 걸리는 파일들 일일이 다 수정했는데, 알고봤더니 그 중에 80%는 쓰지도 않는 클래스들이었다면? index_1.php, index_2.php 이딴 것들도 다 삭제하도록 하자. 한 눈에 들어오는 파일 개수도 유지보수에 큰 영향을 미친다.

안타까운 것은 이런 일이 대부분 소스 버전 관리를 하지 않기 때문에 일어난다는 것이다. 버전 관리를 하고, 안 쓰는 파일은 빨리빨리 삭제하도록 하자. 실험한 코드들도 다 삭제하는 게 좋다. 안 쓰는 코드를 주석처리한 것도 임시로만 하고, 작업 끝나면 꼭 삭제하자.

주석은 되도록 쓰지 말 것

코드 분석에 도움될 정도의 주석을 쓸 시간이 있거든 리팩토링을 하든가, 구현을 더 빨리하는데 시간을 써라. 주석이 필요 없는 코드를 만들라는 게 아니다. 코드가 지저분하든 아니든 주석은 이해에 방해되는 경우가 더 많다. 코드만큼 실시간으로 업데이트되지 않기 때문이기도 하고, 나중에 보는 사람의 관점을 생각해서 주석을 쓰는 것이 쉬운 일이 아니기 때문이기도 하다. 특히 주석에 누가 언제 이 코드를 작성했는지 따위는 제발 남기지 말도록 하자. 불필요한 라인도 코드 분석을 방해한다. 어쩔 수 없이 비정상적인 방법으로 구현했을 때만 주석을 남겨라. 이를테면 다음과 같은 주석은 남겨둘 필요가 있다.

// 결제 처리 중에 왜 안되는지 몰라서 아래 코드를 넣었는데 작동함. TODO 나중에 분석해볼 것.
funckingKoreanPaymentGateway.setUndocumentedOption('blahblah', ...);
코드 외의 기술적인 사항은 반드시 문서를 남길 것

레거시를 접할 때 가장 스트레스 받는 사항이 이거다. 소스를 어떻게 빌드하는지, 서버에 어떻게 deploy하는지, 서버에서 무슨 cronjob이 돌고 있는지, 퍼미션은 어떻게 줬는지, 서버 스타트/스톱은 어떻게 시키는지, 서버에 무슨 설정 파일을 건드렸는지 등등. 이런 건 시간이 들더라도 반드시 문서로 남겨야 한다. 이런 정보가 실종되는 바람에 뻔히 돌고 있는 서비스인데 더 이상 업데이트를 할 수 없게 된 회사도 본 적 있다. 궁극적으로는 각종 설정 파일, 스크립트 등도 모두 소스 코드로 간주해서 버전 관리를 해야 하고, 자동화도 시켜야 하지만, 처음부터 그런 데 시간을 투자하기는 어렵고, 문서로 남겨놓는 것만으로도 충분하다.

적정 기술

소프트웨어 개발에도 적정 기술이 있다. 요즘 성능 관련 컨설팅을 좀 하다보니 가장 많이 받는 질문이 이거다. 우리도 분산 DB 기술을 도입해야 하나요? 앞으로도 물어볼 수많은 사람들을 위해 미리 답변하자면, "그냥 MySQL 쓰세요. 그게 정답입니다. 당신이 원하는 건 다 할 수 있어요." 물론 우리도 언젠가는 분산 DB를 해야 할 것이다. 당신의 비즈니스가 100억 valuation 쯤 될 때쯤에 말이지. 그 전에는 phpmyadmin과 MySQLWorkbench가 있는 MySQL을 쓰자. 아, 물론 팀 내에 DBA가 있고 TOAD 정품 사놨으면 오라클 써도 된다.(근데 요즘도 TOAD 쓰나?) 오픈소스에서 PostgreSQL 계속 써온 사람이 있으면 괜찮다. 그래도 큐브리드는 안됨. mongodb는 MySQL과 또 좀 다른 장점이 있고, 꽤 사용자가 많아져서 약간의 리스크를 걸고 쓰는 건 나쁘지 않다. 오라클에 더럽혀진 MySQL이 싫다면 MariaDB를 써라. MSSQL은? 글쎄, 윈도 개발자라면 더 편할 수도 있겠지만... 요즘 누가 윈도로 개발하나?

웹을 한다면 생산성이 높고 검증된 프레임웍을 사용하라. 두말할 필요 없이 Rails 아니면 Django가 답이다. Java는 검증되었지만 생산성이 너무 낮고, Node.js는 아직 시간이 더 필요하다. 그 외의 것들은 구글링해도 답이 안 나오는 상황을 자주 겪게 될 것이다. 뭐 그래서 하다가 직접 소스 고쳐가면서 오픈소스 커미터도 되고 좋은 거 아냐? 그래, 좋지, 그 개발자 커리어에는. 근데 그 스타트업에 좋은지는 모르겠다. 물론, 개발자가 다른 조직에서 이미 숙련된 프레임웍이 있다면 상관 없다. 여기서 검증된이란 표현에 주체는 스타트업의 개발자 당사자들이다. 이를테면, 도요타는 늘 검증된 기술만 production에 적용하는 원칙으로 유명하지만, 하이브리드 등의 최신 기술에서 오히려 시장을 선도해왔다.(몇 년 전까지는) 남들이 다 모르는 최신 기술이라도 우리가 충분히 써봤고 확신을 가질 수 있다면 그건 검증된 기술이다. 하지만, 우리도 삽질하고 구글링하고 뉴스그룹에 stackoverflow 뒤져가면서 써야 하는 기술이라면, don't even try.

특히 요즘은 매일매일 신기술이 쏟아져 나온다. 크로스 플랫폼으로 모바일앱을 쉽게 만들 수 있어요. 화려한 웹 효과를 코드 몇 줄로 쓸 수 있어요. 이제 웹앱의 시대에는 JS도 MVC 프레임웍을 써야 해요. 다 좋다. 익숙해지면 생산성을 크게 높일 수 있을지 모른다. 이런 거 흐름을 놓치면 시대에 뒤쳐지는 개발자가 되버릴 것 같은 느낌을 주기도 한다. 우리도 얼른 적용해서 뒤쳐지지 말아야지. 이런 생각으로 기술은 따라가면서 스타트업에선 뒤쳐지게 된다. 눈앞의 과제에 대한 최선의 해결책을 찾으려고 하다보면 필요한 신기술은 자연스럽게 적용하게 된다. 따라가려고 애쓰지 말고 당면 과제에 충실하되 변화의 흐름에는 귀만 열어둬라. 필요해질 때 찾아서 쓸 수 있도록.

동일한 목적의 프레임웍이나 라이브러리를 여러 개 쓰지 말 것

이를테면 django를 쓰면서 템플릿 언어가 맘에 안 들어서 mako로 바꾸는 것까진 좋은데, django template으로 된 코드와 mako로 된 코드가 혼재하게 하지는 말라는 것이다. 그러면 뭔가 바꾸어야 할 때 작업이 두 배로 는다. 실제 예를 든다면, 지금 내가 유지보수하고 있는 코드는 PHP인데 Code Igniter를 전면적으로 쓴 코드, Code Igniter에서 일부분만 불러 쓰고 예전 PHP 스타일로 짠 코드, Code Igniter 쪽 완전 무시하고 짠 PHP 코드가 섞여 있다. 근데 페이스북 로그인 처리 쪽에 코드를 고치려고 봤더니 그 과정에서 호출되는 URL 네 개가 다 스타일이 다르다. 그래서 session에서 값 읽어오기, 로그인 여부 처리하는 코드 등등 전부 네 가지 방식을 모두 찾아내서 처리해야 했다. Code Igniter를 쓰기로 결정했다면 끝까지 써야 하고, 갈아엎을 꺼면 빨리 갈아 엎어야 한다.

물론, 현재 쓰고 있는 프레임웍이 맘에 안 든다면 점차적으로 갈아엎을 수는 있다. 그 과정에서 일시적인 공존은 괜찮다. 이런 작업을 할 때는 한 번에 갈아 엎는 것보다 점차적으로 갈아엎는 게 더 낫다. 하지만, 이건 빠른 시간 내에 끝내야 하고, 이런 작업을 할 때조차도 공통적인 코드들은 합쳐 놓으려는 시도를 해야 한다. 이를테면, config는 양쪽 스타일에서 같이 쓸 수 있도록 고쳐놓은 다음 전환 작업을 시작한다거나 하는 방법이 있다.

이미지 리사이징 같은 것도 마찬가지. 어디는 gd2 라이브러리로 하고, 어디는 python-imaging을 쓰고, 어디는 imagemagik 바이너리를 호출하고, 이런 식으로 섞여 있으면 나중에 리사이징 로직에 뭔가를 바꾸었을 때 어딘가 구멍이 생기게 된다. 추상화까지는 해놓지 않더라도, 사용하는 라이브러리만 잘 통일해도 이런 문제는 막을 수 있다.

마무리

어쨋든 스타트업은 quick & dirty로 달려가야 한다. 기술 부채가 두렵다고 clean code를 극한까지 추구한다면 아무도 쓰지 않는 훌륭한 제품이라는 현실에 직면하게 될 것이다. 스타트업도 투자고, 부채로 레버리지를 한다면 원하는 이익 실현 시점을 앞당길 수 있다. 기술 부채 만드는 것을 두려워해선 안된다. 다만 그 기술 부채를 감당할 수 있는 수준으로, 파산하지 않게 유지하라는 것이다. 그렇게 큰 노력을 기울이지 않고도, 엄청나게 훌륭한 리팩토링을 해내지 않고도 그럭저럭 통제할 수 있는 수준을 유지할 수 있는 방법들이 있다. 물론 또 너무 저런 걸 다들 잘하면 내 밥벌이가 안되겠지. 너무 좋은 코드도, 너무 나쁜 코드도 스타트업에겐 좋지 않다. 적정 기술, 적정 품질을 생각하면서 일하는 엔지니어가 되도록 하자.


블로그 / 소프트웨어 개발

Youngrok Pak , 10 years, 5 months ago

아이폰과 맥 사진 관리 방법 정리

그동안 사진 관리에서 삽질 끝에 찾아낸 방법을 정리해본다.

우선 목표는 다음과 같았다.

  1. 어디서 찍은 사진이든 유실되지 않을 것
  2. 아이폰에서 찍은 사진 컴퓨터에서 보기 쉽게
  3. 아이폰 이외에서 찍어서 컴퓨터에 보관 중인 사진도 아이폰으로 볼 수 있게
  4. 여행 등 큰 이벤트는 별도로 정리
  5. 선화나 친가, 처가와 공유할 사진은 공유하기 쉽게
  6. 대용량 사진은 적절한 사이즈로 줄인 사진을 볼 수 있게. 원본은 별도 보관해도 된다.

히스토리를 좀 보자면, 윈도/리눅스를 쓸 때는 피카사를 쓰고 외장하드에 백업하는 방식으로 했는데, 편한 듯 불편한 듯 뭐 그저 그랬다. 그땐 폰으로 흘러간 윈도 모바일폰 알육이를 썼는데, 지금 생각해도 윈도 모바일의 싱크 기능은 아이폰보다 월등히 좋았다. 꽂기만 하면 문서고 사진이고 죄다 자동으로 양방향 싱크를 해주고, 충돌처리까지 어느 정도 해줬으니 iCloud 나오기 전의 iTunes 싱크보다 100배쯤 좋고, 심지어 지금의 포토스트림보다도 편한 부분이 있다. 뭐 아뭏든, 그 땐 사진이 그렇게까지 많진 않아서 좀 수작업 해도 별 문제 없이 관리할 수 있었다.

그러다가 맥으로 넘어가면서 iPhoto를 발견하게 되었는데, 처음에는 정말 너무 좋았다. 피카사도 좋다고 생각했지만 iPhoto가 훨씬 이쁘고 쉬웠다. 그래서 전에 모아둔 사진은 전부 iPhoto 보관함에 밀어넣고 아이폰에서 찍은 건 가끔 연결해서 iPhoto에서 가져오기를 했다. 그리고 iTunes의 사진 싱크를 통해서 아이폰으로 싱크. 여기까진 괜찮았다.

근데 문제는 iCloud를 쓰면서부터 발생했다. 포토스트림이 버그가 있는지 사진이 유실되기도 하고, 무엇보다 자동으로 가져오기를 했더니 이벤트에 "8월의 사진 스트림" 같은 게 딱 생기면서 가끔 아이폰 연결해서 가져오면 중복 사진도 생기고 뭔가 꼬여서 정리가 안되는 느낌. 그래서 이 때부터 고민을 다시 하기 시작했다. 어쨋든 예전에 쓰던 방식은 사진이 클라우드에 보관되는 건 아니라서 불편하고 불안했다. iCloud는 스토리지가 아니라 싱크 개념이라서 목적에 안 맞고. 그래서 Dropbox에 넣고 피카사를 쓰는 방안, iPhoto Library를 통째로 Dropbox에 넣기, 무제한이 된 구글 플러스 이용하기 등등을 검토해보았다. 

우선 사진 정리 도구로는 iPhoto 아니면 피카사다. Apperture를 사진 않을 테고, 우분투로 돌아가서 shotwell을 쓸까 하는 생각도 1초 정도는 했지만... 암튼, iPhoto는 내가 Xcode(아이폰 개발 안되면 맥이 한국에서 뭐 그리 많이 팔렸겠어?)와 함께 맥의 양대 킬러앱으로 꼽는 앱이라 애착이 있었고, 피카사를 3년 넘게 썼다는 게 믿기지 않을 만큼 피카사가 어렵게 느껴져서 결국 iPhoto는 어떻게든 쓰기로 했다.

보관용 클라우드는 iCloud, Dropbox, 구글 플러스 중에 하난데, iCloud는 보관 개념이 아니라서 탈락, 구글 플러스랑 Dropbox 중에서 고르기로 했다.

그리고 아이폰의 사진을 싱크시키기. 이것도 iCloud, Dropbox의 카메라 업로드, 구글 플러스 무제한 자동 업로드 중 하난데, 구글 플러스의 무제한, 그리고 피카사를 보조 도구로 사용하기 좋다는 점, 웹 앨범이 괜찮다는 점 등이 땡겨서 이걸로 먼저 시도해봤다. 근데 구글 플러스 앱을 실행한 직후에만 백그라운드로 업로드가 된다. 그러니까 구글 플러스를 계속 안 열면 사진 찍어도 업로드가 안된다는 것. 물론 이건 iOS의 한계다. 그리고 업로드 진행률 같은 게 적절히 표시되지 않았다. Dropbox 카메라 업로드는 아이폰, 맥 다 되고 구글 플러스에 비해 안정적이고 빨라서 좋지만, 역시나 포토스트림처럼 빨리 싱크가 되진 않는다. 결국 어떻게든 포토스트림을 쓸 수 밖에 없다.

포토스트림을 쓴다면 보관용 클라우드로 구글 플러스는 중복이라 내키지 않는다. 결국 답은 Dropbox.

결국 제약사항들을 따져보면 iPhoto, Dropbox, iCloud의 사진스트림을 조합할 수 밖에 없다는 결론. 이 제약 안에서 어떻게 쓸지 베스트 프랙티스를 만들어가봤다. 그래서 나온 방안은 이렇다.

  1. 아이폰 외에 찍은 사진은 모두 Dropbox의 Photos 폴더 아래에 넣는다. 적절히 폴더로 관리한다.
  2. iPhoto Library를 새로 만들고 그 파일 역시 Dropbox의 Photos 폴더 아래에 넣는다. 그럼 이제 iPhoto의 상태도 자동 백업되는 셈.
  3. iPhoto에서 가져오기할 때 보관함으로 항목 복사를 체크 해제한다. 그러면 사진 가져올 때 메타 정보 가져와서 썸네일만 생성하고 사진 파일 카피를 하지 않는다. 그래서 파일은 iPhoto에서 분류되는 구조가 아니라 원래 있던 위치에 그대로 있다. 이러면 중복 파일이 잘 안 생겨서 용량을 아낄 수 있고(아이폰이 16G라 용량 문제는 꽤 심각하다) 나중에 피카사랑 같이 쓸 수도 있다.
  4. 포토스트림을 켠다. 포토스트림에서 가져온 파일은 iPhoto Library 안에 복사가 된다. 보관함으로 항목 복사를 체크 해제했는데도 복사가 되는 게 뭔가 이상하지만 암튼 내 의도랑은 맞아떨어진다. 포토스트림의 파일이 Dropbox에 옮겨져서 백업되는 셈이기 때문에 안전하다.
  5. 포토스트림에서 자동 가져오기를 켠다. 그러면 "8월의 사진 스트림" 같은 이벤트가 생기는데, 주기적으로 이벤트 - 선택된 이벤트 자동 분리를 실행시켜서 이벤트를 정리해준다. 전에는 이걸 몰랐었다. 이게 있으면 사실 그냥 iPhoto와 iCloud 조합만 써도 백업 이외에는 꽤 만족스럽게 쓸 수 있다.
  6. 공유해야 하는 사진들은 Dropbox에 넣고 공유한다. 부모님도 다 스마트폰이라 public link를 생성해서 보내면 다 볼 수 있다. 경우에 따라 피카사를 띄워서 구글 플러스로 업로드해서 공유하기도 한다.
  7. iPhoto로 정리된 것들은 iTunes를 통해서 아이폰에 싱크한다. 어차피 새로 생기는 사진은 대부분 아이폰에서 생기기 때문에 자주 할 필요는 없다. iTunes 사진 탭에서 다음으로부터 동기화에 iPhoto를 고르면 된다.
  8. 대용량 사진들은 강석천씨가 아이디어를 내고 정성원씨가 개발해서 이콜레모가 출시한! 이콜레모에 매달 20만원씩 벌어다주고 있는! Photo Resizer를 이용해서 적당히 줄인 후, 원본은 외장 하드에 넣어두고 줄인 것만 Dropbox에 넣어서 iPhoto로 가져온다. 솔직히 이거 나도 쓰게 될 줄은 몰랐다.

이걸로 언제 어디서나 내가 찍은 사진들을 볼 수 있고, 사진 잃어버리지 않고 모두 만족스럽다. 다만, Dropbox 100G를 구매해서 매년 $99가 나간다.

이상~


 

블로그

Youngrok Pak , 10 years, 5 months ago

프로그래머에게 필요한 피드백

 

수십년 동안 전문가가 안되는 비결에 따르면, 믿을 수 있는 직관이 형성되려면 유효성과 피드백이 갖춰져야 한다고 한다. 믿을 수 있는 직관이 형성된다는 것은 곧 전문가가 된다는 이야기. 그렇다면 소프트웨어 개발자에게 필요한 유효성과 피드백은 무엇일까? 유효성 이야기는 조금 어렵고 복잡하므로 다음으로 넘기고 피드백을 보자. 프로그래머는 어떤 피드백을 받아야 전문가로 발전하는데 도움이 될까?

아마 많은 사람이 피드백 하면 상사나 동료로부터 잘했다 못했다 이야기를 듣는 것을 먼저 떠올릴지 모른다. 하지만 이건 다들 알다시피 답이 아니다. 상사나 동료가 정확한 판단을 내린다는 보장이 없기 때문이다. 드라이퍼스 모델에 따르면 전문가의 수는 극히 적고 대부분 초보자, 고급 입문자, 중급자에 머물러 있다. 그렇다면 상사나 동료도 전문가일 확률은 아주 낮다. 그렇다면 상사나 동료의 피드백은 비전문가의 피드백이며 그것이 정확한 의견일 가능성은 낮다. 또, 전문가라고 해서 꼭 자신이 왜 잘하는지를 알고 있는 것은 아니기 때문에 전문가 역시 좋은 피드백을 준다는 보장은 없다. 물론, 상사나 동료의 피드백에도 진실은 담겨 있다. 하지만 그것은 전체의 진실이 아니라 일부의 진실이고 열심히 듣되 스스로 판단해야 하는 종류의 피드백이다. 어찌되었건, 전문가로 가는 길과는 크게 상관이 없다.

잠시, 반대로 피드백이 아주 좋은 분야를 생각해보자. 어떤 분야가 있을까? 탁월한_조직이_빠지기_쉬운_5가지_함정에 한 가지 예가 나온다. 스포츠. 스포츠에는 점수와 승패라는 명확한 피드백이 있다. 1:1 경기일수록 피드백은 더 명확하다. 이런 분야일수록 전문가와 비전문가의 차이는 엄청나다. 투자한 시간에 어느 정도 비례해서 실력이 올라가기 때문에 취미로 하는 사람이 프로를 이길 가능성은 거의 없다. 하지만 프로그래머는 어떤가? 낮에는 바쁘게 환자를 치료하면서 밤에 백신을 만든 안철수는 다른 프로그래머들보다 훨씬 빨리 바이러스 대비책을 내놓았다. 수많은 프로그래머들을 제치고 한 고등학생이 한국 앱스토어에서 짱먹었다. 18세 브라질 청소년이 리눅스 커널 메인테이너가 되고, 입사 1년차가 7년 경력 사원보다 높은 성과를 내곤 하는 것이 프로그래머다. 프로그래머들이 프로 바둑기사만큼 전문성을 발전시킬 수 있었다면 이런 일은 일어나지 않을 것이다.

반대로 이야기하면 프로그래머에도 자신의 성과에 대한 명확한 지표가 있다면 더 전문성을 높여갈 수 있다. 탁월한_조직이_빠지기_쉬운_5가지_함정에서 스포츠의 예를 든 이유도 기업이 성과를 내기 위해서 성과를 평가할 수 있는 지표가 필요하다는 이야기를 하기 위함이었다. 프로그래머 역시 그런 지표가 필요하다. 내가 참여한 프로젝트가 얼마나 돈을 벌었는지, 얼마나 많은 사람에게 도움을 주는지, 혹은 얼마나 돈을 절약했는지 등등. 혹은 적어도 이 프로젝트가 납기 안에 잘 끝났는지라도 봐야 한다.

이렇게 성과 측면에서 평가할 때 TheGoal에서 지적하는 부분 최적화를 피해야 함은 물론이다. 나는 완벽하게 프로그래밍했는데 기획이 잘못되서 서비스가 망했어. 이건 제대로 된 평가가 아니다. 프로젝트 성공에 대한 책임은 모두가 같이 지는 것이다. 내가 더 빨리 프로그래밍해줬으면 기획자가 더 빨리 잘못을 인지하고 수정할 수 있지는 않았을까? 이런 질문을 해봐야 한다. 굳이 성과로 회사가 돈을 얼마 벌었는가까지 봐야 하는 이유도 그런 측면이 강하다. 나라는 틀을 벗어나 프로젝트라는 컨텍스트에서 나의 역할을 평가해야 한다.

그렇다고 서비스가 망했으니 우린 모두 루저야...라고 생각할 필요는 없다. 개인의 책임과 권한의 한계가 있기 때문에 프로젝트의 성공 여부가 전적으로 내 성과랑 연결되는 것은 물론 아니다. 때때로 사람들은 프로젝트가 성공하면 자기 역할이 컸다고 생각하면서, 실패하면 자기 권한으로는 어쩔 수 없었다고 말한다. 자연스러운 심리지만 이런 피드백으로는 전문가가 될 수 없다. 성공한 프로젝트의 팀원이었던 사람을 비싼 돈 주고 스카웃해왔는데 잘 못해내는 경우를 우리는 얼마나 많이 봐왔는가. 그게 바로 내가 될 수도 있는 것이다.

예를 들어 이런 식의 평가라면 괜찮은 피드백이 될 수 있을 것이다. 이 프로젝트가 망했는데, 내가 맡은 부분은 제대로 개발했지만 다른 동료들이 맡은 부분이 제대로 안되는 걸 알면서도 팀장에게 이야기해서 대책을 마련하질 않았어. 내가 그런 사실을 미리 팀장에게 알려주고 다른 사람을 도울 수 있었다면 좀더 나은 결과가 나왔을 꺼야. 혹은 이럴 수도 있다. 이 프로젝트는 대박이 났지만 사실 나 때문에 대박 난 건 아니야. 이 서비스는 플래시 컨텐츠 때문에 대박난 건데 난 웹개발 부분만 맡았으니까. 성공한 프로젝트에 참여한 것은 자랑스럽지만 내 성과로 자랑할 프로젝트는 아니야.

그런데, 이 최종 성과라는 측면도 중요하긴 하지만 프로그래머에게 직접적인 피드백은 아니다. 많은 변수와 맥락을 고려해서 깊이 생각해야 알 수 있는 것이다. 이보다 조금 더 쉽게 얻을 수 있는 피드백이 있다.

그건 바로 제대로 돌아가게 만드는 것이다. 프로그래머라면 당연히 이 정도는 해내야 하는 거 아니냐고? 나도 그런 줄 알았다. 품질이라든가, 버그라든가, 그런 이야기를 하는 게 아니다. 그냥 기능이 동작하게 만드는 것, 그걸 못하는 사람도 많다. 프로그래머라면 코드가 지저분하든 어떻든 일단 기능이 돌아가게 만드는 것은 할 줄 알고 볼 일이다. 그게 되고 나서 코드도 정리하고 버그도 잡고 품질도 생각하는 것이다. 내가 이 프로젝트에서 필요한 기능을 제대로 만들어 내고 있는가. 이것이 일차적인 피드백이다.

물론, 이것은 너무 낮은 목표다. 이 피드백을 받아본 결과 제대로 못하는 것 같다면 프로그래머를 그만둬야 하는지도 모른다. 여기에 한 가지가 더 필요하다. XP에서는 간혹 프로그래머의 목표로 clean code that works를 제시한다.(물론 여기서 이야기하는 목표는 미시적인 목표다.) 하지만 여기서 clean code는 정확히 말하면 목표가 아니라 수단이다. 왜 clean code가 필요한가? 미학? 유지보수를 잘하기 위해서? 남들이 알아보기 쉬운 코드가 좋은 코드니까?

내가 생각하는 답은 더 빨리 개발하기 위해서다. that works를 달성한다는 전제 하에, 더 빨리 개발을 해낼 수 없다면 clean code는 무의미하다. 여기서 더 빨리의 스케일은 1시간 이상이다. 1시간 이내라면 clean code 없이 막 짜도 더 빨리 뭔가를 달성할 수 있다. 하지만 1시간을 넘어가도록 지저분한 코드를 그대로 놔두고 있다면 이미 속도가 느려진 상태일 것이다. 뭐, 1시간은 사람에 따라 차이가 있을 수도 있다고 치자. 엄청나게 똑똑한 사람이라면 1시간 정도의 컨텍스트는 아무렇지 않게 머리에 담을 수 있을지 모른다. 그래도 하루가 넘어가면 어떨까? 아침에 출근하면 어제 코드가 생생하게 그대로 머리에 컨텍스트로 들어오는가? 좋다, 당신은 똑똑한 편이다. 그렇다면 일주일은 어떤가? 한 달은? 스케일이 커질수록 clean code 없이 개발 속도는 낼 수 없다. 아마 평범한 사람이라면 하루를 크게 안 넘어가는 선에서 리팩토링이 필요해질 것이다. 단지 필요하다고 느끼지 못하는 것 뿐.

결국 필요한 피드백은 내가 얼마나 빨리 개발하고 있는가이다. 여기에는 상대 평가도 필요하다. 하지만 대개의 프로그래머는 이런 식이다. 프로그래머가 어려운 기능을 구현하는 모습을 상상해보자. 처음 개발을 시작하고 처음에는 진도가 좀 나가는 것 같다가 막힌다. 이리저리 삽질을 해보지만 잘 안된다. 야근도 해가면서 월요일부터 끙끙 머리 싸매고 열심히 개발하다가 금요일, 드디어 완료했다! 프로그래머는 완료한 기쁨에 휩싸인다. 역시 난 해냈어. 난 훌륭한 프로그래머야. that works에 대한 피드백은 확실하게 챙긴다. 하지만, 비슷한 기능을 다른 프로그래머는 이틀 만에 완료했었다는 사실과 비교해보지 않는다.

아마 대부분의 프로그래머가 생각하는 피드백은 돌아가게 만든다 수준에서 멈출 것이다. 돌아가게만 만들면 난 잘한 것이다. 그래서, 전문가로 가는 성장도 여기서 멈춘다. 프로게이머가 겪는 패배를 프로그래머는 겪지 않는다. 기한 내에 못 마치면 일정이 무리한 것이니까 내 잘못은 아니야.

꼭 다른 사람과 비교해야 하는 것은 아니다. 중요한 것은 정량적으로 측정해보는 것이다. 측정이 불가능하다고? 측정이 정확할 필요는 없다. 흔히 정량적인 측정이라고 하면 정확한 수치가 나와야 하는 것으로 생각하는데, 사실 우리가 자로 재는 것조차도 정확한 수치는 안 나온다. 자의 오차, 눈의 오차 등등으로 오차 범위란 게 있다. 단지 이런 문제는 그 오차 범위가 훨씬 더 클 뿐이다. 그래도 여전히 우리는 판단할 수 있을 만큼의 숫자를 뽑아낼 수 있다.

예를 들면 난 이런 식으로 비교해본 적이 있다. 권한 프레임웍을 만드는데 NHN에서 할 때는 개발에 2주 가량 걸렸고 적용하는데 1주 정도 더 걸렸다. 비슷한 수준의 프레임웍을 이슈 트래커를 만들 때 django로 개발했는데 사흘 정도 페어로 완료했고, 올해 초 자원봉사 커뮤니티를 만들 때는 하루 만에 만들었다. 각기 디테일도 다르고 언어도, 프레임웍도, 환경도, 프로젝트도 다르지만 어느 정도 비슷한 부분을 뽑아내서 비교할 수 있다. 물론, 같은 부분을 한 것이기 때문에 반복 효과가 있어서 이게 곧 실력의 향상은 아니라는 점도 감안해야 한다. 이처럼 다양한 오차 요인이 있지만 대략적인 측정은 가능하다.

어쨋든 돌아가게 만든다는 전제 하에 얼마나 빨리 개발할 수 있느냐는 개발자의 능력에 있어 가장 중요한 척도이며, 이것에 대한 피드백을 계속 받아야 전문가로 성장해갈 수 있다.

하지만, 난 여기서 조금 더 과격한 주장을 하고자 한다. 사실 돌아가게 만든다는 말은 여러 가지로 해석할 수 있다. 품질에 대한 척도는 사람마다 다르기 때문에 이 정도면 기능은 돌아가잖아를 보고 또 어떤 사람은 뭐 이거 제대로 쓸 수가 없잖아라고 말하기도 한다. 그럼 어느 정도 품질을 기준으로 빨리 해야 할까?

난 여기에 품질과 상관 없이 무조건 빨리 하는 게 장땡이라고 말하고 싶다. 중요한 건 최종 릴리스 때 버그 없게 나가는 것이지 매 순간순간 버그가 없어야 하는 것은 아니다. 빨리 개발하면 그만큼 빨리 버그를 발견하고 더 빨리 버그를 고칠 수 있다. 개발자가 꼼꼼히 살펴본다고 모든 버그를 발견할 수 있는 것도 아니다. 그런데 품질을 높이기 위해 신경쓰다보면 고객에게 중요한 기능을 릴리스하는 것이 늦어진다. 프로젝트 진행 중에는 대부분의 고객이 버그보다 필요한 기능이 빨리 구현되는 것을 중시한다. 그래야 그 기능이 고객에게 맞는 기능인지 아닌지를 볼 수 있기 때문이다. 완벽하게 개발해놓고 고객한데 쨘! 하고 보여줬는데 나 이거 필요 없어하는 상황을 맞이한다고 상상해보라. 그보다는 버그가 있는 상태에서 고객과 소통하는 이득이 훨씬 클 것이다.

물론, 품질을 깎아 먹은 결과로 전체적인 프로젝트가 더 느려져서는 안된다. 하나하나의 개별 작업이 빨라야 하는 것 뿐 아니라 프로젝트 전체가 빨리 끝나야 하는 것이다. 더 빨리 프로젝트를 끝내기 위해 품질을 지키려 한다면 그것은 OK다. 다만, 정말로 그 품질을 지키는 것이 프로젝트를 빨리 끝내는데 도움이 되는지 심각하게 고민해봐야 할 것이다.

TDD니 리팩터링이니 각종 기법들의 목표는 모두 더 빨리 프로젝트를 완료하는 것이다. 간혹 XP 비판론자에게서 이런 이야기를 듣는다. clean code니 뭐니 상관 없이 빨리 만들어내기만 하면 되는 것 아닌가. TDD가 추구해야 할 그 무엇은 아니지 않은가. 맞는 말이지만 허수아비 공격이다. XP에서는 clean code 자체를 추구하지는 않는다. TDD가 생산성을 높여주지 못한다면 뭐하러 TDD를 하겠는가? 리팩토링이 시간 낭비이고 프로젝트를 느려지게 만든다면 리팩토링 할 필요 없다. 이런 것들이 다 실제로 생산성을 높여줄 수 있을 때만 해야 하는 것이다.

얼마 전에 이런 질문도 받은 적이 있다. 아니 어떻게 그렇게 빨리 개발했는데 모듈화까지 이렇게 다 하셨어요? 저는 그냥 막 짜는데. 비슷한 맥락이다. clean code니까 빨리 개발할 수 있는 것이다. 머릿속에 100라인 짜리 메서드를 담아야 한다면 빨리 개발하기는 힘들 것이다.

아마도 이런 오해가 나오는 것은 실제로 clean code를 추구하느라 느리게 개발하는 사람이 있기 때문일 것이다. 사실 애자일 커뮤니티에 이런 사람이 많이 보인다. 역시 얼마나에 대한 피드백이 부족한 경우다. 자신이 얼마나 빨리 개발하는지에 대한 피드백을 받지 못하니까 열심히 clean code의 극한을 추구하는 것이다. 게다가 짧은 기간 동안은 자신이 느리더라도 길게보면 자신이 더 빠를 것이라고 생각하는 경우도 있다. 역시 장기간에 걸친 얼마나 빨리 개발하는가에 대한 피드백이 없었기 때문이다.

정리하면, 프로그래머가 생각해야 할 피드백은 크게 세 가지다. 내가 참여한 프로젝트가 성공했는가. 내가 개발한 기능은 제대로 동작하는가. 나의 개발 속도는 얼마나 빠른가. 성장을 위해 가장 중요한 것은 세번째이다. 보다시피 다른 누군가가 말로 줄 수 있는 피드백이 아니다. 내가 직접 판단하고 평가해야 하는 것이다. 물론, 팀 차원에서 이런 피드백을 할 수 있다면 더 좋을 것이다.

슬램덩크의 강백호는 누구보다 눈부시게 성장한다. 그런데, 잘 생각해보면 강백호의 학습 환경은 환상적이다. 백호가 거친 플레이를 하면 심판이 피드백을 주고 수비에 실패하면 상대편 공격수는 강백호만 노려서 공격한다. 백호가 슛 성공률이 낮으니까 쉬운 슛 찬스를 그냥 내준다. 최종 성과는 팀의 승패로 다가온다. 훌륭한 피드백 환경이다. 강백호의 강한 승부욕은 피드백에 더 민감하게 만든다. 그리고 그런 피드백을 받을 때마다 스스로 고민하기도 하지만 옆에서 코치해줄 안선생님과 채치수, 한나가 있다. 롤모델 서태웅도 있다. 이런 환경에서 성장을 못한다면 그게 더 이상할 것이다.

프로그래머도 좋은 피드백만으로 전문가가 되는 것은 아닐 것이다. 본인의 성장 의지도 필요하고 피드백에서 알아낸 상관 관계에서 인과 관계를 분석해 줄 수 있는 코치(혹은 본인의 분석력)도 필요하다. 피드백은 전문가로 가는 길의 첫걸음 정도로 생각하면 될 것이다.


 

블로그 / 소프트웨어 개발

Youngrok Pak , 10 years, 5 months ago

코카콜라배온게임넷스타리그결승전

 

어제 친구랑 둘이서 결승전 보려고 장충 체육관엘 갔습니다. 3시 입장인데 2시 반쯤 갔는데 벌써 사람들이 바글바글하더군요. 줄이 쭈욱 서 있는데 그렇게 긴 줄을 기다려본 건 처음인 듯. 8000명 입장인데 우리 뒤에 한 40명 정도 더 들어오고 끊겼음-_-++ 2000명이 입장 못했다던데 어느 정도 사실인 거 같더군요. 사람들이 앉을 자리가 없어서 계단에 앉고 뒤에도 빼곡하게 서서 보더군요. 좀만 늦게 갔더라면 제대로 못 볼 뻔 했음.--+

들어가니까 해설자들끼리 겜한 거 결승전을 오프닝으로 하는데 정일훈이 좀 웃기더군요. 비록 임요환과 홍진호의 경기에 비해 수준은 좀 낮겠지만 재밌게 봐달라는 둥-_- 김도형이 전날 준결승에서 져서 어제 결승전에 못나왔는데 그거 가지고 계속 놀려먹고 나중에 김창선이 캐리어 1부대 나와서 다 밀고 있는데 상대 선수(송 머시긴데 까먹었음)가 커맨드 여기 저기 지으면서 도망다니면서 게기니까 저렇게 버티는 모습은 보기 안좋죠..등-_-;; 좀 심하다 싶을 정도로 깔아뭉개던데 어쨋든 재밌었음.

그리고 그거 끝나고 나서 코크배 온겜넷 스타리그 화제 베스트 3인가 했는데.. 부문별로 베스트 3를 선정한 거였는데, 이번 대회를 거치면서 팬이 가장 많은 비율로 늘어난 선수가 조정현, 홍진호, 임요환 순인데, 임요환은 팬이 4만을 돌파했더군요. 조정현은 팬클럽 없었는데 이번에 생겼는데 4천 돌파..대단.. 엽기 플레이 선정도 했는데 1위에 임요환의 바락 널뛰기가..ㅡ.ㅡ

그 다음 행사로 토크쇼를 했는데 초대손님이 마린과 메딕..-_-;; 열라 유치했지만 간간히 웃긴 대사로 무난히 시간 때움..-_-++ 근데 사실 이거는 없었어야한 행사인 듯. 이거 없이 그냥 4시 입장하고 5시부터 행사 시작, 6시 결승전..하면 좋았을 텐데.

그 외 잡다한 몇 가지 일들이 있고 나서 6시에 결승전 시작. 열라 흥분되더군요. 8천 관중과 함께 본다는 게...진짜 느낌이 색다름. 친구들이랑 모여서 티비 보는거랑 비교가 안될 정도. 게다가 첫 경기부터 환상적인 경기. 둘다 최고의 집중력을 발휘해서 역전에 역전을 거듭하는 경기였습니다. 처음 임요환이 멀티 드랍 실패할 때 홍진호가 첫 게임을 잡고 시작하나..싶은 느낌, 그리고 잠시 후 홍진호가 러커 드랍으로 타격을 꽤 주면서 게임 끝나나 싶었는데 임요환의 주력 부대가 홍진호의 본진에 드랍..--+ 상당한 병력이 있었는데 정말 화려한 컨트롤로 다 잡아내고 본진에 엄청난 피해를 줌. 결국 막아내고 또 홍진호가 임요환에게 타격을 줘서 재역전하나 했는데 다시 임요환의 본진 마무리 드랍..홍진호 본진 청소됨.-_-;; 임요환이 역전승하나..했는데 이후 이런 역전에 역전이 47분간 계속됨.. 정말 누가 이길지 마지막 5분 전까지도 예측하기 힘든 경기였음. 홍진호로서는 정말 아까울 듯.

둘째판은 정글 스토리, 개인적으로 저그가 많이 유리하다고 생각하고 있었는데 홍진호가 의외로 강도경의 전략을 선택하지 않고 자신의 스타일대로 헝그리저그로 출발, 초반 약간 컨트롤 미스가 있었지만 러커로 임요환이 거의 3~4분 이상 자원을 못 캐게 만들고 그 사이 자신은 멀티 띠고.. 여기서 겜 끝나나 싶었는데 임요환이 3마린 1메딕 1탱크 드랍으로 홍진호 본진 드론 다 잡고 자원 채취 방해, 잠시 후 저글링 1.5부대 가량 쏟아부었으나 사베가 와서 디펜시브 한 방 걸고 지형을 절묘하게 활용해서 전멸시키고 잠시 후 멀티까지 언덕 탱크로 교란, 홍진호도 3~4분 이상 자원 못 캠..-_-;; 그 사이 임요환은 몇 차례 러커 다시 막고 병력 모아 러시..여기서 임요환에게 정말 감탄했는데 홍진호 어느 새 복구하고 히럴 모아서 마메탱 막고 가디언으로 앞마당 치고 피니쉬. 역시 감동적인 경기..

셋째판, 네오 레가시 오브 차, 임요환 1바락 더블커맨드, 성공하고 3바락으로 감. 여기서 임요환이 마메로 밀어 붙이면 금방 끝나는 겜이 아닌가 싶었는데 임요환 바락 볼 때마다 불 꺼져 있음-_-;; 웬지 져주는 게 아닌가 싶은 느낌이 들 정도로 임요환 삽질하다가 패배. 임요환이 머쉰의 생산력을 갖춘다면..하는 아쉬움이-_-

넷째판, 기대했던 라그나로크. 홍진호가 자신이 3:1 승리를 예상했다고도 했고 라그나로크가 해볼만하다고 말을 해왔기 때문에 기대를 많이 해왔고 기대대로 허를 찌르는 언덕 아래 성큰 러쉬-_- 성공은 했는데 의외로 언덕 위 공격 시 확률 감소가 커서 scv 몇 마리 잡지도 못하고 잠시 후 탱크 나와서 그거 밀리고 모았던 마린메딕파벳 러시, 멋진 저글링 버로우로 상당한 타격을 입으나 파벳이 워낙 많아서 거의 파벳 러시로 피니쉬..

다섯째판, 홍진호의 허접한 뮤탈 컨트롤이 돋보였던 게임-_-;; 아마 그 뮤탈을 내가 컨트롤했더라면 손쉬운 승리를 하지 않았을까..싶을 정도로 유리한 시점을 다 놓쳐버리고 임요환의 테크니칼한 드랍쉽 교차 드랍?에 털려 겜셋..싱거웠음.

막판이 싱거워서 좀 아쉬웠지만 정말 흥분되고 감동적인 결승전이었습니다. 마지막에 시상식까지 보고 왔는데, 가까이서 보니까 임요환 진짜 잘생겼더군요. 키도 크고 정말 외모에서는 흠잡을 데가 없을 정도. 장진남도 가까이서 보고 조정현도 보고 했는데 다들 잘생겼더군요. 홍진호는 겜 끝나고 울었다던데-_- 정말 눈물 나올만한 상황이었던 듯-_-

아뭏든 정말 재밌었습니다. 담에도 이런 기회가 있으면 한 번 가서 보면 정말 좋을 듯. 여자친구가 스타 좋아하면 같이 가서 봐도 좋을 꺼 같고..--+


스타크래프트분류 / 블로그

Youngrok Pak , 10 years, 5 months ago

정석에_대한_오해

 

정석이라는 말은 수학의 정석이 흐려놓은 개념과는 달리 원래 바둑에서는 상당히 높은 유연성을 함축하고 있는 말이다. 수학의 정석에서는 문제를 푸는 최선의 방법 하나를 이야기하는 것이지만 바둑에서 정석은 정석 사전이 있을 만큼 다양하다. 정석은 귀에서의 수순을 이야기하는 것이지만 실상 실전에서 귀에서 같은 상황이 나왔다고 같은 정석을 써야 한다는 것은 아니다. 이웃한 다른 귀, 심지어 대각선 건너의 귀의 배석에 따라서도 정석 선택이 바뀐다. 그래서 사실 정석은 상황에 따라 선택해야 하는 것이다. 그렇다고 정석 중에만 선택하는 것도 아니다. 때때로 선수를 뽑기 위해 손해를 감수해야 할 때도 있고 여러 가지로 정석과 다른 수순을 밟아야 할 때가 많다. 그래서 정석은 배우고 잊어버려라라는 말이 있는 것이다.


블로그

Youngrok Pak , 10 years, 5 months ago

 


Comments




Wiki at WikiNamu