처리중입니다. 잠시만 기다려주세요.
TTJ 코딩클래스
정규반 단과 자료실 테크 뉴스 코딩 퀴즈
테크 뉴스
Hacker News 2026.06.08 72

포인터에 near와 far가 있던 시절: Win16 메모리 관리가 알려주는 것들

Hacker News 원문 보기
포인터에 near와 far가 있던 시절: Win16 메모리 관리가 알려주는 것들

64KB의 벽과 싸우던 개발자들

요즘 우리는 메모리를 거의 무한한 자원처럼 다루죠. malloc 한 번이면 끝이고, 포인터는 그냥 포인터예요. 그런데 1990년대 초 Windows 3.x, 즉 16비트 Windows(Win16) 시절 개발자들은 메모리 한 조각을 두고 정말 치열하게 머리를 굴려야 했어요. OS/2 Museum의 이 글은 그 시절의 메모리 관리가 어떻게 돌아갔는지를 곱씹어 봅니다. 단순한 추억팔이가 아니라, '제약이 만든 설계'가 무엇인지 보여주는 좋은 사례거든요.

세그먼트, 그리고 near와 far

당시 인텔 16비트 CPU(8086 계열)는 한 번에 다룰 수 있는 주소가 16비트, 즉 64KB까지였어요. 64KB면 요즘 이미지 한 장도 안 되는 크기죠. 그래서 더 큰 메모리를 쓰려고 세그먼트(segment)라는 개념을 도입했어요. 메모리를 64KB짜리 구역으로 나누고, '세그먼트 번호 + 그 안에서의 오프셋' 두 개를 합쳐서 주소를 만든 거예요. 동네(세그먼트)와 집 호수(오프셋)를 따로 적는 주소 체계라고 생각하면 돼요.

여기서 그 악명 높은 near 포인터와 far 포인터가 등장합니다. near 포인터는 "같은 동네 안"만 가리키니까 오프셋(16비트)만 있으면 돼서 작고 빨라요. 반면 far 포인터는 "다른 동네"까지 가리켜야 하니 세그먼트+오프셋(32비트)을 다 들고 다녀서 크고 느렸죠. 개발자가 변수 하나하나에 near/far를 직접 붙여가며 "이건 가까운 거, 저건 먼 거"를 관리해야 했어요. 지금 보면 끔찍하지만, 당시엔 성능과 메모리를 쥐어짜는 필수 기술이었습니다.

핸들과 '움직이는 메모리'

Win16 메모리 관리에서 가장 흥미로운 건 핸들(handle) 기반의 움직이는 메모리예요. GlobalAlloc으로 메모리를 할당하면 보통 우리가 기대하는 '주소'가 아니라 핸들이라는 일종의 교환권을 돌려받아요. 실제로 그 메모리를 쓰려면 GlobalLock으로 잠가서 그제서야 진짜 주소를 얻고, 다 쓰면 GlobalUnlock으로 풀어줘야 했죠.

왜 이렇게 번거롭게 했을까요? 메모리가 부족하던 시절이라 OS가 메모리 조각들을 마음대로 옮기고 정리(compaction)할 수 있어야 했거든요. 빈 공간이 여기저기 흩어지는 단편화(fragmentation)를 막으려면 블록들을 한쪽으로 밀어붙여야 하는데, 그러려면 메모리 주소가 고정되면 안 됐어요. 그래서 "잠그지 않은 메모리는 OS가 언제든 옮길 수 있다"는 규칙을 둔 거죠. 잠근 동안만 주소가 유효하고요. 심지어 잘 안 쓰는 메모리는 디스크로 내쫓았다가(discardable) 필요할 때 다시 불러오기도 했어요. 요즘 GC(가비지 컬렉터)가 객체를 옮기며 메모리를 정리하는 개념의 먼 조상 격이라고 볼 수 있어요.

지금과 비교해보면

32비트, 64비트 시대로 넘어오면서 이 모든 복잡함이 사라졌어요. 플랫(flat) 메모리 모델 덕분에 모든 메모리가 하나의 거대한 연속 공간처럼 보이게 됐고, near/far 구분도 의미가 없어졌죠. 가상 메모리(virtual memory)와 페이징(paging)을 OS와 하드웨어(MMU)가 알아서 처리해주면서, 개발자는 메모리가 물리적으로 어디 있는지 신경 쓸 필요가 없어졌고요. 핸들로 잠그고 푸는 춤도 더는 안 춰도 됩니다.

재밌는 건, 이 옛날 개념들이 완전히 사라진 게 아니라 형태를 바꿔 살아남았다는 점이에요. 핸들이라는 추상화는 파일 디스크립터나 GPU 리소스 핸들에 살아있고, '메모리를 옮기며 정리한다'는 발상은 현대 GC의 핵심이며, 단편화 문제는 지금도 메모리 할당자(allocator) 설계의 영원한 숙제거든요.

한국 개발자에게 주는 시사점

"나는 레거시 윈도우 안 만지는데?" 싶어도 얻을 게 있어요. 핵심 교훈은 제약이 설계를 만든다는 거예요. 64KB라는 하드웨어 한계가 세그먼트와 핸들이라는 정교한 추상화를 낳았듯, 지금 우리가 쓰는 추상화들도 다 어떤 제약에 대한 답이거든요. 왜 이런 구조가 생겼는지 그 '이유'를 알면, 비슷한 제약을 만났을 때 응용할 수 있어요.

또 임베디드나 IoT, 펌웨어를 다루는 분들에겐 남 얘기가 아니에요. 메모리가 빠듯한 환경에선 지금도 비슷한 고민을 하거든요. 메모리 풀을 직접 관리하고, 단편화를 피하려 애쓰는 게 마이크로컨트롤러 세계에선 일상이니까요.

마무리

한 줄 정리: near/far 포인터와 핸들 기반 메모리는 64KB 제약이 낳은 창의적 발명이었고, 그 아이디어들은 형태를 바꿔 지금도 살아있다. 여러분이 당연하게 여기는 추상화 중에 "사실 옛날 제약 때문에 생긴 것"이 또 뭐가 있을까요? 한번 곰곰이 따라 올라가 보면 의외로 재미있는 역사가 나올지도 몰라요.


🔗 출처: Hacker News

이 뉴스가 유용했나요?

TTJ 코딩클래스 정규반

월급 외 수입,
코딩으로 만들 수 있습니다

17가지 수익 모델을 직접 실습하고, 1,300만원 상당의 자동화 도구와 소스코드를 받아가세요.

144+실전 강의
17개수익 모델
4.9수강생 평점
정규반 자세히 보기

"비전공 직장인인데 반년 만에 수익 파이프라인을 여러 개 만들었습니다"

실제 수강생 후기
  • 비전공자도 6개월이면 첫 수익
  • 20년 경력 개발자 직강
  • 자동화 프로그램 + 소스코드 제공

매일 AI·개발 뉴스를 받아보세요

주요 테크 뉴스를 매일 아침 이메일로 전해드립니다.

스팸 없이, 언제든 구독 취소 가능합니다.