📌 컴퓨터구조

  • 참고 강의 : 혼자 공부하는 컴퓨터구조 + 운영체제

컴퓨터 구조 시작하기

  • 중요한 요소들 : 성능, 용량, 비용
  • 컴퓨터가 이해하는 정보 : 데이터, 언어

데이터

  • 숫자, 문자, 이미지, 동영상과 같은 정적인 정보
  • 컴퓨터는 0과 1로 이루어진 데이터만 이해할 수 있다.

명령어

  • 컴퓨터를 실질적으로 움직이는 정보
  • 데이터는 명령어를 위한 일종의 재료 ex. 명령어 : 1과 2를 더해라
    • 데이터 : 1, 2

컴퓨터의 4가지 핵심 요소

  • CPU, 메모리(주기억장치), 보조기억장치, 입출력장치
  • CPU, Central Processing Unit(중앙처리 장치)
    • 컴퓨터 시스템을 통제하고 프로그램의 연산을 실행하는 컴퓨터의 제어 장치
  • 메모리
    • 현재 실행되는 프로그램의 명령어와 데이터를 저장한다.
    • 메모리에 저장된 값을 효율적으로 접근하기 위해 주소(address) 개념 사용
    • RAM(Random Access Memory) : 휘발성, 작업 중인 파일을 한시적으로 저장한다. 전원이 차단되면 데이터가 사라진다. 일반적으로 메모리는 RAM을 지칭한다.
    • ROM(Read Only Memory) : 비휘발성, 컴퓨터에 지시사항을 영구하게 저장한다. 전원이 차단되어도 데이터가 사라지지 않는다.
  • 보조기억장치 : 주기억장치보다 느리지만, 데이터를 영구적으로 보관할 수 있는 장치
    • HHD(Hard Disk Driver), SSD(Solid State Driver)
    • 메모리는 실행할 정보를 저장하고, 보조기억장치는 보관할 정보를 저장한다.
  • 입출력장치 : 컴퓨터 외부에 연결되어 컴퓨터 내부와 정보를 교환할 수 있는 부품

 

  • 메인 보드(Main board)
    • 컴퓨터의 핵심 부품들을 연결한다.
    • 메인 보드의 부품들은 버스(bus)라는 통로를 이용해서 정보를 주고받을 수 있다.
  • 시스템 버스
    • 메인 메모리와 마이크로프로세서 사이 데이터를 전달하기 위해 사용되는 커넥터와 케이블로 구성된 통로
    • 컴퓨터 시스템의 주요 부품 사이에서 데이터와 제어 시그널을 위한 통신을 제공한다.
    • 구성 요소 : address bus(주소 버스), control bus(제어 버스), data bus(데이터 버스)
    • 주소 버스
      • CPU가 주기억 장치나 입출력 장치로 기억장치 주소를 전달하는 통로.
      • 단방향 버스(주소만 전달)
      • 물리적 주소를 찾는 목적으로 사용.
      • 모든 주소 버스는 bit 형태로 CPU 또는 DMA(Direct Memory Access)에 의해 사용
    • 제어 버스
      • CPU에 의해 사용되고, 컴퓨터 내에 포함된 장치들과의 통신에 사용된다.
      • 데이터 버스와 주소 버스를 제어하기 위해 제어 신호들을 전송하는 통로
      • 양방향 버스(읽기, 쓰기 동작 모두 수행)
    • 데이터 버스
      • 데이터 전달에 사용
      • 양방향 버스

CPU 구성 요소

  • ALU(Arithmetic and Logical Unit)
    • 산술논리연산장치
    • 사칙연산 같은 두 숫자의 산술 연산 계산
    • 배타적 논리합, 논리곱, 논리합 같은 논리 연산 계산
  • 제어 장치(Control Unit, CU)
    • 프로세서의 조작을 지시하는 CPU 의 한 요소
    • 제어 신호를 보내고, 명령어들을 읽고 해석, 데이터 처리를 위한 시퀀스를 결정
    • 제어 신호 : 메모리 읽기 or 메모리 쓰기
  • 레지스터(Register)
    • CPU 내부에 위치한 고속 메모리
    • 바로 사용할 수 있는 데이터를 담고 있는 영역
    • PC, Program Counter(프로그램 카운터)
      • 메모리에서 가져올 명령어의 주소
    • IR, Instruction Register(명령어 레지스터)
      • 해석할 명령어(메모리에서 방금 가져온 명령어)
    • MAR, Memory Address Register(메모리 주소 레지스터)
      • 메모리의 주소를 저장
    • MBR, Memory Buffer Register(메모리 버퍼 레지스터)
      • 메모리와 주고받을 값(데이터 명령어)
    • 플래그 레지스터
      • 연산 결과 또는 CPU 상태에 대한 부가적인 정보
    • 범용 레지스터
      • 다양하고 일반적인 상황에서 자유롭게 사용
      • EAX(Accumulator), EBX(Base), ECX(Counter), EDX(Data)...
    • 스택 포인터
      • 스택 주소 지정에 사용, 스택의 top
    • 베이스 레지스터
      • 기존 주소 지정에 사용

명령어 실행 예시

  • 제어 장치는 1번지의 명령어를 읽기 위해서 메모리에 읽기 제어 신호를 보낸다.

  • 메모리는 1번지에 있는 명령어를 CPU 에게 전달, 이 명령어는 레지스터에 전달된다.
  • 레지스터에 들어온 명령어를 제어장치가 해석한다.
  • 레지스터에 있는 명령어(3번지와 4번지를 더하기)에서 3번지와 4번지의 데이터를 얻기 위해 메모리에 메모리 읽기 제어 신호를 보낸다.

  • 메모리에서 3번지와 4번지의 데이터를 CPU 에게 전달, 각각 레지스터에 데이터가 저장된다.
  • ALU 에서 레지스터에 있는 데이터로 계산
  • 계산한 결과 값은 레지스터에 저장된다.
  • 명령어 실행 종료


데이터 표현

  • 정보(information) : 가공된 데이터를 의미한다. 어떤 사물에 대한 소식이나 자료
  • 데이터(data) : 가공되지 않은 데이터.
  • 정보 단위

  • 워드(word)
    • CPU 가 한 번에 처리할 수 있는 정보의 크기 단위
  • 이진법(Binary)
    • 0과 1로 수를 표현하는 방법
    • 숫자가 1을 넘어가는 시점에 자리
    • 2의 보수(음수 표현) : 모든 0과 1을 뒤집고 1을 더한다.
    • ex. 11(2) = 00(2) = 01(2)
    • 양수인지 음수인지 구분하는 방법? : CPU에 있는 레지스터인 플래그(flag)로 구분한다.
    • 접두어 : 0b

  • 16진법(Hexadecimal)
    • 십진법보다 이진수와의 변환이 간단해서 사용
    • 십진수 : 16 = 16진수 : 10
    • 접두어 : 0x


문자 집합(Character Set)

  • 컴퓨터가 이해할 수 있는 문자의 모음
  • 인코딩(Encoding) : 코드화 => 문자를 0, 1으로 이루어진 문자 코드로 변환
  • 디코딩(Decoding) : 코드 해석 => 0, 1으로 이루어진 문자 코드를 문자로 변환

아스키 코드(ASCII : American Standard Code for Information Interchange)

  • 알파벳, 아라비아 숫자, 일부 특수 문자 및 제어 문자
  • 정보 교환용 7비트 부호 체계
  • 8 비트 중 1비트는 오류 검출을 위해 사용되는 패리티 비트(Parity Bit)
  • 7 비트로 하나의 문자 표현 : 2^7 = 총 128개의 부호 사용

유니코드(Unicode)

  • 전 세계의 모든 문자 집합
  • 인코딩 방식 : utf-8, utf-16, utf-32

UTF-8

  • Unicode Transformation Format
  • 가변 길이 인코딩 : 한 글자가 1~4바이트 중 하나로 인코딩 될 수 있다.

고급 언어와 저급 언어

  • 고급 언어(High-Level Language)
    • 사람 중심 언어
    • 실행을 위한 번역이 필요하다.
    • 컴파일 언어, 인터프리터 언어
  • 저급 언어(Low-Level Language)
    • 기계 중심 언어
    • 빠른 실행 속도
    • 기계마다 다른 코드를 가진다.
    • 기게어(Machine Language) : 0과 1로 이루어진 언어
    • 어셈블리어(Assembly Language) : 0과 1로 이루어진 기계어를 읽기 편한 형태로 번역한 언어
      • push rbp, pop rbp, ret

컴파일 언어

  • 소스 코드(고급 언어) -> 컴파일러(컴파일) -> 목적 코드(저급 언어)
  • 소스코드를 모두 기게어로 변환하기 때문에 인터프리터보다 시간이 소요
  • 런타임 상황에서는 이미 모든 소스코드가 변환되어 있어 빠른 실행 가능
  • C, C++

인터프리터 언어

  • 소스코드 -> 인터프리터 -> 목적 코드
  • 기계어로 변환하는 과정에서 인터프리터에 의해 한 줄씩 해석, 실행한다.
  • Python, Ruby

명령어의 구조

  • 명령코드(Operation Code) : 명령어가 수행할 연산
  • 오퍼랜드(Operand) : 연산에 사용할 데이터 또는 데이터의 주소
  • 오퍼랜드는 1개도 없을 수도 있고, 여러 개를 가질 수도 있다.

  • 연산 코드의 종류
    • 데이터 전송
      • MOVE : 데이터를 옮겨라
      • STORE : 메모리에 저장해라
      • LOAD(FETCH) : 메모리에서 CPU로 데이터를 가져와라
      • PUSH : 스택에 데이터를 저장해라
      • POP : 스택의 최상단 데이터를 가져와라
    • 산술/논리 연산
      • ADD, SUBTRACT, MULTIPLY, DIVIDE : 사칙 연산
      • INCREMENT, DECREMENT : 오퍼랜드에 1 증감, 차감
      • AND, OR, NOT
      • COMPARE : 두 개의 숫자 또는 TRUE, FALSE 값을 비교해라
    • 제어 흐름 변경
      • JUMP : 특정 주소로 실행 순서 이동
      • CONDITIONAL JUMP : 조건에 부합하면 특정 주소로 실행 순서 이동
      • HALT : 프로그램의 실행 중지
      • CALL : 되돌아올 주소 저장, 특정 주소로 실행 순서 이동
      • RETURN : CALL을 호출할 때 저장한 주소로 리턴
    • 입출력 제어
      • READ(INPUT) : 특정 입출력 장치에서 데이터를 읽어라
      • WRITE(OUTPUT) : 특정 입출력 장치에서 데이터를 써라
      • START IO : 입출력 장치를 시작해라
      • TEST IO : 입출력 장치 상태를 확인해라

컴파일 과정

  • C 언어
    • test.c(소스 코드) -> 전처리기(preprocessor) -> 컴파일러(compiler) -> 어셈블러(assembler) -> 링커(linker) -> test.exe(실행 파일)

명령어 사이클

  • 프로그램 속 명령어들은 일정한 주기를 반복하면서 실행한다.
  • 이 주기를 명령어 사이클 이라고 한다.
  • 기본적인 명령어 사이클 : 인출 - 실행 - 인출 - 실행 ...
  • 추가적인 메모리 접근이 필요한 경우? : 간접 주소 방식을 사용해서 필요한 데이터를 가져온다.
  • 인터럽트(interrupt) : CPU 가 실행해야 하는 흐름을 멈추는 작업
  • 인출 사이클 -> 간접 사이클 -> 실행 사이클 -> 인터럽트 사이클

인터럽트(Interrupt)

  • 동기 인터럽트(예외) : CPU가 예기치 못한 상황을 접했을 때 발생
  • 비동기 인터럽트(하드웨어 인터럽트) : 주로 입출력장치에 의해 발생
    • 효율적인 명령어 처리를 위해 사용한다. 만약 사용하지 않는다면, 프린트 완료 여부 확인을 위해 주기적으로 확인해야 하는 비용이 발생한다.
    • ex. 세탁기 완료 알림, 전제레인지 조리 알림

클럭(Clock)

  • 컴퓨터의 부품들이 움직이는 시간 단위
  • 클럭 주기 : CPU의 클럭이 한 사이클에 걸리는 시간
  • 클럭 속도 : 헤르츠(Hz) 단위로 측정
  • 헤르츠(Hz) : 1초에 클럭이 반복되는 횟수
    • ex. 클럭이 1초에 100번에 반복되면 100Hz
  • 일반적으로 클럭 속도를 높이면 CPU 속도가 빨라지긴 하지만 과해지면 발열 발생
    • 다른 방법으로는 코어, 스레드 수를 증가시킨다.

코어(Core)

  • 명령어를 실행하는 부품
  • 멀티 코어 : 두 개 이상의 코어를 가지고 있는 CPU
  • 코어가 많다고 무조건 속도가 향상되는 것이 아니다.

스레드(Thread)

  • 프로그램 실행 흐름의 단위
  • 하드웨어적 스레드, 소프트웨어적 스레드가 있다.
  • 하드웨어워 스레드 : 하나의 코어가 동시에 처리하는 명령어 단위
  • 소프트웨어 스레드 : 하나의 프로그램에서 독립적으로 실행되는 단위

명령어 파이프라인

  1. 명령어 인출(Instruction Fetch)2
  2. 명령어 해석(Instruction Decode)
  3. 명령어 실행(Execute Instruction)
  4. 결과 저장(Write Back)
  • 같은 단계가 겹치지 않으면 각자 단계를 동시에 실행할 수 있다.
  • 동시에 여러 개의 명령어를 겹쳐 실행하는 기법이다.

<


명령어 집합

  • 명령어 집합(구조) : CPU가 이해할 수 있는 명령어들의 모음
  • 일반적으로 인텔의 CPU는 X86 명령어 집합, 애플의 CPU는 ARM 명령어 집합을 사용
  • CISC(Complex Instruction Set Computer)
    • CPU를 설계하는 방식
    • 복잡한 명령어 집합을 갖는 CPU 아키텍처
    • 가변 길이 명령어
    • 메모리를 아낄 때 사용했지만, 명령어 파이프라이닝이 불리하다.
  • RISC(Reduced Instrunction Set Computer)
    • CPU를 설계하는 방식
    • 간단하고 적은 종류의 명령어와 주소 지정 모드를 사용
    • 고정 길이 명령어
    • 메모리 접근 최소화, 레지스터 활용

저장 장치 계층 구조

  • CPU 와 가까운 저장 장치는 빠르고, 멀리 있는 저장 장치는 느리다.
  • 속도가 빠른 저장 장치는 저장 용량이 적고, 가격이 비싸다.
  • CPU 에 가까운 순서 : 레지스터 > 메모리(RAM) > USB
  • 캐시 메모리
    • CPU 와 메모리 사이에 위치
    • 레지스터보다 용량이 빠르고, 메모리보다 빠른 SRAM 기반 저장 장치
    • 메모리에 계속 접근하는 것 보다 일부 데이터를 캐시 메모리에서 저장해둔 뒤 사용
    • 캐시 메모리는 CPU(코어)에 위치 하거나 CPU와 메모리 사이에 위치
      • L1, L2 코어에 위치
      • L3 CPU와 메모리 사이에 위치
    • 멀티 코어 프로세서에서는 각 코어에 위치한 캐시 메모리가 다른 경우가 있기 때문에, 싱크를 맞춰주는 작업이 필요하다.
    • CPU가 자주 사용할 법한 메모리를 저장
      • 캐시 히트 : CPU가 캐시 메모리에 저장된 값을 활용(예측 성공)
      • 캐시 미스 : CPU가 메모리에 접근해야 하는 경우(예측 실패)
    • 참조 지역성의 원리
      • CPU가 최근에 접근했던 메모리 공간에 다시 접근하려는 경향
      • CPU가 접근한 메모리 공간 근처를 접근하려는 경향

컴퓨터

  • 하드웨어 : 컴퓨터를 구성하는 기계적 장치
  • 소프트웨어 : 하드웨어의 동작을 지시하고 제어하는 명령어 집합

 

하드웨어

  • 중앙처리장치(CPU) : 비교와 연산을 담당하는 ALU와 명령어의 해석을 담당하는 제어장치, 빠른 속도의 데이터 기억장소인 레지스터로 구성
  • 주기억 장치(Main Memory) : 프로그램, 데이터, 연산의 중간 결과를 저장하는 장치
  • 입출력 장치(I/O devices)
  • CPU, MM, I/O 장치는 시스템 버스로 연결되어 있으며, 시스템 버스는 데이터와 명령 제어 신호를 각 장치로 실어나르는 역할을 한다.
    • 용도에 따라 데이터 버스, 주소 버스, 제어 버스로 나뉜다.

 

소프트웨어

  • 시스템 소프트웨어 : 사용자를 위해 응용 프로그램 간의 하드웨어 사용을 제어하고 조정하는 기능을 수행하는 프로그램
    • 운영체제, 컴파일러
  • 응용 소프트웨어 : 사용자의 여러 요구사항을 해결하기 위해 제공되는 프로그램
    • 워드프로세서, 스프레드시트

 

데이터 버스

  • CPU와 기타 장치 사이의 데이터를 전달하는 통로
  • 양방향 버스

 

주소 버스

  • 데이터를 정확하게 전달하기 위해서 기억장치 주소를 정해줘야 한다.
  • 단방향 버스(CPU -> I/O)

 

제어 버스

  • CPU, Main Memory, I/O 장치에 제어 신호를 전달하는 통로
  • 제어 신호 종류 : 기억장치 읽기 및 쓰기, 버스 요청 및 승인, 인터럽트 요청 및 승인, 클락, 리셋 등
  • 양방향 버스

중앙처리장치(CPU) 

  • 연산장치
    • 산술 연산과 논리 연산 수행. (레지스터 -> 필요한 데이터 -> ALU -> 연산 결과 -> 레지스터)
  • 제어 장치
    • 명령어를 순서대로 실행할 수 있도록 제어하는 장치
    • 주기억 장치 -> 프로그램 명령 -> 제어장치에서 해독 -> 기억장치 or 연산장치 or 입출력장치로 보냄
  • 레지스터
    • 명령어 주소, 코드, 연산에 필요한 데이터 등등 데이터들을 임시로 저장

 

CPU 동작 과정

1. 주기억 장치는 입력 장치에서 입력받은 데이터 or 보조기억장치의 프로그램을 읽어온다.

2. CPU는 프로그램 실행을 위해 CPU에 저장된 프로그램 명령어와 데이터를 읽어와 처리하고 다시 주기억장치에 저장한다.

3. 주기억 장치는 처리 결과를 보조 기억장치에 저장하거나 출력 장치로 보낸다.

테스트 주도 개발 (Test-Driven Development)

  • 설계 이후 코드 개발 및 테스트 케이스를 작성하는 것이 아니라
  • 테스트 케이스 작성 후, 실제 코드를 개발하여 리팩토링 하는 절차

 

TDD 방식의 장점

  • 객체 지향적 코드
  • 재설계 시간의 단축
  • 디버깅 시간의 단축
  • 테스트 문서 대체 가능
  • 추가 구현 용이

 

TDD 방식의 단점

  • 생산성 저하

객체 지향 프로그래밍(Object Oriented Programming)

  • 프로그램 설계 방법론
  • 명령형 프로그래밍 : 프로그램 상태에 대한 문장들을 작성하는 스타일
  • 초기 프로그래밍 방식인 절차적 프로그래밍에서 복잡한 순서도를 가진 코드의 문제점을 해결하기 위해 구조적 프로그래밍 방식이 생겨났다.
  • 하지만 데이터의 구조화는 하지 못했기 때문에 전역 네임스페이스 포화 문제, 실행 콘텍스트를 저장할 방법이 없는 문제 등등 여러 문제들이 있었다.
  • 객체 지향 프로그래밍으로, 큰 문제를 작게 쪼개는 것이 아니라 먼저 작은 문제를 해결할 수 있는 객체를 만든 후, 객체를 조합해서 큰 문제를 해결하는 상향식(Bottom-up) 방식을 도입했다.
  • 객체 지향 프로그램이 복잡해지면서 간결하게 정리할 수 있는 디자인 패턴이 생겼다.
    • 디자인 패턴 : 프로그래밍 형식을 정하는 일종의 약속
  • 객체 지향 프로그래밍은 객체가 상태를 갖기 때문에, 변수가 존재하고 이 변수를 통해 객체가 예측할 수 없는 상태를 갖게 되어 애플리케이션 내부에서 버그를 발생시킨다는 단점이 있다. -> 함수형 프로그래밍

 

객체 지향 프로그래밍의 요소

  • 캡슐화(encapsulation)
    • 변수와 함수를 하나의 단위로 묶는 것
    • 해당 클래스의 인스턴스 생성을 통해 클래스 안에 포함된 멤버 변수와 메소드에 쉽게 접근할 수 있다.
    • 정보 은닉(information hiding) : 응집도를 높이고, 결합도를 떨어트려 유연함과 유지보수 향상
  • 상속(inheritance)
    • 자식 클래스가 부모 클래스의 특성과 기능을 그대로 물려받는 것
    • 오버라이딩(Overriding) : 자식 클래스에서 상속받은 기능을 재정의
  • 다형성(polymorphism)
    • 하나의 변수, 또는 함수가 상황에 따라 다른 의미로 해석될 수 있는 것 
    • 서브타입 다형성(subtype polymorphism)
      • 기초 클래스나 인터페이스를 구현하는 상위 클래스를 생성해서, 해당 클래스를 상속받는 다수의 하위 클래스들을 만들어 상위 클래스의 포인터나 참조 변수들이 하위 클래스의 객체를 참조하게 하는 것
      • 상속받은 상위 클래스의 메소드를 하위 클래스에서 재정의해서 사용할 수 있다. -> 오버라이딩
    • 매개변수 다형성(parametric polymorphism)
      • 타입을 매개변수로 받아 새로운 타입을 되돌려주는 기능
      • 데이터 타입이나 함수를 범용적으로 작성하여 세부 타입에 상관없이 동일하게 처리 가능
      • 제네릭(generic)
        • 지정한 타입 매개변수에 해당하는 타입만 사용하겠다고 약속하는 방식
    • 임시 다형성(ad hoc polymorphism)
      • 함수 오버로딩(function overloading)
        • 같은 이름의 함수를 매개 변수의 개수 또는 타입을 변경하여, 여러 개의 함수가 서로 다르게 행동할 수 있는 성질
        • 잦은 함수 오버로딩은 전체적은 코드의 유지보수가 어렵기 때문에, 템플릿이나 제네릭으로 대체한다.
      • 연산자 오버로딩(operator overloading)
    • 강제 다형성(coercion polymorphism)
      • 묵시적 형변환(implicit type coercion)
      • 명시적 형변환(explicit type coercion)
double a = 30;
// int형 값 30은 double으로 묵시적 형변환

double a = (double)30;
// 결과는 위와 동일하지만, (double)을 통해 int형 값 30이 double으로 변환

 

 

객체 지향적 설계 원칙

  • SPR(Single Responsibility Principle) : 단일 책임 원칙
    • 클래스는 단 하나의 책임을 가진다. 클래스를 변경하는 이유는 단 하나의 이유이어야 한다.
  • OCP(Open-Closed Principle) : 개방-폐쇄 원칙
    • 확장에는 열려 있고, 변경에는 닫혀 있어야 한다.
  • LSP(Liskov Substitution Principle) : 리스코프 치환 원칙
    • 상위 타입의 객체를 하위 타입의 객체로 치환해도 상위 타입을 사용하는 프로그램은 정상적으로 동작해야 한다.
  • ISP(Interface Segregation Princinple) : 인터페이스 분리 원칙
    • 인터페이스는 그 인터페이스를 사용하는 클라이언트를 기준으로 분리해야 한다.
  • DIP(Dependency Inversion Principle) : 의존 역전 원칙
    • 고수준 모듈은 저수준 모듈의 구현에 의존해서는 안된다.

변수명 표기법(Naming Convention)

 

 

카멜 표기법(Camel Case)

- 주로 Java에서 사용

- 앞 단어를 제외한 단어의 첫 번째를 대문자로 표기한다.

- firistName

 

파스칼 표기법(Pascal Case)

- 모든 단어의 첫 번째를 대문자로 표기한다.

- FirstName

 

스네이크 표기법(Snake Case)

- 주로 C에서 사용

- 모든 단어는 소문자, 단어를 구분하기 위해 _ 사용

- first_name

 

헝가리안 표기법(typeHungarian Case)

- 접두어에 자료형을 표기해준다.

- strFirstName

+ Recent posts