컴퓨터에서 돌아가는 프로그램들에는 각각 current directory라는 개념이 있다. 그래서 파일이나 디렉터리를 지정할 때 매번 드라이브 또는 볼륨의 이름부터 쓰는 게 아니라 그걸 생략하고 이름만 달랑 적거나, ..₩ 처럼 간편하게 ‘상대 경로’를 지정해 줄 수 있다.
기술적으로 봤을 때 current directory는 프로세스 전체 단위로 공유되는 속성이다. 스레드 단위가 아니다.
한 디렉터리 아래에 있는 모든 파일과 디렉터리를 조회하는 건 보통 SetCurrentDirectory를 이용해서 함수의 재귀호출로 구현하는 편인데(이름을 줘서 하위 디렉터리로 갔다가 앞으로 되돌아갈 때는 간편하게 ".."만 지정하면 됨), 이건 여러 스레드가 동시에 수행되지 않게 해야 한다.
여러 군데에서의 디스크 수색을 굳이 동시다발적으로 하려면 해당 함수가 경로 문자열 관리를 자체적으로 해서 FindFirstFile에 언제나 절대경로만 전해 주거나, 아니면 상대 경로를 쓸 거면 아예 별도의 프로세스를 만들어서 돌리게 해야 한다.
그런데 여기서 한 가지 의문이 생긴다. 각 드라이브별로 직전까지 작업하던 디렉터리 정보가 운영체제 차원에서 자동으로 보존될까, 그렇지 않을까?
C:\Windows>d:
D:\>cd doc
D:\doc>c:
C:\Windows>d:
D:\doc>
드라이브별 커런트 디렉터리란, 위의 예에서 C에서는 Windows가 보존되고, D에서는 doc가 보존되는 것을 말한다.
그런데 정답부터 말하자면 그건 운영체제가 일일이 자동으로 기억하고 챙겨 주지 않는다.
당장 탐색기나 파일 열기 대화상자의 주소창에서 c: 나 d: 라고만 달랑 쳐 보아라. 이 경우 언제나 해당 드라이브의 루트 디렉터리로만 가지, 명령 프롬프트일 때처럼 직전에 해당 드라이브에서 마지막으로 살펴보던 디렉터리를 기억하지 않는다. 오히려 명령 프롬프트가 예외적으로, 유일하게 그걸 별도로 지원해 주고 있다.
그럼 질문의 초점이 이렇게 바뀔 것이다. 명령 프롬프트만 왜 그러는 걸까?
물론 명령 프롬프트는 GUI와 달리 '뒤로' 같은 버튼이 없으니 디렉터리를 기억해 주는 게 사용자의 입장에서 편리하다. 그리고 더 큰 이유는 먼 옛날 MS-DOS와의 호환을 위해서이다.
MS-DOS의 최초 버전인 1.0은 무려 1981년에 출시되었으며, 얘는 파일 시스템에 디렉터리라는 개념을 지원하지 않았었다. 즉, 모든 디스크는 루트 디렉터리만 존재했으며, 파일 이름에 (역)슬래시 기호가 들어갈 일이 없었다.
마치 Windows 1.0이 프로그램 창을 겹치게 배열하는 게 지원되지 않았던 것과 동급으로 정말 믿어지지 않는다. (뭐, 기술적인 한계 때문은 아니고, 애플 사와의 특허 분쟁을 피해 가느라 일부러 기능을 cripple시킨 것이지만) 1980년대 초의 열악한 컴퓨터는 무슨 매체든 디스크의 공간이 상상하기 힘들 정도로 작고 좁았으니 굳이 디렉터리 계층 구조의 필요가 존재하지 않았던 듯하다.
그러다가 DOS 2.0부터는 드디어 파일 시스템 차원에서 디렉터리가 도입됐다.
그런데 DOS 1.0용으로 개발된 프로그램은 디렉터리라는 걸 전혀 인식하지 않고 역슬래시 문자도 아예 사용하지 않으니 2.0에서 루트가 아닌 다른 디렉터리에 있는 파일을 읽고 쓸 방법이 없다.
그러니 이 문제를 최대한 호환성을 존중하며 해결하기 위해, :₩로 시작하지 않는 경로는 이제부터 상대 경로로 간주시켰다. 그리고 각 드라이브별로 커런트 디렉터리라는 개념을 도입하여, 상대 경로는 루트 고정이 아닌 커런트 디렉터리에 있는 파일에 접근하는 것으로 정책을 바꿨다. 운영체제가 일종의 state machine 역할을 대신해 주는 셈이다.
Windows는 앞서 살펴보았듯이 모든 드라이브를 통틀어서 단일 current directory만 관리하지 DOS처럼 동작하지 않는다. 단지 명령 프롬프트에서는 특수한 환경변수를 운용해서 사용자가 돌아다닌 디렉터리를 드라이브별로 추적하여 도스의 동작을 흉내 내 준다. 이건 물론 오늘날까지도 전적으로 호환성 차원에서 해 주는 것일 뿐이다. the old new thing 블로그를 보면 더 자세한 설명을 볼 수 있다. 환경변수를 사용하는 이유는 이 프로세스로부터 새로 실행된 child 프로세스에게까지 current directory 변경의 여파가 자동으로 이어지게 하기 위해서라 한다.
“타 드라이브의 current directory”라니, 지금까지 한 번도 진지하게 생각해 본 적이 없었는데.. 굉장히 흥미로운 사실을 알 수 있었다. 예전에 Windows 9x에서 존재하던 CD ... (점 3개 이상)처럼 뭔가 호환성과 관련된 사연이 있었던 것이다.
1.
컴퓨터에서 옛날에는 하나밖에 없는 게 당연하다고 여겨졌으나 나중에는 여러 개 존재할 수도 있게 된 것의 예로는 디렉터리뿐만 아니라 CPU 코어(멀티코어!)라든가 모니터(최소한 듀얼..)도 해당되지 싶다.
그러니 하나밖에 인식을 안 하는 소프트웨어에 대해서는 무조건 붙박이가 아니라 현재 default로 지정되어 있는 것 하나를 기준으로 동작하게 운영체제가 샌드박스 처리를 잘 해 줘야 할 것이다.
하드웨어 말고 소프트웨어적인 요소 중에서도 클립보드 같은 건 운영체제 API 차원에서 다변화될 가능성이 있다. 그것 말고는... 설마 한 컴퓨터에 마우스 포인터 같은 게 둘 이상 존재할 일이 있을지는 모르겠다.
마우스 말고 터치스크린은 여러 손가락이 동시에 눌러질 수 있다. Windows 98에서 멀티모니터 지원이 최초로 도입됐다면 Windows 7부터는 멀티터치 지원 기능이 최초로 추가됐는데, 본인은 지금까지 멀티터치 관련 기기나 API를 접할 일이 전~혀 없었다. 문자 입력과도 분명 연계가 가능할 텐데 그쪽으로 연구할 기회가 없었다.
2.
그러고 보니 시스템 전체 차원에서의 current 설정 vs 특정 항목별 current/default 설정이라는 양대 구도는 Windows의 IME에서도 동일하게 찾아볼 수 있다.
Windows에서 돌아가는 모든 UI 스레드들은 어떤 입력 언어/로케일과 연결돼 있다. 이것은 영어 드보락, MS 일본어 IME, 날개셋 등등 중 하나로.. 키보드 드라이버, IME/TSF 모듈을 모두 통합하는 개념이다.
각 스레드들이 서로 다른 입력 언어와 연결 가능하지만(Alt+Shift, Ctrl+Shift, 또는 도구모음줄 클릭), 어떤 스레드가 새로 생성되었을 때 맨 처음 기본으로 지정되는 'default 입력 언어'라는 건 따로 있다. 이건 제어판에서 변경 가능하다. 이게 디렉터리로 치면 current directory에 가깝다.
그런데, 사실은 한국어, 중국어, 일본어 등 각 언어별로도 말 그대로 default 입력 언어가 있다. 한 언어에 속하는 IME들이 여러 개 있을 때, 사용자가 Alt+Shift로 언어만 그걸로 전환하면 그 언어의 default IME에 속하는 놈이 기본 선택된다. DOS에서 존재하던 드라이브별 current directory처럼 말이다.
내 경험상 전체 default IME라든가, 언어별 default IME 같은 건 프로그래밍을 통해 알아 내거나 변경하는 뾰족한 방법이 없다. MSDN을 뒤져 보면 비슷한 기능을 하는 API가 있긴 하지만 current, active, default 등 용어도 혼란스럽고 기능들이 문서화된 대로 정확하게 동작하질 않는다. 더구나 Windows 8부터는 Win+Space를 통해 IME들을 언어 구분 없이 한 리스트에서 쭉 고르게 UI가 바뀌어서 언어별 default IME라는 건 개념이 굉장히 모호해지기도 했다.
이 방식은 운영체제에 설치된 입력기가 적을 때는 깔끔하지만 10개 가까이 많아지면 화면이 굉장히 난잡해진다. 언어별로 구분하는 Windows 7 이하 기존 방식도 여전히 필요하다고 생각된다.
Posted by 사무엘