1. 컴퓨터 구조의 큰 그림
컴퓨터가 이해하는 정보는 무엇일까
- 컴퓨너는 프로그래밍 언어를 직접 이해하지 못한다. (프로그래밍 언어는 사람에게 더 친화적)
- 따라서 데이터와, 명령어로 컴퓨터를 이해시켜야한다!
데이터란?
- 데이터란, 숫자, 문자 등 정적인 정보를 의미한다. 우리가 API를 요청할 때 parameter에 넣거나, 응답해서 받아오는 곳 속엔 모두 데이터가 존재한다. 후에 명령어를 사용할 때 이 명령의 대상이 바로 데이터다.
//예시
{
sucess: true,
data : {
user: "정보",
name: "홍길동",
}
}
명령어는?
- 데이터를 활용하는 정보
- 데이터를 더한다거나, 출력한다거나, 저장한다거나... 데이터 관련 처리를 일컬어 명령어라고 부른다.
- CPU의 종류에 따라 실행 가능한 명령어의 종류, 처리 양상이 달라질 수 있음!
명령어 사이클이란?
- CPU가 하나의 기계어나 명령어를 처리하는 과정을 의미
- 아래와 같은 단계로 구성이 된다.

인출 사이클
- 프로그램 카운터(PC)가 가리키는 메모리 주소에서 명령어를 가져옴
- 이를 명령어 레지스터에 저장하고, PC 값 증가를 통해 다음 명령어를 가리키도록 수행
디코드 사이클
- 이 레지스터에 저장된 명령어를 해석하여 어떤 연산을 수행해야하는지 판단, 결정
실행 사이클
- 디코드 사이클에서 나온 결과를 기반으로 실제 연산 수행
- 이 때 데이터 이동이나, 산술 또는 논리 연산이 수행됨
간접 사이클
- 필수는 아니며, 간접 주소 지정방식인 경우 실제 데이터가 저장된 메모리 주소를 찾는 과정
- 메모리 추가 접근
인터럽트 사이클
- 필수는 아니며, 인터럽트 발생 시 명령어 중단 후 인터럽트 처리 루틴(ISR) 전환
컴퓨터의 필수 부품들!
CPU
- 정보를 읽고, 해석하고, 실행하는 부품
- Central Processing Unit
- 구성요소는 다음과 같음
- ALU - 산술논리 연산장치로, 일종의 계산기
- CU - 제어장치로, 명령어를 해석 후 제어 신호를 내보내는 장치, 해당 신호의 방향에 따라 무엇을 작동 시킬지 결정
- Register - 레지스터로, CPU 내부의 작은 임시 저장장치임. 데이터, 명령어 처리 중 중간 값을 저장함
메모리
- 우리가 흔히 아는 RAM 또는 ROM을 메인 메모리라고 부른다!
- CPU가 처리하는 과정중 생기는 정보들을 저장하는 공간(데이터와 명령어)
- 주소라는 개념을 사용하며, 휘발성인 특징이 있음
주소란...
컴퓨터의 속도 보장을 위해, 원하는 데이터 또는 명령어를 찾기위해 사용하는 개념
데이터 자체를 저장해버리면, 용량적인 측면에서 많은 손해를 본다.
- n번지에 해당하는 데이터를 가져와라! 같이, 원하는 정보를 저장하고, 그 주소를 기억하여 사용
캐시 메모리
- 캐시메모리란 CPU가 더 빨리 메모리의 저장된 값에 접근할 수 있도록 하기 위해 고안된 저장장치임
- 여러 종류가 있다... L1, L2, L3 캐시메모리로, 숫자가 클 수록 느리며 용량은 크다.
보조 기억 장치
- 메인 메모리의 경우, 휘발성이라 컴퓨터 전원이 꺼진 경우, 저장된 정보가 모두 날아감
- 하지만 컴퓨터는 그러면 안되므로 보조 기억 장치를 사용함
- 비휘발성 장치이고, 용량이 아주 크다
- 대신 느리다.
- 또한, CPU는 보조 기억 장치에 저장된 정보를 바로 가져와 실행할 수 없음... 메인 메모리에 적재하여 사용해야 함
입출력 장치
- 우리가 키보드, 마우스, 스피커 등 직접 조절하고 치면서 컴퓨터 내부에 정보를 보내거나,
- 모니터처럼 컴퓨터로부터 정보를 받을 수 있는 장치를 입출력 장치라고 함
- 주변장치라고도 한다.
메인 보드와 버스
- 메인 보드는 마더 보드라고도 부른다.
- 핵심 부품 및 여러 부품을 연결하는 단자, 슬롯이 존재!
- 서로 정보를 받기 위해, 버스라는 통로를 이용함
- 시스템 버스 - 핵심 부품을 연결하는 통로
컴퓨터가 이해하는 정보
- 컴퓨터는 기본적으로 0과 1만 이해 가능하다.
- 가장 적은 정보 단위를 비트라고 한다.
- 각 비트별로, 2의 N승 만큼 데이터를 표현할 수 있다. 예시로, 3비트면 8가지, 6비트면 64가지의 정보를 표현할 수 있다.
- 이 때 숫자로 표현가능한 부분은 2ⁿ - 1 이다! (0부터 시작)
- 각 비트별로, 2의 N승 만큼 데이터를 표현할 수 있다. 예시로, 3비트면 8가지, 6비트면 64가지의 정보를 표현할 수 있다.
비트의 크기...
- 1000비트 = 1kB, 1000kB = 1MB, 1000MB = 1GB
- 위와 같은 크기로 증가하며, 범용적으로 TB(1000GB)까지 사용함
- TMI) 원래 2의 10승이라 1024씩 증가하나, 이는 kiB, GiB처럼 다른 단위로 표현한다.
데이터 - 0과 1로 숫자 표현
- 컴퓨터가 쓰는 01010101을 보자면 우리가 일상적으로 사용하는 십진법의 관점에서 보기엔 좀 이상해보인다...
- 컴퓨터는 2진법을 사용하기 때문!
- 이런 경우에 숫자가 길어진다는 단점이 있어 8진법이나 16진법 등 확장법도 존재한다.
- 소수의 경우 1.10101 ^ 3 처럼 m * 2ⁿ 꼴로 나타낸다.
부동 소수점의 경우 이해가 오래걸려, 다음 블로그를 참조했습니다. - https://cbh2031.tistory.com/110
부동 소수점 2진수 표현
부동 소수점 2진수 표현에 대해서 작성을 합니다 2가지의 방법이 있습니다 64bias 와 127bias 표현법이 있습니다 주로 64 bias 를 사용하며 가끔씩 127bias 가 나타나기도 합니다 컴퓨터는 숫자 0과 1을
cbh2031.tistory.com
데이터로 문자 표현하기
- 0과 1로 숫자 표현은 가능... 근데 문자는 어떻게?
- 기존에는 아스키 문자를 사용
- 8비트로 구성되었으나 1비트는 패리티 비트로 오류 검출을 위해 사용
- 7비트로 데이터를 표현, 총 128가지의 정보 표현 가능함
- 알고리즘에서 사용하는 것이 이 아스키 코드
- 그러나, 한글이 없음
- EUC-KR은 한글을 지원
- 그러나 2350개 정도를 지원하는데, 이정도로는 한글을 모조리 지원할 순 없음
- 그래서 출시된 것이 유니코드
- 한글, 이모티콘 까지 모두 코드로 표현 가능한 통일된 문자 집합
- 한글 이외에도 대부분의 언어를 지원
- UTF-8,UTF-16, UTF-32 등 지원하는 방식이 다양함
- 각각은 가변 길이 인코딩 방식(인코딩의 결과 길이가 일정하지 않음)
- base64의 경우 이진 데이터를 인코딩하는데 주로 사용
명령어
- 앞서 말했 듯 데이터를 처리하는 정보(연산)를 담고 있으며, 수행할 동작과 수행할 대상으로 구성
- 수행할 동작을 연산 코드(연산자), 저장된 위치를 오퍼랜드(피연산자) 라고 함
- 연산 코드는 다양하지만, CPU에 따라 연산 코드의 종류가 달라짐.
기계어와 어셈블리어
- CPU가 이해할 수 있도록 0, 1 표현 정보를 그대로 표현한 언어를 기계어라고 함
- 이를 읽기 편한 형태로 단순 변역한 것이 어셈블리어
2. CPU
레지스터
- CPU안에 있는 작은 임시 저장 장치
- 레지스터는 각각 이름과 역할이 있으며, 이는 WinDbg나 gdb 등 디버깅 도구를 통해 확인할 수 있음
프로그램 카운터
- 메모리에서 다음으로 읽어들일 명령어 주소를 저장
- PC, 또는 IP(명령어 포인터)라고도 함
- 값을 1씩 증가시켜서, 순차적으로 실행될 수 있도록 함
- if나 for에선 바뀔 수도 있다.
명령어 레지스터
- 해석할 명령어를 저장(메모리에서 방금 읽어들인 명령어)
- 명령어 해석 후 ALU로 연산 또는 다른 부품으로 제어신호를 보냄
범용 레지스터
- 다양하고 일반적으로 자유로이 사용할 수 있는 레지스터, 여러 개 존재
플래그 레지스터
- 연산 결과, 또는 CPU 상태에 대한 부가 정보(플래그)를 저장하는 레지스터
- 부호, 제로, 캐리, 오버플로우, 인터럽트, 슈퍼바이저 등 다양한 플래그의 정보를 담고 있음
스택 포인터
- 컴퓨터는 기본적으로 스택과 같은 형태로 사용 가능 주소 공간을 가지고 있음
- 이 때, 각 영역의 최상단을 가리키는 레지스터를 스택 포인터라고 함
인터럽트
- CPU의 작업을 방해하는 신호
- 우리가 흔히 마주치는 예외나, 오류나... 입출력 장치로 다른 것을 입력하거나
- 동기, 비동기 인터럽트로 나뉨
- 동기는, 프로그래밍 오류와 같은 예외적인 상황(예외라고도 부름 / 어떠한 행동을 끝내고 알림을 보내는 것)
- 비동기는, 입출력 장치에 의해 발생(어떤 과정 사이에서, 다른 행동을 하는 주체가 알림을 보내는 것)
- 비동기 인터럽트를 하드웨어 인터럽트라고도 한다.
하드웨어 인터럽트
- 효율적으로 명령어를 처리하기 위함
- 인터럽트가 없을 경우, 해당 작업의 완료시기를 알 수 없어 주기적으로 폴링을 해야함 (비효율)
인터럽트 처리 순서
- 입출력장치가 CPU에게 인터럽트 신호 보냄
- CPU는 실행 사이클이 끝나면, 명령어 인출 전 인터럽트 존재여부를 확인
- 있으면, 인터럽트 플래그를 통해 현재 인터럽트를 받아들일 수 있는지 판단
- 인터럽트를 받아들일 수 있으면, 지금까지의 작업을 백업
- 이후 인터럽트 서비스 루틴 실행(여기서 인터럽트 벡터를 참조)
- ISR이 종료되면, 백업한 작업을 복구 후 실행 재개
막을 수 있는 인터럽트와 막을 수 없는 인터럽트
- 원래 CPU는 인터럽트 플래그를 통해, 수용할지 무시할 지 결정할 수 있음
- 그러나, 우선순위가 높은 경우(하드웨어 고장 또는 정전...) 무시할 수 없는 것이 있는데, 이를 NMI라고 함
인터럽트 서비스 루틴(ISR)
- 인터럽트를 처리하기 위한 프로그램
- 인터럽트 핸들러라고도 함
- 인터럽트를 어떻게 처리하고, 작동할지에 대한 정보로 이루어진 프로그램
인터럽트 벡터
- ISR 실행시 참조하는 정보로, 인터럽트 서비스 루틴을 식별하기 위한 정보임
- 인터럽트 서비스 루틴의 시작 주소를 알 수 있음
예외
- 폴링, 트랩, 중단, 소프트웨어 인터럽트 등...
- 예외 발생 시 해당 예외를 처리(동기적)
- 예외 발생 명령어부터 처리하면 폴트
- 페이지 폴트
- 예외 발생 명령어의 다음 명령어 부터 처리하면 트랩
- 디버깅 브레이크 포인트
- 예외 발생 명령어부터 처리하면 폴트
CPU 성능 향상을 위한 설계
CPU 클럭 속도
- 클럭이란, 컴퓨터의 부품을 움직일 수 있는 시간 단위(clock)
- Hz단위로 측정하며, 클럭의 반복 속도를 측정
- 오버 클럭시, 발열의 위험이 있음
멀티 코어, 멀티 쓰레드
- 코어의 경우, 인간의 뇌 느낌(실행, 처리, 연산 등)
- 쓰레드의 경우, 실행 흐름의 단위
- 하드웨어 쓰레드는 하나의 코어가 동시에 처리하는 명령어 단위(CPU에서 사용)
- 이를 논리 프로세서라고도 함
- 소프트웨어 쓰레드는 하나의 프로그램에서 독립적으로 실행되는 단위(프로그래밍 언어, 운영체제 등에서 사용)
- 하드웨어 쓰레드는 하나의 코어가 동시에 처리하는 명령어 단위(CPU에서 사용)
병렬성과 동시성
- 병렬성은 작업을 물리적으로 동시에 처리한다. (하드웨어 쓰레드에 적합)
- 동시성은 작업을 동시에 처리하는 것 처럼 보이게 한다.(소프트웨어 쓰레드에 적합)
파이프라이닝을 통한 명령어 병렬 처리
명령어 병렬 처리 기법
- 여러 명령어를 동시에 처리하며 CPU를 작동하여 CPU의 성능을 높이는 기법
- 명령어 인출, 해석, 실행, 결과 저장 총 4단계로 구성되어있음
- 이 때, 같은 단계가 겹치지 않으면, 각 단계를 동시에 실행 가능
- 이를 명령어 파이프라이닝이라고 한다.
RISC & CISC
- 명령어 파이프라이닝을 사용하는 대표적인 명령어 집합 유형
- CISC는 인텔 x86 CPU 등...
- RISC는 애플 M1 CPU
- CISC는 다기능 지원 복잡한 명령어로 구성, 적은 명령어로도 프로그램 실행 가능
- RISC는 짧고 규격화된 명령어 집합으로 1클럭 내외로 실행되는 명령어를 지향
글만 보면 CISC가 우세할 것 같으나, 복잡하기에 명령어 하나에 여러 클럭주기가 드는 것은 물론수행 시간이 뒤죽박죽이기에 파이프라이닝에는 비효율적임.
파이프라인 위험
- 파이프라이닝이 실패하여 성능 향상이 이루어지지 않는 현상
- 데이터 위험
- 명령어 간의 데이터 의존성에 의해 발생(병렬 처리 불가 등...)
- 제어 위험
- 프로그램 카운터의 변화에 의해 발생
- 실행 흐름이 갑자기 바뀌는 경우 (점프나 조건 점프 때문에)
- 구조적 위험
- 명령어를 겹쳐 실행하는 과정에서 다른 명령어들이 같은 ALU나 레지스터 등을 사용하려고 할 때 발생
- 자원 위험이라고도 부름
메모리
- CPU에서 사용하는 정보를 저장하는 공간
- 메인 메모리는 휘발성, 보조 메모리는 비휘발성
임의 접근, 순차 접근
- 임의 접근이란, RAM의 특징 중 하나로, 주소를 바로 접근 하는 것이 가능하게 함
- 반대로 순차 접근은 처음부터 (1~10번지) 순차로 접근해야함. 오래걸림
DRAM
- 메인 메모리 중 하나로, 데이터가 동적으로 변한다는 특징이 있음
- 시간이 지나면 저장된 데이터가 사라짐
- 일정 주기로 데이터를 재활성화 시켜서, 소멸을 방지함
- 소비 전력이 낮고, 저렴하여, 메모리를 대용량으로 설계하는데 유리
SRAM
- 데이터가 시간이 지나도 사라지지 않는 RAM
- 그러나 이 역시도 전력이 공급되지 않으면 메모리는 사라진다.
- DRAM보다 속도가 빠르나, 소비전력과 가격이 높아 캐시 메모리 등에 사용
SDRAM
- 클럭신호와 동기화 시킨 발전된 형태의 DRAM의 종류
- 클럭에 맞춰 작동하며 CPU와 정보 교류가 가능
DDR SDRAM
- 대역폭을 넓혀 속도를 빠르게 만든 SDRAM
- DDR2 처럼 뒤의 숫자가 클 수록, 2의 n승 만큼 대역폭이 넓어진다.
빅 엔디안, 리틀 엔디안
- 메모리를 바이트 단위로 관리하는데, 이 바이트를 어떻게 저장하는지 방식에 따라 빅, 리틀으로 구분된다.
빅 엔디안
- 낮은 번지의 주소에 상위 바이트를 저장
- 1A2B3C4D라면,
- 가장 낮은 a번지에 1A를 저장...
- 그 이후 위로가면서 순차적으로 저장
- 메모리 값을 직접 읽거나 디버깅 할 때 편리함(순차니까)
- MSB 부터 저장
리틀 엔디안
- 빅 엔디안의 반대로, 높은 번지의 상위 바이트를 저장
- 수치 계산이 편리하나, 보기는 불편함
- LSB부터 저장
MSB와 LSB
- MSB란, 숫자의 크기에 가장 큰 영향을 미치는 유효숫자로, 가장 왼쪽의 비트를 의미
- LSB란, 숫자의 크기에 가장 적은 영향을 미치는 유효숫자로, 가장 오른쪽의 비트를 의미
캐시 메모리
- CPU 연산속도와 메모리 접근 속도 차이를 줄이기 위해 고안된 메모리
- SRAM 기반 저장장치
- 일부 데이터를 미리 캐시데이터로 가져오면, 시간을 절약할 수 있음
- 우리가 웹 개발에 사용하는 api 데이터도 TanStack - Query처럼 캐싱을 이용하면 확연하게 api호출 시간을 줄일 수 있음!!
- 거리에 따라 L1, L2, L3로 구분되며, 이 때 L3는 CPU 외부에 위치함
- L1 캐시의 경우, 명령어만을 저장하고, 데이터만을 저장하는 곳으로 구분되어있음
- 이를 분리형 캐시라고 함
- L1 캐시의 경우, 명령어만을 저장하고, 데이터만을 저장하는 곳으로 구분되어있음
캐시 히트와 캐시 미스
- 캐시 메모리가 용량이 작으므로, 메모리는 미리 실제로 사용할 데이터를 불러옴
- 이 때, CPU에 의해 실제로 이 데이터가 사용된다면 캐시 히트
- 사용되지 않아 직접 데이터를 가져와야 하는 경우에는 캐시 미스
- 캐시 적중률 = 캐시 히트 / (캐시 히트 + 캐시 미스)
참조 지역성의 원리
- 캐시 메모리가 CPU가 사용할만한 데이터를 예측하는데 사용하는 원리
- 시간 지역성 : CPU는 최근 접근한 메모리에 다시 접근하려 한다.
- 공간 지역성 : CPU는 접근한 메모리 공간의 근처에 접근하려 한다.
- 시간지역성의 대표적인 사례는 변수
- 공간지역성의 대표적인 사례는 배열
캐시 메모리 쓰기 정책, 일관성
- 캐시 메모리에 저장되어있는 상태에서, 메모리의 값을 변경하면 해당 캐시메모리에는 값 변경이 적용되지 않아 잘못된 값이 호출될 수 있음. 방지를 하기위해, 두 가지 방법을 사용
- 직접쓰기는, 캐시 메모리와 기존 메모리에 동시에 적용하는 방법
- 이런 경우에는, 메모리 및 캐시를 동기화 시켜 일관성은 확보하지만, 항상 메모리를 참조해야하기에 시간이 늘어남
- 지연 쓰기는, 캐시에만 값을 써두고 추후에 메모리에 적용하는 기법
- 이는 속도는 향상되지만, 일관성이 깨질 수 있어 조심해야하는 방법
- 직접쓰기는, 캐시 메모리와 기존 메모리에 동시에 적용하는 방법
3. 보조 기억장치, 입출력 장치
RAID
하드디스크 드라이브(HDD)
- 자기적인 방식으로 데이터를 읽고 쓰는 장치
플래시 메모리
- 전기적인 방식으로 데이터를 읽고쓰는 반도체 기반 장치
- SSD, USB 등
RAID
- 데이터의 안전성, 성능 확보를 위해 여러개의 독립 보조기억장치를 하나의 장치처럼 사용할 수 있게하는 기술
- 여러 방법이 있으며, RAID 레벨이라고 한다.
RAID0
- 단순하게 여러 보조기억장치를 저장하는 방법
- 각 보조기억장치에 1번, 2번, 3번, 4번 순으로 저장
- 스트라이핑 저장 방식이라고도한다.
- 빠른 입출력속도를 가졌으나, 하나가 고장나면 데이터 손실이 심각하다.
RAID1
- 완전한 복사본을 만들어 저장하는 방식
- 미러링 방식이라고도 부름
- 안전하지만, 복사본의 크기 때문에 사용 가능한 용량이 적어짐
RAID4
- 패리티 정보를 저장하는 디스크를 따로 두는 방식
- 패리티 저장 장치에 병목현상이 발생할 가능성이 있음
- 새로운 데이터가 올 때 마다, 패리티 저장 디스크에도 쓰기 작업을 수행해야함
RAID5
- 패리티 정보를 분산하여 저장하는 구성 방식
- 각각의 데이터가 들어간 보조기억장치 사이에, 패리티 비트를 저장
- 병목 현상을 보완할 수 있음
RAID6
- 패리티 비트가 하나가 아닌, 2개를 저장하는 방식
- 안전성이 높으나, 데이터 생성 시 패리티비트를 두번 저장해야하므로 쓰기가 4, 5방식에 비해 느림
Nested RAID
- 위 설명한 레벨이외에도, 혼합한 방식이 있는데, 이를 Nested RAID라고 함
- 대표적으로 RAID10, RAID50 등이 있음
입출력 기법
- 보조기억장치도 결국 메모리를 보조하는 입출력장치로 볼 수 있음
장치 컨트롤러
- CPU와 입출력사이의 통신을 중개하는 하드웨어
장치 드라이버
- 장치 컨트롤러의 동작을 알고, 컴퓨터 내부와 정보를 주고받을 수 있게 하는 프로그램
- 대부분 기본 운영체제에 포함되어있는 경우가 많음
- 장치 드라이버가 없으면 블루투스 키보드, 마우스 등을 사용할 수 없음
프로그램 입출력
- 프로그램 속 명령어로 직접 입출력 작업 수행
- 입출력 명령어를 ..알아야 할 듯?
인터럽트 기반 입출력 - 다중 인터럽트
- 인터럽트가 여러 동시다발적으로 발생하는 경우를 뜻함
- 일반적으로 인터럽트에서 우선순위가 높은대로 처리가 됨
프로그래머블 인터럽트 컨트롤러(PIC)
- 다중 인터럽트를 처리하기 위해 사용되는 장치
- 장치 컨트롤러에서 보낸 인터럽트들의 우선순위를 파악하여 CPU에게 처리 순서를 알려주는 장치
- NMI까지는 판별하지는 않는다고 한다.
- 많은 인터럽트를 관리하기 위해, 상위 PIC에 하위 PIC를 연결해서 사용하는 방식이 일반적이다.
DMA 입출력
- 직접 메모리에 접근할 수 있는 입출력 기능
- 시스템 버스에 연결된 DMA 컨트롤러가 필요
- 입출력장치의 장치 컨트롤러는 입출력 전용 버스에 연결
- 이 때, 시스템 버스는 동시에 사용할 수 없기 때문에, CPU가 사용하지 않을 때 조금 씩 사용하는 방식이나 양보 받는 방식으로 사용
- 이를 사이클 스틸링이라고도 한다.