컴퓨터 구조 운영체제 네트워크 자료구조 알고리즘 데이터베이스 내 학습
arch · 18

RISC vs CISC

ISARISCCISC

CPU가 이해하는 명령어의 종류와 모양을 정해 둔 약속을 명령어 집합 구조(ISA, Instruction Set Architecture)라고 합니다. 소프트웨어가 보는 CPU의 얼굴이라서, 같은 ISA를 따르는 CPU는 같은 프로그램을 실행할 수 있습니다. ISA를 설계하는 철학은 크게 둘로 나뉩니다. RISC(Reduced Instruction Set Computer)는 단순한 명령어를 적은 종류로 제공하고 길이를 고정해 하드웨어를 단순하게 만들며, CISC(Complex Instruction Set Computer)는 한 명령어가 메모리 접근과 연산을 함께 하는 것처럼 복잡한 일을 하도록 풍부한 명령어를 제공합니다.

대표적으로 ARM과 RISC-V는 RISC 계열, x86은 CISC 계열로 불립니다. 같은 일을 하더라도 RISC는 보통 단순한 명령어를 더 많이, CISC는 더 적게 씁니다. 다만 오늘날의 구분은 예전만큼 뚜렷하지 않습니다. 현대 x86 CPU는 복잡한 명령어를 안쪽에서 단순한 마이크로 연산으로 나눠 실행하기 때문에, 겉모습은 CISC여도 실행 방식은 RISC와 비슷해졌습니다. 이 토픽에서는 두 철학이 명령어 길이, 메모리 접근 방식, 성능 식에서 어떻게 다른지 봅니다.

핵심 개념

ISA와 구현의 구분

ISA는 소프트웨어가 볼 수 있는 명령어, 레지스터, 주소 지정 방식의 약속이고, 마이크로아키텍처는 그것을 하드웨어로 구현하는 방법입니다. 같은 ISA를 서로 다른 구현으로 만들 수 있습니다.

핵심 개념

RISC의 특징

단순하고 길이가 일정한 명령어, 적은 종류의 주소 지정 방식, 많은 레지스터, 그리고 연산은 레지스터끼리 하고 메모리는 load/store 명령으로만 접근하는 구조가 대표적입니다. 디코딩과 파이프라인 구현이 단순해집니다.

핵심 개념

CISC의 특징

한 명령어가 여러 단계의 작업(예: 메모리 값을 읽어 더하고 다시 저장)을 하고, 명령어 길이가 가변적이며, 연산 명령어가 메모리 피연산자를 직접 다룰 수 있습니다. 같은 프로그램이 더 적은 명령어로 표현될 수 있습니다.

핵심 개념

load/store 구조

연산 명령어는 레지스터만 다루고, 메모리와 레지스터 사이의 이동은 load와 store 명령어가 맡는 구조입니다. 메모리 접근이 명령어마다 눈에 보여 파이프라인과 스케줄링을 단순하게 합니다.

핵심 개념

마이크로 연산

현대 x86 CPU는 명령어를 해독해 더 단순한 내부 연산(마이크로 연산, micro-op)으로 바꿔 실행합니다. 복잡한 ISA를 유지하면서 안쪽 실행 엔진은 단순한 연산 단위로 설계하는 방식입니다.

핵심 개념

CPU 시간 식

CPU 시간 = 명령어 수 × 명령어당 평균 사이클(CPI) × 사이클 시간입니다. RISC는 명령어 수가 늘고 CPI가 낮아지는 경향, CISC는 명령어 수가 줄고 CPI가 높아지는 경향이 있지만 실제 성능은 세 요소의 곱으로 정해집니다.

명령어 수만으로 빠르고 느림을 말할 수 없습니다 — 명령어가 적어도 한 개에 오래 걸리면 느릴 수 있습니다. 성능은 명령어 수, CPI, 사이클 시간을 함께 봐야 합니다.
고정 길이는 디코딩을 단순하게 합니다 — 명령어의 시작 위치가 길이로 정해져 있어 여러 명령어를 한꺼번에 해독하기 쉽습니다. 가변 길이는 코드가 짧아질 수 있는 대신 경계를 찾는 일이 복잡합니다.
경계는 흐려졌습니다 — x86은 안쪽에서 마이크로 연산으로 나눠 실행하고, RISC 계열 ISA도 시간이 지나며 명령어를 더해 왔습니다. 그래서 RISC와 CISC는 순수한 분류보다 설계 경향으로 이해하는 것이 알맞습니다.
ISA가 다르면 바이너리가 호환되지 않습니다 — x86용으로 컴파일한 실행 파일은 에뮬레이션 없이는 ARM CPU에서 실행되지 않습니다. 그래서 서버나 컨테이너 이미지를 만들 때 아키텍처를 구분합니다.
이 시각화에서 확인할 것 — "같은 일 다른 명령어" 탭에서 메모리에 더하기 연산을 CISC와 RISC가 어떻게 쓰는지를, "명령어 길이와 디코딩" 탭에서 고정 길이와 가변 길이의 경계 찾기를, "성능 식" 탭에서 CPU 시간 식으로 둘을 비교하는 방법을 STEP으로 확인하세요.

RISC와 CISC의 배경

RISC라는 이름은 1980년 데이비드 패터슨(David Patterson)과 데이비드 디츨(David Ditzel)의 논문 "The Case for the Reduced Instruction Set Computer"에서 널리 알려졌습니다. 이 논문은 VLSI 시대의 CPU를 RISC로 구현하는 편이 더 알맞을 수 있다고 주장했습니다. CISC는 이에 대비해 기존의 복잡한 ISA 설계를 가리키는 말로 쓰이게 되었습니다. 이후 ARM, MIPS, RISC-V 같은 RISC 계열 ISA와 x86 계열 ISA가 각자 발전해 왔습니다.

숫자로 확인하기

같은 일, 명령어 개수 — 메모리 값에 레지스터를 더해 다시 저장하는 일을 x86에서는 명령어 1개(add [x], eax)로 쓸 수 있고, RISC-V에서는 주소가 레지스터에 있다고 할 때 lw, add, sw 3개로 씁니다.
명령어 길이 — x86 명령어는 1바이트에서 15바이트까지 가변이고, RISC-V의 기본 명령어는 32비트(4바이트) 고정입니다. 6개 명령어의 길이 예시(1, 3, 2, 6, 1, 4바이트)는 합계 17바이트이고, 고정 4바이트라면 24바이트입니다.
성능 식 예시(가정한 값) — 사이클 시간 1ns에서 명령어 1,000,000개 × CPI 3.0은 3ms, 명령어 1,400,000개 × CPI 1.5는 2.1ms입니다. 명령어가 40% 더 많아도 CPI가 절반이면 더 빠를 수 있습니다.

자주 하는 오해

RISC는 명령어가 적어서 항상 느리다 / CISC는 명령어가 적어서 항상 빠르다 — 성능은 명령어 수, CPI, 사이클 시간의 곱입니다. 한 요소만으로 결론을 낼 수 없습니다.
x86은 CISC라서 내부도 복잡하게 실행한다 — 현대 x86 CPU는 명령어를 마이크로 연산으로 나눠 실행해 안쪽은 단순한 연산 단위로 동작합니다. ISA가 CISC라는 것과 실행 방식은 별개입니다.
RISC는 스마트폰용, CISC는 PC용이다 — 쓰이는 분야가 달라 보일 뿐 설계 철학의 구분입니다. Arm 기반 프로세서가 서버(예: AWS Graviton)에도 쓰이고, x86 프로세서가 노트북과 서버에 쓰입니다.
RISC는 메모리 접근이 없다 — 메모리 접근이 load/store 명령어로 분리되어 있을 뿐입니다. 연산 명령어가 메모리를 직접 다루지 않는 구조입니다.

면접에서 이렇게 물어요

면접 질문

RISC와 CISC의 차이는 무엇인가요?

RISC는 단순하고 길이가 일정한 명령어를 쓰고 연산은 레지스터끼리 하며 메모리 접근은 load/store가 맡습니다. CISC는 복잡한 명령어와 가변 길이를 쓰고 연산 명령어가 메모리 피연산자를 다룰 수 있습니다.

면접 질문

대표적인 예와 오늘날의 경계는?

ARM과 RISC-V가 RISC, x86이 CISC의 대표입니다. 다만 현대 x86 CPU는 복잡한 명령어를 마이크로 연산으로 바꿔 실행하므로 두 방식의 경계가 예전보다 흐려졌습니다.

면접 질문

RISC가 파이프라인에 유리하다고 하는 이유는?

명령어 길이가 같고 형식이 단순해 해독이 쉽고, 메모리 접근이 load/store로 분리되어 단계별 동작이 규칙적이기 때문입니다. 그래서 파이프라인 구현이 단순해집니다.

면접 질문

성능은 어떻게 비교하나요?

CPU 시간 = 명령어 수 × CPI × 사이클 시간 식으로 비교합니다. 명령어 수만 보거나 클럭만 봐서는 부족하고, 같은 프로그램에서 세 요소를 곱해 봐야 합니다.

실제 시스템에서는

인텔 문서 — 인텔 최적화 매뉴얼은 x86 명령어가 마이크로 연산(μop)으로 해독되어 실행된다고 설명하고, 소프트웨어 개발자 매뉴얼(SDM)은 x86 명령어 길이를 최대 15바이트로 정의합니다.
RISC-V — RISC-V 명세는 기본 명령어를 32비트 고정 길이로 정의하고, 선택 확장으로 16비트 압축 명령어를 둡니다. 명세는 공개되어 있어 누구나 읽을 수 있습니다.
클라우드 — AWS 문서는 Graviton 프로세서를 Arm 아키텍처 기반이라고 소개합니다. 같은 서비스를 x86과 Arm 인스턴스 모두에서 선택해 쓸 수 있습니다.
파이프라인과의 관계 — RISC의 단순함이 도움이 되는 이유는 파이프라이닝 토픽에서 단계별 동작과 함께 봅니다.

함께 보면 좋은 토픽

명령어 사이클 — 명령어가 인출 · 해독 · 실행되는 기본 단계를 봅니다.
파이프라이닝 — 단순한 명령어가 파이프라인에 유리한 이유를 봅니다.
CPU 구성 요소 — 레지스터와 제어 장치가 어떻게 구성되는지 봅니다.
비순차 실행 — 마이크로 연산을 앞당겨 실행하는 안쪽 엔진을 봅니다.
시스템 콜 — ISA가 제공하는 명령으로 운영체제 기능을 호출하는 방식을 봅니다.

참고 자료

인텔 — Intel 64 and IA-32 Architectures Optimization Reference Manual, Intel 64 and IA-32 Architectures Software Developer's Manual (Vol. 2, 명령어 형식)
논문 — Patterson, Ditzel, "The Case for the Reduced Instruction Set Computer", ACM SIGARCH Computer Architecture News 8(6), 1980
교재 — Hennessy, Patterson, "Computer Architecture: A Quantitative Approach", "Fundamentals of Quantitative Design and Analysis" 장 (CPU 성능 식)

같은 C 코드가 ISA마다 다른 명령어가 됨

// C: 포인터가 가리키는 값에 y를 더함
void add_to(int *p, int y) { *p += y; }

; x86-64 (Intel 문법): 메모리 피연산자를 직접 다루는 명령어 1개
add DWORD PTR [rdi], esi
ret

; RISC-V (RV64): load → 연산 → store
lw   a5, 0(a0)
addw a5, a5, a1
sw   a5, 0(a0)
ret

; AArch64 (Arm): RISC-V처럼 메모리 접근을 load/store 명령으로만 함
ldr w2, [x0]
add w2, w2, w1
str w2, [x0]
ret

x86-64에서는 add DWORD PTR [rdi], esi 한 명령어가 메모리에서 읽고, 더하고, 메모리에 다시 씁니다. RISC-V와 AArch64는 연산 명령어가 레지스터만 다루므로 load, 연산, store의 세 명령어로 나뉩니다. 이 출력은 컴파일러와 최적화 수준에 따라 달라질 수 있는 예시입니다. 배포판에 따라 x86-64 출력 앞에 endbr64가 붙기도 합니다. 직접 확인하려면 gcc -O2 -S로 어셈블리를 만들어 보거나 대상 아키텍처의 크로스 컴파일러를 쓰면 됩니다. 어느 쪽이 더 낫다는 뜻이 아니라, 같은 일을 표현하는 방식이 ISA 철학에 따라 달라진다는 것을 보여 줍니다.

명령어 길이 — 가변과 고정

; objdump -d 출력 예: 주소, 기계어 바이트, 어셈블리
; x86-64: 명령어마다 길이가 다름 (2바이트, 1바이트)
 0:  01 37             add DWORD PTR [rdi], esi
 2:  c3                ret

; RISC-V: 기본 명령어는 모두 4바이트 (압축 확장 C를 쓰지 않을 때)
 0:  00052783          lw   a5, 0(a0)
 4:  00b787bb          addw a5, a5, a1
 8:  00f52023          sw   a5, 0(a0)
 c:  00008067          ret

x86의 두 명령어는 2바이트와 1바이트로 길이가 다릅니다. 명령어의 길이는 앞의 바이트를 해석해야 알 수 있어서 시작 위치를 찾는 일이 앞에서 뒤로 이어집니다. RISC-V의 기본 명령어는 모두 4바이트라서 다음 명령어가 항상 4바이트 뒤에서 시작합니다. 위 기계어는 예시이며 컴파일러와 옵션에 따라 달라질 수 있습니다. 이 예시에서는 x86이 메모리 피연산자 덧셈을 명령어 하나(3바이트)로 처리해 코드가 작고, 고정 4바이트 RISC-V는 명령어 길이가 일정해 디코딩이 단순합니다. 다만 RISC-V에는 2바이트 압축(C) 확장이 있어 같은 코드가 더 작아질 수 있으므로, 실제 크기는 명령어 조합과 확장에 따라 달라집니다.

내 컴퓨터의 아키텍처 확인

# 리눅스/맥: 머신 아키텍처 (x86_64, aarch64 등)
uname -m

# 실행 파일이 어느 아키텍처용인지 확인
file ./server
# 예: ELF 64-bit LSB executable, x86-64 ...  또는  ... ARM aarch64 ...

# 컨테이너 이미지를 두 아키텍처용으로 빌드
docker buildx build --platform linux/amd64,linux/arm64 -t app:latest .

ISA가 다르면 기계어가 달라서 x86용 실행 파일은 Arm CPU에서 그대로 실행되지 않습니다. uname -m은 현재 머신의 아키텍처를, file 명령은 실행 파일이 어느 아키텍처용인지 알려 줍니다. Arm 기반 서버나 노트북을 함께 쓴다면 컨테이너 이미지를 linux/amd64와 linux/arm64 모두 빌드해 두는 방법이 있습니다. 여러 플랫폼 이미지를 로컬에 적재하려면 containerd 이미지 스토어를 켜야 하고, 그렇지 않으면 --push로 레지스트리에 올립니다. 인터프리터나 가상 머신 위에서 도는 코드(자바 바이트코드, 파이썬 스크립트)는 그 인터프리터가 해당 아키텍처를 지원하면 소스를 바꾸지 않고 실행됩니다.

Q1

RISC 아키텍처의 특징으로 옳은 것은?

Reduced(축소된) Instruction Set 이라는 이름을 떠올려 보세요.
RISC는 명령어 종류를 줄이고 길이를 대체로 고정해 디코딩과 파이프라인 구현을 단순하게 만듭니다. 연산은 레지스터 사이에서 하고 메모리 접근은 load/store 명령이 전담합니다.

Q2

CISC 아키텍처의 특징으로 옳은 것은?

Complex(복잡한) Instruction Set 입니다.
CISC는 하나의 명령어로 여러 단계의 작업(예: 메모리 값을 읽어 더하고 다시 저장)을 수행할 수 있도록 풍부한 명령어를 제공하며, 명령어 길이도 가변적입니다.

Q3

대표적인 아키텍처를 알맞게 짝지은 것은?

스마트폰 CPU와 PC용 인텔 CPU를 떠올려 보세요.
ARM은 대표적인 RISC, x86은 대표적인 CISC입니다. 다만 현대 x86 CPU는 내부적으로 복잡한 명령어를 단순한 마이크로 연산(micro-op)으로 바꿔 실행하기 때문에 두 방식의 경계는 예전보다 흐려졌습니다.