[인프런 워밍업 클럽 3기 - CS] - 3주차 발자국(운영체제)
💻 가상메모리📌 개요32bit CPU 를 사용한다면 약 4GB(2^32)의 메모리, 가상 메모리를 가진다. ❓그러면 가상 메모리의 용량을 뛰어넘는 프로세스들을 어떻게 실행되는 것인가?✅ 물리 메모리 내용의 일부를 스왑 영역에 저장하고 필요 시에만 물리 메모리로 스왑 메모리 관리자(MMU Memory Management Unit)은 물리 메모리 + 스왑 영역을 전체 메모리 공간으로 보고 가상 주소를 물리 주소로 변환시킨다 (동적 주소 변환 DAT) ❓메모리 관리자는 어떻게 메모리 공간을 관리하나?✅ 물리 메모리의 0번지는 운영체제의 영역이며 나머지 영역에 대해 "가변 분할 방식(세그멘테이션)"과 "고정 분할 방식(페이징)"으로 구분하여 나눈다. 또한 매핑 테이블을 관리하여 가상주소를 물리주소로 전환이 가능하다. 📌 세그멘테이션(배치정책)세그멘테이션(Segmentation): 함수, 모듈 등으로 세그먼트를 분할(코드, 힙, 데이테, 스택,,)프로그램 입장에서는 각 세그먼트는 모듈 별로 분리되어 있다고 판단프로세스 입장에서는 각 세그먼트는 인접하게 판단각 세그멘테이션이 모듈로 처리되어 역할에 맞게 분할되어 관리가 가능하다외부 단편화가 발생할 수 있다. 세그멘테이션 테이블 : 세그멘테이션에서 사용되는 매핑 테이블Base Address : 세그멘테이션 메모리 시작 주소Bound Address: 세그멘테이션 크기, 접근 가능 최대 범위 물리 주소 변환 과정1. CPU가 논리주소, 세그멘트 번호 전달2. 메모리 관리자는 Segment Table Base Register 를 통해 물리 메모리 n 번지에 저장된 세그먼테이션 테이블 로드3. 세그멘트 번호를 인덱스로 테이블에서 Base Address, Bound Address 조회4. Bound Address(메모리 크기)와 논리 주소를 비교1. Bound Address > 논리 주소 = Base Address + 논리 주소 = 물리 주소2. Bound Address < 논리 주소 = 메모리 침범 -> 에러 발생- 컨텍스트 스위칭마다 해당 세그멘테이션 테이블에 프로세스의 데이터를 수정해야 함으로 비용이 큰 작업이다. 📌 페이징(배치정책)고정 분할 방식: 메모리를 정해진 크기의 페이지로 나누어 관리프로세스는 같은 크기의 페이지로 분할되며, 메인 메모리는 같은 크기의 프레임으로 분할된다. 페이지 테이블page number: 조회할 페이지 번호frame number: 물리메모리 프레임 번호물리 주소 변환 과정1. CPU 논리주소 전달2. 메모리 관리자는 Page Table Base Register을 통해 물리메모리 n번지에서 페이지 테이블 로드3. 페이지 번호 = 논리주소 / 페이지 크기4. 오프셋은 논리주소 % 페이지 크기5. 페이지 테이블에서 페이지 번호를 인덱스로 프레임, 오프셋를 알아냄6. 만약 프레임에 invalid로 저장되면 스왑영역에 저장 세그멘테이션 VS 페이징1. 세그멘테이션은 Base Address가 필요하지만 페이징은 각 페이지 영역이 동일하여 필요 없음2. 세그멘테이션 외부 단편화 발생, 페이징 내부 단편화 발생3. 세그멘테이션 논리적 영역별로 구분, 페이징은 고정된 페이지에 저장하여야 하니 논리적으로 구분 불가4. 각 프로세스마다 페이지 테이블을 갖고 있기에, 페이지 테이블의 크기 관리가 중요하다. 📌 페이지드 세그멘테이션페이지 + 세그멘테이션 프로세스 접근 권한- 코드: RE- 데이터: RW(o)- 힙: RW- 스택: RW세그멘테이션 테이블권한 비트Page Number페이지 개수물리 주소 변환 과정CPU가 0x12300번지 접근 요청메모리 관리자가 메모리에서 세그멘테이션 테이블이랑 페이지 테이블 로드세그먼트 번호를 통해 인덱스를 확인 후, 접근 권한 위반 여부를 파악페이지 크기와 비교하여 메모리 침범 여부를 확인페이지 넘버를 통해 페이지 테이블의 프레임 확인물리 메모리의 프레임 번호 + 접근 요청된 메모리 오프셋 = 물리 주소단점1. 물리메모리에서 데이터를 가져오기 위해서는 메모리 접근 두 번 해야함 (세그멘테이션 테이블, 페이지 테이블) 📌 디멘드 페이징(가져오기 정책)지역성 이론1. 공간의 지역성: 현재 위치에서 가까운 데이터에 접근 확률이 높음2. 시간의 지역성: 현재 시간에서 가까운 데이터에 접근 확률이 높음(최근) 디멘드 페이징: 필요한 데이터만 메모리에 올리고 사용하지 않는 데이터는 스왑 영역으로 이동보조저장장치에서 데이터를 가져오는 것은 레지스터보다 몇 배는 더 많은 시간이 소요스왑영역이 보조저장장치에 있기에, 스왑영역에 데이터를 저장하는 것을 최소화해야 함. 스왑 인(swap in): 스왑 영역 -> 물리 메모리스왑 아웃(swap out): 물리 메모리 -> 스왑 영역 페이지 테이블 엔트리(PTE)1. 접근 비트: 데이터 접근 여부(읽기, 실행 작업 시, 1)2. 변경 비트: 데이터 쓰기 여부(쓰기 작업 시, 1)3. 유효 비트: 페이지가 물리 메모리에 있는지(있음 0)4. WRE 비트: 접근 권한 비트5. 프레임: 프레임 번호 저장 디멘드 페이징 과정1. 페이지 테이블에서 유효비트와 프레임 번호를 확인2. 유효비트가 0일 경우, 물리 메모리에서 해당 프레임 번호로 데이터 반환3. 1일 경우, 스왑영역에서 프레임 번호로 데이터 추출4. 물리 메모리에서 빈 프레임을 확인5. 빈 프레임이 있으면 물리 메모리로 데이터를 적재하고 페이지 테이블 수정6. 빈 프레임이 없으면 물리 메모리에서 필요하지 않은 데이터를 스왑 영역으로 이동 후, 빈 프레임으로 이동 📌 페이지 교체정책페이지 교체정책: 가득찬 메모리에서 스왑영역으로 보낼 페이지를 고르는 기법1. 무작위 선택(Random): 지역성을 고려하지 않아, 자주 사용되는 페이지가 교체될 수 있음2. 가장 오래된 페이지 교체(FIFO): 가장 오래된 페이지가 자주 사용될 수도 있음3. 가장 오랫동안 사용하지 않을 페이지 교체(Optimum): 사실상 구현이 불가(이론상)4. 최근 사용이 가장 적은 페이지 교체(Least Recently Used)1. 지역성 이론에 따라, 최근 사용이 적은 페이지는 앞으로도 사용이 적을 것이다는 추정2. optimum 알고리즘과 근접한 성능을 갖지만, 지역성 이론에 따르지 않는다면 성능이 안좋아짐3. 시간을 기록하는 비트 수가 많아짐 Belady의 역설: 페이지 폴트를 줄이기 위해 메모리를 늘려 프레임을 늘렸더니 페이지 폴트가 더 많이 발생(FIFO에서 발생) LRU 알고리즘의 성능은 좋지만 구현이 어렵고 시간을 기록할 비트가 많이 필요하며 시간이 오래 지나면 오버 플로우가 발생한다. 클락 알고리즘(clokc algorithm)접근 비트를 하나만 이용일정시간마다 접근 비트를 0으로 초기화페이지 조회 시, 접근 비트 1로 수정페이지를 원형으로 연결페이지 폴트 발생 시, 클락 핸드(원형 페이지를 순회하는 포인터)를 시계방향으로 돌려접근 비트가 1이면 0으로 수정하고접근 비트가 0이면 교체할 페이지로 선택향상된 클락 알고리즘접근 비트와 변경 비트 모두 확인접근 비트 0 / 변경 비트 0접근 비트 0 / 변경 비트 1접근 비트 1 / 변경 비트 0접근 비트 1 / 변경 비트 1순서대로 페이지 교체 우선 순위 선정 하드웨어적으로 접근비트를 지원하지 않는 시스템에서 FIFO를 사용해야 함.(FIFO 최적화 필요)2차 기회 페이지 교체 알고리즘- FIFO와 동일하게 동작- 만약 페이지 폴트없이 페이지 접근이 성공하면, 가장 첫 체이지를 큐의 가장 뒤로 이동 📌 스레싱과 워킹셋스레싱: CPU 사용률을 높이기 위해 더 많은 프로세스를 실행하지만 물리 메모리의 공간 초과로 스왑에 더 많은 시간이 할당되어 CPU 사용률이 낮아지는 것- 물리메모리의 크기가 부족하여 스레싱 발생- 물리적으로 메모리의 성능을 늘리는 것은 한계가 있음(스레싱이 발생하지 않는다면 업그레이드에 대한 효율이 없음)- 페이지를 적게 할당하면 page fault가 많이 발생 / 페이지를 많이 할당하면 다른 프로세스가 사용할 페이지가 적음- 프로세스를 실행하며 page fault가 많이 발생하면 페이지를 더 할당- page fault가 적게 발생하면 페이지를 조금 할당- 적절한 페이지 수가 결정되어 지역성 이론에 따라 유지할 페이지들을 골라야 함. 워킹셋: 현재 메모리에 올라온 페이지는 다시 사용할 확률이 높기 때문에 하나의 세트로 묶어서 메모리에 저장- 프로세스 준비 -> 실행 상태로 컨텍스트 스위칭할 때 사용된다. 💻 입출력장치📌 주변장치(I/O 디바이스, 저장장치)I/O Device하드웨어완 연결할 수 있는 외부 인터페이스I/O 데이터 전달을 위한 버스 인터페이스(address, data, control 버스 3개)장치 상태 및 데이터 저장을 위한 레지스터(C메모리로 전달되기도 함)컨트롤러, 로직I/O 처리 과정CPU는 I/O 작업을 입출력 제어기에게 맡기고 다른 작업CPU, 메모리, 그래픽 카드(입출력 장치지만 대용량 데이터를 다룸)는 시스템 버스를 이용하고 (고속으로 이용)입출력 제어기는 고속 입출력 버스를 통해 빠른 장치(HDD 등)데이터 전송과 저속 입출력 버스를 통해 느린 장치(마우스 키보드 등)입출력 제어기는 입출력 두 개의 버스에서 온 데이터를 시스템 버스를 통해 메모리로 옮김입출력 제어기가 메모리에 접근하려면 CPU가 필요한데, 효율성이 떨어지니 DMA(Direct Meomry Access)를 통해 메모리에 저장CPU와 DMA 메모리 공간을 분리 - Memory Mapped I/O 📌 마우스 / 키보드마우스과거는 볼을 사용하여 마우스 움직임 계산현재는 카메라로 초당 1500회의 사진을 찍어 DPS를 통해 마우스 좌표를 계산DPS 입력 감지 시, 디바이스 컨트롤러가 인터럽트 발생마우스 드라이버가 데이터를 운영체제에 이벤트 전달 > Foreground 애플리케이션 전달 > 애플리케이션 데이터 처리키보드디바이스 컨트롤러 입력 감지 및 인터럽트 발생키보드 드라이버 이벤트 전달 > 운영체제 Foreground 애플리케이션 전달 > 애플리케이션 데이터 처리📌 하드디스크/Flash Memory(SSD) 하드디스크의 구조sector: track에서 여러개의 sector로 나뉘고 하드디스크의 가장 작은 단위 track: platter에 여러개의 track이 존재하고 표면의 자성으로 N극은 0, S극은 1platter: 원판 형태로 데이터 저장cylinder: 모든 헤드는 같이 움직이고 여러개의 헤드가 가리키는 트랙의 집합spindle: platter를 지지하는 막대read/write head: disk arm에 달려있어, platter의 표면을 읽음 과정cylinder C로 가서 track B에 있는 sector D를 읽어라disk arm은 헤드를 cylinder C로 이동시키고(seek, seek time < 하드 디스크가 느린 이유)track B에 Sector D가 head에 닿을때까지 spindle을 회전Flash Memory하드디스크기계적으로 움직여 소음도 일어나고 속도가 느림자기적으로 처리 -> 고장 가능성이 높음충격에 약함flash memory전기적으로 데이터를 읽기 때문에 조용하고 속도가 빠름안전함덮어쓰기가 불가능지우기 가능한 횟수가 정해져있어서, 지우고 쓰기가 여러번 쓰일 수 없음 💻 파일시스템📌 파일과 파일 시스템파일 시스템 기능파일, 디렉토리 생성, 수정, 삭제접근 권한 관리무결성 보장백업과 복구암호화파일 -> 블록 단위로 저장 -> 메모리 관리자가 바이트로 변환 -> 사용자가 접근운영체제는 File Descriptor를 갖고 있으며 파일마다 독립적인 File Descriptor가 존재하여 파일이 오픈되면 메모리에 올라간다. 사용자가 파일을 실행하면 운영체제가 file descriptor를 전달하여 파일을 찾아온다. 파일 구조순차파일구조: 파일 내용이 연속적으로 이어져있음직접파일구조: 해시 함수를 통해 해시 테이블에 데이터 저장인덱스파일구조: 순차 + 직접 파일구조 📌 디렉토리Root Directory: 최상위 디렉토리디렉토리 헤더는 디렉토리 정보가 시작하는 위치를 가리킨다.다단계 디렉토리: 하나의 디렉토리에 하위의 디렉토리를 만들 수 있는 트리 구조 📌 파일과 디스크블록: 디스크 공간을 일정한 크기로 나누고 주소를 할당(1 ~ 8KB)연속할당: 파일 구성 블록들을 디스크에 연속적으로 할당시작주소만 알면 파일을 읽을 수 있음내부 단편화 발생불연속할당: 데이터를 분산하여 저장연결할당: 시작 블록 주소만 알고 있으며, 연결리스트를 통해 블록 저장인덱스할당: 인덱스 블록의 주소를 저장하고, 인덱스 블록에 저장된 데이터 블록 인덱스들로 데이터 블록을 읽어옴 📌 더 찾아본 점 ❓ 페이징, 세그멘테이션, 페이지드 세그멘테이션페이징 테이블 구성: 페이지 번호 / 프레임 번호 / 유효/무효 비트페이징 테이블 엔트리: 페이지 테이블에서 페이지에 대한 위치 정보를 담은 각 행CPU가 (p, d) 전달페이징 테이블에서 p에 대한 f를 찾고 반환물리 주소에서 f 번 프레임의 d 번째 위치 (페이지 크기 * f + d)세그멘테이션 테이블 구성: 세그멘테이션 번호 / Base Address / Bound AddressCPU가 (s,d) 논리주소 전달세그먼트 테이블에서 s에 대한 base address와 limit 확인d가 limit 보다 크면 에러물리 주소 = base address + d페이지드 세그멘테이션: 프로세스를 각 세그멘테이션으로 구분하고 세그멘테이션을 고정 크기의 페이지로 분할CPU는 (s,p,d) 논리주소 전달세그먼트 번호를 통해 p를 확인하고 d와 페이지 개수를 비교하여 메모리 침범인지 확인p를 통해 페이지 테이블에서 인덱스를 확인하고 프레임 번호를 확인물리 주소: 프레임 번호 시작 주소 + d = f \* 페이지 크기 + d ❓ 메모리에 없는(invalid)데이터를 어떻게 저장장치에서 가져올까?Demand Paging: 프로그램 실행 중에 필요한 페이지만 물리 메모리에 저장하고, 실행 중에 요구되는 페이지에 대해서는 저장장치에서 로드Page Fault: 페이지 테이블에서 가져오려는 데이터가 invalid 한 상황. 운영체제에게 trap을 발동시키고 이를 통해 요구되는 페이지를 메모리로 로드 1. 페이지 테이블에서 찾으려난 데이터가 valid인지 invalid인지 확인2. invalid일 경우, page fault가 발생되고 운영체제의 trap에 걸림(프로세스 대기).3. 물리 메모리에서 비어있는 frame 주소를 찾음4. 제 2 저장장치에서 요구되는 페이지를 찾고 해당 프레임에 할당5. 물리 주소 프레임 위치를 페이지 테이블에 매핑6. 인터럽트가 끝나고 프로세스 중단된 명령어부터 다시 실행 ❓ Second-Chance Algorithm?FIFO 알고리즘에 접근 비트(reference bit)를 추가하여 접근 여부를 파악0이면 해당 페이지를 교체, 1이면 0으로 수정한 후 다음 FIFO page로 이동향상된 Second-Change Algorithm(clock algorithm)원형 큐로 생성포인터가 각 큐를 순회하며 접근 비트가 0인 것을 발견.최악의 경우(모든 접근 비트가 1), 모든 접근 비트를 0으로 수정하고 FIFO와 동일하게 가장 앞에 페이지를 교체 ❓ Thrashing, Working set?프로세스가 page in, page out으로 너무 많은 swapping을 하는 현상많은 프로세스를 메모리에 올려(멀티 프로그래밍) 실행 시키면, 어느 순간 CPU 효율성이 떨어지는 현상프로세스 실행 > page fault > process wait queue > page in > next page > page fault ...Working Set지역성 이론에 따라서 최근에 가장 많이 조회된 페이지들의 집합working set안에 있다 - 자주 참조되는 페이지 / 없다 - 교체 대상 페이지t1 시간에는 {1,2,5,6,7} 로 워킹셋 생성, t2에 {3,4} 로 워킹셋 수정Δ (델타) 를 통해 working set window를 생성하고 그 사이즈를 적절히 정하는게 중요운영체제는 각 프로세스의 working set을 모니터링하면서 사이즈에 맞게 frame을 할당충분한 프레임이 남는다면 프로세스를 더 실행 / 각 프로세스의 워킹셋 총합이 사용가능한 프레임의 수가 초과되면 프로세스 중지이를 통해 멀티 프로그래밍 정도를 높이면서 CPU 효율성을 유지❓ 입출력 장치의 I/O 인터럽트가 발생해도 끊김이 없는 이유?interrupt-request line을 통해 CPU는 명령어를 실행한 후 인터럽트가 발생하였는지 감지현재 실행 중인 프로세스의 데이터, 상태를 저장인터럽트 핸들러를 실행인터럽트의 원인을 확인하고 필요한 작업을 수행수행 후, 상태값을 복원하여 이전 작업으로 복귀아무런 작업이 없는 컴퓨터에서 10초 동안 23,000개의 인터럽트가 발생 - 초당 수백개의 인터럽트를 처리해야 함. 현재 운영체제에서는 조금 더 정교한 interrupt handling 특징들이 있음1. 중요한 프로세스 작업 중 인터럽트 핸들링을 지연시킬 능력이 필요하다2. polling을 통한 인터럽트 발생 확인이 아닌, 적절한 인터럽트 핸들러를 통해 효율적으로 인터럽트 관리3. multilevel interrupt를 통해 상위 - 하위 우선순위의 인터럽트를 구분하고 여러 인터럽트 동발생 시, 긴급성에 따라 응답4. 운영체제의 attention을 바로 받을 수 있을 만한 명령어가 필요 (page fault는 trap) 📌 백엔드 면접 질문✏ 페이지 폴트(Page Fault)는 언제 발생하며, 운영체제는 이를 어떻게 처리하는가??✅ 페이지 폴트란 프로세스가 논리 주소로 데이터를 요청할 때, 메인 메모리에 데이터가 없는 경우 발생하는 인터럽트이다.스왑 영역에 저장되어 있는 페이지를 가져오기 위해 프로세스를 대기 상태로 변경 시켜, 운영체제에 트랩을 발생시키고스왑 영억에서 데이터를 가져와 메인 메모리에 저장하고 페이지 테이블을 다시 변경해서 프로세스를 이어서 실행시킵니다. ✏ Node.js에서 가상메모리는 어떻게 관리되는가?V8 엔진은 JS코드가 저장되는 Code segment, 함수 호출과 실행 컨텍스트를 저장하는 Call Stack, 객체와 데이터를 저장하는 Heap Memory로 구분된다. V8에서는 페이징 기법을 통해 힙 영역을 가상 메모리로 관리한다. 힙 영역에 각각의 space(new space, old space, large object space,,)들은 페이지로 구성되어 있으며 각 페이지는 large object space를 제외하고는 1MB정도이다. 또한 가비지 컬렉터를 통해 단편화가 많이 일어난 페이지에 대해 메모리 압축을 진행한다. - 살아있는 객체들을 한 곳으로 이동시키고 포인터 갱신 ✏ Node.js에서 파일을 읽는 방법은?- Node.js는 싱글스레드에서 동작하지만 내부적으로 멀티 쓰레드(Worker Pool)에서 작업을 한 후에 이벤트 루프를 통해 결과를 반환한다. 이벤트 루프는 비동기 작업에 대해 작업이 완료되면 콜백함수를 task queue에 저장하고 콜스택이 비어있으면 task queue에서 콜백함수 실행. readFile 메서드는 비동기로 실행되며 콜백 함수를 통해 파일 읽기 작업이 마무리되면 콜백이 실행되며 readFileSync는 동기적으로 실행되고 blocking 상태가 되어, 파일을 읽을 때까지 작업이 대기된다. 📔 회고🚀 최종 목표 : 더 효율적인 백엔드 개발을 위해 기본적인 운영체제 지식들을 확실히 잡아가기🚀 매주 규칙:각 섹션마다 하나의 .md 파일을 생성하고, 섹션 내 각 유닛은 헤더로 구분강의를 듣고 최대한 이쁘게 (?) 정리해놓기 매 강의 듣고 해당 내용 공룡책 & 강의 1회 정독 및 수강매 강의에 대한 내용 백엔드 면접 질문을 추려서 답변하고 개념 구체화하기이번 인프런 워밍업 클럽을 진행하면서 커리큘럼에 맞춰 매일 강의를 듣고 지키려고 하였던 나의 목표 및 규칙이다.규칙부터 살펴보자면,각 섹션마다 하나의 .md 파일을 생성하고, 섹션 내 각 유닛은 헤더로 구분 : 10 / 10강의를 듣고 최대한 이쁘게 (?) 정리해놓기 : 8 / 10매 강의 듣고 해당 내용 공룡책 & 강의 1회 정독 및 수강 : 7 / 10매 강의에 대한 내용 백엔드 면접 질문을 추려서 답변하고 개념 구체화하기 : 7 / 10매 강의를 듣고 섹션별, 유닛별로 모든 내용을 정리하여 저장하였으니 10점을 주었다.강의를 듣고 최대한 이쁘게 정리를 하려고 노력하였지만 2점이 감점된 이유는 시간이 지날 수록 점점 이모지 사용이 줄고 글간, 행간과 같은 사소한 부분을 신경쓰지 않게 된 것같다,, 그래도 이 노력을 통해서 일관된 템플릿을 형성할 수 있었다는 점, md파일로 매일 정리해보며 파일 정리에 조금 익숙해진 것 같다.매 강의를 듣고 관련된 내용을 공룡책에서 찾아서 읽어보고 어려운 내용에 대해서는 공룡책 관련 강의와 함께 수강하려고 노력하였다. 2주차까지는 강의에서 나온 내용과 공룡책이 챕터 별로 일치하여 찾아보기가 편하여 공룡책에 나온 내용을 읽어보고 스스로 정리해보며 부족한 부분을 기록하였다면, 이번 주차부터는 공룡책에 안나오는 내용들이 점차 등장하여 미리 궁금한 내용들은 정리해두고 다른 블로그나 공식문서들을 참고하여 지식을 채워갔다. 7점을 준 이유는 아무래도 공룡책 챕터 별로 범위가 넓고 깊이 있게 다루기 때문에 정독의 수준에는 미치지 못한 것 같다. 또한 이해가지 않은 부분은 쉽게 넘어가고 전체적인 흐름만 파악하려 하였기에 아쉬운 점이 조금 남은 것 같다.매 강의를 듣고 GPT를 이용하여 관련된 강의 내용에 관련된 백엔드 면접 질문들을 추려서 스스로 답변하면서 정리해보았다. 관심이 많던 Node.js 를 기반으로 더 깊이있게 공부해봤던 것 같고 CS 지식들을 실무에 적용시켜서 생각해보려고 노력하였다. 하지만 Node.js 프롬프트를 이용한 질문은 유료라 한도가 항상 잡혀서 아쉬운 점이 컸던 것 같다. 무료 프롬프트는 어딘가 의심이 드는 답변들이 많아 두번 세번 더 찾아봐야하는 문제점이 있어, 한정된 질문들에 대해 소중하게 답변했던 것 같다. 7점을 주었던 이유는 면접 질문을 정리하고 스스로 공부해봤던 개념들을 따로 정리해놓지는 않아서 부족하게 진행되었던 것 같고 이번 기회에 매일 면접 질문들을 답변해보면서 공부를 한 것들을 기록하여 정리해보려 한다.그래서 최종적으로 내가 설정하였던 목표에 대해서는더 효율적인 백엔드 개발을 위해 기본적인 운영체제 지식들을 확실히 잡아가기 : 8/10나름 높은 점수를 주었지만 이 점수는 나의 과정에 대한 점수이지 결과에 대한 점수는 아닌 것 같다. CS에 대해서는 아직 부족한 부분이 많지만 이번 로드맵을 통해 CS가 더 흥미로워졌고 더 깊이 공부해보고 싶은 생각이 들었다.무엇보다 가장 좋았던 부분은 CS에 대한 전반적인 틀을 잡을 수 있었고 공부 해야할 방향성이 조금씩 잡혀나가는 것 같다는 느낌이 들었다. 이를 기반으로 더 깊이 있게 공부하면서 실무적으로 계속 연결하여 생각해보고 백엔드 개발에서 더 효율적이고 올바른 판단을 하기 위해 꾸준히 노력해 볼 생각이다.