티스토리 툴바


Tron 게임

etc 2012/02/17 07:26


초등학교 때였던가?  이게 영화가 있는 것도 모르고, 게임에 빠져들었던 적이 있었는데, PC에서 실행할 수 있는 프로그램이 있어서 올려봅니다.


기억이 참 새롭네요 ^^*
저작자 표시 비영리 변경 금지

'etc' 카테고리의 다른 글

Tron 게임  (0) 2012/02/17
퍼포먼스를 위한 발악  (2) 2012/02/11
LED Display  (0) 2012/01/18
SoundTouch 버그 수정  (0) 2012/01/18
아들 넘의 첫 번 째 게임 - 홀짝 맞추기  (0) 2012/01/17
비리 의혹에 대한 처리 결과  (0) 2011/12/26
Posted by 류종택
오래 전부터 습관이 된 탓에 and 조건을 분별할 때에는 항상 확률이 낮은 것부터 나열하도록 신경을 쓰고 있었습니다.  그러다가, 요즘 PC에서 그런 것이 과연 얼마나 퍼포먼스 향상에 도움이 될 까 궁굼해 졌습니다.  바로 테스트에 들어 갔습니다.

[소스 1]
procedure TForm1.Button1Click(Sender: TObject);
var
  Tick : Cardinal;
  Loop, a, b : integer;
begin
  Tick := GetTickCount;

  for Loop := 1 to 100000000 do begin
      a := Random(2);
      b := Random(100);
//      if (a = 1) and (b = 1) then Tag := Tag + 1;
      if (b = 1) and (a = 1) then Tag := Tag + 1;
  end;

  Caption := IntToStr(GetTickCount - Tick);
end;
11: 라인과 12: 라인이 오늘의 주인공입니다.  결과적으로 똑같은 두 문장의 속도 차이는 아래와 같습니다.
  • 11: 라인 평균 1200 ms 정도
  • 12: 라인 평균 730 ms 정도
and 문장에서는 앞에서 false가 판별되었을 경우 다음 조건을 검사하지 않기 때문에 확률이 낮은 것을 먼저 분별하면 성능에 도움이 됩니다.  or 에서는 반대로 확률이 높은 것부터 나열하는 것이 조금이나마 이득이 됩니다.

근래에는 PC의 성능이 워낙에 좋아졌기 때문에 일반적인 경우 퍼포먼스에 대한 고민을 많이 할 필요가 없었졌습니다.  하지만, 스마트폰, 게임 및 증권 시스템 트레이딩과 같이 반복 계산이 많은 프로젝트 등에서는 이런 작은 차이들이 엄청난 결과를 만들어 내기도 합니다.

그렇긴 해도 반복 횟수를 감안하면 상당한 뻘짓이네요 ^^; 
저작자 표시 비영리 변경 금지

'etc' 카테고리의 다른 글

Tron 게임  (0) 2012/02/17
퍼포먼스를 위한 발악  (2) 2012/02/11
LED Display  (0) 2012/01/18
SoundTouch 버그 수정  (0) 2012/01/18
아들 넘의 첫 번 째 게임 - 홀짝 맞추기  (0) 2012/01/17
비리 의혹에 대한 처리 결과  (0) 2011/12/26
Posted by 류종택

LED Display

etc 2012/01/18 21:49
http://codejob.co.kr/code/view/57/ 에 제시된 문제를 풀어 본 것 입니다.

[소스 1]
program Sample;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  TextCanvas in 'TextCanvas.pas',
  DigitFont in 'DigitFont.pas';

var
  DigitFont : TDigitFont;

begin
  DigitFont := TDigitFont.Create;
  try
    DigitFont.FontSize := 1;
    DigitFont.WriteDigit('01234');
    WriteLn;

    DigitFont.FontSize := 2;
    DigitFont.WriteDigit('56789');
  finally
    DigitFont.Free;
  end;

  Write('Press any key...');
  ReadLn;
end.
문제대로 파일을 읽고 등등은 생략 ^^;
문제의 핵심을 폰트 크기와 숫자를 LED 디스플레이로 표시하는 것으로 압축하고, 거기에 해당하는 인터페이스를 가진 클래스 제작하였습니다.  그리고, 실행 결과는 [그림 1]과 같습니다.

[그림 1] 실행 결과 

[소스 2] TDigitFont 클래스의 중요 부분
procedure TDigitFont.WriteDigit(Digit:string);
const
  _FontWidth  = 3;
  _FontHeight = 5;
var
  sFontData : string;
  Loop: Integer;
begin
  FCanvas.Width  := Length(Digit) * (FontSize + 1) * _FontWidth;
  FCanvas.Height := FontSize * _FontHeight;
  FCanvas.Clear;

  for Loop := 0 to Length(Digit)-1 do begin
    // 현재 폰트를 찍을 위치로
    FCanvas.MoveTo(Loop * (FontSize + 1) * _FontWidth, 0);

    // 현재 폰트의 벡터 정보 가져오기
    sFontData := _DigitFontData[Ord(Digit[Loop+1]) - Ord('0')];
    draw_Digit(sFontData);
  end;

  FCanvas.Draw;
end;

procedure TDigitFont.draw_Digit(FontData: string);
var
  Loop : Integer;
begin
  for Loop := 1 to Length(FontData) do begin
    case FontData[Loop] of
      'l': FCanvas.MoveLeft;
      'r': FCanvas.MoveRight;
      'd': FCanvas.MoveDown;
      'u': FCanvas.MoveUp;

      '<': FCanvas.MoveLeft(FontSize);
      '>': FCanvas.MoveRight(FontSize);
      '.': FCanvas.MoveDown(FontSize);
      '^': FCanvas.MoveUp(FontSize);

      'L': FCanvas.LineLeft(FontSize);
      'R': FCanvas.LineRight(FontSize);
      'D': FCanvas.LineDown(FontSize);
      'U': FCanvas.LineUp(FontSize);
    end;
  end;
end;

[소스 3] 벡터 정보
type
const
  _DigitFontData : array [0..9] of string = (
    'dDdDrRuUuUlL',      // 0
    'rrdDdD',            // 1
    'rRdDlLdDrR',        // 2
    'rRdDdDlL^urR',      // 3
    'dDrR^DdD',          // 4
    'rR<ldDrRdDlL',      // 5
    'rLdDrRdDlLuU',      // 6
    'rRdDdD',            // 7
    'rRdDlLdDrRuUl<uU',  // 8
    'd.rLuUrRdDdDlL'     // 9
  );

lrdu : 한 칸 이동 (각각 Left, Right, Down, Up)

<>,^ : 폰트 크기 만큼 이동 (각각 Left, Right, Down, Up)

LRDU : 폰트 크기 만큼 직선 그리기 (각각 Left, Right, Down, Up)


[소스 4]  위에서 사용되는 TTextCanvas 클래스의 인터페이스 (FCanvas) 
type
  TTextCanvas = class
  private
  public
    procedure Clear;

    procedure MoveTo(X,Y:integer);

    procedure MoveLeft(Count:integer = 1);
    procedure MoveRight(Count:integer = 1);
    procedure MoveDown(Count:integer = 1);
    procedure MoveUp(Count:integer = 1);

    procedure LineLeft(Count:integer = 1);
    procedure LineRight(Count:integer = 1);
    procedure LineDown(Count:integer = 1);
    procedure LineUp(Count:integer = 1);

    procedure Draw;

    property X : integer;
    property Y : integer;
    property Width : integer;
    property Height : integer;
  end;

그리고 아래는 전체 소스


저작자 표시 비영리 변경 금지

'etc' 카테고리의 다른 글

Tron 게임  (0) 2012/02/17
퍼포먼스를 위한 발악  (2) 2012/02/11
LED Display  (0) 2012/01/18
SoundTouch 버그 수정  (0) 2012/01/18
아들 넘의 첫 번 째 게임 - 홀짝 맞추기  (0) 2012/01/17
비리 의혹에 대한 처리 결과  (0) 2011/12/26
Posted by 류종택

SoundTouch 버그 수정

etc 2012/01/18 06:47
VoiceZip(http://ryulib.tistory.com/178)에 사용된 오픈 소스 중에 SoundTouch의 버그 수정 내용과 파일을 아래와 같이 첨부합니다.  (SoundTouch는 음성의 속도, 피치 등을 조절 할 수 있는 오픈 소스 라이브러리 입니다)


출처:  http://www.surina.net/soundtouch/ 

* SoundTouchDLL.h 버그 수정
SOUNDTOUCHDLL_API void soundtouch_putSamples(HANDLE h, 
        const SAMPLETYPE *samples,       ///< Pointer to sample buffer.
        unsigned int numSamples     ///< Number of samples in buffer. Notice
                                    ///< that in case of stereo-sound a single sample
                                    ///< contains data for both channels.
        );


* 버그는 아니고, 16비트 샘플을 위해서 수정 한 부분, STTypes.h
// 16비트 샘플을 사용한다.
#define SOUNDTOUCH_INTEGER_SAMPLES 1

저작자 표시 비영리 변경 금지

'etc' 카테고리의 다른 글

퍼포먼스를 위한 발악  (2) 2012/02/11
LED Display  (0) 2012/01/18
SoundTouch 버그 수정  (0) 2012/01/18
아들 넘의 첫 번 째 게임 - 홀짝 맞추기  (0) 2012/01/17
비리 의혹에 대한 처리 결과  (0) 2011/12/26
유치원생을 위한 프로그래밍 세 번 째 날  (0) 2011/12/26
Posted by 류종택


   1 : program Step_10;

   2 :

   3 : {$APPTYPE CONSOLE}

   4 :

   5 : {$R *.res}

   6 :

   7 : uses

   8 :   System.SysUtils,

   9 :   BaseTools in '..\..\Lib\BaseTools.pas';

  10 :

  11 : var

  12 :   c : integer;

  13 :   u : integer;

  14 :

  15 : begin

  16 :   Randomize;

  17 :

  18 :   repeat

  19 :     c := Random(2);

  20 :

  21 :     write('0 또는 1 맞추세요: ');

  22 :     readln(u);

  23 :

  24 :     if c = u then writeln('맞았습니다.');

  25 :     if c <> u then writeln('틀렸습니다.');

  26 :

  27 :     writeln('컴퓨터: ', c, 사람: ', u);

  28 :     writeln;

  29 :   until false;

  30 : end.

 

유치원생에게 프로그래밍을 가르치기 위해서 꽤 고민을 해서 교재를 만들고 있습니다.

BaseTools는 입문 교육에 기본적으로 필요한 라이브러리를 몰아 넣으려고 일단 만들어 둔 것 입니다.


"최소한의 지식으로 최대한의 결과를 만들어 낸다"라는 원칙으로 이 간단한 게임을 만들기 위해서,

얼마나 힘이 겨웠는지 ㅠ.ㅠ

(if then else도 안가르치고, if문 만으로 해결 중)


이제 어느 정도 감을 잡은거 같고, 초기보다 더욱 흥미를 가진 거 같아서,

당분간은 쉽게 갈 듯.


줄 맞추기는 수업 끝나고 제가 해준 겁니다.



저작자 표시 비영리 변경 금지
Posted by 류종택
비리 의혹을 제기하는 원문 :  http://ryulib.tistory.com/165 

결과적으로 의혹으로 끝났습니다.  관심 주신 분들에게 죄송합니다.  하지만, 참으로 아쉽네요.  답변의 내용을 보면서 개인적으로 정리하자면 다음과 같습니다.  (원문을 공개해도 되는 지 몰라서)


서울시 감사는 비리 의혹을 제시한 담당자와 해당 공사에서만 조사를 마친 듯 합니다.  

연관된 다른 청과 회사나 인원들에 대한 조사는 전혀 없었던 듯 합니다.  전화로 확인하였으나, 제가 거기에 있는 분들을 다 아는 것도 아니라서 추측으로만 적습니다.  결국 의혹을 가진 담당자의 이야기를 요약하여 조사를 마친 것이 되겠지요.


개발 가이드라인이 통보되었다.
"카메라 두 대로 경매용 PC와 경매 참가자들을 녹화한다"  수준의 가이드라인을 전문적인 프로젝트 가이드 라인이라고 봐야 하는지 참으로 답답합니다.  최소한이라고 생각할 수 있는, 해상도 및 프레임 수 등의 스팩도 빠져 있었고, 음성 녹음에 대한 요구사항도 한 참 후에 발생한 문제였습니다.  프로젝트 진행의 부실에 대한 조사가 있었기나 한 것인지 의심스럽습니다.  프로젝트를 시작 할 만한 요구사항 명세서라던가, RFP와 같은 문서는 어디에도 없었습니다.
 
 
업체 대표가 작성해 준 문건을 공문으로 발생했다라는 의혹
아래가 원문 중에 내용입니다.
"특정 업체 대표의 글을 그대로 공문으로 발생한 것이 아니고 검증 결과에 나온 얘기를 정리하여 보완 지시하였고, 마지막 보완지시 공문내용은 상당부분 S청과 전산담당자가 실토한 내용을 정리하여 통보한 사항임" 
일단 감사팀은 S청과와는 아무런 접촉이 없었음을 확인하였습니다.  담당자도 "몰 실토했다는 거죠?"라는 군요.  그리고, 청문회가 있을 때 제가 직접 "이 공문은 저 업체 대표님이 작성해 준거라면서요?"라고 직접 물었던 적이 있었습니다.  분위기가 썰렁해졌고 반박을 하지 못하더군요, 하지만 아쉽게도 답변을 회피 할 뿐 정확한 답변을 듣지 못했었습니다.  단순히 심증만 가는 상황이 되어 버린 것 입니다.  그리고, 해당 공문 내용은 일반인이 쓸 수 있는 내용이 아닌 전문적인 내용입니다.  더구나 한 쪽 이야기만 듣고 작성한 글이고, 이에 대한 반발로 인해서 겨우 청문회를 가졌던 것이고요.  정말 아쉬운 것은 업체 대표가 작성한 글을 공문으로 발송했다라는 말은 이 사건의 핵심 관련자인 S청과 직원들 뿐이라고 하는 군요.
 

결국 "A가 B를 때렸어요!"라고 신고했는데, A에게 너 저 녀석 때렸어? 라고 묻고 나서, "A는 B를 안때렸다"라고 결론을 받은 것과 같은 기분입니다.

서울시의 감사 활동에 조금은 기대를 했었는데, 의혹을 풀려는 의지가 있었던 것인 지 상당히 궁굼합니다.  같은 결과가 나왔더라도, 관련자 모두를 조사하고 프로젝트 과정의 문제점을 전문가와 함께 연구하려는 시도조차 없었던 것으로 보입니다.

참고로, 이미 저는 저에게 주어진 요구사항을 마무리하고 나온지 몇 개월이 지났고, 개발비도 받았고, 이런 의혹을 제기해서 얻어지는 이익은 전혀 없습니다.
저작자 표시 비영리 변경 금지
Posted by 류종택
도영군이 오전에 일어나자 마자 프로그래밍 공부 하자고 졸라서 세 번 째 수업을 마쳤습니다.  오늘은 반복문입니다. 

일단 이미 배웠던 '별표를 그대로 출력해라!" 써라 대신 출력이라는 말로 바꿔서 연습시키고 있습니다.

program Step_03;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  BaseTools in '..\..\Lib\BaseTools.pas';

begin
  write('*');
end.

이미 배운 것이라서 쉽게 따라하더군요.  "이제 반복문을 알려주기 위해서 별표를 반복해서 출력하려면 어떻게 해야 할 까?"라고 물으니  도영군이 바로 아래와 같이 하더군요.

program Step_03;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  BaseTools in '..\..\Lib\BaseTools.pas';

begin
  write('**************************************************************');
end.

켁!  아빠가 졌다.  그래도 일단 진도는 나가기로 했습니다.  "백 만 개를 그려 볼래?"   도영군이 웃더군요.  그제서야 반복문을 소개 할 여유가 생겼습니다.

"영어로 반복이 모지?"
"음..?"
"엄마한테 물어보고 와!"

그렇게 해서 repeat가 반복이고 until은 언제까지 반복해야 하는 지 알려준다고 말해줬습니다.  이 부분이 참으로 마음에 들지 않습니다.  초보를 위해서 그냥 무작정 반복 할 수 있는 예약어를 추가하고 싶더군요.  조건이니 boolean이니 하는 것은 초보에게 너무 버겁기 때문입니다.  어쩔 수 없이 그냥 "until false"를 통째로 끝없이 반복하는 것이라 알려줬습니다.

program Step_03;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  BaseTools in '..\..\Lib\BaseTools.pas';

begin
  repeat
    write('*');
  until false;
end.

그리고, 흥미를 유발하기 위해서 파도 타기 예제를 마무리로 수업을 마쳤습니다.  한 줄 씩 뛰어서 출력하기 위해서는 Line의 약자 Ln을 뒤에 붙인다고 이미 설명을 마쳤었기 때문에, Write 대신 WriteLn을 사용하도록 하였습니다.  줄 맞추기는 나중에 제가 손을 봐줬습니다.

program Step_04;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  BaseTools in '..\..\Lib\BaseTools.pas';

begin
  repeat
    writeln('*');
    writeln('**');
    writeln('***');
    writeln('****');
    writeln('*****');
    writeln('****');
    writeln('***');
    writeln('**');
    writeln('*');
  until false;
end.

파도가 너무 정신없이 흐르기 때문에 느리게 할 필요가 생겼습니다.  

"한 줄 씩 출력하면서 컴퓨터를 자게 만들자!  잠자다가 영어로 모지?"
"Sleep이요"  (대답을 유도하는데 한 참 걸렸음)
"한 줄 출력 하고 난 뒤에 50 셀 때까지 자라고 하자!"

컴퓨터는 숫자를 빨리 센다고 설명해줘야 했고, 밀리세컨드와 같은 불필요한 요소들은 설명을 생략하였습니다.  최소한의 정보로 최대한의 결과를 만들어야 초보자에게 접근하기 쉽기 때문입니다.

마지막 코딩은 제가 도와 줬습니다.   도영군이 이미 독수리 타자를 하는데 지쳐버렸기 때문입니다.

program Step_04;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  BaseTools in '..\..\Lib\BaseTools.pas';

begin
  repeat
    writeln('*');
    sleep(50);

    writeln('**');
    sleep(50);

    writeln('***');
    sleep(50);

    writeln('****');
    sleep(50);

    writeln('*****');
    sleep(50);

    writeln('****');
    sleep(50);

    writeln('***');
    sleep(50);

    writeln('**');
    sleep(50);

    writeln('*');
    sleep(50);
  until false;
end.



 
저작자 표시 비영리 변경 금지
Posted by 류종택
겨울 방학 동안 아들 넘 프로그래밍을 가르치기로 해서 오늘이 두 번 째 날이었습니다.  보통 프로그래밍 입문하면 피할 수 없는 프로그램이 있습니다.  바로 "Hello, World!" 라고 할 수 있는데, 사실 저는 이는 잘못된 접근 방식이라고 생각합니다.  문자열을 설명하는 것 자체가 상당히 곤혹스러운 일이기 때문입니다.  그냥 "처음에는 일단 외우고 시작하자!" 라는 방식도 어느 정도 효과를 걷을 수 있긴 하지만, 개인적으로는 선호하지 않습니다.

일단 프로젝트 생성 및 저장 등 기본적인 준비는 제가 해주고, begin end. 사이에만 집중하도록 하고 있습니다.

저의 첫 번째 예제는 Write(1 + 2) 입니다.  Write가 실제 의미하는 것과 출력을 살펴보면서 아이가 직관적으로 Write가 하는 일을 알 수 있게 되기 때문입니다.  괄호가 필요한 이유는 설명하지 않았습니다.  모든 것을 다 설명하려다 보면, Write 자체에 집중하기 어려워지기 때문입니다.  이후 자신이 계산하고 싶은 것들을 입력하게 하거나, 가족의 나이를 전부 더하는 것을 미션으로 주었습니다.

두 번 째 날에는 문자열에 대한 설명을 시작하였습니다.  우선 첫 번째 수업의 복습으로 123456789 + 123456789 를 계산하도록 하였습니다.  결과에서 이상한 점을 찾아보라고 하니, 찾아내더군요 ^^*

문자열에 대해서는 우선 Write(1 + 2)를 출력하게 하고, Write('1 + 2')를 이어서 출력하도록 했습니다.  아이가 혼란스러워하더군요.  그래서, 설명을 해주었습니다.  따옴표로 감싸주면 "네가 입력한 그대로 써라(Write)"  그리고, 따옴표가 없으면 "계산한 결과를 써라" 라고 몇 번 반복시키고 차이점을 계속 느낄 수 있도록 하였습니다.  문자열이라는 명칭을 알려주기는 했으나 외울 필요없으니 그런게 있구나 하고 넘어가도록 했습니다.  "입력한 그대로" 만을 잊지 않도록 반복시켰습니다.

다음은 반복문을 통해서 호기심을 유발할 수 있는 예제가 있는데, 이것이 델파이에서는 문제가 되는 군요.  델파이와 같은 일반적인 언어에서 반복문의 수준이 너무 높기 때문입니다.  루비의 경우에는 5.times 와 같이 직관적인 방법이 제공되는데 참으로 아쉽습니다.  최대한 쉬운 반복문을 표현하기 위한 것이 미리 함수를 만들어 두는 것이었고, 사용방법은 아래와 같습니다.
repeat
  WriteLn('*');
until RepeatCount(3);

// 미리 만들어 둔 RepeatCount 함수
var
  _RepeatCount : integer = 0;

function RepeatCount(Count:integer):boolean;
begin
  if _RepeatCount = 0 then _RepeatCount := Count;
  Dec(_RepeatCount);
  Result := _RepeatCount <= 0;
end;

이런 저런 언어를 두고 고심을 많이 했지만, 모든 경우가 제가 원하는 수업 방식에 맞지 않았습니다.  그래서 직접 교육용 언어를 만들고 있었는데, 아들에게 그 언어를 통해서 가르칠 만큼 준비가 되지 않아서 일단 델파이로 가벼운 시작을 하고 있습니다.  내년에는 개인 사업을 시작하기 때문에 교육용 언어 개발은 더욱 지연이 될 거 같네요 ㅠ.ㅠ

여하튼 초보자들을 가르치다보면 가장 힘든 것은 그 수준에 맞춰서 진도를 유지하는 것과, 초보자가 숙련자에게 너무 당연한 것에 대해 의문을 가질 때 그것을 설명해줘야 하는 경우 입니다.


저작자 표시 비영리 변경 금지
Posted by 류종택
오늘은 그 동안 바쁘다는 핑계로 미뤄두었던 글을 써보려고 합니다.  제가 관련됐었던 프로젝트에 대한 이야기 입니다.

http://goo.gl/U9Xrf

 
가락시장에서 농산물경매 중 비리가 발생하자 해당 공사는 경매과정을 녹화하여 투명성을 확보하기 위한 프로젝트를 시작합니다.  이러한 비리는 이전부터 계속 반복 되어왔다고 합니다.
 

비리를 막기 위한 프로젝트에 비리가?

이에 각 경매를 진행하는 청과 회사들은 2011년 7월까지 경매과정을 녹화하기 위한 시스템을 각자가 구축해야 하는 상황에 놓이게 됩니다.  하지만, 담당자들은 공사에서 제시한 개발 목표가 과연 실효성이 있는 가 하는 의문을 갖게 됩니다.  그리고, 제가 속한 S청과회사에서는 자체적으로 보안책을 연구하고 이를 추진하려고 했으나, 공사의 담당자는 특정 업체를 지원하는 것처럼 보이는 상황이 계속 연출됩니다.


의혹을 제기하는 이유 - A업체의 대표가 대신 공문을 작성했다! 
어느 날, 청과에서 공문이 하나 발송되었습니다.  S청과가 추진하려는 개발목표를 보고 받고 공사 측에서 내보낸 문건에는 S청과가 진행하려는 방식은 왜 안되는 지 상세하게 설명되어 있었습니다.  그런데, 그 공문의 내용을 A 업체 대표가 쓴 것을 그대로 발송한  것이라고 공사 담당자 자신의 입으로 시인했다고 하더군요.  순간 정신이 혼미해지고 말았습니다.  공문은 A 업체 방식을 두둔하는 형식이었고, 억지스러운 주장들도 상당 부분을 차지하고 있었습니다. 


의혹을 제기하는 이유 - 공청회!  그러나 사실은 압박?
S청과가 강하게 반발하자, 공사측에서는 교수님 한 분을 초청하여 공청회를 열게 됩니다.  하지만, 공사의 담당자는 결론을 짓지 않고, 애매하게 마무리 합니다.  "어떻게 해라라고 하지는 않겠다.  대신 결과가 자신의 마음에 안들면 책임 못진다."라고 하고는 마무리하였습니다.  제가 받은 느낌은 압박 넘어 협박에 가까워 보였습니다.  회의를 마치고 나오는 도중, S청과 팀장은 X청과 팀장에게 "너희는 어떻게 할꺼야?"라고 물으니, "저렇게 까지 하는데 그냥 하라는 대로 해야지!"라고 하였습니다.


의혹을 제기하는 이유 - 다 필요없고 A  업체처럼 하세요.
개발 과정 중에 가끔씩 공문이나 담당자의 구두로 지시가 내려옵니다.  심지어 A 업체 프로그램 화면을 캡쳐해서 그대로 만들라고 공문을 내려 보냅니다.  그러면서도 "이거 특정 업체 밀어주기 아닙니다."라고 공사의 담당자가 어느 회의에서 발언을 합니다.  S청과는 공사에서 기준으로 제시한 A 업체의 문제점을 지적하지만, 담당자는 "다 필요없고 A 업체처럼 해!."라는 식입니다.


비리가 아니라면 공사의 심각한 무능이다. 
우선 소프트웨어 개발에 대한 스팩이 없었습니다.  정확한 가이드 라인은 애초에 존재하지 않고, 담당자의 마음대로 일 뿐이었습니다.  그나마, 기준은 A 업체의 산출물입니다.  이나마도 개발 도중에 스팩이 변하게 됩니다.  더욱 큰 문제는 실질적인 문제점을 파악하고 개선하려는 의지 자체가 없었다는 것입니다.

청과 회사의 전산 담당자들은 실질적이고 효과적으로 비리를 막을 수 있는 방법들을 충분히 만들어 낼 수 있다고 생각했습니다.  S청과에서 생각해 낸 것 중 하나는 바로 "실시간 공개"입니다.  녹화도 추후 얼마든지 수정하거나 분실 등의 사고로 감춰질 수 있기 때문에, "실시간 공개" 방식이라면 어떤 비리도 끼어들 틈이 없다는 발상이었습니다.  즉, "녹화 과정이 실시간으로 중계된다면, 나중에 이를 덮어버리는 것이 불가능하다"라는 발상이었습니다.  그리고, 여기에는 카메라나 비싼 녹화 장비도 필요 없기 때문에 S청과는 이러한 개발 방식을 공사에 제안했던 것 입니다.  

하지만, "신문에 카메라 두 대로 녹화하기로 발표했으니까 그렇게 해!", "카메라가 보여야 제대로 대처한다는 것을 보일 수 있으니까 그렇게 해!"로 마무리 됩니다.

애초에 정확한 가이드라인을 제시하지도 못했던 공사는 끝까지 추상적인 개발 목표를 고집합니다.  카메라의 해상도는 어느 수준인지, 프레임 수 제한, 기타 방식에 대한 아무런 언급도 없이 "검수 조건은 내 맘대로"를 고수합니다.  소프트웨어 개발에서 요구사항이 중간에 변하거나 추가되는 경우는 많지만, 완료 시점에서 까지 정확한 가이드 라인은 없고 "결과물을 보니 안되겠다, 다시 해!"를 기준으로 고집합니다.

결론적으로 공사는 스스로 이 프로젝트를 진행하고 관리 감독할 능력 자체가 없었다는 의미입니다.  그냥 "우리가 카메라를 번쩍이며 녹화하고 있는 모습을 보여서 사람들이 잘하고 있다는 인식을 심어주자!"가 목표였을 뿐이라는 생각이 듭니다.


사건의 전개
  • 경매 과정을 녹화하라
    이미 앞 부분에서 밝혔듯이 이번 프로젝트는 경매 과정을 녹화해서 비리를 막아보자고 시작된 것이었습니다.  하지만, 실무 담당자들은 이것 역시 많은 허점이 있고 단순히 전시 행정으로 끝날 수 있음을 깨닫고, 좀 더 효율적인 방법을 연구하다가 "실시간 중계"라는 아이디어를 공사에 제안합니다.  하지만, A 업체 대표가 써준 A 업체의 입장만을 대변하는 글을 공문으로 발송하면서 비논리적인 반대를 합니다.  이에 S청과가 반발하자 허울 뿐인 공청회를 열어서 오히려 압박하는 분위기를 연출 합니다.  그런 압박 중에도, S청과는 PC원격제어와 유사한 방식으로 화면을 녹화하여 실시간으로 중계하는 방식을 추진합니다.  이 방식은 실시간으로 감시하는 것은 물론 녹화도 가능합니다.  공사나 기타 중립 기관에서 2중으로 녹화를 하여 보관 할 수도 있는 방식이기도 합니다.
  • 녹화 화면에 글자가 안보여
    A 업체의 카메라로 컴퓨터 화면을 녹화하는 방식으로는 녹화된 화면의 글씨가 안보이는 문제점이 발생하였습니다.  그러자, 화면 위에 자막으로 컴퓨터 화면에 있는 주요 정보를 표시하라고 A 업체의 사진을 첨부로 하여 공문이 발송됩니다.  결국 S청과의 제품은 컴퓨터 화면에 있는 모든 정보가 그대로 깨끗하게 보이는데도, 자막을 또 씌우는 우수운 일이 벌어집니다.
  • 프로젝트 완료에 가까워졌는데, 이럴 수가!
    우여곡절 끝에 프로젝트 완료에 가까워졌는데, 심각한 요구사항이 추가 됩니다.  컴퓨터 화면을 실시간으로 중계하더라도 A 업체와 같이 카메라 두 대로 추가 녹화하라는 것 입니다.  개발을 총괄하는 저의 입장에서는 해당 솔루션을 개발해 본 적이 없기 때문에 심각한 상황이었습니다.  예상되는 문제점을 S청과에 보고하면서, 지금이라도 공사의 요청을 들으라고 권유했지만, S청과는 해당 문제점은 공사에서 제시한 가이드인에 언급이 되지 않았기 때문에 자신이 책임지겠다고 하여, 추가 개발에 들어가게 됩니다. 
  • 비용없이 추가 개발 그러나
    공사의 담당자도 괘씸하고, 어떻게든 효율적인 방법을 찾고자 노력하는 분들이 오히려 징계를 받을 위기에 처해 있는 것이 안타깝기도 해서, 추가 비용없이 개발을 연장하게 되었습니다.  (추가 비용을 요청했지만 거절 당했습니다.  하지만, 그래도 연장 개발에 참가하기로 결정하였습니다)  진행 과정에서 S청과의 과실도 다소 있었습니다.  내부 보고가 잘 못 되어, 아직 완료되지 않은 상태에서 완료 보고가 들어갔고, 부족한 상태에서 PT까지 진행하면서 상황이 더욱 악화된 것 입니다.  공사에게 발표하는 바로 전까지 잠도 못자고 개발에 매달렸지만, 역부족이었습니다.  이를 계기로 S청과는 더욱 공사에 끌려 다니게 됩니다.  그리고, 아직도 검수를 받기 위해 새로운 개발이 진행되고 있으며, 징계를 받는 수준에 이르렀다는 이야기를 전해 들었습니다.  (이미 받았을 지도 모릅니다)


마무리
제가 이 글을 쓰면서 주장하고 싶은 것은 아래와 같습니다.
  • 프로젝트 진행 과정 중에 나타난 의혹을 풀어주세요.  특정 업체 대표의 글을 그대로 공문으로 발송했다는 사실만으로도 충분 경악할 만한 일이라고 생각합니다.
  • 추후 해당 공사가 프로젝트를 진행 할 경우에는 전문가를 통해서 정확한 분석과 가이드라인을 수행할 수 있도록 개선해 주세요.
  • "무엇인가 더 좋은 길이 없을 까?"를 고민하고 소신으로 추진했던 담당자들에게 상을 주지 못할 망정 징계는 문제가 있다고 생각합니다.
바쁘기도 했었지만, 부끄럽게도, 이런 문제를 제기하면 저만 귀찮아 질것으로 생각했기 때문에 미룬 것도 사실입니다.  늦게라도 잘못된 것을 지나치지 않고 바로잡기 위해서 글을 정리해 봅니다.  이제 이 글이 문제를 해결할 수 있는 능력을 가진 분에게 전달 될 수 있도록 최선을 다하겠습니다.


저작자 표시 비영리 변경 금지
Posted by 류종택


절대 쉽게 생각해서는 안되는 브랜칭 비용.
일반인 고객이 그렇게 생각하는 것은 어느 정도 이해가 되나,
개발자가 그 가치를 이해하지 못한다면 전문가로서 자격이 없다.
 
소스 관리에  대한 비용을 효과적으로 조절하지 못할 경우,
시간이 흐를 수록 엄청난 재앙으로 다가오기 때문이다.
 
바쁜 실무에서 소스 관리가 완벽하리라는 생각은 어리석다.
저작자 표시 비영리 변경 금지
Posted by 류종택