'개발'에 해당되는 글 13건

  1. 2009.02.01 짧고 습관적인 코드로 패턴 만들기 (3)
  2. 2009.01.01 사가의 시대가 다시 도래하기를 기다리며
  3. 2008.10.15 그래도 기획서는 필요하다 (2)
  4. 2008.10.05 프로그래머가 원하는 기획서 (21)
  5. 2007.10.01 단위 테스트로 스펙을 정의해요 (10)
  6. 2007.08.22 서브버전 커밋 알림 (12)
  7. 2007.08.20 자주 통합하고 커밋 알림을 사용하세요 (13)
  8. 2007.02.12 왜 사용자 스토리? (26)
  9. 2007.01.13 기획에서 기능 명세 얻기 (4)
  10. 2007.01.10 사용자 스토리 (9)

짧고 습관적인 코드로 패턴 만들기

두 요소를 비교하거나 컨테이너에 들어있는 요소의 정렬할 때 키가 둘 이상인 경우가 종종 있지요. 먼저 하나를 비교하고 같을 때 두 번째 값을 비교하는 형태로 구현합니다. 그러면 아래처럼 생긴 코드가 되지요.

  1. bool greater(const Element& source, const Element& target)
  2. {
  3. if (source.first < target.first) {

  4. return true;

  5. } else if (source.first == target.first) {

  6. return source.second < target.second;

  7. }

  8. return false;

  9. }

이런 함수를 클래스 연산자로 재정의하기도 하고 유틸리티 함수로 만들기도 하는데요 오늘은 범용으로 사용할 수 있는 함수를 하나 만들어 볼까 합니다. 오늘 하고 썼다고 해서 내일 뭔가 만들지는 않습니다만.

논리표현식 적용하기

제가 복잡한 조건문을 읽기 편하게 만들기 위해 사용하는 클래스가 있습니다. 이름은 아무래도 상관없지만 여기서는 이걸 LogicalExpression 이라 부르겠습니다. And(&&)와 Or(||)가 복잡하게 섞인 조건문은 아무래도 읽기 어렵기 때문에 괄호로 싸인 각각의 묶음을 역할에 따라 이름을 붙여주려 할 때 사용합니다. 예를 들어 다음과 같은 코드가...

  1. // 버프가 취소됐거나 지속 시간이 지났으면 제거합니다
  2. if (
  3. (buff.live == false) ||
  4. (buff.live && (buff.tickInitialized + buff.tickDuration <= Time::tickNow)) {
  5. remove(buff);

  6. }

아래처럼 바뀔 수 있습니다. 

  1. LogicalExpression isDead(buff.live == false);
  2. LogicalExpression isExpired(buff.live);
  3. isExpired.and(buff.tickInitialized + buff.tickDuration <= Time::tickNow);
  4. if (isDead.or(isExpired)) {
  5. remove(buff);

  6. }

의미가 더 명확해졌죠. 이제 주석이 필요없는, 의미를 말하는 코드가 되었습니다. 비록 예를 위한 예이긴 해도 어떤 용도로 쓰는지는 아실 거에요. 그럼 우리가 처음에 만든 비교문을 LogicalExpression을 써서 다시 만들되 범용성을 갖도록 해봅시다.

  1. template< typename _Ty1, typename _Ty2 >
  2. bool greater(_Ty1 s1, _Ty1 t1, _Ty2 s2, _Ty2 t2)
  3. {
  4. LogicalExpression greaterFirst(s1 < t1);
  5. LogicalExpression greaterSecond(s1 == t1);
  6. greaterSecond.and(s2 < t2);
  7. return greaterFirst.or(greaterSecond);
  8. }

코드는 더 짧고 명확해졌고, 의도한 건 아니지만 복잡성이 줄어드는 부작용도 일어났습니다. 에전 함수는 Element에 대해서만 사용할 수 있었지만 새로운 함수는 그렇지 않고요. 대신 예전보다 부르기가 번잡스러우니 일을 줄여주는 매크로를 만들 수도 있겠지요.

  1. #define GREATER_2(s,t,a,b) greater(s.a, t.a, s.b, t.b)
  2. {
  3. if (GREATER_2(source, target, first, second)) {

  4. // target이 더 크다!

  5. }

  6. }

뭔가 신경쓰인다

우리가 만든 새로운 greater 함수에서 첫 번째 요소가 두 번 나오잖아요? 큰지 한 번 보고 같은지 한 번 보니까요. 신경쓰이네요. 비슷한 구문이 반복되면 실수할 여지도 생기고, 이유야 어쨌든 왠지 기분 나쁩니다. 비교하는 값은 동일하고 부등호만 바꿔볼 수 있는 객체가 있으면 좋겠군요. 이걸 PairEvaluate 라고 합시다. 이 객체에 값을 한 번만 넣고 greater()나 equal() 메소들를 부르면 될 것 같네요.

 

  1. #define GREATER_2(s,t,a,b) greater(PairEvaluate(s.a, t.a), PairEvaluate(s.b, t.b))
  2. {
  3. if (GREATER_2(source, target, first, second)) {

  4. // target이 더 크다!

  5. }

  6. }

    template< typename _Ty1, typename _Ty2 >
  7. bool greater(const PairEvaluate< _Ty1 >& first, const PairEvaluate< _Ty2 >& second)
  8. {
  9. LogicalExpression greaterFirst(first.greater());
  10. LogicalExpression greaterSecond(first.equal());
  11. greaterSecond.and(second.greater());
  12. return greaterFirst.or(greaterSecond);
  13. //return first.greater() || (first.equal() && second.greater());
  14. }

마지막 줄에는 LogicalExpression 없이 동일한 의미를 하는 코드를 적어봤는데요, 오히려 이편이 읽기 좋군요.

이 글은 스프링노트에서 작성되었습니다.

신고
Trackback 1 Comment 3

사가의 시대가 다시 도래하기를 기다리며

1996년 봄, 나는 내가 공동 창업했던 회사로 돌아왔다. 켄 슈와버는 인디비쥬얼 사에서 체험했던 스크럼에 대해서 상당히 많은 내용을 기록해 놓았다. 인디비쥬얼 사의 스크럼에서 가장 인상 깊었던 점은 개발팀이 한 분기에 두 개의 인터넷 제품을 인도했다는 사실도, 그 제품들 중 하나가 여러 차례 릴리스 되었다는 사실도 아니다. 그것은 스크럼을 시작하면서부터 한 주에 여덟 시간이나 하던 고위 임원들의 회의를 없애버렸다는 사실이다.

많은 기록의 목적 중에서 역사를 남기는 것만큼 재밌는 게 또 있을까 싶습니다. 옛날처럼 목숨을 걸고 해야만 하지 않는다면요. 요즘 스크럼 책을 읽고 있는데, 스크럼이 지금의 모습으로 이룩된 근저에는 켄 슈와버씨의 저 기록이 큰 실마리가 되었지 않나 하고 조금 감동을 받았습니다. 기록의 중요성은 또 말해 무엇하겠습니까만, 소프트웨어 개발에 있어서든 조직에 있어서든 기록만큼 중요한 것은 없습니다. 그것이 조직의 성장에 직접적으로 기여하기 때문입니다. 정확히 말하면 결과물을 인도하는 것 다음으로 중요한 것이겠죠.

십 년을 넘게 살아 남은 역전의 용사와 같은 조직들 내부를 들여다 보면 실상은 그리 자라지 않은 듯한 인상을 받는 일이 많습니다. 왜 그럴까요? 일전에 김창준님이 일 년짜리 경험을 열 번 반복하는 개발자에 대해 쓰신 글을 인상적으로 읽은 기억이 있는데, 조직의 경우에도 마찬가지로 대입할 수 있는 통찰입니다. 차라리 십 년짜리 경험을 쌓은 개인을 찾는 편이 더 쉬울 것 같습니다. 저도 개인의 경험이 조직의 지식으로 편입되지 않는 현실이 안타까워 개인적으로 메모를 남겨 두었던 것이 기억납니다. 그런 차원에서 친구가 작은 회사에서 기획 팀장을 맡게 되었다고 했을 때 그에게 모든 것을 기록해야 한다고 조언한 적이 있어요. 모든 팀원이 프로젝트에 대한 기록을 한 자라도 더 남길 것을 장려하려면 블랙 박스를 하나 만드는 것이 어떠냐고 말입니다. 프로젝트가 끝나야만 열어볼 수 있는 블랙 박스에 익명으로 지금의 심정을 적을 수 있도록 해서 자주 사용하게 권유하라고요. 만약 그 일이 제대로 진행되었다면, 마지막에 그 상자를 열어 보는 기분이 어떨까, 매우 각별하지 않을까, 지금도 종종 상상해보곤 합니다.

적으나마 제 경험을 나누어 볼게요. 지난 회사에서 마지막으로 진행했던 프로젝트에서 저는 여러 가지 문제를 겪으며 고생을 하다가 중도에 나오게 되었습니다. 그러면서 다짐을 했습니다. 이번 프로젝트엔 성공하든 실패하든 기록을 차곡 차곡 쌓아가서 포스트 모텀을 써보자고요. 그게 벌써 삼 년이 지났네요. 이제 프로젝트가 마무리할 때가 되었거나, 터닝 포인트가 될쯤에 서서, 지나온 길을 되돌아 보니 남아 있는 기록이 거의 하나도 없더군요. 사람이 기억하는 내용은 반드시 사멸하는 법입니다. 책임 있는 자리에 있는 사람조차도 중요한 것은 거의 아무 것도 기억해내지 못하고요. 인간이니까, 어쩔 수 없지요. 위키위키나 svn 로그를 통해 사라진 역사를 역산해 보려고 했지만, 모든 게 남아있는 것은 아니라 수월치 않았습니다. 정확히 말하면, 결정은 남아 있지만 과정은 없더라는 거죠.

환경을 바꾸려고 들기 전에 해야 할 일은 나부터 바꾸는 일일 겁니다. 비교적 의욕을 가지고 시작했고, 통계를 내보고 싶은 메트릭도 많이 있었고, 흥미도 있었지만, 결국 좌절하고 말았습니다. 흔히 개발자가 본래 다루어야 할 업무와 다르다고 여겨지는 일을 하는 것은 여유로 보여지고, 그 역량을 본래 투자되어야 할 곳으로 돌리도록 요구됩니다. 설사 이 또한 개발자의 업무라고 인정되는 환경에서 일한다 해도 제가 생각한 만큼 충분한 시간을 투자하는 것은 어려운 일이라는 결론을 얻었습니다. 팀에는 다양한 관점으로 보고 다양한 형태의 기록을 남겨줄 전문적인 테크니컬 라이터가 필요합니다. 때문에 제가 종종 꿈꾸는 '내 팀'에는 테크니컬 라이터도 한 자리를 차지하고 있습니다. 그러나 제가 항상 고민하는 건 그의 커리어 패스를 어떻게 보장해야 할까? 하는 문제입니다. 우리 팀에서 테크니컬 라이터에게 업무를 주고, 역량을 키워나간다 쳐요. 그러나 현실적으로 업계에는 그가 따라 갈 커리어 패스가 없습니다. 여러가지 이유로 그가 팀을 나가게 된다면 최악의 경우 경력을 인정받지 못하거나, 적어도 가시밭 길이 예정되어 있을 겁니다. 차마 그런 미래를 그에게 줄 수 없어, PM 밑에 두었다가 기획팀에 두었다가 합니다. 하지만 주위를 둘러보면 그렇게 안배해 놓은 인력도 급해지면 적당히 다른 곳으로 옮겨졌다가 영영 돌아오지 못하는 전직의 길을 걷더라고요.

최근에 미투데이에서 yagur님께 문서화를 전담하는 테크니컬 라이터가 필요하다는 고견을 들었는데 이 모든 이야기들이 서로 통하는 바가 있습니다. 많은 성공작과 그보다 더 많은 실패작을 만들어 내는 아주 많은 회사들이 망한 프로젝트로부터 아무런 배움도 얻지 못하는 이유는 결과는 남되 과정이 남지 않기 때문일 겁니다. 그래서 프로젝트에 사서로 참여하고, 그 결과를 드리밍 인 코드라는 책으로 쓴 스콧 로젠버그가 그토록 부러울 수가 없습니다. 사든 어쩌든, 이 책을 읽어야겠어요.

이 글은 스프링노트에서 작성되었습니다.

신고
Trackback 2 Comment 0

그래도 기획서는 필요하다

그럼에도 불구하고 기획서는 필요한데, 언제일까요?

  • 테스트할 때 - 정상적인 동작이 무엇인지 알아야 합니다
  • 연관된 작업을 할 때 - 기획자나 프로그래머나 다른 작업과 모순이 일어나지 않도록 하기 위해서 --- 또는 기능을 손질하기 위해서 돌아볼 일이 종종 있습니다
  • 새로운 사람이 들어왔을 때 - 기획자나 프로그래머에게 물어봐도 모릅니다
  • 매뉴얼을 작성할 때

기획 단계에 작성했든 개발 직전에 작성했든, 설계 문서의 가장 큰 문제는 개발이 진행 되면서 바뀌는 내용에 대한 지속적인 갱신이 무척 힘들다는 것입니다. 모든 프로그래머는 코딩이 끝나는 순간 일이 끝났다는 안도감을 느끼는 법인데(네, '모든'이라고 썼습니다), 따라서 최종 산출물로 문서를 작성하라는 요구에는 강력히 저항할 수밖에 없습니다. 양을 줄이면 어떨까요? 보통 사용자 스토리에는 자세한 작동 방식을 담지 않기 때문에, 개발이 끝난 다음 상세 명세를 첨부하는 방법을 생각해볼 수도 있겠습니다. 하루 분량의 스토리에서 구현할 수 있는 내용은 많지 않기 때문에 스토리 단위로 문서를 작성하되, 짝과 기획자, QA 담당자와 함께 검토하면서 작성하면 좀 나을지도 모르겠습니다. 전문적인 테크니컬 라이터가 있으면 훨씬 좋겠지만요.

신고
Trackback 0 Comment 2

프로그래머가 원하는 기획서

저는, 무슨 생각이었는지, 어릴 때부터 게임 기획자가 아닌 다른 직업을 가질거라고는 한 번도 생각해본 적이 없었습니다. 특히 --- 회사원이오! (매일 사무실에서 서류를 뒤적이면서, 뭘 하고 돈을 받는 거죠?) 그렇다고 뭐 싹수가 보이는 훌륭한 기획자 지망생이었던 것은 아니지만 그 외에 아무 것도 할 수 없었거든요. 제 청소년기는 온전히 게임 디자인 동호회에서 보냈고, 어느새 정신을 차려보니 게임 기획자로 현업에 데뷔했죠. 열심히 일했고, 오랫동안 준비했기에 자신도 있었습니다. 그리고, 저는, 어느 순간, 마침내, 게임 기획자의 길에서 도망쳤습니다! 단 하나 외에는 한 번도 생각해보지 않은 길에서 내려온 것입니다. 그래서 저는 뭘 하면 좋을지 전혀 모르게 되어버렸었어요.

저는 이제 8년차 게임 서버 프로그래머입니다. 저는 지금 게임 기획자가 아니지만, 제가 예전에 많은 시간을 온전히 거기에 바쳤다는 것을 잊지 않았고, 거의 모든 게임 개발업 종사자들과 마찬가지로 언젠가 내 마음에 꼭 들, 부끄럽지 않은 게임을 만들기 위해 일을 하고 있습니다. 다른 프로그래머들에 비해 제가 좀 유리한 점이 있긴 합니다. 언제라도 기획자의 입장을 이해할 준비가 되어 있다는 것이지요. 준비가 되어 있는 것과 그렇게 하는 것은 조금 다른 문제입니다만. 저는 가능하면 늘 게임 기획자가 원하는 기능을 정확히 구현하려고 노력합니다. 그들이 말하지 않았거나 빠뜨렸던 것까지요. 가끔은 제게 '자꾸 그렇게 해주면 버릇만 나빠진다'거나 '네게 익숙해지면 다른 프로그래머와는 일하기 힘들어진다' 하고 충고해주는 분들도 계십니다만, 저는 예전에 기획자였다는 것을 잊지 않으려고 노력합니다.

하지만 --- 이렇게 생각해봤어요. 내가 언젠가 기획자였기에 유리한 점이 있다면(혹시나 조금이나마 그랬다면), 나중에 다시 게임 기획을 할 적에, 프로그래머였어서 유리할 점도 있을까? 하고요. 그 전에 그런 생각을 한 적이 전혀 없었다는 것은 사실이 아닙니다만 돌이켜보니 구체적인 사례를 떠올려가며 생각한 적은 없더군요. 이 글은 그런 차원에서 생각해보고자 써내려가고 있습니다.

왜 기획서가 못마땅한가?

많은 프로그래머가 기획자나 기획서에 불만을 터뜨리는데, 그 이유가 무엇일까요? 어떤 프로그래머는 기획서가 완벽하지 않으면 코드를 한 글자도 짜지 않겠다기도 하고, 이 기획서 그대로 만들테니 나중에 다른 소리 하지 말라고 다짐을 받기도 합니다. 다 좋은 게임 만들자고 하는 건데 그들이 이렇게 까다롭게 구는 이유가 무엇일까요? 그냥 프로그래머들은 까칠한 성격이 많아서이거나, 까칠해야 프로그래머가 될 수 있다거나 하는 그런 이유일까요?

그들이 가능할 리 없는 --- 한치의 오류도 없이 정확한 기획서를 원하는 것처럼 보이는 이유는 그저 일을 다시 하고 싶지 않기 때문입니다. 프로그래머는 일을 대충하는 것을 싫어합니다. 결과가 신통치 않으면 다시 해야 되고, 정해진 시간에 두 번 일을 하려면 대충하는 수밖에 없죠. 일이 갑자기 늘어나거나 일정이 줄어들어 어쩔 수 없을 때면 죄책감에 빠지기도 하는 게 프로그래머입니다. 어느 수준을 넘으면 그만 자포자기하기도 하고요. 연약한 마음을 가진 사람들이죠.

기획서에 있는 그대로 만들었다고 해서 기획자가 원하는 게임이 만들어진다는 법은 없습니다. 그래서 기획서 그대로 토씨 하나 차이 없이 만들어 내고 나면 기획자도 프로그래머도 고객도 모두가 불만족스러워지는 것입니다. 일을 정말 잘 하기 위해서 필요한 건 사실 기획서가 아닙니다. 정말로 필요한 건 기획자가 원하는 것이 무엇인지 알아내는 거죠. 기획서는 기획자의 부분집합일 뿐입니다. 그들도 사람인지라 실수를 하고 논리적 허점을 발견하지 못하기도 하고, 알고 있는 것을 완벽히 표현하지도 못합니다. 기획서란 그들이 정말로 원하는 것이 무엇인지 알 수 있는 단초에 불과하죠. 그런데 프로그래머는 대체 왜 그런 기획서를 토씨 하나까지 그대로 만들어 내겠다고 하는 건가요? 뻔히 보이는 실수까지 그대로 말입니다. 좀 물어보면서 하면 안 됩니까? 간단한 오류는 스스로 고쳐서 하면 안 되고요?

그것은 많은 프로그래머들이 지쳐있기 때문입니다. 트라우마를 가지고 있기 때문이기도 하고, 어차피 결과를 알고 있기도 하고요. 기획서에 빠진 부분이나 논리적인 결함을 '해결'해서, 소위 빈 칸을 채워가며 개발하고 나면 자기가 들을 소리라고는 '왜 이렇게 만들었느냐' 또는 '내가 원한 건 이게 아니다' 정도 아니겠습니까?

문제가 뭘까?

기획자와 프로그래머의 말이 모두 일리 있습니다. 그렇다면 일이 왜 이 지경이 된 걸까요? 문제는 모든 일이 끝난 다음에야 기획자가 평가를 하기 때문입니다. 모든 일어날 수 있는 사건은 이미 다 일어났습니다. 실수라는 실수는 다 벌어졌고요, 문제라는 문제는 다 발생했죠. 단어 하나에도 까다로운 프로그래머 역시 사람이기 때문에 실수를 합니다. 오해도 하고요. 기획자란 자기가 원하는 결과를 기획서에 옮겨적는 것 하나 제대로 못 하는 사람들이지만 프로그래머는 그걸 그대로 만드는 것조차 못합니다. 결과가 어떻게 되었겠습니까? '글쎄, 이건 내가 원한 게 아니군요.' '그럼 기획서나 제대로 써놓던지요!'

프로그래머가 원하는 기획서는 별 게 아닙니다. 공백이 많은 기획서라도 좋습니다. 기획자의 의도만 확실히 알 수 있다면 그 공백을 유추하여 채울 수 있습니다. 그러고 나서 유추한 결과가 맞는지 미리 알 수 있으면 됩니다. 네, 그렇습니다. 일이 다 벌어진 다음이 아니라 말이죠. 프로그래머가 원하는 건 논리적 결함없이 섹시하게 잘 빠진 기획서가 아니라, 기획자 그 자체입니다. 기획서 따위 알 게 뭐에요. 기획서를 그대로 만든 게임이 재미가 없다면 무슨 소용이 있습니까. 기획자라면 어떻게든 문제를 해결하겠지만요.

한 가지 짚고 넘어갈 게 하나 있습니다. 바로 위에서 내린 결론은 공백이 많은 기획서가 좋다는 게 아닙니다. 모든 일이 다 끝나기 전에 우리가 잘 가고 있는지 가이드가 필요하다는 말입니다. 사람이 쓴 글이라면 늘 오해가 있는 법이라고 말했죠?

한 줄 요약 - 프로그래머가 원하는 기획서는...

사실 그들은 기획서를 원하지도 않습니다. 부분과 전체가 올바르게 제자리를 찾아갈 때까지 기획자와의 반복적이고 지속적인 교감을 원하는 것 뿐이죠.

이 글은 스프링노트에서 작성되었습니다.

신고
Trackback 4 Comment 21

단위 테스트로 스펙을 정의해요

다들 동의하시겠지만, 테스트를 만들 때 제일 힘든 건 역시 이름 짓기입니다. 테스트에는 목적을 잘 드러내는 이름을 붙여 주어야 합니다. 그래서 안 되는 영어로 열심히 작명을 하다 보면 메서드 이름이 너무 길어져서, 원래는 설명을 하려던 것이 도리어 알아볼 수 없는 이름이 되고 말죠. 나중에 결과를 봐도 파일 이름과 줄 번호로 찾아가서야 겨우 알게 되고요. 이럴 때 어떻게 하시나요? 저는 이름을 열심히 짓고, 나중에 못 알아볼까봐서 주석도 열심히 달고 그랬습니다. (저는 CppUnit을 사용합니다.)

루비라는 언어를 보면 일종의 테스트 프레임워크로써 RSpec이라는 게 있습니다. 기존 단위 테스트 프레임워크와의 차이는 클래스에 테스트 메서드 이름을 짓는 대신 일종의 DSL로써 스펙을 말로 정의한다는 거죠. 국내 RoR 레퍼런스의 대표격인 스프링노트를 만드신 강규영(=강애란)님은 RSpec을 본따서 JSSpec을 만드신 바도 있습니다. 아마 테스트 메서드 이름 짓기에 치인 개발자라면 RSpec 환경이 한없이 매력적으로 보일 겁니다. 저처럼 경험이 많지 않은 사람조차 그런걸 보면요.

아무튼 그래서 없어보이지만, 다음과 같은 짓을 해보았어요.

CppUnit.png

저는 Visual Studio 2005를 사용하고요, 테스트 프레임워크는 앞에서도 밝혔다시피 CppUnit입니다. 어느 쪽이든 저렴해 보이긴 마찬가지지만, 중요한 것은 메서드 이름을 지으려고 노력하는 대신 사용자 스토리를 만들거나 스펙을 적는다는 감각으로 하는 게 중요합니다.

CppUnitResult.png

그냥 볼만 하죠?

이 글은 스프링노트에서 작성되었습니다.

신고
Trackback 0 Comment 10

서브버전 커밋 알림

사실 지난 에서 중요한 내용은 커밋 알림이 아니었기 때문에 간단히 다루고 넘어갔는데요, 여러(두) 분이 많은 관심을 보여주셔서 이렇게 소개하는 자리를 따로 마련해 보렵니다. 사실 구현은 간단합니다. 하지만 그 간단한 걸 만들지 않는 이유도 이해합니다. 저도 그랬거든요.

서브버전CVS처럼 몇 가지 후킹 포인트를 제공합니다. 기본적인 기능을 제공하지 않음으로써 후킹을 적극적으로 사용하도록 권장하기도 하지요(^^). 예를 들면 로그 수정같은 기능 말입니다. 후킹이 뭔지에 대해서 설명하고 싶은데, 제 글을 읽는 분 중 저보다 모르는 분은 아마 없으리라 생각해서 관두렵니다. 부끄러워서요.

아무튼 제가 커밋 알림 봇을 만들기 전에 쓰던 후킹 스크립트는 두 개였습니다. 로그 수정을 허용하는 것과 로그 없는 커밋을 거절하도록 하는 스크립트인데, 각각 '리비전 설정 변경 직전'과 '커밋 직전'에 이루어지는 작업입니다. CVS를 사용하던 시절에도 비슷한 스크립트를 넣어 놓곤 했었죠.

아주 예전에 언젠가, msn 봇을 만들려고 파이썬으로 만들어진 라이브러리를 들여다 본 적이 있습니다. 꽤 잘 만들어진 콘솔 메신저를 제공하고 있어서 몇 번 뚝딱거려보고는 말았습니다만은. 그러니까, 저는 그걸 어떻게 만들어야 하는지 이미 알고 있었다는 거지요.

왜 그럴까요? 왜 그걸 안 만들었을까요? 이럴 때 쉽게 할 수 있는 변명은, 바쁘다는 겁니다. 저는 정말 바빴어요. 그리고 또 다른 변명은, 그게 좋은 건 알겠지만, 얼마나 좋은지 몰랐다는 겁니다. 이것도 흔한 변명이죠. 개발 일이 본격화 하고 나면 컨텐츠와 상관없는 것(눈에 보이지 않는 것)에는 손을 대기가 쉽지 않아집니다. 새로운 일을 하는 건 언제나 즐겁지만, 또 언제나 두렵습니다. 우리에게는 관성이라는 게 있기 때문입니다. 하지만 이것 하나는 확실합니다. 곱하기는 언제나 더하기 보다 더 낫다는 거요. 김창준님식으로 하면 복리적인 행동이라고 할 수 있겠죠.

개발 환경에 투자하는 것은 언제나 안 하는 것보다 낫습니다! 하지만, 같은 일을 하더라도 최소한의 노력으로 하는 게 더 이익인 셈이죠. 다른 사람의 동작하는 작업물을 바탕으로 하면 관성과 두려움을 이기기에 더 도움이 되리라 생각합니다. (정신 차려 보면 전혀 다른 코드가 되어 있을지라도요.)

이 소스는 msnlib을 필요로 합니다. 소스를 옮겨 넣으시고, hooks 디렉토리에 들어 있는 'post-commit'을 수정하셔야 합니다.

  1. REPOS="$1"
  2. REV="$2"
  3. /home/svn/project/hooks/commit-notifier.py "$REPOS" "$REV" >> /home/svn/project/hooks/msn.log 2>&1 &

어제도 적었지만 몇 가지 문제는 있습니다. 아마 이 문제를 해결하려면 전혀 다른 방식으로 해야 할거예요. 완성하시면 다시 공개해주실 것을 기대합니다. :]

  • 아직 원인은 찾지 못했는데, 봇이 로그인만 하고 로그를 보내주지 않는 경우가 드물게 있습니다.
  • 봇이 이미 로그인 한 상태에서 소스가 새로 커밋되면 기대하는 동작을 못할 겁니다.

이 글은 스프링노트에서 작성되었습니다.

신고
Trackback 0 Comment 12

자주 통합하고 커밋 알림을 사용하세요

로그 달기

예전에 소스세이프와 서브버전의 차이에 대해서 글을 쓴 적이 있습니다. 로그를 읽어야 쓰기도 한다는 얘기였지요. 이것은 도구의 차이라기보다는 문화의 차이입니다. 그리고 도구가 문화의 필요조건이 되기도 합니다.

로그를 쓰는 이유는 두 가지가 있습니다. 하나는 내가 읽기 위해 쓰는 것이고, 나머지 하나는 다른 사람을 위해 쓰는 것입니다. 내가 쓴 로그를 읽는 것은 어떤 경우가 있을까요? 어떤 코드가 왜 들어갔는지 기억이 안 날 때, 특정한 시점의 작업 내역을 되돌릴 필요가 있을 때, 특정한 시점으로 돌아갈 필요가 있을 때 등이 있겠지요.

그럼 다른 사람을 위해 쓰는 경우는 어떨까요?  다른 사람을 위해 쓴다는 것은 반대로 말하면 다른 사람이 쓴 로그를 내가 읽는다는 것입니다. 일반적으로 협업의 경우겠습니다. 개발자들이 멀리 떨어져 있는 일이 많은 오픈소스 개발에서는 로그 없이는 기본적으로 일이 안 됩니다. 누군가 로그를 달지 않으면 내가 힘드니까 나부터 달게 되는 거지요. 하지만 현업에서는 오히려 로그를 달지 않는 일이 비일비재합니다. 그냥 말로 하면 되기 때문이죠. 정책적으로 다중 체크아웃을 꺼놓고 소스세이프를 사용하면 개발자간의 지속적인 대화 없이는 업무가 불가능합니다. 누군가 파일을 잠궈버리면 아무도 일을 못하니까요. 내가 작업하려는 파일이 잠겨 있으면 잠근 사람에게 요청합니다. 얼른 풀어달라고요. 그 사람이 그저 올리는 것만 잊은 상태라면 즉시 올려줄 겁니다. 그러나 그 파일을 고치는 중이었으면 다급해집니다. 잠시만요, 금방 올릴게요! 급하게 작업을 마무리하고 잠금을 풀어줍니다. 뭐가 빠졌죠? 로그를 달지 않았네요!  그치만 적으면 뭐해요? 아무도 읽질 않는데. 그냥 물어보면 돼죠. 로그를 보는 것이 불편하기 때문에 적을 생각도 들지 않습니다.

버전 컨트롤 시스템을 서브버전으로 바꾼다면 사정이 좀 나아질까요? 별로 그런 것 같지도 않습니다. 어쨌든 로그를 읽을 일이 없잖아요.

자주 통합하기

저는 자주 통합하는 것을 지향하는 파(^^)지만, 현업에서도 통합의 시점에 대한 스펙트럼은 굉장히 넓습니다. 제가 생각하는 자주는 일일 평균 3~5회입니다. 일정 시간마다 하는 것은 아니고 작은 단위로 나눈 일이 끝날 때마다 통합하는 것을 기준으로 하고 있습니다. 적어도 작동하는 상태에서 통합해야하는 것은 당연하지요. 개발자가 여럿이다보면 업무 진도에는 편차가 있기 마련이고, 따라서 평균 1~6회 정도면 적당하다고 봅니다.

반면에 기능이 완성되지 않으면 열흘이고 보름이고 통합을 하지 않는 개발자도 있습니다. 여기에는 어떤 문제가 있을까요? 통합이 늦으면 늦을 수록 통합 비용과 리스크가 상승합니다. 서로 연결되어야 할 모듈을 각기 다른 철학으로 만들거나, 기획을 제대로 이해하지 못해 기능을 잘못 구현하는 등의 문제는 언제든지 발생할 수 있습니다. 문제를 늦게 발견하니 위험이 커지는 것은 당연합니다. 그럼 왜 자주 통합하지 않나요?  저는 이 역시 문화적인 문제라고 봅니다. 아직도 버전 컨트롤 시스템을 쓰지 않고 WinMerge나 WinDiff를 사용하는 팀도 있을 겁니다. (물론 좋은 툴이지요.) 게다가 코드는 FTP나 공유 폴더로 공유하고요. (물론 편하죠.) 이런 환경에서는 잦은 통합 작업이 힘듭니다. 저는 2002년까지도 그런 팀에서 일했습니다. 통합을 늦게 하는 개발자는 아마 최근까지 그런 환경에서 일했을 겁니다. 도구는 쉽게 바꿀 수 있어도 문화의 영향은 쉽게 벗어나기 힘든 법이죠.

자, 만일 여러분이 혼자 일하고 있다고 생각해 보세요. 소스 코드의 주인은 누구인가요? 그리고 그 코드를 빌드하는 주체는 누구인가요? 누구의 코드가 올바른 코드일까요? 사용자의 경험을 제공하는 코드는 결국 누구의 코드일까요? 답을 말씀 드리겠습니다. 답은 물론 여러분과 여러분의 코드죠. 여러분의 하드 디스크 안에 들어 있는 바로 그 코드가 빌드 되어 완성된 모습으로 사용자에게 제공됩니다.

그러면 이번엔 여러분이 혼자 일하긴 하지만 이력 관리를 위해 소스 컨트롤을 사용한다고 생각해보세요. 뭔가 달라지나요? 여럿이 함께 작업한다면 어떤가요? 앞의 질문을 여러분의 팀에 던져보세요. 누구의 코드가 올바른 코드인가요? 여전히 여러분의 코드일까요?

아닙니다. 사용자에게 제공되는 코드는 여러분의 코드가 아니라, 바로 저장소에 있는 코드입니다. 여러분은 그걸 잠시 빌려와서 쓰는 것뿐입니다. 작업하고 있는 동안의 코드는 불안정한 상태입니다. 가능하면 빨리 안정적인 상태로 되돌려 놓아야 합니다. 절대 여러분의 코드가 사용자에게 제공된다고 생각해서는 안 됩니다. 여러분의 컴퓨터에서 프로그램이 잘 빌드 되고 똑바로 실행된다고 해서 최종적인 버전도 반드시 그렇다고 볼 수는 없습니다. 그래서 커밋을 자주 하고 저장소의 코드를 깨뜨리지 않으려고 노력해야 합니다. 저장소 앞에 앉아서 사람들이 소스 코드를 가져가고 돌려놓는 것을 지켜본다고 생각해 보세요. 어떤 부류의 개발자와 일할 때 안심이 되겠어요?

이제 위에서 던져 놓은 질문에 대답하겠습니다. 저장소에 있는 소스 코드가 올바른 코드입니다. 여러분은 저장소의 코드로 결과물을 빌드해야 합니다. 물론 빌드 하는건 더 이상 여러분이 아닐 수도 있죠.

커밋을 자주 하면 문화의 변화가 생깁니다. 커밋을 하기 위해서는 먼저 업데이트를 할 수 밖에 없습니다. (소스세이프에서는 Get Lastest Version이라고 부르는 그것.) 그렇기 때문에 항상 작은 통합을 하게 됩니다. 통합을 하다가 종종 충돌이 나고 빌드가 깨지는 문제가 발생해서 업데이트 하기를 꺼리는 사람도 있습니다. 하지만 반대로 생각을 해 보세요. 그 충돌은 언젠가 나도 날겁니다. 문제가 작을 때 해결하는 게 낫지요. 큰 문제를 잘게 쪼개서 작은 문제가 여러 번 난다면 무슨 이득이 있냐구요? 글쎄요, 이미 작은 문제가  일어났는데 큰 문제가 일어날 때까지 기다릴 수 있을까요?

XP에서는 오히려 커밋을 더 자주하기를 권고합니다. 어떤 문서에서는 15분마다 소스를 동기화(업데이트하고 커밋하는 일련의 작업을 동기화라고 부를 수도 있습니다)하라고 합니다. 이렇게 하는 것에는 부수적인 효과가 있습니다. 개발자마다 각자 작업을 해서 그 결과물을 때때로 저장소에 올려놓는 것이 아니라, 우리가 하나의 소스를 다루고 있다는 생각이 들게 합니다. 일을 하면서 빌드 에러 메시지를 한 번도 보지 않을 수는 없습니다. 마찬가지로 작은 충돌 또한 겨우 그 정도로 여기게 됩니다. 어떤 놈이 잘못된 코드를 확인도 안 하고 저장소에 넣어서 나를 열받게 만드는 게 아니고요.

팀이 소스 저장소에 대해 어떤 어휘를 사용하나요? 주의를 기울여 잘 살펴보세요. 공유폴더 메타포를 사용한다면 이미 위험한 상황입니다. 공유폴더 메타포는 내 하드 디스크에 있는 코드가 진짜고 다른 사람에게 주기 위해 저장소에 올린다는 문화가 만연해 있다는 것을 의미하기 때문입니다.

언제 올려줄거예요?

공유 폴더를 사용하든 버전 컨트롤 시스템을 사용하든 개발자 간에 코드를 공유하는 이상 내가 원하는 코드가 언제 올라오는가를 아는 것이 중요합니다. 예를 들어보죠. 저는 필요한 코드가 올라올 때까지 다른 일을 시작해보려고 합니다. 항상 그럴 수 있는 것은 아니지만 못할 것도 없지요. 마냥 놀면서 기다릴 수는 없잖아요. 그런데 언제까지 그 일을 하고 있으면 될까요? 코드가 올라왔을 때 내가 그 코드를 받을 준비가 되어 있지 않으면 어떻게 할까요? 또, 코드를 올려놓고 알려주지 않거나, 알려주려고 할 때 마침 내가 자리에 없어서 전달되지 않는다면 어떻게 될까요? 어떤 사람이 깨지는 코드를 올렸는데, 그가 퇴근하고 난 뒤에나 그 사실을 알게 된다면요? 하지만 그걸 어쩌겠어요? 이러한 단절은 두 명 이상의 개발자가 작업을 하기 때문에 필연적으로 생기는 걸요. 단지 프로그래머이기 때문이 아니라 혼자서 할 수 없는 모든 분야의 모든 일에서 단절의 문제는 언제나 생깁니다. 역사적으로 한 사람이 모든 일을 다 할 수 없게 된 다음부터 이 모든 문제가 존재하고 있었습니다.

제가 있는 팀은 15분마다 소스 코드를 동기화 하고 있지는 못하지만, 서로의 코드를 그럭저럭 잘 반영하는 편입니다. 서브버전에 소스가 커밋되면 그 내용이 MSN으로 전달됩니다. 그러면 작업자는 내용을 확인하고 필요한 것이면 업데이트를 합니다. 눈에 띄거나 의심스러운 내용이 들어오면 로그를 열어서 변경 내역을 바로 확인하기도 하지요.

서로의 코드가 반영이 잘 안 되는 경우도 있습니다. 릴리즈 막판까지 커밋을 미루었다가 한꺼번에 하는 경우가 그렇습니다. 일을 하면서 그럴 일이 전혀 없을 수는 없습니다. 이 경우에도 업데이트를 자주 한다면 문제를 줄일 수 있습니다. 자주 업데이트 해서 내가 작업하고 있는 내용의 전제가 바뀌지 않았다는 것을 확인해야 합니다. 아무리 일이 다 끝나고 올리고 싶다지만 내가 가정하고 있는 내용이 모두 다 바뀐다면 어떻게 하겠어요? 그걸 커밋할 때 비로소 알았다면 어떻겠어요? 어떻긴요, 저는 일주일간의 작업분을 날린 거지요.

SvnMsnNotifier.png

이 스샷은 파이썬으로 만들어진 msnlib의 msnbot을 조금 수정해서 만든 알리미인데, 만드는 데 들인 공에 비하면 팀에 긍정적인 관점의 변화를 가져오고 있습니다. (치명적인 버그가 있긴 합니다.)

이 글은 스프링노트에서 작성되었습니다.

신고
Trackback 0 Comment 13

왜 사용자 스토리?

여러분들도 이런 경험을 했는지 모르겠습니다. 저는 그런 일이 꽤 많았거든요. 뭐냐고요?

자, 기획서가 잔뜩 나왔다고 칩시다. PM은 여러분에게 기획서 더미를 가져다 주며 일정을 산출해 달라고 합니다. 아직 기획이 완벽하지 않은 상황이니 일정은 대략적이기만 해도 된다고 하네요. 어떨 때는 기획서 대신 시스템 목록만 주는 경우도 있죠. 이제 여러분은 몇 개로 나뉜 시스템 제목을 기준으로 일정을 잡기 시작합니다.

  • A 시스템: 3주
  • B 시스템: 2주
  • C...

하다보니 시스템이 너무 크고 뭉뚱그려 있어서 감이 잘 오지 않습니다. 기획서를 대충 훑어 보면서 시간을 어림셈한 다음 나온 숫자에 안전하게 두 배를 하고 거기에 여분을 더합니다. 에드 요돈의 죽음의 행진(Death March)에 따르면 이런 일정 산출법은 피라미드 시대부터 있었다고 합니다. 나름 역사적 전통이 있는 셈법이지요.

다 마쳤나요? '대략적으로' 산출된 일정을 가져다 줍시다. 이것이 그대로 반영된다면 좋겠지만 현실은 그리 녹록치 않습니다. 현실 세계의 프로젝트는 대부분 '문제 프로젝트'이며 안전한 일정은 잘 받아들여지지 않는 경향이 있습니다. [죽음의 행진]은, 어떤 부류의 PM들은 프로그래머가 가져온 일정을 반 토막 내길 즐긴다고 말하고 있습니다. (개발자이던 시절의 일정 산출법을 떠올리기라도 하나보죠.) 저도 그런 경험을 해보지 않은 것은 아닙니다. 일정이 반토막 날 때 어떤 기분이 들까요? 제 경우를 돌이켜 보면, 억울하긴 했지만 일이 앞으로 어떻게 될 것인지 잘 알 수 없었습니다. 그거라도, 어떻게, 내가 잘 하면 될 거라고 생각했어요. 제가 왜 그렇게 생각했을까요? 미쳤나봐요...

구현의 시간. 시스템의 기능을 하나씩 구현해 나갑니다. 수시로 기획자와 상의를 하고, 기획을 보강 - 수정하고, 구현하기를 반복하다 보니 아무리 계산기를 두드려도 도저히 일정 내에 완료가 불가능하게 생겼습니다. 어떻게 해야 할까요? 업무 간의 우선순위는 정해져 있지만 모든 시스템이 이번 릴리스에 들어가야 하는 필수 항목이라고 합니다. 그래서야 그런 우선순위가 도대체 무엇에 쓸모가 있겠습니까? 결국은 작업하던 시스템의 핵심적인 부분만 구현하고 다음 작업으로 넘어갑니다. 기분이 영 찝찝합니다. 내가 뭘 하고 뭘 안 했는지 누가 알고 있을까요? 애초에 각 시스템이 핵심 기능과 부가 기능으로 나뉘어 있다면 어땠을까 생각해봤습니다만 대안 프로세스가 잘 작동하리라는 확신이 없었습니다. 용기도 없었구요. A 시스템의 핵심 기능이 B 시스템의 부가 기능에 의존성이 있다면 어떻게 합니까? B 시스템의 핵심 기능보다 부가 기능의 우선순위가 더 높아야 할까요? 그런 우선순위는 또 무엇에 쓸모가 있겠어요?

사용자 스토리는 바로 그런 일을 합니다. 시스템을 몇 개의 스토리로 잘 쪼개면 우선순위가 높은 시스템의, 우선순위가 낮은 스토리를 추출해낼 수 있습니다. 그래서 스토리를 사용하면 보다 실질적인 우선순위를 얻을 수 있습니다.

..라고 저는 주장합니다.

사용자 스토리는 어떻게 쓸까요?

저난이도: 인덱스 카드 사기

사용자 스토리를 시도하는데 있어 가장 쉬운 관문은 인덱스 카드를 사는 겁니다. 지금이라도 문구점에 가서 500원짜리 묶음을 사세요. 정말 쉽습니다. 저도 마음을 먹자마자, 문구점에 들른 김에 재미삼아 사봤습니다. 연하장을 좀 사러 가려던 길이었지요. 그러니까, 작년 초에요. 그리고 서랍 속에 넣어두세요. 마음이 든든해질겁니다.

중간난이도: 인덱스 카드 쓰기

이건 좀 어렵습니다. 인덱스 카드를 산 다음에 저는 이런 생각을 했습니다. '사용자 스토리를 좀 더 알게 되면 쓰자.' 하지만 잘 생각해 보세요. 겨우 500원 짜리라구요. 게다가 한 팩에 수십 장이나 들어있어요. 그저 낙서라도 하지 못할 이유가 어디 있어요? 잘 알게 되면 정말 썼을지도 모르지만 알려는 시도조차 안 하게 되더군요. 결국 테이프를 뜯는 데에 반 년이 넘게 걸렸습니다. 정말 용기가 없었던 거죠. 여러분은 그러지 마세요.

일단 시작하고 나니 일은 술술 풀렸습니다. 맨 처음 적었던 것은 에픽이었습니다. 그냥 카드 하나당 시스템 이름 하나씩만 적었지요. 사용자 스토리에 대해 잘 알 필요도 없고, 평소에 하던 것과 그리 다르지도 않습니다.

에픽은 엄밀히 말해 사용자 스토리가 아닙니다. 에픽은 사용자 스토리가 갖는 기본적인 특징과 장점을 갖지 않습니다. 그러나 그것은 처음 사용자 스토리를 적을 수 있는 용기를 갖게 해 줍니다. 에픽에는 커다란 시스템 이름을 적으면 됩니다. 에픽은 우선순위도 크기도 없습니다. 아직 자세한 사용자 스토리를 적을 수 없고 커다란 덩어리만 알고 있는 경우에 에픽을 적어 붙이면 됩니다. 그래서 스토리(이야기)가 아닌 에픽(서사시)입니다. 사용자 스토리는 대개 어떤 에픽에 속하는 경향을 보입니다. 하지만 에픽을 체계적으로 관리할 생각은 말고 세부 기능 목록을 사용자 스토리로 적을 수 있을 때가 오면 떼어버리는 것이 좋겠습니다.

고난이도: 사용자 스토리 만들기

인덱스 카드에 사용자 스토리를 적는 것은 쉽습니다. 그저 몇 줄 적으면 되죠. 어려운 것은 '잘 쓰는 것'입니다. 애초에 왜 사용자 스토리가 필요했는지 생각해보세요. 각자 자신의 이유가 있을 것입니다. 저는 위에서 적었던 대로 우선순위 결정을 위해 뭔가 인식의 전환이 필요했고, 그것이 의미있기 위해서는 '잘' 써야만 했습니다. 어떻게 하면 잘 쓸 수 있을까요?

우리는 사용자 스토리를 알기 전에도 작업에 들어가기 전에 명세 비슷한 무언가를 작성해 왔습니다. 문제는 그 둘의 차이가 무엇인가 하는 것입니다. 사용자 스토리의 기본적인 성격을 생각해봅시다.

  • 사용자 스토리는 사용자의 경험을 설명해야 합니다. 제 경험상 단어의 나열이나 단언보다는 ~할 수 있다, ~한다 등으로 끝나는 일반적인 문장 한 두 줄로 만드는 것이 적합했습니다.
    • 단어의 나열이나 단언) 금액 입력 시 소지 금액 검사
    • 일반적인 문장) 입력한 액수가 소지 금액을 초과하는 순간 소지 금액으로 변한다
  • 사용자 스토리는 고객이 읽고 우선순위를 정할 수 있어야 합니다. 개발자의 시각에서 작성한 스토리는 고객이 알아볼 수가 없습니다. 개발자에게만 의미 있는 스토리도 적어서는 안 됩니다.
    • 개발자 우선: Log.xml 파일 로더를 작성한다. 백엔드는 기존에 사용하던 xml 라이브러리를 활용한다.
    • 사용자 경험: Log.xml 파일을 읽어서 화면에 보여준다.
  • 사용자 스토리는 고객이 정한 우선순위에 따라 개발 순서가 달라져야 합니다. 따라서 각각의 스토리가 다른 스토리에 덜 의존할수록 좋습니다. 의존성이 아예 없을 수는 없지만 개발 상황이나 환경의 변화에 따라서 어느 시점에서든지 릴리스 할 수 있다고 생각해야 합니다. 의존성이 얼기설기 뒤엉켜 있다면 작업을 끊을 수가 없을 것입니다. 제가 위에서 설명한 바가 있습니다. "그런 우선순위가 무슨 의미가 있겠어요?"
위의 이야기가 다음에서 설명하는 '케이크 자르기'에 함축되어 있습니다.

케이크 자르기

마이크 콘은 그의 책 사용자 스토리에서 스토리를 자르는 기준을 케이크 자르는 것에 비유했습니다. 이 메타포로 설명하자면 케이크를 잘못 자르는 방법은 다음과 같습니다.

  • 바깥쪽 둘레의 크림만 잘라 먹는다
  • 초콜릿 장식만 떼어 먹는다
  • 윗단의 크림만 잘라 먹는다
  • 밑단의 스폰지 케이크만 먹는다
(아, 케이크 먹고 싶네) 그럼 이 메타포를 사용자 스토리에 대입하면 어떻게 될까요? 즉 사용자 스토리를 잘못 자르는 방법은 어떤걸까요? 그것은 이렇습니다.
  • 사용자 정보 DB를 만든다
  • 사용자 정보 입력 폼을 만든다
  • 사용자 정보를 저장한다
  • 프로토콜을 정의한다

어디서 많이 본 구조입니다. 우리는 흔히 이런 식으로 업무를 쪼갭니다. 이렇게 사용자 스토리를 나누면 뭐가 나쁠까요? 이런 사용자 스토리를 각각 구현해서는 아무런 기능도 동작하지 않습니다. 고객에게 동작하는 버전을 '언제나' 전달 할 수 없다는 의미입니다. 가장 큰 문제는 이런 상황에서는 우선순위를 정하는 것이 아무런 의미가 없다는 것입니다. 코 앞에 닥쳐온 출시일에 맞춰 우선순위가 낮은 스토리를 잘라내고자 할 때, 어디서 자를 수 있겠습니까?

케이크를 잘 자르는 방법은 케이크의 중심점에서 바깥으로 케이크의 모든 요소가 다 들어있게 자르는 것입니다. 그리고 스토리를 제대로 나누는 방법은 다음처럼 하는 것입니다.

  • 사용자의 기본 정보 3~5개를 입력하고 저장한다
  • 사용자의 선택적인 정보를 저장한다

큰 기능을 기본적인 동작과 부가적인 동작으로 나누는 것은 가장 초보적이고 기본적인 시도입니다. 필요하면 기능별로 조각조각 나누고 우선순위에 상관없이 고를 수 있게 하는 것이 좋습니다. 하나의 스토리는 하나의 조각 케이크라고 생각하세요.

그런데 케이크 메타포는 사실 좀 어렵습니다. 왜냐하면 케이크 조각은 너비, 높이, 깊이의 정보를 가진 삼차원 좌표계이기 때문입니다. 게다가 어떤 사람들은 정말 크림만 잘라먹고 싶어할지도 모릅니다. 특히 케이크 위에 올려진 생과일과 초콜릿은 따로 떼어먹기 좋게 유혹합니다. 따라서 저는 보다 단순한 이차원적인 좌표계를 가진 메타포로 피자를 추천합니다. 토핑만 떼어먹으면 나중에 얼마나 힘들어질까는 잘 아실 거예요.

스토리 크기

모든 일은 소요 시간이 다릅니다. 이 크기를 수치화해서 스토리 구석 어딘가에 적습니다. 이것이 스토리 크기가 됩니다. 수치의 단위가 얼마인가는 아무 상관이 없습니다. 단지 동일한 크기의 스토리는 서로 비슷한 시간이 걸리고 두 배 큰 스토리가 두 배 긴 시간을 소모하기만 하면 됩니다. 마이크 콘은 스토리 크기 1을 이상적인 작업시간 기준으로 하루로 하는 것이 어떤가 제안하고 있습니다. 이상적인 작업시간이란 회의도 없고, 전화도 걸려오지 않고, 보고 문서를 작성할 필요도 없는 말 그대로의 이상적인 환경에서 누구의 방해도 없이 근무시간 내내 일하는 것을 의미합니다.

사용자 스토리를 모르던 시절에 저는 일정 산출과 업무 보고를 위해 개인적으로 유닛이라는 단위를 만들어 사용했는데, 1 유닛은 하루를 3등분하고 각 유닛 사이에 적당한 휴식 시간을 포함해 각각 두시간 반씩을 할당한 업무 단위를 의미했습니다. 나름 퇴근 준비 시간으로 사용하기 위해 퇴근 전 30분이 비어 있었죠. 그 시간에 정말로 퇴근 준비를 한 적은 없었지만 말입니다.

지금은 스토리 크기 1을 일반적인 하루 근무에 해당하도록 작성하고 있습니다. 우리 환경에서 이상적인 근무를 할 수 있는 경우는 거의 없으며, 따라서 스토리 크기를 읽거나 측정할 때 이상적인 근무일을 일반적인 근무일로, 또는 일반적인 근무일을 이상적인 근무일로 변환하는 과정이 필요하기 때문이었습니다. 저는 지난 몇 달간 시계부를 작성하여 제 자신의 업무 패턴을 조사한바 있는데, 실험 결과 하루에 집중해서 일하는 시간은 3 ~ 5시간에 불과했습니다. (야근을 하는 경우는 5 ~ 6시간.) 이 시간은 주위에서 듣거나 직접 겪는 체감 수치와 일치합니다. 그래서 스토리의 크기를 추측할 때 이 정도의 시간을 기준으로 삼기로 했습니다.

일하지 않는 시간에는 무엇을 할까요? 대개 업무 준비, 업무 지원, 회의, 협업, 업무 상 토론, 휴식(집중력이 떨어져서 쉬는 것), 잡담(친목 도모), 딴짓(대개 컴파일 시간에 KLDP를 보다가 끝난지도 모르고 계속 보는 것. 인터넷 쇼핑을 하거나 공과금을 내러 은행에 가거나 주민등록등본을 떼는 것. 집에는 잠만 자러 들어가니 집에서 할 방도가 없지 않습니까?) 등이 있습니다. 혼자 일하지 않는 이상 이 일들을 전혀 하지 않을 수는 없습니다. 그러나 일정 예측이 틀리거나 긴급한 일이 벌어졌을 때 이 시간들을 줄일 수는 있을 것입니다. 회의를 안 할 수는 없어도 미룰 수는 있는 법이죠. TortoiseSVN 같은 건 다음날 설치해줘도 되지 않습니까? 이런 의미에서 스토리 크기 1을 일반적인 하루 근무 시간으로 잡는 것은 나쁘지 않다고 봅니다.

그런데 왜 마이크 콘은 이상적인 작업시간을 단위로 잡았을까요? 그런 문제를 생각하지 못해서였을까요? 그 이유는 다음 단락인 팀 속도에서 알 수 있습니다.

팀 속도

현대의 방법론과 고수들은 더 자주 릴리스하고 더 빨리 실패할 것을 권장합니다. 여기에 위키위키의 아버지인 워드 커닝엄이 말했다는 'Fail ealry and often'이라는 경구가 있습니다. 워드 커닝엄은 XP의 중요한 리더 중 한 사람이기도 합니다. XP를 포함해 최근에 인기를 얻고 있는 기민한 방법론들에서 공통적으로 주장하는 것은 짧은 주기의 릴리스입니다. XP에서는 이런 작은 개발 주기를 이터레이션(iteration)이라고 부릅니다. 개발팀은 한 주나 두 주, 길어도 네 주를 넘지 않는 정해진 크기의 이터레이션 동안 개발을 진행하고 릴리스를 배포합니다. 이는 우리가 흔히 하는 것과는 반대라고 볼 수 있습니다. 꼭 필요한 기능이 들어갈 때까지 릴리스를 기다리는 것이 아니라 릴리스 시점이 먼저 정해지고 그 시간을 스토리로 채웁니다. 이렇게 해보면 왜 케이크 자르기(피자 자르기)가 중요하고 우선순위가 중요한지, 스토리를 작게 만드는 것이 왜 중요한지 알게 됩니다.

한 번의 이터레이션이 끝나면 그 기간 동안 완성된 스토리의 크기를 다 더해봅니다. 그 숫자가 팀의 속도가 됩니다. 다음 이터레이션에는 몇 개의 스토리를 완성할 수 있을까요? 항상 같은 속도를 낼 수는 없지만 팀의 경험이 쌓여갈 수록 예측은 정확해질 것입니다. 예측이 빗나가서 이번 이터레이션에는 팀의 속도가 상당히 떨어질 것이라고 생각해 봅시다. 팀에는 어떤 변화가 생길까요? 릴리스가 미뤄질까요? 그렇지 않습니다. 왜? 우리는 고객이 정한 우선순위에 따라 어떤 스토리를 배제해야 하는지 알고 있기 때문입니다. 팀의 속도가 빨라졌다면요? 그럼 스토리를 하나 더 시작해 보죠.

저도 책을 읽으면서 그랬지만, 이런 의문이 들 수 있습니다. 우리 팀은 일반적인 하루 근무를 기준으로 스토리의 크기를 매깁니다. 반면에 옆 팀은 이상적인 작업시간을 기준으로 스토리의 크기를 매깁니다. 일반적으로 사용자 스토리의 크기는 우리 팀이 더 크고, 같은 기간동안 우리는 더 많은 점수를 땁니다. 그럼 우리 팀은 옆 팀보다 두 배 빠를까요? 그렇지 않습니다. 팀 속도의 비교는 같은 팀에서의 상대적인 비교만 의미가 있습니다. 따라서 팀이 스토리의 크기를 어떤 기준을 사용하든 상관없는 것입니다. 마이크 콘이 이상적인 작업시간을 사용한다고 해서 이상주의자라고 비난할 수는 없는 일이지요!

마치며

이전 글에서도 쓴 바가 있지만 저는 '일이 어떻게 시작되고 결국 정착되는가'에 관심이 많습니다. 성공한 실험은 결과만 남지 과정은 남지 않는 경우가 많거든요.적어도 시스템 도입에서는 결과만 가지고는 배우기가 힘이 듭니다. (그 수많은 부자되기 류나 영어완전정복 류의 책들을 떠올려 보세요. 부자가 된 사람은 그 책의 저자뿐입니다.) 경험상 새로운 시도는 용두사미가 되는 경향이 많음에도 불구하고 아직 검증 되지 않은 이야기를 위험을 무릅쓰고 늘어놓고 있습니다. 양해 바랍니다. 어느 날 결국 실험 실패 글을 올리고 잠적할지도 모릅니다. :]

특히 이번 글은 제 예상보다 더 길어진 데다 재미도 없어서 부득이 이런 단락을 마련했습니다. ^^; 저의 사용자 스토리 실험은 그 뒤로 인상적인 변화가 있어서 새로운 전기를 맞고 있습니다. 아직 공개할 단계는 아닌데, 다음 번에는 긍정적인 실험 결과를 소개할 수 있다면 좋겠군요.

신고
Trackback 2 Comment 26

기획에서 기능 명세 얻기

아래에서 제가 설명하고자 하는 내용은 현업에서 폭넓게 다양한 사람들에게 적용해본 결과는 아닙니다. 몇 가지 개인적인 실험의 일환으로 시도해 보았고, 나름대로 성과를 얻었기에 공유하고자 합니다. 글을 쓰다가 흥이 올라서 과장을 하거나 막 나가는 경우가 있었는지도 모릅니다. 양해를 구하겠습니다. 어쩌면 흐름이 일정치 않은 부분도 있을 것이고요. 그건 최근 따로 여유 시간이 없는 관계로 며칠에 걸쳐서 조금씩 적어서 그렇습니다. 본문에서 사용하는 예는 모두 순전히 가상입니다. (오해하실까봐)

용어의 혼란

여러분에게는 이런 경험이 있었을 것입니다. 

"캐릭터가 특정 존에 들어왔을 때 캐릭터에게 특정한 효과가 부여되게 하고 싶은데요,"

"잠깐만요, '존'이라는 게 정확히 뭔가요?"

"'존'이 뭐냐고요? 캐릭터가 돌아다니는 게임 공간을 말하는 거죠."

"아, 제가 필드라고 부르는것 말이군요."

"그래요? 필드라고요? 그래픽팀이나 우리도 다 '존'이라고 부르는데 용어를 좀 통일하면 안 될까요?"

"안돼요, 소스코드에 이미 그렇게 썼어요."

"?_?"

이런 일도 있었겠죠?

"사용자가 여기를 지나다가 함정에 빠지면 대미지를 입고요, 여기서는 무조건 죽어요. 그러면 죽음 페널티를 받게 되는데, 레벨 차이가 얼마나 나는 캐릭터가 살려주느냐에 따라 부활 페널티의 효과가 높아지거나 낮아지거나 하는거죠."

"잠깐만요. 아까 전에 말한 '죽음 페널티'는 '부활 페널티'와 다른건가요?"

"뭐가요?"

"아까는 '죽음 페널티', 좀전엔 '부활..'"

"아아, 그건 그냥 그렇게 부른거예요."

"그럼 그 '뭔가' 페널티는 죽을 때 적용되나요 부활할 때 적용되나요?

"?~?"

아마 이 비슷한 예는 셀 수도 없이 많을 겁니다. 어떤 때는 몇 시간동안 서로의 용어를 질문하고 고쳐주느라고 정신이 없기도 하죠. 그렇다고 어디 나와 너의 용어만 다르던가요? 같은 내용을 지칭하는 용어가 내가 말하는 중에도 조금씩 바뀌거나 하죠. 설령 그게 죽음 페널티이든 사망 페널티이든 뭐 그렇게 중요하겠어요? (하지만 부활 페널티는 뉘앙스가 정말 다릅니다.) 그래서 책을 읽거나 다른 선배님들의 경험을 들으면 그렇게들 프로젝트의 용어 사전을 만들어야 한다고 하는가봐요. 그건 어떻게 만들까요? 조금 있다가 알아보죠.

내용의 중복

좀 다른 이야기. 이런 저런 이유로 열심히 문서를 작성하다보면 간혹 문제에 봉착할 때가 있습니다. 내용들이 서로 관련이 있을 때죠. A를 설명하는 중에 B의 일부와 밀접한 관련이 발생했습니다. B-a를 빼놓고는 A-b를 설명할 수가 없어요. 어떻게 해야 할까요? 좀 불친절하게도 B-a를 설명하는 문서를 참조하시라고 적을 수도 있겠죠. 어쨌든 모든 내용은 제 머릿속에 있는데, B-a가 정말은 어느 문서에 있는지 알 수가 없네요. 제일 쉬운 방법은 제가 알고 이해하고 있는 내용을 A-b 근처에 다시 적는 겁니다. 사실 아직 어느 문서에도 없을 수도 있잖아요. 저라면 그렇게 하겠어요. 두 번 쓰는게 뭐 그리 대수인가요?

그런데... 문제는 하나의 사실을 표현하는 말이 역시 하나인 것은 아니라는 겁니다. 왜 비슷한 내용이 여기 저기에 있죠? 고쳐야 할 일이 있을 때는 어떻게 할까요? 그 내용이 대체 어디어디에 있는거에요?

사실 기획은 문서에 있는 것이 아닙니다. 그건 기획자의 머릿속에 있죠. (어쩌면 기획자들의 '사이에' 있는 경우도 있어요.) 그러니까 기획서의 오류도 뭐 그리 대단한 것은 아니에요. 기획자에게 물어보면 언제나 정답을 알 수 있습니다. 그리고 기획서를 갱신해주겠다는 대답도 하죠. 기획서는 소통의 도구일 뿐입니다. 이 사람과 저 사람의 소통을 위한 도구이기도 하고, 한 사람의 과거와 현재를 이어주기도 하고요. 기획서가 아예 없다고 하더라도 기획만 잘 전달이 된다면 괜찮습니다. 어차피 잘 쓰여진 기획서라도 그것만 갖고는 모든걸 이해할 수는 없어요. (작가의 의도는 무엇인가 - 한 두 번 들어보셨어요?) 정말 문제는 내가 기획을 제대로 이해하고 있는가 아닌가입니다.

자, 이제 기획자에게 꼬치꼬치 캐물어 기획에 대한 모든 걸 다 들었다고 칩시다. 그럼 그건 이제 어디에 있나요? 제 머릿속에요? 농담마세요, 저는 들은지 5분이면 까맣게 다 잊는다고요!

명세서를 쓰자

가끔 우리는 한참 설명을 듣다가 이렇게 말하는 때가 있습니다. "제가 다시 설명을 해 볼테니 제대로 이해했는지 들어주세요." 마치 '제가 전화번호를 제대로 들었는지 다시 불러볼게요' 같죠. 이건 꽤 유용한 행동입니다. 다른 사람에게 말로 설명할 때 자신이 제대로 이해하고 있는지 아닌지를 알 수 있게 되는 경험, 여러번 해보셨을 거예요. 기록이 남지 않는다는게 단점이긴 하죠. 글로 적어보는 것은 어떻습니까? 남의 글을 별로 읽을 기회가 없는 기획자에게 거꾸로 문서를 주어보자구요.

글을 쓰는데 제가 추천하는 도구는 위키위키입니다. 몇 가지 장점이 있습니다. 적는 법을 알려드리죠. 대신 전제가 있습니다. 여러분은 기획자와 방금 기획서 리뷰를 끝내고 돌아와 아직 모든걸 다 잊기 전이어야 합니다. 그러니까, 제 경우는 5분이 지나기 전이죠.

새로운 페이지의 이름을 정해야 합니다. 뭐가 좋을까요? 기획서 이름으로 해도 좋고, 일반적으로 통용될 수 있는 이름이라면 다 좋습니다. 기존에 정해둔 이름이 있다면 그걸로 해도 좋습니다. 저는 '캐릭터의 죽음과 부활'이라는 문서를 받았는데, 제가 선택한 페이지 이름은 '플레이어의 죽음'이었습니다. 공교롭게도 지난번에 거기까지만 정의를 해놓고 페이지 만들기를 끝낸 적이 있었거든요. 뭐든 앞으로 '그 내용'을 지칭할 땐 '그 이름'을 써야 한다는 것만 지키면 됩니다. 이유는 곧 알게 되실 겁니다.

다음은, 그 페이지에 기획서의 내용 전체를 털어넣겠다고 덤벼듭니다. 안 들어갈 것 같죠? 맞습니다. 다 넣을 필요도 없고요. 군더더기는 다 뺍니다. 빼야할 것들의 목록은 다음과 같습니다. 그림, 그래프, 순서도, 도표, 표들은 뺍니다. 설명을 위한 설명, 접속사, '~습니다', '~할 것입니다', '다음 기획서 A32067zQ에서 보강합니다...', 뺍니다. 기획 의도, 동기들도 빼야할 주요 요소 중 하나입니다. 그런 것들은 기획자와의 리뷰에서 벌써 해결했어야 합니다. 여기까지 들고 오진 마세요. 이제와서 기획 의도를 의심해서 어쩌겠어요?

진짜 알맹이들은 구조화 해서 모아야 합니다. 단락이나 들여쓰기, 총알 목록 등을 이용해서 관련 있는 것끼리 모읍시다.

문제가 생겼어요!

정리를 하다보니 앞에 나왔던 유사한 내용이 다시 등장했습니다. 어쩌죠?

앞에 나온 내용으로 다시 돌아가서 둘을 비교해 보세요. 완전히 같거나 혹은 완전히 같아야 할 내용인가요? 좋아요, 그러면 잘라냅니다. 새로운 페이지를 만들어서 거기에 넣고 두 군데에 그 이름으로 링크를 겁니다. 왠지 익숙한 행동이네요... ReFactoring에서 ExtractMethod라고 부르는 그것이죠. 위키위키에서는 이런걸 ExtractPage라고 합니다. 이제 앞으로 이 새로운 페이지가 여러 곳에서 불려진다면 좋겠네요. 그래야 잘 분리한 거겠죠? 중요한 건 페이지의 이름이 '바로 그 내용'을 잘 반영하는 좋은 이름이어야 한다는 겁니다. 앞으로 그런 내용을 이야기할 때는 내용을 일일이 말하거나 아무래도 좋은 이름을 사용하는 대신, 정확하게 바로 그 페이지 이름을 사용하세요. 기껏 열심히 생각해서 만들었는데 아깝잖아요.

이제 다 됐나요? 혹시 명세서가 너무 길진 않나요? 위키위키에서 긴 글을 편집할 수도 있지만, 위키위키로 정리한 명세서는 통상 그리 길어지지 않습니다. 저는 15페이지짜리 기획서를 정리하는데 스무줄 정도면 됐어요.

페이지를 뚫어져라 노려봅시다. 비슷한 성격의 기능 명세는 서로 모여있을 것입니다. 유사한 명세의 묶음과 다른 성격의 묶음들이 눈에 들어오나요? 따로 분리할 수 있을 것 같은 기분이 들진 않나요? 이름을 하나 붙여준다면 그 묶음을 따로 떼어 부르기 쉬울 것 같은데요. '어쩌구저쩌구.doc'의 '4.2.1 뭐뭐의 기능과 효과'라고 부르는 대신 말이에요.

저는 '죽었을 때는 이것과 저것과 요것, 조것, A, B, C, D는 할 수 없다. E는 할 수 있다. F는 받을 수만 있다'를 모아놓은 총알 목록이 눈에 띄이길래 ExtractPage를 하고, [사망 상태]라고 이름을 붙여주었습니다. 원래 페이지에는

  • [사망 상태]가 된다

라고 적었습니다. 그리고 이런 내용들도 있더라고요. 'A가 Aa만큼 감소한다. B가 Ba만큼 감소한다. C는...'. [죽음 페널티]로 묶었습니다. '마을에서 부활하거나, 그 자리에서 부활하거나, 다른 사람이..' 라는 기능 묶음은 [부활]이라고 이름을 붙였습니다. 그랬더니,

  • [사망 상태]가 된다
  • [죽음 페널티]가 주어진다
  • [부활]을 기다린다

죽었을 때 일어나는 일은 사실 몇 가지 되지 않네요. 이제 명세서가 한 화면 이내로 줄었나요? 수고하셨습니다. 이제 명세서의 주소를 기획자에게 주고 검토해 달라고 하세요. 구현은 기획서를 보고 하는게 아니라 명세서를 기준으로 할 거고, 그러므로 기획서와 명세서가 같은지 검토할 필요가 있다고 하세요. 즉, '제가 제대로 이해했는지 적어봤어요, 읽어주세요'와 같습니다.

기획자가 명세서를 읽는 동안, 우리도 지금까지 우리가 무엇을 했는지 검토해 봅시다.

  • 용어를 정립했습니다: 우리는 어떤 기능 목록마다 알맞는 이름을 정해주었습니다. 이제는 [죽음 페널티] 대신 [사망 페널티], [부활 페널티]라고 부를 방법이 없습니다. 그런 페이지는 아예 있지도 않으니까요.
  • 중복되는 내용들을 제거했습니다: 이제 더 이상 여기서 조금 다르고 저기서 조금 다른 내용은 없습니다. 딱 하나뿐이니까요!
  • 기획을 잘 이해했습니다: 어떤 내용을 다른 사람에게 설명하는 것은 자신이 오히려 더 잘 이해할 수 있는 방법입니다. 기획자의 설명을 듣고 기획서를 읽는 동안 괜찮다고 생각했던 내용에 오류가 있었다는 것도 발견했을 겁니다. 기획서의 오류를 고치는 공짜 기능도 있었네요!
  • 비슷한 기능 명세를 서로 모아놓았습니다
  • 꼭 필요한 내용만 남기고 분량이 줄어서 전체 흐름을 더 잘 이해할 수 있게 되었습니다
  • 어떤 기능이 영향을 미치는 다른 시스템과 기능들을 찾아냈습니다: 페이지 제목을 눌러서 역링크를 찾아보세요. [이동 속도]를 고치면 어떤 기능들이 영향을 받나요?

이렇게 정리된 명세서를 가지고 구현에 들어갈 수 있는데요, 사실 다른 것도 할 수 있습니다. 다음 번엔 사용자 스토리를 도출하는 방법을 알아보죠.

신고
Trackback 0 Comment 4

사용자 스토리

제가 어떻게 사용자 스토리를 시작할 마음을 먹게 되었을까요? 여러분은 어떻게 시작하게 되었나요?

우리가 어떤 일을 시작하려는 마음을 먹고 나면 먼저 주변에서 이미 그 일을 해낸 사람들을 보게 됩니다. 어떤 일이냐에 따라 다르지만 대개 시작하는 사람들보다는 하고 있는 사람들이 많고 그보다는 해낸 사람들이 많습니다. 이들 사이에는 어떤 차이가 있을까요? 그들이 그 일을 시작하게 된 데에는 어떤 동기와 용기, 그리고 어떤 행위유발성이 있었을까요?

저는 가끔 무언가에 도달한 사람들이 '나도 예전엔 그랬었지'라고 하는 것을 듣습니다. 그리고 그런 말은 별로 의미가 없다고 생각해요. 아직 시작하지 못하고 있는 사람들이 시작하게 되는 사이에는 비선형적인 단계가 있고 거기를 넘어가는 데에는 계기가 필요합니다. 그 사람들에게는 '예전엔 그랬었지, 지금은 요래' 보다 바로 '그 과정'이 중요합니다. 중요한 것은, TDD(또는 금연)를 어떻게 시작할 마음을 먹게 되셨어요? 기존의 습관을 어떻게 고치셨어요? 어느 순간 갑자기 깨닫는 어떤 계기가 있었어요? 이런 질문들이죠.

사용자 삽입 이미지

< 당신에게 무슨 일이 생겼나요? >

우리가 관심있는 것은 빨간 원 안에서 일어났던 일입니다. 제가 늘 관심을 두고 있는 것도 그렇습니다. 다른 블로그에서 Winter Bell 게임을 숙달해 가는 과정에 대해 쓴 글들(1, 2, 3)도 그런 형태의 과정에 대한 관심이라고 볼 수 있습니다.

저는 XP에 꾸준히 관심을 갖고 있었지만, 마음이 맞는 팀을 우연히 통째로 - 그러니까 공짜로.. - 만나기 전에는 실제 업무에 도입할 수 없을 거라 생각했습니다. 그러다가 TDDBE(위키페이지)를 읽고나서 이건 혼자서도 할 수 있는 일이구나 싶었습니다. 몇 가지 다른 언어로 맛을 보고, 실제 업무에도 제한적으로 도입해 보았습니다. (이 얘기는 따로 할 기회가 있을 것입니다.) 그리고 마이크 콘의 사용자 스토리(위키페이지)를 읽었습니다. 'XP의' 사용자 스토리로 접했을 때에 비해 훨씬 많은 이해와 통찰을 얻었고, XP의 각 요소들을 개별적으로도 도입할 수 있겠구나 하는 용기를 얻었습니다. 그래서 다시 한 번 혼자서 사용자 스토리를 사용해보기 시작했습니다. 본격적인 반복을 한지는 몇 주 되지 않았는데, 작지만 의미있는 진전이 보이고 있습니다.

사진을 몇 장 찍어보았습니다. 개인적인 실험이기 때문에 제 자리의 파티션에 붙여두고 있습니다. 아래는 에픽과 스토리를 구분해서 붙여놓은 것입니다. 사진 상단의 많은 쪽이 에픽이고 적은 쪽은 스토리입니다. 에픽이 스토리만큼 중요한 것은 아니지만, 다른 사람들의 주목을 받는데에는 큰 역할을 하고 있습니다. :) 에픽을 잔뜩 붙이기 전과 지금은 관심도가 달라요. 눈에 보이는 것이 생각보다 더 중요하다는 것을 깨달은 시점이었습니다.

스토리 오른쪽 상단에는 두 개로 나눈 칸을 그려서 왼쪽엔 시작하기 전에 측정한 스토리의 크기를, 오른쪽엔 스토리가 끝났을 때 측정한 크기를 적습니다. 스토리를 설명하는 길이는 한 문장에서 두 문장 정도로 간략하게 합니다.

사용자 삽입 이미지

에픽과 스토리

스토리가 완성되면 오른쪽 책꽂이 위에 한동안 붙여놓습니다. 보통 반복이 끝날 때까지는 계속 둡니다.

사용자 삽입 이미지

(팀)속도

반복이 끝나면 완성된 스토리를 옆에 아무렇게나 시위하듯이 붙여놓습니다. 사실은 치워야 되는데 귀찮아서 그러지 못하고 있네요. 예전 스토리와 지금의 스토리를 비교하면서 읽어보면 점점 스토리를 만드는 요령이 생기는 것을 느낍니다. 아직 떠들 정도는 아니지만, 앞으로는 여기에 대한 이야기를 차차 적어보겠습니다.

사용자 삽입 이미지

신고
Trackback 1 Comment 9

prev 1 2 next


티스토리 툴바