StringBuffer의 setLength에 의한 초기화

|

참 오랜만에 글 쓴다. 게다가 뜬금없이 Java에 대한 포스팅...
(스리슬쩍 어투도 반말로 전환..-_-;)

발단은 아래 글 때문이다.

http://gall.dcinside.com/list.php?id=programming&no=110315&page=7 
 
요약하면 어떤 네이버 블로그의 포스팅을 까는 건데 그 블로그는 요기.

http://blog.naver.com/damduck01/130025921363 

대충 까는 요지는 두 가지이다.

1. 객체 변수를 null로 초기화 시켜놓고 오퍼레이션을 하려고 하는게 당연히 문제다.
2. setLength를 써서 초기화 하는 건 잘못된 정보다.

1번은 누가 봐도 문제다.
근데 블로그 주인장이 글을 나중에 고쳤는지는 모르겠지만 블로그에도 1번은 실수담으로 적어 놓은 것이며(본인도 문제가 된 이유는 포스팅 쓸 당시에는 잘 몰랐던 것 같지만) 그걸 정보라고 제공한다고 쓴 글이 아니다.

그러므로 글이 나중에 수정된게 아니라면 이건 까는 놈들의 국어실력의 문제이며 비판할 이유가 전혀 없다. 그러므로 이건 패스.

문제는 2번인데...

DC의 pupustory라는 아이디가 얼마나 대단한 개발자인 지는 모르겠지만 어쨌든 Java에 대한 지식은 어느 정도 있어 보이고 댓글의 내용을 종합해 보면, setLength는 저런 용도(사용 중이던 StringBuffer를 초기화 하는 용도)로 쓰는 것도 아니며, 저런 경우에는 new StringBuffer()로 해주는게 좋다고 써놨다. 다른 사람이 delete를 쓴다는 의견도 냈지만 이건 pupustory 말마따나 비효율적이고... 
근데 남의 방법은 비효율적인 줄 알면서 본인의 방법은 비효율적인지 잘 모르는 듯...-_-;
이 경우에는 생각만큼 delete가 비효율적이진 않다. 오히려 pupustory의 방법이 제일 비효율적이다 -_-; 일단 이유는 아래에서...


StringBuffer

일단 StringBuffer란게 생긴 이유는 Java의 문자열이 수정 불가능한 객체이기 때문이다. 그러므로 StringBuffer이란 객체를 써서 내부에 char 배열을 갖고 문자열이 추가됨에 따라 이 배열을 확장시켜 가며 최종적으로 String으로 변환시킴으로써 중간의 문자열 추가에 대한 오버헤드를 줄이기 위한 목적으로 만들어졌다.

StringBuffer 객체가 생성되면 대략 아래와 같은 구조를 갖추게 된다.

{
char value[16];
int capacity;  // 16
int length; // 0
}

특정 프로그래밍 코드가  아니니 그냥 가볍게 읽으시길.
간단하게 말하면 실제 데이터를 저장할 배열이 초기 길이 16으로  세팅되고 배열의 길이를 표시하는 capacity라는 변수가 있고(역시 16), 실제 데이터의 길이를 저장하는 length라는 변수가 있다(처음이므로 당연히 0).

그리고 append 등으로 문자열이 추가 될 때마다 length값이 늘어나게 된다.
그래서 16을 넘어가게 된다면? 배열 크기를 늘린다. 대략 두 배 크기로 늘리게 되므로 대충 아래처럼 바뀐다.

{
char value[32];
int capacity;  // 32
int length; // 17
}

사용하는 동안 이런 식의 과정이 반복되며 늘 필요한 수준 이상의 char 배열을 확보한 채로 동작하게 된다.


delete, new StringBuffer(), setLength 

그럼 delete를 하는 경우를 생각해 보자. delete 메써드의 기본 목적은 추가한 문자열 중 잘못된 부분을 삭제하는 것이다. 그렇기 때문에 중간의 문자열을 삭제하는 경우 그 뒷쪽의 문자열을 삭제한 부분에 복사해 채워넣는다. 여기까지는 pupustory의 말이 맞다.
하지만 이 경우는 전체 삭제이므로 그럴 바에는 new로 초기화 하겠다고 써놨는데 그야말로 하나만 알고 둘은 모르는 소리다.

전체 문자열에 대해 delete할 경우 뒤의 문자열을 카피하고 말고 할 것도 없으므로 length를 0으로 만들어 버리고 끝난다.
그러므로 delete를 주장한 놈은 내부적으로 setLength랑 똑같은 일을 하는 코드를 쓰면서 setLength 쓴 놈을 욕하는 꼴이고(제주 항공 타면서 진에어 무시하는 격), pupustory는 어레이 카피가 일어난다는 것만 생각하고는 delete도 살짝 무시하고 있는 것이다.

그럼 setLength(0)은 초기화의 의미가 있는가? 물론이다. 사용하는 데이터의 길이를 0으로 세팅하므로 배열의 길이 자체는 늘어나 있더라 할 지라도 논리적으로는 그냥 저장된 문자열이 없는 상태에서 처음부터 다시 쓰는 것이고 length 이후의 배열에 저장된 데이터를 가져다 쓸 일도 없으므로 기존에 무슨 데이터가 들어 있었는 지도 상관이 없다. 더더군다나 그 배열은 객체 외부에서 접근도 불가능하다. 이게 객체지향의 장점 아닌가?

pupustory라는 하나만 알고 떠드는 시키는 'setLength는 저렇게 쓰는게 아니지'란 식의 덧글을 달았던데 그럼 도대체 언제 쓴단 얘긴지?
Java API 문서에는 "setLength의 인자가 현재 length보다 크면 나머지 부분을 null 캐릭터로 채우며 작은 경우 length만 새로 바뀐다. 인자는 반드시 0 이상이어야 한다" 요약하면 이 정도로 써 있다. 못 쓸 이유가 전혀 없는데 도대체 어디서 줏어듣고 까부는 건지? -_-;;;

그럼 pupustory가 주장한 new StringBuffer()는?
적어도 초기화를 위해서 가장 확실해 보이기는 한다. 하지만 리소스를 재생성하는 것에는 언제나 오버헤드가 뒤따른다. 서버에서 쓰레드 풀이라든가 커넥션 풀같은 기능을 사용하는 이유는 새로 만드는 데에 그만큼 비용이 들기 때문에 커넥션 객체나 쓰레드를 새로 만들지 않고 재사용해서 새 것처럼 쓰는 것이다.
StringBuffer도 마찬가지다. 여러 번 자주 써야 하는 경우라면 setLength(0)을 사용하는 것이 객체 자체를 새로 만드는 것보다 아마 몇십배 이상 효율적일 것이다. 게다가 내부 배열도 어느 정도 크기를 갖고 있는 상태이므로 확장 비용도 들지 않는다. 배열이 차지하는 메모리가 아깝다면 역시 객체 재생성보다는 trimToSize() 메써드를 쓰는게 더 효율적이다.

그러므로 잘난 체 하던 인간이 주장하던 바는 실제로는 가장 비효율적인 방법이 된다. 

본인이 주장하던 '인터넷에 잘못된 정보는 정말 무서운 거다'란 말을 되돌려주고 싶다.
Java API 같은 걸로 남을 까기 전에 최소한 소스나 문서 정도는 확인하자. 
저작자 표시 비영리 변경 금지
Trackback 0 And Comment 2

주5일제에 대한 단상

|

그동안 회사를 자주 옮겨서 벌써 네 번째 회사를 다니고 있는데... 지금은 구직 상태는 아닙니다만 그래도 프로그래밍 커뮤니티에 올라 오는 구인 글들을 가끔 훑어보게 됩니다.

그런데 드물지 않게 '근무 조건'내지 '복지'란에는 '주 5일' 혹은 '4대 보험' 같은게 들어가 있는 회사가 많습니다.
그냥 제공하는 복지가 없는 거죠. 저런 거 좀 쓰지 마세요...-_-;; 특히 4대 보험은 제공 하지 않으면 그게 악덕 업주에 불법이지 무슨 복지입니까...

그나마 IT 쪽에서는 일반화가 됐다고는 하지만 주5일제 자체는 아직 전반적으로 실행된다고 보기는 힘들죠.

제가 첫 번째 다닌 회사는(2002년 말 취업) 10명 내외의 작은 회사였는데, 그 때는 그 회사 사장님이 정말 주 5일이 엄청난 혜택인 양 목에 힘을 주셨죠 -_-;
다른 혜택은 저녁 식대를 제외하고는 전혀 없었구요... 나중에 월급이 6개월 밀리기도 했죠 -_-
우리 나라 회사들의 특징은 '삼성 따라하기'를 좋아하는 회사가 많다는 점인데 그 회사도 월급 밀리기 전까지 회사가 커지기 위한 준비를 해야 된다면서 뜬금없이 회사 내규를 만들고 근태 관리 한다면서 출근 제 시간에 하라는 압박을 하고는 했죠(그 이후로 지금까지 그 회사는 계속 작은 회사입니다). 내규를 정비해 지각 3회는 결근으로 처리한다고 압박을 하면서...-_- 아쉽게도(?) '그럼 야근 수당 주세요'라는 모 대리님 말씀에 갑자기 흐지부지 됐지만...;

두 번째 다닌 회사는 100명 정도 됐는데 꽤 잘 나가던 회사였습니다. 지금은 망했죠.
그리고 제가 다녀 본 유일한 주 6일제(토요일 격주 휴무) 회사였습니다. 사실 지금 생각하면 크게 나쁘지는 않았던 것 같아요. 일단, 토요일은 일하는 분위기가 아니었고 팀끼리 영화를 본다든가 체육 활동을 하거나, 회사에 있어도 별로 일에 치이는 분위기는 아니었으니까요. 게다가 월차가 존재했기 때문에 연차가 아니라도 매달 하루는 눈치 안 보고 쉴 수 있는 장점도 있었고요.
그 회사의 아이템은 나름 초기엔 혁신적이었는데 그 혁신을 계속 유지하지 못해서 결국 망했습니다만... 제가 다니던 중간에 주 5일제를 도입했는데 정말 엄~~~청 생색을 내더군요 -_-; 경쟁사는 아직도 다 격주 휴무인데 우리만 주 5일제를 갑자기 하게 됐다는 둥... 마인드는 별로 혁신적이 아니었죠.

다른 에피소드지만 그 회사도 무지하게 관리하기를 좋아했는데 심지어는 회사의 상무가 '캠페인을 제안합니다'라는 제목으로 메일을 보냈는데 메일 내용이 가관이었죠. 출근시간 지키자는 거랑 출입문 열어놓고 다니지 말자는 거, 지키지 않는 사람에겐 무슨 불이익이 돌아갈 거라는 거... 세상에 이런 캠페인이 어딨습니까? -_-; 갈구는게 캠페인이라면 연대장 지시사항은 죄다 캠페인이게요 ㅡ.ㅡ;
음, 그 외에 직원들에게 도서구입비도 지원해 줬는데 나중에는 인터넷 도서 구입 영수증 시간이 업무 시간이라고 태클 걸고 뭐 그러기도 했죠...-_-; 업무 시간에 주식 사이트랑 쇼핑몰 사이트 다 막아버리기도 했고...

그 이후로 다닌 회사들은 외국계들이라 주 5일이 당연했습니다만...
여튼 생각해 보면 고용주들은 직원들이 노는 꼴을 못 보는 것 같습니다 -_-; 뭐, 일을 다 내팽개치고 노는 건 문제가 있긴 하지만 과도한 압박은 생산성도 생산성이고 개개인의 삶의 질에도 별로 좋은 영향을 끼치지 않죠.

다른 회사들은 어떤지 궁금하네요. 여튼 주 5일제나 4대보험을 구인 조건으로 내세우는 회사는(그것도 장점인양) 그만큼 내세울게 없다는 얘기가 아닐까 하네요. 그냥 '남들 하는 만큼은 마지 못해 해줘' 이렇게 보입니다.
저작자 표시 비영리 변경 금지
Trackback 0 And Comment 0

NEIS 프로그램 오류에 대한 허접(?) 기사

|
또 무지한 기사 까는 글을 올리게 됐군요 -_-;

http://news.chosun.com/site/data/html_dir/2011/07/25/2011072500100.html
 
확신할 순 없지만 기사로 미루어 보건대, 아마도 프로그래밍 카페에도 자주 올라오는 단골 질문 중 하나인 부동 소수점 연산을 함부로 써서 문제가 생긴 것 같네요.

부동 소수점 연산은 일반적으로 프로그래밍 언어에서 흔히 지원하는 float나 double 타입을 이용한 연산을 가리키는데 물론 이 타입들이 소수 연산에 쓰라고 만들어 놓은 건 사실입니다만, 소수점 이하 부분의 정밀도가 요구되는 작업에는 '절대' 쓰면 안 됩니다. 이걸로 계산한 결과 올려놓고 Java의 버그니 C의 버그니 하는 분들도 간혹 계신데 그러지 마세요 -_-;

자세하게 설명하면 매우 길어지지만 왜 정밀도 문제가 생기냐 하면 위에 언급한 타입들은 소수도 '2진수'로 저장하기 때문입니다.

예를 들어보죠. 편의상 왼쪽은 2진수, 오른쪽은 10진수입니다.

0.1 = 0.5
0.01 = 0.25
0.001 = 0.125
0.0001 = 0.0625
...

그럼 10진수 0.6 을 2진수로 나타내면? 벌써 머리 아픕니다 -_-;

결국 2진수로 나타낸 소수는 아무리 자릿수가 내려간다 한들 1/2의 지수승이 반복되는 것 뿐이므로 10진수로 된 소수를 완벽하게 표현하기가 힘들어집니다(좀 더 자세한 설명은 더 하기 힘들고, 부동소수점과 IEEE-754를 검색해 보세요).

직업 프로그래머인데 위의 사실을 몰랐다면? 본인의 자질을 의심해 보심이...-_-;

하여튼 설마 그럴 리는 없지만, 치명적인 소수점 데이터를 기본 타입인 float나 double로 다뤘다면 위 기사처럼 프로그래머들이 욕 먹어도 마땅하긴 합니다만, 다른 문제는 따로 있습니다.

일단은 제대로 된 QA 프로세스가 부재했음이 더욱 결정적인 이유 같은데 기사에는 그런 점은 없고 개발자의 문제로 호도하는 경향이 좀 강하네요. 프로그래밍은 '코딩'만으로 이루어지지 않습니다. 설계 및 디자인, 코딩, 디버깅, 테스팅 및 검증이 모두 어우러져야 제대로 된 결과물이 나옵니다. 그리고 테스팅과 검증은 개발자만의 책임이 아닙니다. 저희 회사도 그렇고 많은 회사들이 테스터의 OK 사인이 나지 않은 소스는 릴리즈에 포함시키지도 않습니다.

역시 추측이지만 결국 고객의 압박과 시간에 쫓겨 제대로 된 테스팅과 검증이 이루어질 수 없지 않았나 하는 생각이 드네요. 이미 트위터에서는 '개발자에게만 책임을 지우느냐'는 반론이 많이 퍼지는 듯 합니다.

그리고 약간 다른 관점에서는, '아웃소싱', 즉 외주가 정답인가 하는 것입니다. 한국처럼 무식하게 SI 하는 나라는 아마 한국밖에 없을 것입니다 -_-; 프로젝트 하는 동안 우~~ 모여서 코딩하고 프로젝트 끝나면 유지보수 인력 말고는 또 다 빠져나가버리는 그런 식의 구조에서 얼마나 제대로 된 결과물이 나올까요?

KTX나 테크노 마트 등등 해마다 불거지는 부실 논란 만큼이나 S/W 쪽도 이대로는 영원히 부실 논란을 피하지 못할 것 같습니다.

덧붙여, 기사 말미의 '쓰레기값'에 대한 설명은 그야말로 지나가던 소가 웃을 설명을 써놨네요...-_-
원인이 밝혀지지는 않기는 개뿔... 무슨 자동차 자동 기어 급발진 사고인가 -_-

 
저작자 표시 비영리 변경 금지
Trackback 0 And Comment 0
prev | 1 | 2 | 3 | 4 | 5 ... | 56 | next