성급한 널 처리의 오류
절대 죽지 않는 프로그램을 짜고 싶었습니다. 널 처리만 잘하면 된다고 생각했습니다.
프로그램이 죽는 이유의 대부분이 널 포인터를 건드리는 경우였으니까.
첫 회사에 입사해서 윈도우 클라이언트 프로그램을 부여받았습니다.
맨티스라는 도구에 버그가 올라오면 내가 고칠 수 있는 게 있을까 신이 나서 찾아 고쳤습니다.
대부분 널 포인터만 감싸면 고쳐지는 에러였습니다.
26살의 신입사원답게 아주 재빨랐습니다.
재현 후 디버거를 붙여서 값이 널로 들어온다? 오케이, 찾았군.
바로 널 체크 코드를 추가했습니다.
if (pData == NULL)
return;
그리고 다시 재현해 보고 더 이상 죽지 않으면 Fixed
로 변경.
아~ 코딩 참 쉽다.
저는 이걸 성급한 널 처리의 오류라고 부르고 싶습니다.
경험이 쌓이면서 이게 그리 쉬운 문제가 아니라는 걸 알았습니다.
이렇게 널과 널 체크를 남용하면 프로그램이 죽지는 않더라도 버그를 영영 감추는 꼴이 되어버리고 맙니다.
절대 죽지 않는 프로그램보다 문제가 생기면 곧장 죽는 프로그램이 오히려 낫다는 걸 시간이 지나고서야 깨달았습니다.
감춰진 버그는 나중에 결국 나에게 돌아온다는걸.
ASSERT(pData);
ASSERT 같은 코드를 왜 쓰는지도 그쯤에야 깨달았습니다. (학생 때는 도무지 이해가 되지 않았습니다)
알게 된 후로는 적극적으로 사용했습니다.
이후로는 변수가 널이어야 하는 경우와 절대 널이어선 안 되는 경우를 엄격하게 구분하기 시작했습니다. 애초에 널 상태를 만들지 않으려 애썼습니다.
변수를 처음 선언할 때부터.
DB 스키마를 만들 때부터.
서버에서 클라이언트에 데이터를 내려줄 때도 함부로 null 을 사용하지 않았습니다.
이렇게 하면 그걸 받아서 쓰는 애플리케이션 쪽에서 고민거리가 줄어들므로 코딩이 편해집니다.
C/C++처럼 낡은 언어와는 다르게 요즘 언어들은 nullable 혹은 optional 타입 기능을 제공하는 것 같습니다.
저는 C#에서 이걸 처음 봤는데, 최근 언어는 다 탑재하고 있더라고요.
가끔 귀찮다는 느낌이 들 때도 있긴 하지만… 귀찮다고 느껴질 때는 널을 다뤄야 할 때입니다.
애초에 널을 건네주는 곳이 없다면 귀찮을 일도 생기지 않습니다. 이 기능에 대해 호불호가 있지만 저는 선호하는 쪽입니다.
함께 읽으면 좋은 글: