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

ARM 노트북에서 옛날 x86 프로그램이 돌아가는 비밀 — 마이크로소프트가 '엉터리 코드'를 몰래 고쳐주는 이유

Hacker News 원문 보기
ARM 노트북에서 옛날 x86 프로그램이 돌아가는 비밀 — 마이크로소프트가 '엉터리 코드'를 몰래 고쳐주는 이유

ARM 노트북에서 옛날 x86 프로그램이 돌아가는 비밀

요즘 노트북 시장이 정말 빠르게 바뀌고 있죠. 애플은 인텔을 버리고 자체 ARM 칩인 M 시리즈로 갈아탔고, 윈도우 진영도 퀄컴 스냅드래곤 같은 ARM 칩을 단 노트북을 점점 늘리고 있어요. 그런데 여기서 골치 아픈 문제가 하나 생깁니다. 세상에 깔린 수십 년치 윈도우 프로그램들은 거의 다 인텔·AMD가 쓰는 'x86'이라는 명령어 체계로 만들어졌거든요. ARM 칩은 이 x86 명령어를 그대로는 알아듣지 못해요. 사람으로 치면 서로 쓰는 언어가 다른 셈이죠.

그래서 등장한 게 바로 에뮬레이터예요. 이게 뭐냐면, x86으로 쓰인 프로그램의 명령어를 실행하기 직전에 ARM 명령어로 즉석에서 번역해 주는 통역사라고 보면 됩니다. 애플의 '로제타 2', 마이크로소프트의 'x86 에뮬레이터'가 정확히 이 일을 해요. 그냥 한 줄씩 통역하면 너무 느리니까, 자주 도는 코드 덩어리를 통째로 ARM 코드로 번역해 저장해 두고 재활용하는데, 이런 기법을 JIT(Just-In-Time) 바이너리 변환이라고 불러요.

'이 코드 너무 엉망인데… 그냥 우리가 고쳐서 돌릴까?'

마이크로소프트의 레이먼드 첸이 풀어놓은 에뮬레이터 팀 일화가 흥미로운데요. 핵심은 마이크로소프트의 오래된 철학, 곧 '기존 앱을 절대 깨뜨리지 않는다'에 있어요. 윈도우가 30년 넘게 호환성으로 유명한 이유죠.

문제는, 세상 프로그램이 다 깔끔하게 짜여 있지 않다는 거예요. 어떤 프로그램은 명령어를 잘못 만들어 놨는데, 진짜 인텔 CPU에서는 우연히, 운 좋게 동작하던 경우가 있어요. 표준에 정의돼 있지도 않은 동작에 기대거나, 살짝 어긋난 명령어 배치인데 실제 칩이 너그럽게 봐주던 거죠. 그런데 이걸 에뮬레이터가 '글자 그대로 충실하게' 번역하면, ARM 위에서는 그대로 뻗어버립니다(크래시).

여기서 에뮬레이터 팀의 선택이 재밌어요. 사용자 입장에선 '이 프로그램이 원래 버그가 있었네'가 아니라 '윈도우 ARM은 프로그램이 안 돌아가네'라고 느끼거든요. 그래서 팀은 그 특정한 엉터리 패턴을 콕 집어 감지한 다음, 번역 단계에서 프로그램이 원래 하려던 '올바른 동작'으로 바꿔치기해 버립니다. 원본 실행 파일은 손도 안 대고, 메모리에서 통역되는 그 순간에만 슬쩍 교정해 주는 거예요.

특히 까다로운 게 자기 수정 코드(self-modifying code)예요. 이게 뭐냐면, 프로그램이 실행 도중에 자기 자신의 명령어를 바꿔 쓰는 코드인데요. 에뮬레이터는 번역해 둔 ARM 코드를 캐시에 저장해 재활용하잖아요? 그런데 원본이 슬쩍 바뀌면 캐시는 옛날 버전이라 엉뚱하게 돌아갑니다. 그래서 에뮬레이터는 '코드 영역이 수정됐나?'를 늘 감시하다가, 바뀌면 캐시를 버리고 다시 번역해야 해요. 이런 뒷처리를 전부 조용히 해주는 거죠.

다른 곳들은 어떻게 할까

이런 고민은 마이크로소프트만의 것이 아니에요. 애플의 로제타 2도 비슷한 변환을 하고요(다만 애플은 호환성을 좀 더 과감하게 끊는 편이라 정책 차이가 있어요). 오픈소스 진영엔 QEMU라는 만능 에뮬레이터가 있고, 리눅스에서 게임을 돌릴 때 쓰는 box86·FEX 같은 프로젝트도 같은 문제를 안고 있어요. 윈도우엔 아예 호환성 심(shim) 데이터베이스라는 게 있어서, 특정 프로그램이 실행될 때 미리 만들어둔 '교정 패치'를 끼워 넣어요. '이 게임은 옛날 API를 잘못 쓰니까 이렇게 보정해 줘라' 같은 규칙이 수천 개 들어 있죠.

한국 개발자에게

당장 에뮬레이터를 만들 일은 없겠지만, 배울 점이 분명히 있어요. 첫째, 호환성은 공짜가 아니라 누군가의 엄청난 노동으로 유지된다는 점이에요. 우리가 옛날 exe를 ARM 맥북·윈도우에서 아무렇지 않게 돌릴 때, 뒤에선 이런 보이지 않는 교정이 돌고 있는 거죠. 둘째, 라이브러리나 API를 설계할 때 '잘못 쓰는 사용자'까지 염두에 둬야 한다는 교훈이에요. 문서에 없는 동작에 사람들이 기대기 시작하면, 그게 사실상 스펙이 되어버리거든요(이걸 '하이럼의 법칙'이라고 불러요). 셋째, 추상화 계층을 한 겹 두면 원본을 안 건드리고도 동작을 바꿀 수 있다는 설계 아이디어는, 미들웨어나 프록시를 짤 때도 그대로 써먹을 수 있어요.

한 줄 정리: 잘 만든 호환성 계층은 '원본의 버그까지 책임지고 흉내 내거나, 몰래 고쳐주는' 일을 한다는 것.

여러분이라면 어떻게 하시겠어요? 명백히 버그가 있는 프로그램을 만났을 때, 원작자의 의도대로 '몰래 고쳐서' 돌려주는 게 맞을까요, 아니면 버그는 버그대로 재현해서 개발자가 직접 고치게 두는 게 맞을까요? 🤔


🔗 출처: Hacker News

이 뉴스가 유용했나요?

TTJ 코딩클래스 정규반

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

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

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

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

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

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

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

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