Emacs Lisp에서 setq와 setq-default의 차이

Emacs // 2024년 06월 22일 작성

Emacs를 세팅하다 보면 생소한 느낌의 단어를 자주 사용하게 되는데 그 중에 setqsetq-default의 차이에 대해 알아보자.

버퍼 로컬 변수 개념

Emacs에는 '버퍼 로컬(buffer-local) 변수'라는 특별한 개념이 있다. 마치 해당 버퍼에 종속되는 전역 변수와 비슷한 느낌으로 설명할 수 있다.

예를 들자면 tab-width 가 대표적이다. 이 변수는 들여쓰기의 크기를 설정하는 변수로 각 버퍼의 메이저 모드마다 이 변수의 값이 다 다를 수 있다. 버퍼에 속한 로컬 변수이기 때문이다. 하지만 기초 값으로 사용되는 전역 변수도 따로 있다.

이 '버퍼 로컬 변수' 개념만 이해하고 있다면 둘의 차이는 쉽게 구분할 수 있다.

setq

setq명령어는 Set eQual의 약자로 다른 언어에선 대입(assign)과 비슷한 의미의 명령이다. 이 명령은 만약 로컬 변수가 있다면 해당 변수의 값을 지정하고, 로컬 변수가 없다면 전역 변수에 지정하는 방식으로 동작한다.

(setq tab-width 8)

위 코드는 현재 버퍼의 들여쓰기 레벨을 8로 설정하는 명령이다. 하지만 다른 메이저모드 버퍼에는 적용되지 않는다. 왜냐하면 tab-width는 앞서 이야기 했다시피 버퍼 로컬 변수라는 특수한 변수이기 때문이다.

setq-default

setq-default는 버퍼 로컬 변수를 생략하고 무조건 전역 변수의 값을 지정하는 용도로 사용된다.

(setq-default tab-width 8)

위 코드는 현재 버퍼가 아니라 모든 버퍼에서 참고하는 기본 들여쓰기 레벨을 설정하는 코드다. 따라서 새롭게 만들어지는 버퍼는 모두 이 값을 참조하여 들여쓰기 레벨을 결정한다. 물론 이후 setq로 해당 버퍼 로컬 변수의 값이 바뀔 수는 있겠지만 말이다.

사족

default라는 이름에 집중하면 왠지 조금은 더 이해가 잘 되는 것 같다. 즉 기본값(default value)을 설정하기 위한 용도로 setq-default가 쓰이는 것 같다. 뭔가 대단한 일을 하는 함수 같다.

그렇다고 해도 보통 Lisp 코딩에서는 setq가 압도적으로 많이 쓰인다. 로컬 변수에서도 사용하니 당연하다. 오히려 setq-default를 쓸 일은 그다지 많지 않을 수도 있다.