블로그

(2주차) 운영체제 미션 제출

FIFO 스케줄링의 장단점이 뭔가요?은행에 줄 서서 기다리는 상황이라고 비유 했을 때, 먼저 온 사람이 먼저 창구에서 업무를 보고 뒤에 온 사람은 무조건 앞사람이 끝나야 한다.장점누가 먼저 왔는지만 따지기 때문에 누구한테도 특혜가 없으므로 공정하다고 느껴진다구현이 간단하다 : 큐에 넣고 순서대로 꺼내면 되니까 코드도 쉽고 시스템 자원도 적게 쓴다.단점CPU를 오래 쓰는 프로세스가 앞에 있으면 뒤의 짧은 작업들도 기다려야 한다앞사람이 대출 상담(시간 오래 걸리는 업무)을 보고 있다면 뒤에 온 사람들(단순 이체 업무)이 빨리 끝날 수 있는데도, 무조건 기다려야 한다.짧은 작업이 불필요하게 오래 기다리는 경우가 많아서 전체적인 대기 시간이 늘어난다. SJF를 사용하기 여러운 이유가 뭔가요?프로세스의 CPU Burst Time(실행 시간)을 미리 알기 어렵다 -> 예측이 쉽지 않아서 실시간 시스템에서는 비현실적  잘못 예측하면 기대 성능이 안 나오지 않는다비선점형으로 하면 긴 프로세스가 무한정 대기할 수 있다RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요?Context Switch이 자주 발생한다 -> 오버헤드가 커져서 CPU 시간의 낭비처리 시간이 짧은 프로세스에도 효율이 떨어진다운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요?행동 패턴을 기준으로 자동 분류한다 -> CPU를 오래 쓰면 낮은 우선순위로 강등, 입출력(I/O) 위주로 빠르게 종료하면 높은 우선순위를 유지한다즉, CPU 사용 시간과 빈도에 따라 레벨이 조정된다공유자원이란무엇인가요?여러 프로세스/스레드가 동시에 접근하려는 자원 -> CPU, 메모리, 파일, 프린터 등동시에 접근하면 경쟁이 발생하고 동기화가 필요하다 교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야할까요? 상호 배제: 자원을 하나의 프로세스만 사용 가능하다점유와 대기: 자원을 가진 상태에서 다른 자원을 기다린다비선점: 자원을 강제로 빼앗을 수 없다순환 대기: 프로세스 간에 원형 대기 상태위 조건을 모두 충족해야 교착상태에 빠진다

[인프런 워밍업 클럽 3기 - CS] - 2주차 미션 (자료구조와 알고리즘)

재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요?기저 조건이 없으면 무한으로 반복해 콜스택이 가득차 스택 오버플로우가 발생하여 프로그램이 비정상적으로 종료됩니다.  0부터 입력 n까지 홀수의 합을 더하는 재귀 함수를 만들어보세요.자바 코드 예시 public static int sum(int n) { if (n == 1) return 1; // 탈출 조건 if(n % 2 == 1){ return n + sum(n - 1); } return sum(n - 1); } public static void main(String[] args) { System.out.println("홀수합 = " + sum(10)); // 120 출력 } 자바스크립트 예제function sumOdd(n){ if(n == 1) return 1; if(n % 2 == 1){ return n + sumOdd(n-1); } return sumOdd(n-1); } console.log(sumOdd(10)) // 25다음 코드는 매개변수로 주어진 파일 경로(.는 현재 디렉토리)에 있는 하위 모든 파일과 디렉토리를 출력하는 코드입니다. 다음 코드를 재귀 함수를 이용하는 코드로 변경해보세요.const fs = require("fs"); // 파일을 이용하는 모듈 const path = require("path"); // 폴더와 파일의 경로를 지정해주는 모듈 function traverseDirectory1(directory){ const stack = [directory]; // 순회해야 할 디렉토리를 저장할 스택 while (stack.length > 0) { // 스택이 빌 때까지 반복 const currentDir = stack.pop(); // 현재 디렉토리 const files = fs.readdirSync(currentDir); // 인자로 주어진 경로의 디렉토리에 있는 파일or디렉토리들 for (const file of files) { // 현재 디렉토리의 모든 파일or디렉토리 순회 const filePath = path.join(currentDir, file); //directory와 file을 하나의 경로로 합쳐줌 const fileStatus= fs.statSync(filePath); // 파일정보 얻기 if (fileStatus.isDirectory()) { // 해당 파일이 디렉토리라면 console.log('디렉토리:', filePath); stack.push(filePath); } else { // 해당 파일이 파일이라면 console.log('파일:', filePath); } } } } traverseDirectory1("."); // 현재 경로의 모든 하위 경로의 파일, 디렉토리 출력 자바 코드 예시public static void directory(String directory) { if(directory == null){ return; } File dir = new File(directory); // 디렉토리값을 기반으로 파일 객체 생성 File[] files = dir.listFiles(); // 파일 및 하위 디렉토리 정보 저장 배열 if (files != null) { for (File file : files) { if (file.isDirectory()) { System.out.println("디렉토리 : " + file.getAbsolutePath()); // 경로를 출력 directory(file.getAbsolutePath()); // 재귀로 하위 디렉토리 탐색 } else { System.out.println("파일 : " + file.getAbsolutePath()); } } }else{ return; } } public static void main(String[] args) { directory("."); // 현재 경로의 모든 하위 경로의 파일, 디렉토리 출력 }

[인프런 워밍업 클럽 3기 - CS] - 2주차 미션 (운영체제)

운영체제FIFO 스케줄링의 장단점이 뭔가요? 장점 : 선입선출 방식의 알고리즘이라 프로세스가 들어온 순서대로 처리할수 있어 단순하고 직관적임단점 : 먼저 온 프로세스가 실행 시간이 길면 실행 시간이 짧은 프로세스들은 그 뒤에서 작업이 끝날떄 까지 기다려야하는 호위효과가 발생하게됨 SJF를 사용하기 여러운 이유가 뭔가요?burst Time의 예측이 어렵고 burst Time이 짧은 작업이 계속 들어올경우 상대적으로 작업시간이 긴 프로세스는 계속 대기해야하는 기아현상이 발생합니다.  RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요?CPU의 프로세스 간에 전환이 너무 자주 일어면 컨텍스트 스위칭이 자주 발생해 오버헤드가 커져 효율성이 떨어집니다.  운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요? CPU를 사용하는 프로세스가 실행하다가 스스로 CPU를 반납하면 I/O Bound Process이고CPU를 사용하는 프로세스가 타임 슬라이스를 오버해서 스케줄러에 의해 강제로 CPU를 뺏기는 상황이면 CPU Bound Process 입니다. 공유자원이란무엇인가요?프로세스 간 통신에서 공동으로 사용하는 변수나 파일이고 여러 프로세스가 동시에 접근하면 순서에 따라 결과가 달라질 수 있습니다.   교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야할까요?상호 배제, 비선점, 점유와 대기, 원형 대기가 모두 충족이 되어야 하고 이 중 하나라도 충족하지 못하면 교착상태에 빠지지 않습니다.   

[인프런 워밍업 클럽 3기 CS전공지식] 2주차 발자국

1일차프로세스 동기화와 통신,재귀 프로세스 간 통신프로세스는 독립적으로 실행될 수도 있지만 다른 프로세스와 데이터를 주고받으며 통신하기도 합니다.통신 방식은 한 컴퓨터 내의 프로세스 간 통신과 네트워크를 통해 다른 컴퓨터의 프로세스와 통신하는 방법으로 나눌 수 있습니다. 프로세스 간 통신 방법파일(File) 이용통신하려는 프로세스들이 공통된 파일을 이용하여 데이터를 읽고 씁니다.파이프(Pipe) 이용운영체제가 생성한 파이프를 통해 데이터를 읽고 쓰는 방식입니다. 한 프로세스가 파이프에 데이터를 쓰면, 다른 프로세스가 이를 읽습니다. 쓰레드를 이용한 통신한 프로세스 내에서 쓰레드 간 통신 방법입니다.쓰레드는 코드, 데이터, 힙 영역을 공유하고, 각 쓰레드는 독립적인 스택을 가집니다. 따라서 공유된 데이터나 힙 영역을 통해 쓰레드 간 데이터를 주고받을 수 있습니다.네트워크를 이용한 통신소켓(Socket): 운영체제가 제공하는 소켓을 사용하여 네트워크 상의 다른 컴퓨터와 통신합니다.RPC(Remote Procedure Call, 원격 프로시저 호출): 네트워크를 통해 다른 컴퓨터의 프로세스에 있는 함수를 호출하는 방식입니다.  공유 자원과 임계 구역공유 자원프로세스 간 통신에서 공동으로 사용하는 변수나 파일 등을 공유 자원(Shared Resource) 이라고 합니다.공유 자원은 여러 프로세스가 동시에 접근할 경우, 접근 순서에 따라 결과가 달라질 수 있습니다.경쟁 조건 (Race Condition)여러 프로세스가 동시에 공유 자원에 접근하려고 경쟁하는 상황을 경쟁 조건이라 합니다.컨텍스트 스위칭(Context Switching)으로 인해 어떤 프로세스가 먼저 실행될지 예측하기 어렵습니다.따라서 여러 프로세스가 동시에 사용하면 안되는 영역을 정의했는데 이를 **임계구역이라 함**임계 구역 (Critical Section)여러 프로세스가 동시에 접근하면 안 되는 코드 영역을 임계 구역이라 합니다. 임계 구역 문제 해결 - 상호 배제 매커니즘(Mutual Exclusion)임계 구역 문제를 해결하려면 상호 배제 매커니즘이 필요합니다.주요 상호 배제 메커니즘뮤텍스(Mutex):상호 배제를 위한 동기화 도구로, 한 번에 하나의 프로세스 또는 스레드만 접근할 수 있도록 합니다.세마포어(Semaphore):공유 자원에 여러 프로세스가 동시에 접근하는 것을 방지하기 위한 동기화 도구입니다.모니터(Monitor):공유 자원과 해당 자원에 대한 연산을 묶어서 관리하는 동기화 도구입니다.상호 배제를 만족하기 위한 요구사항:상호 배제: 어떤 시점에도 하나의 프로세스만 임계 구역에 접근해야 합니다.진행 조건: 여러 프로세스가 임계 구역에 들어가기를 원하면, 하나의 프로세스만 선택되어야 합니다.유한 대기: 임계 구역에 들어간 프로세스는 최대한 빨리 종료해야 하며, 다른 프로세스가 무한정 기다리는 것을 방지해야 합니다.  프로세스 동기화 기법세마포어 (Semaphore)공유 자원에 여러 프로세스가 동시에 접근하는 것을 방지하기 위한 동기화 도구입니다.wait() 함수와 signal() 함수를 사용하여 자원 접근을 조절합니다.문제점: wait()와 signal()을 잘못 사용하면 **교착 상태(Deadlock)나 **경쟁 상태가 발생할 수 있습니다.**교착 상태 : 여러 프로세스가 서로 필요한 자원을 기다리면서 무한정 대기하는 상태입니다. 세마포어의 wait() 함수를 잘못 사용하면 교착 상태가 발생할 수 있습니다.**경쟁 상태 : 세마포어의 signal() 함수를 잘못 사용하면 여러 프로세스가 동시에 임계 구역에 접근하여 데이터 불일치 등의 문제가 발생할 수 있습니다. 세마포어의 사용 코드 예제(JAVA) public static void main(String[] args) throws InterruptedException { Semaphore semaphore = new Semaphore(1); semaphore.acquire(); // acqurie()는 wait()과 같은 역할을 담당 System.out.println("wait 실행"); semaphore.release(); // release()는 signal()과 같은 역할을 담당 System.out.println("signal 실행"); } 모니터 (Monitor)세마포어의 문제점을 보완한 상호 배제 매커니즘입니다.운영체제가 아닌 프로그래밍 언어 차원에서 제공하며, Java의 synchronized 키워드가 대표적입니다.synchronized 키워드가 붙은 메서드는 한 번에 하나의 쓰레드만 접근할 수 있습니다. 그럼 세마포어의 문제점을 보완한게 모니터니까 모니터를 사용하는게 가장 좋은건가??세마포어와 모니터: 세마포어는 개발자가 직접 'wait'과 'signal'을 조작해야 하기 떄문에 세밀한 관리가 가능하지만 호출 순서 및 위치를 잘못 설정하면 교착상태,경쟁조건이 생길 수 있어 복잡하고 세밀한 동기화를 사용하기 좋음모니터는 공유 자원에 접근하는 코드를 '모니터'라는 방 안에 넣으면 알아서 한 번에 한 명씩만 들어가도록 관리를 해줘 개발자는 안전하게 코드가 작성이 가능해 안전한 동기화에 좋지만 세마포어보다 오버헤드가 클 수 가있음모니터의 사용 코드 예제(JAVA) public static void main(String[] args) { Object lock = new Object(); // 락으로 사용할 객체 synchronized (lock) { // 락이 있을경우 해당 메서드에 진입해 실행 System.out.println("Inside synchronized block."); //실행문 종료 후 별다른 명령어 없이 자동으로 lock 반납 } }  뮤텍스 (Mutex)세마포어와 유사하지만, 뮤텍스는 오직 하나의 프로세스/스레드만 공유 자원에 접근하도록 제한합니다.잠금(lock)과 해제(unlock) 연산을 통해 임계 영역을 보호합니다.주로 하나의 공유 자원에 대한 접근을 순차적으로 처리해야 할 때 사용됩니다.뮤텍스는 잠금을 소유한 스레드만이 잠금을 해제할 수 있다는 특징이 있습니다.뮤텍스의 사용 코드 예제(JAVA) public static void main(String[] args) { ReentrantLock lock = new ReentrantLock(); lock.lock(); // lock 활성화 System.out.println("Lock acquired."); lock.unlock(); // lock 반납 System.out.println("Lock released."); }재귀 (Recursion)재귀란?어떤 것을 정의할 때 자기 자신을 참조하는 방식입니다.함수가 자기 자신을 호출하는 재귀 함수가 대표적인 예입니다.재귀 함수의 종료 조건재귀 함수에는 반드시 탈출 조건이 필요합니다.탈출 조건이 없으면 무한 재귀가 발생하며, **콜 스택(Call Stack)이 가득 차 프로그램이 비정상 종료됩니다.함수를 호출하면 해당 함수는 콜스택 위에 올라가고 함수가 종료되면 콜스택에서 제거됨**콜 스택 (Call Stack)함수 호출 기록을 저장하는 메모리 영역입니다.FILO(First In Last Out) 구조를 가지며, 마지막에 호출된 함수가 가장 먼저 종료됩니다. 재귀, 반복문반복문(for, while)으로 해결 가능한 문제를 재귀 함수로 구현하면 비효율적일 수 있습니다.재귀 함수는 함수를 호출할 때마다 새로운 **스택 프레임을 생성합니다. 이 스택 프레임에는 함수의 매개 변수지역 변수,반환 주소 등의 정보가 저장되어 코드만 실행하면 되는 반복문에 비해 함수 호출 및 스택 관리에 더 많은시간과 메모리를 소비해야함** 스택 프레임??프로그램 실행 중에 함수가 호출될 때 생성되는 메모리 블록으로 함수에 호출된 정보를 저장그러나 팩토리얼 계산등 문제의 구조 자체가 재귀적인 경우 재귀 함수가 유리합니다.// 반복문 int sum = 0; for (int i = 1; i <= n; i++) { sum += i; } // 재귀 함수 int recursiveSum(int n) { if (n == 1) { return 1; } return n + recursiveSum(n - 1); } 팩토리얼 예제(JAVA)public class FactorialExample { public static int factorial(int n) { if (n == 1) return 1; // 탈출 조건 return n * factorial(n - 1); } public static void main(String[] args) { System.out.println("5! = " + factorial(5)); // 120 출력 } }2일차프로세스 동기화와 통신,재귀 교착상태 (Deadlock)교착상태란?교착상태(Deadlock)는 여러 프로세스가 서로 다른 프로세스가 보유한 자원을 기다리며 무한히 대기하는 상태를 의미합니다. 이 상태에 빠지면 어떤 프로세스도 작업을 진행하지 못하게 됩니다.공유 자원: 프로세스들이 서로 공유하는 자원(예: 프린터, 메모리 등)이 있을 때 발생할 수 있음.독립 자원: 반대로, 공유하지 않는 자원만 사용한다면 교착상태는 발생하지 않음.  교착상태의 필요조건교착상태가 발생하기 위한 4가지 필요조건이 있으며, 이 중 하나라도 충족되지 않으면 교착상태가 발생하지 않습니다.상호 배제 (Mutual Exclusion)어떤 자원이 한 프로세스에 의해 점유되었다면, 그 자원은 다른 프로세스와 공유되지 않아야 함.비선점 (No Preemption)다른 프로세스가 점유한 자원을 강제로 빼앗을 수 없어야 함.점유와 대기 (Hold and Wait)어떤 프로세스가 자원을 점유한 상태에서 추가 자원을 기다려야 함.즉, 이미 할당된 자원을 보유하면서 다른 자원을 요청하고 대기하는 상태여야 합니다.원형 대기 (Circular Wait)점유와 대기 상태의 프로세스들이 원형으로 연결되어 있어야 함.예를 들어, 프로세스 A는 프로세스 B가 가진 자원을 기다리고, 프로세스 B는 프로세스 C가 가진 자원을 기다리고, 프로세스 C는 프로세스 A가 가진 자원을 기다리는 식입니다.  교착상태 해결 방법교착 상태는 여러 프로세스가 서로 필요한 자원을 기다리며 무한히 대기하는 상황을 의미합니다. 이러한 교착 상태를 해결하기 위한 다양한 방법 중 하나가 바로 **교착 상태 회피입니다.**교착 상태 회피란?시스템이 자원을 할당하기 전에 교착상태 가능성을 검사하고, 교착상태가 발생하지 않도록 자원을 할당.대표 알고리즘: **은행가 알고리즘 (Banker's Algorithm)** 은행가 알고리즘의 특징시스템은 프로세스들의 최대 요구 자원을 미리 알고 있어야 함.자원 할당 전에 시스템의 상태를 안정 상태(Safe State)와 불안정 상태(Unsafe State)로 구분안정 상태(Safe State): 교착상태에 빠지지 않을 수 있는 상태.불안정 상태(Unsafe State): 교착상태에 빠질 가능성이 있는 상태. (불안정 상태가 반드시 교착상태를 의미하진 않음)안정 상태의 예시시스템의 총 자원 14개P1: 최대 9개, 현재 5개 점유 → 추가로 4개 필요P2: 최대 6개, 현재 4개 점유 → 추가로 2개 필요P3: 최대 4개, 현재 3개 점유 → 추가로 1개 필요사용 가능한 자원: 2개자원 할당 순서P1은 4개를 요청하므로 거절.P2는 2개 요청 가능 → 작업 완료 후 6개 반납.P1은 이제 4개 요청 가능 → 작업 완료 후 자원 반납.불안정 상태의 예시시스템의 총 자원 10개P1: 최대 7개, 현재 5개 점유 → 추가로 2개 필요P2: 최대 5개, 현재 3개 점유 → 추가로 2개 필요P3: 최대 4개, 현재 2개 점유 → 추가로 2개 필요사용 가능한 자원: 1개자원 할당 상태P1, P2, P3 모두 추가 자원을 받기 위해 대기.사용 가능한 자원이 1개뿐이라 어느 프로세스도 필요한 자원을 다 받지 못함.세 프로세스가 서로 자원을 기다리며 무한 대기 상태 → 교착상태 발생  교착상태가 발생한지 알아내는 방법가벼운 교착상태 검출:타이머를 설정해 특정 시간 동안 프로세스가 작업을 하지 않으면 교착상태라고 판단.해결 방법 : 체크포인트를 통해 주기적으로 상태를 저장하고, 교착상태 발생 시 마지막 체크포인트로 롤백.간단하지만, 오탐지 가능성이 있고 롤백에 따른 오버헤드가 발생할 수 있습니다무거운 교착상태 검출:**자원 할당 그래프(Resource Allocation Graph, RAG)를 사용.프로세스-자원 관계를 그래프로 표현하고 사이클이 발견되면 교착상태로 간주.정확도가 높지만, 자원 할당 그래프를 관리하고 순환을 탐지하는 데 오버헤드가 발생합니다.오버헤드가 발생하지만, 프로세스를 강제로 종료하지 않고 교착상태를 해결 가능. **자원 할당 그래프자원할당 그래프의 사이클이 존재하는 지 그림으로 확인해당 그림처럼 프로세스와 자원 간의 사이클이 존재한다면 교착상태이고 해당 그림처럼 프로세스와 자원간의 사이클이 없으면 교착상태가 아니다하지만 사이클이 있어도 교착상태에 안걸리는 경우도 존재하는데P2와 P4가 작업을 완료하고 자원을 반납하면R1과 R2의 자원을 반납P1과 P3가 필요한 자원을 얻을 수 있음.원형 대기 상태가 깨지므로 교착상태가 해소됨.  재귀적으로 생각하기 패턴 1: 단순 반복의 재귀적 구현 (비효율적)반복문으로 간단하게 해결할 수 있는 문제를 재귀 함수로 구현하는 것은 일반적으로 비효율적입니다. 재귀 호출은 콜 스택 공간 사용을 발생시키므로 단순 반복 작업은 for 문을 사용하는 것이 좋습니다.// 반복문 (효율적) public static int sum1(int n) { int total = 0; for (int i = 1; i <= n; i++) { total += i; } return total; } // 재귀 함수 (비효율적) public static int sum2(int n) { if (n == 1) { return 1; } return n + sum2(n - 1); } 패턴 2: 하위 문제 기반 문제 해결 (하향식 vs. 상향식)재귀는 하위 문제의 결과를 기반으로 현재 문제를 해결하는 데 특히 유용합니다. 대표적인 예가 팩토리얼 계산입니다.재귀함수를 이용한 팩토리얼 자바코드 예시public static int factorial(int n) { if (n == 0) { return 1; } return n * factorial(n - 1); }for문을 이용한 팩토리얼 자바코드 예시public static int factorial(int n) { int result = 1; for (int i = 1; i <= n; i++) { result *= i; } return result; } 재귀와 반복문재귀 함수는 상향식 계산도 가능하지만, 반복문으로 구현하는 것보다 성능이 좋지 않습니다.재귀 함수는 하향식 계산에서 위력을 발휘합니다. 특히 문제의 구조 자체가 재귀적인 경우 재귀 함수를 사용하면 코드를 간결하고 이해하기 쉽게 만들 수 있습니다. 재귀와 for문을 이용해 배열의 합 구현// 재귀 함수 public static int arraySum(int[] arr, int n) { if (n == 0) { return 0; } return arr[n - 1] + arraySum(arr, n - 1); } // 반복문 public static int arraySum(int[] arr) { int total = 0; for (int num : arr) { total += num; } return total; } 문자열 길이 계산 public static int strLength(String arr) { if (arr == null || arr.isEmpty()) { return 0; } return strLength(arr.substring(1)) + 1; }  지수 함수 하향식 구현public static int power(int x, int y) { if (y == 0) { return 1; } return x * power(x, y - 1); } 3일차컴파일과 프로세스, 재귀 - 하노이 탑 컴파일과 프로세스프로그래밍 언어의 종류프로그래밍 언어는 컴파일 언어와 인터프리터 언어로 구분할 수 있습니다.컴파일 언어개발자가 코드를 작성하고 컴파일이라는 과정을 거쳐 기계어(0과 1) 로 된 실행 파일을 생성합니다.컴파일 과정에서 문법 오류가 있는지 검사하고, CPU에서 실행할 수 있는 기계어로 변환합니다.미리 실행 파일을 만들어 놓으므로 실행 속도가 빠릅니다.예시: C, C++, C# 등인터프리터 언어개발자가 작성한 코드를 미리 기계어로 변환하지 않고, 실행 시점에 한 줄씩 해석하며 실행합니다.실행 전에 오류 검사를 하지 않기 때문에 실행 중 오류가 발생할 수 있으며, 속도도 컴파일 언어보다 느립니다.예시: JavaScript, Python 등  컴파일 언어로 작성된 파일이 프로세스가 되기까지C 언어로 작성된 test.c 파일이 실행 파일이 되고, 최종적으로 프로세스가 되는 과정1. 컴파일 과정전처리컴파일러가 실행되면 가장 먼저 전처리기가 동작합니다.전처리기는 #include, #define 등 전처리 구문을 처리합니다.주석 제거를 수행한 후 전처리된 코드를 .i 파일로 저장합니다.컴파일전처리된 코드를 기계어에 가까운 어셈블리어로 변환합니다.이 과정에서 문법 오류 체크도 함께 이루어집니다.결과물은 어셈블리 코드가 담긴 .s 파일입니다.어셈블어셈블리어를 기계어 코드(오브젝트 코드)로 변환합니다.생성된 오브젝트 파일은 .o 확장자를 가집니다.이 오브젝트 파일에는 코드 영역과 데이터 영역이 나눠져 있습니다.링커오브젝트 파일은 실행 파일이 되기 위해 링커(Linker) 를 거칩니다.링커는 여러 오브젝트 파일을 하나로 합치고, 코드 영역과 데이터 영역을 하나로 묶습니다. 결과물은 실행 파일(.exe)입니다. 2. 프로세스 생성 과정실행 파일이 프로세스가 되려면 다음 과정을 거칩니다프로그램 실행사용자가 .exe 파일을 실행합니다.운영체제가 프로세스를 생성합니다.메모리 할당운영체제는 실행 파일에 있는 코드 영역과 데이터 영역을 가져와 프로세스의 코드 영역과 데이터 영역에 로드합니다.그리고 빈 스택(Stack)과 힙(Heap) 영역도 할당합니다.PCB 생성운영체제는 PCB를 생성하여 프로세스를 관리합니다.PCB에는 프로세스 상태, 프로그램 카운터(PC), CPU 레지스터, 메모리 정보 등이 저장됩니다.프로그램 카운터 설정프로그램 카운터(PC) 는 다음 실행할 명령어의 주소를 가리킵니다.처음에는 코드 영역의 첫 번째 명령어의 주소를 가리킵니다.CPU 스케줄링운영체제의 CPU 스케줄러가 프로세스를 준비 상태에 놓고, CPU를 할당받으면 실행 상태로 전환되어 명령어가 실행됩니다.   재귀-하노이탑자바 코드 사용 예시 public static void hanoi(int count, String from, String to, String temp) { if (count == 0) { return; } hanoi(count - 1, from, temp, to); System.out.println(count + "를 " + from + "에서 " + to + "로 이동"); hanoi(count - 1, temp, to, from); } public static void main(String[] args) { hanoi(3, "A", "C", "B"); // 3은 옮겨야할 갯수 A는 시작위치 C는 도착해야할 위치 B는 거쳐갈 위치 }결과창4일차메모리 관리,버블정렬과 선택정렬 메모리의 종류레지스터가장 빠른 기억 장소로 CPU 내부에 존재합니다.컴퓨터의 전원이 꺼지면 데이터가 사라지므로 휘발성 메모리입니다.CPU의 32비트, 64비트는 레지스터 크기를 의미합니다.CPU는 연산 시 메인 메모리(RAM)에 있는 데이터를 레지스터로 가져와 계산하고, 결과를 다시 메인 메모리에 저장합니다. 캐시(Cache)레지스터와 메인 메모리 사이에 위치하여, 데이터 접근 속도를 향상시키는 역할을 합니다.CPU는 필요한 데이터를 메인 메모리에서 가져오기 전에 L1 캐시 → L2 캐시 → L3 캐시 순으로 확인합니다.캐시에 가져올 데이터가 없으면 메인 메모리에서 데이터를 가져옵니다. 메인 메모리(RAM) 실제 운영체제와 프로세스가 로드되는 공간입니다.휘발성 메모리로, 전원이 꺼지면 데이터가 사라집니다.속도는 HDD/SSD보다 빠르지만, 가격이 비싸기 때문에 실행 중인 프로그램만 저장합니다. HDD/SSD비휘발성 메모리로, 전원이 꺼져도 데이터가 보존됩니다.속도는 메인 메모리보다 느리지만, 가격이 저렴하여 데이터 저장 용도로 사용됩니다.  메모리 할당 방식메모리 오버레이:프로그램을 분할하여 필요한 부분만 메모리에 로드하고, 나머지는 스왑 영역에 저장합니다.스왑(Swap): 스왑영역에 있는 데이터를 메모리로 가져오고 메모리에 있는 데이터를 스왑영역으로 옮기는것을 말합니다.가변 분할 방식(Variable Partitioning)프로세스 크기에 따라 메모리를 연속된 공간에 동적으로 할당합니다.장점: 연속된 공간으로 할당하기 때문에 내부 단편화가 발생하지 않습니다.단점: 외부 단편화가 발생합니다.예시: 프로세스 A(50MB), B(30MB), C(15MB), D(10MB)가 메모리에 차례로 로드이후 A와 D가 종료되어 빈 공간(50MB + 10MB)이 생기고 새로운 프로세스 E(60MB)를 로드하려고 할 때 이 공간들은 연속되어 있지 않아 할당할 수 없는데 이를 외부 단편화라고 하며, 조각 모음을 통해 빈 공간들을 하나로 합쳐야 합니다. 이 과정은 메모리에 있는 프로세스를 일시 중지하고 공간을 이동시키는 작업이므로 오버헤드가 발생합니다. 고정 분할 방식(Fixed Partitioning)메모리를 고정 크기 블록으로 나눠 프로세스를 할당합니다.장점: 구현이 간단하고 오버헤드가 적습니다.단점: 프로세스 크기와 상관없이 고정된 크기로 메모리를 할당하므로 내부 단편화가 발생합니다.예시: 메모리를 2MB로 나눈다 가정할 때 프로세스 A(1MB), B(2MB), C(5MB)를 할당할 경우,A는 2MB 블록에 할당되어 1MB의 내부 단편화가 발생합니다. B는 2MB 블록에 할당되고 B는 2MB이기 때문에 정확히 떨어짐. C는 총 5MB이기 때문에 2MB 블록을 3개의 구역에 나눠서 저장해 1MB의 내부 단편화가 발생. 버디 시스템(Buddy System)가변 분할 방식과 고정 분할 방식을 혼합하여 단점을 보완합니다.메모리를 2의 제곱수 크기로 나누고, 필요할 때마다 나눠 프로세스를 할당합니다.장점: 외부 단편화를 방지하고, 메모리 합병(병합)이 간단합니다.단점: 약간의 내부 단편화가 발생할 수 있습니다. 그럼 메모리 할당 방식은 둘의 단점을 최소화한 버디 시스템이 최고인가??버디 시스템의 내부 단편화와 작은 크기의 블럭을 지나치게 나누면 생기는 메모리 관리 오버헤드가 커질수있어 최신 운영체제는 페이징 기법을 활용하거나, 세그멘테이션과 조합해서 사용페이징 기법 (Paging)정의:메인 메모리를 고정된 크기의 블록인**페이지 프레임(Page Frame)으로 나누고, 프로세스의 가상 메모리 공간도 동일한 크기의 **페이지(Page)로 나눕니다.프로세스의 페이지들은 메모리의 페이지 프레임에 비연속적으로 할당됩니다.페이지 프레임과 페이지란???페이지는 프로세스를 나눈 조각페이지 프레임은 메모리를 나눈 조각장점:외부 단편화가 발생하지 않습니다.메모리 관리가 단순해집니다.단점:내부 단편화가 발생할 수 있습니다. (마지막 페이지가 완전히 채워지지 않는 경우)예시:프로세스 A가 5KB이고, 페이지 크기가 2KB라면, A는 3개의 페이지로 나뉩니다.마지막 페이지는 1KB만 사용되고 1KB는 낭비되므로 내부 단편화가 발생합니다.추가 설명: 페이지 테이블을 사용하여 가상 주소를 물리 주소로 변환합니다.고정 분할 방식과 페이징 기법은 비슷하지만 고정 분할 방식은 메모리를 나눈 후 프로세스를 맞춰 넣는 방식이고,페이징은 프로세스를 나눈 후 메모리에 퍼즐처럼 넣는 방식  세그멘테이션 (Segmentation)정의:프로세스를 논리적인 의미 단위인 세그먼트(Segment)로 나누어 메모리에 로드합니다.세그먼트의 크기는 가변적입니다.장점:논리적으로 관련된 코드나 데이터가 한 곳에 모이므로 효율적입니다.프로그램의 구조를 반영하여 메모리를 관리할 수 있습니다.단점:외부 단편화가 발생할 수 있습니다.예시:프로그램이 코드(10KB), 데이터(5KB), 스택(8KB)으로 나뉜 경우, 각 부분이 독립적인 세그먼트로 관리됩니다.추가 설명:세그먼테이션은 프로그램의 논리적인 구조를 반영하여 메모리를 관리하는 데 유용합니다.최근에는 페이징과 함께 사용되어 메모리 보호 및 공유 기능을 강화합니다.요약:페이징은 메모리를 고정 크기로 나누어 관리하고, 세그멘테이션은 논리적인 단위로 나누어 관리합니다.페이징은 외부 단편화를 해결하고, 세그멘테이션은 프로그램의 논리적인 구조를 반영합니다.. 페이징 + 세그먼테이션을 사용하면 내부/외부 단편화가 완전히 사라지는 것은 아니지만, 각각의 단점을 최소화할 수 있습니다.   버블 정렬과 선택 정렬정렬 알고리즘은 데이터를 특정 순서로 나열하는 방법을 정의버블 정렬과 선택 정렬은 가장 기본적인 정렬 알고리즘으로 이해와 구현이 쉽지만 성능은 다소 아쉬움1. 버블 정렬 (Bubble Sort)원리:인접한 두 원소를 비교하여 순서가 맞지 않으면 교환하는 과정을 반복합니다. 예시:[4, 2, 3, 1] 배열을 정렬하는 과정:[2, 4, 3, 1] (4와 2 교환)[2, 3, 4, 1] (4와 3 교환)[2, 3, 1, 4] (4와 1 교환)위 과정을 반복하여 [1, 2, 3, 4] 완성성능:시간 복잡도: O(n²) - 데이터가 많아질수록 비교 횟수가 제곱으로 증가합니다.장단점:장점: 이해와 구현이 매우 쉽습니다.단점: 성능이 좋지 않아 대규모 데이터 처리에는 부적합합니다. 자바코드로 예시 구현 public static void bubble(int[] arr) { int n = arr.length; for (int i = 0; i < n - 1; i++) { // arr 배열의 길이에서 -1만큼만 반복 for (int j = 0; j < n - i - 1; j++) { if (arr[j] > arr[j + 1]) { // arr[j]번쨰 값이 arr[j]다음의 값보다 크다면 int temp = arr[j]; // 현재 arr[j]번째의 값을 저장해두고 arr[j] = arr[j + 1]; // arr[j]의 값을 arr[j] 다음의값으로 변경 arr[j + 1] = temp;// arr[j] 다음의값을 이전에 temp에 저장해둔 arr[j]값으로 변경 } } } } public static void main(String[] args) { int[] arr = {4, 2, 3, 1}; bubble(arr); for (int num : arr) { System.out.print(num + " "); } }    2. 선택 정렬 (Selection Sort)원리:배열에서 가장 작은 원소를 찾아 첫 번째 위치로 이동시키고, 다음으로 작은 원소를 찾아 두 번째 위치로 이동시키는 과정을 반복합니다.정렬되지 않은 부분에서 최소값을 선택하여 정렬된 부분의 마지막 위치로 이동시킵니다.예시:[4, 2, 1, 3] 배열을 정렬하는 과정:[1, 2, 4, 3] (최소값 1을 첫 번째 위치로 이동 기존에 있던 4는 1이있던 자리로 이동)[1, 2, 4, 3] (다음 최소값 2는 이미 정렬된 위치)[1, 2, 3, 4] (다음 최소값 3을 세 번째 위치로 이동)성능:시간 복잡도: O(n²) - 버블 정렬과 마찬가지로 성능이 좋지 않습니다.장단점:장점: 버블 정렬과 마찬가지로 이해와 구현이 쉽습니다.단점: 성능이 좋지 않아 대규모 데이터 처리에는 부적합합니다. 자바코드로 예시 구현 public static void selection(int[] arr) { for (int i = 0; i < arr.length - 1; i++) { // 정렬되지 않은 부분의 첫 번째 원소를 최소값으로 가정 // 정렬된 부분은 반복에서 제거하기위해 사용 int minValueIndex = i; // 정렬되지 않은 부분에서 최소값을 찾음 for (int j = i + 1; j < arr.length; j++) { if (arr[j] < arr[minValueIndex]) {// arr[j]값이 arr[minValueIndex] 값보다 작을경우 minValueIndex = j; // 정렬할 인덱스 값을 넣어주고 } } // 최소값을 정렬되지 않은 부분의 첫 번째 원소와 교환 int temp = arr[i]; // 현재 arr[i]의 값을 temp에 저장 arr[i] = arr[minValueIndex]; // arr[i]의 값을 arr[minValueIndex] 변경 arr[minValueIndex] = temp; // arr[minValueIndex]값을 이전에 temp에 저장해둔 값으로 변경 } } public static void main(String[] args) { int[] arr = {4, 2, 1, 3}; selection(arr); System.out.print("실행 결과 :"); for (int num : arr) { System.out.print(num + " "); } }  정리버블 정렬과 선택 정렬은 기본적이지만 비효율적인 정렬 알고리즘입니다.  2주차 회고 잘한 점저번주에 다짐했던 그날그날 강의를 듣고 정리하는건 잘지켰고 확실히 그날 배운 내용을 바로바로 정리하니 저번주보다 죽은지식이 덜했습니다.저번주는 몰아서 정리하다보니 아 이거 뭐였지 하며 다시 찾아보고 하는 경우가 많았는데 현저히 줄어든게 느껴졌습니다. 아쉬운 점운영체제는 역시 여전히 어려웠습니다.아무래도 강의가 기본으로 쉽게 이해하려는데 초점이 맞춰져있다보니 아주 쉽게 동작원리를 알려주다보니 하나의 내용을 던져주고 궁금해서 그걸 가지고 파다보면 끝도없는 용어와 또 다른 내용이 튀어나와 역시 쉽지않았습니다.자료구조와 알고리즘은 재귀 버블정렬 등 해당 알고리즘의 개념을 이해만 한다면 코드로 녹여내는건 생각보다 어렵지않았고 오히려 정말 재밌게 공부했었습니다.이무래도 코드를 작성하면 시각적으로 결과가 바로바로 보여지다보니 좀더 흥미를 느꼈던거같습니다. 개선할 점이제 다음주가 마지막 주차인데 이번주 보다 공부 시간을 좀 더 늘리겠습니다. 목표이번주 역시 로드맵에 맞게 해당 강의 영상을 듣고 바로바로 발자국으로 내용 정리하기2주차에 투자한 공부시간보다 더 늘리기질문 더 많이하기   

[워밍업 클럽 3기 - CS 전공 지식] - Day 9 미션 2

운영체제FIFO 스케줄링의 장단점이 뭔가요?장점단순하고 이해하기 쉽다단점실행 시간(burst time)이 짧은 프로세스는 실행 시간이 길더라도 일찍 도착한 프로세스의 완료를 기다려야한다 SJF를 사용하기 여러운 이유가 뭔가요?A. 프로세스의 실행시간을 예측하기 어렵다.  RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요?A. 컨텍스트 스위칭을 처리하는 비용이 증가한다. 운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요?A. CPU 사용시간에 따라 우선순위 큐에 다르게 배치하면서 구분한다. 예를 들어, CPU 바운드 작업은 타임 슬라이스를 I/O 바운드 작업보다 오래 점유해서 사용하기 때문에, 우선순위가 낮은 큐에 배치시키고, 더 짧게 사용하는 I/O 바운드 프로세스는 우선순위가 더 높은 큐에 배치시킨다. (타임 슬라이스를 사용하는 시간과 요청 빈도에 의한 피드백) 공유자원이란 무엇인가요?A. 프로세스간 통신에서 공통으로 접근해서 이용하게 되는 데이터. 교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야할까요?상호 배제: 자원은 한번에 하나의 프로세스만 사용비선점: 이미 점유한 자원은 다른 프로세스가 뺏어갈 수 없다점유와 대기: 이미 자원을 점유한 프로세스가 추가적인 자원을 기다리는 상태원형 대기: 프로세스들이 서로가 가지고 있는 자원을 기다리며 대기하는 상태자료구조와 알고리즘재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요?A. 함수에서 탈출하지 못하기 때문에 무한하게 재귀를 호출하게 되면서 스택 오버플로우(StackOverflow)가 발생한다.0부터 입력 n까지 홀수의 합을 더하는 재귀 함수를 만들어보세요.A.function sumOdd(n) { if (n <= 0) return 0; // 기저조건 if (n % 2 === 0) return sumOdd(n - 1); return n + sumOdd(n - 2); } console.log(sumOdd(10)) // 25 다음 코드는 매개변수로 주어진 파일 경로(.는 현재 디렉토리)에 있는 하위 모든 파일과 디렉토리를 출력하는 코드입니다. 다음 코드를 재귀 함수를 이용하는 코드로 변경해보세요.import fs from "fs"; import path from "path"; function traverseDirectory1(directory){ const stack = [directory]; // 순회해야 할 디렉토리를 저장할 스택 while (stack.length > 0) { // 스택이 빌 때까지 반복 const currentDir = stack.pop(); // 현재 디렉토리 const files = fs.readdirSync(currentDir); // 인자로 주어진 경로의 디렉토리에 있는 파일or디렉토리들 for (const file of files) { // 현재 디렉토리의 모든 파일or디렉토리 순회 const filePath = path.join(currentDir, file); //directory와 file을 하나의 경로로 합쳐줌 const fileStatus= fs.statSync(filePath); // 파일정보 얻기 if (fileStatus.isDirectory()) { // 해당 파일이 디렉토리라면 console.log('디렉토리:', filePath); stack.push(filePath); } else { // 해당 파일이 파일이라면 console.log('파일:', filePath); } } } } traverseDirectory1("."); // 현재 경로의 모든 하위 경로의 파일, 디렉토리 출력 console.log("------------------------"); function traverseDirectory2(directory){ const files = fs.readdirSync(directory); // 현재 디렉토리의 파일 목록 가져오기 for (const file of files) { const filePath = path.join(directory, file); // 파일 또는 디렉토리의 전체 경로 const fileStatus = fs.statSync(filePath); // 파일정보 얻기 if (fileStatus.isDirectory()) { // 해당 파일이 디렉토리라면 console.log('디렉토리:', filePath); traverseDirectory2(filePath); // 재귀 호출하여 내부 탐색 } else { // 파일인 경우 console.log('파일:', filePath); } } } traverseDirectory2("."); // 현재 경로의 모든 하위 경로의 파일, 디렉토리 출력 

워밍업클럽3기cs미션

wonderson

[워밍업 클럽 3기 CS 전공지식] 2주차 회고

[2 주차 시작하기 전 다짐]아침에 일어나서 주어진 강의 분량을 다 듣기틈날 때 강의 듣기저녁에 집에 와서 다시 듣기 또는 실습 진행강의 들으면서 강의 노트도 실시간으로 작성하기![2 주차 회고]칭찬할 점2 주차 다짐을 모두 지켰다!=> 꾸준히 하는 걸 힘들어하는 나에게 칭찬하고 싶다.아쉬운 점 강의 노트를 적는 동안은 생각을 안 하고 따라 치기만 한 것 같다.=> 강의를 듣고 그 날 강의 노트를 정리하는 시간을 가지자. [강의 내용 정리][운영체제][프로세스 동기화]프로세스 간 통신프로세스는 독립적으로 실행되기도 하지만 다른 프로세스와 데이터를 주고받으며 통신을 하는 경우도 있다.종류한 컴퓨터 내에서 프로세스 간 통신파일을 이용한 방법통신을 하려는 프로세스들이 하나의 파일을 이용해 읽고 쓰는 방법파이프를 이용한 방법운영체제가 생성한 파이프를 이용해 데이터를 읽고 쓰는 방법한 프로세스 내에서 쓰레드 간 통신쓰레드는 코드, 데이터, 힙 영역을 공유하고 스택만 자기의 것을 가진다.데이터 영역에 있는 전역변수나 힙을 이용하면 통신이 가능하다.네트워크를 이용한 통신운영체제가 제공하는 소켓 통신하는 방법다른 컴퓨터에 있는 함수를 호출하는 RPC(원격 프로시저 호출)를 이용해 통신하는 방법공유자원과 임계구역공유자원프로세스 간 통신을 할 때 공동으로 이용하는 변수나 파일들문제여러 프로세스가 공유하고 있어서 각 프로세스의 접근 순서에 따라 결과가 달라진다.컨텍스트 스위칭으로 시분할 처리를 하기 때문에 어떤 프로세스가 먼저 실행될 지 예측하기 어렵다.연산 결과를 예측하기 힘들다. 여기서 발생한 문제가 '동기화 문제' 이다.그러니 예측 불가능하고 손 댈 수 없는 운영체제 보다는 예측 가능하고 손 댈 수 있는 코드를 수정하는 게 최선이다.동기화 문제여러 프로세스 또는 여러 쓰레드가 공유 자원에 동시에 접근할 때 발생하는 문제이다.적절한 제어 없이 데이터가 동시에 수정되면 경쟁 조건(Race Condition)이 발생하여 예측 불가능한 결과나 데이터 불일치가 일어난다.해결 방법으로는 세마포어, 모니터 등의 동기화 기법을 사용한다.임계구역(Critical Section)여러 프로세스가 동시에 사용하면 안되는 영역임계구역 문제를 해결하기 위해서는 '상호 배제(Mutual Exclusion)' 메커니즘'이 필요하다.상호 배제(Mutual Exclusion) 요구사항 세가지임계영역에는 동시에 하나의 프로세스만 접근한다.(동시에) 여러 요청에도 하나의 프로세스의 접근만 허용한다.임계구역에 들어간 프로세스는 빠르게 나와야 한다.그렇지 않으면 다른 프로세스들이 오래 기다려야 한다. 세마포어(Semaphore)상포배제 메커니즘의 한 가지이다.정수형 변수이다.공유되는 자원의 개수에 따라 세마포어의 초기값 숫자를 설정한다.wait() 함수로 시작하고 signal() 함수로 끝나야 한다. 사이에 코드 작성세마포어를 이용하면 공유자원에 여러 프로세스가 동시에 접근하지 못하기 때문에 동기화 문제가 발생하지 않는다.단점wait(), signal() 함수의 순서를 이상하게 호출해서 잘못 사용할 경우가 있다.=> 이것을 해결한 방법은 '모니터'이다.모니터(Monitor)세마포어의 단점을 해결한 상호배제 메커니즘운영체제가 처리하는 것이 아닌 프로그래밍 언어 차원에서 지원하는 방법대표적으로 Java 에서 모니터를 지원synchronized 키워드해당 키워드가 붙은 함수들은 동시에 여러 프로세스에서 실행시킬 수 없다.상호배제가 완벽하게 이루어진다. [데드락]교착 상태(데드락)여러 프로세스가 서로 다른 프로세스의 작업이 끝나기를 기다리다가 아무도 작업을 진행하지 못하는 상태발생 이유여러 프로세스가 공유하는 자원 때문이다.자원을 공유하지 않으면 교착 상태가 발생하지 않는다.유명한 예시식사하는 철학자교착 상태의 필요조건교착상태가 발생하기 위해서는 4가지 필요 조건이 모두 충족되어야 한다.상호배제프로세스A가 한 자원을 점유했다면 그 자원은 프로세스B에게 공유가 되면 안된다.비선점프로세스A가 자원을 점유하고 있는데 프로세스B가 자원을 빼앗을 수 없어야 한다.점유와 대기어떤 프로세스가 자원A를 가지고 있는 상태에서 자원B를 원하는 상태여야 한다.원형 대기점유와 대기를 하는 프로세스들의 관계가 원형을 이루고 있다.해결교착 상태 회피(Deadlock avoidance)프로세스들에게 자원을 할당할 때 어느 정도 자원을 할당 했을 때 교착 상태가 발생하는지 파악해서 교착 상태가 발생하지 않는 수준의 자원을 할당한다.전체 자원의 수와 할당된 자원의 수를 기준으로 안정 상태(Safe state)와 불안정 상태(Unsafe state)로 나뉜다.운영체제가 최대한 안정 상태를 유지하려고 한다.불안정 상태에 있더라도 무조건 교착 상태에 빠지는 건 아니고 교착 상태에 빠질 확률이 높아진다.은행원 알고리즘돈을 빌려줄 때 사업가들의 상환 능력도 보면서 빌려준다.교착 상태 발생했을 때 해결교착 상태를 막지 못한다. 그래서 교착 상태가 발생했을 때 해결하는 방법을 알아보자.가벼운 교착 상태 검출타이머를 이용한 방식프로세스가 일정 시간 동안 작업을 진행하지 않는다면 교착상태가 발생한 걸로 간주하고 해결한다.교착 상태 해결일정 시점마다 체크포인트를 만들어 작업을 저장한다.타임아웃으로 교착상태가 발생했다면 마지막으로 저장했던 체크포인트로 롤백한다.무거운 교착 상태 검출자원 할당 그래프를 이용현재 운영체제에서 프로세스가 어떤 자원을 사용하는지 지켜보고 교착상태가 발생했다면 해결한다.프로세스들 간 자원 점유와 대기가 순환구조가 생긴다면 교착상태가 생긴 그래프이다.교착상태를 검출했다면 교착상태를 일으킨 프로세스를 강제종료 시킨다.그리고 다시 실행시킬 때 체크포인트로 롤백을 시킨다.운영체제가 지속적으로 자원 할당 그래프를 유지하고 검사해야 하기 때문에 오버헤드가 발생한다.가벼운 교착상태 검출에서 발생할 수 있는 억울하게 종료되는 프로세스는 발생하지 않는다. [프로그래밍 언어, 프로세스] 프로그래밍 언어컴파일 언어개발자가 코드를 작성하고 컴파일 과정을 거쳐서 0과 1로된 기계어로 실행파일을 만든다.컴파일 과정에서 문법 오류를 검사하고 CPU에서 처리가능한 기계어로 실행파일을 만들어 놓기 때문에 속도가 빠르다.C, C++, C# 등이 이에 속한다.인터프리터 언어개발자가 작성한 코드를 미리 기계어로 만들지 않고 실행 시 코드를 한 줄씩 해석해 실행하는 언어이다.미리 검사를 하지 않기 때문에 실행할 때 오류가 날 수 있고 속도도 컴파일 언어와 비교하면 느리다.JavaScript, Python, Ruby 등이 이에 속한다.프로세스의 메모리 구조코드 영역, 데이터 영역, 스택 영역, 힙 영역으로 나뉜다.코드 영역말 그대로 실행해야 할 코드가 들어가는 영역데이터 영역전역변수나 배열이 들어가는 영역스택과 힙은 프로세스가 실행될 때 할당되는 메모리스택 영역지역변수와 함수 관련 값들힙 영역실행중에 메모리 공간을 할당할 수 있는 유동적인 공간프로그램을 실행 시켰을 때사용자가 프로그램을 실행시키면 운영체제가 프로세스를 만든다.운영체제는 exe 파일에 있는 코드 영역과 데이터 영역을 가져온다.프로세스의 코드 영역과 데이터 영역에 넣어준다.빈 상태의 스택과 힙을 할당한다.PCB(Process Control Block)를 만들어 관리가 가능하도록 만든다.프로그램 카운터 즉, 다음 실행할 명령어의 주소를 생성한 프로세스의 코드 영역의 첫 번째 주소로 설정한다.운영체제의 CPU 스케줄링에 따라서 프로세스가 실행되다기 작업을 마친다.  [메모리]메모리 종류레지스터, 캐시, 메인메모리(RAM), 보조저장장치(하드디스크(이하 HDD), SSD)오른쪽으로 갈수록 가격은 싸지고 용량은 커진다. 속도는 느려진다.레지스터가장 빠른 기억 장소로 CPU 내에 존재한다.컴퓨터 전원이 꺼지면 데이터가 사라진다. 휘발성 메모리라고 부른다.32bit 레지스터를 가지고 있으면 32bit CPU라고 말한다.64bit 레지스터를 가지고 있으면 64bit CPU라고 말한다.CPU는 계산 할 때 메인메모리에 있는 값을 레지스터로 가져와서 계산한다. 계산 결과는 다시 메인메모리에 저장시킨다.캐시레지스터와 메인메모리에서 중간 단계 역할을 한다.레지스터는 CPU가 사용하는 메모리로 굉장히 빠르다. 그에 비해 메인메모리는 너무나 느리다.메인메모리에 있는 값을 레지스터로 옮기려면 한참 걸린다. 그래서 필요할 것 같은 데이터를 미리 가져오기로 한다.미리 가져온 데이터를 저장하는 곳이 바로 캐시이다.메인메모리(RAM)운영체제와 다른 프로세스들이 올라가는 공간이다.전원이 공급되지 않으면 데이터가 지워져 휘발성 메모리이다.HDD나 SSD 보다는 속도는 빠르지만 가격이 비싸기 때문에 데이터를 저장하기 보다 실행중인 프로그램만 올린다.보조저장장치인 HDD와 SSD가격이 저렴하고 전원이 공급되지 않아도 데이터가 지워지지 않는 비휘발성 메모리이다.저장 작업하기에 좋다. 메모리와 주소운영체제는 메모리를 관리하기 위해 1바이트 크기로 구역을 나누고 숫자를 매긴다.이 숫자를 '주소'라고 부른다. - 1바이트(8비트)마다 주소를 가지고 있다.물리 주소와 논리 주소물리 주소메모리 0x0번지부터 시작하는 주소 공간논리 주소사용자 관점에서 바라본 주소 공간사용자는 물리 주소를 몰라도 논리 주소로 물리 주소에 접근할 수 있다.경계 레지스터하드웨어적으로 운영체제 공간과 사용자 공간을 나누는 경계 레지스터절대 주소와 상대 주소절대 주소실제 프로그램이 올라간 주소는 0x4000번지로 메모리 관리자가 바라본 주소이다.상대 주소컴파일러는 0x0번지라고 가정해서 프로그램 만든다.사용자가 바라본 주소인 '상대 주소'는 '논리 주소 공간'이라고 부른다.메모리 관리자가 바라본 주소인 '절대 주소'는 '물리 주소 공간'이라고 부른다.메모리 관리자CPU가 요청한 상대 주소와 재배치 레지스터에 있는 절대 주소를 더해서 데이터에 접근한다.재배치 레지스터프로그램의 시작 주소가 저장되어 있다.시작 영역이 바뀌면 재배치 레지스터만 변경해주면 된다. 그래서 굉장히 유연하다.메모리 할당방식유니프로그래밍 환경에서 메모리보다 더 큰 프로그램을 실행시키는 방법메모리 오버레이(memory overlay)큰 프로그램을 작게 나누어 일부만 실행하고 일부는 HDD의 스왑 영역에 저장된다.스왑(swap)스왑 영역에 있는 데이터 일부를 메모리로 가져오고 메모리에 있는 데이터를 스왑 영역으로 옮긴다.멀티프로그래밍 환경에서 메모리 관리가변 분할 방식프로세스의 크기에 따라 메모리를 나누는 방식프로세스가 크면 메모리도 크게 할당한 프로세스가 메모리에 연속된 공간에 할당되서 '연속 메모리 할당'이라고 한다.장점메모리에 낭비되는 공간이 없다. - 내부 단편화가 없다.단점외부 단편화가 발생한다.외부 단편화메모리 할당 해제 된 자리를 더하면 새로운 프로그램을 올릴 수 있는데 따로 따로 자리가 있어서 다른 프로그램을 올릴 수 없다.해결외부 단편화가 발생한 공간을 합쳐주는 조각모음을 하면된다.고정 분할 방식프로세스의 크기와는 상관없이 메모리를 정해진 크기로 나누는 방식프로세스 크기와 상관없이 메모리를 할당한 프로세스가 메모리에 분산되어 할당되어서 '비연속 메모리 할당'이라고 한다.장점구현이 간단하고 오버헤드가 적다.단점메모리에 낭비되는 공간이 있다. - 내부 단편화가 발생한다.가상 메모리에서 가변 분할 방식은 '세그멘테이션', 고정 분할 방식은 '페이징'이라고 부른다.버디 시스템가변 분할 방식과 고정 분할 방식의 단점을 최소화한 시스템2의 승수로 메모리를 분할해 메모리를 할당하는 방식프로세스가 사용을 마치고 메모리에서 나가도 근접한 메모리 공간을 합치기 쉽다.장점가변 분할 방식처럼 프로세스 크기에 따라 할당되는 메모리 크기가 달라진다.외부 단편화를 방지하기 위해 메모리 공간을 확보하는 것이 간단하다.고정 분할 방식처럼 내부 단편화가 발생하기는 하지만 많은 공간의 낭비가 발생하지 않는다. [자료구조와 알고리즘][java로 실습한 것은 깃허브에 올려두었다.]재귀사전적 정의 : 어떠한 것을 정의할 때 자기 자신을 참조하는 것재귀 함수재귀적으로 정의된 함수기저 조건(탈출 조건)이 반드시 있어야 한다.if() 로 함수를 종료하지 않으면 콜스택에 메모리 공간이 가득 차서 자동으로 종료된다.=> java.lang.StackOverflowError 에러 발생콜스택함수가 호출되면서 올라가는 메모리 영역으로 스택이라고 부른다.스택의 특성처럼 먼저 들어온 데이터가 나중에 나간다. (FILO : First In Last Out)함수를 호출하면 해당 함수는 콜스택에 올라가게 되고 함수가 종료되면 콜스택에서 제거된다.public class Recursion { public static void main(String[] args) { myFunction(1); } public static void myFunction(int number) { if (number > 10) return; System.out.println(number); myFunction(number + 1); } }재귀 함수 - 팩토리얼n이 주어질 때 1부터 n까지 모든 수의 곱을 말한다.예시) 5! => 5*4*3*2*1 => 120재귀 함수 쉽게 작성하는 방법재귀 함수 내에서 자기 자신을 호출할 때 이 함수가 벌써 구현이 되어 있다고 가정하자.5! 구현하기5 * 4!(4*3*2*1) => 하위 4 * 3!(3*2*1) => 하위 3 * 2!(2*1) => 하위 2 * 1!(1)factorial() 함수가 이미 구현되었다고 가정하면 5 * factorial(4)를 호출하면 된다.이를 일반화 하면 number * factorial(number-1)그리고 중요한 기저 조건을 만들어야 한다.1이 되면 팩토리얼은 종료된다.0! 은 1이기 때문에 같이 기저 조건에 넣겠다.public class Factorial { public static void main(String[] args) { System.out.println(factorial(5)); // 120 } public static int factorial(int number) { if (number == 1 || number == 0) { return 1; } else { return number * factorial(number - 1); } } }재귀적으로 생각하기패턴1단순히 반복 실행콜스택 공간을 많이 차치해 성능은 for문보다 좋지 않다.패턴2하위 문제의 결과를 기반으로 현재 문제를 계산하는 것재귀를 이용해 하위 문제의 결과를 기반으로 현재 문제를 계산하는 방식 - 하향식 계산재귀를 이용해서 상향식 계산도 가능하다.재귀 함수의 진정한 위력은 하향식 계산에서 발휘된다.  재귀 - 하노이탑 (정리 한번하기) 재귀 함수의 대표적인 예시하향식 계산 방식을 보여줄 수 있는 좋은 예시이다.세 개의 기둥과 서로 다른 크기의 원반들이 있다.가장 큰 원반이 아래에 있고 위로 갈수록 작은 원반으로 이루어져 있다.현재 기둥에서 다른 기둥으로 옮겨야 한다.규칙한 번에 하나의 원반을 움직일 수 있다.가장 위에 있는 원반만 옮길 수 있다.아래에 작은 원반이 올 수 없다.하위 문제 찾기 (재귀함수를 이용해서 하향식으로 접근)[깃허브 코드]이미 해결을 한 상황을 예상해보기 (하위 문제)첫 번째 목표 : 원반3을 기둥A에서 기둥C로 옮긴다. 하위 문제1 : 원반3 위에 있는 원반1,2를 기둥A에서 기둥B로 옮겨야 한다.hanoi(count - 1, from, temp, to);하위 문제2 : (하위 문제1) 이 해결되었다면 출력System.out.printf("원반 %d을/를 %s에서 %s로 이동%n", count, from, to);=> 원반 3을 A에서 C로 이동하위 문제3 : (하위 문제2) 가 해결되었다면 => 두 번째 목표 : 원반1,2를 기둥 B에서 기둥C로 옮겨야 한다.hanoi(count - 1, temp, to, from);기저 조건(탈출 조건)원반이 없는 경우, 옮길 원반이 없을 때if (count == 0) return; 정렬 - 버블정렬가장 쉽게 생각할 수 있는 정렬 중 하나이다.구현하기 쉽지만, 성능은 좋지 않다.앞에 있는 숫자와 옆에 숫자를 비교해서 자리를 바꾸는 알고리즘이다.방식앞에서부터 요소들을 하나씩 비교한다.가장 큰 숫자는 자기 위치를 찾아 가장 끝에 정렬된다.이미 정렬된 마지막 원소를 제외하고 앞에서부터 다시 요소를 검사한다.남은 원소가 하나이면 더이상 정렬을 할 필요가 없다.성능반복 횟수 for문 * 원소비교 for문 => O(n제곱)성능이 좋지 않다.장점가장 쉽게 생각할 수 있는 정렬 방법으로 이해와 구현이 간단하다.단점성능이 O(n제곱)으로 좋지 않다. 정렬 - 선택정렬버블정렬과 마찬가지로 구현이 쉬운 알고리즘이해와 구현이 간단하지만 성능이 아쉽다.방식정렬된 영역과 정렬되지 않은 영역을 나눠서 정렬되지 않은 영역을 비교한다.정렬되지 않은 첫 번째 원소를 시작으로 마지막 원소까지 비교 후 가장 작은 값을 첫 번째 원소로 가져온다.첫 번째 원소는 정렬된 영역으로 제외하고 다시 정렬되지 않은 영역을 비교한다.정렬되지 않은 영역에 요소가 한 개 남으면 정렬할 필요없이 끝이난다.성능반복 횟수 for문 * 원소비교 for문 => O(n제곱)성능이 좋지 않다.장점이해하기 쉽고 구현이 간단하다.단점성능이 O(n제곱)으로 좋지 않다.   ※ '강의 내용 정리' 출처[인프런 / 그림으로 쉽게 배우는 운영체제 (감자) / 섹션 4~7][인프런 / 그림으로 쉽게 배우는 자료구조와 알고리즘 (감자) / 섹션 3 (유닛 1~5)]

인프런 워밍업 클럽 스터디 3기 - 백엔드 클린 코드, 테스트 코드 2주차 발자국

섹션 6 코드 다듬기해당 섹션에서 가장 와닿았고, 머리가 아팠던 것은 "과연 좋은 주석이란 무엇일까?" 에 대한 것이었다.결론적으로, 좋은 주석은 코드에 비즈니스 요구 사항과 의도를 모두 잘 녹여냈다는 가정 하에 더 전달해야만 하는 정보가 남았을 때 남기는 것이다! 섹션 7 리팩토링 미션이제까지의 학습을 바탕으로, 리팩토링 진행https://github.com/Chaeruin/readable-code/pull/1단계적으로, 공통적인 것부터 추상화 및 리팩토링을 진행하였다.io 패키지 인터페이스 추상화model 일급컬렉션 분리Machine 기능 추상화버그 수정!이후 중간 점검 세션을 통해 다른 분들 코드와 비교하고, 말씀해주신대로 다음날 리팩토링 + 강의 수강을 통해 간과하고 있었던 Provider의 개념, 리팩토링을 놓친 부분 (FileHandler 등...), VO에 대한 부족한 이해가 있음을 알고 이에 대해 더 학습하는 시간이 필요할 것 같다는 생각... 더 미루지 말고 다음 주에는 꼭 !! 해보아야겠다. 참조 강의 :: https://www.inflearn.com/course/readable-code-%EC%9D%BD%EA%B8%B0%EC%A2%8B%EC%9D%80%EC%BD%94%EB%93%9C-%EC%9E%91%EC%84%B1%EC%82%AC%EA%B3%A0%EB%B2%95섹션 2 테스트는 왜 필요할까?테스트의 중요성 -> 테스트 코드의 부재는 결국 유지보수의 어려움을 낳는다테스트 코드는 빠른 피드백과 코드의 자동화, 이는 곧 전체 프로젝트의 높은 안정성을 낳는다 섹션 3 단위테스트단위 테스트란? 작은 단위(클래스나 메소드와 같은-)의 코드를 독립적으로 검증하는 테스트이다.JUnit5/AssertJ를 기반으로 해피 케이스 / 예외 케이스 / 경계값 모두 테스트 해야함 섹션 4 TDDTDD는 왜 하는걸까? 처음엔 시간이 오래 걸리는 것처럼 보이지만, 디버깅 시간 단축, 빠른 문제 식별, 리팩토링 안정성 보장 덕분에 장기적으로 개발 속도가 빨라진다고,Flow (3단계 순환)Red : 빨간 불을 보는 테스트를 먼저 작성 (내부 메서드 구현X 혹은 더미값)Green : 단순하고 빠르게 테스트를 통과할 수 있는 로직 구현 Refactor : 해당 Green을 기준으로 같은 값을 낼 수 있는 로직으로 리팩토링장점복잡도가 낮고, 테스트 가능한 코드를 구현할 수 있게 한다.쉽게 발견하기 어려운 엣지 케이스를 놓치지 않게 해준다.과감한 리팩토링이 가능해진다.  섹션 5 테스트는 [ ] 다.JUnit5부터 @Display 를 통해 명사의 나열보다 문장으로테스트 행위에 대한 결과까지 기술도메인 용어를 사용하여 한층 추상화된 내용을 담아테스트의 현상을 중점으로 기술하지 말 것  BDD 시나리오 기반 테스트 케이스에 집중한 테스트Given // When // Then참조 강의 :: https://www.inflearn.com/course/practical-testing-%EC%8B%A4%EC%9A%A9%EC%A0%81%EC%9D%B8-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B0%80%EC%9D%B4%EB%93%9C

[인프런 워밍업 스터디 클럽 3기 풀스택] 2주차 발자국

강의수강Supabase storage파일과 미디어를 저장하고 관리할 수 있는 서비스bucket파일을 저장하는 컨테이너클라이언트 또는 서버에서 파일을 업로드하고 가져올 수 있음drag and drop을 도와주는 라이브러리 react-dropzoneHTML5 호환 drag 와 drop 영역을 생성하는 react hookgetRootProps : drag and drop 영역을 감싸는 요소의 props를 반환, 이 props를 추가하면 해당 요소가 drop 존 역할을 함getInputProps : 파일 입력 요소에 적용할 props를 반환, 브라우저에서 파일 선택 버튼을 크릭하여 업로드하는 기능을 제공isDragActive : 사용자가 파일을 drag해서 drop존 위에 올려놓았을 때 true 가 됨onDrop : 파일을 drop했을 때 동작할 함수  미션파일 목록에서 각 파일의 "마지막 수정 시간"을 표시 supabase-storage에서 반환하는 파일의 형식 created_at : "2025-03-05T10:15:27.972Z", id: "ca54ea55-4dce-4fc8-a64c-7066b757d663", last_accessed_at: "2025-03-05T10:15:27.972Z", metadata: {eTag: '"72c7f0e0341f03be49876c063d3ff79f"', size: 340, mimetype: 'image/png', cacheControl: 'max-age=3600', lastModified: '2025-03-05T10:15:28.000Z', …}, name: "25-phd.png", updated_at: "2025-03-05T10:15:27.972Z"update_at 값을 이용해 마지막 수정시간을 렌더링한다. 시간을 좀 더 보기 쉽게 변경하기 위해 지난 미션에서 사용했던 함수 formatDate 로 렌더링

jurjur

CS 2주차 발자국

운영체제프로세스간 통신프로세스는 독립적으로 실행되지만, 다른 프로세스와 데이터를 주고 받는 경우가 존재.통신은 동일한 컴퓨터 또는 네트워크에 연결된 다른 프로세스와 통신이 가능함.한 컴퓨터 내에서 프로세스간 통신하는 방법파일 & 파이프하나의 파일을 이용해 읽고 쓰는 방법운영체제가 생성한 파이프를 이요해 데이터를 읽고 쓰는 방법쓰레드한 프로세스 내에서 쓰레드간 통신을 하는 방법.쓰레드는 코드, 데이터, 힙 영역을 공유하므로 데이터 또는 힙 영역을 통해 통신네트워크소켓 통신다른 컴퓨터에 있는 함수를 호출하는 RPC(원격 프로시저 호출)를 이용해 통신하는 방법공유 자원과 임계 구역통신을 할때 공동으로 이용하는 함수나 파일이 있는데 이를 공유 자원이라 함.공유 자원은 여러 프로세스가 공유하기 때문에 각 프로세스가 접근하는 순서에 따라 결과가 달라짐.컨텍스트 스위칭으로 시분할 처리 되기 때문에 어떤 프로세스가 먼저실행되고 나중에 실행되는지 예측이 어려움.→ 연산 결과를 예측하기 힘들고 동기화 문제가 발생임계 구역여러 프로세스가 동시에 사용하면 안되는 영역을 임계 구역(Critical Section)이라 함.공유자원을 서로 사용하기 위해 경쟁하는 것은 경쟁 조건(Race Condtion)이라 함.임계 구역을 해결 하기 위해서는 상호 배제 매커니즘이 필요.상호 배제의 요구사항임계구역엔 동시에 하나의 프로세스만 접근한다.여러 요청에도 하나의 프로세스의 접근만 허용한다.임계 구역에 들어간 프로세스는 빠르게 나와야 한다.세마포어정의운영체제는 자원을 사용할 수 있는 열쇠(세마포어)를 설정해서 공유 자원 요청이 온 프로세스에게 열쇠를 전달.열쇠를 전달받은 프로세스는 공유 자원을 사용다른 프로세스가 공유자원을 요청이전의 프로세스가 열쇠를 반납할때까지 대기큐에서 대기.공유 자원을 다 사용하고 난 후 운영체제에 열쇠를 반납.운영체제는 대기 큐에서 기다리고 있는 프로세스에세 열쇠를 전달 하여 공유 자원 사용 허락.단점세마포어 호출이 꼬일 경우 원하는 대로 동작이 되지 않을 수 있다.모니터세마포어의 단점을 해결한 상호배제 메커니즘.운영체제에서 처리하는 것이 아닌 프로그래밍 언어 차원에서 지원하는 방법자바 예시public class Health { private int health = 100; synchronized void increase(int amout) { health += amout; } synchronized void decrease(int amout) { health -= amout; } } synchronized 키워드가 붙어 있는 함수는 동시에 여러 프로세스에서 실행 시킬 수 없음.상호배제가 완벽히 이루어짐.교착상태(데드락)여러 프로세스가 서로 다른 프로세스의 작업을 끝나길 기다리다가 아무도 작업을 진행하지 못하는 상태.발생 이유는 공유자원.교착상태 필요조건아래 조건들이 모두 만족하면 교착상태가 발생.하나라도 만족하지 않으면 교착 상태가 발생하지 않음.상호배제어떤 프로세스가 한 리소스를 점유 했다면 그 리소스는 다른 프로세스에게 공유가 되면 안됨.비선점리소스를 갖고 있는 프로세스 한테서 다른 프로세스가 리소스를 빼앗을 수 없다.점유와 대기리소스A를 갖고 있는 프로세스가 리소스B를 원하는 상태원형 대기점유와 대기를 하는 프로세스들의 관계가 원형을 이루고 있는 상태.교착 상태 해결교착 상태 회피(Deadlock avoidance)프로세스에게 자원을 할당할때 교착 상태가 발생하는 상황을 파악해서 교착상태가 발생하지 않는 수준의 자원을 할당.전체 자원의 수와 할당된 자원이 수로 안정상태와 불안정 상태로 나눔.운영체제는 최대한 안정상태를 유지하려고 자원을 할당.불안정 상태에 있다하더라고 무조건 교착 상태에 빠지는게 아니라 교착 상태에 빠질 가능성이 높아짐.은행원 알고리즘(Banker’s Algorithm)은행이 대출해주는 방식의 알고리즘돈을 빌려줄때 은행의 여윳돈과 사업가들에게 빌려준 돈들을 보고 대출 가능한 상황인지 보고 빌려주는 알고리즘.운영체제는 프로세스에게 자원을 할당하기 전에 자신이 가지고 있는 자원의 수를 파악→ 시스테의 총 자원프로세스들은 각자 자기가 필요한 자원의 최대 수를 운영체제에 알려줌→ 최대 요구 자원 ⇒ 은행원 알고리즘은 교착 상태를 피하는 좋은 알고리즘이지만 비용이 비싸고 비효율적.교착 상태의 발생은 허용하지만, 교착 상태가 발생시 해결 방법을 연구.교착 상태 검출 방법 고민.가벼운 교착 상태 검출프로세스가 일정시간 동안 작업을 진행하지 않는다면 교착 상태에 발생했다고 감지하고 교착 상태를 해결.해결 방법은 일정 시간마다 체크포인트를 만들어 작업을 저장하고 교착 상태가 발생하면 마지막으로 저장한 체크포인트로 롤백 하는 방식.무거운 교착 상태 검출자원 할당 그래프를 사용하여 현재 운영체제에서 프로세스가 어떤 자원을 사용하는지 지켜보고 교착 상태가 발생하면 해결.자원 할당 그래프를 통해 순환 구조가 발생하면 교착 상태로 판단.교착 상태를 검출하면 교착 상태를 일으킨 프로세스를 강제 종료하고, 다시 실행할때 체크포엔트로 롤백을 진행.운영체제가 지속적으로 자원할당 그래프를 유지하고 검사해야 하기 때문에 오버헤드가 발생.가벼운 교착 상태 검출에서 발생하는 억울하게 종료되는 프로세스는 발생되지 않음.메모리 종류레지스터 - 캐시 - 메인 메모리(RAM) - 보조 저장 장치(HDD, SSD)좌 → 우 갈수록 속도가 느려지고 용량이 커지며 가격이 저렴해진다.레지스터가장 빠른 기억 장소로 CPU내에서 존재컴퓨터 전원이 꺼지면 데이터가 사라지기 때문에 휘발성 메모리라고 부름.32bit, 64bit는 레지스터의 크기.CPU는 계산을 할 때 메인 메모리에 있는 값을 레지스터로 갖고와서 계산하고 계산 결과를 메인 메모리에 다시 저장.캐시레지스터와 메인 메모리 사이에 존재하는 메모리.레지스터와 메인 메모리 데이터 속도의 차이 때문에 필요한 데이터를 미리 갖고와서 저장하는 공간.속도에 따라 L1, L2, … 캐시가 존재.메인 메모리실제 운영체제와 다른 프로세스가 올라가는 공간전원이 공급되지 않으면 데이터가 지워지기 때문에 휘발성 메모리.하드디스크나 SSD 보다 속도는 빠르지만 가격이 비싸기 때문에 실행중인 프로그램만 올라감.보조 저장 장치전원이 공급되지 않아도 데이터가 지워지지 않는 비 휘발성 메모리.메모리와 주소메인 메모리에 대한 설명오늘 날의 컴퓨터는 폰 노이만 구조.폰 노이만 컴퓨터는 모든 프로그램을 메모리에 올려 실행.유니 프로그래밍 환경에서는 하나의 프로세스만 메모리에 올라가 메모리 관리가 쉬었으나, 멀티 프로그래밍 환경에서는 여러개의 프로세스가 올라가 실행되어 복잡하고 어려워짐.운영체제는 메모리를 관리하기 위해 1바이트(8bit) 단위로 나누고 숫자를 할당.→ 주소32bit, 64bit CPU32bit CPU는 레지스터 크기가 32bit, CPU가 처리하는 ALU(산술 논리 연산 장치)도 32bit, 데이터가 이동하는 버스도 32bit. 또한 CPU가 다룰 수 있는 메모리도 2^32으로 4GB.64bit CPU는 레지스터 크기가 64bit, CPU가 처리하는 ALU(산술 논리 연산 장치)도 64bit, 데이터가 이동하는 버스도 64bit. 또한 CPU가 다룰 수 있는 메모리도 2^64으로 거의 무한대에 가까움⇒ 64bit가 32bit보다 한번에 처리할 수 있는 양이 많아 속도가 빠름.물리 주소와 논리 주소메모리를 컴퓨터에 연결하면 0x0번지부터 시작하는 주소 공간이 존재→ 물리 주소 공간.사용자 관점에서 바라보는 주소 공간→ 논리 주소 공간사용자는 물리 주소를 몰라도 논리 주소를 알면 물리 주소에 접근할 수 있음.메모리에는 운영체제와 다 수의 프로세스가 올라옴.운영체제를 위한 공간은 따로 만들어 사용자 프로세스가 운영체제에 침범 할 수 없도록 운영체제 공간과 사용자 프로세스 공간을 나누는 경계 레지스터를 만듦.경계 레지스터는 CPU내에서 존재하는 레지스터로 메모리 관리자는 사용자 프로세스가 경계 레지스터의 값을 벗어 났는지 확인하고, 침범했다면 사용자 프로세스를 종료 시킴.절대 주소와 상대 주소상대 주소개발자가 프로그램 개발 시 주소는 신경 쓰지 않고 개발.이는 컴파일러가 메모리 0번지에서 실행한다고 가정.→ 상대 주소(논리 주소 공간)절대 주소실제 프로그램이 올라간 주소→ 절대 주소(물리 주소 공간)사용자가 0x100번지 데이터를 요청하면, CPU도 0x100번지(상대 주소, 논리 주소)의 데이터를 요청. 그리고 메모리 관리자는 CPU가 요청한 0x100번지의 주소와 재배치 레지스터에 있는 프로그램이 올라간 주소(e.g. 0x4000)의 값을 더해 0x4100번지(절대 주소, 물리 주소)에 접근해서 데이터를 가져옴.재배치 레지스터에는 프로그램이 시작된 주소가 저장 되어 있음.메모리 관리자 덕분에 사용자는 모든 메모리는 0x0번지에 시작한다고 가정할 수 있고, 시작 영역이 바뀌더라도 재배치 레지스터만 변경해 하면 되므로 굉장히 유연.메모리 할당 방식메모리 오버레이(Memory overlay)메모리 보다 더 큰 프로그램을 실행 시키는 방법.큰 프로그램을 잘라서 당장 실행 시켜야 할 부분만 메모리에 올리고 나머지 부분은 하드 디스크에 저장(하드디스크의 스왑 영역)하는 방식.스왑스왑 영역에 있는 데이터 일부를 메모리에 가져오고, 메모리에 있는 데이터를 스왑 영역으로 옮기는 것사용자는 실행 중인 프로그램만큼 메모리를 사용한다고 느끼지만 실제는 그것보다 적으므로 메모리가 큰 컴퓨터보다는 느리게 동작.유니 프로그래밍에서 사용하는 방식.가변 분할 방식(세그멘테이션)프로세스의 크기에 따라 메모리를 나누는 방식.한 프로세스가 메모리에 연속된 공간에 할당되기 때문에 연속 메모리 할당 이라고 함. 고정 분할 방식(페이징)프로세스의 크기와 상관없이 메모리를 할당.메모리 분할 크기에 따라 프로세스들을 해당 크기에 맞게 나눠서 할당하는 방식.한 프로세스가 여러개로 쪼개져서 메모리에 할당 되기 때문에 비 연속 메모리 할당 이라고 함. 가변 분할과 고정 분할 방식의 장단점가변 분할 방식장점메모리에 연속된 공간에 할당 되기 때문에 낭비되는 공간인 내부 단편화가 없다.단점외부 단편화 발생중간에 다른 프로세스들이 종료되고 새로운 프로세스가 실행되는 경우 새로 시작하는 프로세스가 기존 종료된 프로세스들의 메모리 합보다 같거나 작지만, 연속된 공간에 할당 할 수 없는 상황. 해결방법조각모음.조각모음을 하려면 현재 메모리에서 실행되고 있는 프로세스들의 작업을 일시 중지해야하고 메모리 공간을 이동하는 작업을 해야 하기 때문에 오버헤드가 발생.고정 분할 방식장점구현이 간단하고 오버헤드가 적음.단점작은 프로세스도 큰 공간에 할당 되면 내부 단편화 발생할당된 공가보다 작은 크기의 프로세스를 할당할 경우 낭비 공간이 발생.해결방법은 없어서 분할되는 크기를 조절해서 내부 단편화를 최소화.버디 시스템가변분할 방식과 고정 분할 방식을 혼합해 단점을 최소화 한 방법2의 승수로 메모리를 분할해 메모리를 할당하는 방식.예시메모리 크기가 2^11승인 2024b가 존재.이때 크기가 500b인 프로세스가 메모리 할당을 원함.2의 승수로 500b 작은 값을 만날때까지 메모리 영역을 나눔1024 / 1024 → 1024 / 512 / 512 → 1024 / 512 / 256 / 256즉, 1024b / 512b / 256b / 256b 4가지 영역이 생성256b에는 500b의 프로세스를 할당할 수 없으니 512b 영역에 프로세스를 할당.12b가 낭비되는 내부 단편화 발생.내부 단편활가 발생되긴 하지만 많은 공간이 발생하지는 않음.해당 프로세스가 종료되어 메모리 공간 할당이 해제 되어도 근접한 메모리 공간을 합치기 쉬움2의 승수로 동일할게 나누어서 반대로 조립만 하면 큰 공간이 만들어져서 조각 모음보다 간단함1024 / 512 / 512 → 1024 / 1024 → 2024자료구조와 알고리즘재귀재귀어떠한 것을 정의할때 자기 자신을 참조하는 것재귀 함수예시const myFunction = (number) => { console.log(number); myFunction(number + 1); } myFunction(0); 이 함수는 실행하면 오류가 발생한다.node:internal/util/inspect:765 function formatValue(ctx, value, recurseTimes, typedArray) { ^ RangeError: Maximum call stack size exceeded 탈출 조건이 없어 계속 실행하다가 메모리가 부족해서 오류가 발생.기저 조건(탈출 조건)있는 재귀함수예시const myFunction = (number) => { if (number > 10) return; console.log(number); myFunction(number + 1); } myFunction(0); 콜 스택함수가 호출되면서 올라가는 메모리 영역으로 스택이라고도 부름.콜스택은 스택의 특성처럼 FILO(First In Last Out) 특성을 갖고 있음.함수를 호출하면 콜스택에 올라가고, 함수가 종료되면 콜스택에서 제거됨.재귀적으로 생각하기패턴1 - 단순한 반복 실행단순한 반복 실행을 재귀로 구현하면 반복문으로 구현했을 때보다 크게 이점은 없다.콜스택의 공간을 많이 차지해 반복문보다 좋지 않음.패턴2 - 하위 문제의 결과를 기반으로 현재 문제를 계산팩토리얼 함수를 예시로 설명예를 들어 5!의 계산을 구할때 5 * 4! 계산 방식으로 구하는 방법.하위문제: 4!현재 문제: 5!팩토리얼을 반복문으로도 구현이 가능하지만, 현재 문제를 해결하는데 하위 문제가 쓰이는 것이 중요한 포인트반복문은 상향식 계산.재귀 함수로 구현하면 하향식 계산.재귀를 사용한다고 무조건 하향식 계산은 아님.상향식 계산도 가능.재귀 함수의 위력은 하향식 방향 계산에서 발휘.⇒ 재귀를 사용하는 이유예시배열의 모든 원소의 합.const sumArray = (arr) => { if (arr.length === 1) return arr[0]; return sumArray(arr.slice(0, -1)) + arr[arr.length - 1]; } let arr = [1, 2, 3, 4, 5]; const res = sumArray(arr); console.log(res); 문자열의 길이 구하기const strLength = (arr) => { if (!arr[0]) return 0; return strLength(arr.slice(0, -1)) + 1 } const str = 'abcde'; const res = strLength(str); console.log(res); 지수 함수const power = (x, n) => { if (n === 0) return 1; return power(x, n - 1) * x; } console.log(power(2, 5)); // 2^5 계산 하노이 탑하향식 계산 방식의 좋은 예정렬배열에 무작위로 섞인 숫자를 정렬하는 방법.버블 정렬(Bubble Sort)가장 쉽게 생각할 수 있는 정렬중 하나구현하는 방법은 쉬우나 성능은 좋진 않다.예시 코드코드const bubbleSort = (arr) => { for (let i = 0; i < arr.length - 1; i++) { for (let j = 0; j < (arr.length - i - 1); j++) { if (arr[j] >= arr[j + 1]) { let tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } } } } const arr = [4, 2, 3, 1]; console.log('> > > 정렬 전 < < <'); console.log(arr); bubbleSort(arr); console.log('> > > 정렬 후 < < <'); console.log(arr); 결과> > > 정렬 전 < < < [ 4, 2, 3, 1 ] > > > 정렬 후 < < < [ 1, 2, 3, 4 ] 버블 정렬의 성능버블 정렬의 성능을 구하면 등차수열의 합과 같은 경우의 수가 나타남$\frac{n^2 - n}{2}$시간 복잡도는 $O(n^2)$$n$이 증가할때마다 계산량은 엄청나게 증가하게 됨.성능이 중요한 시스템을 만든다면 버블 정렬 방식은 사용하기 힘듦.장단점이해와 구현이 간단함.성능이 좋지 않음.선택 정렬(Selection Sort)버블 정렬처럼 이해와 구현이 간단.아쉬운 성능배열의 정렬되지 않은 영역의 첫 번째 원소를 시작으로 마지막 원소까지 비교 후 가장 작은 값을 첫 번째 원소로 가져옴.코드 예시코드const selectionSort = (arr) => { for (let i = 0; i < arr.length - 1; i++) { let minValIdx = i; for (let j = i + 1; j < arr.length; j++) { if (arr[j] < arr[minValIdx]) { minValIdx = j; } } const tmp = arr[i]; arr[i] = arr[minValIdx]; arr[minValIdx] = tmp; } } const arr = [4, 2, 1, 3]; console.log('> > > 정렬 전 < < <') console.log(arr); selectionSort(arr); console.log('> > > 정렬 후 < < <') console.log(arr); 결과> > > 정렬 전 < < < [ 4, 2, 1, 3 ] > > > 정렬 후 < < < [ 1, 2, 3, 4 ] 선택 정렬의 성능버블 정렬과 마찬가지로 $\frac{n^2 - n}{2}$ 나타남.성능도 마찬가지로 $O(n^2)$ 시간 복잡도를 갖고 있음.장 단점이해와 구현이 간단함.성능이 좋지 않음. 

김예원

[인프런 워밍업 클럽 스터디 3기] PM/PO 2주 차 발자국

2주 차 학습 내용섹션 3. 고객에 대한 전문성 쌓기고객 전문가가 되기 위한 유일한 방법, 고객을 직접 만나기중간에 누군가를 끼지 않고 직접 고객을 만나서 이야기를 나누고 관찰해야 한다.고객리서치 설계 접근법목적 설정이 중요하다. 더 나은 의사결정을 하기 위한 목적.PM이 고객을 파악하는 가장 강력한 도구 1. 심층 인터뷰 하는 법고객의 '문제'를 파악하기에 좋은 리서치 방법의사결정의 근거로서 활용PM이 고객을 파악하는 가장 강력한 도구 2. 사용성테스트사용성 테스트는 언제하면 좋은지, 진행 방법 섹션 4. 데이터에 대한 전문성 쌓기PM은 데이터를 활용해서 어떤 일들을 하나데이터를 비즈니스에 활용PM으로서 데이터 역량을 어떻게 쌓을 수 있나의도를 갖고 데이터를 정의2주 차 학습 회고스스로 칭찬하고 싶은 점출퇴근길에 강의를 열심히 수강한 점아쉬웠던 점 / 보완하고 싶은 점 / 다음 주에는 어떻게 학습할지아쉬웠던 점과 보완하고 싶은 점은 없고, 다음 주에도 열심히 💪🏻💪🏻💪🏻2주 차 미션 해결 과정어떤 관점에서 접근했는지 / 문제를 해결하는 과정은 무엇이었는지 / 왜 그런 식으로 해결했는지 / 미션 해결에 대한 회고2주 차 미션은 “고객 조사 설계하기”였습니다. 제가 맡은 프로덕트의 고객 조사 계획을 세워보는 것이였는데요. 조사 주제를 설정하고, 어떤 사람들을 어떤 방법으로 조사할지, 어떤 질문을 할지 설계해 보고, 인터뷰 질문지까지 만드는 과정이었습니다. 조사 주제 설정부터 조사 대상 선정, 조사 방법 선택, 그리고 질문지 작성까지 순차적으로 진행했습니다.제가 진행하는 프로덕트처럼 낯선 분야일수록, 단순 설문이나 지표 분석만으로는 사용자가 느끼는 심리적 장벽이나 잠재된 기대를 충분히 드러낼 수 없다고 판단했기 때문에, 심층 인터뷰 방식을 주된 리서치 수단으로 삼았습니다.‘사업 질문 → 리서치 질문 → 인터뷰 질문’으로 이어지는 가이드를 바탕으로 접근하니, 막막함 없이 논리를 체계적으로 잡아갈 수 있었고, 인터뷰 결과 역시 비즈니스 의사결정과 직접적으로 연결되는 형태로 활용할 수 있다는 점이 좋았습니다.또한, 모집 방법과 사전 질문을 통한 필터링 기법까지 배움으로써 원하는 타깃을 구체적으로 선정할 수 있었고, 그 덕분에 전체 리서치 방향을 제가 의도한 대로 이끌어갈 수 있다는 점이 좋았습니다.

기획 · PM· PO김민우인프런워밍업클럽시작하는PM/POPMPO

jurjur

CS 2주차 미션

운영체제 FIFO 스케줄링의 장단점이 뭔가요? 장점단순하고 직관적단점한 프로세스가 완전히 끝나야 다음 프로세스가 실행됨.때문에 실행시간이 짧고 늦게 도착한 프로세스가 실행시간이 길고 빨리 도착한 프로세스의 작업을 기다려야함. SJF를 사용하기 여러운 이유가 뭔가요? 어떤 프로세스가 얼마나 실행 될지 예측이 힘듦.BurstTime이 긴 프로세스는 아주 오랫동안 실행 되지 않을 수 있음.  RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요?컥텍스트 스위칭이 너무 자주 발생함.프로세스의 처리 양보다 컨텍스트 스위칭을 처리하는 양이커져 오버헤드가 너무 커지는 상황이 발생. 운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요?CPU를 실행하는 프로세스가 스스로 CPU를 반납하면 CPU 사용량이 적음I/O Bound Process 가능성이 높음.CPU를 사용하는 프로세스가 타임 슬라이스 크기를 오버해서 강제로 Cpu를 뺏기는 상황CPU Bound Process 가능성이 높음.  공유자원이란무엇인가요?통신을 할 때 공동으로 이루는 함수나 파일을 공유자원이라고 함. 교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야할까요? 상호 배제어떤 프로세스가 한 리로스를 점유 했다면 그 리소스는 다른 프로세스에게 공유가 되면 안됨.비선점리소스를 갖고 있는 프로세스 한테서 다른 프로세스가 리소스를 빼앗을 순 없음.점유와 대기리소스A를 갖고 있는 프로세스가 리소스 B를 원하는 상태원형 대기점유와 대기를 하는 프로세스들의 관계가 원형을 이루고 있는 상태. 자료구조와 알고리즘 재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요?콜 스택에 계속해서 함수가 생성되어 실행되어 결국 메모르가 부족한 오류가 발생하게 됨. 0부터 입력 n까지 홀수의 합을 더하는 재귀 함수를 만들어보세요.function sumOdd(n){ // 재귀 로직 if (n == 0) return 0; return (n%2 != 0 ? n : 0) + sumOdd(n - 1) } console.log(sumOdd(10)) // 25 다음 코드는 매개변수로 주어진 파일 경로(.는 현재 디렉토리)에 있는 하위 모든 파일과 디렉토리를 출력하는 코드입니다. 다음 코드를 재귀 함수를 이용하는 코드로 변경해보세요.import fs from "fs"; import path from "path"; function traverseDirectory(directory) { const files = fs.readdirSync(directory); for (const file of files) { const filePath = path.join(directory, file); const fileStatus = fs.statSync(filePath); if (fileStatus.isDirectory()) { if (filePath.includes("git")) continue; // 특정 디렉토리 제외 console.log("디렉토리:", filePath); traverseDirectory(filePath); // 재귀 호출 } else { console.log("파일:", filePath); } } } traverseDirectory("."); // 현재 경로의 모든 하위 경로의 파일, 디렉토리 출력  

시스템 · 운영체제운영체제자료구조

이수진

[인프런 워밍업 클럽 Full-Stack 3기] 2주차 발자국 - Dropbox 구현

이번주에 배운 내용은 Storage를 통해 Image를 CRUD 하는 기능이다. 이 강의를 들은 다음 추후 Next.js + Supabase 스택으로 블로그를 만들 생각이었어서 그 때 Supabase Storage를 사용할거라 좀 더 유심히 들었다.이번 Dropbox 프로젝트에서는 지난 TodoList 프로젝트를 했을 때 개인적으로 Meterial UI Tailwind를 사용할 때 마음에 들지 않았던 부분들이 있어서 한번 써보고 싶기도 했던 Shadcn/ui를 통해 css를 구현해봤다.수강 내용Section 4. Dropbox 클론코딩이번 섹션에서 배운 내용들은 다음과 같다.Storage 설정 (Bucket 생성 및 Policy 설정)파일 업로드, 검색, 수정, 삭제 기능드래그 앤 드롭을 통한 파일 업로드 기능 추가주로 이제 스토리지에 어떻게 접근해 파일들을 제어할 것인지가 핵심 내용이었다.export async function uploadFile(formData: FormData) { const supabase = await createServerSupabaseClient(); const file = formData.get("file") as File; const { data, error } = await supabase.storage .from(process.env.NEXT_PUBLIC_STORAGE_BUCKET!) .upload(file.name, file, { upsert: true }); handleError(error); return data; }예를들어 다음과 같은 코드는 파일을 업로드할 때 사용하는 코드이다. upsert를 통해 insert + update 기능으로 같은 이름이 있다면 자동으로 수정해주는 기능이 있다는 것도 처음 알게 된 사실이다.프로젝트에서 한가지 아쉬운 점이 있었다면 파일을 검색할 때 예를들어 A 를 검색했다면 A 로 시작하는 파일 이름만 검색된다는 점이었다. 따라서 이 부분을 개인적으로 한번 수정해보기도 했다.export async function searchFiles(keyword: string = "") { const supabase = await createServerSupabaseClient(); const { data, error } = await supabase.storage .from(process.env.NEXT_PUBLIC_STORAGE_BUCKET!) .list(); // 전체 파일 목록 가져오기 handleError(error); return data ? data.filter((file) => file.name.includes(keyword)) : []; }다음과 같이 keyword를 받아오면 supabase storage의 전체 파일 리스트들을 가져오고, 그 안에서 filter을 통해 keyword가 포함된 데이터들만 표시되도록 구현해봤다. 이렇게 하면 검색 키워드가 포함된 파일 이름들은 모두 나타나게 된다. 드래그 앤 드랍 기능도 구현했는데 이는 react-dropzone 라이브러리를 사용했다.const onDrop = useCallback((acceptedFiles: File[]) => { // Do something with the files }, []); const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });npm에 적혀있는 공식 사용법인데, 기존에 사용했던 form을 삭제하고 div로 바꾼 다음 div와 input에 getRootProps getInputProps를 넣고 각각에 적절한 로직들을 넣어주면 드래그 앤 드랍을 통한 파일 업로드 기능도 정상적으로 이루어진다.미션미션은 마지막으로 업데이트 된 날짜를 이미지 카드에 표시해주는 내용이었다. supabase에서 이미지 리스트들을 불러오면 각각의 이미지들은 다음과 같은 구조를 띈다.따라서 lastModified 나 updated_at을 작성해주면 된다. (둘이 무슨 차이가 있는지 잘 모르겠다.....) 날짜 포맷은 지난 Todolist때 사용했던 것 그대로 사용했다. :)결과 화면은 다음과 같다.마무리파일 업로드를 Supabase에 어떤 방식으로 해야할 지 알게 된 시간이었다. 그리고 지난번 기초를 잘 잡아두니 (초기 세팅 등) 별다른 불편함 없이 프로젝트를 새로 시작할 수 있어서 역시 초기 세팅이 중요하다 생각됬다. 또한 강의만 따라 듣는 것이 아닌 부족한 점을 개선하고 내 방식을 추가해서 작업했다는 점도 고무적이었다.다음 프로젝트는 Netflix 프로젝트인데 사실 넷플릭스 프로젝트는.. 다른 강의에서도 몇번 해봤던 내용이지만 특히 그 중 기대하는 점은 SEO에 관한 내용이 있다는 것이었다. Next.js를 사용하는 큰 이유 중 하나가 바로 SEO 관련인데 이 부분에 대해 어떤 내용일지가 궁금하다. 예를 들어 Next.js는 자체적으로 sitemap이나 robots.txt 기능을 제공한다는 점과 강의에서도 말씀해주셧든 page.tsx가 서버 컴포넌트여야 하는 이유 등 어떻게하면 Next.js만이 가지는 장점을 최대한 효율적으로 활용하면서 프로젝트를 만들 수 있을지 기대가 된다. 

웹 개발웹개발Next.js프론트엔드Supabase

구탱

인프런 워밍업 클럽 스터디 3기 - CS 전공지식 (운영체제, 자료구조, 알고리즘) 회고

알고리즘 2주차 회고이번주 배운 알고리즘 개념은 재귀와 정렬이다.재귀는 어떠한 것을 정의할 때 자신의 참조하는 것이다.아래는 재귀를 위해 실습한 코드 일부...function sumArray(arr){ if(arr.length == 1) return arr[0]; return sumArray(arr.slice(0, -1)) + arr[arr.length -1]; } let arr = [1,2,3,4,5]; let sum = sumArray(arr); console.log(sum);재귀에서는 하노이의 탑을 이용한 방식이 있는데, 값을 이동시킬 때 사용할 수 있는 개념이라고 생각했다.예를 들면 int a=5이고 int b=4일때, a와 b의 값을 서로 바꾸는 경우 temp라는 값을 두고 바꾸는 것도 하노이의 탑과 유사할 것이다.버블정렬은 앞의 숫자와 옆의 숫자를 비교해서 자리를 바꾸는 것인데, 반복할 수록 비교할 횟수가 줄어들긴 하지만 성능이 O(n제곱)이라 좋지 않다. 선택정렬은 배열의 첫번째부터 마지막까지 비교를 하면서 정렬하는데 버블정렬과 동일하게 구현은 쉽지만 성능이 O(n제곱)으로 좋지않다.운영체제 2주차 회고스케줄링 개념을 집중해서 익혔다. 그리고 데드락에 대한 수업을 듣고 교착상태 해결방법에 대해 배울 수 있어서 유익했다.하지만 실제 상황에서 교착상태 문제 해결을 위한 능력을 갖추려면 더 공부가 필요...ㅜㅜCPU스케줄링: 운영체제에서 프로세스들에게 CPU를 할당하고 해제하는 것프로세스 상태스케줄링의 목표: 리소스 사용률, 오버헤드 최소화, 공평성, 처리량, 대기시간, 응답시간 -> 모든 것을 완벽하게 고려하기는 어렵기 때문에 밸런스 유지가 중요하다.종류: FIFO(순서대로 진행), SJF(짧은작업 먼저 진행), RR(정해진시간을 두고 순서대로 진행), MLFQ(가장 일반적으로 쓰이며 타임슬라이스를 이용해서 우선순위를 따져 진행)데드락(교착상태): 여러 프로세스가 서로 다른 프로세스 작업이 끝나기를 기다리거나 아무 프로세스도 작업을 시작하지 못한 상태교착상태는 상호배제와 비선점, 점유와 대기, 원형대기가 필요조건이다.교착상태 해결을 위해서는 교착상태 회피와 교착상태 검출이 사용될 수 있다.    

Eun-Ng

인프런 워밍업 클럽 스터디 3기 - CS 2주차 미션

운영체제FIFO 스케줄링의 장단점이 뭔가요?장점관리가 용이하고, 오버헤드가 적습니다.프로세스가 순서대로 처리되기에 예측 가능성이 높습니다.단점버스트 타임이 긴 프로세스가 처리중이면 대기중인 프로세스들이 오래 대기해야합니다.그에 따라 평균 대기 시간이 길어질 수 있습니다.SJF를 사용하기 여러운 이유가 뭔가요? 이론적으로 본다면 버스트 타임이 짧은 프로세스를 먼저 처리해 전체적인 대기 시간이 감소하고, 평균 대기 시간을 줄이기 용이합니다.실질적으로는 어떤 프로세스가 얼마나 실행될지 예측하기가 힘들고, 버스트 타임이 짧은 프로세스들이 많거나 중간중간 계속 발생된다면 버스트 타임이 긴 프로세스들은 영원히 실행되지 않을 수도 있습니다.RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요? 타임 슬라이스를 작게 설정하는 경우 사용자의 입장에서는 동시에 실행되는 느낌을 받을 수 있지만 컨텍스트 스위칭을 처리하는 양이 훨씬 많아져서 오버헤드가 너무 커지게 됩니다.운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요? 할당된 타임 슬라이스를 전부 사용하거나, 오버해서 사용하다 스케줄러에 의해 반납하는 상황, I/O 요청이 적은 경우 CPU Bound Process일 확률이 높습니다.반면, CPU 사용시간이 짧아 스스로 반납하거나, 타임 슬라이스를 다 쓰기 전에 I/O 요청이 생기는 경우 I/O Bound Process일 확률이 높습니다.공유자원이란 무엇인가요? 프로세스간 통신을 할 때 공동으로 이용하는 변수나 파일 등입니다.동시에 사용하면 문제가 발생할 수 있기에 상호배제가 필요한 자원입니다.교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야할까요? 교착상태의 필요조건 4가지상호배제 - 자원은 한 번에 한 프로세스에서만 사용 가능합니다. 다른 프로세스가 사용중인 자원은 사용 불가능합니다.비선점 - 이미 사용중인 자원은 다른 프로세스가 빼앗을 수 없습니다.점유와 대기 - 프로세스가 하나의 자원을 보유한 상태에서 다른 자원을 추가로 요청해야 합니다.원형 대기 - 점유와 대기를 하는 프로세스들의 관계가 서로 원형을 이루고 있습니다.자료구조와 알고리즘재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요? 함수가 계속해서 호출되기에, 콜 스택에 호출된 함수들이 계속 쌓여 메모리 한계에 도달합니다.메모리 한계에 도달한 이후 프로그램은 강제 종료됩니다.0부터 입력 n까지 홀수의 합을 더하는 재귀 함수를 만들어보세요.function sumOdd(n){ let sum = 0; for (let i = 0; i < n; i++) { if (i % 2 === 1) { sum += i; } } return sum; } console.log(sumOdd(10)) // 25 다음 코드는 매개변수로 주어진 파일 경로(.는 현재 디렉토리)에 있는 하위 모든 파일과 디렉토리를 출력하는 코드입니다. 다음 코드를 재귀 함수를 이용하는 코드로 변경해보세요const fs = require('fs'); // 파일을 이용하는 모듈 const path = require('path'); // 폴더와 파일의 경로를 지정해주는 모듈 function traverseDirectory1(directory) { const files = fs.readdirSync(directory); // 인자로 주어진 경로의 디렉토리에 있는 파일or디렉토리들 for (const file of files) { // 현재 디렉토리의 모든 파일or디렉토리 순회 const filePath = path.join(directory, file); //directory와 file을 하나의 경로로 합쳐줌 const fileStatus = fs.statSync(filePath); // 파일정보 얻기 if (fileStatus.isDirectory()) { // 해당 파일이 디렉토리라면 console.log('디렉토리:', filePath); traverseDirectory1(filePath); } else { // 해당 파일이 파일이라면 console.log('파일:', filePath); } } } traverseDirectory1('.'); // 현재 경로의 모든 하위 경로의 파일, 디렉토리 출력

Eun-Ng

인프런 워밍업 클럽 스터디 3기 - CS 2주차 발자국

운영체제섹션 4. 프로세스 동기화4-1. 프로세스간 통신프로세스는 독립적으로 실행되기도 하지만, 다른 프로세스와 데이터를 주고받으며 통신을 하는 경우도 있음프로세스 통신의 종류파일과 파이프를 이용하는 방법(프로세스 간 통신 방법)파일: 통신하려는 프로세스들이 하나의 파일을 이용해 읽고 쓰는 방법파이프: 운영체제가 생성한 파이프를 이용해 데이터를 읽고 쓰는 방법쓰레드를 이용하는 방법(프로세스 내 쓰레드 간 통신 방법)쓰레드는 코드, 데이터, 힙 영역을 공유하고 스택만 각자 지니고 있음데이터 영역의 전역변수나 힙을 이용하면 통신이 가능함네트워크를 이용하는 방법운영체제가 제공하는 소켓 통신RPC(원격 프로시저 호출)를 이용한 통신: 다른 컴퓨터에 있는 함수를 호출하는 방법4-2. 공유자원과 임계구역프로세스 간 통신을 할 때 공동으로 이용하는 변수나 파일들을 공유자원 이라고 일컬음공유자원은 여러 프로세스가 공유하고 있기 때문에 각 프로세스의 접근 순서에 따라 결과가 달라질 수 있음. 또한 컨텍스트 스위칭으로 시분할 처리를 하기 때문에 어떤 프로세스가 먼저 실행되고 어떤 프로세스가 나중에 실행되는지 예측하기가 힘듦따라서 연산결과를 예측하기가 힘들고, 여기서 발생한 문제를 동기화 문제라고 부름따라서 여러 프로세스가 동시에 사용하면 안되는 영역이 임계 구역(Critical Section)임공유자원을 서로 사용하기 위해 경쟁하는 것은 경쟁조건(Race Condition)임계구역 문제를 해결하기 위해서는 상호 배제(Mutual Exclusion) 메커니즘이 필요함상호 배제의 요구사항임계구역엔 동시에 하나의 프로세스만 접근한다.여러 요청에도 하나의 프로세스의 접근만 허용한다.임계구역에 들어간 프로세스는 빠르게 나와야한다.4-3. 세마포어상호배제 메커니즘 중 하나. 여러 프로세스나 스레드의 공유 자원 접근을 제어하는 동기화 도구로써 정수형 변수로 이루어짐.4-4. 모니터세마포어의 단점을 해결한 상호배제 메커니즘운영체제가 처리하는 것이 아닌 프로그래밍 언어 차원에서 지원하는 방법모니터의 구현만 완벽하다면 프로그래머는 세마포어처럼 wait(), signal() 함수를 임계영역에 감싸지 않아도 돼서 편리하고 안전하게 코드를 작성할 수 있음섹션 5. 데드락5-1. 데드락이란?(feat. 식사하는 철학자)교착상태(데드락) 이란 여러 프로세스가 서로 다른 작업이 끝나기를 기다렸다가 아무도 작업을 진행하지 못하는 상태공유자원 때문에 교착상태가 발생함교착상태의 필요조건 4가지상호배제 - 어떤 프로세스가 한 리소스를 점유했다면, 그 리소스는 다른 프로세스에게 공유가 되면 안됨비선점 - 프로세스 A가 리소스를 점유하고 있는데, 프로세스 B가 리소스를 뺏을 수 없어야함점유와 대기 - 어떤 프로세스가 리소스A를 가지고 있는 상태에서 리소스 B를 원하는 상태여야 함원형 대기 - 점유와 대기를 하는 프로세스들의 관계가 원형을 이루고 있음이중에 한가지라도 충족하지 않는다면 교착상태는 발생하지 않음.5-2. 데드락 해결(feat. 은행원 알고리즘)교착상태 회피(Deadlock avoidance)란 프로세스들에게 자원을 할당할 때 어느정도 자원을 할당해야 교착상태가 발생하는지 파악해서 교착상태가 발생하지 않는 수준의 자원을 할당하는 것 교착상태 회피는 전체 자원의 수와 할당된 자원의 수를 기준으로 안정상태(Safe state), 불안정 상태(Unsafe state)로 나눔. 불안정상태에 있더라도 무작정 교착상태에 빠지는것이 아니라, 교착상태에 빠질 확률이 높아짐운영체제는 프로세스들에게 자원을 할당하기 전에 자기가 가지고 있는 전체 자원의 수를 알고 있어야함. 이가 시스템의 총 자원.그리고 프로세스들은 각자 자기가 필요한 자원의 최대숫자를 운영체제에게 알려줘야 함.이가 최대 요구 자원.불안정 상태에 있더라도 모든 프로세스가 최대 자원을 요청하지 않는다면 교착상태에 빠지지 않을 수도 있지만 불안정상태에 빠지지 않도록 유지하는게 좋음은행원 알고리즘은 교착상태를 피하는 좋은 방법이지만 비용이 비싸고, 비효율적임그래서 교착상태는 허용하지만, 발생했을때 이를 해결하는 방식을 연구함교착상태 검출 방식가벼운 교착 상태 검출타이머를 이용하는 방식. 프로세스가 일정시간 동안 작업을 진행하지 않는다면 교착상태가 발생했다고 간주하고 교착상태를 해결함해결법 - 일정 시점마다 체크포인트를 만들어 작업을 저장하고 타임아웃으로 교착상태가 발생했다면 마지막으로 저장한 체크포인트로 롤백함무거운 교착 상태 검출자원 할당 그래프를 이용하는 방식. 현재 운영체제에서 프로세스가 어떤 자원을 사용하는지 지켜보고 교착상태가 발생하면 해결함해결법 - 교착상태가 검출되면 교착상태를 일으킨 프로세스를 강제종료 시킴. 그리고, 다시 실행시킬 때 체크포인트로 롤백 시킴. 이 방식은 운영체제가 지속적으로 “자원 할당 그래프”를 유지하고 검사해야 하기에 오버헤드가 발생함. 하지만 가벼운 교착 상태 검출에서 발생할 수 있는 억울하게 종료되는 프로세스가 발생되지 않음섹션 6. 쉬어가기6-1. 컴파일과 프로세스컴파일 언어: 컴파일 과정에서 개발자가 문법 오류를 일으켰는지 검사를 하고, CPU에서 처리 가능한 기계어로 실행파일을 만들어 놓기에 속도가 빠름인터프리터 언어: 인터프리터 언어는 개발자가 작성한 코드를 미리 기계어로 만들지 않고, 실행 시 코드를 한 줄씩 해석해 실행하는 언어. 미리 검사하지 않기 때문에 실행할 때 오류가 날 수도 있고, 속도도 컴파일 언어와 비교하면 느림컴파일 과정전처리 단계: 전처리 구문 처리컴파일러 단계: 기계어에 가까운 어셈블리어로 변환어셈블러 단계: 오브젝트 파일로 변환. 0과 1로 된 기계어로 구성링커 단계: 모든 오브젝트 파일을 하나의 코드영역과 데이터영역으로 묶음. 실제로 실행될 주소를 매핑시킴. 링커까지 거친 후 .exe 실행 파일 생성섹션 7. 메모리7-1. 메모리 종류레지스터: 가장 빠른 기억장소로 CPU 내에 존재하고 있음. 컴퓨터의 전원이 꺼지면 데이터가 사라지기에 휘발성 메모리로 불림. 32bit, 64bit는 레지스트리의 크기를 말함. CPU는 계산을 할 때 메인메모리에 있는 값을 레지스터로 가져와 계산함. 계산 결과는 다시 메인메모리에 저장캐시: 휘발성 메모리. 미리 가져온 데이터들을 저장. 캐시는 성능의 이유로 여러 개 두고 사용함. CPU가 값을 요청해 레지스터로 값을 옮겨야 한다면 단계에 따라 가장 속도가 빠른 L1 → L2 → 메인 메모리 순으로 참조함. 즉 빠른 캐시에 있는 값을 먼저 찾으려고 함메인 메모리(RAM): 실제 운영체제와 다른 프로세스들이 올라가는 공간. 전원이 공급되지 않으면 데이터가 지워지기에 휘발성임. HDD, SDD 보다 속도는 빠르지만 가격이 비싸기에 데이터를 저장하기보다는 실행중인 프로그램만 올림보조저장장치(HDD, SSD): 다른 메모리에 비해 비교적 가격이 저렴하고, 전원이 공급되지 않아도 데이터가 지워지지 않는 비휘발성 메모리.7-2. 메모리와 주소운영체제는 메모리를 관리하기 위해서 1바이트 크기로 구역을 나누고 숫자를 매김.이 숫자는 곧 “주소”. 각 CPU의 bit는 레지스터 크기, ALU, 버스의 크기가 동일함.물리주소와 논리주소0x0번지부터 시작하는 주소공간 = 물리 주소 공간사용자 관점에서 바라본 주소공간 = 논리 주소 공간사용자는 물리 주소를 몰라도 논리 주소로 물리 주소에 접근할 수 있음.운영체제는 특별하기에 메모리에 따로 공간을 마련해둠.그래서 하드웨어적으로 운영체제 공간과 사용자 공간을 나누는 경계 레지스터를 만듦.경계 레지스터는 CPU내에 존재하는 레지스터로 메모리 관리자가 사용자 프로세스가 경계 레지스터의 값을 벗어났는지 검사하고 만약 벗어났다면 그 프로세스를 종료 시킴.절대주소와 상대주소개발자는 프로그램을 만들 때 프로그램이 실행될 주소를 신경쓰지 않고 개발함. 이는 컴파일러가 컴파일을 할 때 메모리 0번지에서 실행한다고 “가정”하기 때문.7-3. 메모리 할당방식메모리 오버레이란? 유니프로그래밍 환경에서 메모리보다 더 큰 프로그램을 실행시키기 위해 큰 프로그램을 메모리에 올릴 수 있도록 잘라 당장 실행시켜야 할 부분만 메모리에 올리고, 나머지는 하드디스크에 저장하는 기법.현대의 멀티프로그래밍 환경에서 메모리를 나누는 방식가변 분할 방식: 가변 분할 방식이란 프로세스의 크기에 따라 메모리를 나누는 방식고정 분할 방식: 프로세스 크기와 상관없이 메모리를 할당가변 분할 방식한 프로세스가 메모리에 연속된 공간에 할당되기에 연속 메모리 할당이라고 함가변 분할 방식은 프로세스의 크기에 딱 맞게 할당되기에 낭비되는 공간인 “내부 단편화”가 없음단점으로는 “외부 단편화”가 발생함고정 분할 방식프로세스가 쪼개져 할당되어 여러곳에 할당됨고정 분할 방식의 장점은 구현이 간단하고 오버헤드가 적음단점으로는 작은 프로세스도 큰 영역에 할당돼서 공간이 낭비되는 “내부 단편화”가 발생버디 시스템가변 분할 방식과 고정 분할 방식을 혼합해 단점을 최소화함버디 시스템은 2의 승수로 메모리를 분할해 메모리를 할당하는 방식프로세스가 종료후 해제되도, 근접한 메모리 공간을 합치기 쉬움알고리즘&자료구조섹션 3. 알고리즘재귀(Recursion)함수가 자기 자신을 호출하는 프로그래밍 방식큰 문제를 동일한 형태의 작은 문제로 나누어 해결재귀 함수를 사용하기 위해서는 기저 조건(탈출 조건)이 필요함팩토리얼(Factorial)n!로 표시1부터 n까지의 모든 양의 정수를 곱한 값하향식 계산큰 문제 → 작은 문제로 분할가장 작은 문제(기저 조건)까지 내려감결과를 다시 위로 올라가며 조합버블정렬(Bubble Sort)앞에 있는 숫자와 옆에 숫자를 비교해 자리를 바꾸는 알고리즘장점: 이해와 구현이 간단함단점: 성능이 좋지 않음시간복잡도O(n²)선택정렬(Selection Sort)배열에서 최솟값을 찾아 맨 앞으로 이동하는 정렬. 정렬되지 않은 부분에서 가장 작은 요소를 선택하여 정렬된 부분의 끝에 추가함장점: 이해와 구현이 간단함단점: 성능이 좋지 않음시간복잡도O(n²)회고복습이 조금 부족했던거 같다. 발자국을 정리하면서 그나마 회고하는 시간을 가져서 좋았다.

Hyun Ho Kim

인프런 워밍업 클럽 스터디 3기 - CS 전공지식(운영체제) -2주차 미션-

1. 선입선출(FIFO)의 장단점장점스케쥴링의 이해와 구현이 단순하다.자원의 효율성이 높다.단점실행시간이 긴 프로세스가 앞에서 장시간 독점하는 경우 다른 프로세스들이 오래 대기해야한다.평균 응답 시간이 길어질 수 있다.2. 최소작업 우선 - SJF(Shortest Job First)을 사용하기 어려운 이유준비큐에 있는 프로세스 중에서 실행 시간이 가장 짧은 작업부터 CPU를 할당하는 비선점형 방식이다.그러므로 실행 시간이 긴 프로세스들이 무한정 대기하는 현상이 발생한다.3. RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요?라운드 로빈 스케줄링준비 큐에 가장 먼저 삽입된 프로세스부터 시작하여순서대로 프로세스에 CPU자원을 할당해서 실행실행할 때마다 일정하게 정해진 시간만큼만(time slice) 실행하고 다음 프로세스로 CPU자원을 넘겨주는데, 이 정해진 시간을 너무 작게(짧게) 설정하면 프로세스 간의 CPU 사용 교체가 빈번해져 실행 프로세스 교체에 소요되는 리소스가 과도해짐에 따라 오버헤드가 발생한다.4. 운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요?일반적으로 연산이 많이 필요한 로직은 CPU Bound로컬 파일 시스템 혹은 네트워크 통신이 많은 로직은 I/O Bound 라고 한다.여기서 프로세스 수행과정 중에 CPU burst , I/O burst가 계속 변경, 수행되며 프로세스 작업의 종류에 따라 각자가 일어나는 시간이 달라진다.이 때 CPU burst가 많이 일어나는 작업을 CPU Bound Process라고 하고 I/O burst가 많이 일어나는 작업을 I/O Bound Process라고 한다. 버스트 여기서 버스트란 연속된 신호 또는 데이터의 모임, 어떤 현상이 짧은 시간에 집중적으로 일어하는 현상을 뜻하거나 주기억 장치의 내용을 캐시 기억 장치에 블록 단위로 한꺼번에 전송하는 것을 뜻한다.CPU BoundCPU Bound는 프로세스가 진행될 때, CPU 사용 시간이 I/O Waiting 보다 많은 경우이다. 그러므로 CPU의 성능에 의해 작업 속도가 결정된다.I/O Bound프로세서가 진행될 때 I/O Waiting이 많은 경우이다.파일 쓰기, 디스크 작업, 네트워크 통신을 할 때 주로 나타나며5. 공유자원이란 무엇인가요?시스템 내에서 여러 프로세스나 스레드가 함께 접근할 수 있는 자원이다.메모리, 파일, 데이터 등을 말한다.공유자원은 공동으로 이용되기 때문에 누가 언제 데이터를 읽거나 쓰느냐에 따라 그 결과가 달라질 수 있다.6. 교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야할까요?교착상태는 둘 이상의 프로세스가 다른 프로세스가 점유하고 있는 자원을 서로 기다리는데 무한 대기 상태에 빠지는 상황을 일컫는다.즉, 한정된 자원을 여러 곳에서 사용하려고 함으로써 다음 처리를 하지 못하는 상태이다.요약멀티 프로그래밍 환경에서 한정된 자원을 얻기 위해 서로 경쟁한 프로세스가 자원을 점유하고 있다면 동시에 다른 자원이 사용할 수 없는 상황 발생이 때 점유하지 못한 다른 프로세스는 대기 상태로 들어감.대기 상태로 들어간 프로세스들이 실행 상태로 변경될 수 없을 때, 교착 상태 발생발생 조건상호 배제자원 하나 당 한 프로세스만 사용할 수 있다.점유 대기다른 프로세스에 할당되어 사용되고 있는 자원을 추가로 점유하기 위해 대기하는 프로세스가 존대비선점할당된 자원은 사용이 끝나서 반납될 때까지 강제로 빼앗을 수 없다.순환대기프로세스들의 집합이 점유대기 상태를 순환하는 것

운영체제cs

와땅깡

[인프런 워밍업 클럽 3기 / 백엔드 프로젝트] 2주차 정리

해당글은 [입문자를 위한 Spring Boot with Kotlin - 나만의 포트폴리오 사이트 만들기: 정보근]https://www.inflearn.com/course/%EC%9E%85%EB%AC%B8%EC%9E%90-spring-boot-kotlin-%ED%8F%AC%ED%8A%B8%ED%8F%B4%EB%A6%AC%EC%98%A4/dashboard강의를 보고 공부한 내용입니다.2주차 부터는 실습 위주의 강의로 공부 내용의 경우 어노테이션 중심으로 정리했습니다. 공부 내용 정리1. 도메인 레이어도메인 레이어 설명Entity: 데이터베이스 테이블과 매핑되는 클래스.Repository: JPA를 활용하여 엔티티와 데이터베이스 간의 CRUD 작업을 수행하는 인터페이스.관련 어노테이션@Entity // JPA 엔티티 클래스 지정. @Id // 기본 키(PK) 지정. @GeneratedValue // PK 자동 생성 전략 설정. @Column // 데이터베이스 컬럼과 매핑. @CreatedDate // 엔티티 생성 날짜 자동 저장. @OneToMany // 1:N 관계 설정. @ManyToOne // N:1 관계 설정. @JoinColumn //외래 키 지정. @OneToOne //1:1 관계 설정. @ManyToMany // N:M 관계 설정. Spring Data JPA - JpaRepository 설명JpaRepository는 Spring Data JPA에서 제공하는 인터페이스로, 기본적인 CRUD 메서드를 제공합니다.public interface UserRepository extends JpaRepository<User, Long> {}기본 CRUD 메서드save(entity) // 엔티티 저장 또는 수정 findById(id) // ID(PK)로 조회 existsById(id) // 존재 여부 확인 delete(entity) // 엔티티 삭제 deleteById(id) // ID(PK)로 삭제 findAll() // 모든 데이터 조회 count() // 전체 데이터 개수 조회메서드 네이밍 규칙도메인에 종속되는 기능이라도 메소드명 네이밍 규칙을 따르면 그에 맞는 쿼리를 자동으로 생성해주기도 합니다. 따라서 기본적인 명명 규칙을 찾아 정리해보았습니다.findBy + 필드명 : 특정 필드로 조회 findBy + 필드명 + And/Or + 필드명 : 복합 조건 조회findBy + 필드명 + GreaterThan/LessThan : 비교 연산 findBy + 필드명 + Containing/StartsWith/EndsWith : Like 검색 findBy + 필드명 + IsNull/IsNotNul : NULL 처리 findBy + 필드명 + OrderBy + 필드명 + Asc/Desc : 정렬 findTopNBy + 필드명 : 상위 N개 조회  2. 프레젠테이션 레이어프레젠테이션 레이어 설명프레젠테이션 레이어는 HTTP 요청을 받아 서비스 계층과 상호작용하며, 클라이언트에 응답을 반환하는 역할을 수행합니다. 컨트롤러, DTO, 서비스, 인터셉터로 구성됩니다.Controller: HTTP 요청을 처리하는 역할.DTO: 데이터 전달을 위한 객체.Service: 비즈니스 로직을 처리하는 계층.Interceptor: 컨트롤러에 도달하기 전후에 요청을 가로채는 역할. 관련 어노테이션 정리@Controller // Spring MVC 컨트롤러 역할. 뷰를 반환. @RestController // @Controller + @ResponseBody 조합. JSON 반환. @RequestMapping // 특정 URL과 컨트롤러 메서드 매핑. @GetMapping // GET 요청 처리. @PostMapping // POST 요청 처리. @Service // 비즈니스 로직을 담당하는 서비스 클래스에 붙임. @Repository // 데이터베이스와 연동되는 DAO 클래스에 붙임. @Component // Spring Bean으로 등록하는 가장 기본적인 어노테이션. @Transactional // 트랜잭션 관리. DB 작업 중 실패 시 롤백. @Configuration // Spring 설정 클래스에 붙임.  4. 테스트 코드테스트 코드의 작성은 기능을 개발하는 것만큼 중요한 작업입니다.코드의 정확성, 유지보수성, 신뢰성을 보장하며, 개발 속도를 높이는 데에도 중요한 역할을 합니다.단위 테스트 vs 통합 테스트 비교단위 테스트 (Unit Test) : 개별 메서드, 클래스의 기능 검증. Mock 객체 사용. 실행 속도 빠름. 통합 테스트 (Integration Test) : 여러 계층(Controller → Service → Repository)의 연계를 테스트. 실제 DB 사용. 실행 속도 느림. 테스트 관련 어노테이션 정리@ExtendWith // JUnit5와 스프링 테스트 환경 통합. @InjectMocks // @Mock 객체를 테스트 대상 클래스에 주입. @Mock // 테스트에서 Mock 객체 생성. @SpringBootTest // Spring Boot 애플리케이션 컨텍스트 로드 후 테스트 실행. @AutoConfigureMockMvc // MockMvc 자동 설정. @DisplayName // 테스트 실행 시 표시될 이름 지정.  미션미션3 - REST API 설계하기API 명세서 작성 도구 선택API 명세서 작성 도구로 어떤 도구를 선택해야할지 미션 전 고민이 많았습니다. 클라이언트 개발을 했을떈 보통 백엔드 팀원 분들이 스웨거 문서로 프로젝트 진행 시 사용을 했었는데 현재 Swagger에 대한 학습이 부족한 상태였기에 다른 방법을 찾아보았습니다. 대안 도구 = 포스트맨 문서 활용포스트맨에서도 문서를 작성할 수 있고, 해당 내용을 공유할 수있음을 알게되었고 스웨거 적용 전 포스트맨 문서를 활용하기로 결정하였습니다. 200 외 오류 응답코드userId 혹은 capsuleId를 찾을 수 없는 경우와 접근 권한(ROLE) 이 허용되지 않는 경우에 따라 다른 처리를 해야하기에 해당 케이스들을 명확하게 구분해야 했습니다.특히, 프로젝트에서 작성자(OWNER) 와 참여자(MEMBER) 역할(Role)이 존재하기 때문에, 권한(Role) 기반 오류 처리 규칙을 정해야 했습니다.오류 코드 정리400 Bad Request : 잘못된 요청 -> userId 또는 capsuleId가 유효한 형식이 아닐 경우401 Unauthorized : 인증 실패 -> 로그인하지 않은 사용자가 보호된 API에 접근 시 (JWT Token 사용 시 주로 사용)403 Forbidden : 권한 없음 (인가 실패) -> 사용자는 존재하지만, role 에 따른 권한이 없어 접근 불가한 경우404 Not Found : 리소스 없음 -> 요청한 리소스가 존재하지 않는 경우코드 적용 규칙1. 권한(Role)에 따라 접근이 제한되는 경우 → 403 Forbidden - 예) 참여자(MEMBER)가 캡슐을 삭제하려고 하는 경우 → 삭제 기능은 OWNER만 가능하므로, 권한 부족 → 403 응답 반환1. 요청 데이터가 정상적으로 전달되었지만, 해당 리소스가 존재하지 않는 경우 → 404 Not Found - 예) 존재하지 않는 userId로 게시글 조회 시 → 해당 리소스가 없으므로 404 반환 회고GOOD단순히 아키텍쳐에 대한 이론만 들었을 때는 이해가 부족한 느낌이였는데 실습을 통해 뼈대를 잡으면서 점차 이해를 높일 수 있었습니다.PROBLEM처음 진행해보는 스프링 프로젝트기에 수많은 어노테이션들의 각 기능에 대해 개념이 섞이는 느낌이라 아직은 낯설게 느껴져 강의 자료를 참고하지않고 혼자서 작성하기에는 아직은 무리였습니다.처음 h2 확인 실습 시 콘솔에 접속되지 않는 문제가 있었는데 코드 레벨에서의 문제는 없어 꽤 많은 시간을 해결하는데 할애하였습니다. 단순히 인텔리제이 Build설정을 Intellij IDEA -> Gradle로 설정하니 해결되었습니다.성능 개선 부분에서 조금 이해가 어려웠습니다.TRY성능 개선 방법에 대해 개인적으로 더 공부해보고 고민해보기

백엔드인프런워밍업클럽백엔드발자국

xx

[인프런 워밍업 클럽 3기 CS] 2주 차 발자국

운영체제프로세스 간 통신프로세스는 독립적으로 실행되기도 하지만 다른 프로세스와 데이터를 주고 받으며 통신을 하는 경우도 있음통신은 한 컴퓨터 내에서 실행되고 있는 다른 프로세스와 할 수 있고, 네트워크로 연결된 다른 컴퓨터에 있는 프로세스와 할 수도 있다.종류한 컴퓨터 내에서파일: 통신을 하려는 프로세스들이 하나의 파일을 이용해 읽고 쓰는 방법파이프: 운영체제가 생성한 파이프를 이용해 데이터를 읽고 쓰는 방법한 프로세스 내에서쓰레드 간 통신: 전역 변수나 힙을 사용네트워크를 이용한 방법운영체제가 제공하는 소켓 통신다른 컴퓨터에 있는 함수를 호출하는 RPC공유자원과 임계구역공유자원프로세스 간 통신을 할 때 공동으로 이용하는 변수나 파일 등공유자원은 여러 프로세스가 공유하기 때문에 각 프로세스의 접근 순서에 따라 결과가 달라질 수 있음컨텍스트 스위칭으로 시분할 처리를 하기 때문에 어떤 프로세스가 먼저 실행되고 나중에 실행되는지 예측하기 어렵다.연산 결과를 예측하기 힘들고 동기화 문제가 발생임계구역여러 프로세스가 동시에 사용하면 안 되는 영역공유자원을 서로 사용하기 위해 사용하는 것은 경쟁조건이라 한다.해결 방법상호 배제의 요구사항임계영역에는 동시에 하나의 프로세스만 접근한다.여러 요청에도 하나의 프로세스의 접근만 허용한다.임계구역에 들어간 프로세스는 빠르게 나와야 한다.세마포어상호배제 매커니즘 중 하나모니터synchronized동시에 여러 프로세스에서 실행시킬 수 없음교착상태(데드락)여러 프로세스가 서로 다른 프로세스의 작업을 끝나기를 기다리다가 아무도 작업을 진행하지 못하는 상태원인은 공유자원 때문필요조건상호배제: 어떤 프로세스가 한 리소스를 점유했다면 그 리소스는 다른 리소스에게 공유되면 안 된다.비선점: 프로세스 A가 리소스를 점유하고 있는데 프로세스 B가 빼앗을 수 없어야 한다.점유와 대기: 어떤 프로세스가 리소스 A를 가지고 있는 상태에서 리소스 B를 원하는 상태여야 한다.원형 대기: 점유와 대기를 하는 프로세스들의 관계가 원형을 이루고 있는 것교착상태 해결 방법교착상태 회피프로세스들에게 자원을 할당할 때 어느정도 자원을 할당해야 교착상태가 발생하는지 파악해서 교착상태가 발생하지 않는 수준의 자원을 할당하는 방법전체 자원의 수와 할당된 자원의 수를 기준으로 안정 상태와 불안정 상태로 나눈다.운영체제는 최대한 안정 상태를 유지하려고 자원을 할당한다.불완전 상태에 있다고 교착상태에 빠지는 것이 아니라 교착상태에 빠질 확률이 높아진다.교착상태를 검출하는 방법가벼운 교착상태 검출: 타이머를 이용해 프로세스가 일정시간 동안 작업을 진행하지 않는다면 교착상태가 발생했다고 간주하고 해결함일정 시점마다 체크 포인트를 만들어 작업을 저장하고 타임 아웃으로 교착상태가 발생했다면 마지막으로 저장했던 체크 포인트로 롤백무거운 교착상태 검출: 자원 할당 그래프를 이용해 현재 운영체제에서 프로세스가 어떤 자원을 사용하는지 지켜보고 교착상태가 발생했다면 해결함오버헤드가 발생하지만 가벼운 교착상태 검출에서 발생할 수 있는 억울하게 종료되는 프로세스는 발생하지 않는다.컴파일과 프로세스컴파일 언어개발자가 코드를 작성하고 컴파일을 거쳐 0과 1로 된 기계어로 실행 파일을 만듦컴파일 과정에서 문법 오류 검사하고 CPU에서 처리 가능한 기계어로 실행 파일을 만들어 놓기 때문에 속도가 빠름인터프리터 언어개발자가 작성한 코드를 미리 기계어로 만들지 않고 실행 시 코드를 한 줄씩 해석해 실행하는 언어실행할 때 오류가 날 수도 있고 컴파일 속도가 느림메모리레지스터가장 빠른 기억저장소CPU 내에 존재컴퓨터의 전원이 꺼지면 데이터가 사라져 휘발성 메모리라고 함캐시필요할 것 같은 데이터를 미리 가져와 저장하는 곳성능의 이유로 여러 개를 둔다메인 메모리실제 운영체제와 다른 프로세스들이 올라가는 공간전원이 공급되지 않으면 데이터가 지워지기 때문에 휘발성 메모리하드디스크나 SSD보다 속도는 빠르지만 가격이 비싸기 때문에 데이터를 저장하기 보다 실행 중인 프로그램만 올림보조 저장 장치비휘발성 메모리속도가 느리고 가격이 쌈메모리와 구조운영체제는 메모리를 관리하기 위해 1바이트 크기로 구역을 나누고 숫자로 매긴다. → 주소라고 부름물리 주소메모리를 컴퓨터에 연결하면 0번지부터 시작하는 주소 공간논리 주소사용자 관점에서 바라본 주소 공간물리 주소를 몰라도 논리 주소로 접근할 수 있음메모리 할당 방식메모리 오버레이: 당장 실행해야 될 부분부터 메모리에 올리고 나머지는 하드디스크(스왑 영역)에 저장하는 방식가변 분할 방식(세그멘테이션)프로세스 크기에 따라 메모리를 할당하는 방식장점 단점 메모리의 연속된 공간에 할당되기 때문에 낭비되는 공간인 내부 단편화가 없음 외부 단편화 발생고정 분할 방식(페이징)프로세스 크기와 상관없이 정해진 크기의 메모리를 할당하는 방식장점 단점 구현이 간단하고 오버헤드가 적음 작은 프로세스도 큰 영역에 할당되어 낭비되는 내부 단편화 발생외부 단편화남아있는 메모리의 크기가 실행하고자 하는 프로세스보다 크지만, 연속적이지 않은 공간에 존재하여 실행하지 못하는 현상외부 단편화를 해결하는 방법은 공간을 합쳐주는 조각모음을 하면 된다.내부 단편화Partition의 크기가 프로세스의 크기보다 커서 메모리가 남지만, 다른 프로세스가 사용할 수 없는 상태 알고리즘재귀어떠한 것을 정의할 때 자기 자신을 참조하는 것재귀 함수: 재귀적으로 정의된 함수function myFunction(number) { console.log(number); myFunction(number + 1); } 콜스택이라는 메모리 공간이 가득차면 자동으로 종료됨위 코드는 종료 조건이 없음재귀 함수는 탈출 조건 즉, 기조 조건이 반드시 있어야 함function myFunction(number) { if (number > 10) return; console.log(number); myFunction(number + 1); } 콜스택함수가 호출되면서 올라가는 메모리 영역으로 스택이라고도 부름팩토리얼function factorial(number) { if (number == 1 || number == 0) { return 1; } else { return number * factorial(number - 1); } } 하노이탑한 번에 한개의 원판만 옮길 수 있다.가장 위에 있는 원판만 이동할 수 있다.큰 원판이 작은 원판 위에 있어서는 안 된다.정렬버블 정렬서로 인접한 두 원소를 비교하여 정렬하는 알고리즘O(n^2)장점: 이해와 구현이 간단함단점: 성능이 좋지 않음 선택 정렬정렬되지 않은 영역의 최솟값을 찾아 맨 앞의 위치한 값과 교체하여 정렬하는 알고리즘O(n^2)장점과 단점은 버블 정렬과 동일References그림으로 쉽게 배우는 자료구조와 알고리즘 (기본편)그림으로 쉽게 배우는 운영체제

xx 2일 전
xx

[인프런 워밍업 클럽 0기 CS] 자료구조 및 알고리즘 2주 차 미션

1. 재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요?기저 조건이 없거나 잘못 설정되면 재귀 호출이 끝나지 않고 무한히 호출되면서 스택 메모리를 초과하여 Stack Overflow 오류가 발생할 수 있다.기저 조건이 정확하지 않으면, 재귀 호출이 정상적으로 종료되지 않거나 의도한 값과 다른 결과를 반환할 수 있다 2. 0부터 입력 n까지 홀수의 합을 더하는 재귀 함수를 만들어보세요.function sumOdd(n){ if ( n == 0 ) { return 0; } if (n % 2 == 0) { return sumOdd(n - 1); } else { return n + sumOdd(n - 2); } } console.log(sumOdd(10)) // 253. 다음 코드는 매개변수로 주어진 파일 경로(.는 현재 디렉토리)에 있는 하위 모든 파일과 디렉토리를 출력하는 코드입니다. 다음 코드를 재귀 함수를 이용하는 코드로 변경해보세요.const fs = require("fs"); const path = require("path"); function traverseDirectory(directory) { const files = fs.readdirSync(directory); for (const file of files) { const filePath = path.join(directory, file); const fileStatus = fs.statSync(filePath); if (fileStatus.isDirectory()) { console.log("디렉토리:", filePath); traverseDirectory(filePath); } else { console.log("파일:", filePath); } } } traverseDirectory1("."); // 현재 경로의 모든 하위 경로의 파일, 디렉토리 출력 

xx 2일 전
보키

2주차 회고 발자국 🐾

1주차와 마찬가지로 KPT 회고 프레임워크를 선택해서 작성해보려고 한다! Keep(만족, 지속하고 싶은 부분)이번 2주차는 개인프로젝트에서는 RDB 모델링을 마친 뒤 엔티티를 정의했으며 현재는 조회 API를 만들고 있고, 강의에서는 Presentation Layer에 대한 부분을 수강했다. 강의가 개인프로젝트보다 좀 빠르지만, 그만큼 개인 프로젝트에 적용할 수 있는 부분에 대한 인사이트를 미리 얻어갈 수 있는 것 같아서 좋다.Problem(부족, 아쉬웠던 부분)또 내 과욕이 부른 스불재(스스로 불러온 재앙) 느낌의 아쉬운 부분을 써보자면.. RDB를 너무 현업과 비슷하게 만드는 것을 목표로 잡지 않았나 싶다..ㅎㅎ 뭐 어쩌겠어~ 벌린 일이니 해야지..!!강의에 대한 내용은 아쉬운게 전혀 없다!! JSP에서 Tag(<% %>)가 빠진, Spring 공식 팀에서도 밀고 있는 템플릿 엔진인 Thymeleaf를 잘 알고 계시고, 다시 배워보니 좋았다!여담으로, Template for Spring으로는 JSP / Thymeleaf / FreeMarker / Groovy Markup / Jade4j / JTE(Java Template Engine) / Velocity / JMustache / Pebble가 있다.어느것을 택하든 자유이나 Spring에서 공식적으로 Support하고 Advertise하는 제품(라이브러리)를 사용하는 것을 추천한다.Try(도전, P에 대한 해결책 등으로 다음번에 보완하거나 시도할 부분)엔티티를 너무 많이 만들고 관계도 1:N, N:1, N:M(을 풀기위한 중간 엔티티) 여러가지를 사용한만큼 JPA를 잘 알고 사용해서 열심히 풀어나가면 되는 문제이고, SSR대신 CSR로 해서 내가 익숙한 Vue보다는 React with TS로 화면을 구성해보려고 한다.그리고 테스트코드도 좀 더 다양한 방법으로 도전해보면 어떨까싶다(TODO).예를 들면 TestContainer라던지.. 아니면 MockMVC대신에 RestAssured(또는 RestAssuredMockMvc), WebTestClient등을 사용해볼 수도 있겠고 RestDocs 또는 RestDocs와 Swagger를 함께 사용하는 restdocs-api-spec를 써볼수도 있을 것 같다.일단 큰 목표는 마음과 머릿속 한켠에 자리를 잡아두고 MVP(Minimum Viable Product)라고 불리는 최소 기능 제품을 만들어서 정상작동하는데 문제가 없는 제품을 만들고 고도화를 통해서 기능개선 또는 기능추가, 사용성개선 등을 생각해보는게 맞지 않나 싶다!

백엔드인프런워밍업클럽3기프로젝트KotlinSpringboot스프링

xx

[인프런 워밍업 클럽 3기 CS] 운영체제 2주 차 과제

1. FIFO 스케줄링의 장단점이 뭔가요?장점프로세스를 요청 순서대로 처리하므로 구현이 간단하다. 먼저 도착한 프로세스가 먼저 실행되므로 기아 상태(Starvation)가 발생하지 않는다.단점실행 시간이 긴 프로세스가 먼저 도착하면 뒤의 짧은 프로세스들이 오래 기다려야 하는 문제가 발생할 수 있다. CPU 사용률이 떨어진다. 2. SJF를 사용하기 여러운 이유가 뭔가요?프로세스의 종료 시간을 예측하기 어렵다.Burst Time이 긴 프로세스는 영원히 실행되지 않을 수 있다.  3. RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요?타임 슬라이스가 너무 작으면 컨택스트 스위칭이 자주 발생하여 오버헤드가 커진다. 실제로 작업 처리보다 스케줄링 오버헤드가 커서 전체적인 성능이 저하된다. 4. 운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요?CPU 점유 시간을 기반으로 레벨을 조정해 CPU를 많이 사용하는 프로세스는 낮은 우선순위 큐로 이동하고, I/O 중심 프로세스는 높은 우선순위 큐에 머무르는 방식으로 동작한다.I/O 요청을 자주 발생시키는 프로세스는 CPU 사용 시간이 짧고, 반대로 CPU Bound Process는 긴 CPU 실행 시간을 가진다. 5. 공유자원이란무엇인가요?프로세스 간 통신을 할 때 공동으로 이용하는 변수나 파일 등공유자원은 여러 프로세스가 공유하기 때문에 각 프로세스의 접근 순서에 따라 결과가 달라질 수 있다.컨텍스트 스위칭으로 시분할 처리를 하기 때문에 어떤 프로세스가 먼저 실행되고 나중에 실행되는지 예측하기 어렵다. 6. 교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야할까요?상호배제: 어떤 프로세스가 한 리소스를 점유했다면 그 리소스는 다른 리소스에게 공유되면 안 된다.비선점: 프로세스 A가 리소스를 점유하고 있는데 프로세스 B가 빼앗을 수 없어야 한다.점유와 대기: 어떤 프로세스가 리소스 A를 가지고 있는 상태에서 리소스 B를 원하는 상태여야 한다.원형 대기: 점유와 대기를 하는 프로세스들의 관계가 원형을 이루고 있는 것

xx 2일 전
채널톡 아이콘