태그 미디어로그 위치로그
개발의 기수: R0의 하루…
개발자 세상

이번 글이 개발의 기수 몇 탄 째더라…흠…

막상 글을 쓰려하니 예전에 만들어 놓은 멋진 ‘개발의 기수’ 카테고리는 어디가고

개발 스토리라는 딱딱해보이는 게시판이 떵그렁 있다.

예전 글은 하나도 없고…

나름 열심히 쓴 글인데…

궁시렁…궁시렁…

지난 3월.

본인은 개발 본부내 임시 조직인 R0팀 업무를 한달동안 했었다.

지금은 프로젝트를 새롭게 시작해서 이렇게 글 쓸 여력도 되지만,

그때 당시엔 하루하루가 정신없고 피곤하고 알티베이스 일은 죄다 혼자 다하는 것 처럼 설쳐댔었다.

R0 팀이란, 고객을 지원하는 지원 본부를 지원하는 개발 본부내 임시 조직 쯤 된다.

한마디로 ‘실시간’ 유지보수 팀이라 할 수 있다.

디비가 실시간 디비라 그런지 유지보수도 실시간인가보다-_-

한국 사람들은 참 빠른걸 좋아한다.

오늘은 R0하면서 있었던 몇가지 에피소드를 소개해보련다.

R0 팀 업무 수행하는 느낌을 살리기 위해 여러 case들이 순서 없이 context-switching할 것이다.

읽는데 좀 정신이 없겠지만, 실제 업무에 비하면 이건 맛보기에 불과하다는 사실!!

자, 레츠고~~

case-1
알티베이스에서는 CREATE TABLE TB (A NUMBER)라고 한 후, DESC TB했을 때

A 컬럼의 타입이 FLOAT라고 표시되는데

어떤 고객이 자기네들이 만든 자동화 툴이 DESC를 조회해서 스키마를 구분하는데

이것 때문에 프로그램이 동작하지 않는단다.

NUMBER로 만들었으니 표시도 NUMBER로 해야하는게 아닌가??

뭐 따지고 보면 그렇긴하지…

case-2
“프로시저 디버깅하기 너무 힘들어요~~”

우리 고객지원본부팀원께서 이런 불평과 함께 프로시저가 너무 길면

에러 라인이 표시 안된다는 버그를 리포팅하셨다.

가령
create or replace procedure proc1(msg in char(100))
as
k number;
begin
if k > 0 then
k = msg;
end if;
end;
/

line 6: parse error
K = msg;

^
처럼 에러 라인이 표시되는데

create or replace procedure proc1(msg in char(100))
as
k number;
begin
system_.println(’aa’);
system_.println(’aa’);
system_.println(’aa’);
system_.println(’aa’);
…(수십 라인 반복)
if k > 0 then
k = msg;
end if;
end;
/

[ERR-31001 : SQL syntax error ]

처럼 프로시저가 길면 에러 라인이 표시가 안된다는 거다.

실제로 고객사에서는 수천라인이 넘는 프로시저도 만들더라-_-

왠만한 큰 프로그램도 분석하는데 별로 부담이 없는 나이지만…

프로시저 수천 라인은….GG이시다.

case-3
4.3.9에서 잘 쓰던 애플리케이션이 5.1.5로 업그레이드하니 안되요!!

5.1.1에서도 잘 됐었는데…왜 안되죠?

SQLProcedureColumns()라는 ODBC 함수의 동작에 대한 문제였다.

결과로 리턴되는 row들의 순서가 예전과 달라서 고객 애플리케이션이 제대로 동작이 안된다는 것이다.

고객도 나름 불만이었지만 우리 고객 지원 부서에서 더 큰 불만인 듯 했다.

case-1
우린 NUMBER라는 타입이 없다.

생성시 NUMBER타입의 컬럼들은 모두 FLOAT이거나 NUMERIC으로 변경되서 메타에 저장된다.

그러니 DESC를 하면 FLOAT 또는 NUMERIC(10) 등으로 표시된다.

고객님: 왜 그러냐? NUMBER로 생성했으니 NUMBER로 나와야 하지 않느냐???
O사도 그렇다! 바꿔라…

어쩌지…

NUMBER라는 타입의 실체를 만들어야하나?

이거 작업 큰데…

case-3

버그 리포트와 스펙 자료들을 찾아보니,

과거엔 결과 row들을 column_name, column_position 순으로 정렬했지만,

최신 버전엔 column_name, column_type 순으로 정렬하고 있었다.

최신 버전의 정렬은 스펙에 근거한 것이었다.

“아~ 그거 찾아보니 5.1.5에서 표준 스펙에 맞게 바꾼거에요~ 5.1.5가 표준에 맞아요.”

지원본부: “표준은 고객에게 안통합니다. O제품이나 S제품은 우리 예전 버전이랑 똑같아요~
이렇게 함부로 바꾸면 어떡합니까??”

어떡하지? 다시 예전으로 복구하느냐 스펙을 고수하느냐…

패치 레벨 업그레이드시엔 인터페이스는 바꾸지 말았어야 하는건데…

case-4
어느날, 새벽에 한 증권 고객사에서 메시징 시스템 실장비에 대대적인 버전업 패치가 있었다.

무려 30대에 15식에 대해 4.3.7에서 4.3.9로 버전업 작업이 진행되었었는데

아침에 실서비스를 해야하기 때문에 새벽내로 패치가 완료되야 하는 긴박한 상황이었다.

드디어 데이터 마이그레이션을 무사히 마치고 애플리케이션을 새 버전에 맞게 다시 빌드하고

애플리케이션을 구동하는 순간…

죄다 insert 구문들이 실패한다는 거다.

실장비이니만큼 최우선 처리를 요구했다.

나는 아침부터 오자마자 다른 케이스들을 제쳐두고 요걸 분석해야 했다.

분석하자~~

case-2
에러 메시지를 자세히 보라.
K = msg;

^

^는 에러가 난 위치를 나타낸다.

그렇다면 ^위의 공백들은 뭐지?

탐정 영화에서 빈 종이는 분명 그냥 빈종이가 아니듯이

이 공백도 빈 공백이 아니었던 것이다!

마우스로 긁어보라!! (실제 웹에선 공백이 안모임ㅠ:저자주;;)

신비하게 어떤 글자가 나타…….나진 않지만;;

분명 공백들의 길이는 큰 힌트를 주었다!

모양이 프로시저 텍스트 모양과 일치하지 않는가!

요거…공백이 뭔 비밀을 가지고 있는듯….

case-4

작업 환경을 세팅하기 위해 고객사와 동일 버전을 내려받고 디버깅 모드로 컴파일 시킨다.

‘공간 부족 에러…’

에효…이노무 장비는 또 disk full이다.

메일 공지를 날려 disk 공간을 확보했더니 이젠 java_home 문제로 컴파일 에러가 난다.

OS 재설치로 뭔가 환경이 달라져서인가보다.

바쁠 때 이런 예외 상황이 발생하면 짜증 지수가 오르기 시작한다ㅠ

분석…분석…

시간은 째깍째깍…

long타입 변수를 numeric(10)에 바인딩했는데…

왜 overflow 에러가 날까…왜왜왜~~(디버깅하다보면 모니터와 가장 많이 하는 대화가  ‘왜’이지 싶다-_-)

거기다 실제 long 변수에는 100이 할당되어 있다.

겨우 100이자나…왜 이게 오바냐고…안들어가는 니가 더 오바야!!

좀 들어가주면…안되겠니??ㅠㅠ

case-5

이번달은 바빠서 부르지 마라했거늘…친구들이 한잔 하자고 결국 불러냈다.

모듬전에 소주가 나와 한잔 기울이려는데….전화가 온다.

“WAS에서 자꾸 JDBC에러가 나요. 왜죠?왜죠?왜죠?”

‘저…R0하면서 오늘 처음 7시에 퇴근했는데…이제막 모듬전이 나왔는데…ㅠㅠ’

case-3
어라..찾아보니 O 제품은 전혀 딴 판의 방식인데요?

M사와 I사만이 함수 스펙을 명시하고 있고 다른 제품들은 아예 함수 스펙 자체도 없어요.

표준 ODBC 스펙을 따랐을 리가 만무하죠!

우리가 맞다고 우깁시다!!

내 주장은 이랬다.

“고객이 애플리케이션을 바꿔보겠답니다.”

오예~

case-5
술잔과 모듬전을 마다하고 달려갔다.

WAS, 제우스 모두 에러난댄다.

얘네들은 뭔 쿼리를 날리길래 자꾸 에러나나…

살펴보니 디비가 죽었나 살았나 확인하기 위해 “SELECT * FROM DUAL”을 주기적으로 날린댄다.

헉..이런 간단한 쿼리가 왜 에러나지??

case-2
분석분석…

푸하하하~~~

와…이거 진짜 대박 버그다.

문제의 원인을 발견하고 난 진짜 크게 웃어버렸다.

아~~주 사소한 변수 하나를 잘못써서 ^를 찍기전까지 프로시저 길이만큼 공백을 찍고 있었던 것이다.

더 대박이었던 건…

무려 이 버그가 6년넘게 살아있었다는 사실…

내가 입사이후로 아마 최장수 버그가 아니었나 생각된다.

아무도 저 공백을 눈여겨보지도 않았고 더우기 버그라는 생각은 전혀 못했다는 상황이 너무 우스웠다.

하나 깔끔하게 해결…

이 버그의 압권은 지원본부 임옥섭님께서 마우스로 긁어서 큰 힌트를 주셨다는 것.

case-3
“고객이 로직을 하나 바꿔보니 온통 에러가 난답니다. 바꿀 분량도 너무 많아

도저히 못바꾸겠대요~”

에효…어쩌나…

다시 빠꾸해야하나…

논의 끝에 SQLProcedureColumns2() 따위의 함수를 제공해주자는 의견이 나왔다.

column_name, column_position으로 정렬하도록 하는 비표준 함수인 것이다.

뭐 그런거라면..얼마든지…

이렇게 해서 SQLProcedureColumnsOrderByPos()라는 길고 긴 이름의 함수가 탄생되었다….

이 함수는 이 고객덕에 앞으로 평생을 함께 해야할 운명이 되어버렸다.

case-1
그러는중 지원 본부 이창훈님이 카운터 펀치 한방을 고객에게 날리셨다!

O사는 모조리 NUMBER 타입으로 나오는데요???

그렇다.

O사는 FLOAT로 만들던 NUMERIC으로 만들던 DESC해보면 죄다 NUMBER로 표시되는 것이었다.

뭐야 이게…

우리보다 더 심하잖아!!

그랬더니 고객님 왈…

“O사처럼 해주세요…”

그래도 O사처럼 해달란다.

허허…

case-5
저 간단한 select 구문이 PreparedStatement.execute()라는 메소드로 실행된게 문제였다.

우리의 JDBC는 execute()를 실행하면 execute protocol만 수행하고 fetch protocol은 수행하지 않는다.

효율을 위해…

따라서 execute하고 ResultSet을 얻지 않고 다시 execute()를 수행하면 에러가 발생하는 것이다.

그래..죽었나 살았나 알아보는데 굳이 결과는 필요없지…

근데 왜 executeQuery()를 놔두고 execute()를 수행하느냐 말이다. ㅠ

WAS를 고칠 수는 없댄다.

어떻게 해서든 우리 제품을 수정할 수 밖에…

쳇…

우리 플랫폼 개발자 맞아요?

우기면 될 일이지만 우린…..힘이 없다 ㅠ

어쨌든 간단한 수정으로 해결…

다시 술자리로 고고~

case-4

점심이 지났다.

지원본부에선 자꾸 재촉의 전화가 온다.

지원본부 팀장님까지 불려가시고 고객의 불만이 하늘을 찌른대나…

근데 이노무 디버거 또 죽네..급해죽겠는데

독일놈들 싸잡아 때려주고 싶다.

이렇게 버그 많고 잘죽는데…그 치밀하다는 독일애들도 어쩔 수 없나보다.

뭐 공짜니 군말없이 써야지…ㅠ

내 시간나면 꼭 이클립스 깔아서 써야지..이노무 DDD… 품질도 D감이다.

오늘 난 투덜이 스머프가 됐다 ㅠ

분석분석…
어라!!

클라이언트가 32비트 컴파일 환경이라 long이 4바이트일텐데…왜 8바이트로 바인딩 되었지?

결정적인 힌트를 찾았다.

8바이트의 단서를 가지고 범인을 추적했다.

덜컹…

sesc가 범인이었다.

sesc는 우리 클라이언트 패키지에 포함된 전처리 컴파일러인데

32비트 클라이언트 환경에 sesc가 64비트로 빌드되었던 것이다.

이..이거…누가 설치를 잘못했나본대요?

64비트 서버 패키지와 32비트 클라이언트 패키지를 섞어서 설치한 것 같습니다.

두둥…다행히 제품의 문제는 아니었고, 설치 지원시 실수가 있었던 것이었다.

사건 종료…

case-1
같은 IT 업종인 친구가 얘기했다.

자기도 언젠가는 플랫폼 개발해보고 싶다고…

(여기서 언젠가는 이란말은 돈이 넉넉하게 벌렸을 때를 말한다.

고로 플랫폼 개발이 돈이 될 거라는 가정은 아예 배제하고 있다…요놈…-_-)

플랫폼 개발…

많은 프로그래머들이 개발할 수 있는 환경을 만들고,

기반이 되는 시스템이자 표준을 구현하는 멋진 작업이다.

그런줄 알았다.

근데 오늘도 고객의 엉뚱한 요구는 면접시험때 나온 문제를 또 한번 떠올리게 했다.

“Custom” is always true.

속으로 그랬다.

‘실장님…면접 시험 이제 바꿀 때도 되지 않았나요?’

플랫폼 개발은 표준을 정하는것이 어려운게 결코 아니다.

후발주자로서 선발주자의 악덕 인터페이스까지 자존심을 구기며 제공해야 하는 그런 지저분한 일이 힘든 것이다.

버뜨…이번 경우엔 못해주겠다고 못박았다.

우린 o사와 숫자 타입 체계가 전혀 다르기 때문에 이런것까지 따라할 수는 없는 노릇이었다.

하루에도 동시에 수많은 case들이 올라오고 정신없이 작업 전환을 하면서 처리하느라면

내가 그동안 참 편한 프로젝트 개발을 하고 있었구나 생각되었다.

이렇게 앞에서 막아주던 과거의 R0팀들 너무 고생이 많았구나…

더우기 우리가 개발을 편하게 할 수 있기까지 지원본부에서 밤샘 고생을 정말 너무 많이들 하고 계시는구나…

등등 느낀게 많았다.

밤 9시가 넘어서면 비로소 사무실은 조용해지고 해결하기 힘들어 묵혀두었던 case들을 끄집어 내서 분석해본다.

해결하고 싶은 마음이야 굴뚝같지만…

집중력은 이내 바닥나서 지친 몸을 이끌고 퇴근해야만 했다.

그러기를 30일…

case들을 미쳐 다 처리하지 못하고 다음 R0팀에게 넘기게 되어 미안할 따름었다.

유지보수 일을 두루 해보게 되면 우리 제품의 전체적인 품질 수준을 느껴보게 된다.

그 느낌은 프로젝트 수행 때 고스란히 긍정적인 역할을 하게 된다.

프로젝트 개발과 유지보수 일은 그래서 번갈아가며 해볼 만 하다.

문제는 그 주기를 얼마에 두느냐인데

개발본부 내에서 그에 대해 많은 고민을 하고 있다.

어쨌든…

꽃피는 4월이 어느덧 왔는데

오늘도 수고하시는 r0팀원들에게 화이팅을 불어넣어 주고 싶다.

쓰고보니 참 주절주절 말이 많았다.

이런 긴글을 누가 읽을까…ㅠ

사실 오늘 쓰고 싶었던 글은

‘일반화’에 대한 코딩 철학을 쓰고 싶었는데…

큐에 미리 들어가 있었던 r0 글을 이렇게 먼저 올린다.

다음엔 일반화에 대해 끄적여 볼랜다.