태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

11월에 이사갑니다

엑셈 뉴스룸 2008. 7. 30. 10:36

사용자 삽입 이미지




8년 만에
내집 장만을 성공한 저희는 오는 11월에 테헤란로를 떠나 한강이 내다보이는 염창동으로 이사를 갑니다.

덕분에 이곳 역삼역 아주빌팅 9층은 요즘 술렁술렁합니다.

사용자 삽입 이미지

[출처: 네이버 지도]


 한강 시민공원까지 걸어서 5분거리라는 정보가 흘러나온 후 '강변따라 걸어서 출근하겠다', '소풍 자주 가자', '자전거를 사겠다', '저녁마다 강을 건너가 고기를 구어먹겠다' 등등 기대감이 베어나오고 있습니다.

하지만 한가지 안타까운 사실이 있습니다.
답사 결과 저희 사무실에서 한강은 아파트와 앞 건물에 막혀, 무척이나 아쉬운 조망권을 자랑하게 되었습니다. 그래도 매일매일 역삼역 사거리에서 시끄럽게 빵빵거리는 차량의 물결들 대신 한강의 한 자락을 보고 있는 것이 훨씬 낫겠죠.

사용자 삽입 이미지사용자 삽입 이미지

게다가 '엎어지면 코닿을 거리'에 이마트가 있습니다.
배가 출출한 오후에 이마트 식품코너로 산책이나 다녀올렵니다.


사용자 삽입 이미지
저희가 이사갈 새 사무실은 빌딩 한 층의 반인 200평 규모에 디자인에  매우 신경써서 꾸며질 예정입니다.

해외에 상주하고 있는 분들을 빼면 50명인 식구들이 쓰기에는 무척이나 넉넉한 공간입니다.

말 그대로 '쾌적하고 건강한' 사무실을 위해 예산을 아끼지 않고 공기 순환 시스템 설계도 도입할 예정입니다. 오후만 되면 머리를 멍해지게 만들었던 축 가라앉은 공기와도 가을이면 안녕입니다.
  [새 사무실이 들어갈 공간(출처: 우림블루나인]


이 공간들을 꾸며 줄 업체 선정이 한참 진행 중에 있습니다.

비록 규모의 제약 때문에 벤치마킹하기에는 무리가 있지만,
'구글 오피스'처럼 일과 휴식 그리고 즐거움이 공존하는 곳으로 만들어 나가는 것이 저희들의 목표고 업체 선정에 앞선 인터뷰에서도 이 부분을 강조하고 있습니다.

더불어서 엑셈 사람들을 대상으로 어떻게 공간이 꾸며졌으면 좋겠는지 아이디어들을 받고 있습니다.


그렇게 해서 나온 아이디어로 ,
사각형인 책상에서 탈피해서 권위나 서열보다 자유로운 분위기가 조성될 수 있는 업무 환경을 꾸밀 겁니다.

그리고 휴식할 수 있거나 각종 오락시설을 즐길 수 있는 공간을 만들어 사무실에서도 즐겁게 지낼 수 있도록 할 계획입니다. 또한 이러한 공간들을 주말에는 엑셈 사람들의 가족들도 즐길 수 있도록 할 겁니다.

발코니를 정원처럼 만들고, 자전거를 타고 출근하거나 한강 시민공원에서 운동하고 온 분들을 위한 샤워실도 만들기로 했습니다.

사용자 삽입 이미지

[마무리 공사 중인 업무 공간]

사용자 삽입 이미지

[샤워실이 들어설 후보지들]

8월 중순에는 디자인 제안을 해온 인테리어 회사들 중 한 곳을 선정하여 2달간 본격적으로 사무실 꾸미기 공사에 들어갑니다.
엑셈의 새로운 사무실, 어떤 모습일까요? 무척이나 기대됩니다.

새로운 모습들이 나오는 대로 포스팅하여 알려드릴께요~

  • orion 2008.07.30 16:19 ADDR 수정/삭제 답글

    와우~새로 이사갈 사무실이 무척이나 기대됩니다.
    정말 열심히 일할 수 있을 것 같군요 ㅎㅎㅎㅎ

  • Favicon of http://blog.naver.com/ewnho 호야.. 2008.07.30 20:58 ADDR 수정/삭제 답글

    와.. 샤워실.. 정말 좋겠당..
    자전거로 출퇴근할수 있다는 점이 정말 매력적이군요..

  • 강대일 2008.08.01 13:18 ADDR 수정/삭제 답글

    샤워실 청소는 누가 하나요...하하하
    좋은시설이긴 한데....

  • 이명진 2008.08.06 14:24 ADDR 수정/삭제 답글

    웬지 무척... 설레고 기대됩니다^^

  • midas 2008.09.18 11:28 ADDR 수정/삭제 답글

    음.. 새론 삼실에서 새론 맘으로 희망차게 내일을 향해 달려가면 그 끝은 성공이겠지요..^^
    엑셈 여러분들 파이링~~!

EXEM Japan 분들과 함께한 즐거웠던 저녁 식사~

엑셈 뉴스룸 2008. 7. 28. 15:48

사용자 삽입 이미지



 정례회를 위해 3일간 한국에 방문중인  EXEM Japan 분들과  가든식 삼겹살 집에서 저녁식사를 했다.
 (요후~~ 난 삼겹살을 우리 신랑 다음으로 사랑한다~~~ ^^)
 
  EXEM Japan 분들은 일본에서 열심히 우리 MaxGauge를 홍보하고 판매하며, 기술지원까지 해주시는
  아주 노고가 많으신 분들이다...

  얼마전  MaxGauge가  NRI(노무라 종합 연구소)에 표준 툴로 지정되었다는 기사를 접했는데,
  한국의 솔루션이 일본 대기업의 표준화 툴이 되었다는 센세이션을 일으킨것은   EXEM의 모든 직원들은
  물론 이거니와 EXEM Japan 분들의 노력이 이루어낸 성과가 아닌가 싶다.

 점심에도 EXEM Japan 분들과 식사를 같이 했지만 선듯 인사가 나오지 않아 멀지 감치 떨어져 갔던 ...
 자리도 피해 앉으려  했던 기억이 난다.
 
 그냥 "하지메 마시떼~~~ ^^;;" 하고 손한번 한번 흔들어 주면 될것을....
 (이말이 "처음 뵙겠습니다 !"  가 맞어 틀려~~?? "안녕하십니까" 아니야??  모야~~?? 하며
  혼자 속으로 생각 하는동안 타이밍을   다 놓쳐 버렸다....    그이후로는 벙! 어! 리!...ㅜㅜ )
 
  솔직히 난 그분들과 식사를 한다는것에 의미를 두기 보다는 삼겹살을 실컷먹을수 있다는 생각에
  그날은  일하는 시간 내내 행복해 했던것 같다. ( 난 참 단순해~~ ^^ )

  처음 어색한 인사를 나누며 합석 했을때의 서먹함을 훌~ 훌~  떨쳐 버리게한 맥주 와 소주를 시작으로
 우리들의 저녁 식사는 시작 됐다.

사용자 삽입 이미지


혜원씨가 열심히 구워 놓은
고기로 허겁지겁 배를 채운후... 살짝 카메라를 꺼내 들었다.
첨에는 사진찍는것 조차 왜그렇게 어색 했던지.....
에라 모르겠다~  일본어 통역을 통해 그냥 자연 스런 모습 찍고 싶다고 얘기 하고
카메라로 마구 찍어 대기 시작 했다.
평소 술을 잘 못하는데 분위기에 이끌려 맥주를 글라스로 2잔 먹은거 같다...
그래서 인지 손이 덜덜덜 떨려 흔들린 사진들이 많다는..... ^^;;;


사용자 삽입 이미지



이와모토상이 사진찍는것을 보자 뽀빠이 아저씨 포즈를 취한다...^^


사용자 삽입 이미지



나와 같은 테이블에 있었던 가와무카상~ 전략 기획팀 은경씨와 한컷...
꿀 먹은 벙어리 마냥 가만히 있던 나와는 달리
평소 재밌고 발랄하고 톡톡 쏘는 은경씨가 가와무카이씨랑과 많은 얘기를 나눈다...
^^ 둘을 보며 나는 심심함을 달랠수 있었다.~


사용자 삽입 이미지



유후~ 드디어 원샷 퍼레~이드...
이날 최고의 분위기 메이커인 최과장님이 맥주를 술술 넘기고 계신다...^^


사용자 삽입 이미지



원샷 끝~~ 만세!! 를 외치시는 이채학 부장님 ^^


사용자 삽입 이미지



한국인 일본인이 만나 영어를 쓰는 모습을 상상해 본적 있는가? ^^
이날 둘은 일본어도 한국어도 아닌 영어로 대화 하드라....(부럽쌈~ ^^)

이와모토상이 우리 주영씨 맘에 들었나부다..ㅎㅎ

          이와모토상 : "저... 사진 한컷.....^^;;;"
          주영씨 : (아이 부끄~~)         


사용자 삽입 이미지



자연스런 모습을 찍을려고 했는데 ....
으흐흐흐 우리 고토 사장님 너무 자연스럽게 찍히 셨네~~~
한국 삽겹살 맛있지요?? ^^
( 식사중 이사진을 돌려 보면서 웃을 바다가 됐었다는....)


사용자 삽입 이미지


짜잔~~ 드뎌 오셨다~~~
고토 사장님의 천적~(왜 천적인지는 이제 알것이다...ㅎㅎㅎ)
이강녕 부장님~~(자칭 고토 사장님의 형 이라고 하심^^)
오시자 마자 삼합을 시키신다... ㅎㅎㅎ
(과연 무슨일이 일어날 것인가...??)

사용자 삽입 이미지


요것이 바로 삼합!!
한국인인 나의 입맛에도 맞지 않는 홍어...
(하지만 꾀 비쌌다는.....)
과연 일본에서 오신 손님들의 반응은 어떨까? ^^

사용자 삽입 이미지


이미 한번 홍어의 맛을 봤던 것일까?
최과장님 께서 삼합을 쌈싸고 있는동안 고토 사장님 뒤로
저만치 비키신다...ㅎㅎㅎ

최과장님 : " 자~ 요것이 한국에서 맛나고 비싼 음식인
삼합 입니다~ 맛 보세요 ^^ "

고토 사장님 : '머야 머야 설마 나주려는것은 아니겠......'

사용자 삽입 이미지



그렇다.... 그 쌈은 고토 사장님의 입속으로 들어갔다...
최과장님 : "자! 아~~"
고토 사장님 : "아~~" (ㅜㅜ 왜 나야...)


사용자 삽입 이미지



고토사장님의 입속에선 지금 삼합과의 전투가 일어나고 있다....^^

고토사장님 : ' 물 물 물어딨어?? 에라 소주라도.... 완샷!!'


사용자 삽입 이미지



저쪽~ 상황을 모르고 있던 가와무카이상...
누가가가 싸준 삼합쌈을 먹으려 하고 있다....

카와무카이 : '이거 뭐야~~~? 냄새는 왜이래..?? 근데... 고토 사장님쪽은  왜 초토화 된거야...??'


사용자 삽입 이미지



난~~ 삼합을 먹고 있는 가와무카이상 을 보면서
회심의 미소를 짓는다.... 으흐흐흐

가와무카이 : 'ㅜㅜ 물 물.... 에라.. 맥주라도...'


사용자 삽입 이미지



첨엔 조용하고 어색했던 자리가 점점 즐겁고 화기애애한 장소로 바뀌면서....
아쉽지만 여기까지 1차를 마무리 했다.

난 친정에 가야해서.... 그날의 하이라이트 라고 할수 있는 광란의 2차는 가지 못했다...
난 다음을 기약.... ^^





정작 나의 사진은 엄따... ( 하하하 내가가 바라던 바 ^^)
어둑 어둑 해질무렵.... 카메라 베터리도 다되가고 해서
 마지막으로  한참 즐기고 있는 우리들의 모습을 풀-동영상 으로 담아 본다....




  • orion 2008.07.28 16:13 ADDR 수정/삭제 답글

    이날의 즐거움이 그데로 묻어나네요~
    동영상 너무 생생한데요!
    고토 사장님과 윤진영씨 때문에 한참 웃었습니다ㅋㅋ

  • 강대일 2008.07.28 19:06 ADDR 수정/삭제 답글

    참 즐거워 보이네요.....요홋....
    전 뭐하느라 참석을 못했을까....
    은경씨는 영어로 가와무카상과 얘기했겠지요...^^

  • 주영 2008.07.29 22:37 ADDR 수정/삭제 답글

    이날 고토 사장님 덕분에 웃고 윤진영씨의 180도 달라진 모습에 웃고
    고기도 맛있고 시원했던 저녁이었습니다.

[염동환]쉘 프로그래밍, 얕봤다간 큰 코 다칩니다

엑셈 사람들 2008. 7. 25. 17:47

사용자 삽입 이미지
멕스게이지 지원을 가다보면 SMS 연동이나 기본 기능 외의 기능을 추가하기 위해 스크립트를 만들거나 서버상에서 추가적인 작업들을 많이 하게 된다.


이때
필요한 기술이 프로그래밍이다.


어떻게
보면 제일 간단하고 쉬운것인데 아주 작은 실수 때문에 오히려 고생할 때가 많다.

 

첫번째 중간중간 파일을 생성하고 읽어야 할경우가 많이 있다. 이때 절대경로를 쓰지 않으면 파일이 어디로 떨어질지 알기 어렵다.

실제로 절대 경로가 아닌 현제 디렉토리 기준에서 작성했다가 고생한적이 있다. 분명히 스크립트만 수행하면 정상적으로 동작하는데 데몬의 띄어 데몬에 의해 수행하게 하면 생성되어야 파일이 생성이 안되는 것이었다.

스크립트가 잘못되었나 계속 확인해 보아도 답이 안나와서 헤메는데 엉뚱한데 파일이 계속 생기고 있었음을 알고 ! 이것때문이구나 하면서 이런 실수를 하다니 하며 고생했던 적이 있다.

 

그리고 두번째가 실행권한이다 파일을 만들게 되면 기본적으로 읽기 쓰기만 되고 실행할수 있는 권한이 빠져있게 된다. 그래서 반드시 실행하기 전에 실행권한을 chmod 바꿨는지 확인해야 한다. 이것도 아주 기본적이지만 쉽게 놓칠 있는 경우이다.

 

서버작업을 제일 많이 했었던 H모증권사에서 있었던 일이다.


여기는
10개정도의 DB 멕스게이지가 설치되어있는데 서버에 SMS연동을 시켜 놓았다. 그날 낮에 열심히 각서버에 SMS 연동 스크립트를 만들어서 그들이 원하는 지표에 대해 그리고 이벤트에 대해 SMS연동을 시켜 놓았다. 그래서 정상적으로 동작하는지 테스트도 해가면서 문자가 잘가는 것을 확인하고 아주 뿌듯하게 나왔었었다. 그런데 다음날 아침 일찍 나를 깨우는 전화가 있었다.

 

바로 H모증권의 담당자였다. 담당자 얘기로 밤새 문자가 날라와서 잠을 잘수가 없었다고 했다. 계속 쉬지않고 와서 문자 수신함이 가득차고 그래서 결국 SMS 서비스가 안되게 데몬을 내려놓기까지 했다는 것이다.

 

이유는 밤마다 배치작업을 하는데 배치작업을 하면 CPU 100%까지 사용되고 각종 이벤트가 발생하는 것이었다. 그래서 결국 SMS문자를 warning 아닌 critical 레벨일때만 갈수 있게 고치고 항목도 줄이고 그리고 밤에는 아예 보내지 않게 다시 수정했다.

 

이번 사건을 통해서 너무 많이 설정하는 것도 좋지 않다는 것을 배우게 되었다.

일본 최대 IT 아웃소서가 선택한 맥스게이지

엑셈 뉴스룸 2008. 7. 22. 18:37

사용자 삽입 이미지

가뭄 속의 의미있는 성과

엑셈 뉴스룸 2008. 7. 22. 18:36

사용자 삽입 이미지
 
사용자 삽입 이미지


  • orion 2008.07.24 18:09 ADDR 수정/삭제 답글

    와우 대표님 얼굴에서 빛이나요!!

미래를 준비할 때 한 번쯤은 읽어봐야 할 "새로운 미래가 온다"

[한민호]HashedStringList 제대로 알고 사용하기

엑셈 사람들 2008. 7. 18. 17:44

사용자 삽입 이미지
 

 엑셈에 입사하게 되면서 학창시절 어렵게 공부했던 List에 관심을 갖기 시작했다. 프로그래밍에 문외한이었던 나에게 자료구조 초반에 배웠던 List는 어렵고 과연 저것이 얼마나 많이 사용될까 싶었는데 현업에서는 매우 자주 사용되고 있었다. 또한 초보 프로그래머들에게는 라이브러리 클래스로 지원되는 List를 이용하면 공들여 List를 프로그래밍 하지 않고도 쉽게 사용할 수 있었다.


 
델파이를 접하게 되면서 가장 처음 접하게 된 리스트가 StringList였다. 정말 유용하지만 List에 데이터가 많을 경우 첫 번째 인덱스부터 순차적으로 검색하기 때문에 검색속도가 매우 떨어지는 단점에도 불구하고 다른 방법이나 내부적 구조를 몰랐기에 그냥 사용할 때가 많았다.


어느 날 검색속도에 관심을 갖고 StringList의 대안을 찾던 중 HashedStringList라는 꽤 괜찮은 List을 알게 되었다. HashedStringList StringList를 그대로 상속받아 만들어져 StringList가 가진 기능들을 전부와 단지 IndexOf 메소드의 기능을 충실히 할 수 있도록 Name ValueHash키만을 가지고 있었다.


 Hash Table
을 가지고 있는 것만으로도 검색속도는 매우 좋을 것이라 생각했고 이것이 어떠한 함정이 있을 것이라곤 깊게 생각하지 못했다.


 이 HashedStringList에 대해 자세히 알아보기 위해 예제를 만들어 확인해 보기로 했다. 예제는 1500만 건의 숫자 스트링을 10 Insert 해본 통계와 10회의 Search 성능의 통계이다.

 

 
 
예제를 보면 StringList HashedStringList Insert 속도는 거의 동일한 것을 확인 할 수 있고 검색 속도는 평균적으로 HashedStringList가 훨씬 앞서는 것을 확인할 수 있다. 예제상의 화면만으로 분석을 해보자면 Insert Hash Table을 생성하지 않는 다는 것을 추측해 볼 수 있다. Hash Key 를 생성하고 Hash List를 만든다면 1500만 건의 데이터를 삽입하는데 절대 동일한 성능이 나올 수가 없기 때문이다. 또한 Search 테스트를 보면 Hash List가 언제 생성되는지 추측해 볼 수 있다. Search 테스트를 보면 Hash List는 첫 번째 데이터를 조회할 때 생성된다고 볼 수 있다.

 1
을 조회하는데 StringList 0ms이 걸렸지만 HashedStringList 7250ms( 7)나 걸렸기 때문이다. 오히려 Insert를 한 시간보다 더 오래 걸린 것을 확인할 수 있다. 이것은 Hash List Insert하기 전 Hash Key를 생성하는데 드는 시간이라 볼 수 있다
.


 StringList
1부터 1500만까지 0을 하나씩 늘려가며 조회해 볼 때마다 시간이 점점 늘어나는 것을 확인할 수 있는데 이것은 단순 for루프를 이용해서 조회가 되기 때문이다. 그러나 HashedStringList Hash List가 생성된 이후 Hash Key를 이용해서 단번에 찾아가기 때문에 검색 시 검색어의 Hash Key를 생성하는 시간을 제외하고는 더 이상 검색하는 속도에는 시간이 들지 않기 때문에 매우 효율적인 검색이 가능하다.


 이러한 결과에 대해 소스를 확인해보면서 좀더 설명해 보도록 하자.

 

-          THashedStringList 소스

THashedStringList = class(TStringList)

  private

    FValueHash: TStringHash;

    FNameHash: TStringHash;

    FValueHashValid: Boolean;

    FNameHashValid: Boolean;

    procedure UpdateValueHash;

    procedure UpdateNameHash;

  protected

    procedure Changed; override;

  public

    destructor Destroy; override;

    function IndexOf(const S: string): Integer; override;

    function IndexOfName(const Name: string): Integer; override;

  end;

 

 소스에서 IndexOf IndexOfName만 오버라이드 했다는 것만 봐도 이 함수들에 대한 내용이   변경이 되었다는 사실을 알 수 있다. 또한 중점적으로 보아야 할 부분이 Value Name에 대해 Hash List가 있다는 것이다. 이것이 바로 검색 시 참조될 리스트 이다.


 
이 두 개의 리스트로 인해 생기는 단점은 메모리 사용량이 데이터 개수가 늘어날 때마다 함께 증가 할 수 있다는 것이다(검색 기능을 이용하지 않는다면 증가하지 않을 수도 있다.). 때문에 데이터가 매우 많다면 윈도우에서 한 프로세스가 소유할 수 있는 메모리가 2GB로 제한되어 있기 때문에 Hash List가 생성될 시점에 Out of Memory와 같은 메시지가 출력될 수도 있다는 문제점이 있다.


 
그렇다면 이 Hash List가 어느 시점에 생성이 되느냐가 중요할 수 있는데 보통 Hash Table은 데이터가 Bucket에 들어가면서 함께 업데이트가 된다. 하지만 앞서 테스트 예제와 같이 HashedStringList는 좀 달랐다. IndexOf IndexOfName을 통해 검색이 될 시점에 Hash List가 생성이 되도록 되어 있었다.

 그래서 Insert 통계를 보면 Hash Table을 생성하지 않기 때문에 일반 StringList HashedStringList가 거의 동일한 데이터 Insert 성능을 보여주었던 것이다.


 
소스를 확인해보시면 더 이해가 빠르리라 생각된다.

 

-          IndexOf 함수

function THashedStringList.IndexOf(const S: string): Integer;

begin

  UpdateValueHash;

  if not CaseSensitive then

    Result :=  FValueHash.ValueOf(AnsiUpperCase(S))

  else

    Result :=  FValueHash.ValueOf(S);

end;

 

-          UpdateValueHash 프로시저

procedure THashedStringList.UpdateValueHash;

var

  I: Integer;

begin

  if FValueHashValid then Exit;

 

  if FValueHash = nil then

    FValueHash := TStringHash.Create

  else

    FValueHash.Clear;

  for I := 0 to Count - 1 do

    if not CaseSensitive then

      FValueHash.Add(AnsiUpperCase(Self[I]), I)

    else

      FValueHash.Add(Self[I], I);

  FValueHashValid := True;

end;

 

 

IndexOf 소스를 보면 UpdateValueHash 프로시저를 호출하게 되는데 이 UpdateValueHash를 확인해보면 ValueHash List를 생성하여 Hash Table을 만들고 있다. 이 과정 때문에 초기 검색 시 매우 많은 시간이 소요되며 많은 데이터가 존재할 경우 아예 검색이 안될 수도 있는 상황이 발생할 수 있다. 실제 1억 건 정도의 숫자 스트링 데이터를 Insert Out of Memory 메시지가 출력이 되어 검색이 제대로 되지 않았다.


 
그리고 최대 단점은 Hash List Bucket이 데이터 수만큼의 배열로 관리가 되고 있기 때문에 한 건의 데이터가 추가되거나 삭제되어 바뀌더라도 배열을 새로 생성해야 한다는 것이다. 때문에 HashedStringList의 데이터가 변경(Add, Delete, Update)되면 다시 검색속도가 느려지는 치명적인 단점을 가지고 있다.


 
결론을 짓자면 HashedStringList를 사용은 변동이 없는 정적인 데이터들을 보관하고 그것들을 자주 조회하는 프로그래밍에 적합하다고 생각된다. 무조건 조회가 빠르다고 해서 사용했다간 오히려 StringList보다 더 많은 메모리를 사용하면서 성능의 이득조차 볼 수 없는 그런 상황이 되어버릴 수 있다. 하지만 적합한 환경에 사용한다면 엄청난 이득을 볼 수 있는 좋은 List란 생각이 든다.

조금은 다른 엑셈 채용 과정 이야기

엑셈 뉴스룸 2008. 7. 17. 20:51

사용자 삽입 이미지
최근 엑셈에서는 채용이 활발히 진행중이다.

지난 주, 무지하게 졸렸던 오후였다.
시원한 커피생각에 탕비실을 가다가 잔쯕 긴장한 채로 대기하던 면접자를 보았다.
그 모습을 보니 문뜩 엑셈에 들어오기 위해 치렀던 입사전형이 생각이 난다.

엑셈은 채용과정이 좀 다르다.

사용자 삽입 이미지
여타 다른 채용공고 처럼 채용 분야와 자격들에 대해 열거한 부분을 지나 채용 절차에 대해 설명한 부분을 보면 눈에 띄는 게 있다. 바로 면접 전까지 읽어와야하는 필독도서필 시청 동영상 목록이다.

하지만 왜 면접 때 이 책들을 읽고서 그리고 동영상을 보고서 들어가야 하는지 이해가 안된다.

도대체 왜일까?


그건 바로 같은 가치관을 공유할 수 있는 구성원을 뽑기 위해서이다.
사용자 삽입 이미지


펄떡이는 물고기처럼
에서
저자는 생동감 넘치는 일터를 만들어보자고 외치고,
행복학 강의로 유명한 해피어는 과연 성과위주로 남들과 무한 경쟁을 하면서 사는 것이 정말 행복한 인생인지 되묻는다.

임동창, 나는 우리 음악이 좋다는 회사생활과
무슨 상관이 있을까할 정도로 황당하지만, 방송을 보다보면 그 황당했던 감정은 나도 저렇게 열정적으로 살 수 있을까하는 반문으로 바뀐다.


이 쯤에서 엑셈에서 같이 일하고 싶은 사람들이 어떤 사람인지 알수있을 거다.
바로 무언가를 이루어나가는 과정에서 즐거움을 느끼고 적극적으로 사는 사람이다.

한 시간 넘도록 진행되는 1차 면접에서는 지원자가 어떤 가치관을 지닌 인재인지 확인 하기 위해 무수한 질문을 던진다.

"정말 행복하다고 느낄때는 어떤 때였습니까?"
"무엇을 하면서 살면 즐겁게 살수 있을 것 같으세요?"

그 질문에 답하고 또 꼬리를 무는 질문에 받다 보면 기술 면접이 아닌데 꽤나 진땀이 난다. 이러한 면접과정을 거치고 엑셈에 들어온 사람들은 다들 한 마디씩 한다.

"저 진짜 면접 보는 내내 '이 회사 도대체 뭐지?' 했어요."
 

인생에 있어서 행복과 즐거움에 대해 한 시간이 넘도록 이야기 하는 것이 과연 인재를 뽑는 과정으로 적합한가 라는 의문이 들 수도 있다.

정답을 찾기란 쉽지 않다.

하지만,

뭔가에 열중할 줄 알고 그 속에서 즐거움을 느끼는 사람들이 모인 조직은 개개인의 성장과 함께 튼실하게 커가게 된다고 믿는,
그리고 그런 사람들에게 무대가 되어줘야 한다고 믿는 조직에게는 꽤나 적합한 인재 찾기라고 생각된다.

[박성호]물리적 파일 처리가 당신을 괴롭힌다면

엑셈 사람들 2008. 7. 11. 10:10
최근 몇 년간 외부 성능개선 튜닝컨설팅을 나가 담당했던 파트가 온라인 프로그램(OLTP)이였었다.

그러던 와중 모 텔레콤사에서 수납관리 배치 프로그램 튜닝을 진행하게 되었다. 통신회사에서 수납관리라는 업무도 처음 접하는 것이였고, 배치 프로그램 또한 예전 포스코 튜닝그룹에서 일할 때 ERP 파트 튜닝을 진행하면서 겪었던 DW성 튜닝이 전부라 상당히 고전할 것으로 여겨져 은근히 부담이 많이 들었었다.

 

첨에 튜닝을 진행하기 위해서 고객사에 가서 수납관리에 관한 업무를 이해하고, 그 업무들에서 수행되는

프로그램들에 대해 친숙해 지는 과정을 거치며 업무를 수행하는 배치 프로그램들에 대한 튜닝을 실시하였다.

 

일반적으로, OLTP 프로그램(온라인)에 대한 튜닝을 진행하는데 중요한 성능개선방법은 국내에 나와있는 많은 책들에서 이미 소개된 것과 같이

 

-      인덱스에 대한 재조정

-      SQL 재 작성

-      힌트 조정

-      페이징 기법

-      Memory Keep

-      Parameter 조정

-      기타

 

등을 활용하여 프로그램의 일량을 최소화 할 수 있도록 효율적인 Access Path로 유도하는 것이 중요한 성능개선 방법이 될 것이다. 온라인 프로그램과 마찬가지로 배치 프로그램에서도 물론 위의 개선방법들을 많이 사용을 하게 된다.

하지만, 배치 프로그램을 계속 진행하면서 익히 알고 있는 다양한 성능개선방법으로만 튜닝을 진행 하는 것은 뭔가 알 수 없는 벽을 만난듯한 그런 느낌을 많이 받았다. 그런 벽의 존재가 기존에 일반적으로 널리 알려진 성능개선방법과 오라클에서 제안하는 다양한 신기술들이 접목이 되었을 때 배치 프로그램에 대한 성능개선이 좀더 잘 이뤄진다라는 그런 사실이 날 가로막고 있었던 거다.

 

오라클 제품이 버전 업그레이드 되면서 새롭게 등장하는 많은 신기술, 신기능들에 대한 지식이 필요하다라는 생각이~ 들게 했던 계기가 있었는데

물리 파일을 읽어 조회작업과 트랜잭션 처리(UPDATE)를 수행하는 프로그램 중 성능문제가 심각한 프로그램이 있어 이를 해결하기 위해 조치를 취한 방법으로 배치 프로그램(or DW) 튜닝을 지속적으로 해 오셨던 분들은 모두들 알고 있는 기능이겠지만 실제 적용을 해보지 않았던 분들에게는 생소한 기능들 중(나 역시도 한번도 접하지 않고 기능이 나온 지만 알고 있었던 ) 오라클이 9i 에서 첨 소개한 External Table이 있다.  External Table에 대한 정보를 찾고 적용하게 된 것은 아래의 그림과 같은 로직으로 수행이 되는 배치 프로그램이 있었고, 해당 프로그램은 수납관리 프로그램 중 아주 중요한 역할을 수행하고 수행시간이 아주 중요한 배치 프로그램으로 성능개선이 꼭 되어야 하는 핵심 프로그램 중 하나의 내용이다.

사용자 삽입 이미지


위의 배치 프로그램의 로직을 보면, 물리 파일에서 최대 300만 건을 한 건씩 읽어, 300만 건에 대한 한 건씩

UPDATE를 수행하는 프로그램으로 최대 300만 건 수행하는데 3~4시간이 소요되어 수행시간이 길었으며, 고객의 요구는 최대 30분 이내에 처리를 해달라는 것 이여서 상당히 고민에 빠지게 하는 배치 프로그램 이었다.

 

오라클 9i 이전에는 물리 파일에 있는 내용을 읽어 처리하는 조회작업이나 DML 작업(트랜잭션 처리)

경우는 Temp(임시 처리용) Table을 생성하고 SQL*Loader를 이용하여 DB Insert 한 이후 배치 처리하는

방법이 있을 것이고, 물리 파일(업무적인 병렬처리)을 읽어 배치 프로그램 로직을 수행(조회,DML작업)하는 방법이 일반적인 방법일 것이라 생각이 들었다.

그렇지만, 이 방법들은 식빵에 쨈을 발라서 먹지 않을 때 혹은 저녁을
먹을 때 반찬 중에 김치가 빠져 있을 때 느끼는뭔가 허전하고 뭔가 중요한 것이 빠져있는 느낌이 상당히 많이 들게 되었고 또한, 30분 이내에 배치 프로그램의 수행이 완벽히 끝낼 수 있을지 의문이 들었고 기존에 사용되던 방식들을 이용하여 30분 이내에 처리가 되더라도 업무적인 병렬 처리 등등의 처리를 활용하게 되면 프로세스간의 경합과 비효율적인 서버 자원을 사용하게 될 가능성이 많게 되고, 프로그램 수행을 하기 위한 관리적인 요소가 별도로 들어가야 할 것으로 판단되어, 오라클 DW 성능개선 방법들을 오라클 매뉴얼등등을 활용하여 문제의 배치 프로그램의 성능개선을 위한 좋은 방법이 있는지도 꼼꼼히 훑어보기 시작했다.

 

그러던 와중 ~ 이것이다.” 라는 기능이 있는 것이었다.
그것도 Oracle 9i에서 나온 기능 중에.

그것이 바로, External Table 이었다.

External Table
은 물리 파일의 처리에 대한 문제점을 해결하기 위해서 Oracle 9i에서 새로 나온 기능으로 문제의 배치 프로그램을 External Table + Merge Into ~ 구문을 활용하면 아주 괜찮은 성능개선이 될 것이라는 확신이 생겨났다. 또한, 이곳 ORACLE 버전이 10.2.0.3으로 10g부터는 Merge Into ~ 구문도 Upsert (UPDATE+INSERT)으로 작성하지 않고 UPDATE문만 처리하는 것도 가능하기에 문제의 배치 프로그램의 성능 개선방법으로 걸림돌이 되지는 않았다. External Table Merge Into~구문을 활용하여 배치 프로그램을 개선방법을 적용하여 아래와 같이 개선이 되었다.

사용자 삽입 이미지

물리 파일의 300만 건의 읽는 작업은 External Table을 활용하여 한번 읽는 작업으로 처리를 하고, 300만 건의 UPDATE 처리는 Merge Into ~ 구문에서 PARALLEL DML 처리로 하여 적용하였고, 개선 전에 300만 건 처리 시 3~4시간 소요되는 것이 적용 후 최대 15분 이내에는 처리가 완료되는 것을 확인할 수 있었다.

 

적용했던 사례는 아래와 같다.

 

먼저, 물리 파일을 읽기 위하여 UTL DIRECTORY에 물리 파일이 있는 DIRECTORY UTL_FILE_DIR 파라미터에 설정을 한다.

STEP1. utl directory에 위치시키기


SQL> show parameter utl

     

NAME                                    TYPE        VALUE

 -------------------------- ----------- ------------------------------

create_stored_outlines           string

utl_file_dir                             string      /usr/tmp, /usr/tmp, /app/oracl

                                                           e/product/10.2.0/db/appsutil/o

                                                           utbound/NDB2_cdb4, /usr/tmp

 

: /home1/var/lll/projs/if/work 폴더(물리적 파일위치) UTL_FILE_DIR 파라미터에 추가하여야 함.




그리고, 물리 파일을 읽어 들일 External Table을 생성한다.






STEP2. External Table 생성하기

 

- Directory 지정

    CREATE OR REPLACE DIRECTORY dat_dir AS '/home1/var/lll/projs/if/work ';

  CREATE OR REPLACE DIRECTORY log_dir AS '/home1/var/lll/projs/if/work ';

    CREATE OR REPLACE DIRECTORY bad_dir AS '/home1/var/lll/projs/if/work ';

    CREATE OR REPLACE DIRECTORY dat_dir AS '/usr/tmp';

    CREATE OR REPLACE DIRECTORY log_dir AS '/usr/tmp';

    CREATE OR REPLACE DIRECTORY bad_dir AS '/usr/tmp';

 

    GRANT READ ON DIRECTORY dat_dir TO 배치유저; à 프로그램 수행 유저

    GRANT WRITE ON DIRECTORY log_dir TO 배치유저;

    GRANT WRITE ON DIRECTORY bad_dir TO 배치유저;

 

- External Table 생성하기 

    CREATE TABLE TB_PAYMENT_UPDATE (

                            payment_data varchar2(180)

    ) ORGANIZATION EXTERNAL

    (

       TYPE ORACLE_LOADER

       DEFAULT DIRECTORY dat_dir

       ACCESS PARAMETERS

       (

         records delimited by newline

         badfile bad_dir:'ext_test%ar_%p.bad

         logfile log_dir:'ext_test%ar_%p.log'

         fields terminated by ','

         missing field values are null

         (

              payment_data

         )

       )

       LOCATION ('payment_update.dat')

    )

    PARALLEL 4

    REJECT LIMIT UNLIMITED

    ;

    ALTER TABLE 배치유저. TB_PAYMENT_UPDATE NOPARALLEL

/home1/var/lll/projs/if/work/payment_update.dat(물리 파일)을 읽을 준비는 다 되었다.









위에서 물리파일의 하나의 Row가 컬럼 구분자 없이 구성이 되어 있어, 물리 파일을 TB_PAYMENT_UPDATE라는






External Table로 불러들이게 되는데, 물리 파일의 한 Row(한줄)을 Payment_data 라는 하나의 Column으로 매칭을
 






시켜서 데이터를 가져와서 원하는 데이터를 자리수로 계산하여 잘라 필요한 데이터를 사용하게 된다. 물리 파일을 읽고,






물리 파일의 데이터를 업데이트하는 로직을 Merge Into ~ 구문을 활용하여 처리를 변경하여 최종 반영하게 된다.





STEP3. SQL 변경하기

 

개선 전 :

- FILE READ : MAX 300만건 à /home1/var/lll/projs/if/work/payment_update.dat (물리 파일)

     - UPDATE STATEMENT 수행 : MAX 300만번 수행됨.

      UPDATE TB_PAYMENT SET

             APPLICATION_ID         = :sql_application_id,

             WDRW_IMPSB_RSN_CD      = :sql_wdrw_impsb_rsn_cd,

             ATST_RETN_AMT          = to_number(:atst_retn_amt2),

             SYS_UPDATE_DATE        = SYSDATE

       WHERE WORK_YYMM  BETWEEN TO_CHAR(ADD_MONTHS(SYSDATE,-1),'YYYYMM')

         AND TO_CHAR(SYSDATE,'YYYYMM')

         AND BILL_ACNT_GRP_NO       = MOD(:sql_bill_acnt_no,20) + 1

         AND BILL_ACNT_NO           = :sql_bill_acnt_no

         AND ATST_BILL_SEQNO        = to_number(:atst_bill_seqno2)

         AND FILE_PRSS_NO           = :sql_file_prss_no

 

개선 후 :

- FILE READ : 테이블 두번 FTS로 해석 à Merge Into ~

- UPDATE   : Merge Into

~


MERGE /*+ USE_HASH(T B) */ INTO  TB_PAYMENT T

            USING ( SELECT /*+ LEADING(H P U) USE_HASH(H P U) FULL(H) FULL(P) FULL(U) */ à File 읽기

                                P.WORK_YYMM       ,  

                                P.BILL_ACNT_GRP_NO,   

                                P.BILL_ACNT_NO    ,                        

                                H.FILE_PRSS_NO    ,

                                P.ATST_BILL_SEQNO ,

                                P.WORK_DV_CD      ,

                                U.WDRW_IMPSB_RSN_CD,

                                TO_NUMBER(U.ATST_RETN_AMT) ATST_RETN_AMT

                          FROM  TB_PAYMENT P,

                              (

                                SELECT SUBSTR(PAYMENT_DATA,36,9) BILL_ACNT_NO, à 파일에서 해당 데이터 위치

                                       SUBSTR(PAYMENT _DATA,45,10) ATST_BILL_SEQNO,

                                       SUBSTR(PAYMENT _DATA,9,11) ATST_RETN_AMT,

                                       SUBSTR(PAYMENT _DATA,3,6) WDRW_IMPSB_RSN_CD

                                FROM  TB_PAYMENT_UPDATE

                                WHERE PYM_DATA LIKE 'RD%'  ) U,

                             (  SELECT SUBSTR(PYM_DATA,24,5) FILE_PRSS_NO

                                FROM  TB_PAYMENT_UPDATE

                                WHERE PYM_DATA LIKE 'RH%'

                              ) H

                         WHERE P.WORK_YYMM  BETWEEN TO_CHAR(ADD_MONTHS(SYSDATE,-1),‘

                                    YYYYMM') AND TO_CHAR(SYSDATE,'YYYYMM')

                           AND P.BILL_ACNT_GRP_NO   = MOD(U.BILL_ACNT_NO,20) + 1

                           AND P.BILL_ACNT_NO       = U.BILL_ACNT_NO

                           AND P.ATST_BILL_SEQNO    = U.ATST_BILL_SEQNO

                           AND P.FILE_PRSS_NO       = H.FILE_PRSS_NO

                       ) B

                ON ( -- PK로 해당건만 UPDATE -> ROWID 비교도 가능함.

                          T.WORK_YYMM        = B.WORK_YYMM

                      AND T.BILL_ACNT_GRP_NO = B.BILL_ACNT_GRP_NO

                      AND T.BILL_ACNT_NO     = B.BILL_ACNT_NO

                      AND T.FILE_PRSS_NO     = B.FILE_PRSS_NO

                      AND T.ATST_BILL_SEQNO  = B.ATST_BILL_SEQNO

                      AND T.WORK_DV_CD       = B.WORK_DV_CD

                )

                WHEN     MATCHED THEN

                         UPDATE SET  T.APPLICATION_ID         = :sql_application_id,

                                        T.WDRW_IMPSB_RSN_CD  = B.WDRW_IMPSB_RSN_CD ,

                                        T.ATST_RETN_AMT        = B.ATST_RETN_AMT,

                                        T.SYS_UPDATE_DATE      = SYSDATE










개선내용확인하기 - SELECT 처리 TEST 결과 (FILE READ -> UPDATE 대상 선별)

 

call     count       cpu    elapsed       disk      query    current        rows

      ------- ------  -------- ---------- ---------- ---------- ----------  ----------

      Parse        1      0.06       0.05          0        663          0           0

      Execute      1      0.00       0.00          0          0          0           0

      Fetch    68321     38.02      44.25          0      95293          0     1024792

      ------- ------  -------- ---------- ---------- ---------- ----------  ----------

      total    68323     38.08      44.31          0      95956          0     1024792

     

      Misses in library cache during parse: 1

      Optimizer mode: FIRST_ROWS

      Parsing user id: 427

     

      Rows     Row Source Operation

      -------  ---------------------------------------------------

      1024792  FILTER  (cr=96701 pr=0 pw=0 time=40230686 us)

      1024792   HASH JOIN  (cr=96701 pr=0 pw=0 time=40230278 us)

      1024792    EXTERNAL TABLE ACCESS FULL TB_PAYMENT_UPDATE (cr=704 pr=0 pw=0 time=7209313 us)

      1194024    HASH JOIN  (cr=95997 pr=0 pw=0 time=18037752 us)

            1     EXTERNAL TABLE ACCESS FULL TB_PAYMENT_UPDATE (cr=704 pr=0 pw=0 time=7288229 us)

      1194024     PARTITION RANGE ITERATOR PARTITION: KEY KEY (cr=95293 pr=0 pw=0 time=8359986 us)

      1194024      PARTITION LIST ALL PARTITION: 1 20 (cr=95293 pr=0 pw=0 time=7165527 us)

      1194024       TABLE ACCESS FULL TB_PAYMENT PARTITION: KEY KEY (cr=95293 pr=0 pw=0 time=7168107 us)




외부 성능개선 컨설팅 중 발생했던 배치 프로그램의 문제를 접근하는 방향이 익히 알고 있는 성능개선 방법뿐만 아니고
 




잘 사용되지 않는 오라클 기술들을 잘 활용하면 문제 접근이 의외로 쉬울 수 있고, 성능개선 효과 또한 아주 큰 경우가 많






이 있을 것으로 생각된다. 오라클 버전 업그레이드 되고, 오라클이 신기술(New Feature)발표하면 이러한 기술들을 최






소한 그 기능이 어떻게 활용이 되면 좋을지 그리고, 향후 적용할 수 있는 영역이 어딘지 등등에 대해 고민하는 것도 아주
 





좋을 것 같다.








아스터! 시작에서 탄생 Story

엑셈 뉴스룸 2008. 6. 25. 16:34
사용자 삽입 이미지
사용자 삽입 이미지

  • orion 2008.07.23 13:02 ADDR 수정/삭제 답글

    정말 고생이 하면서 만든 캐릭터 ㅜㅜ
    그만큼 애정도 큰~++
    아스터 머그컵이 빨리 나왔으면 좋겠어요ㅋㅋ

  • 이명진 2008.07.23 14:33 ADDR 수정/삭제 답글

    저도 빨리 받고 싶습니다~ 만드느라 고생많이 하셨습니다.^^