운영체제의 역사 그리고 표준이 중요한 이유

Eddy·2022년 8월 15일
36

유닉스의 탄생

유닉스는 AT&T 벨 연구소의 연구원이었던 켄 톰슨과 데니스 리치가 만들었다. 벨 연구소는 20세기 과학기술에 엄청난 기여를 한 혁신적인 장소다. 일단 벨 연구소 출신으로 노벨과학상 받은 사람만 10명이 넘으니 말 다했다. 트랜지스터부터 우주배경복사까지 수많은 업적을 쌓았다.

이 벨 연구소가 낳은 역작 중 하나가 바로 유닉스다.


(유닉스의 창시자, 켄 톰슨과 데니스 리치)

왜 갑자기 유닉스 얘기를 하냐고?

바로 유닉스가 현대 운영체제의 시조새 같은 존재기 때문이다. 지금 우리가 쓰고 있는 대부분의 운영체제는 (윈도우즈만 제외하고) 유닉스를 뿌리로 하고 있다.

유닉스의 등장 배경을 아주 짧게 알아보자.

1960년대 후반, 벨 연구소에서는 많은 돈을 들여서 '멀틱스'라는 운영체제 개발 프로젝트를 진행했다. 멀틱스는 멀티 프로그래밍, 멀티 유저를 지원하는 혁신적인 운영체제였다. (그렇다. 그 이전 컴퓨터는 프로그램도 동시에 여러개 못 돌렸고, 하나의 컴퓨터에 여러 유저가 접속할 수도 없었다.)

그렇지만 멀틱스 운영체제 개발은 상업적으로 완전히 실패했다.

대신 교훈을 남겼다. 켄 톰슨과 데니스 리치는 멀틱스 개발을 하면서 깨달은 점이 있었다.

멀틱스에서 느꼈던 문제점을 개선하고 싶어서, 버려진 구식 컴퓨터를 이용해 다락방에서 간단한 운영체제를 하나 만들었다. 이게 바로 유닉스(UNIX)다. ('멀틱스'의 반대 어원으로 '유닉스'라는 이름이 나왔다고 한다.)

멀틱스의 안 좋은 기억 때문에, 벨 연구소 경영진들은 유닉스 개발에 별로 신경도 안 썼다. 컴퓨터 사달라는데 지원도 안 해줬다. (당시 컴퓨터는 수천-수억원짜리 기계였으므로)

하지만 유닉스는 당시 운영체제의 불편한 점들을 많이 개선했다. 결과적으로는 엄청난 성공을 거뒀다.

이 이야기는 <유닉스의 탄생>이라는 책에서 읽은 것이다. 당시 유닉스 개발팀이었던 브라이언 커닝핸이 썼다. 벨 연구소의 천재 개발자들이 유닉스를 만들어가는 이야기를 담고 있다. 컴퓨터 공학 역사에서 굉장히 중요한 스토리다. 한번쯤 읽어보자. 재밌다.

(브라이언 커닝핸은 그 유명한 C 언어 교재를 쓴 사람이기도 하다. 최근에 번역된 <1일 1로그 100일 완성 IT 지식> 이라는 책도 있다. 글을 참 잘 쓴다.)

전세계로 뻗어나간 유닉스의 다양한 버전

벨 연구소는 유닉스가 돈이 될 거라고 생각을 못했다. (나중에 후회하지만) 유닉스를 저렴한 가격에 외부 배포를 했다.

그러자 전세계 개발자들이 유닉스를 보고 '아아니... 이렇게 좋은 게 있다니!'하면서 유닉스 배포판을 가져다가 수정하고 개선하기 시작했다. 유닉스 개발은 벨 연구소를 벗어나 전세계로 뻗어나갔다.


(UNIX의 역사, 출처: wikipedia)

이 그림을 보면 유닉스가 엄청나게 다양한 버전으로 갈라져나간 것을 볼 수 있다. 세세히 다 알 필요는 없지만, 크게 2가지 계열이 있었다.

BSD (Berkeley Software Distribution)

하나는 캘리포니아 버클리 대학에서 만들고 배포한 BSD 계열이다. BSD는 초기 유닉스를 기반으로 했지만, 자체적으로 코드를 작성하며 계속 발전시켰다.

1985년 스티브 잡스가 만든 NeXT 컴퓨터의 운영체제가 BSD 기반이었다. 이후 잡스가 돌아가면서 NeXT는 MacOS의 기반이 됐다. MacOS는 이후 iOS의 기반이 됐다. 그러니 애플 운영체제도 넓게 봐서 유닉스 계열이다.

System V

또 다른 쪽은 AT&T가 뒤늦게 유닉스 저작권을 가지고 돈을 벌기 위해 만들었던 System V 계열이다. (그림 아래쪽) IBM, 오라클, HP 같은 시스템 공급 업체들이 사용하는 OS의 기반이 되었다.

유닉스 전쟁

이 두 진영은 1980년대 후반 이른바 ‘유닉스 전쟁'을 벌인다.

당시 수많은 업체, 기관이 각자의 유닉스 버전을 가지고 경쟁했다. 제멋대로 갈라져나간 수많은 유닉스 버전들은 인터페이스도 다를 수밖에 없었다. 당연하게도 유닉스 위에서 어플리케이션을 개발하는 사람들 입장에서는 굉장히 불편했다.

표준이 필요한 시점이었다. 당연히 업계는 표준화가 필요하다는 걸 인정했지만, 누가 진짜 유닉스의 표준이 되어야 하는가는 의견이 다를 수밖에 없었다.


(System V가 진정한 표준이라고 홍보하는 1988년 신문 광고)

BSD 계열과 System V 계열이 특히 박터지게 싸웠다.

AT&T는 BSD가 자기들 코드를 사용했다고 하면서 고소를 했고, BSD는 AT&T에서 유래한 코드를 제거하고 새로 작성했기 떄문에 문제가 없다고 받아쳤다. 지루하고 길고 긴 법정 싸움이 이어졌다.

뭐 아무튼 이 이야기까지 중요한 것은 아니고...

결과적으로 중요한 건, 업계에서는 2가지의 핵심 표준이 유닉스 계열 운영체제의 표준으로 자리잡았다는 것이다.

하나는 POSIX이고, 다른 하나는 SUS다.

POSIX와 SUS

POSIX (Portable Operating System Interface)는 IEEE가 정의한 운영체제 인터페이스 표준이다. 더 자세히 말하면, 시스템 콜에 대한 C 언어 API 표준이다.

POSIX는 '유닉스 계열'이라고 불리는 운영체제의 기준이다. BSD, Linux, MacOS 등은 유닉스는 아니지만, OSIX를 따르기 때문에 유닉스 계열이라고 부른다.

SUS(Single Unix Standard)는 유닉스의 상표권을 가진 오픈 그룹이 만든 유닉스 표준이다. SUS는 POSIX를 포함하는 상위 집합이다.

SUS는 '유닉스'라고 불리는 운영체제의 기준이다. SUS와 호환이 되는 운영체제는 ‘유닉스'라고 불릴 수 있다.

앞으로 우리는 시스템 콜을 배우게 될 텐데, 대부분은 POSIX에서 정의한 시스템 콜이다. POSIX가 가장 널리 통용되는 표준이고, 핵심 인터페이스를 담고 있기 때문이다.

리눅스

여기서 리눅스 얘기가 빠질 수 없다.

유닉스가 한창 인기인 시절. 유닉스와 호환이 되는 미닉스라는 운영체제가 있었다.

어느날 21살짜리 핀란드 대학생이 취미로 이 미닉스를 가지고 무료 운영체제를 개발하기 시작했다. 사람들한테 '내가 이런 걸 개발하고 있다'고 알리자 관심을 가진 프로그래머들이 모여서 같이 개발에 참여했다.

이 운영체제는 이 대학생의 이름을 따서 ‘리누스의 유닉스(Linus's UNIX)’, 리눅스(LINUX)라고 이름이 붙여진다.

리눅스는 그 후로 엄청난 성공을 거두었다.

리눅스는 지구상에서 가장 널리 쓰이는 운영체제다. 수십 억개의 안드로이드폰, 인터넷을 이루는 서버의 거의 대부분, 자동차, TV 등의 임베디드 장비도 거의다 리눅스를 사용한다. 윈도우가 짱 먹은 데스크탑과 iOS의 아이폰을 제외하고는 리눅스가 짱짱맨이라는 뜻이다.

21살 프로그래머가 재미로 시작해서 커뮤니티를 통해 발전해온 운영체제가 전세계에서 가장 널리 쓰이는 운영체제가 됐다는 사실은 아무리 생각해도 놀랍다.
자동차 덕후 한명이 집에서 취미로 사람들을 불러서 수제 자동차를 만들기 시작했는데, 30년 뒤에 갑자기 전세계 1등 자동차 브랜드가 됐다고 상상해보라…

리눅스는 유닉스와는 분명히 다르다. 하지만 POSIX와 SUS를 지키려고 노력하고 유닉스 철학을 많이 영향받은 ‘유닉스 계열 운영체제'다.

C 언어 표준

아, C 언어 표준도 얘기하고 넘어가야 한다.

C 언어는 1980년대부터 거의 대부분의 개발자들이 쓰는 언어가 되었는데, 딱히 정해진 표준이랄 게 없었다. 여러개의 C 버전이 존재했다.

그래서 미국 표준협회인 ANSI에서 C 언어의 국제 표준을 정했다. 이 표준은 C 언어의 기본 문법, 라이브러리, 헤더 파일을 정의한다.

ANSI C 표준의 첫 버전은 89년에 나왔는데 C89라고 불린다. 그 외에 C90, C95, C99를 거쳐 가장 최근에는 C11까지 나왔다.

표준 인터페이스

'표준'에 대해서 이렇게 길게 얘기한 이유가 있다. 운영체제 개발자들이 절대로 이 표준 인터페이스를 벗어나지 않으려고 엄청 노력하기 때문이다.

"시스템 콜 인터페이스는 돌에 새겨진 글씨와 같다."
<리눅스 시스템 프로그래밍>, 로버트 러브

전세계 수많은 개발자들이 이 표준에 맞춰서 개발을 하고 있다. 함부로 인터페이스를 변경하면 엄청난 문제가 될 수 있다.

반대로 말하면 표준을 잘 따르면 우리가 작성하는 프로그램이 어떤 기기나 환경에서도 제대로 돌아간다는 것이다.

따라서 시스템 프로그래밍에서 표준은 매우 중요하다.

시스템 프로그래밍을 배운다는 것은 표준 인터페이스를 배운다는 뜻이다. 운영체제마다 내부 구현은 다르겠지만, 표준 인터페이스는 최대한 지킨다.

리눅스도 공식적으로 POSIX나 SUS 인증을 받은 것은 아니지만, 이 인터페이스를 따르지 않으면 버그로 취급한다고 한다.

앞으로 우리가 배울 시스템 콜은 ‘리눅스'와 POSIX 표준을 기준으로 한다. 왜냐하면 내가 리눅스 시스템 프로그래밍 책으로 공부했으니까.

리눅스는 가장 널리 쓰이기도 하고, iOS 또한 POSIX를 따르는 유닉스 계열이다.

API와 ABI

호환성과 표준에 대해 얘기할 때 하나 짚고 넘어가야할 용어가 있다. 바로 API와 ABI다.

API, ABI는 이 시스템 호환성에 매우 큰 영향을 끼친다.

왜냐? 둘 다 '인터페이스'이기 때문이다.

인터페이스란 '접점'이다.

인터페이스란 무엇인가?

인터페이스는 서로 다른 소프트웨어/하드웨어를 이어주는 '접점'이다.

이 접점이 들어맞을 때, 서로 다른 소프트웨어나 하드웨어를 쉽게 갈아끼워서 사용할 수 있게 된다. 즉, 호환이 된다.

만약 A 모듈이 B라는 접점에 맞도록 구현되어있다고 하자. 모두 B라는 접점을 가지는 B1, B2, B3가 있다. 얘네들이 실제 모양은 달라도 A는 모두 문제없이 사용할 수 있다. 즉 호환성을 가지게 된다.

마치 다용도 드라이버를 생각하면 된다. 조립식으로 된 드라이버를 본 적이 있을 것이다. 드라이버 손잡이하고 맞으면 언제든지 다양한 모양의 드라이버를 끼워서 사용할 수 있다.

'인터페이스'는 아마 컴퓨터를 배우면 가장 많이 등장하는 단어중 하나일 것이다.

왜냐하면 컴퓨터 공학의 기본 원리가, 매우 복잡하고 거대한 시스템을 작고 뚜렷한 모듈로 쪼개고, 그 모듈들 간의 접점을 설계하는 일이기 때문이다.

쉽게 말해, 컴퓨터 공학은 일체형 가구가 아닌 조립식 가구를 지향한다. 조립식 가구에서 중요한 것은 조립하는 부품들 간의 접점이 잘 맞아들어가는가다.

아무튼 API와 ABI는 둘다 인터페이스다. 어떤 수준의 인터페이스인지만 다르다.

소스 코드 수준의 접점: API

시스템 수준에서 API는 소스 코드 수준에서의 인터페이스를 말한다.

즉, API는 소스 코드와 컴파일러 사이의 '접점'이다. 예를 들어, printf() 라는 함수를 사용했을 때 콘솔에 출력을 할 수 있다는 인터페이스가 대표적이다.

C 라이브러리는 메모리 관리, 문자열 처리 같은 기능을 사용할 수 있는 C 언어 인터페이스 (API)를 제공한다.

대표적인 운영체제 API는 유닉스/리눅스 계열을 위한 POSIX API, 윈도우즈 시스템을 위한 Windows API가 있다.

C 컴파일러는 API를 제대로 사용한 소스 코드를 받아서, 컴파일과 링크를 거친다. 우리가 원하는 바이너리 코드로 바꿔준다.

바이너리 수준의 접점: ABI

ABI는 바이너리 코드 수준에서의 인터페이스다. 바이너리와 하드웨어 간의 '접점'이다.

"'aa'라는 레지스터에 1이라는 값을 넣으려면 '010010110'라는 바이너리 코드를 사용한다" 같은 인터페이스가 표적이다. CPU는 여러가지 연산 기능을 사용할 수 있는 바이너리 코드 인터페이스 (ABI)를 제공한다.

컴파일러가 소스코드를 컴파일한 명령어 덩어리(프로그램)가, 이 시스템에서 원하는 대로 실행될 수있게 해준다.

만약 x86의 ABI에 맞춰서 컴파일한 코드를, ARM CPU를 가진 기기에서 돌리려고 하면 실행이 되지 않는다. 둘의 ABI가 다르기 때문이다.

즉, ABI는 하드웨어(CPU) 아키텍처와 밀접한 관련이 있다. 각 CPU 아키텍처마다 서로 다른 ABI를 가지고 있고, 이게 호환성에 영향을 미친다.

우리가 맥에서 소프트웨어 실행 파일을 다운로드 받을 때 인텔 맥용 프로그램이 따로 있고, M1 맥용 프로그램이 따로 있는 이유다. 이 둘은 ABI가 다른 CPU를 사용한다.

하지만 대부분의 프로그래머에게는 ABI보다는 API가 훨씬 익숙하다.

사실상 ABI는 크게 신경쓸 일이 없다. API만 잘 맞추면 컴파일러가 알아서 컴퓨터 구조에 맞춰 처리하기 때문이다.

하지만 ABI가 있다는 것은 알아두자.

요약 정리

  • 대부분의 현대 운영체제는 유닉스에서 시작해서 다양한 버전으로 갈라져 나왔다.
  • 유닉스 표준을 두고 유닉스 전쟁이 일어났고, 결과적으로 POSIX와 SUS라는 2개의 표준이 생겼다.
  • POSIX는 '유닉스 계열'의 기준이고, SUS는 '유닉스'의 기준이다.
  • 시스템 프로그래밍을 배운다는 것은 이 표준 인터페이스를 배운다는 뜻이다.
  • API는 소스 코드 수준에서의 인터페이스, ABI는 바이너리 수준에서의 인터페이스를 뜻한다. 이 둘은 특정 소프트웨어의 이식성/호환성을 결정한다.
profile
개발 지식을 쉽고 재미있게 설명해보자. ▶️ www.youtube.com/@simple-eddy

8개의 댓글

comment-user-thumbnail
2022년 8월 20일

Dennis M. Ritchie 선생님이 보여서 홀린 듯이 들어왔네요...
덕분에 좋은 글 잘 읽었습니다. 감사합니다 : )

+ 참고로 SUS 는 Single Unix Standard 가 아닌 Single Unix Specification 입니다.
출처는 이하와 같습니다: SUS 표준을 관리하는 OpenGroup 공식 홈페이지입니다.
https://www.opengroup.org/membership/forums/platform/unix

1개의 답글
comment-user-thumbnail
2022년 8월 23일

저도 유닉스의 탄생 정말 재미있게 읽었는데 반갑네요! 좋은 글 감사합니다 :)

답글 달기
comment-user-thumbnail
2022년 8월 25일

이야기가 있는 정리글이라 재밌게 읽었습니다. 감사합니다 :)

답글 달기
comment-user-thumbnail
2022년 8월 25일

유닉스랑 리눅스... 시작은 모두 작았었네요 ㅎㅎ

답글 달기
comment-user-thumbnail
2022년 9월 6일

안녕하세요, Eddy 님.
(주)도서출판 인사이트의 편집자입니다.
운영체제의 역사에 관해 잘 정리해 주셔서 유익하게 읽었습니다.
다른 글도 상당히 쉽고 재미있게 설명해 주셔서 홀린 듯 읽었습니다.
혹시 출간을 제안드리고 싶은데, 괜찮으시다면 editorsuji@gmail.com으로 메일 부탁드리겠습니다! :D

답글 달기
comment-user-thumbnail
2023년 10월 20일

선생님 글을 정말 잘 쓰시는 것 같습니다. 재미있게 읽었습니다. 감사합니다.

답글 달기