뛰어난 개발자가 되기 위해서는 단순히 코드를 작성해서 프로그램이 작동되게 하는 것이 아니라 '제대로 프로그램이 작동하게' 만들도록 노력해야 한다. 자신이 작성한 코드가 어떤 과정을 거쳐 실행되는지 설명할 수 있다는 뜻이다. 이런 프로그램의 실행 원리를 제대로 알기 위해 컴퓨터 과학(CS)을 이해해야 하고, 이것이 많은 기업에서 기술 면접을 통해 입사자의 CS 지식을 검증하는 이유이다.
컴퓨터 구조
1. 컴퓨터가 이해하는 정보
CPU는 기본적으로 0과 1만을 이해할 수 있다. 0과 1을 나타내는 가장 작은 정보의 단위를 '비트'라고 한다. 비트, 바이트, 킬로바이트, 메가바이트 등 모두 프로그램의 크기를 나타낼 때 사용하는 정보 단위이다. CPU 관점에서 정보 단위는 '워드'이다
- 데이터 : 숫자, 문자, 이미지, 동영상과 같은 정적인 정보를 의미
a = 0.1
b = 0.2
c = 0.3
if a + b == c:
pring("Equal")
else:
print("Not Equal")
- 위 소스 코드의 결과는 무엇일까? Equal일까? 놀랍게도 결과는 'Not Equal'이다. 이러한 오차가 발생하는 이유는 부동 소수점 방식의 정밀도에 한계 때문이다. 10진수 소수를 2진수로 표현할 때, 10진수 소수와 2진수 소수의 표현이 딱 맞아떨어지지 않을 수 있고, 컴퓨터의 저장공간은 한정적이기 때문에 무한히 많은 소수점을 저장할 수도 없다. 따라서 딱 맞아떨어지지 않는 소수를 표현할 때는 일부러 소수점을 생략하여 저장한다. 그래서 오차가 발생할 수 있다
- 0과 1로 숫자 표현하기
- 앞서 언급했듯이 컴터는 0과 1만 이해할 수 있다. 따라서 2진법을 사용
- 2진법을 사용하는 방법은 익히 알려져있으니 생략하겠다
- 0과 1로 문자 표현하기
- 문자 집합 : 컴퓨터가 이해할 수 있는 문자들의 집합
- 아스키 : 초창기 컴퓨터에서 사용하던 문자 집합 중 하나(알파벳, 아라비아 숫자, 일부 특수 문자 포함)
- 하나의 아스키 문자를 표현하기 위해 8비트(1바이트) 사용
- 8비트 중 1비트는 패리티 비트 : 오류 검출을 위해 사용되는 비트
- 유니코드 : 한글을 포함한 훨씬 많은 언어, 특수문자, 화살표, 이모티콘까지 코드로 표현 가능 -> 통일된 문자 집합
- 아스키 : 초창기 컴퓨터에서 사용하던 문자 집합 중 하나(알파벳, 아라비아 숫자, 일부 특수 문자 포함)
- 문자 인코딩 : 문자 집합에 속한 문자를 컴퓨터가 이해하는 0과 1로 이루어진 문자 코드로 변환하는 과정
- 문자 디코딩 : 문자 인코딩과 반대, 0과 1로 표현된 문자를 사람이 이해하는 문자로 변환
- 문자 집합 : 컴퓨터가 이해할 수 있는 문자들의 집합
- 명령어
- 명령어 = 수행할 동작 + 수행할 대상(데이터 자체 or 데이터가 저장된 위치)
- 연산 코드(opcode)
- 데이터 전송, 산술/논리 연산, 제어 흐름 변경, 입출력 제어
- 오퍼랜드(operand)
- 연산 코드에 사용될 데이터가 저장된 위치, 즉 메모리 주소나 레지스터의 이름이 명시됨
- 기계어와 어셈블리어
- 기계어 : CPU가 이해할 수 있도록 0과 1로 표현된 정보를 있는 그대로 표현한 것
- 어셈블리어 : 0과 1로 표현된 기계어를 읽기 편한 형태로 단순 번역한 언어
기계어 어셈블리어
0101 0101 push rbp
0101 1101 pop rbp
1100 0011 ret
- 우리가 코딩을 하면 -> 프로그래밍 언어로 이루어진 프로그램 -> 컴퓨터 내부에서는 0과 1로 이루어진 기계어로 변환하여 프로그램 실행
- 명령어 사이클
- CPU가 명령어를 처리하는 과정에서 프로그램 속 각각의 명령어들은 일정한 주기를 반복하며 실행되는데, 이 주기를 명령어 사이클이라고 함
- 인출 사이클 : 메모리에 있는 명령어를 CPU로 가지고 오는 단계
- 실행 사이클 : CPU로 가져온 명령어를 실행하는 단계
- 간접 사이클 : 명령어를 실행하기 위해 한 번 더 메모리에 접근하는 단계
- 어떤 명령어는 인출과 실행 사이클만으로 실행되고, 어떤 명령어는 인출, 간접, 실행 사이클 모두 거쳐 실행됨
- 인터럽트 사이클
2. 컴퓨터의 핵심 부품
- CPU : 데이터와 명령와 같은 정보를 읽어 들이고, 해석하고, 실행하는 부품
- 레지스터 : CPU 안에 있는 작은 임시 저장장치
- 프로그램 카운터(PC) : 메모리에서 다음으로 읽어들일 명령어의 주소를 저장
- 명령어 레지스터(IR) : 해석할 명령어(메모리에서 방금 읽어 들인 명령어를 저장하는 레지스터)
- 범용 레지스터 : 다양하고 일반적인 상황에서 자유롭게 사용할 수 있음
- 플래그 레지스터 : 연산의 결과 혹은 CPU 상태에 대한 부가 정보인 플래그 값을 저장
- 부호 플래그 : 연산 결과의 부호(음수일 경우 1, 양수일 경우 0)
- 제로 플래그 : 연산 결과가 0인지 여부
- 캐리 플래그 : 연산 결과에 올림수나 빌림수가 발생했는지 여부
- 오버플로우 플래그 : 오버플로우가 발생했는지 여부
- 인터럽트 플래그 : 인터럽트가 가능한지의 여부
- 슈퍼바이저 플래그 : 커널 모드로 실행 중인지, 사용자 모드로 실행 중인지 여부
- 스택 포인터 : 메모리 내 스택 영역의 최상단 스택 데이터 위치를 가리키는 특별한 레지스터
- 인터럽트 : CPU의 작업을 방해하는 신호
- 동기 인터럽트(Synchronous interrupts) : CPU에 의해 발생하는 인터럽트 -> '예외'
- CPU가 프로그래밍 오류와 같은 예외적인 상황을 마주쳤을 때 발생하는 인터럽트
- 폴트 : 예외를 처리한 직후에 예외가 발생한 명령어부터 실행을 재개하는 예외
- 트랩 : 예외를 처리한 직후에 예외가 발생한 명령어의 다음 명령어부터 실행을 재개하는 예외
- 중단 : 프로그램을 강제로 중단시킬 수밖에 없는 심각한 오류를 발견했을 때 발생하는 예외
- 소프트웨어 인터럽트 : 시스템 콜이 발생했을 때 발생하는 예외
- 비동기 인터럽트(Asynchronous interrupts) : 입출력장치에 의해 발생하는 인터럽트 -> '알림' 역할
- CPU가 하드웨어 인터럽트(비동기 인터럽트) 처리하는 순서
- 입출력장치는 CPU에게 인터럽트 요청 신호 보냄
- CPU는 실행 사이클이 끝나고 명령어를 인출하기 전에 항상 인터럽트 여부 확인
- CPU는 인터럽트 요청 확인하고, 인터럽트 플래그를 통해 현재 인터럽트를 받아들일 수 있는지 여부 확인
- 인터럽트 받아들일 수 있다면 CPU가 지금까지의 작업을 백업
- CPU는 인터럽트 벡터를 참조하여 인터럽트 서비스 루틴을 실행
- 인터럽트 서비스 루틴 실행이 끝나면 백업해 둔 작업을 복구하여 실행 재개
- CPU가 하드웨어 인터럽트(비동기 인터럽트) 처리하는 순서
- 동기 인터럽트(Synchronous interrupts) : CPU에 의해 발생하는 인터럽트 -> '예외'
- CPU 성능 향상을 위한 설계
- CPU 클럭 속도
- 클럭 : 컴퓨터의 부품을 일사불란하게 움직일 수 있게 하는 시간의 단위
- 클럭 속도가 높아지면 CPU는 명령어 사이클을 더 빠르게 반복, 다른 부품도 그에 발맞춰 빠르게 작동할 것이라고 기대 가능
- 클럭 속도는 CPU의 속도 단위로 간주되기도 함
- 하지만 클럭 속도를 필요 이상으로 높이면 컴퓨터 발열이 심해짐 -> 클럭 속도를 높이는 것만으로 CPU 성능을 높이는 것에 한계가 존재
- 멀티코어와 멀티스레드
- 코어 : CPU 내에서 명령어를 읽어 들이고, 해석하고, 실행하는 부품
- 여러 개의 코어를 포함하고 있는 CPU를 멀티코어 CPU 혹은 멀티코어 프로세서라고 부름
- 스레드 : 실행 흐름의 단위
- 하드웨어 스레드 : 하나의 코어가 동시에 처리하는 명령어의 단위
- '병렬성'을 구현하기 위한 물리적인 실행 단위에 가까움
- 소프트웨어 스레드 : 하나의 프로그램에서 독립적으로 실행되는 단위
- '동시성'을 구현하기 위한 논리적인 실행 단위에 가까움
- 하드웨어 스레드 : 하나의 코어가 동시에 처리하는 명령어의 단위
- CPU 클럭 속도
병렬성 : 작업을 물리적으로 동시에 처리하는 성질
동시성 : 동시에 작업을 처리하는 것처럼 보이는 성질

- 파이프라이닝을 통한 명령어 병렬 처리
- 명령어 병렬 처리 기법 : 여러 명령어를 동시에 처리하여 CPU를 한시도 쉬지 않고 작동시킴으로써 CPU의 성능을 높이는 기법
- 명령어 파이프라이닝
- 명령어 인출(Instruction Fetch)
- 명령어 해석(Instruction Decode)
- 명령어 실행(Execute Instruction)
- 결과 저장(Write Back)
- 각각의 단계를 동시에 실행 가능
- 명령어들을 명령어 파이프라인에 넣고 동시에 처리하는 기법 => '명령어 파이프라이닝'
- 파이프라이닝 성능의 차이를 보이는 대표적인 명령어 집합 유형
- CISC(Complex Instruction Set Computer) : 다채로운 기능을 지원하는 복잡한 명령어로 구성된 명령어 집합
- RISC(Reduced Instruction Set Computer) : 짧고 규격화된 명령어, 되도록이면 1클럭 내외로 실행되는 명령어 지향
- 파이프라이닝 성능의 차이를 보이는 대표적인 명령어 집합 유형
- 파이프라인 위험 : 파이프라이닝이 실패하여 성능 향상이 이루어지지 않는 상황
- 데이터 위험 : 명령어 간의 데이터 의존성에 의해 발생
- 제어 위험 : 프로그램 카운터의 갑작스러운 변화에 의해 발생
- 구조적 위험(자원 위험) : 명령어들을 겹쳐 실행하는 과정에서 서로 다른 명령어가 동시에 ALU, 레지스터 등 같은 CPU 부품을 사용하려고 할 때 발생
- 명령어 파이프라이닝
- 명령어 병렬 처리 기법 : 여러 명령어를 동시에 처리하여 CPU를 한시도 쉬지 않고 작동시킴으로써 CPU의 성능을 높이는 기법
- 메모리
- RAM(휘발성 저장장치) : 임의 접근 메모리
- 임의 접근(-> 직접 접근) : 저장된 요소에 순차적으로 접근할 필요 없이 임의의 위치에 곧장 접근 가능한 방식
- 1. DRAM
- 시간이 지나면 저장된 데이터가 점차 사라지는 RAM
- 데이터 소멸을 막기 위해 일정 주기로 데이터를 재활성화 해야 함
- 장점 : 소비 전력 낮고, 저렴하고, 집적도가 높아 메모리를 대용량으로 설계하기 용이
- 2. SRAM
- 시간이 지나도 저장된 데이터가 사라지지 않는 RAM -> 비휘발성이라는 뜻은 아님!
- DRAM과 비교해 속도는 빠름
- 소비 전력이 크고, 가격도 비싸고, 집적도도 낮아서 대용량으로 만들 필요는 없지만 속도가 빨라야 하는 저장장치에 사용(ex. 캐시 메모리 등)
- 3. SDRAM
- 클럭 신호와 동기화된, 보다 발전된 형태의 DRAM
- 클럭 타이밍에 맞춰 CPU와 정보를 주고 받을 수 있음
- 4. DDR SDRAM
- 대역폭을 넓혀 속도를 빠르게 만든 SDRAM
- 메모리에 바이트를 밀어 넣는 순서
- 빅 엔디안
- 낮은 번지의 주소에 상위 바이트부터 저장하는 방식
- 장점 : 일반적인 숫자 체계의 읽고 쓰는 순서와 동일 -> 메모리 값 직접 읽거나, 특히 디버깅할 때 편리
- 리틀 엔디안
- 낮은 번지의 주소에 하위 바이트부터 저장하는 방식
- 장점 : 수치 계산이 편리
- 빅 엔디안
- 캐시 메모리
- CPU의 연산 속도와 메모리 접근 속도의 차이를 줄이기 위해 탄생한 저장장치로, CPU와 메모리 사이에 위치한 SRAM 기반의 저장장치
- L1 캐시, L2 캐시, L3 캐시(코어에 가까운 순)
- 캐시 메모리 크기 : L1 < L2 < L3
- 속도 : L3 < L2 < L1
- L1 캐시는 명령어만 저장하는 L1l 캐시와 데이터만 저장하는 L1D 캐시로 구분 -> 분리형 캐시
- 캐시 히트와 캐시 미스
- 캐시 메모리는 메모리보다 용량이 작아 모든 내용을 저장할 수 X -> 'CPU'가 사용할 법한 것을 저장함
- 캐시 히트 : 캐시 메모리가 예측하여 저장한 데이터가 CPU에 의해 실제로 사용되는 경우
- 캐시 미스 : 틀린 예측으로 인해 CPU가 메모리로부터 필요한 데이터를 직접 가져와야 하는 경우
- 캐시 적중률 : 캐시 히트 횟수 / (캐시 히트 횟수 + 캐시 미스 횟수)
- 참조 지역성의 원리
- 캐시 적중률을 높여야 함. 어떻게 예측함? -> 참조 지역성의 원리라는 원칙에 따라 메모리로부터 가져올 데이터 결정
- 시간 지역성 : CPU는 최근에 접근했던 메모리 공간에 다시 접근하려는 경향이 있다
- ex) 변수
- 공간 지역성 : CPU는 접근한 메모리 공간의 근처에 접근하려는 경향이 있다
- ex) 배열
- 캐시 메모리의 쓰기 정책과 일관성
- 즉시 쓰기
- 캐시 메모리와 메모리에 동시에 쓰는 방법
- 메모리를 항상 최신 상태로 유지하여 캐시 메모리와 메모리 간 일관성이 깨지는 상황을 방지
- 데이터 쓸 때마다 메모리를 참조해야 하므로 버스의 사용 시간과 쓰기 시간이 늘어난다는 단점
- 지연 쓰기
- 캐시 메모리에만 값을 써 두었다가 추후 수정된 데이터를 한 번에 메모리에 반영하는 방법
- 메모리 접근 횟수 줄일 수 있어 즉시 쓰기에 비해 속도는 더 빠르다
- 메모리와 캐시 메모리 간의 일관성이 깨질 수 있다는 위험 감수해야 함
- 즉시 쓰기
- 보조기억장치 : 전원이 꺼져도 저장된 정보가 사라지지 않는 비휘발성 저장장치
- 보조기억장치의 본분
- 전원이 꺼져도 데이터를 안전하게 보관
- CPU가 필요로 하는 정보를 조금이라도 빠른 성능으로 메모리에 전달하는 것
- 하드 디스크 드라이브 : 자기적인 방식으로 데이터를 읽고 쓴느 보조 기억장치
- 플래시 메모리 기반 저장장치 : 전기적인 방식으로 데이터를 읽고 쓰는 반도체 기반의 저장장치(USB, SD카드, SSD)
- RAID : 데이터의 안전성 or 성능을 확보하기 위해 여러 개의 독립적인 보조기억장치를 마치 하나의 보조기억장치처럼 사용하는 기술
- RAID0 : 데이터를 여러 보조기억장치에 단순하게 나누어 저장하는 구성 방식
- 장점 : 빠른 입출력 속도
- 단점 : 저장된 정보가 안전하지 않다
- RAID1 : 완전한 복사본을 만들어 저장하는 구성 방식 -> '미러링'
- 장점 : 복구가 간단하고 안정성 높다
- 단점 : 사용 가능한 용량이 적어짐
- RAID4 : 패리티 정보를 저장하는 디스크를 따로 두는 구성 방식
- 패리티 : 오류를 검출할 수 있는 정보
- 장점 : 적은 하드 디스크로 안전하게 데이터 보관 가능
- 단점 : 패리티를 저장하는 장치에 병목 현상 발생
- RAID5 : 패리티를 분산하여 저장하는 구성 방식
- RAID4의 단점인 병목 현상 보완 가능
- RAID6 : 서로 다른 2개의 패리티를 두는 구성 방식 -> 오류를 검출하고 복구할 수 있는 수단이 2개가 생긴 것
- 장점 : RAID4나 5에 비해 안전성이 높다
- 단점 : 새로운 정보를 저장할 때마다 함께 저장할 패리티가 2개이므로 5에 비해 쓰기 속도는 일반적으로 느리다
- RAID0 : 데이터를 여러 보조기억장치에 단순하게 나누어 저장하는 구성 방식
- 입출력 기법 - CPU와 장치 컨트롤러가 정보를 주고받는 작업
- 프로그램 입출력 : 프로그램 속 명령어로 입출력 작업을 수행하는 방법
- 인터럽트 기반 입출력 : 다중 인터럽트
- 인터럽트가 여러 입출력장치로부터 동시다발적으로 발생하는 경우
- 우선순위가 더 높은 인터럽트가 우선적으로 처리
- CPU는 플래그 레지스터 속 인터럽트 비트가 활성화되어 있는 경우, 혹은 인터럽트 비트를 비활성화해도 무시할 수 없는 인터럽트인 NMI(Non-Maskable Interrupt)가 발생한 경우, 우선순위가 높은 인터럽트부터 먼저 처리
- PIC(Programmable Interrupt Controller) : 다중 인터럽트를 처리하기 위한 하드웨어
- PIC는 여러 장치 컨트롤러에 연결되어 있어 장치 컨트롤러에서 보낸 하드웨어 인터럽트 요청들의 우선순위를 판별한 뒤, CPU에게 지금 처리해야 할 하드웨어 인터럽트가 무엇인지 알려 주는 장치
- 우선순위가 더 높은 인터럽트가 우선적으로 처리
- 인터럽트가 여러 입출력장치로부터 동시다발적으로 발생하는 경우
- DMA 입출력 : CPU를 거치지 않고도 입출력장치와 메모리가 상호작용할 수 있는 입출력 방식
'Computer Science' 카테고리의 다른 글
| [이것이 컴퓨터 과학이다] 2. 운영체제 (5) | 2025.07.03 |
|---|---|
| [전공] CS 지식 관련 사이트 (0) | 2024.03.22 |