Clean Code?
중복 제거, 코드 표현력, 설계 단계에서 간단한 추상화. 끝.
클린 코드의 원서는 다음과 같습니다.
2009. Clean Code: A Handbook of Agile Software Craftsmanship. Prentice Hall.
아니, 2009년에 나온 책의 코드 기법을 왜 읽으시려고 합니까? 말 많은 서적이기도 하던데요?
라고 말할 수도 있겠지만.. 일단은 프로젝트를 진행하기 전 코드 컨벤션이야 미리 정하고들 시작은 합니다. 하지만, 막상 이런 걸 정하고 시작한다 하더라도 결국 개개인의 코드 습관으로 인해 어쩔 수 없이 코드가 난잡해집니다. 물론 컨벤션이야 대부분 클래스/메서드/변수 작명 규칙이 대부분이긴 합니다. 코드 습관을 고치기 위함이 첫 번째.
실제로 이 책의 저자인 로버트 C. 마틴(밥 아저씨(이젠 할아버지)) 역시 1장에서 논쟁의 여지가 있을 것이라 언급하고 있습니다. 그럼에도 이 책을 읽으려고 하는 이유는 한 분야의 전문가가 쌓아온 경험과 교훈들을 얻어가기 위함입니다. 이것이 두 번째.
그리고 일부러 번역 어투를 이렇게 한 건지 궁금해서 원문을 찾아봤는데 원문 어투도 상당히 유머러스합니다. 제가 쓰는 글 스타일이랑 유사해서 더 읽고 싶은 마음도 있긴 합니다. 좀 더 실용적인 책은 이펙티브 자바류의 서적이긴 하겠지만? 취준 하면서 가볍게(?) 읽을만한 글거리가 필요했습니다.
책 리뷰를 시작하게 된 이유
리뷰를 가장한 복붙 수준의 글들을 싫어하는 편이라 Book Review 게시판에 올라오는 글들은 보고 느낀점 정도로만 올라올 것 같습니다. 개발 서적 리뷰는 지난 프로젝트 코드들에 적용할만한 게 있다면 그런 부분을 고쳐보는 정도로 리뷰할 것 같습니다. 사실 이 책은 예전에 42 Seoul 하는 친구가 추천해 줘서 훑어본 적이 있긴 한데 꽤 오래됐습니다.
...
사실 자소서를 쓰다가 들여쓰기와 개행을 해야 하나 말아야 하나 계속 고민하고 있었는데 여기서 인덴트가 갑자기 궁금해져서 말이죠.
그럼 살짝 들여쓰기에 대해서 알아볼까요? 사실 클린 코드 111페이지부터 잠깐 들여쓰기에 대해 언급하긴 하지만, 여기까지 알아본 사람은 없을 것 같습니다. 있다면 말고요.
Indentation
음, 이런 식으로 글쓸거면 유튜브 채널 하나 만들어서 영상화하면 괜찮긴 할 텐데 전 텍스트 미디어를 선호하는 편입니다. 영상은 보기가 귀찮습니다. 눈과 귀를 둘 다 사용해야 하고 원하는 정보를 빠르게 찾을 수가 없어서... 아무튼 어디까지 거슬러 올라가야 하느냐. 기계어 다음을 보면 되겠죠? 최초의 프로그래밍 언어인 어셈블리어. 학부생 시절에 어셈블리어 과목을 수강했는데 마침 들여쓰기를 썼었던 기억이 있습니다.
그런데 초기의 어셈블리어는 명령어와 데이터를 특정한 메모리 주소와 레지스터에 할당하는 방식으로 작성되었고, 각 명령어가 컴퓨터의 하드웨어와 1:1 대응되는 매우 단순한 구조를 가지고 있었습니다. 들여쓰기 없이도 컴퓨터는 명령어를 정확하게 이해할 수 있었기 때문에, 들여쓰기는 처음부터 존재하지 않았습니다.
MOV AX, 1
ADD BX, AX
JMP 0040h
코드는 직선적인 명령어의 나열로 작성되었으며, 들여쓰기는 컴퓨터가 해석하는 데 영향을 주지 않았습니다. 하지만 코드가 복잡해지고 더 많은 명령어와 데이터가 포함되면서, 개발자들은 코드의 가독성을 높이기 위해 들여쓰기를 사용하기 시작했습니다. 인덴트의 창시자!가 있지 않을까 하는 기대감에 찾아봤지만 없었습니다..
section .data
msg db 'Hello, world!', 0
section .text
global _start
_start:
; write 'Hello, world!'
mov eax, 4 ; syscall number for sys_write
mov ebx, 1 ; file descriptor 1 (stdout)
mov ecx, msg ; message to write
mov edx, 13 ; message length
int 0x80 ; make kernel call
; exit
mov eax, 1 ; syscall number for sys_exit
xor ebx, ebx ; return 0
int 0x80 ; make kernel call
... "그 당시 개발자들이 자발적으로 가독성과 유지보수성을 높이기 위해 사용했다." 정도로만 생각하면 될 것 같습니다. space 2칸/4칸이니 탭이니 하면서 인덴트에 대한 깊은 철학이 있지 않을까 싶었는데요. 그런 건 없었던 것 같습니다. 하지만 고급 프로그래밍 언어가 등장하게 되면서 코드 블록에 대한 개념이 생겼습니다.
Code Block
조금 생소할 수도 있는데 Algol(1958)이라는 언어에서 코드 블록을 구분하는 구조적인 개념을 처음 도입하였습니다. 그러나, Algol에서는 중괄호 {}가 아닌 begin과 end를 사용하여 블록을 구분했습니다. MySQL 프로시저 작성할 때 사용해서 익숙한 구조죠?
begin
integer i;
for i := 1 step 1 until 10 do
begin
x := x + 1;
end;
end
그러면 중괄호는 언제부터 사용하게 됐나요?
BCPL(Basic Combined Programming Language, 1967)이 중괄호 {}를 처음으로 코드 블록을 구분하는 데 사용한 언어입니다. C 언어의 직계 조상이며, 코드 블록을 {}로 감싸는 방식을 도입했습니다.
LET N = 100
WHILE N > 0 DO {
WRITE(N);
N = N - 1
}
그 다음 C 언어(1972)가 BCPL의 영향을 받아 중괄호 {}를 사용해 블록을 구분했습니다. C 언어는 구조적 프로그래밍을 쉽게 구현할 수 있는 언어로, 중괄호 블록 구조가 많은 프로그래밍 언어에 영향을 미쳤습니다.
int main() {
int i;
for (i = 0; i < 10; i++) {
printf("%d\n", i);
}
return 0;
}
들여쓰기가 필수적인 언어
자, 여기까지는 들여쓰기가 코드의 가독성을 위해 사용된 언어들이었습니다. 하지만 들여 쓰기가 문법적으로 필수적인 언어가 있죠? Python과 Haskell을 예로 들 수 있겠습니다. 들여쓰기가 문법의 일부로 간주되며, 코드 블록을 구분하기 위해 필수적인 역할을 합니다. 들여쓰기가 없거나 잘못된 경우, 프로그램이 구문 오류를 발생시키며 실행되지 않습니다. 이러한 언어에서는 들여쓰기가 코드의 논리적 구조를 표현하는 데 매우 중요한 요소입니다.
Python
def example():
for i in range(5):
print(i) # 올바른 들여쓰기
print("done") # 들여쓰기가 어긋나면 오류 발생
Haskell
main = do
let x = 5
y = 10 -- 수평 정렬이 중요
print (x + y)
YAML
person:
name: John # 들여쓰기 사용
age: 30
Makefile
target:
gcc -o myprog main.c # 들여쓰기 필수 (탭 사용)
리뷰를 마치며
뭔가 다른 길로 빠진 느낌이 있긴 한데 인덴트도 클린코드의 한 요소니까.