블로그

대롱대롱

[인프런 워밍업클럽 CS 2기] 1주차 미션

첫째주 미션입니다하나씩 풀어보겠습니다.운영체제위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다. 이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다. 이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요?A. 폴링방식의 성능 문제 해결에는 '인터럽트'를 사용하면 됩니다. 인터럽트는 비동기적으로 동작하기 때문에 성능에 이점이 있어요. 프로그램과 프로세스가 어떻게 다른가요?A. 프로그램은 저장장치에 저장된 명령문의 집합체로 '애플리케이션(앱)'이라 불리기도 합니다. Window에서는 .exe 파일의 형태를 보입니다. 저장장치만 사용하는 '수동적인 존재'입니다.프로세스는 실행중인 프로그램을 의미하는데 프로그램이 '메모리'에 올라갔을 때를 의미합니다. 프로그램과는 다르게 '능동적인 존재'이기도 합니다. 멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?A. 멀티프로그래밍은 메모리에 여러개의 프로세스가 올라온 것을 의미합니다. 멀티프로세싱은 CPU가 여러 프로세스를 처리하는 것을 의미하는데 이때 CPU는 시분할 처리로 각각의 프로세스를 짧은 시간 동안 교대로 실행합니다.) 운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?A. 프로세스 관리를 위해 'PCB'를 사용합니다. 프로세스가 만들어지면 운영체제는 PCB를 만들어 프로세스의 정보를 저장합니다. 만약 프로세스가 종료되면 운영체제는 해당 프로세스의 PCB를 제거합니다. PCB에는 포인터, 프로세스상태, 프로세스ID, 프로그램Counter, 레지스터 정보, 메모리 관련정보, CPU스케줄링 정보 등의 다양한 정보를 저장하고 있는 구조입니다. 컨텍스트 스위칭이란 뭔가요?A. Context Switching은 프로세스를 실행하는 중에 다른 프로세스를 실행하기 위해 실행중인 프로세스의 상태는 저장하고 다른 프로세스의 상태값으로 교체하는 작업을 의미합니다.CPU 점유시간이 다 되었거나, 입출력 요청이 있거나, 다른 종류의 interupt가 있을 때 context switching을 합니다. 자료구조여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다. 이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요.A. 학생의 정보를 저장하고 열람하기 위해서 '딕셔너리'를 사용할 것 같아요. 학생이름을 key로 하고 학생정보를 value로 해서 학생의 이름과 정보를 저장하고 열람하기 편하게 만들 것 같아요. 딕셔너리는 데이터 탐색, 삽입, 삭제가 쉽기 때문에 학생 정보를 관리하기에 적합하다고 생각합니다. 여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요.A. 고객의 주문을 들어온 순서대로 처리하기 위해서 FIFO 구조인 '큐'를 선택할 것 같아요. 큐는 FIFO(First In First Out)로 먼저 들어온 데이터가 먼저 나가게 하는 자료구조이기 때문에 위와 같은 목적에 적합할 것 같습니다.

애플민트

[워밍업 클럽_CS 전공 스터디 2기] 1주차 발자국

강의 수강요약운영체제운영체제, CPU, 프로세스 등이 무엇인지에 대한 개념을 익혔고, 또 운영체제는 프로세스를 어떻게 관리하는 지에 대해 학습하였습니다.그 과정 속에서 메모리를 효율적으로 사용하고, CPU 성능을 향상시키기 위해 고려해야할 조건들에 대해 생각해볼 수 있었습니다.자료구조와 알고리즘자료구조와 알고리즘에 대한 정의 및 시간 복잡도에 대한 이해를 바탕으로 7가지(배열, 연결 리스트, 스택, 큐, 해시테이블, 덱, 셋) 자료구조의 개념을 학습하고, 예제 코딩을 실습하였습니다.회고현업으로 일한 지 꽤 오래되었지만 기본적인 CS 지식이 현저히 낮았습니다. 그래서 CS 지식 공부의 필요성만 느끼고, 업무에 치여 미루던 것을 이번 기회에 마음먹고 도전한 제 자신에게 칭찬을 해주고 싶습니다.한 주마다 배우는 것을 잘 정리해서 시간이 날 때마다 복습하며 체득화 시키도록 노력하고자 합니다. 미션요약운영체제는 학습했던 개념에 대해 찬찬히 복기하면서 문제를 풀었고, 자료구조와 알고리즘은 문제 의도를 파악하고자 문제 내의 힌트들을 생각하면서 풀었습니다.회고평소엔 막연하게 자료구조와 알고리즘이 접근하기 어렵다고만 느껴서 학습을 중도 포기해왔는데 이 강의를 들으면서 처음으로 '재밌다!' 라고 느꼈습니다. 앞으로 남은 강의도 재미있게 수강하며 끝까지 완주하는 것이 목표입니다!

알고리즘 · 자료구조

애플민트

[워밍업 클럽_CS 전공 스터디 2기] 1주차 미션

운영체제1.while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 }위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다. 이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다. 이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요? 답변:인터럽트 방식을 사용합니다.프로그램과 프로세스가 어떻게 다른가요?답변:프로그램은 어플리케이션이나 exe 파일처럼 저장 장치에 저장된 명령문의 집합체이고, 프로세스는 메모리 위에 프로그램이 실행 중인 것을 말합니다.멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?답변: 멀티 프로그래밍은 메모리에 여러 개의 프로세스가 올라와 있는 것이고, 멀티 프로세싱은 CPU가 여러 개의 프로세스를 처리하는 것을 말합니다.운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?답변: 프로세스의 정보를 가지고 있는 PCB를 만들고, 저장합니다. PCB는 포인터, 프로세스 상태, 레지스터 정보, 메모리 관련 정보, CPU 스케쥴링 정보 등으로 구성되어 있습니다.컨텍스트 스위칭이란 뭔가요?답변: CPU에서 처리 중인 프로세스를 다른 프로세스로 교체하는 것을 말합니다. 자료구조와 알고리즘여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다.이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요. 답변: 배열을 선택하겠습니다. 우선 학생 수는 변동 사항이 크지 않고, 조회 및 수정하는 부분이 가장 많을 것이므로 인덱스를 이용해 빠르게 참조하고, 수정할 수 있는 배열이 적합하다고 생각합니다.여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요.답변: 들어온 순서대로 처리해야기 때문에 FIFO 선입선출 방식의 Queue(큐)를 선택하겠습니다. 

진이

[미션] 인프런 워밍업 클럽 2기 CS 1주차

운영체제 인터럽트 방식을 사용하는게 좋을 것 같습니다. 인터럽트 방식을 사용하면 스킬 사용 시점에만 CPU가 작업을 처리하므로 불필요한 반복 체크를 없앨 수 있고, 이벤트가 발생할 때만 즉시 반응하므로 성능에도 효율적으로 사용할 수 있을 것 같습니다.프로그램은 컴퓨터 관점에서 저장장치만 사용하는 수동적인 존재이고, 프로세스는 메모리도 사용하고 CPU도 사용하고 필요에 따라 입출력을 하는 능동적인 존재입니다.멀티프로그래밍은 메모리의 관점에서 메모리에 여러 개의 프로세스가 올라온 것이고,멀티프로세싱은 CPU의 관점으로 CPU가 여러 개의 프로세스를 처리하는 것입니다.프로세스 제어 블록(PCB, Process Control Block)에 저장하고, 이를 프로세스 테이블이라는 데이터 구조로 관리합니다.프로세스를 실행하는 중에 다른 프로세스를 실행하기위해 실행중인 프로세스의 상태를 저장하고 다른 프로세스의 상태값으로 교체하는 작업이다.자료구조와 알고리즘저는 배열을 사용할 것 같습니다, 학생의 정보는 학기 초에 일괄로 받은 후 정리해서 저장을 하기 때문에, 정보가 바뀔 일이 많이 없기 때문입니다. 또한 학생의 수는 정해져 있기 때문에 인덱스로 관리도 용이할 것 같고, 데이터 참조시에는 O(1)의 시간복잡도를 가지고 있기 때문입니다. 크기도 고정이기에 학생의 수가 변동이 크지않기에 배열을 선택하는게 낫다고 생각하였습니다.주문이 들어온 순서대로 처리가 된다면 선입선출의 구조로 되어있는 큐(Queue)를 사용할 것 같습니다. 큐는 말 그대로 먼저 들어 온 것이 먼저 나가기 때문에, 문제의 "들어온 순서대로 처리"에 맞다고 생각합니다. 

알고리즘 · 자료구조알고리즘자료구조워밍업클럽cs운영체제

대롱대롱

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

워밍업클럽 시작하고 처음 작성하는 발자국입니다강의 듣고 정리하다보니 일주일이 금방 지나가 버렸습니다-이번주에 공부한 내용의 키워드-운영체제운영체제 개요, 역사, 구조컴퓨터 하드웨어 구조, 컴퓨터의 부팅과정, 인터럽트프로그램&프로세스, 멀티프로그래밍&멀티프로세싱PCB, 프로세스 상태, 컨텍스트 스위칭, 프로세스 생성&종료, 쓰레드CPU스케줄링, 다중큐, 스케줄링목표, FIFO알고리즘&자료구조시간복잡도배열, 스택, 큐, 덱해시테이블, 셋-이번주에 공부한 내용 요약-운영체제컴퓨터의 다양한 기능 수행을 위해 필요한 "운영체제"는 프로세스 관리와 메모리 관리, 하드웨어 관리, 파일시스템 관리를 합니다어떻게 하면 CPU를 최대한 많이 사용할 수 있을까라는 고민 덕분에(?) 운영체제는 더욱 복잡하게 발전이 되었고 그렇게 해서 오늘날의 운영체제가 되었습니다.프로그램을 메모리 위에 올려서 실행하는데 이를 프로세스라고 부릅니다. 메모리 위에 올라간 프로그램은 운영체제가 관리합니다. 프로세스 정보는 PCB가 가지고 있어요.오늘날의 운영체제는 멀티 프로그래밍과 멀티 프로세싱을 합니다. CPU가 시분할 처리로 여러 프로세스를 교대로 실행하죠프로세스는 생성, 준비, 실행, 대기, 완료 상태의 5가지 상태로 구분할 수 있습니다. 입출력 요청한 프로세스가 대기상태가 되는데 대기상태인 동안 다른 프로세스에게 CPU를 할당합니다. 입출력작업이 끝나면 대기 상태였던 프로세스에게 CPU를 할당해서 CPU를 쉬지 않고 굴립니다.프로세스 여러개를 교대로 실행하는데 실행하는 프로세스의 상태를 저장하고 다른 프로세스의 상태값으로 교체하는 것이 Context Switching입니다. 이때 pcb내용이 변경됩니다.(pcb에 프로세스 정보 있으니까요)프로세스 수가 늘어날 수록 무거워지기 때문에 이를 해결하기 위해 '쓰레드'가 있습니다.(이 때 왜 크롬을 무겁다고 하는지 알 수 있었습니다;;;)프로세스 여러개 실행할 때 모든 프로세스에 CPU를 할당하고 해제하는 CPU스케줄링이 이루어집니다. 스케줄러는 CPU스케줄링을 할 때 여러 사항들을 고려해서 '잘' 스케줄링을 해야합니다.스케줄링 관리할 때 '다중큐'로 관리가 됩니다.(큐에는 PCB(프로세스 정보 가진 녀석)가 들어갑니다.)CPU스케줄링 알고리즘에는 여럿이 있지만 가장 초반의 알고리즘으로 FIFO(먼저 들어오면 먼저 CPU할당받는) 방식이 사용되었습니다. 알고리즘&자료구조프로그램은 자료구조와 알고리즘으로 구성됩니다.자료구조: 데이터가 어떻게 저장되고 사용될까알고리즘: 문제를 '확실하게' 해결하는 방법좋은 알고리즘으로 문제를 해결하고 싶은데 일반적으로 '알고리즘 속도'를 성능의 척도로 사용합니다. 그래서 '시간복잡도'를 사용합니다.성능평가에는 여러 기준이 있는데 최악의 경우를 따지는 '빅-오(bigO)' 방식을 가장 많이 사용합니다.빅-오 표기법으로 표기할 때는 계산에 가장 많은 영향을 미치는 항만 표기합니다(O(n), O(n^2))배열은 모든 프로그래밍 언어에서 기본적으로 제공하는 자료구조입니다. 읽고 쓰고 참조에는 너무 좋은데 데이터 삽입/삭제할때 성능이 안좋아요배열의 문제점을 해결해 줄 수 있는 것이 바로 '연결리스트'입니다.노드를 만들어서 데이터 저장하고 다른 노드와 연결한 구조입니다.데이터 삽입/삭제가 배열보다 쉬워요근데 데이터가 떨어져있어서 바로 접근은 못해요스택: FILO구조로 먼저 들어간 데이터가 나중에 나옵니다.연결리스트를 사용해서 한쪽(head)에만 데이터를 삽입하고 제거하면 구현가능합니다.큐: FIFO구조로 먼저 들어간 데이터가 먼저 나옵니다운영체제에서 사용되기도 합니다.(FIFO Scheduling)연결리스트로 구현가능합니다.(이중연결리스트 사용) head에서 데이터 추가하고 tail에서 데이터를 제거합니다.덱: 데이터 삽입/제거를 head/tail 두 군데에서 자유롭게 합니다.얘 이용하면 stack, queue모두 구현 가능해요 해시테이블해시=맵=해시맵=딕셔너리해시와 테이블(표)이 합쳐진 자료구조입니다.테이블의 인덱스를 만들어주는 '해시함수'가 중요한 역할을 합니다.데이터 탐색, 삽입,삭제가 쁠지만 공간효율성이 안좋은 점이 단점입니다.셋데이터의 중복을 허용하지 않은 자료구조로 해시테이블을 사용하기도 합니다(그래서 '해시셋'으로 불리기도!)해시테이블의 value는 사용하지 않고 key만 사용해서 구현합니다.-간단한 이번 주 회고-강의가 다들 짧아서 금방 듣고 끝날 줄 알았는데 내용이 생각보다 많고(1차당황), 정리할 것도 많고(2차당황) 그래서 시간이 생각보다 오래 걸렸습니다. 정리하는 것을 하루만 밀려도 양을 감당하기 어려우니 하루하루 꾸준하게 정리하는 것이 최선입니다. 다행히도 그날 해야하는 것은 그날 끝내서 공부할 것이 밀리지 않아 다행입니다. 이번 주에 시간관리가 중요함을 깨달았으니 다음 주는 이번 주의 경험을 바탕으로 더 잘 공부하고 정리할 수 있을 것 같아요. 다음 주 내용도 만만치 않으니 하루하루 꾸준하게 공부하며 내 것으로 만드는 작업을 해야겠습니다. 복습도 꾸준하게 해서 잊지 말아야겠어요.

알고리즘자료구조운영체제

진이

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

자료구조와 알고리즘처음에는 막연하게 이해 못했던 것들도 강의를 듣다보니 이해가 되었고, 자료구조의 종류와 장단점을 알 수 있게 된게 좋았던것 같다. 매번 이유없이 그냥 사용했던 것들이 이제는 어떻게 실행이 되고, 어떤식으로 굴러가는지? 이런 상황에서는 어떤 자료구조를 사용해야하는지, 아직은 초반이라 한번 듣고 완전 이해한 건 아니지만 하나하나 공부해가는 재미가 있는 것 같다.배열 : 모든 프로그래밍 언어에서 기본적으로 제공하는 자료구조연결리스트 : 빈 메모리 공간 아무곳에 데이터를 생성하고 연결스택 : FILO(First In Last Out)큐 : FIFO(First In Fast Out)덱 : 양쪽에서 삽입과 삭제가 가능,스택과 큐의 연산을 모두 지원해시테이블 : (Key, Value)로 데이터를 저장셋 : 데이터의 중복을 허용하지 않는 자료구조  운영체제운영체제는 언제 한번 공부하고 싶었던 부분인데 좋은 기회로 듣게되어 오히려 자료구조보다 더 빨리 들었던 것 같다.운영체제의 구조는 어떻게 되어있는지 하드웨어가 뭔지 아직까지 처음 듣는 내용이지만서도 재밌게 듣고있다.회고칭찬하고 싶은 점ㅎㅎ ;; 아직 없다 ..아쉬웠던 점내일배움캠프와 같이 진행중이라, 시간이 많지않아 강의를 매일매일 챙겨보지못해 밀리는게 매우 아쉽다.또한 아직까지 기본적인 개념이 자리잡지 않은 것 같은 느낌이 들었다.보완할 점새벽까지하더라도 밀리지 않게 강의를 듣는게 좋을 것 같다. 또한 내용은 여러번 반복해서 !평일에 밀리지 않게 들은 후 주말에는, 저번 주에 들었던 내용 + 이번 주 내용 배속으로 한번 더 듣는걸로 해야겠다.

알고리즘 · 자료구조워밍업클럽운영체제알고리즘자료구조cscs스터디

Jay

워밍업 클럽 CS 1주차 발자국 : 미션

운영체제1. 아래 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다. 이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다. 이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요?while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 }인터럽트를 활용할 수 있습니다.CPU는 입출력 관리자에게 입출력 명령을 내리고, 이 과정에서 다른 작업을 계속 수행할 수 있습니다.입출력 관리자는 입출력이 완료되면 CPU에게 신호를 보내고, CPU는 이 신호를 수신하여 서비스 루틴(Interrupt Service Routine, ISR)을 실행해 작업을 완료합니다.여기서 서비스 루틴이란 특정 인터럽트가 발생했을 때 해당 인터럽트를 처리하기 위해 실행되는 함수를 말합니다.(이 때, “특정 인터럽트가 발생했을 때 해당 인터럽트를 처리한다”는 것은 CPU가 어떤 특정한 이벤트(인터럽트)를 감지하고, 그 이벤트에 따라 미리 정의된 작업, 즉 서비스 루틴을 실행하는 과정을 의미합니다)인터럽트는 비동기적으로 동작하기 때문에 성능을 개선할 수 있는 이점이 있습니다.이와 같이 인터럽트를 사용하면 폴링 방식보다 더 효율적으로 스킬 사용 여부를 체크할 수 있으며, CPU 자원을 보다 효과적으로 활용할 수 있습니다. 2. 프로그램과 프로세스가 어떻게 다른가요?프로그램은 하드디스크나 SSD와 같은 저장장치에 저장된 명령어와 데이터의 집합입니다. 예를 들어, 애플리케이션이나 앱도 프로그램에 해당됩니다. 프로그램은 그 자체로는 실행되지 않으며, 컴퓨터가 실행할 준비 상태에 있는 정적인 존재입니다.프로세스는 실행 중인 프로그램을 의미합니다. 저장장치에 있던 프로그램이 메모리에 로드되어, 운영체제의 제어를 받으며 CPU, 메모리 등 컴퓨터 자원을 활용해 작업을 수행하는 능동적인 존재입니다. 프로세스는 CPU 스케줄링을 통해 처리되고, 필요에 따라 입력 및 출력 작업도 수행합니다. 3. 멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?멀티프로그래밍은 하나의 CPU가 여러 프로세스를 시분할 방식으로 처리하는 메모리 관리 개념입니다.멀티프로세싱은 여러 CPU가 각기 다른 프로세스를 병렬로 처리하는 CPU 관리 개념입니다.멀티프로그래밍은 메모리 관점에서 여러 프로그램(또는 프로세스)이 동시에 메모리에 올라와 있는 상태를 말합니다. 운영체제는 이 프로그램들 중 하나가 CPU를 사용할 수 없을 때(예: 입출력 작업 대기 시) 다른 프로그램이 CPU를 사용할 수 있도록 하여 자원의 효율성을 높입니다. 즉, 하나의 CPU가 여러 프로그램을 시분할 방식으로 실행하는 것을 말합니다. 멀티프로그래밍의 반대 개념은 유니프로그래밍, 즉 한 번에 하나의 프로그램만 메모리에 올라오는 방식입니다.멀티프로세싱은 CPU 관점에서 둘 이상의 CPU가 동시에 여러 프로세스를 처리하는 것을 의미합니다. 멀티프로세싱 시스템에서는 각 CPU가 독립적으로 다른 작업을 수행할 수 있기 때문에 작업 처리 속도와 시스템의 효율성이 크게 향상됩니다. 이는 다중 CPU 또는 코어를 활용하는 시스템에서 이루어지며, 이를 통해 여러 프로세스가 동시에 병렬로 처리될 수 있습니다. 4. 운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?운영체제는 프로세스 제어 블록(PCB: Process Control Block)을 사용하여 여러 개의 프로세스를 관리합니다. 각 프로세스가 실행 중일 때, 운영체제는 해당 프로세스의 상태와 정보를 PCB에 저장하여 추적하고 관리합니다.프로세스가 생성되면 운영체제는 그 프로세스에 대한 고유한 PCB를 생성합니다. 이 PCB에는 다음과 같은 주요 정보들이 포함됩니다:프로세스 ID (PID): 프로세스의 고유 식별자프로세스 상태: 실행, 대기, 준비 등 현재 상태CPU 레지스터 정보: 프로세스가 CPU에서 작업을 하던 도중의 상태(레지스터 값)메모리 관리 정보: 프로세스의 코드, 데이터, 스택 등이 저장된 메모리 영역 정보입출력 상태 정보: 입출력 요청이나 장치 사용 상황우선순위: 프로세스의 우선순위에 따른 스케줄링 정보운영체제는 이 PCB들을 연결 리스트(또는 다른 자료구조)로 관리하여, 여러 프로세스를 효율적으로 스케줄링하고 제어합니다. PCB는 각 프로세스의 상태를 기억하기 때문에 프로세스가 CPU를 사용하다가 중단될 때, 해당 프로세스의 정보를 PCB에 저장하고, 나중에 다시 해당 프로세스가 CPU를 사용할 때 이전 상태에서부터 이어서 작업할 수 있습니다.프로세스가 종료되면 운영체제는 해당 프로세스의 PCB를 연결 리스트에서 제거하고 메모리에서 해제하여 자원을 회수합니다. 5. 컨텍스트 스위칭이란 뭔가요?CPU가 한 프로세스에서 다른 프로세스로 전환할 때 수행되는 작업입니다. CPU는 여러 프로세스를 동시에 처리할 수 없기 때문에, 하나의 프로세스를 실행하다가 다른 프로세스를 실행하려면 현재 프로세스의 상태를 저장하고 새로운 프로세스의 상태를 복구해야 합니다. 이러한 상태 정보는 프로세스 제어 블록(PCB)에 저장됩니다.컨텍스트 스위칭 과정은 다음과 같습니다:현재 실행 중인 프로세스의 상태 저장: CPU는 현재 실행 중인 프로세스의 상태(프로그램 카운터, 레지스터 값, 메모리 관리 정보 등)를 PCB에 저장합니다. 이렇게 하면 나중에 이 프로세스를 다시 실행할 때, 중단된 지점부터 작업을 이어서 할 수 있습니다.새로운 프로세스의 상태 로드: 다음으로 실행할 프로세스의 PCB에서 저장된 상태 정보를 CPU에 로드합니다. 이때 새로운 프로세스가 실행되기 위한 프로그램 카운터, 레지스터 값, 메모리 정보 등을 CPU가 가져옵니다.CPU 전환: CPU는 이제 새로운 프로세스의 명령어를 실행하며 작업을 이어나갑니다.컨텍스트 스위칭은 필수적인 작업이지만, 오버헤드가 발생합니다. 이 과정은 비교적 짧은 시간이 걸리지만, 불필요하게 자주 발생하면 CPU가 실제 작업보다는 프로세스 전환에 더 많은 시간을 소모할 수 있습니다.따라서 컨텍스트 스위칭은 효율적인 CPU 자원 관리와 동시성 유지를 위한 필수적인 메커니즘이지만, 너무 빈번하게 발생하지 않도록 스케줄러가 잘 조정해야 합니다.  자료구조와 알고리즘1. 여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다. 이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요.해시 테이블(Hash Table)을 사용하겠습니다. 해시 테이블은 해시 함수를 사용해 데이터를 효율적으로 저장하고 검색할 수 있는 자료구조입니다. 해시 함수를 통해 학생 정보(예: 학생 ID)를 키로 변환하고, 해당 키에 맞는 위치에 데이터를 저장합니다.이 자료구조의 장점은 데이터의 삽입, 수정, 삭제, 검색이 평균적으로 O(1)의 시간 복잡도를 가지기 때문에 매우 빠릅니다. 따라서 학생 정보가 많더라도, 특정 학생의 정보를 빠르게 조회하거나 수정할 수 있습니다. 또한, 해시 테이블은 중복을 허용하지 않으므로 학생 ID와 같은 고유 식별자를 기반으로 데이터 관리가 용이합니다.그러나 해시 테이블의 단점으로는 충돌 관리가 필요하다는 점이 있습니다. 해시 함수가 서로 다른 데이터를 동일한 해시 값으로 변환할 경우, 이를 해결하기 위한 방법(체이닝 또는 오픈 어드레싱 등)을 구현해야 합니다. 하지만 전체적으로 성능과 효율성 측면에서 학생 관리 프로그램에 적합합니다. 2. 여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요.큐(Queue)를 선택하겠습니다. 큐는 FIFO(First In, First Out) 구조로, 먼저 들어온 데이터가 먼저 처리되는 자료구조입니다. 주문 처리는 보통 고객이 주문한 순서대로 처리되어야 하기 때문에 큐는 자연스럽게 이러한 요구 사항을 충족시킵니다.큐에서 데이터 삽입(Enqueue)은 뒤쪽에서 이루어지고, 데이터 삭제(Dequeue)는 앞쪽에서 이루어지기 때문에 주문이 들어온 순서대로 처리가 보장됩니다. 즉, 프로그램이 새로운 주문을 받을 때는 큐의 뒤에 추가하고, 주문을 처리할 때는 큐의 앞에서 데이터를 꺼내 처리합니다.큐는 또한 O(1)의 시간 복잡도로 삽입과 삭제 작업이 이루어지기 때문에, 대량의 주문이 처리될 때에도 효율적으로 관리할 수 있습니다. 이 구조 덕분에 고객 주문의 공평한 처리와 성능 측면에서 매우 유리합니다.

미션CS

Jay 1개월 전
유선아

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

한줄 평자료구조 및 알고리즘 에서는 배열, 연결리스트, 스택(Stack), 큐(Queue), 덱(Deque), 해시 테이블(Hash Table), 셋(Set)등의 개념에 대해서 공부했다. 특히 실생활에서의 예를 들어 설명을 해주셔서 더욱 쉽게 이해할 수 있었다.운영체제는 거의 처음 공부해보는 것이어서 낯선 부분도 있었고, 새롭게 알게 되어 흥미로운 부분도 있었다. 학습 했던 내용 요약자료구조 및 알고리즘 배열: 읽기, 쓰기와 같은 참조에는 O(1)의 성능을 가지고, 삭제에서는 O(n)의 성능을 가진다.연결리스트: 배열과 달리 크기가 동적이지만, 데이터 참조 및 삭제에서 모두 O(n)의 성능을 가진다.스택 : FILO 구조를 가진다.큐 : 스택과 반대로 FIFO 구조를 가진다.덱 : 데이터 삽입 제거를 head, tail 모두에서 이룰 수 있는 자료구조.해시 테이블 : (Key, Value)로 데이터를 저장하는 자료구조. 해시 함수는 키를 해시 값으로 변환하는 함수인데, 해시 함수는 키를 고르게 분포시키고, 충돌을 최소화해야 한다.셋 : 데이터의 중복을 허용하지 않는 자료구조이다.운영체제운영체제의 구조 : 커널, 사용자(인터페이스를 통해), 애플리케이션(시스템 콜통해), 하드웨어(드라이버 통해)컴퓨터 하드웨어 구조 : CPU와 메모리 필수!CPU의 구조 : 산술논리 연산장치, 제어장치, 레지스터메모리 구조 : RAM, ROM인터럽트 : 폴링방식을 해결한 방식 프로세스와 쓰레드 : 프로세스(실행중인 프로그램), 프로세스(운영체제가 작업을 처리하는 단위)PCB : 운영체제가 프로세스를 관리할 때 이를 활용프로세스 상태 : 생성, 준비, 실행, 대기 , 완료컨텍스트 스위칭 : 프로세스를 실행하는 중에 다른 프로세스를 실행하기 위해, 실행 중인 프로세스의 상태를 저장하고, 다른 프로세스의 상태값으로 교체하는 작업회고일주일 동안 스스로 칭찬하고 싶은 점일중일치 시간표 대로의 진도대로 인강을 다 수강하고, 미션과 발자국도 기한내에 진행한 점.아쉬웠던 점토요일까지로 미션과 발자국을 미리 완수하고 싶었는데, 그렇지 못한 점. 일주일의 진도는 밀리지 않았지만, 하루하루 진도는 정확히 일치하게 수행하지는 못한 점보완하고 싶은 점매일 시간표대로 진도를 나가고 싶다. 구현 강의부분에서 스스로 먼저 해보고 강의를 들었어야 했다는 아쉬움이 있다.인강을 듣고, 추가로 궁금한 사항이나 활용해보는 부분을 더 진행하고 싶다.다음주 학습 목표진도를 누락하지 않고 인강을 수강하기구현 부분을 먼저 스스로 해보고, 강의 듣기개념에 대해서 더 깊게 찾아보거나, 코드로 활용가능한 부분들은 더 활용 해보기  출처 : 그림으로 쉽게 배우는 운영체제 - 감자 , 그림으로 쉽게 배우는 자료구조와 알고리즘 (기본편)- 감자

알고리즘 · 자료구조워밍업클럽운영체제자료구조알고리즘CS발자국

유선아

[미션] 인프런 워밍업클럽 CS 2기 1주차 미션

운영체제 1. while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 } 위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다. 이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다. 이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요? 인터럽트 방식을 이용해야합니다.CPU가 입출력 관리자에게 입출력 명령을 내리고 CPU는 다른 작업을 계속 하고, 입출력관리자가 입출력이 완료됐을 때, CPU 에게 신호를 주면, CPU는 그 신호를 받아 인터럽트 서비스 루틴 ISR을 실행시켜 작업을 완료합니다. 즉, CPU가 주기적으로 진행상황을 계속 확인할 필요가 없기 때문에 성능의 이점이 생깁니다. 프로그램과 프로세스가 어떻게 다른가요?프로그램은 하드디스크 등과 같은 저장장치에 저장된 명령문의 집합체입니다.프로세스는 프로그램이 메모리에 올라갔을 때, 실행중인 프로그램을 프로세스라고 합니다.멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?멀티프로그래밍은 메모리에 여러개의 프로세스가 올라온 것이고 메모리에 관점에서 정의된 것 이고,멀티프로세싱은 CPU가 여러개의 프로세스를 처리하는 것으로 CPU관점에서 정의한 것 입니다. 운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?운영체제는 프로세스의 정보를 가지고 있는 PCB를 사용해 프로세스를 관리한다. 운영체제는 프로세스가 만들어지면 해당 프로세스의 정보를 가지고 있는 PCB 을 만들고 저장 하고,(PCB에는 포인터, 프로세스 상태, 프로세스 ID, 프로그램 카운터, 레지스터 정보, 메모리 관련 정보, CPU스케줄링 정보등이 저장된다.)PCB들은 연결리스트라는 자료구조로 저장되고, 운영체제는 프로세스가 종료되면 연결리스트에서 해당 프로세스의 PCB를 제거한다. 컨텍스트 스위칭이란 뭔가요?컨텍스트 스위칭이란 프로세스를 실행하는 중에 다른 프로세스를 실행하기 위해, 실행 중인 프로세스의 상태를 저장하고, 다른 프로세스의 상태값으로 교체하는 작업입니다. 현재 작업 중이던 프로세스의 작업 내용을 PCB에 저장하고, 실행 할 프로세스의 PCB를 가져와 그 정보를 참조하여 CPU가 다시 세팅되어 이어서 실행됩니다.  자료구조와 알고리즘 여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다. 이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요. 배열을 선택할 것입니다.보통 학생의 정보는 학기 초에 일괄적으로 저장한 다음, 그 이후에 정보를 확인하고 찾는 작업이 주를 이루고 학생의 정보가 추가되거나 수정되는 일은 자주 일어나지 않기 때문입니다. 학생 번호는 인덱스로 두어 인덱스로 학생의 정보를 쉽게 찾을 수 있을 것 같다고 생각하기 때문에 읽기 기능이 O(1)의 성능을 가진 배열을 이용하는 것이 좋을 것 같습니다. 여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요. Queue 자료구조를 선택할 것입니다.Queue는 FIFO(first in first out)으로 먼저 들어간 데이터가 먼저 쓰이는 데이터 구조이기 때문에 주문 들어온 순서대로 처리하기 위해 적합하다고 판단 되기 때문입니다.

알고리즘 · 자료구조워밍업클럽운영체제자료구조알고리즘CS미션

서채영

[인프런 워밍업클럽 CS 2기] 1주차 미션

 운영체제1.while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 }위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다.이 방식은 폴링방식입니다.1초마다 체크하기 때문에 성능에 좋지 않습니다.이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요?비동기 방식인 인터럽트를 사용해야 합니다. 2. 프로그램과 프로세스가 어떻게 다른가요?프로그램은 애플리케이션, 앱, .exe와 같이 저장장치에 저장된 집합체들을 의미합니다.프로세스는 실행 중인 프로그램을 의미하고, 메모리에 프로그램이 올라갔을 때를 말합니다. 3. 멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?멀티프로그래밍은 메모리에서 여러 프로세스가 올라가서 실행되는 것이고,멀티프로세싱은 CPU에서 여러 프로세스가 처리되는 것입니다. 4. 운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?PCB를 사용하여 관리합니다. 5. 컨텍스트 스위칭이란 뭔가요?특정 프로세스 실행 중에 다른 프로세스를 실행하기 위해 해당 정보를 저장하고, 다른 프로세스로 상태값을 교체하는 것을 말합니다. 자료구조와 알고리즘1. 여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다.이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요?이유를 함께 적어주세요. 해시테이블을 사용하겠습니다. 키 값을 이용해서 관리하고 접근과 수정이 용이하기 때문입니다 2. 여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다.주문은 들어온 순서대로 처리됩니다.이 때 여러분이라면 어떤 자료구조를 선택하실 건가요?이유를 함께 적어주세요.주문이 들어온 순서대로 처리해야 한다면 선입선출인 FIFO, 큐를 선택하겠습니다. 

Jay

워밍업 클럽 CS 1주차 발자국 : 운영체제

운영체제 들어가기운영체제 개요운영체제(OS, Operating System)는 컴퓨터 하드웨어와 사용자 간의 중개자 역할을 하는 소프트웨어입니다.컴퓨터 자원(CPU, 메모리, 디스크, 네트워크 등)을 효율적으로 관리하고, 사용자와 응용 프로그램이 하드웨어를 쉽게 사용할 수 있도록 도와주는 역할을 합니다. 운영체제는 여러 작업을 동시에 처리할 수 있도록 프로세스를 관리하고, 파일 시스템, 네트워크 통신, 보안 등을 담당하며, 하드웨어 장치와 소프트웨어 간의 인터페이스 역할도 합니다.운영체제가 하는 주요 기능:1. 프로세스 관리: 실행 중인 프로그램(프로세스)을 관리하고, 여러 프로세스가 동시에 실행될 수 있도록 스케줄링과 자원 배분을 조절.2. 메모리 관리: 실행 중인 프로그램들이 메모리를 효율적으로 사용하도록 조정하고, 메모리 간 충돌을 방지.3. 하드웨어 관리: CPU, 메모리, 디스크, 입출력 장치 등의 하드웨어 자원을 관리하고, 응용 프로그램이 이 자원에 접근할 수 있도록 인터페이스를 제공.4. 파일 시스템 관리: 데이터를 파일 단위로 저장하고, 사용자가 이를 읽고 쓸 수 있도록 파일 관리 시스템을 제공.5. 보안 및 접근 제어: 시스템 자원에 대한 접근을 제어하고, 권한을 부여해 사용자의 보안을 유지.운영체제는 다양한 하드웨어를 제어하며 컴퓨터 시스템의 효율성과 안정성을 보장하는 중요한 소프트웨어입니다. 대표적인 운영체제에는 윈도우(Windows), 리눅스(Linux), 맥OS(macOS) 등이 있습니다. 운영체제 역사운영체제는 애니악 같은 초기 컴퓨터부터 발전해 왔습니다. 초기에는 입출력 작업과 같은 기본 기능만 수행했지만, 시분할 시스템의 도입으로 멀티프로그래밍과 다중 사용자 환경이 가능해졌고, 이 시기에 유닉스가 탄생했습니다. 이후, 개인용 컴퓨터가 상용화되면서 현대의 운영체제가 발전했습니다.운영체제는 CPU 사용률을 높이고 비용을 절감하려는 노력에서 시작되었습니다. 운영체제의 구조운영체제의 구조는 커널, 사용자 인터페이스, 하드웨어와의 상호작용으로 나눌 수 있습니다.커널(Kernel): 운영체제의 핵심으로, 프로세스, 메모리, 저장장치를 관리합니다. 커널은 사용자가 직접 접근할 수 없으며, 커널이 사용자로부터 자신을 보호하기 위한 인터페이스인 시스템 콜을 통해 응용 프로그램과 소통합니다.사용자 인터페이스: 사용자와 커널 간의 상호작용을 위해 GUI(그래픽 사용자 인터페이스)나 CLI(명령 줄 인터페이스)를 제공합니다. 사용자는 시스템 콜을 통해 커널의 기능을 요청합니다.하드웨어와의 상호작용: 커널은 디바이스 드라이버를 사용하여 하드웨어를 제어합니다. 드라이버는 하드웨어와 커널 간의 통신을 담당하며, 기본적인 드라이버는 커널에 포함되지만 복잡한 장치는 제조사에서 제공하는 드라이버를 설치해야 합니다. 컴퓨터 하드웨어와 구조오늘날의 대부분의 컴퓨터는 프로그램 내장 방식의 폰 노이만 구조를 따릅니다. 과거의 애니악 같은 컴퓨터는 하드웨어로 프로그램을 구성해야 했으며, 프로그램 변경 시마다 스위치와 배선을 재조정하는 불편함이 있었습니다.폰 노이만 구조의 주요 요소:CPU: 중앙 처리 장치로, 모든 연산과 제어를 담당합니다.BUS: 데이터를 전달하는 통로 역할을 합니다.메모리 (RAM): 프로그램을 실행하기 위해 메모리에 올리는 방식입니다. 프로그램이 메모리에 내장되어 실행되므로, 소프트웨어만 교체하면 됩니다.메인보드:하드웨어 연결 장치: 다양한 하드웨어를 연결하여 통합하는 역할을 합니다.데이터 전송: 장치 간의 데이터 전송은 메인보드의 버스가 담당합니다.CPU는 크게 산술논리 연산장치(ALU), 제어장치(Control Unit), 레지스터(Register)로 나눌 수 있습니다:산술논리 연산장치 (ALU):CPU에서 실제 데이터 연산을 수행하는 장치로, 산술 연산(덧셈, 뺄셈 등)과 논리 연산(AND, OR, NOT 등)을 처리합니다.제어장치 (Control Unit):CPU 내 모든 장치의 동작을 지시하고 제어하는 역할을 하며, 프로그램 명령어를 해석하여 ALU와 레지스터 등 다른 장치의 동작을 조정합니다.레지스터 (Register):CPU 내부에서 계산을 위해 임시로 데이터를 보관하는 장치로, 변수를 저장하는 역할을 합니다. 레지스터는 빠른 데이터 접근 속도를 제공합니다.메모리는 크게 RAM과 ROM으로 구분되며, 각각의 특징은 다음과 같습니다:RAM (Random Access Memory):저장된 위치와 관계없이 읽는 속도가 일정합니다.휘발성 메모리로, 전원이 꺼지면 데이터가 사라집니다.주로 메인 메모리로 사용되어, 현재 실행 중인 프로그램과 데이터를 임시로 저장합니다.ROM (Read Only Memory):비휘발성 메모리로, 전원이 꺼져도 데이터가 유지됩니다.데이터가 한 번 쓰이면 수정할 수 없습니다.주로 컴퓨터 부팅과 관련된 BIOS를 저장하는 데 사용됩니다. 컴퓨터 부팅 과정전원 공급: 컴퓨터 전원이 켜지면 하드웨어에 전력이 공급되고, 프로세서가 초기화되면서 부팅이 시작됩니다.BIOS 실행: 컴퓨터의 메인보드에 내장된 ROM(Read-Only Memory)에 저장된 BIOS(Basic Input/Output System)가 실행됩니다. BIOS는 컴퓨터의 기본적인 입출력 기능을 담당하며, 부팅 초기 단계에서 중요한 역할을 합니다.POST(전원 켠 후 자가 테스트): BIOS는 POST(Power-On Self Test)를 수행하여 CPU, 메모리, 키보드, 마우스, 그래픽 카드, 하드디스크 등 주요 하드웨어 장치가 정상적으로 작동하는지 확인합니다. 문제가 있으면 오류음을 내거나 화면에 오류 메시지를 표시하고, 부팅이 중단됩니다.부트로더 로드: 하드웨어 점검이 완료되면, BIOS는 저장 장치(주로 하드디스크 또는 SSD)에서 MBR(Master Boot Record)을 찾아 실행합니다. MBR에는 컴퓨터의 첫 번째 부팅 섹터와 부트로더가 저장되어 있습니다.부트로더 실행: MBR에서 불러온 부트로더는 설치된 운영체제들을 확인하고, 사용자가 부팅할 운영체제를 선택할 수 있도록 합니다. 예를 들어, 컴퓨터에 윈도우와 리눅스가 함께 설치되어 있으면 운영체제 선택 화면이 표시됩니다.운영체제 로드: 사용자가 운영체제를 선택하거나 기본 운영체제가 하나만 있으면, 선택된 운영체제가 하드디스크에서 메모리로 로드됩니다. 이때 운영체제의 커널이 메모리에 올라가며, 운영체제가 컴퓨터를 제어하기 시작합니다.바탕화면 표시: 운영체제가 성공적으로 로드되면, 모니터에 바탕화면이 표시되고, 사용자 인터페이스(UI)가 준비됩니다. 이 시점부터는 사용자가 응용 프로그램을 실행하고, 운영체제가 이를 관리하게 됩니다.  인터럽트인터럽트는 CPU가 입출력 장치와 상호작용할 때 발생하는 중요한 개념입니다.1. 입출력 작업 시작: CPU가 입출력 작업이 들어오면 입출력 관리자에게 명령을 내립니다.2. 폴링 방식CPU는 입출력 명령의 완료 여부를 주기적으로 체크해야 합니다. 이 방식을 폴링(Polling)이라고 합니다.단점: CPU가 자주 확인해야 하므로 성능이 저하됩니다.3. 인터럽트의 도입인터럽트는 폴링의 단점을 해결하는 방식입니다.CPU는 입출력 명령을 내린 후 다른 작업을 계속 수행합니다.입출력 관리자가 작업이 완료되면 CPU에 신호를 보내고, CPU는 이 신호를 수신하여 인터럽트 서비스 루틴(ISR)을 실행하여 작업을 완료합니다.ISR (인터럽트 서비스 루틴):특정 인터럽트가 발생했을 때 그 인터럽트를 처리하는 함수입니다.인터럽트의 장점:인터럽트는 비동기적으로 동작하여 CPU의 성능을 높이는 데 도움을 줍니다.인터럽트의 종류 : 하드웨어 인터럽트: 입출력 장치에서 발생합니다.소프트웨어 인터럽트: 사용자 프로그램에서 발생하며, 예를 들어 0으로 나누기 또는 유효하지 않은 명령어에 접근할 때 발생합니다.프로세스와 스레드프로그램과 프로세스프로그램:하드디스크와 같은 저장장치에 저장된 명령문의 집합체로, 애플리케이션 또는 앱이라고도 함.컴퓨터 관점에서는 수동적인 존재로, 저장장치에만 존재함. 프로세스:실행 중인 프로그램을 의미하며, 저장장치에 있는 프로그램이 메모리에 올라갔을 때 형성됨.능동적인 존재로, 메모리와 CPU를 사용하며 입력과 출력을 처리함.운영체제의 CPU 스케줄링 알고리즘에 따라 CPU 사용.  프로세스의 구조코드 영역 : 실행 중인 프로세스의 코드가 저장됨.데이터 영역: 전역 변수 및 정적 변수가 저장됨.스택 영역:지역 변수와 함수 호출에 필요한 정보가 저장됨.함수 호출 시 매개변수와 복귀 주소를 저장.힙 영역:개발자가 런타임 중 동적으로 메모리를 할당할 수 있는 공간.C 언어에서 malloc, free 함수를 사용하여 자원 할당 및 해제를 수행.  프로세스 생성 과정 (C 언어의 경우)전처리: 전처리기를 통해 매크로를 치환하고 필요한 파일을 포함함. 이때 파일의 확장자는 .i가 됨.컴파일:컴파일러가 C 언어를 저수준 어셈블리어로 변환함. 파일 확장자는 .s가 됨.어셈블리:어셈블러가 어셈블리어를 기계어로 변환함. 결과 파일의 확장자는 .o가 됨.링킹:링커가 여러 라이브러리 및 다른 소스코드를 연결하여 최종 실행 파일을 생성함. 확장자는 .exe가 됨.프로세스 생성:생성된 실행 파일을 더블 클릭하면 하드디스크에 있는 파일이 메모리에 올라가 프로세스가 형성되며 운영체제에 의해 관리됨.  CPU 관점에서의 프로세스 실행CPU는 0과 1로 이루어진 기계어만을 실행함.예를 들어, CPU가 숫자 5와 7을 메모리에 저장하고, 이를 레지스터로 가져옴.제어장치가 레지스터의 값들을 가지고 더하라는 명령을 내리면, 산술 논리 연산 장치가 두 숫자를 더하고 결과를 레지스터에 저장.제어장치가 레지스터에서 결과값을 가져와 메모리에 저장함. 멀티프로그래밍과 멀티프로세싱메모리 관점 :유니프로그래밍: 메모리에 오직 하나의 프로세스만 올라와 있는 상태입니다.멀티프로그래밍:메모리에 여러 개의 프로세스가 동시에 올라와 있는 상태입니다.CPU 관점 :멀티프로세싱:CPU가 여러 개의 프로세스를 동시에 처리하는 방식입니다. 오늘날의 운영체제는 멀티프로그래밍과 멀티프로세싱 두 가지 방식을 공존하여 사용합니다.멀티프로그래밍:메모리에 여러 개의 프로세스가 올라와 있으며, 이들 프로세스는 동시에 존재합니다.시분할 처리:CPU는 각 프로세스를 짧은 시간 동안 교대로 실행하여 멀티프로세싱을 구현합니다. 과거에는 메모리의 크기가 작아 멀티프로그래밍이 불가능하여 유니프로그래밍과 멀티프로세싱을 사용했습니다. 스와핑 : 메모리에 있는 데이터를 다른 저장장치로 보내고, 다른 저장장치에서 있는 데이터를 메모리에 올리는 과정을 말합니다. 이로 인해 메모리의 활용성을 극대화할 수 있습니다. PCB : Process Control Block운영체제는 여러 개의 프로세스를 효율적으로 관리하고 공평하게 실행해야 합니다. 프로세스가 생성되면, 운영체제는 해당 프로세스의 정보를 포함하는 PCB(프로세스 제어 블록)를 생성하고 저장합니다. 이 PCB들은 연결 리스트라는 자료구조로 저장되어 운영체제에서 관리됩니다. 프로세스가 종료되면, 연결 리스트에서 해당 프로세스의 PCB가 제거됩니다.포인터:부모 및 자식 프로세스에 대한 포인터와 할당된 자원에 대한 포인터를 포함합니다.프로세스 상태 전환 시 저장하는 포인터를 갖고 있어 효율적인 접근을 지원합니다.프로세스 상태:현재 프로세스의 5가지 상태를 나타냅니다:생성, 준비,실행,대기,완료프로세스 ID (PID):프로세스를 식별하기 위한 고유 숫자를 저장합니다.프로그램 카운터:다음에 실행될 명령어의 주소를 포함합니다. 운영체제가 시분할 처리로 여러 프로세스를 번갈아 실행할 때, 어떤 프로세스가 CPU를 빼앗기고 다시 실행될 때 원래의 명령어가 실행될 수 있도록 프로그램 카운터는 필수적입니다.레지스터 정보:프로세스 실행 시 사용했던 레지스터 값들이 저장됩니다. 이는 CPU를 빼앗긴 후 다시 시작할 때 이전에 사용하던 값을 복구하기 위한 용도로 사용됩니다.메모리 관련 정보:프로세스가 메모리에 있는 위치 정보, 메모리 침범을 방지하기 위한 경계 레지스터 값 등이 저장됩니다.CPU 스케줄링 정보:CPU 스케줄링에 필요한 우선순위, 최종 실행 시간, CPU 점유 시간 등이 저장됩니다.기타 정보:PCB에는 프로세스의 상태 관리와 관련된 기타 정보도 포함될 수 있습니다. 프로세스 상태프로세스는 시분할 처리를 위한 다음과 같은 5가지 상태를 갖습니다:생성 (New):PCB(프로세스 제어 블록)가 생성되고, 메모리에 프로그램을 적재하기 위한 요청이 이루어지는 상태입니다.준비 (Ready):CPU 사용을 기다리는 상태입니다.준비 상태에 있는 프로세스는 배분된 CPU 스케줄러에 의해 CPU가 할당됩니다.대부분의 프로세스는 이 준비 상태에 있습니다.대기 (Waiting):프로세스가 입출력 요청을 할 때, 해당 요청이 완료될 때까지 기다리는 상태입니다.CPU는 매우 빠른 반면, 입출력 작업은 상대적으로 느리기 때문에, 특정 프로세스가 입출력 요청을 하면 CPU가 그 프로세스를 기다리게 하는 것은 비효율적입니다.따라서, 입출력 요청을 한 프로세스는 대기 상태로 전환되고, 다른 프로세스에게 CPU를 할당합니다.입출력 작업이 완료되면 대기 상태에 있던 프로세스에게 CPU 할당 기회를 줍니다.실행 (Running):준비 상태에 있는 프로세스가 CPU 스케줄러에 의해 CPU를 할당받아 실행되는 상태입니다.CPU가 하나인 경우 실행 상태의 프로세스는 최대 1개만 존재합니다.실행 상태에 있는 프로세스도 CPU를 무한정 사용할 수 없으며, 부여된 시간만큼 사용합니다.CPU 스케줄러는 부여된 시간을 초과하면 할당된 CPU를 강제로 뺏고 프로세스는 다시 준비 상태로 전환됩니다.완료 (Terminated):프로세스가 종료된 상태입니다.프로세스가 사용했던 데이터는 메모리에서 제거되고, 생성된 PCB도 제거됩니다. 프로세스 A, B, C가 동시에 실행될 때의 동작 과정:프로세스 로드:사용자의 입력에 의해 운영체제는 A, B, C 프로그램을 메모리에 로드합니다.이 과정에서 각 프로그램에 대한 프로세스 제어 블록(PCB)도 생성됩니다.CPU 할당:운영체제는 스케줄러에 의해 A 프로세스에 CPU를 할당합니다.명령어 주소 지정:운영체제는 PCB에서 A 프로세스의 정보를 가져와 CPU의 프로그램 카운터에 실행될 명령어의 주소를 지정합니다.A 명령어 실행:CPU는 메모리에서 A 프로세스의 동작에 필요한 명령어를 가져오고, 연산을 수행합니다.컨텍스트 스위칭 (A → B):스케줄러에 의해 A 프로세스에서 B 프로세스로 컨텍스트 스위칭이 발생합니다.PCB 업데이트:운영체제는 PCB에서 A 프로세스의 정보를 업데이트합니다. (프로그램 카운터 값도 저장)B 프로세스 정보 로드:운영체제는 PCB에서 B 프로세스의 정보를 가져와 CPU의 프로그램 카운터에 실행될 명령어의 주소를 지정합니다.B 명령어 실행:CPU는 메모리에서 B 프로세스의 동작에 필요한 명령어를 가져오고, 연산을 수행합니다.컨텍스트 스위칭 (B → C):스케줄러에 의해 B 프로세스에서 C 프로세스로 컨텍스트 스위칭이 발생합니다.반복:위의 과정이 반복되면서 A, B, C 프로세스가 CPU를 공유하며 실행됩니다.이러한 방식으로 운영체제는 여러 프로세스의 CPU 자원을 효율적으로 관리하며, 각 프로세스의 PCB를 통해 실행 상태와 정보를 추적합니다. 컨텍스트 스위칭을 통해 CPU는 각 프로세스를 빠르게 교대로 실행하여 사용자에게 다중 작업을 수행하는 것처럼 보이게 합니다. 컨텍스트 스위칭 Context SwitchingCPU가 하나의 프로세스를 실행하다가 다른 프로세스를 실행하기 위해 현재 실행 중인 프로세스의 상태를 저장하고, 다음 프로세스의 상태로 교체하는 작업입니다.이 과정에서 프로세스의 제어를 원활하게 유지하기 위해 프로세스 제어 블록(PCB)의 내용(프로세스 상태, 다음 실행할 명령어의 주소를 담고 있는 프로그램 카운터, 각종 레지스터 값, 메모리 관련 정보)이 변경됩니다. 컨텍스트 스위칭 과정CPU 점유 시간 초과:프로세스 A가 CPU를 사용하는 동안 할당된 점유 시간을 초과합니다.인터럽트 발생:운영체제는 프로세스 A가 CPU를 너무 오랫동안 사용했다고 판단하고 인터럽트를 발생시킵니다.상태 저장:프로세스 A는 현재 실행 중인 작업을 중지하고, 현재 CPU의 레지스터 값과 상태를 PCB A에 저장합니다.프로세스 B 상태 설정:PCB B를 참조하여 이전 프로세스 B의 상태로 CPU의 레지스터 값을 설정합니다.PCB B에는 다음에 실행할 명령어의 주소를 포함하는 프로그램 카운터가 저장되어 있습니다.프로세스 B 실행:CPU는 프로세스 B의 명령어를 실행할 준비가 완료되며, 즉시 실행을 시작할 수 있습니다.다시 인터럽트 발생:프로세스 B가 점유 시간을 다 사용하면, 운영체제는 또 다시 인터럽트를 발생시킵니다.상태 저장 및 교체:프로세스 B의 상태를 PCB B에 저장하고, PCB A에서 프로세스 A의 상태를 가져와 다시 프로세스 A를 실행합니다. 컨텍스트 스위칭 발생 이유컨텍스트 스위칭이 발생하는 이유는 여러 가지가 있습니다:CPU 점유 시간 초과: 프로세스가 할당된 CPU 점유 시간을 초과했을 때.I/O 요청: 프로세스가 입출력 작업을 요청하여 대기 상태로 전환될 때.다른 종류의 인터럽트: 시스템의 다른 요구사항이나 이벤트로 인해 발생하는 인터럽트가 있을 때.  스와핑 (Swapping) vs 컨텍스트 스위칭 (Context Switching)스와핑과 컨텍스트 스위칭은 모두 운영체제가 프로세스를 효율적으로 관리하기 위한 기법이지만, 사용되는 상황과 방법이 다릅니다. 스와핑은 주로 메모리 관리와 관련되어 있으며, 컨텍스트 스위칭은 CPU 자원의 효율적 분배와 관련되어 있습니다.스와핑 (Swapping)정의: 스와핑은 메모리 관리 기법 중 하나로, 운영체제가 프로세스를 메모리에서 디스크(스왑 공간)으로 이동시키는 작업입니다. 프로세스가 필요하지 않을 때 메모리에서 제거하고, 다시 필요할 때 다시 메모리로 로드합니다.목적:메모리 공간을 확보하여 다른 프로세스가 실행될 수 있도록 합니다.물리적 메모리가 제한되어 있는 경우 여러 프로세스의 동시 실행을 지원하기 위해 사용됩니다.작동 방식:프로세스가 메모리에서 제거될 때, 해당 프로세스의 모든 데이터와 상태를 디스크에 저장합니다.나중에 프로세스가 필요할 때, 디스크에서 다시 메모리로 로드합니다. 컨텍스트 스위칭 (Context Switching)정의: 컨텍스트 스위칭은 CPU가 실행 중인 프로세스의 상태를 저장하고, 다른 프로세스의 상태로 교체하는 작업입니다. 이는 다중 프로세스 환경에서 CPU 자원을 효율적으로 할당하기 위해 필요합니다.목적:여러 프로세스 간에 CPU 자원을 공정하게 분배하고, 각 프로세스가 주어진 시간 내에 실행될 수 있도록 합니다.작동 방식:현재 실행 중인 프로세스의 상태(레지스터 값, 프로그램 카운터 등)를 PCB에 저장합니다.다음 실행할 프로세스의 PCB에서 상태를 읽어와 CPU에 로드합니다.주요 차이점 프로세스의 생성과 종료프로세스 생성 과정:1. 사용자 실행: 사용자가 .exe 파일을 더블 클릭하여 프로그램을 실행합니다.2. 메모리 로드: 운영체제가 해당 프로그램의 코드 영역과 데이터 영역을 메모리에 로드하고, 빈 스택과 빈 힙을 생성하여 공간을 확보합니다.3. PCB 생성: 이 프로세스를 관리하기 위한 프로세스 제어 블록(PCB)을 만들어 초기화합니다.위의 프로세스 생성 과정은 운영체제가 부팅되고 0번 프로세스가 생성될 때 딱 한 번만 실행합니다.0번 프로세스와 자식 프로세스:0번 프로세스: 운영체제가 부팅되면 0번 프로세스가 생성되고, 나머지 모든 프로세스는 이 0번 프로세스를 복사하여 생성됩니다. 복사가 새로 생성하는 것보다 더 빠르기 때문입니다.부모-자식 관계: 자식 프로세스는 부모 프로세스인 0번 프로세스의 코드 영역, 데이터 영역, 스택 영역, PCB 내용을 모두 복사합니다. 부모-자식 관계 및 자식 프로세스의 독립적인 실행을 통해 효율적인 메모리 관리와 프로세스 관리를 가능하게 합니다. exec() 함수 사용:자식 프로세스의 실행: fork() 함수로 생성된 자식 프로세스가 부모와 동일하게 실행되지 않도록 하기 위해 exec() 함수를 사용합니다.코드와 데이터 덮어쓰기: exec() 함수를 호출하면 자식 프로세스의 코드와 데이터 영역을 원하는 값으로 덮어써 자식 프로세스는 부모와 완전히 다른 동작을 하게 됩니다. 프로세스 종료:exit() 함수: 자식 프로세스는 작업이 끝났음을 부모 프로세스에게 알리기 위해 exit() 함수를 호출합니다.exit status: 부모 프로세스는 자식 프로세스의 종료 상태(exit status)를 읽고 자식 프로세스를 정리합니다. 좀비 프로세스:정상 종료 실패: 만약 부모 프로세스가 자식 프로세스보다 먼저 종료되거나, 자식이 비정상적으로 종료되어 exit 신호를 주지 못하면, 부모가 자식의 exit status를 읽지 못하고 메모리에 남아 있는 상태를 "좀비 프로세스"라고 부릅니다.성능 저하: 좀비 프로세스가 많아지면 메모리를 차지하여 시스템이 느려질 수 있으며, 재부팅을 통해 메모리가 초기화되어 성능이 회복될 수 있습니다. 스레드운영체제의 작업 처리 단위: 프로세스운영체제는 사용자가 요청하는 작업을 처리하기 위해 프로세스를 생성합니다.각 프로세스는 프로세스 제어 블록(PCB)과 메모리에 필요한 코드, 데이터, 스택, 힙 영역을 할당받습니다. 프로세스의 한계프로세스는 메모리 사용량이 많아 여러 개의 프로세스를 생성하는 것이 비효율적입니다.각 프로세스가 독립적으로 자원을 사용하므로 메모리 오버헤드가 발생합니다. 스레드의 도입스레드는 프로세스 내에서 실행되는 작업의 단위로, 여러 개의 스레드가 존재할 수 있습니다.스레드는 같은 프로세스 내에서 PCB, 코드, 데이터, 힙 영역을 공유합니다. 하지만 각 스레드는 독립적인 스택을 가집니다. 스레드 관리스레드의 구분을 위해 각 쓰레드에 고유한 스레드 ID를 부여하고, 이를 관리하기 위한 스레드 컨트롤 블록(TCB)도 생성됩니다.이로 인해 운영체제는 프로세스 내의 스레드를 개별적으로 관리할 수 있습니다.  장단점 비교:스레드는 프로세스에 비해 메모리 사용이 효율적이고 실행 속도가 빠르며, 적은 오버헤드를 통해 작업을 수행할 수 있는 장점이 있지만, 안정성 측면에서는 프로세스에 비해 취약한 단점을 가집니다.안전성 프로세스: 서로 독립적이므로 하나의 프로세스에 문제가 생겨도 다른 프로세스에 영향을 주지 않습니다.스레드: 같은 프로세스 내에서 실행되므로, 하나의 스레드에 문제가 생기면 해당 프로세스 내의 모든 스레드에 영향을 미칩니다.속도와 자원:프로세스: 각 프로세스가 고유한 자원을 가지므로, 프로세스 간 통신 시 오버헤드가 크고 속도가 느립니다.스레드: 스택 영역을 제외한 모든 영역을 공유하기 때문에 오버헤드가 적고, 데이터 공유가 용이하지만 공유 자원에서 동기화 문제를 발생할 수 있습니다. CPU 스케줄링CPU 스케줄링 개요프로그램을 실행시키면 메모리에 프로세스가 생성되고 각 프로세스에는 1개 이상의 스레드가 있습니다. 프로세스들은 CPU를 차지하기 위해 운영체제의 명령을 기다리고 있습니다.운영체제는 모든 프로세스에 대해 CPU를 할당하고 해제하는 역할을 수행합니다. 이 과정을 CPU 스케줄링이라고 합니다. 스케줄링 고려 사항어떤 프로세스에게 CPU를 할당할 것인가?: 메모리에 있는 수많은 프로세스 중에서 CPU 사용 권한을 부여할 프로세스를 결정합니다.CPU를 할당받은 프로세스가 얼마나 오랫동안 CPU를 사용할 것인가?: 현대의 시스템에서는 시분할 처리 방식으로 여러 프로세스가 짧은 시간 동안 CPU를 번갈아 사용하는 방식입니다.  CPU Burst와 I/O BurstCPU Burst: CPU를 할당받아 실행되는 작업입니다.I/O Burst: 입출력 작업으로, CPU와는 별개로 수행됩니다.  다중큐프로세스 상태1. 생성: 프로세스가 생성되면 준비 상태로 전환됩니다.2. 준비 상태: CPU를 기다리고 있는 프로세스들은 CPU 스케줄러에 의해 실행 상태로 전환됩니다.3. 실행 상태: CPU를 할당받은 프로세스는 CPU 사용 시간이 끝나면 다시 준비 상태로 돌아갑니다.- 입출력 요청: 프로세스가 입출력 요청을 하면 대기 상태로 전환됩니다.- 작업 완료: 프로세스 작업이 끝나면 완료 상태로 전환됩니다. 큐와 프로세스 관리준비 상태와 대기 상태의 프로세스는 큐라는 자료구조로 관리됩니다.큐는 선입선출(FIFO) 방식으로, 먼저 들어온 작업이 먼저 처리됩니다. 프로세스 우선순위와 큐프로세스가 실행 상태에서 준비 상태로 돌아갈 때, 운영체제는 해당 프로세스의 우선순위를 확인하고 그에 맞는 준비 큐에 넣습니다. CPU 스케줄러프로세스 정보가 담긴 PCB는 준비 상태의 다중 큐에 들어가 실행되기를 기다립니다.CPU 스케줄러는 준비 상태의 다중 큐에 있는 프로세스들 중에서 적절한 프로세스를 선택하여 실행 상태로 전환합니다. 입출력 작업 관리실행 중인 프로세스에서 입출력 작업이 발생하면, 해당 작업의 종류별로 나뉜 큐에 들어갑니다.CPU 스케줄러는 이 큐를 참조하여 입출력 작업의 스케줄링을 수행합니다.  스케줄링 목표리소스 사용률CPU 사용률: CPU의 효율적인 사용을 극대화.I/O 디바이스 사용률: 입출력 장치의 사용 효율을 높이는 것.오버헤드 최소화스케줄링을 위한 계산이 복잡하거나 컨텍스트 스위칭이 빈번하면 오히려 성능 저하를 초래.스케줄러는 이러한 오버헤드를 최소화하는 것을 목표로 함.공평성모든 프로세스에게 공정하게 CPU를 할당하는 것을 목표로 함.공정성의 의미는 시스템의 특성에 따라 달라질 수 있음.처리량주어진 시간 내에 처리 가능한 작업의 양을 극대화하는 방법을 목표로 함.대기 시간작업 요청 후 실제 작업이 시작되기까지의 대기 시간이 짧아야 함.응답 시간대화형 시스템에서 사용자 요청에 대한 반응 속도를 중요하게 고려.응답 시간이 짧아야 사용자 경험이 향상됨. 상반되는 목표모든 목표를 동시에 최적화하는 것은 어려움.예: 처리량을 높이기 위해 하나의 프로세스에 CPU를 오랫동안 할당하면 응답 시간이 길어질 수 있음. 반대로, 여러 프로세스에 CPU를 고르게 할당하면 응답 시간이 줄어들지만, 처리량이 감소할 수 있음.시스템에 따른 목표 설정목표는 사용자와 사용 환경에 따라 다르게 설정되어야 함. 사용자의 필요와 시스템의 목적에 맞게 조정이 필요함. 스케줄링 알고리즘FIFO : First In First OutFIFO 스케줄링은 먼저 들어온 작업이 먼저 나가는 방식입니다.스케줄링 큐에 들어온 순서대로 CPU를 할당하며, 먼저 들어온 프로세스가 완전히 끝나야 다음 프로세스가 실행될 수 있습니다.FIFO는 직관적인 스케줄링 방식이지만, 평균 대기 시간이 증가할 수 있는 단점이 있어 현대 운영체제에서는 제한적으로 사용되며, 주로 일괄처리 시스템에서 효과적입니다. 장점단순하고 직관적: 구현이 간단하고 이해하기 쉬운 방식입니다.단점긴 대기 시간: 프로세스의 실행 순서만 변경했을 뿐인데도 평균 대기 시간의 차이가 클 수 있습니다.성능 차이: 프로세스의 Burst Time에 따라 성능 차이가 심합니다. 긴 작업이 먼저 실행될 경우, 그 뒤에 대기하는 짧은 작업들의 대기 시간이 늘어날 수 있습니다.비효율적 사용: 입출력 작업이 발생하는 경우 CPU가 대기하는 동안 사용률이 떨어지는 단점이 있습니다. 사용 사례FIFO 알고리즘은 현대 운영체제에서는 잘 사용되지 않지만, 일괄처리 시스템에서 유용합니다. 여기서는 각 프로세스가 완전히 끝나야 다음 프로세스가 시작되기 때문에 실행 시간이 짧고, 단순한 작업 흐름에 적합합니다. 성능 평가스케줄링의 성능은 평균 대기 시간으로 평가됩니다.평균 대기 시간: 여러 프로세스가 실행될 때 이 프로세스들 모두의 대기 시간을 평균한 값으로, 이 값이 낮을수록 스케줄링 효율이 높다고 평가됩니다. SJF, RR, MLFQ는 다음 주차에서..        

CS운영체제

Jay 1개월 전
Jay

워밍업 클럽 CS 1주차 발자국 : 자료구조와 알고리즘

개요자료구조와 알고리즘자료구조는 데이터를 저장하고 사용하는 구조를 나타내며, 데이터의 종류에 따라 저장 방식과 처리 방법이 다릅니다.알고리즘은 문제를 해결하는 절차로, 선택한 자료구조에 따라 다양한 알고리즘이 존재할 수 있습니다.즉, 적절한 자료구조를 선택한 후, 이를 효율적으로 처리하는 알고리즘을 적용해 원하는 결과를 얻습니다. 시간복잡도시간복잡도는 알고리즘의 성능을 평가하는 기준입니다.알고리즘의 실행 시간은 컴퓨터 성능에 따라 다르므로, 실제 시간을 측정하는 대신 반복문과 같은 성능에 큰 영향을 미치는 요소를 기준으로 평가합니다.시간복잡도는 여러 경우로 나뉘며, 최악의 경우(O), 평균의 경우(Θ), 최선의 경우(Ω)로 나뉘는데, 주로 빅오 표기법(O)을 사용해 성능을 표현합니다.빅오 표기법은 입력이 늘어날 때 계산량의 증가율을 나타내며, 가장 큰 항만을 표기해 성능을 간략히 표현합니다.예시: 3n^2 + 2n + 100 ⇒ O(n^2) 자료구조배열 (Array)- 특징: 메모리에서 연속된 공간을 할당하여 데이터를 저장. 배열의 시작 주소만 기억하고, 인덱스 참조는 O(1) 성능.- 장점: 빠른 읽기, 쓰기, 참조.- 단점: 삽입, 삭제 시 성능 저하. 배열 크기를 미리 알아야 하고, 메모리 낭비가 발생할 수 있음.- JavaScript 배열: 불연속적 메모리를 할당하지만, 사용자에게는 연속된 배열처럼 보임. 연결 리스트 (Linked List)- 구성: 노드(Data + 다음 노드를 가리키는 포인터)로 이루어짐.- 장점: 데이터의 삽입/삭제가 쉽고, 메모리 공간을 유연하게 사용.- 단점: 참조 시 성능이 O(n)으로 배열보다 느림. 스택 (Stack)- 특징: FILO(First In Last Out) 구조로, 되돌리기와 문법 검사 등에 사용. 큐 (Queue)- 특징: FIFO(First In First Out) 구조로, 운영체제의 프로세스 작업 처리에 주로 사용.- 성능 개선: 마지막 노드를 가리키는 tail 변수를 사용하면 O(1) 성능으로 데이터 제거 가능. 덱 (Deque)- 특징: 헤드와 테일에서 데이터의 삽입/삭제가 모두 가능한 자료구조. 스택과 큐를 모두 구현할 수 있음. 해시테이블 (Hash Table)- 특징: 해시 함수를 사용해 데이터를 효율적으로 저장 및 검색할 수 있는 자료구조.- 장점: 데이터 삽입, 수정, 삭제가 O(1)로 매우 빠름.- 단점: 해시 충돌 시 성능이 O(n)으로 저하될 수 있음. 메모리 효율이 떨어지고, 데이터를 골고루 분배 시켜주는 좋은 해시 함수 구현이 중요. 셋 (Set)- 특징: 데이터의 중복을 허용하지 않으며, 해시 테이블 기반으로 구현. key가 데이터로 사용됨. 

알고리즘 · 자료구조CS알고리즘자료구조

Jay 1개월 전

인프런 워밍업 클럽 CS 2기 1주차 미션

운영체제1.while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 }위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다. 이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다. 이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요?: 폴링방식은 CPU가 주기적으로 장치의 상태를 검사해야 하기 때문에 성능이 좋지 않습니다. 따라서 예외상황이 발생시 CPU에게 요청을 하는 인터럽트 방식을 사용하는 편이 좋습니다.2.프로그램과 프로세스가 어떻게 다른가요?==> 프로그램 : 프로그래머가 작성한 명령어들의 집합체==> 프로세스 : 프로그램이 메모리에 적재되어 실행중인 상태 , 프로세스는 메모리와 CPU를 사용하며 CODE영역,STACK영역,HEAP영역 , STACK영역으로 나뉘어진다.3. 멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?==>멀티프로그래밍 : 멀티프로그래밍은 메모리에 여러 프로세스를 적재하여 실행시키는것을 멀티프로그래밍이라 한다.==>멀티프로세싱 : CPU가 여러개의 프로세스를 처리하는것을 의미한다. 4. 운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?==> PCB(Process Control Block)을 사용한다. PCB는 프로세스가 생성될 때 운영체재가 생성하여 포인터,프로세스 상태 , 스케쥴링 정보 , 프로그램 카운터 , 레지스터 정보 등을 가지고 있다.5. 컨텍스트 스위칭이란 뭔가요?==> 컨텍스트 스위칭이란 CPU를 사용중인 프로세스를 중단하고 다른 프로세스로 교체할 때 실해중이던 프로세스의 상태를 저장하고 다른 프로세스의 상태를 불러오는 작업을 말한다.  자료구조  여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다. 이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요?이유를 함께 적어주세요. ==> 교실의 학생정보같은경우 만약 주소 , 나이 , 성별 등 자주 변경될일 없는 정보들이 저장되는 학생정보인 경우 배열을 사용할 것이고 , 성적이나 주간으로 자주 변경해야 하는 내용들이 저장되어 있는 정보들이 라면 수정에 용이한 링크드리스트를 사용할 것입니다.  여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요.==> 순서대로 처리하기위해서는 먼저들어온 데이터가 먼저 처리되는 FIFO방식인 Queue를 사용할 것 같습니다.

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

 강의 수강 내용 및 회고 운영체제대학생때 다 배웠던 내용이지만 막상 실무를 하면서는 잘 생각하지 않아서 까먹었던 개념들을 다시 복습할 수 있어서 좋았다. 이미 알고 있다고 생각했던 개념도 그림과 함께 설명을 들으니 훨씬 쉽게 느껴지고 이해도 빠르게 할 수 있었다. CPU, 메모리, 하드디스크 등등.. 각각이 하는 역할을 명확히 구분할 수 있게 되는 시간이었고, 헷갈렸거나 혼용해서 쓰던 개념도 정리할 수 있는 시간이었다. 자료구조와 알고리즘이것도 운영체제와 마찬가지로 강의 커리큘럼 내용만 보고 처음에는 '음.. 대충 다 알고 있는 내용이라서 금방하겟군' 이라고 생각했었는데, 막상 직접 구현해보려고 하니 중간중간 헷갈리는 부분이 있었다. 역시 머리로만 이해하고 사용하는 것과 실제로 구현해보는 것은 하늘과 땅 차이였다. 개념 수업을 들으면서 평소에 코드를 구현할 때 어떤 자료구조를 사용할지 고민했던 순간들이 떠오르면서 좀 더 나은 방향성을 찾아보는 시간이었다.  칭찬할 점운영체제 강의 같은 경우 실습이 없었기 때문에 출퇴근 시간을 이용해서 강의를 들었는데, 생각보다 아침시간에 집중도 잘되었고, 업무하면서도 강의 들었던 내용을 상기하면서 업무를 할 수 있어서 수업내용을 체화하는데 도움이 더 되었던 것 같다. 그리고 일단.. 업무시간 이외에 공부를 하지 않던 내가 따로 시간을 내서 공부를 했다는 것에 가장 큰 박수를 ~ 아쉬웠던 점초반에 강의 수강 진도표를 잘못 읽고 운영체제 강의만 다 듣고 일주일 진도를 끝냈다고 생각해서 몇일을 날려먹었다.막판에 미션을 작성하려고 보니 알고리즘 강의 진도도 있다는 걸 깨닫고 막판에 몰아서 듣다보니 실습 부분을 더 깊게 생각할 시간이 부족했다. 다음주 강의를 수강하면서 이번주에 더 깊게 생각하지 못했던 부분을 보완해야겠다. 보완할 점역시 미뤄듣지 말고 매일매일 나눠서 꾸준히 수강을 하도록 보완해야겠다.그리고 이번주는 강의 내용을 따로 요약정리하지는 않았는데 다음주에는 수업 후 요약정리를 좀 해봐야겠다.  

알고리즘 · 자료구조워밍업클럽운영체제알고리즘자료구조CS

[미션] 인프런 워밍업 클럽 2기 CS 1주차

CS 1주차 미션운영체제1.Cwhile(true){       wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 }위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다.이 방식은 폴링방식입니다.1초마다 체크하기 때문에 성능에 좋지 않습니다.이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요?인터럽트. 플레이어가 스킬을 사용하고 있다는 신호가 오기 전까지 자원을 다른 곳에 쓸 수 있음2. 프로그램과 프로세스가 어떻게 다른가요?프로그램은 코드가 디스크에 저장되어 있는 상태프로세스는 프로그램이 메모리에 올라가 있는 상태3. 멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?멀티프로그래밍은 메모리 관점에서 메모리에 여러 프로세스가 올라가있는 것멀티프로세싱은 CPU 관점에서 CPU가 메모리에 올라가있는 여러 프로세스를 시분할 처리하는 것4. 운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?PCB를 이용해 프로세스의 상태를 관리한다5. 컨텍스트 스위칭이란 뭔가요?운영체제는 CPU를 효율적으로 사용할 수 있도록 여러 프로세스를 번갈아가면서 CPU를 할당하는데, 이때 각 프로세스의 작업 진행 상황을 유지할 수 있도록 PCB의 상태를 업데이트하는 것을 말한다.자료구조와 알고리즘1. 여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다.이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요?이유를 함께 적어주세요.해시테이블. 학생을 식별할 수 있는 key값(학생번호 등)을 이용해 학생정보를 저장하면 그 key값을 통해 해당 학생의 정보를 저장하고 관리할 수 있다. 관리 프로그램은 데이터에 빠르게 접근할 수 있어야 하고, 수정이 용이해야 할 것 같아서 해시테이블을 선택했다.2. 여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다.    주문은 들어온 순서대로 처리됩니다.    이 때 여러분이라면 어떤 자료구조를 선택하실 건가요?    이유를 함께 적어주세요.큐. 큐는 먼저 들어온 데이터를 먼저 처리하는 FIFO 방식이기 때문에 주문이 들어온 순서대로 처리하는 작업에 알맞은 자료구조이다.

알고리즘 · 자료구조워밍업클럽운영체제알고리즘자료구조CS

하얀종이개발자

인프런 워밍업 클럽 2기 - CS 전공지식 스터디 1주차 발자국

운영체제 1주차 학습 요약 운영체제운영체제는 컴퓨터를 유연하게 동작시키기 위해 필요하다.운영체제가 하는일프로세스를 관리 (여러 프로그램을 동작시킴)메모리를 관리 (프로그램은 메모리에 올라감)하드웨어 관리 (사용자의 하드웨어에 대한 직접 접근을 막음)파일 시스템 관리 (하드디스크에 많은 파일들을 효율적으로 저장&관리)운영체제의 구조커널 - 프로세스와 메모리, 저장장치를 관리하는 핵심적인 기능을 담당인터페이스 - 사용자가 시스템과 상호작용을 도와주는 외부 인터페이스시스템 콜 - 커널은 사용자 애플리케이션과 커널이 소통할때 사용되는 내부 인터페이스 (커널을 보호)드라이버 - 하드웨어와 커널간의 인터페이스폰노이만 구조CPU와 메모리를 분리하고 프로그램을 메모리에 올려서 실행하는 구조인터럽트인터럽트는 폴링 방식의 단점을 해결하기위해 CPU가 현재 진행중인 작업을 일시중단하고 외부에서 발생한 이벤트를 처리하기위해 서비스루틴을 실행하는 매커니즘프로세스프로그램이 메모리에 올라가서 CPU 할당의 대상이 되는 능동적인 존재프로세스의 구조코드영역(실제 코드), 데이터영역(전역변수, 정적변수), 스택영역(지역변수, 함수), 힙영역 (객체 등, 런타임시 동적인 메모리를 할당할 수 있는 공간)컴파일 과정test.c -> 전처리기 -> test.i -> 컴파일러 -> test.s(어셈블리어) -> 어셈블러 -> test.o(기계어) -> 링커(라이브러리 연결) -> test.exe프로세스 컨트롤 블록 (PCB)운영체제는 여러개의 프로세스를 관리하고 공평하게 CPU를 할당하기 위해 프로세스 정보를 담은 PCB를 만들고 저장함식별자, 프로세스 상태, 프로그램카운터, 레지스터 정보등을 저장프로세스 상태생성, 준비, 실행, 대기, 완료컨텍스트 스위칭프로세스를 실행하는 중에 다른 프로세스를 실행하기 위해 실행중인 프로세스를 저장하고 다른 프로세스의 상태값으로 교체하는 작업쓰레드한 프로세스 내에서 동시에 각자 실행될 수 있는 작업 흐름의 단위기본적으로 프로세스 1개에는 1개의 쓰레드가 존재쓰레드끼리는 스택영역을 제외한 다른 영역은 공유해서 사용, 프로세스에 할당된 Virtual Memory로 공간이 제약됨공유하는 영역을 통해 메모리 낭비를 줄이고 쓰레드끼리 소통할때 비용이 적게 들지만, 안정성이 떨어짐CPU 스케쥴링운영체제는 CPU를 여러 프로세스에 할당/해제 하는 것을 CPU 스케쥴링이라고 함다중 큐준비, 대기 상태의 프로세스는 다중 큐 자료구조에서 관리다중큐에는 정확하게는 프로세스의 정보를 가진 PCB가 저장CPU 스케쥴링 알고리즘FIFO (First In First Out)스케쥴링 큐에 들어온 순서대로 CPU를 할당 받는 방식한 프로세스가 완전히 끝나야 다음 프로세스가 시작되고, I/O작업시 I/O작업이 끝날때까지 CPU가 대기하는 단점이 있음프로세스의 BURST TIME에 따라 성능차이가 심하게 나기 때문에 잘 쓰이지 않고, 일괄처리 시스템에서 쓰임  알고리즘 & 자료구조 1주차 학습 요약 알고리즘어떤문제를 해결하기 위한 구체적이고 확실한 방법자료구조데이터를 효율적으로 저장하고 사용할 수 있도록 정리하는 방법상황에 맞는 적절한 자료구조를 선택하고 이에 맞는 적절한 알고리즘을 적용할 수 있어야 한다.시간복잡도더 좋은 알고리즘이란 무엇일까? 메모리를 더 적게 사용하는 것? 속도가 빠른 것?입력값이 달라지더라도 동일하게 알고리즘의 속도를 표현하는 방법이 시간복잡도입력값에 따른 변화의 추이를 나타내는 방법중에 최악의 경우를 기준으로 표기하는 빅 오 표기법이 가장 많이 사용됨배열동일한 데이터 타입의 요소들을 연속된 메모리 공간에 저장하는 자료구조읽기, 쓰기와 같은 참조에는 O(1)의 성능을 가짐그러나 데이터 삽입, 삭제에서는 데이터 복사, 이동등이 일어나 비효율적임또한, 고정된 크기로 배열을 생성해야함연결리스트배열의 단점은 연속된 메모리공간이 필요하다는 것과 초기 배열의 크기를 모르면 메모리가 낭비될 수 있다는 점임연결리스트에 데이터를 추가한다면 빈 메모리 공간에 데이터를 생성하고 연결만 해주면 됨연결리스트는 요소 접근시 첫번째 노드부터 이동하면서 찾아야함, O(N)배열 VS 연결리스트배열은 메모리 크기가 고정이고, 연속된 주소에 할당되는 단점, 그러나 인덱스 접근으로 인해 참조는 매우 빠름 연결리스트는 초기 크기를 알 필요없이 데이터를 생성하고 연결만 해주면 됨대신 인덱스 접근이 느림 (첫번째 노드부터 이동하면서 찾아야 함)스택먼저 들어간 데이터가 가장 마지막에 나가는 First In Last Out의 자료구조큐먼저 들어간 데이터가 가장 먼저 나오는 First In First Out의 가료구조덱데이터 삽입과 제거를 앞과 뒤 모두에서 자유롭게 사용할 수 있는 자료구조덱을 이용하면 스택과 큐 모두 구현 가능해시테이블해시 함수에 의해 생성된 해시값을 인덱스로 사용하여, key, value 쌍으로 저장됨해시충돌서로 다른 입력값이 동일한 해시값을 갖는 상황체이닝충돌이 발생한 경우, 동일한 해시값을 갖는 여러개의 항목을 연결리스트로 저장 (실제로는 레드블랙트리) 해시테이블의 장.단점장점 : 빠른 데이터 읽기, 삽입, 삭제 - O(1)의 성능단점 : 메모리를 많이 차지함 (좋은 해시함수는 필수)셋데이터의 중복을 허용하지 않는 자료구조 (순서를 보장하지 않고 중복을 허용하지 않음) 회고1주일동안 CS 전공지식 스터디를 하면서 부족한 것을 채우면서 많이 공부하게 된 것 같아요. 다른사람들이 어떻게 공부하고 있는지, 그리고 미션을 통해 가장 중요하게 알고 넘어가야 하는 부분들을 집어주셔서 확실히 개념이 잡히는 것 같아요.스터디를 진행하면서 전공자임에도 스스로 알고 있다라고 생각했던 것들이, 생각보다 잘 모르고 있구나 라는 반성을 많이 하게 된 것 같습니다. 스터디와 강의로 통해서 개념을 다시 정리할 수 있게되어 너무 좋았어요. 특히, 운영체제 부분 프로세스의 상태 전환 하는 부분에서 많이 배운 것 같네요.개발을 할 때 필요한 기본 지식들, 알고리즘 그리고 자료구조들은 평생 사용하는 것들인데 스터디를 통해 많은 것들을 얻는 것 같아요. 이제 2주 남았는데요. 짧다면 짧은 기간이지만 함께 달려서 완주했으면 좋겠습니다.  

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

이선주

인프런 워밍업 클럽 스터디 2기 CS 1주차 과제

운영체제while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 }위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다.이 방식은 폴링방식입니다.1초마다 체크하기 때문에 성능에 좋지 않습니다.이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요?(답): 인터럽트프로그램과 프로세스가 어떻게 다른가요?(답): 프로그램은 하드디스크와 같은 저장장치에 저장된 명령문에 집합체이고, 프로세스는 프로그램이 메모리에서 실행중인 상태를 말한다.멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?(답): 멀티프로그래밍은 메모리에 여러 프로세스가 올라온 것을 말하고, 멀티프로세싱은 CPU가 여러 프로세스를 처리하는 것을 말한다. 즉, 멀티프로그래밍은 메모리 관점이고 멀티프로세싱은 CPU 관점이다.운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?(답): CPU 스케줄링컨텍스트 스위칭이란 뭔가요?(답): CPU가 현재 실행중인 프로세스의 상태를 저장하고 다른 프로세스의 상태로 교체하여 실행하는 것을 말한다.자료구조와 알고리즘여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다. 이때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? (이유를 함께 적어주세요.)(답): 해시테이블, 이유는 학생 이름을 이용하여 상수시간(O(1))의 성능으로 빠르게 학생 정보를 열람할 수 있기 때문이다.연결리스트 또는 배열로 구현할 경우..- 연결리스트로 구현한다면 저장/삭제에 용이하지만, 조회는 해당 인덱스까지 노드를 찾아가야 하기 때문에 O(n)의 성능이 발생 - 배열로 구현한다면, 조회는 인덱스를 이용하여 메모리 주소에 바로 접근이 가능하기 때문에 O(1), 저장/삭제에는 배열 특성상 새로운 메모리 공간을 확보해야 하기 때문에 연결리스트에 비해 불리하다.여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요. (답): 큐, 이유는 큐 자료구조의 특성인 FIFO이기 때문이다. 처음 들어온 자료(First In)가 먼저 나가기(First Out) 때문

알고리즘 · 자료구조

김주현

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

강의 수강운영체제일주일 간의 학습했던 내용운영체제가 하는 일 : 프로세스 관리, 메모리 관리, 하드웨어 관리, 파일 시스템 관리운영체제의 역사1. 1950년대 에니악 : 스위치와 배선을 연결해서 프로그래밍, 입출력 중간에 계산 불가2. 1950년대 초 : 직접 회로가 만들어짐, 컴퓨터가 카드를 읽어 계산하고 라인 프린터로 출력3. 1950년대 중후반 : "싱글스트림 배치시스템"의 등장, 입출력 중에도 CPU가 계산 가능 4. 1960년도 : 시분할 시스템의 등장 5. 1970년대 이후 : 개인용 컴퓨터 사회의 등장, GUI 도입 운영체제의 등장운영체제의 구조커널 : 프로세스와 메모리, 저장장치를 관리하는 핵심적인 기능 담당-> 사용자는 운영체제의 커널에 직접 접근 불가-> 애플리케이션은 '시스템 콜'을 통해서 커널에 접근 가능-> 시스템 콜 없이 하드디스크에 접근 가능하다면, 중요 데이터를 덮어쓸 수 있다.컴퓨터 하드웨어와 구조오늘날 대부분의 컴퓨터는 프로그램 내장 방식의 폰 노이만 구조 메인보드 : 다른 하드웨어를 연결하는 장치CPU : 중앙처리 장치 메모리  컴퓨터의 부팅과정1. ROM에 저장된 바이오스 실행됨2. 바이오스는 주요 하드웨어에 이상이 없는지 확인3. 이상이 있으면 부팅 X, 이상이 없다면 부트로더를 메모리로 가져와서 실행4. 운영체제가 여러 개 설치되어 있다면, 선택 화면이 나온다.5. 운영체제를 메모리로 불러온다.6. 부팅 후부터는 운영체제가 메모리를 관리한다.  인터럽트폴링 방식을 보완한 방식CPU는 입출력 명령을 내린 후 자기는 다른 작업을 계속 함입출력 관리자는 입출력이 완료되면 CPU에게 신호를 주고, CPU는 신호를 받아서 ISR를 실행 시켜서 작업 완료한다.인터럽트는 비동기 방식이기 떄문에 성능에 이점이 있다. 프로그램과 프로세스프로그램 : 저장장치에 저장된 명령문의 집합체프로세스 : 실행중인 프로그램프로세스 영역 -> Code : 실행하는 코드-> Data : 전역변수, static 변수-> Stack : 지역변수, 매개변수-> Heap : 프로그래머가 런타임 시 할당할 수 있는 동적 메모리 공간 exe 파일을 실행하게 되면, 하드디스크의 프로그램이 메모리에 올라가게 되고 이제 프로세스로 불린다.  멀티 프로그래밍과 멀티 프로세싱멀티프로그래밍 : 메모리에 여러 개의 프로세스가 올라간 상태멀티프로세싱 : CPU가 여러 개의 프로세스를 처리하는 것오늘날 멀티프로그래밍, 멀티프로세싱 두 개가 공존한다.  PCB프로세스가 만들어지면 운영체제는 해당 프로세스의 정보를 가지고 있는PCB를 만들고 저장한다.PCB의 구조 : 프로세스 상태, 프로세스 ID, 프로그램 카운터, 여러 레지스터 정보 등등  프로세스 상태 컨텍스트 스위칭프로세스를 실행하는 중에 다른 프로세스를 실행하기 위해실행중인 프로세스의 상태를 저장하고 다른 프로세스의 상태값으로 교체하는 것을 말함.컨텍스트 스위칭이 일어날 때 PCB의 내용이 변경됨-> 실행중인 프로세스의 작업내용을 PCB에 저장하고 실행될 기존 프로세스의 PCB의 내용대로 CPU가 다시 세팅  프로세스 생성과 종료프로세스 생성 과정-> 운영체제는 해당 프로그램의 코드영역과 데이터 영역을 메모리에 로드하고-> 빈 스택고 빈 힙을 만들어 공간을 확보-> 해당 프로세스를 관리하기 위한 PCB를 만들고 값을 초기화위 생성과정은 운영체제가 부팅되고 0번 프로세스를 만들 때 딱 한번만 실행됨 나머지 프로세스는 0번 프로세스를 복사해서 쓰게 된다. 복사된 프로세스는 코드와 데이터 영역을 자신이 원하는 값으로 덮어쓴다.쓰레드프로세스 내의 존재하고, 프로세스의 PCB, 코드, 데이터, 힙 영역을 공유한다.스택 영역은 공유하지 않고 쓰레드마다 하나씩 가지고 있다. 프로세스는 독립적이기 때문에 안정성이 높음, 쓰레드는 프로세스에 의존적이기 때문에 안정성이 낮음프로세스 간의 통신은 IPC를 사용해야 하기 때문에 오버헤드가 크고 속도가 느림, 쓰레드 간의 통신은 빠름CPU 스케줄링어떤 프로세스에게 CPU 사용권을 줘야 하는지CPU를 할당받은 프로세스가 얼마의 시간동안 이용해야 하는지다중 큐프로세스의 준비 상태와 대기 상태는 큐 자료구조로 관리된다.운영체제는 해당 프로세스의 우선순위를 보고 그에 맞는 "준비 큐"에 넣는다.CPU 스케줄러는 "준비상태의 다중큐"에 들어있는 프로세스들 중에 적당한 프로세스를 선택해서 실행상태로 전환시킨다큐에는 프로세스의 PCB가 들어간다.FIFO장점 : 단순하고 직관적단점 : 한 프로세스가 완전히 끝나야 다음 프로세스가 시작, CPU 사용률 감소FIFO는 프로세스 Burst 타임에 따라 성능 차이가 심하게 난다. -> 현대 운영체제에서 잘 쓰이지 않는다.자료구조와 알고리즘일주일 간의 학습했던 내용자료구조와 알고리즘이란?자료구조 : 데이터가 어떤 구조로 저장되고 어떻게 사용되는지를 나타낸다.알고리즘 : 어떤 문제를 해결하기 위한 확실한 방법알고리즘은 자료구조에 많은 영향을 받는다.시간복잡도일반적으로 알고리즘의 속도 = 성능의 척도주로 Big-O (최악의 경우 시간복잡도) 로 시간복잡도를 계산한다.Big-O 표기법 : 계산에 영향을 많이 미치는 항만 표기한다.배열장점 : 빠른 참조 성능 -> O(1)단점 : 데이터 삽입, 삭제가 비효율적이다, 메모리 낭비 발생 가능연결리스트장점 : 초기 크기를 알 필요가 없다. (메모리 낭비 가능성 감소), 삽입/삭제가 간편함단점 : 느린 참조 성능 -> O(n)스택FILO의 구조그림판의 Ctrl + Z, 괄호 형식 체크에 쓰일 수 있다.큐FIFO의 구조스택과 반대 성질을 가진 구조이다.덱데이터의 삽입과 제거를 head, tail에서 자유롭게 할 수 있다.스택과 큐의 성질을 모두 가지고 있는 구조해시 테이블해시 함수로 인덱스를 새로 만들어서 데이터를 저장하는 구조이다.장점 : 성능이 매우 빠르다. (읽기, 삽입, 수정, 삭제 : O(1))단점 : 해시함수에 따라 메모리를 많이 차지할 수도 있다.인덱스가 같으면 충돌 현상이 있을 수 있다. -> Value를 연결리스트로 구현하면 해결 가능셋데이터의 중복을 허용하지 않는 구조해시테이블의 Value는 사용하지 않고 Key만 사용해서 구현 가능 회고칭찬하고 싶은 점 강의 스케줄을 밀리지 않고 수강한 점에 대해서 칭찬하고 싶습니다. 늦게 퇴근했던 날에는 쉬고 싶기도 했는데, 다른 스터디원들이 올려주신 블로그 글이나 디스코드에서 다양한 개발 관련 이야기를 해주시는 걸 보고 동기부여를 받고 강의를 수강했습니다. 배울 점이 많은 스터디원과 함께 하는 것 같아서 좋습니다👍아쉬웠던 점 강의를 듣다 보면 생소한 키워드들이 나올 때가 있었는데, 이에 대해서 개인적으로 공부하는 시간이 부족했던 것 같습니다. 또, 잘 이해했는지 복습하는 시간이 부족했던 것 같습니다.보완하고 싶은 점 차주부터는 강의 수강뿐만 아니라, 이해가 부족한 부분을 찾아서 개인 공부하는 시간을 늘리려고 합니다. 또, 강의를 들은 다음 날에는 복습하는 시간을 가져서 효율적인 학습을 하기 위해 노력할 것입니다. 미션 미션을 해결한 과정운영체제 미션 1번 문제는 폴링 방식으로 작성된 예제 코드를 어떻게 수정해야 인터럽트 방식으로 개선이 가능한지 고민했습니다.주기적으로 확인하는 반복문을 제거하고 ISR 메서드를 만드는 방식으로 수정했습니다.자료구조와 알고리즘 1번 문제는 답이 정해져 있지 않다고 생각해서, 특정 요구사항이 있다고 가정하고 답변을 작성했습니다. (저장하는 경우가 많은지, 열람하는 경우가 많은지 등)그 외 문제는 공부한 내용을 토대로 작성했습니다! 회고미션 해결을 하면서 학습했던 내용을 복습하게 되는 것 같아서 좋았습니다.처음에는 강의를 안 보고 답변을 작성한 후에, 강의를 보고 부족한 답변을 보완하는 방식으로 문제를 해결했는데다음 미션 때는 강의를 안 보고도 부족한 답변이 없도록 노력하겠습니다!  

김주현

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

운영체제 while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 }1. 위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다. 이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다. 이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요? 인터럽트 방식을 사용해야 합니다.폴링 방식은 주기적으로 작업이 완료됐는지 확인하기 떄문에 성능이 떨어집니다.인터럽트 방식은 작업이 완료됐을 때 신호를 주고, 신호를 받은 CPU는 인터럽트 서비스 루틴을 실행시켜서 작업을 완료하는 방식입니다.인터럽트 방식은 주기적으로 작업 완료를 확인하지 않고, 비동기적으로 동작하기 때문에 폴링 방식보다 성능이 더 좋습니다.플레이어가 스킬을 사용했을 떄 실행될 함수를 만들어서 아래처럼 수정할 수 있습니다.void checkStillActivated() { Skill skill = new Skill(); // 스킬 사용 (로직 생략) actiavteSkill(skill); // ISR 실행 } // ISR interrupt activateSkill(Skill skill) { if (skill == ATTACK) { print("Use Attack Skill") } } 2. 프로그램과 프로세스가 어떻게 다른가요?프로그램은 저장장치에 저장된 명령문의 집합체입니다.프로세스는 현재 메모리에 올라가 있는 실행 중인 프로그램입니다.컴퓨터 관점에서 보면 프로그램은 저장장치만 사용하는 수동적인 존재이지만,프로세스는 메모리, CPU를 사용하고 입출력 작업도 수행하기 때문에 능동적인 존재로 볼 수 있습니다.3. 멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?멀티프로그래밍은 메모리에 여러 개의 프로세스가 올라온 상태이고,멀티프로세싱은 CPU가 여러 개의 프로세스를 처리하는 것을 말합니다.OS는 메모리에 여러 프로그램을 올려놓고, 시분할 처리로 CPU가 여러 프로그램을 교대로 실행합니다.즉, 오늘날 OS는 멀티 프로그래밍과 멀티 프로세싱이 공존합니다.4. 운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?PCB를 사용합니다.프로세스가 만들어지면 운영체제는 이를 관리하기 위해 해당 프로세스의 정보를 가지고 있는 PCB를 만들고 저장합니다.PCB에는 다른 프로세스로 접근하기 위한 포인터, 프로세스 상태, 프로세스 ID, 프로그램 카운터, 레지스터 정보, 메모리 관련 정보, CPU 스케줄링 정보 등등 프로세스와 관련된 정보가 저장되어 있습니다. 5. 컨텍스트 스위칭이란 뭔가요?프로세스를 실행하는 중에 다른 프로세스를 실행하기 위해실행중인 프로세스의 상태를 저장하고 다른 프로세스의 상태값으로 교체하는 것을 말합니다.현재 실행중인 프로세스의 작업내용을 PCB에 저장하고,실행될 기존 프로세스의 PCB의 내용대로 CPU가 다시 세팅됩니다.컨텍스트 스위칭이 일어날 때 PCB의 프로세스 상태, 프로그램 카운터, 각종 레지스터 값들이 변경됩니다.자료구조와 알고리즘 1. 여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다. 이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요.요구사항에 따라 배열과 연결리스트 둘 중 하나를 선택할 것 같습니다.학생 정보가 추가/삭제되는 경우가 많다면 메모리의 크기를 미리 지정하기 어렵기 떄문에 연결리스트를 사용할 것이고,학생을 열람하는 경우가 많다면 참조 성능이 좋은 배열을 사용할 것 같습니다.연결리스트는 미리 크기를 지정하지 않아도 되고,배열은 데이터에 접근할 때 O(1)의 시간복잡도가 들기 때문입니다.2. 여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요.큐를 선택하겠습니다.큐는 먼저 들어온 데이터가 먼저 나가는 FIFO의 구조를 가지고 있기 때문에,먼저 들어온 주문이 먼저 처리되는 방식을 효율적으로 개발할 수 있을 것 같습니다.   

오리너구리

[인프런 워밍업 클럽 스터디 2기] 프로덕트 디자인 1주차 발자국

인프런 워밍업클럽 2기를 시작하며슬픈이유로 회사를 퇴사하고 면접 준비하고 나를 계속 증명하고 정신없는 나날을 보내다가 인프런 워밍업 클럽 공지를 보았다.개인 포트폴리오도 있어빌리티하게 가꾸고 겸사겸사 IT계의 진정한 조각의 꽃인 플랫폼 디자인 직군에 지원해 보고 싶었는데 작업 동기부여가 필요해서 워밍업 클럽을 신청하게되었다. (도깨비 방망이 하나를 냅다 파고 조각하는걸 좋아하는 강박 성향이 있어서 플랫폼 디자이너 이전부터 너무 해보고 싶은 직무였었다.)  1주차때 배운 것배리어블 등록 (색상, 간격, 타이포그래피, 아이콘, 그림자 그리드) 이전에도 강의를 듣긴 했는데 퇴사하고 오랜만에 복기하려니 또 새로웠다. 그래도 전에는 다시 뒤돌아가고 다시듣고 백버튼을 무한대로 누르면서 보는 엉금엉금 속도였는데 이제는 이해가 훨씬 빠르게 되었었다. 아쉬웠던 점내 개인 프로젝트에 적용해보지 않은 나의 습관반복 복습하는 자세도 중요하지만 개발환경이나 내 서비스에 맞게 고민해보고 베리어블을 짜볼 수 있는 경험으로 이어져야 진정한 내것이 될 것 같았다. 너무 그간 수동적이였던 건 아니였을까? 그러면서도... 맘 한켠으론 모르는데 어캄? 이해될 때까지 반복해보는것도 중요한디? 혼란스러웠다.  다음에 시도해보기포폴용 DS 개인 파일 만들어보기전에 다닌 회사에서 베리어블 나오기 전에 작업한 컴포넌트 라이브러리? 가이드라인? 정도 볼륨의 피그마 작업 파일이 있었는데 해당파일에 베리어블과 토큰 개념을 추가해서 업데이트 해보려한다. 이걸 가지고 플랫폼 디자이너 채용 공고에도 지원을 할 것이다. 경기가 너무어려워서 PD취업도 쉽지 않고 아직도 뭐해 먹고 살지 고민이지만, 절대 포기하지 않고 나만의 무기를 계속 연마해서 좋은 동료들이 있는 회사에 꼭 붙고 말것이다.

UX/UI디자인시스템DS베리어블워밍업클럽볼드님강의2기

지민철

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

운영체제섹션 1- 기초운영체제는 개인용 컴퓨터나 대형 컴퓨터, 스마트폰, 임베디드 등에 들어간다.컴퓨터는 운영체제가 있어야 동작하는가 - NO하지만 운영체제가 없으면 한가지 기능만 가능할 뿐 다양한 기능을 사용 불가능하다.옛날 전화기는 전화만 가능했지만 지금은 스마트폰의 운영체제를 통해 통화를 비롯해 다양한 기능을 사용 가능하다.- 운영체제가 하는 일프로세스 관리 -> 만약 하지 않는다면 하나의 프로세스가 CPU를 혼자 먹어서 다른 프로세스가 동작하지 않을 것이다메모리 관리 ->모든 프로그램은 메모리에 올라와서 동작하는데 다양한 방법으로 메모리를 관리한다하드웨어 관리 -> 운영체제가 판단하여 적절한 위치에 사용자의 프로그램을 저장한다파일 시스템 관리 -> 파일을 효울적으로 관리해준다- 운영체제의 역사1940 -> 애니악1950 초 -> 직접회로가 개발되었다, 펀치카드로 프로그래밍하여 넣으면 라인프린터로 출력되었다.1950 중후반 -> 50년대 초의 인간의 프로그래밍 과정이 너무 오래 걸려서 싱글스트림 배치시스템이 개발되었다.1960 -> 앞선 방법의 한계가 해결되었다, 시분할 시스템을 사용하였다, UNIX가 개발되었다.ㄴ허나 시분할 시스템으로 인해 메모리 침범 문제가 생겼다.1970 이후 -> 개인용 컴퓨터의 시대, 애플의 매킨토시와 마이크로소프트의 MS-DOS가 많이 사용되었다ㄴ매킨토시는 GUI의 적용으로 인기를 끌었다- 운영체제의 구조핵심은 커널이다, 사용자는 인터페이스(GUI,CLI)를 통해 커널에 접근한다.GUI : 그래픽으로 된 인터페이스CLI : 유닉스나 리눅스가 지원하는 인터페이스app은 시스템 콜을 통해 부른다, 시스템 콜 없이 불러져서 어플리케이션이 맘대로 저장소에 저장하면 중요한 데이터를 덮어쓰거나 할 수도 있기 때문에 시스템 콜이 필요하다. 시스템 콜은 write를 통해 저장하는데 자동으로 빈 공간에 저장하는 역할을 한다.하드웨어와 커널의 인터페이스로는 드라이버를 사용한다.운영체제는 다양한 하드웨어를 사용할 수 있어야 하는데 운영체제에 모든 하드웨어에 맞는 프로그램을 가지고 있기는 어려워서 제조사에서 드라이버를 제공하는 편이다.- 컴퓨터 하드웨어와 구조현대의 컴퓨터는 폰 노이만 구조를 하고있다. 애니악 때의 방식이 불편하다고 생각하여 이를 해결하기 위해 CPU와 메모리를 두고 버스로 연결한다.프로그램을 작동하려면 메모리에 올려야 하는데 프로그램을 메모리에 내장했다고 해서 프로그램 내장 방식이라고 한다.메인보드 -> 메인보드는 다른 하드웨어를 연결하는 역할CPU -> 중앙처리장치로 불리며 산술논리연상장치, 제어 장치, 레지스터로 이루어져있다.메모리 종류 -> RAM과 ROM으로 나누어지는데 RAM은 전력이 끊기면 저장된 값을 잃어서 메인 메모리로 사용된다. ROM은 전력이 끊겨도 값이 사라지지 않아서 부팅과 관련된 바이오스를 저장하는데 주로 쓰인다.- 컴퓨터의 부팅과정전원버튼을 통해 전력이 들어가면 바이오스가 켜진다. (바이오스는 주요 하드웨어를 체크한다)이상 없을 시 부트로더를 가져와 RAM으로 실행한다.운영체제를 모니터로 불러오고 우리가 아는 바탕화면이 나온다.- 인터럽트CPU는 입출력을 하려고 하면 입출력 관리자에게 명령을 내린다.CPU는 스스로 입출력을 하지 않기 때문에 관리자에게 지속적으로 확인을 한다.앞선 방식을 폴링 방식이라고 한다.폴링 방식은 너무 자주 신호를 보내서 성능이 좋지 않다.이런 단점을 해결한 것이 인터럽트이다.CPU는 입출력 신호를 보내고 다른 일을 한다, 만약 입출력관리자에게 신호가 온다면 ISR을 실행시킨다.ISR은 특정 인터럽트가 들어오면 그 인터럽트를 해결하는 함수이다.인터럽트는 2개의 방식으로 나누어진다하드웨어 방식 : 앞서 설명한 입출력 같은 인터럽트소프트웨어 방식 : 사용자 프로그램에서 발생한 인터럽트 (유효하지 않은 접근이나 0으로 나누기 등...)섹션 2- 프로그램과 프로세스 프로그램 : 저장장치에 저장된 명령문의 집합체(app등으로 불리고 .exe의 모양을 가지고 있다)프로세스 : 실행중인 프로그램(하드디스크에 있는 앱이 메모리로 가서 작동되면 그것이 프로세스이다)차이점 : 프로그램은 그저 명령문의 집합체인 수동적이 존재이고 프로세스는 메모리에서 CPU도 사용하고 입출력도 하는 능동적인 존재이다.프로세스의 구조는 code,data,stack,heap으로 이루어져 있다.c언어의 컴파일 과정파일 -> 전처리기 -> .i로 변경 -> 컴파일러 -> .s로 변경 -> 어셈블러로 변경 -> .o로 변경 -> 링커 -> .exe로 변경위 과정을 걸쳐 exe파일을 더블클릭하면 메모리로 올라가고 운영체제가 관리를 한다.- 멀티프로그래밍과 멀티프로세싱유니프로그래밍 : 메모리에 오직 하나의 프로세스가 올라온 상황멀티프로그래밍 : 메모리에 여러개의 프로세스가 올라온 상황멀티프로세싱 : CPU가 여러 개의 프로세스를 처리하는 것을 말한다현대에는 멀티프로그래밍과 멀티프로세싱이 있다.옛날에는 메모리의 크기가 작아서 멀티프로그래밍이 불가능해서 유니프로그래밍으로 멀티프로세싱을 했다.유니프로그래밍(옛날) : 메모리에 프로그램 올리기 -> 실행 -> 저장장치에 상태 저장하고 넣기 -> 다른 프로그램 메모리에 두기 -> 새로 가져온 프로그램 실행하기(프로그램을 메모리와 저장장치 사이로 옮기는 것을 스와핑이라고 한다)- PCB(Process Control Block)운영체제는 여러개의 프로세스를 알고리즘에 따라 실행시켜야 한다.프로세스가 만들어지면 해당 프로세스의 정보를 가지고 있는 PCB를 만들고 저장한다.(연결리스트 자료구조의 형이다)운영체제는 프로세스가 종료되면 연결리스트에서 해당 프로세스의 PCB를 제거한다.구조 : 프로세스 구조, 프로세스 ID, 프로그램 카운터, 레지스터 정보 등....- 프로세스 상태사용자가 프로그램을 실행시키면 메모리에 올라가면서 프로세스가 생성된다.운영체제가 프로세스를 관리하기 위해 프로세스 상태라는 것이 존재한다.생성상태 : PCB를 생성하고 메모리에 프로그램 적재를 요청준비상태 : 적재승인 시 적재를 기다리고 있는 상태대기상태 : 프로세스가 입출력 요청을 할 시 입출력이 올 때 까지 대기상태로 변환, 입출력이 끝날 시 준비상태로 이동실행상태 : 실행상태에 있는 프로세스의 수는 CPU의 개수와 같다.(부여된 시간만큼만 CPU사용 가능, 시간이 끝날 시 준비상태로 변함)완료상태 : 프로세스가 종료된 상태- 콘텍스트 스위칭시분할 처리 중 다른 프로세스를 실행하기 위해 현재 프로세스의 상태를 저장하고 다른 프로세스의 상태값으로 바꾸는 작업콘텍스트 스위칭이 일어나면 PCB의 내용이 변경된다.작업중이었던 내용을 PCB에 저장하고 다음 프로세스의 PCB내용을 토대로 CPU의 상태를 바꾼다.발생 이유는 다양하지만 인터럽트나 CPU점유시간이 끝났을 때 일어난다.- 프로세스 생성과 종료프로세스가 생성될때의 가정은 이러하다.exe파일 더블클릭운영체제가 프로그램의 코드영역과 데이터영역을 로드하고 빈 스택과 빈 힙을 만들어 공간을 확보한다.PCB를 만들어서 값을 초기화한다.위 방법은 부팅될때 1번만 실행되고 그 뒤로는 0번 프로세스(1~3번 과정에서 만들어진 프로세스)를 복사하여 사용한다.복사하여 생성되는 프로세스는 자식 프로세스라고 하며 반대로는 부모 프로세스라고 한다.주로 부모 프로세스가 자식프로세스에게 시작 신호를 보내고 자식이 종료 신호를 보내면 부모 프로세스가 자식 프로세스를 종료시킨다.하지만 부모 프로세스가 먼저 사라지거나 자식프로세스가 종료 신호를 보내지 못하고 사라지면 종료되지 못하고 남아있는 좀비 프로세스가 생긴다. 이러한 프로세스는 컴퓨터의 성능 저하를 유발하나 컴퓨터를 껐다가 키면은 사라진다.- 쓰레드운영체제의 작업 처리 단위는 프로세스이다.사용자가 운영체제에게 작업을 요구하면 그만큼 프로세스의 수가 늘어난다.프로세스가 생성되는 PCB가 생성되고 코드,데이터,스택,힙 등의 영역이 생긴다.만약 웹브라우저를 20개 틀면 20번 복제되고 메모리의 사용량이 너무 많아진다.앞선 문제를 해결하기 위해 쓰레드를 고안해냈다.쓰레드는 프로세스 안에 존재하며 여러개가 있을 수 있다.프로세스 내에 쓰레드들은 PCB, 코드, 데이터,힙 영역을 공유한다.쓰레드를 관리하기 위해 ID를 부여하고 TCB도 생겼다.이렇게 되면 운영체제가 작업을 관리하는 단위는 쓰레드가 되었다.이렇게 되면 탭을 생성할 때 최초생성은 프로세스가 생격나지만 탭을 추가하면 프로세스가 아닌 쓰레드가 추가된다.프로세스와 쓰레드의 장단점프로세스는 독립적이어서 하나가 문제가 생겨도 문제가 생기지 않는다.허나 쓰레드는 예를 들어 힙 영역이 문제가 생기면 공유하는 모든 프로세스가 문제가 생긴다--프로세스는 모든 자원을 각각의 프로세스가 가지고 있어서 통신하려면 IPC통신을 사용해야 하는데 오버헤드가 크고 속도가 느리다.반면 쓰레드는 다양한 자원을 공유해서 오버헤드가 굉장히 작다.섹션 3- CPU스케줄링 개요프로그램을 실행하면 메모리에 프로세스가 생기고, 그 안에는 1개 이상의 쓰레드가 있다.프로세스들은 CPU를 사용하기 위해서 운영체제의 명령을 기다린다.운영체제는 모든 프로세스들에게 CPU 할당/해제하는데 이를 CPU스케줄링이라고 한다.오늘날 운영체제는 프로세스들을 시분할 처리방식으로 CPU를 할당한다.- 다중큐프로세스들은 준비 상태에 있다가 운영체제의 명령으로 실행 상태가 된다, 그 후 지정된 시간이 끝나면 준비 상태, I/O가 필요하면 대기 상태, 끝나면 완료 상태로 변한다.이 중 준비와 대기는 큐 자료구도로 작동된다.작동은 선입선출구조이다.(FIFO)운영체제는 준비상태에 프로세스가 있으면 다양한 프로세스 중 우선순위를 보고 그에 맞는 '준비 큐'에 넣는다.또한 대기상태에 있는 프로세스는 동류에 따라 다른 큐에 넣는데 예를 들어 하드디스크를 사용하는 경우에는 HDD큐에 들어가고 키보드를 사용하면 키보드 큐에 넣는다.(자세히는 프로세스 그 자체보다는 PCB가 들어간다)- 스케줄링 목표리소스 사용률CPU 혹은 I/O디바이스 사용률을 높이는 것이 목표이다.오버헤드 최소화공평성처리량 증가대기시간 감소 응답시간 앞선 목표들을 다 맞추기는 힘들다.그 이유는 목표가 서로 상반되는 경우도 있기 때문이다.- FIFOCPU스케줄링 알고리즘 중 하나.가장 정석적인 알고리즘으로 먼저 들어온 순서대로 CPU를 할당받는 방식이다.마트의 계산대와 같은 느낌이다.장점 : 단순하고 직관적단점 : 순서가 가장 중요하기에 비효율적인 상황이 생길 수 있다(예시 I/O작업)스케줄링의 성능은 평균 대기시간으로 정한다.현대 운영체제에서는 잘 쓰이지 않고 일괄처리시스템에 쓰인다.자료구조와 알고리즘섹션 1- 하고 싶은 말알고리즘은 무지성으로 따라하거나 암기하는 것이 아닌 이해하는 것이 문제를 해결 할 때 가장 좋다.- 자료구조와 알고리즘이란자료구조자료구조란 테이터가 어떤 구조로 저장되고 어떻게 사용되는지를 나타냅니다.가장 단순한 자료구조는 변수이다.그 외에도 사용했었던 자료구조는 배열이 있다.a = 87 b = 70 c = 100 average = (a+b+c)/3arr = [87,70,100] average = 0 for i in arr: average+=i average/=len(average)위의 코드 예시처럼 자료구조 간의 사용 방법과 저장된 모양도 다르다알고리즘어떤 문제를 해결하기 위한 확실한 방법예를 들어 평균을 구하는 문제를 풀 때는 알고리즘이 필요하다- 시간 복잡도보통 시간이 가장 적게 걸리는 알고리즘을 좋은 알고리즘이라고 한다.보통 반복문이 시간에 영향을 미쳐서 반복문으로 성능을 확인한다.예를 들어 5개의 리스트에서 특정 숫자를 찾을 때 처음부터 찾는다면 최악의 경우 리스트의 길이만큼 체크한다.이런 경우를 O(n)이라고 한다.상수시간 알고리즘은 O(1)로 표현한다.(문제를 해결할 때 입력과 상관없이 계산량이 같을 때 이다)그 외에도 O(nlogn), O(n^2), O(2^n)등이 있다.섹션 2- 배열일반전인 배열배열을 선언하면 운영체제가 그 크기만큼 빈 공간을 찾아서 순서대로 값을 선언한다.운영체제는 배열의 첫번쨰 주소만 저장한다운영체제는 배열의 시작 주소를 기준으로 가져온다(O(1)의 성능)데이터의 삽입,삭제는 느리다만약 할당된 공간의 크기를 넘기면 운영체제는 새로 빈 공간을 찾는다.물론 처음부터 큰 크기의 배열을 만들면 편하겠지만 메모리 사용량이 너무 크다JS식 배열js배열은 불연속적으로 할당하고 내부적으로 연결한다기능상 배열이라고 부를 수 있다- 연결리스트연결리스트 - 개념개발자들은 배열의 단점을 해결하기 위해 연결리스트를 만들었다연결리스트는 노드로 이루어져있다노드는 다음 노드의 주소를 알고있다. 즉, 처음 노드의 주소만 알면 모든 노드를 찾을 수 있는 것이다장점연결리스트는 새로 삽입하면 주소만 바뀌주면 되서 문제가 없다또한 삭제도 노드를 지우고 주소를 바꾸면 된다단점배열은 데이터 접근이 O(1)의 성능으로 아주 빠르다. 허나, 연결리스트는 1번부터 천천히 가야해서 O(n)의 성능이다.선택참조가 메인이라면 배열삽입&삭제가 메인이라면 연결리스트연결리스트 - 구현import { Node, LinkedList } from "./LinkedList.mjs"; let node1 = new Node(1); let node2 = new Node(2); let node3 = new Node(3); node1.next = node2; node2.next = node3; console.log(node1.data); console.log(node1.next.data); console.log(node1.next.next.data); let list = new LinkedList(); console.log("========= insertAt() 다섯 번 호출 =========="); list.insertAt(0, 0); list.insertAt(1, 1); list.insertAt(2, 2); list.insertAt(3, 3); list.insertAt(4, 4); list.printAll(); console.log("======= clear() 호출=========="); list.clear(); list.printAll(); console.log("======= insertLast() 호출=========="); list.inserLast(0); list.inserLast(1); list.inserLast(2); list.printAll(); console.log("======= deleteAt() 호출=========="); list.deleteAt(0); list.printAll(); list.deleteAt(1); list.printAll(); console.log("======= deleteLast() 호출=========="); list.inserLast(5); list.deleteLast(); list.deleteLast(); list.printAll(); console.log("======= getNodeAt() 호출=========="); list.inserLast(1); list.inserLast(2); list.inserLast(3); list.inserLast(4); list.inserLast(5); let secondNode = list.getNodeAt(2); console.log(secondNode);class Node { constructor(data, next = null) { this.data = data; this.next = next; } } class LinkedList { constructor() { this.head = null; this.count = 0; } printAll() { let currentNode = this.head; let text = "["; while (currentNode != null) { text += currentNode.data; currentNode = currentNode.next; if (currentNode != null) { text += ", "; } } text += "]"; console.log(text); } clear() { this.head = null; this.count = 0; } insertAt(index, data) { if (index > this.count || index < 0) { throw new Error("범위를 넘어갔습니다."); } let newNode = new Node(data); if (index == 0) { newNode.next = this.head; this.head = newNode; } else { let currentNode = this.head; for (let i = 0; i < index - 1; i++) { currentNode = currentNode.next; } newNode.next = currentNode.next; currentNode.next = newNode; } this.count++; } inserLast(data) { this.insertAt(this.count, data); } deleteAt(index) { if (index >= this.count || index < 0) { throw new Error("제거할 수 없습니다."); } let currentNode = this.head; if (index == 0) { let deleteNode = this.head; this.head = this.head.next; this.count--; return deleteNode; } else { for (let i = 0; i < index - 1; i++) { currentNode = current.next; } let deleteNode = currentNode.next; currentNode.next = currentNode.next.next; this.count--; return deleteNode; } } deleteLast() { return this.deleteAt(this.count - 1); } getNodeAt(index) { if (index >= this.count || index < 0) { throw new Error("범위를 넘어갔습니다."); } let currentNode = this.head; for (let i = 0; i < index; i++) { currentNode = currentNode.next; } return currentNode; } } export { Node, LinkedList }; -스택스택 - 개념스택이란 단순한 규칙을 가지고 있는 배열작동 구조는 FILO(First In Last Out) (선입후출)예시 : 엘리베이터에 타는 사람들 등구현의 개념삽입은 오직 첫번째에(head 위치)삭제도 오직 첫번째만(head 위치)스택 - 구현import { Stack } from "./stack.mjs"; let stack = new Stack(); console.log("===첫 번째 출력===="); stack.push(1); stack.push(2); stack.push(3); stack.push(4); console.log(stack.pop().data); console.log(stack.pop().data); console.log(stack.pop().data); console.log(stack.pop().data); console.log("===두 번째 출력===="); stack.push(1); stack.push(2); stack.push(3); stack.push(4); console.log(stack.peek().data); stack.pop(); console.log(stack.peek().data); console.log(`isEmpty: ${stack.isEmpty()}`); stack.pop(); stack.pop(); stack.pop(); console.log(`isEmpty: ${stack.isEmpty()}`); console.log(stack.pop()); import { LinkedList } from "./LinkedList.mjs"; class Stack { constructor() { this.list = new LinkedList(); } push(data) { this.list.insertAt(0, data); } pop() { try { return this.list.deleteAt(0); } catch (e) { return null; } } peek() { return this.list.getNodeAt(0); } isEmpty() { return this.list.count == 0; } } export { Stack }; - 큐큐 - 개념리스트의 일종선입선출, FIFO운영체게가 프로세스를 큐에 넣고 CPU가 들어온 순서대로 실행구현의 개념삽입은 head에삭제는 tail에(tail : 마지막 노드 위치)tail삭제 후 이전 노드를 tail로 지정해야하기 때문에 이중연결리스트를 사용큐 - 구현class Node { constructor(data, next = null, prev = null) { this.data = data; this.next = next; this.prev = prev; } } class DoublyLinkedList { constructor() { this.head = null; this.tail = null; this.count = 0; } printAll() { let currentNode = this.head; let text = "["; while (currentNode != null) { text += currentNode.data; currentNode = currentNode.next; if (currentNode != null) { text += ", "; } } text += "]"; console.log(text); } clear() { this.head = null; this.count = 0; } insertAt(index, data) { if (index > this.count || index < 0) { throw new Error("범위를 넘어갔습니다."); } let newNode = new Node(data); if (index == 0) { newNode.next = this.head; if (this.head != null) { this.head.prev = newNode; } this.head = newNode; } else if (index == this.count) { newNode.next = null; newNode.prev = this.tail; this.tail.next = newNode; } else { let currentNode = this.head; for (let i = 0; i < index - 1; i++) { currentNode = currentNode.next; } newNode.next = currentNode.next; newNode.prev = currentNode; currentNode.next = newNode; newNode.next.prev = newNode; } if (newNode.next == null) { this.tail = newNode; } this.count++; } inserLast(data) { this.insertAt(this.count, data); } deleteAt(index) { if (index >= this.count || index < 0) { throw new Error("제거할 수 없습니다."); } let currentNode = this.head; if (index == 0) { let deleteNode = this.head; if (this.head.next == null) { this.head = null; this.tail = null; } else { this.head = this.head.next; this.head.prev = null; } this.count--; return deleteNode; } else if (index == this.count - 1) { let deleteNode = this.tail; this.tail.prev.next = null; this.tail = this.tail.prev; this.count--; return deleteNode; } else { for (let i = 0; i < index - 1; i++) { currentNode = current.next; } let deleteNode = currentNode.next; currentNode.next = currentNode.next.next; currentNode.next.prev = currentNode; this.count--; return deleteNode; } } deleteLast() { return this.deleteAt(this.count - 1); } getNodeAt(index) { if (index >= this.count || index < 0) { throw new Error("범위를 넘어갔습니다."); } let currentNode = this.head; for (let i = 0; i < index; i++) { currentNode = currentNode.next; } return currentNode; } } export { Node, DoublyLinkedList };import { DoublyLinkedList } from "./DoublyLinkedList.mjs"; class Queue { constructor() { this.list = new DoublyLinkedList(); } enqueue(data) { this.list.insertAt(0, data); } dequeue() { try { return this.list.deleteLast(); } catch (e) { return null; } } front() { return this.list.tail; } isEmpty() { return this.list.count == 0; } } export { Queue };import { Queue } from "./Queue.mjs"; let queue = new Queue(); console.log("====== enqueue() 세 번 호출=========="); queue.enqueue(1); queue.enqueue(2); queue.enqueue(3); console.log(queue.front()); console.log("===== dequeue() 네 번 호출 ======"); console.log(queue.dequeue()); console.log(queue.dequeue()); console.log(queue.dequeue()); console.log(queue.dequeue()); console.log(`isEmpty: ${queue.isEmpty()}`); - 덱덱 - 개념덱은 삽입삭제를 head와 tail에서 자유롭게 하는 자료구조이다.덱을 이용하면 스택과 큐를 다 구현할 수 있다.덱 - 구현import { DoublyLinkedList } from "./DoublyLinkedList.mjs"; class Deque { constructor() { this.list = new DoublyLinkedList(); } printAll() { this.list.printAll(); } addFirst(data) { this.list.insertAt(0, data); } removeFirst() { return this.list.deleteAt(0); } addLast(data) { this.list.insertAt(this.list.count, data); } removeLast() { return this.list.deleteLast(); } isEmpty() { return this.list.count == 0; } } export { Deque };import { Deque } from "./Deque.mjs"; let deque = new Deque(); console.log("==== addFirst ====="); console.log(deque.isEmpty()); deque.addFirst(1); deque.addFirst(2); deque.addFirst(3); deque.addFirst(4); deque.addFirst(5); deque.printAll(); console.log(deque.isEmpty()); console.log("\n"); console.log("======== removeFirst ========="); deque.removeFirst(); deque.printAll(); deque.removeFirst(); deque.printAll(); deque.removeFirst(); deque.printAll(); deque.removeFirst(); deque.printAll(); deque.removeFirst(); deque.printAll(); console.log(deque.isEmpty()); console.log("\n"); console.log("========= addList========"); deque.addLast(1); deque.addLast(2); deque.addLast(3); deque.addLast(4); deque.addLast(5); deque.printAll(); console.log(deque.isEmpty()); console.log("\n"); console.log("=====removeLast===="); deque.removeLast(); deque.printAll(); deque.removeLast(); deque.printAll(); deque.removeLast(); deque.printAll(); deque.removeLast(); deque.printAll(); deque.removeLast(); deque.printAll(); console.log(deque.isEmpty()); - 해시테이블해시테이블 - 개념해시테이블은 언어마다 여러가지 이름으로 불린다해시맵해시맵딕셔너리이름처러 해시+테이블인 자료구조이다해시테이블은 key 와 value로 이루어져있고 삽입, 수정 등이 O(1)의 시간이 걸린다.장점빠른 데이터 탐색, 삽입, 삭제 등..단점공간의 효율성이 좋지 않다좋은 해시 함수의 구현이 필수적해시테이블 - 구현import { DoublyLinkedList } from "./DoublyLinkedList.mjs"; class HashData { constructor(key, value) { this.key = key; this.value = value; } } class HashTable { constructor() { this.arr = []; for (let i = 0; i < 10; i++) { this.arr[i] = new DoublyLinkedList(); } } hashFunction(number) { return number % 10; } set(key, value) { this.arr[this.hashFunction(key)].insertAt(0, new HashData(key, value)); } get(key) { let currentNode = this.arr[this.hashFunction(key)].head; while (currentNode != null) { if (currentNode.data.key == key) { return currentNode.data.value; } currentNode = currentNode.next; } return null; } remove(key) { let list = this.arr[this.hashFunction(key)]; let currentNode = list.head; let deletedIndex = 0; while (currentNode != null) { if (currentNode.data.key == key) { return list.deleteAt(deletedIndex); } currentNode = currentNode.next; deletedIndex++; } return null; } } export { HashTable };import { HashTable } from "./HashTable.mjs"; let hashTable = new HashTable(); hashTable.set(1, "이운재"); hashTable.set(4, "최진철"); hashTable.set(20, "홍명보"); hashTable.set(6, "유상철"); hashTable.set(22, "송종국"); hashTable.set(21, "박지성"); hashTable.set(5, "김남일"); hashTable.set(10, "이영표"); hashTable.set(8, "최태욱"); hashTable.set(9, "설기현"); hashTable.set(14, "이천수"); console.log(hashTable.get(1)); hashTable.remove(1); console.log(hashTable.get(1)); console.log(hashTable.get(21)); - 셋셋 - 개념셋은 오직 데이터의 중복을 허용하지 않는 자료구조헤시 셋이라고도 불린다셋 - 구현import { HashTable } from "./HashTable.mjs"; class HashSet { constructor() { this.HashTable = new HashTable(); } add(data) { if (this.HashTable.get(data) == null) { this.HashTable.set(data, -1); } } isContain(data) { return this.HashTable.get(data) != null; } remove(data) { this.HashTable.remove(data); } clear() { for (let i = 0; i < this.HashTable.arr.length; i++) { this.HashTable.arr[i].clear(); } } isEmpty() { let empty = true; for (let i = 0; i < this.HashTable.arr.length; i++) { if (this.HashTable.arr[i].count > 0) { empty = false; break; } } return empty; } printAll() { for (let i = 0; i < this.HashTable.arr.length; i++) { let currentNode = this.HashTable.arr[i].head; while (currentNode != null) { console.log(currentNode.data.key); currentNode = currentNode.next; } } } } export { HashSet };import { HashSet } from "./HashSet.mjs"; let hashSet = new HashSet(); console.log(hashSet.isEmpty()); console.log("=========add========="); hashSet.add(1); hashSet.add(1); hashSet.add(123); hashSet.add(512); hashSet.printAll(); console.log(hashSet.isEmpty()); console.log("=========check========="); console.log(hashSet.isContain(1)); console.log("=========remove========="); hashSet.remove(1); hashSet.printAll(); console.log(hashSet.isEmpty()); console.log("=========check2========="); console.log(hashSet.isContain(1)); console.log("=========clear========="); hashSet.clear(); hashSet.printAll(); console.log(hashSet.isEmpty());

양성빈

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

이 블로그 글은 박우빈님의 강의를 참조하여 작성한 글입니다.드디어 0기때 이후 첫 발자국을 작성해보는 시간이다. 처음 마음 먹었던 초심을 생각하며 0기때보다 더 나은 활동을 해보자고 다짐하며 이 글을 써내려간다.강의 소개처음 이 강의를 듣기 전, 나는 아래와 같이 생각했다.🤔 읽기 좋은 코드가 과연 무엇일까? 읽기 좋은 코드는 왜 필요할까?해당 물음을 가지고 강의를 듣기 시작하였다.우리는 코드를 작성(쓰기)보단 읽는데 시간을 더 많이 투자한다. 기존 코드에 내 코드를 추가하기 위해 내가 과거에 작성한 코드 혹은 다른 동료분들이 작성한 코드를 읽는다고 해보자. 하지만 이해가 안된다면 다시금 읽게 될 것이다. 그리고 많은 시간 끝에 이해라는 경지에 도달하거나 절망이라는 경지에 도달할 것이다. 결국 코드를 작성한다는 것은 모두가 이해하기 쉬운 읽기 기반의 코드를 작성한다는 의미이다. 그리고 코드를 잘 짠다라고 말하는 것은 결국 읽기가 좋다는 의미이고 읽기 좋은 코드는 결국 미래를 위해 유지보수를 위해 필요한 작업이라고 생각이 든다.또한 우린 가끔 이런 말을 하곤 한다. 나도 몇번 들었던 말이다.코드는 작성하고 난 순간부터 레거시다.여기서 레거시란, 오래되고 유지보수가 힘든 코드라고 생각하면 된다. 즉, 우리가 작성한 코드들은 먼 훗날의 레거시 코드가 되고 이 레거시 코드들을 유지보수 할 미래의 나 혹은 동료들을 위해 읽기 쉬운 코드를 작성함이 좋을듯 싶어진다. 나 또한 이번에 제대로 학습하여 실무에도 적용해볼 수 있는 기회가 되었으면 한다.✅ 읽기 쉬운 코드 작성하는 현재까지 생각- 미래를 위해 그래야함- 유지보수 하기 좋음- 미래의 나와 동료를 위해 읽기 쉬운 클린코드를 작성해야함. 강의 구성클린코드, 리팩토링 과정의 최고의 연습은 테스트코드를 작성하는 것이다.테스트 코드를 작성문화를 가진 기업들은 일반적으로 아래의 절차를 가진다.🛠 리팩토링 프로세스 (주관적인 생각)1. 리팩토링 대상/범위 확인2. 기능보장을 위한 테스트 코드 작성3. 리팩토링4. 테스트 코드 검증위의 프로세스로 리팩토링을 진행하지만 우빈님께서는 현재 테스트코드 없이 진행한다고 하셨다. 또한 롬복도 사용을 하지 않으신다고 하며, 순수코드에 집중한다고 하셨다.나 또한 이번에 우빈님 말씀대로 순수코드에 집중해보며, 시간과 여유가 있을 시, 내가 스스로 테스트 코드도 작성해봄이 좋을 것 같다! 강의에 사용할 용어들 📚 용어정리- 도메인(domain): 실무에 자주 사용되는 말들로, 해결하고자하는 문제영역들을 말한다.(비즈니스 요구사항 함축)- 도메인 지식: 도메인을 이해하고 해결하는데 필요한 지식- 레거시, 유산: 우리가 현자 가지고 있는 코드- 조상: 과거의 나 / 동료 / 이 코드를 작성했던 개발자분들- 후손: 미래의 나 / 동료 / 내가 만든 코드들을 보게 될 많은 개발자분들 우리가 클린코드를 추구하는 이유 우리는 왜 클린코드라는 것을 지켜야 하는걸까? 결론부터 말하면 가독성때문이다. 가독성이 좋다라는 것은 이해가 잘된다는 것을 말하며 그것은 곧 유지보수가 수월해지며 그 만큼 우리의 시간과 자원을 절약한다. 세상에는 클린코드라 지칭하는 수많은 원칙들과 조언들이 존재한다. 하지만 이런 원칙들을 관통하는 아주 중요한 주제가 있는데 그게 바로 추상이다. 이번부터 추상을 한번 알아보자. 프로그램의 정의 그러면 추상이라는 것을 구체적으로 들어가기 전에 프로그램이 무엇인지 알아보자. 내가 생각하는 프로그램은 아래와 같다. 프로그램 = 설치하는 것 쉽게 생각해서 프로그램은 설치하는것이라 알고 있었다. 거기서 프로그램의 구조는 데이터 + 코드로 이루어진다 생각한다. 그래서 앞으로 이 2가지를 가지고 데이터의 추상과 코드의 논리를 가지고 학습해볼 예정이다. 추상과 구체 이제 본격적으로 추상을 들어가보자. 추상하면 같이 따라 다니는 단어가 있는데 그것이 바로 구체이다. 이 두 단어는 매우 중요한 단어이다. 추상이라는 단어가 무엇일까? 우빈님께서 한자와 위키백과, 피카소의 명언을 참조하셔서 말씀을 해주셨듯이 추상은 아래와 같다. 📚 추상- 구체적인 정보에서 어떤 이미지를 뽑아내는 것이다- 중요한 정보는 가려내어 남기고 덜 중요한 정보는 생략하여 버린다.- 추상은 항상 구체적인 실제에서 시작해야한다.(feat. 피카소) 즉, 위에 이야기를 토대로 나온 것이 추상화 레벨이다. 즉, 추상화라 하는 것은 내가 생각했을 때 추상적인 것이 몇 %이고 구체적인것이 몇 %이냐라는 것이다. 쉽게 비유하면 이런것이다. 친구와 이야기를 나눌때 진지함 30%이고 농담 70% 주제야!라고 한다. (개인적인 이야기) 아무튼 추상화는 중요한것 같다. 하지만 막상 너무 어렵게 느껴진다. 하지만 오히려 인간은 추상화 능력이 매우 뛰어난 존재이다. 예시를 보자. 친구와 아래와 같이 이야기를 했다 해보자. 🗒 예시Q. 주말에 뭐했어?A. 나는 하나의 큰 공간에서 나의 신경을 이용해 나의 걷는 수단으로 하나의 큰 구체를 차는 행위를 했어! 이렇게 했을 때 친구의 반응은 아래와 같을 수 있다. 하지만 우리는 유추를 어느정도 해볼 수 있다. 🗒 예시Q. 주말에 뭐했어?A. 축구했어! 첫번째 예시는 구체이고 바로 위의 예시가 추상화 과정이다. 추상화: 정보 함축, 제거 구체화: 유추, 정보재현 이해 이것은 컴퓨터 과학에서도 사용된다. 🙋🏻 컴퓨터는 0과 1밖에 모르는데 어떻게 고수준의 작업을 할까? 먼저 정답을 이야기하면 바로 추상화과정때문이다. 그럼 자세히 들어가보자. 1bit가 무엇일까? 0과 1을 의미한다. 이것은 정보의 최소단위이고 이것은 결국 전구의 켜짐과 꺼짐을 나타내는데 이것을 존재성이라 한다. 1byte는 무엇일까? 용량의 최소단위이며 8bit를 묶어서 1byte라 한다. 또한 프로그래밍 언어에서 자료형을 이야기할때 몇byte를 묶어서 하나의 자료형을 나타낸다. 여기서 데이터(bit) 덩어리를 짤라서 묶고 어떻게 읽을것인가이다. 즉, 이것이 추상화이다. 또한 AND나 OR같은 논리 연산식도 데이터와 데이터가 만나 새로운 데이터를 만드는 방법을 의미한다. 즉, 종합해보면 이전에 프로그램을 데이터와 코드로 나타냈는데 위의 예시를 통해 각각 추상화가 가능하다는 것을 알 수 있다. 그러면 처음 질문으로 돌아가서 고수준 작업은 무엇일까? 고수준이라는 것은 추상화 레벨이 높다는 것이고 그와 반대로 저수준은 추상화 레벨이 낮다는 것이다. 대표적인 예시로 프로그래밍 언어와 기계어, 하드웨어와 운영체제와 어플리케이션, OSI7 Layer를 예로 보면 확 알 것이다. 그런데 우리는 읽기 좋은 코드를 이야기 하고 있는데 왜 추상화 과정이 필요할까? 적절한 추상화는 복잡한 데이터와 복잡한 로직을 단순화하여 이해하기 쉽도록 돕는다. 즉, 읽기 쉽다! 예시를 통해 보자. 성빈나라에 축구라는 것을 뻥뻥이라고 해보자. 그리고 친구한테 뻥뻥이했다라고 말하면 친구는 못알아 들을 것이다. 이렇게 못알아 듣는 이유 즉, 추상으로부터 구체를 유추하지 못한 이유는 추상화 과정에서 중요정보를 부각시키지 못했고 상대적으로 덜 중요한 정보를 제거했기 때문이다. 또한 해석자가 동일하게 공유하는 문맥이 아니기 때문이다. 이 말은 중요한 정보는 기준이 각각 다르고 즉, 도메인 별로 추상화 기준이 다르다는것을 알 수 있다. 그래서 다른 실무진들이 도메인 지식이 중요하다는 것도 이와 같기 때문이라 생각이 든다. 잘못된 추상화는 side-effect를 유발하며 이는 매우 critical하다. 적절한 추상화는 해당 도메인의 문맥 안에서 정말 중요한 핵심개념만 남겨서 표현한다. 적절한 추상화의 대표적인 행위가 바로 이름짓기인데 한번 이름짓기에 대해 살펴보자. 이름 짓기 개발자들이 업무를 하면서 무엇이 가장 힘드냐고 물어보면 10의 9은 "이름짓기"가 힘들다고 말한다. 나 또한 실무에서 변수명같은것을 짓는데만 30분을 소비한 경험이 있곤 하다. 그런데 진짜로 이름 잘 짓는게 중요할까? 나는 중요하다고 본다. 중요하지 않은 일을 이렇게 시간투자하면서 많은 개발자들이 힘들게 시간을 투자하고 있지 않을 것이다. 이름 짓는다는 행위는 추상적인 사고를 기반으로 한다.추상적인 사고는 첫째, 표현하고자 하는 구체에서 정말 중요한 핵심개념만을 추출하여 잘 드러내는 표현이며, 우리 도메인의 문맥안에서 이해되는 용어이다. 그럼 이름 짓는 주의 점들을 살펴보겠다. 단수, 복수 구분 끝에 -(e)를 붙여서 어떤 데이터(변수, 클래스)가 단수인지 복수인지 나타내는 것만으로도 읽는이에게 중요한 정보를 전달 할 수 있다. 이름 줄이지 않기 줄임말이라는 것은 가독성을 제물로 바쳐 효율성을 얻는 것으로 대부분 잃는 것에 비해 얻는 것이 적다. 즉, 자재하는 것이 좋으나 관용어처럼 많이 사람들이 사용하는 줄임말이 존재한다. column → col, latitude → lat, longitude → lon, count -> cnt 위의 예시에서 count를 줄이는 것은 우빈님은 비추하신다고 하셨다. 왜냐하면 겨우 5글자에서 3자로 줄이고 cnt만 봤을때 count라고 연상이 안된다고 하셨는데 그 이야기를 들어보니 나도 뭔가 와 닿지 않았다. 이전까지 실무에서도 귀찮을때 이렇게 줄이곤 했는데 조금 반성하게 되는 계기가 된 것 같았다. 또한 자주 사용하는 줄임말이 이해할 수 있는 것은 사실 문맥을 보고 알 수 있다. 예를 들어 익명 클래스에 저런 관용어가 있다고 해보자. 처음 보는 신입 개발자는 알 수 없을 것이다. 은어, 방언 사용 X 농담에서 파생된 용어, 일부 팀원, 현재 우리팀만 아는 은어 금지해야한다. 만약 다른 개발자가 해당 코드를 보면 이해하기 힘들기 때문이다. 또한 되도록 도메인 용어를 사용하자! 우리도 실무에서 도메인 용어 사전을 엑셀로 만들어서 사용하곤 한다. 이러닝 도메인을 가진 우리의 예로 보면 스코라는 단위를 표현할때 sco라는 표현 혹은 sc를 많이 사용한다. 물론 이렇게 정의되었더라도 하나로 정하면 그 프로젝트에서는 그것으로 밀고 사용해야한다. 좋은 코드 보고 습득하기 비슷한 상황에서 자주 사용하는 용어, 개념을 습득하자. github에 open되어 있는 라이브러리나 프레임워크의 코드를 보면서 용어들을 정리해 볼 필요가 있다고 느껴졌다. ex. pool, candidate, threshold등 (일상 용어 != 코드용어) 그럼 이제 코드를 통해 우빈님이 제공해준 코드를 고쳐보자. 자세한 것은 강의를 통해 확인해보고 간략히만 설명해보겠다. 아래와 같이 의미가 없는 변수들을 변경해보았다. 대표적으로 for문의 i와 j의 변수를 아래와 같이 변경해보았다. for (int row = 0; row < 8; row++) {   for (int col = 0; col < 10; col++) {     board[row][col] = "□";   } } 이런식으로 나머지도 수정을 해보았다. 추가적으로 나는 주석도 달아보았다. 주석이 없으니 우빈님과 코드를 읽으면서 뭔가 난해한 부분도 많기 때문에 주요 로직에 주석을 다는것도 Readable code이지 않을까? 메서드와 추상화 잘 쓰여진 코드의 메서드는 반드시 1개의 주제를 가져야 한다. 메서드의 선언부로 우리는 구체적인 내용을 추상화 할 수 있다. 만약 그렇게 하기 힘들다면 그 메서드는 2가지 이상의 일을 하고 있다고 볼 수 있다. 역할분리가 힘든 메서드라고 나는 생각한다. 그래서 메서드를 작성할때 생략할 정보와 의미를 부여하고 드러낼 정보를 구분하는것이 중요하다. 즉, 추상화가 중요하다. 만약 아까처럼 메서드 내용을 보고 이름을 유추하기 힘들다면 그 메서드 안에 의미를 담을 수 있는 더 작은 단위로 쪼개고 그 쪼갠것을 보고 하나의 유추할 수 있는 포괄적 의미의 메서드 이름을 적어보는 것이 좋을 것 같다. 메서드 선언부 메서드 선언부는 아래와 같이 구성되어 있다. 반환타입 메서드명(파라미터) {} ✅ 용어정리메서드 명과 파라미터를 통틀어서 메서드 시그니처라는 용어를 사용한다.메서드 시그니처를 통해서 자바에서 오버로딩이 가능하다. 메서드는 추상화된 구체를 유추할 수 있는 적절한 의미가 담긴 이름이어야 한다. 또한 메서드의 파라미터라는 정보를 통하여 더 풍부한 의미를 전달할 수 있다. 보통 메서드 명을 동사로 시작하는 경우가 있지만 반드시 일 필요는 없다. 단순 데이터 반환 같은 경우는 명사로 하여도 무방하다. 파라미터와 같이 사용할때 메서드 명은 보통 전치사로 끝나는게 좋다고 하셨다. int selectedColIndex = convertColFrom(cellInputCol); int selectedRowIndex = convertRowFrom(cellInputRow); 위와 같이 표기하면 확실히 읽을때 명확해짐을 볼 수 있었다. 파라미터의 타입, 개수, 순서를 통하여 의미전달이 또한 가능하다. 아래의 코드를 살펴보자. public void createLecture(String title, String localDateToString) {} public void createLecture(String lectureTitle, LocalDate openDate) {} 위의 두 메서드중에 2번째것이 명확하다는 것을 알 수 있을것이다. 첫번째 메서드는 메서드를 사용할때 두번째 파라미터에 무엇을 넣어야 하는지 불분명하기 때문이다. 여기서 파라미터는 외부와 소통하는 창이라고 볼 수 있다. 사용하는 입장에서 어떤 정보가 필요한지 알려주는 기능을 한다. 또한 메서드 시그니처에 납득이 가는 적절한 타입의 반환값을 돌려줘야 한다. 만약 납득이 안 간다면 문제가 있는 메서드일 확률이 높다. 또한 void 대신 충분히 반환할만한 가치가 있는 값이 있는지 고민을 해보는게 좋을 것이다. 그리고 추가적으로 메서드를 리팩토링 과정을 거쳐 추상화함에 있어서 너무 긴 코드들을 메서드로 묶는다는 생각보단, 추상화가 필요한 부분을 리팩토링한다고 생각하는것이 좋다. 단 1줄이더라도 추상화할만한 가치가 있다면 하는것이 좋다. 그래서 강의를 통해 예제 프로젝트를 기능단위로 묶어서 메서드로 분리함으로 조금 더 깔끔한 코드로 리팩토링 실습을 해보았다. 추상화 레벨 우리는 이전까지 엄청 긴 코드들(구체)에서 추상화 과정을 거쳐서 메서드를 추출해보았다. 이렇게 메서드를 추출하는 그 순간 읽는 자 기준으로 외부세계와 내부세계의 경계가 생긴다. 당연하게 생각해보면 쭉 코드를 읽다가 갑자기 메서드를 보면 살짝 멈칫할 것이다. 여기서 외부세계란 추상화 레벨이 높은 세계이고 내부세계란 추상화 레벨이 낮은 구체라고 생각하면 좋을 것이다. 그래서 내부세계에서는 구체적인 내용이 들어가 있고 외부세계에서는 메서드의 필요한 파라미터를 내부세계로 넘겨서 메서드명과 반환타입을 전달하게 될 것이다. 또한 하나의 세계 안 에서 추상화 레벨은 동등해야 한다. 만약 그렇지 못한다면 레벨을 맞추게 추상화 과정을 거쳐야 한다. 그래서 실습을 통하여 같은 추상화 레벨이 되도록 메서드들을 분리해보았는데 나는 여기서 몇몇 이해가 안되는 부분이 있었다. 이 부분은 질문을 해봐야 겠다. 매직 넘버, 매직 스트링 매직 넘버, 매직 스트링을 알기 전에 상수부터 알아보자. 상수로 추출한다는 것은 하나의 이름을 부여한다는 것이고 즉, 추상화 한다는 것이다. 매직 넘버와 매직 스트링은 의미를 갖고 있으나 상수로 추출되지 않은 숫자나 문자열을 의미하며 이름을 부여함으로 읽기 좋은 코드에 다가간다. 실습을 통해 매직 넘버와 매직 스트링을 상수로 추출해보았다. 미션1 해당 미션을 진행하면서 구체와 추상에 대한 개념을 확실히 이해할 수 있었다. 조금은 어색했지만 예시들을 몇개 해보니 당연한 것들이었다.제가 작성한 미션 링크는 아래와 같습니다. 미션1 링크  뇌 메모리 적게 쓰기 정리하는 시스템에서 중요한 과제는 최소한의 인지적 노력으로 최대의 정보를 제공해야 한다고 뇌 과학에서 이야기를 한다. 지금 내가 생각해보면 그렇다. 인간의 뇌가 컴퓨터 메모리라고 하였을때 우리의 뇌는 싱글 스레드 기반으로 처리할 것이다. 그리고 다른 사물을 보았을때 다른것을 생각할때 컨텍스트 스위칭이라는 작업을 거쳐야 한다. 우리의 뇌는 다른 것을 생각할때 범주화라는 작업을 거쳐야 한다. 범주화란 특정 대상의 특징들을 분류하는 작업을 말한다. 즉, 범주화를 통해 우리의 뇌는 최소한의 기억 데이터로 최대 효과를 볼 수 있다. 우리의 뇌는 싱글 스레드 기반으로 돌아간다고 하였고 만약 멀티태스킹을 진행할 경우 수행능력이 떨어지며 속도가 저하된다. 그래서 우리의 뇌는 최소의 인지로 최대의 효율을 볼 수 있다. 이것은 코드도 같다. 결국 이것을 기반으로 우리의 뇌에 적은 메모리가 올라가야 읽기 쉬운 코드가 된다. 후손들이 코드를 읽을때 독자의 메모리를 어떻게 효과적으로 쓸지 고민을 해야 좋은 코드가 된다 생각한다. Early return if else if else구조는 우리의 뇌 메모리를 생각해야 한다. 왜냐하면 else if문을 생각하면 앞의 조건식을 한번 더 생각해야하기 때문이고 else문도 마찬가지다. 그럼 해결책은 무엇이 있을까? 이 조건식들을 하나의 메서드로 추출하고 else if문과 else문을 지우고 if문들을 만들어 거기서 바로 return을 하는 것이다. 이것은 if문뿐만 아니라 switch문에도 같이 적용된다. 즉 결론은 아래와 같다. Early return으로 else의 사용을 지양 그래서 해당부분을 예제 코드에서 리팩토링 하는 과정을 거쳐봤다. 사고의 depth 줄이기 사고의 depth 줄이기가 나오면 아래의 2가지를 들 수 있다. 1. 중첩 분기문, 중첩 반복문2. 사용할 변수는 가깝게 선언하기 그럼 하나하나 살펴보자. 중첩 분기문, 중첩 반복문 왜 사고의 depth를 줄여야 하나? 이유는 이전에 설명했듯이 간단하다. for (int i = 1; i <= 9; i++) {   for (int j = 1; j <= 9; j++) {     if (i >= 2 && j < 8) {       doSomething();     }   } } 위의 코드를 실행한다고 생각해보자. 그러면 첫번째 반복문이 뇌에 입력이 될 것이다. 그리고 두번째 반복문을 만나면 그것도 뇌에 입력이 될 것이다. 그 다음 조건식을 보면 이것또한 뇌에 입력이 되어 같이 생각을 하면 메모리를 많이 쓰게 된다. 그러면 어떻게 추출할까? 아래와 같이 추출할 수 있을듯 하다. for (int i = 1; i <= 9; i++) {   doSomethingI(); } private void doSomethingI() {   for (int j = 1; j <= 9; j++) {     doSimethingIJ();   } } private void doSimethingIJ() {   if (i >= 2 && j < 8) {       doSomething();     } } 위와 같이 메서드로 추출하면 외부의 벽이 생긴다. 그렇게 뇌의 메모리를 분리시켜서 생각하게 할 수 있다. 각각의 메서드는 다른 메서드들이나 조건들을 생각을 안해도 된다. 그렇다고 무조건 1 depth로 만들자고 하는 것은 아니다. 보이는 depth를 줄이는데 급급한것이 아니라 추상화를 통한 사고과정의 depth를 줄이는 것이 중요하다. 2중 중첩구조로 표현하는 것이 사고하는데 도움이 된다면 메서드 분리보다는 그대로 두는 것이 좋다. 때로는 메서드 분리하는 것이 더 혼선을 주기 때문이다. 우리의 실습에서는 메서드 분리보단 Array-Stream을 사용하여 해결을 하였다. 그 이유는 row와 col을 사용하는 이중 반복문이 있는데 이를 각각 메서드로 분리하는게 이상하기 때문이다. 그 이유는 row-col은 하나의 세트처럼 작동하기에 분리가 조금 애매했다. ⚠ 주의그렇다고 무조건 Stream을 쓰라는 말도 아니다. 사용할 변수는 가깝게 선언하기 당연한 애기다. 애를 들어 변수를 선언하고 100줄정도 있다가 그 변수를 사용한다면 선언한 이 변수가 뭐였는지 다시 찾아보는 비효율적인 행동을 해야한다. 우리는 예제코드의 Scanner를 가깝게 위치시켰고 그러다보니 무한반복문에 위치하게 되어 이것을 상수로 바꿔보고 리팩토링 하는 과정을 보았다. 공백 라인을 대하는 자세 공백라인도 의미를 가진다. 복잡한 로직의 의미단위를 나누어 보여줌으로 읽는 사람에게 추가적인 정보전달이 가능하다. 해당 부분을 실습을 통해 의미단위로 끊어보았다. 부정어를 대하는 자세 부정연산자는 생각을 2번하게 만든다. 해당 조건을 먼저 이해해야하고 해당 조건이 아닌 상황을 한번 더 생각해야하기 때문이다. 즉, 가독성이 떨어진다. 그래서 해결방안은 아래와 같다. 1. 부정어구를 쓰지 않아도 되는 상황인지 체크2. 부정의 의미를 담은 다른 단어가 존재하는 지 고민 or 부정어구 메서드 구성 해당 부분을 토대로 예시코드를 리팩토링 해보았다. 해피 케이스와 예외 처리 일반적인 사람들은 해피 케이스에 대해 몰두하는 경향이 존재한다. 하지만 예외를 항상 생각하고 사용자 입력을 불신한 상태에서 예외처리를 꼼꼼이 하는 것이 견고한 소프트웨어를 개발하는 자세일 것이다. 그럼 어떻게 예외처리를 할 수 있을까? 먼저 예외처리 전에 예외 발생 가능성을 낮추는 방법이 있다. 어떤 값의 검증이 필요한 부분은 주로 외부세계와 접점일테니 반드시 검증을 꼼꼼이 구체적으로 해야한다.(ex. 사용자 입력, 객체 생성자, 외부서버의 요청) 또한 의도한 예외와 의도치 못한 예외를 구분해야한다. 의도한 예외는 커스텀 Exception 클래스로 정의하여 두고 그외의 의도치 못한 예외는 Exception클래스로 두는등의 행위를 하고 spring boot같은 웹 어플리케이션에서 ExceptionHandler를 만들어서 처리를 하는등의 행위를 거쳐야 한다. 또한 null을 주의해야한다. 코틀린같은 언어는 언어단에서 처리를해주지만 자바같은 경우는 NullPointerException을 주의해야한다. 그래서 항상 NullPointerException을 방지하는 방향으로 경각심을 가져야 한다. 또한 메서드 설계시 return null을 자제해야한다. 만약 불가피 하다면 Optional 클래스를 이용해보자. Optional Optional은 비싼 객체이다. 꼭 필요한 상황에서 반환타입으로만 사용하자. ⚠ 주의만약 파라미터같은 경우에 사용하는 경우는 피해야한다. 아마 이 부분은 IDE에서 경고표시를 해줄 것이다. 왜 피해야하냐면 분기 케이스가 3개 생기기 때문이다. (Optional이 가진 데이터가 null인지 Optional 그 자체가 null인지 생각때문) 마지막으로 Optional을 반환받았다면 최대한 빠르게 해소해야 한다. Optional 해소 분기문을 만드는 isPresent()-get()대신 풍부한 API를 사용하자. (ex. orElseGet(), orElseThrow 등등) ⚠ 주의orElse와 orElseGet에 사용에 주의하자! orElse같은 경우 항상 실행을 한다. 이게 무슨말이냐면 호출할 필요가 없는 경우에도 항상 실행된다. 그래서 파라미터로 확정된 값이 있을 경우 사용하자. 반면 orElseGet은 null일때만 실행을 한다. 그레서 우리 예제 코드에서 Scanner의 입력을 올바르지 않게 했을때의 부분들을 리팩토링하며, 해당 예외를 커스텀 예외와 의도치 않은 예외를 구분하여 처리하였다. 여기서 나는 조금 더 세밀한 예외정의를 하는게 좋지 않을까라는 생각을 해본다. 추상의 관점으로 바라보는 객체 지향 프로그래밍 패러다임에는 아래와 같이 크게 3가지로 나뉜다. 1. 절차지향: 지금까지 예제코드 작성했듯이 컴퓨터 처리구조처럼 차례대로 실행하는 흐름을 가지는것2. 객체지향: 객체간 협력을 통한 프로그래밍3. 함수형: 순수함수 조합으로 프로그래밍 🙋🏻 순수함수란?외부의 요인 없이 같은 input을 넣었을때 같은 output이 나오는것을 의미한다. 즉, 가변데이터는 멀리하고 side effect없이 프로그래밍하는 것을 의미한다. 그럼 우리는 자바로 프로그래밍을 하므로 객체지향에 대해 알아보자. 여기서 객체란 어떤 목적으로 설계된 추상화된 무엇을 의미한다. 즉, 쉽게 말해 데이터와 코드의 조합으로 보면 된다. 객체지향을 하면서 각각의 많은 객체들을 생성하다보니 객체간 협력과 객체가 담당하는 책임이 높아졌다. '캡추상다'라는 용어를 들어봤나? 나는 처음이다. 하지만 뭔가 대강은 알것 같았다. 캡추상다는 아래와 같다. 1. 캡슐화: 객체 데이터를 숨기고 가공로직을 숨기고 일부만 들어내는것. 즉, 추상화개념이다.2. 추상화3. 상속: 상속은 강력한 기능이지만 너무 남발하면 안된다.4. 다형성: 일종의 추상화이다. 상위 추상화 레벨에서 요구되는 그런 특징들만 뽑아서 인터페이스화해서 사용하는 것을 말한다. 이렇게 하면 구현체 여러개에 바껴서 사용이 가능하다. 객체지향에서만 쓰이는 애기는 아니지만 객체지향을 공부하다보면 관심사 분리 개념이 나온다. 관심사 분리란 특정 관심사에 따라 객체 생성 및 기능과 책임을 나눈다. 이렇게 하는 이유는 나중에 유지보수성이 좋아지기 때문이다. 또한 관심사 분리는 일련의 개념을 모아 이름을 짓고 기능을 부여하는데 일종의 추상화라 확인이 가능할 것이다.(높은 응집도와 낮은 결합도) 객체 설계하기 우리는 메서드 추출과정에서 외부세계와 내부세계가 나눠짐으로 추상화시킨다고 이야기 한 적이 있다. 객체도 마찬가지다. 적절한 관심사들을 분리하여 객체로 만들고 공개 메서드를 통해 외부세계와 소통함으로 객체의 책임을 들어낼 수 있다. 이런 객체들이 모여 객체간 협력을 할 수 있다. 객체 추상화 비공개 필드(데이터), 비공개 로직(코드)공개 메서드 선언부를 통해 외부세계와 소통각 메서드의 기능은 객체의 책임을 드러내는 창구객체의 책임이 나뉨에 따라 객체간 협력이 발생 객체가 제공하는 것절차지향에서 잘 보이지 않았던 개념을 가시화관심사가 한군데로 꼽히기 때문에 유지보수성 증가여러 객체를 사용하는 입장에서는 구체적인 구현에 신경쓰지 않고 보다 높은 추상화 레벨에서 도메인 로직 다룸 아래는 회원의 나이의 유효성 검사를 나타내는 예이다. 이런 식으로 관심사를 집중 시킬 수 있지 않을까? ⚠ 새로운 객체를 만들 때 주의점 1개의 관심사로 명확하게 책임이 정의되었는지 확인한다.메서드를 추상화할때와 유사객체를 만듬으로써 외부세계와 어떤 소통을 하려고 하는지 생각변경된 요구사항 및 리팩토링 과정에서 객체의 책임과 역할이 변경될 수 있다.생성자, 정적 팩토리 메서드에서 유효성 검증이 가능하다.도메인에 특화된 검증로직이 들어갈 수 있다. class Member {   private int age;   public Member(final int age) {     if (this.age < 0) {       throw new IllegalArgumentException("회원의 나이는 0살 미만일 수 없습니다.");     }     this.age = age;   } } setter 사용자제 데이터는 불변이 가장 좋다. 변하는 데이터라도 객체가 핸들링 할 수 있다.객체 내부에서 외부세계의 개입없이 자체적인 변경이 가능한지 확인해보고 가공으로 처리할 수 있을지를 확인해보자.만약 외부에서 가지고 있는 데이터로 데이터 변경 요청을 해야하는 경우 set~이라는 단순한 이름보다 update~같이 의도를 들어내자. getter 사용자제 getter라도 처음에는 사용을 자제하자. 반드시 필요한 경우에만 추가하자.외부에서 객체 내 데이터가 필요하다고 getter를 남발하는것은 객체에 대한 실례되는 행동이다.객체에 메세지를 보내는 방법을 선택해보자. Member member = new Member(); member.getPassword() // 비유하자면 어떤 사람이 강제로 비밀번호를 뺏는 형식이라 볼 수 있다. 필드의 수는 적을수록 좋다. 불필요한 데이터가 많을수록 복잡도가 높아지고 대응할 변화가 많아진다.필드A를 가지고 계산할 수 있는 A필드가 있다면 메서드 기능으로 제공단, 미리 가공하는 것이 성능상 이점이 있다면 필드로 가지고 있는 것이 좋을 수 있다. 그러면 이제 실습의 대략적인 요약을 해보자. 우리는 예제 코드로 Cell이라는 객체로 관심사를 분리 시켰다. 그에따라 변경되는 static 변수들을 변경하고 로직도 변경을 했다. 하지만 여기서 우리는 새로운 도메인 지식을 획득했다. 이제까지 셀이 열렸다/닫혔다라는 개념을 통해 로직을 작성해왔다면 지금은 Cell이라는 객체로 관심사를 분리함으로 사용자가 체크했다라는 개념이 나온것이다. 기존 String기반의 Sign기반의 BOARD가 있고 이를 상황에 따라 표시 할 sign을 갈아끼우는 형태에서 이제 Cell을 정보를 담을 공간의 객체가 생성되었다. BOARD는 Cell을 갈아끼우는 것이 아니라 사용자의 입력에 따라 Cell의 상태를 변화시키는 방향으로 진행하고 리팩토링을 거쳤다. SOLID SRP: Single Responsibility PrincipleOCP: Open-Closed PrincipleLSP: Liskov Substitution PrincipleISP: Interface Segregation PrincipleDIP: Dependency Inversion Principle SRP: Single Responsibility Principle 하나의 클래스는 단 1가지의 변경 이유(책임)만을 가져야만 한다.객체가 가진 공개 메서드, 필드, 상수등은 해당 객체의 단일 책임에 의해서만 변경되어야 한다.관심사 분리높은 응집도, 낮은 결합도(서로다른 두 객체간 의존성 최소화로 결합도를 낮춰야 한다.) 🔥 중요'책임'을 볼 줄 아는 눈이 필요하다. 그래서 우리는 이를 토대로 예제 프로젝트를 리팩토링해보았다. 처음에는 우리의 main메서드에 실행하는 부분을 별도의 GameApplication으로 분리하여 실행로직과 게임 로직을 분리하였다. 다음으로 입출력 부분을 각각 별도의 Handler클래스로 분리하여 리팩토링을 진행해보았다. 마지막으로 상수로 되어있는 BOARD를 객체로 분리하여 마지막 리팩토링을 분리해왔다. 이렇게 실습하면서 이제까지 나는 객체지향적으로 작성하지 못했다는 것을 깨달았다. 즉, 단일책임의 원칙을 지키지 못한것이다. 단일책임원칙은 약간 비유적으로 표현하면 이런것 같다. 축구로 비유하면, 축구에서 11명의 선수들은 각자 포지션이라는 책임을 가지고 있다. 각 선수는 자기 포지션에 맞는 역할만 해야 한다는 것과 같아. 예를 들어, 수비수는 수비에만 집중하고, 공격수는 공격에만 집중해야 팀이 효율적으로 움직일 수 있을것이다. 만약 수비수가 공격도 하고 골키퍼 역할까지 하려고 한다면 팀이 혼란에 빠질것이다. 즉, 한 선수에게 여러 역할을 맡기면 혼란이 생기고 효율성이 떨어지기 때문에, 선수마다 책임을 명확하게 분리하는 것이 중요하다. OCP: Open-Closed Principle확장에는 열려있고 수정에는 닫혀있어야 한다.기존 코드의 변경없이 시스템의 기능을 확장할 수 있어야한다.추상화와 다형성을 활용해서 OCP를 지킬 수 있다. 우리는 위를 토대로 예제코드를 리팩토링하였다. 예제코드에 게임 난이도라는 추가 요구사항이 나왔다. 하지만 이것을 유동적으로 변경 전에 알파벳 제한과 숫자가 2자리가 되면 오류가 발생함을 알 수 있었다. 그래서 이것을 해결하고 인덱스 치환 로직을 SRP원칙에 따라 별도 객체로 분리하고 리팩토링 작업을 하였다. 이제 추가요구사항인 난이도를 넣을때 우리는 인터페이스를 이용해 메서드 선언부를 선언해주고 구현체들을 각각 만들어 해결을 하였다. 축구로 비유하면, 축구 팀의 감독이 선수들에게 전술을 지시할 때, 기존 선수들의 역할을 크게 바꾸지 않고도 새로운 전략을 추가하는 상황과 비슷하다. 예를 들어, 새로운 선수가 팀에 합류하거나 새로운 전술을 추가하려고 할 때 기존에 있던 선수들의 역할을 건드리지 않고, 그 새로운 선수나 전술만 추가하는 식이다. 만약 기존의 모든 선수 배치를 다 바꿔야 한다면 팀이 혼란에 빠지지 않을까? 대신 기존의 포지션을 그대로 두고, 새로운 포지션을 하나 더 추가해 전술을 보완하는 것이 OCP에 비유로 들 수 있을 것 같다. 다른 비유로는 레고 블록으로 비유할 수 있다. 레고 집을 만들 때, 기존에 완성된 부분을 해체하지 않고도 새로운 부품을 추가해 더 멋진 집을 만들 수 있는 것이 OCP에 해당한다. LSP: Liskov Substitution Principle상속구조에서 부모클래스의 인스턴스를 자식클래스의 인스턴스로 치환이 가능해야 한다.자식클래스는 부모클래스의 책임을 준수하며 부모클래스의 행동을 변경하지 않아야 한다.LSP를 위반하면 상속클래스를 사용할때 오동작이 발생한다. 예상 밖의 예시가 발생하거나 이를 방지하기 위한 불필요한 타입체크가 동반된다. 보통 부모클래스보다 자식클래스가 하는 기능들이 더 많은게 일반적이다. 그래서 조심해야한다. 부모가 일하는 곳에 자식이 갔다가 올바른 방향으로 동작하지 않거나 예상치 못한 예외를 발생시키거나 이를 방지하기 위해 자식의 타입을 체크하는 분기가 발생한다. 이런 분기는 뇌 메모리에 더 올라가기에 불필요한 분기가 생기니 코드가 읽기 불편해진다. 그래서 우리는 예제코드에서 Cell이라는 것을 부모클래스(추상클래스)로 두고 각각 빈 셀, 숫자 셀, 지뢰 셀 클래스를 만들어 리팩토링 하는 과정을 해보았다. 축구로 비유하면, 팀의 주전 선수가 교체 선수로 대체될 때에도 팀의 전술이 동일하게 잘 유지되어야 한다는 것과 같다. 예를 들어, 만약 주전 공격수가 부상당해서 교체 선수가 들어온다고 해도, 그 교체 선수가 주전 선수의 역할을 잘 수행할 수 있어야 팀의 전술에 문제가 생기지 않을것이다. 교체 선수가 갑자기 공격을 포기하고 수비만 하려 한다면, 팀의 전술이 흐트러질 것이다. 즉, 교체 선수는 주전 선수와 같은 역할을 할 수 있어야 한다는 것이 LSP의 핵심이다. 즉, 축구처럼 자식 클래스가 부모 클래스를 언제든지 대체할 수 있도록 만드는 것이 LSP다. ISP: Interface Segregation Principle클라이언트는 자신이 사용하지 않는 인터페이스에 의존하지 않아야한다.예를 들어 하나의 인터페이스에 선언부가 여러개 있고 여러 구현체들이 이 인터페이스를 구현할때 일부 구현체가 모든 선언부가 필요없는 경우 어떻게 할까?인터페이스를 쪼개면 된다.ISP를 위반하면 불필요한 의존성으로 인해 결합도가 높아지고 특정기능의 변경이 여러 클래스에 영향을 미칠 수 있다. 그래서 우리는 실습예제에서 동작부분과 초기화 부분을 인터페이스로 구현했는데 만약 다른 게임이 초기화 부분이 필요없다 가정하고 실습을 했다. 그럴 경우 간단히 이 인터페이스를 분리시켰다.축구로 비유하자면, 모든 선수가 똑같은 훈련을 받기보다는, 각 포지션에 맞는 훈련만 받는 것이 더 효율적이다는 것과 비슷하다. 예를 들어, 공격수는 골을 넣는 훈련을 집중적으로 해야 하고, 골키퍼는 공을 막는 훈련에 집중해야하지 않을까? 공격수가 골키퍼 훈련까지 받게 된다면 불필요한 훈련으로 시간만 낭비하게 된다. 각 선수는 자신의 역할에 맞는 훈련만 받아야 하는 것이다. DIP: Dependency Inversion Principle상위 수준의 모듈(추상)은 하위 수준의 모둘(구체)에 의존해서는 안된다. 모두 추상화에 의존해야 한다.의존성 순방향: 고수준 모듈이 저수준 모듈을 참조하는 것의존성 역방향: 고수준, 저수준 모듈이 모두 추상화에 의존 저수준 모듈이 변경되어도 고수준 모듈에는 영향을 끼치면 안된다. 의존성: 하나의 모듈이 다른 하나의 모듈을 알고 있거나 직접적으로 생성하는 것을 말한다. 우리의 예제코드에서 이제 위의 개념으로 실습을 하면 아래와 같다. 우리는 ConsoleInputHandler과 ConsoleInputHandler을 직접 객체를 생성해서 하고 있었다. 하지만 콘솔이라는 것은 너무 구체화되어 있다. 만약 갑자기 웹기반으로 변경되면 많은 부분을 변경해야할 것이다. 그것을 방지하기 위해 두 클래스를 인터페이스로 변경하고 구현을 하는 방식으로 하면 해결이 된다. 축구로 비유하자면, 감독이 특정 선수 개인의 능력에 의존하지 않고, 그 선수의 포지션에 맞는 역할에 의존해야 한다는 것과 비슷하다. 예를 들어, 감독이 특정 공격수에만 의존해서 전략을 짠다면, 그 선수가 부상당하거나 경기에 나가지 못할 경우 큰 문제가 생길것이다. 대신, 공격수라는 포지션에 맞는 역할을 정의하고, 누구든 그 역할을 수행할 수 있도록 전략을 짠다면, 주전 선수가 빠지더라도 팀의 전략은 계속 유지될 수 있을것이다. 만약 감독이 호날두나 메시에 의존해서 전술을 짜다가 그 선수가 없을 시, 팀은 사면초가에 빠질 것이다. 🧐 꿀팁DIP를 애기하면 Spring의 DI와 IoC를 헷갈려 하는 것 같다. 나도 처음에는 그랬다. 둘을 비교해보자.1. DI: 의존성 주입이며 일반적으로 생성자를 통해 주입한다. 여기서 생각나는 숫자는 3인데 두 객체가 서로 의존성을 맺을려면 제 3자가 역할을 해주는데 바로 IoC Container인 Spring Context이다.2. IoC: 제어의 역전이라 하며 이것은 Spring에서만 통하는 개념은 아니다. 제어의 역전이란 프로그램의 흐름을 순방향은 개발자가 가져가야하지만 이것을 역전시켜서 프레임워크가 담당하고 나의 코드를 프레임워크 일부로 동작시킨다. 이러면 우리는 직접 생성 및 생명주기 관리를 프레임워크에 위임시킬 수 있으며 우리는 그냥 사용하기만 하면 된다. 미션2 미션2를 하면서 조금은 논리적 사고 및 객체지향적으로 어떻게 해야하고 읽기 좋은 코드를 만들기 위해 어떻게 할지 또한 SOLID에 대한 정리를 해보았다. 상세 내용은 아래 내가 작성한 포스트를 확인하자! 미션2 블로그 SOLID관련해서만 잠깐 정리를 해보았다. 정리 정리를 해보면 아래와 같다. 1. SRP (Single Responsibility Principle) - 단일 책임 원칙각 클래스는 하나의 책임만 가져야 한다는 원칙이야. 클래스가 여러 책임을 가지면, 하나의 기능을 변경할 때 다른 기능에도 영향을 줄 수 있다. 축구로 비유하자면, 공격수는 공격만, 골키퍼는 수비만 담당하는 것처럼, 각 클래스는 명확한 역할을 가져야 한다.2. OCP (Open-Closed Principle) - 개방-폐쇄 원칙클래스는 확장에 열려 있고, 수정에는 닫혀 있어야 한다는 원칙이다. 즉, 새로운 기능을 추가할 때 기존 코드를 변경하지 않고 확장할 수 있어야 한다는 뜻이다. 축구로 비유하면, 새로운 전술을 추가할 때 기존 선수 배치에 큰 변화를 주지 않고도 쉽게 새로운 선수를 추가하는 것과 같다.3. LSP (Liskov Substitution Principle) - 리스코프 치환 원칙하위 클래스는 상위 클래스의 자리를 대체할 수 있어야 한다는 원칙이다. 축구로 설명하자면, 교체 선수가 주전 선수의 역할을 대신할 수 있어야 팀의 전술이 무너지지 않듯이, 자식 클래스는 부모 클래스의 기능을 해치지 않고 그대로 사용할 수 있어야 한다.4. ISP (Interface Segregation Principle) - 인터페이스 분리 원칙클라이언트는 자신이 사용하지 않는 메서드에 의존하지 않아야 한다는 원칙이다. 축구에서는 공격수와 수비수가 똑같은 훈련을 받지 않고, 각자의 포지션에 맞는 훈련을 받는 것처럼, 인터페이스도 필요한 기능만 나눠서 설계해야 한다.5. DIP (Dependency Inversion Principle) - 의존 역전 원칙상위 모듈은 하위 모듈에 의존하지 않고, 둘 다 추상화된 인터페이스에 의존해야 한다는 원칙이다. 축구로 비유하면, 특정 선수에게 의존하지 않고 포지션 자체에 의존하는 것처럼, 상위와 하위 모듈은 서로 구체적인 것이 아닌 추상적인 규약에 의존해야 한다. 이 다섯 가지 원칙을 잘 따르면, 시스템의 유지보수성, 확장성, 유연성이 훨씬 좋아진다. 마치 축구 팀이 각 선수의 역할을 잘 분배하고 새로운 전술을 도입할 때 기존 시스템에 혼란이 없도록 만드는 것처럼 말이다. 상속과 조합 상속과 조합은 무엇일까? 상속은 지난시간에 배워서 알겠지만 부모 클래스를 자식클래스가 상속받아 부모의 기능을 그대로 이용하는 것이다. 조합은 상속과 항상 같이 따라 다니는데 객체간 협력을 이용할때 조합을 이용한다. 이렇게 볼때 알 수 있듯이 상속보단 조합이 객체지향적으로 더 좋다는 것을 알 수 있아보인다.상속보단 조합을 이용하자.상속은 시멘트처럼 굳어진 구조다. 그래서 수정이 어렵다.부모와 자식의 결합도가 높다.조합과 인터페이스를 활용하는 것이 유연한 구조다.상속을 통한 코드의 중복제거가 주는 이점보다 중복이 생기더라도 유연한 구조 설계가 주는 이점이 더 크다. 옛날에는 하드웨어 성능이 안 좋아서 코드 중복 제거가 매우 큰 효과를 주었다. 하지만 오늘날은 하드웨어 성능이 굉장히 뛰어나다. 그래서 상속보단 조합을 이용해 유연한 설계를 하는 것이 좋다. 하지만 이렇다 해서 상속을 아예 사용하지 말자라는 말은 아니다. 확실한 상속구조거나 상속이 주는 효과가 매우 뛰어날것 같다고 느껴지면 상속을 이용하자. 그 외에는 조합으로 다 해결된다. 상속은 또한 부모 자식간의 결합도가 높아 캡슐화가 안 되어 있다고 한다. 이 점도 생각해보자.그래서 우리는 기존 추상클래스로 되어있는 Cell을 인터페이스로 만들고 Cell의 상태 변경을 하는 필드들을 CellState에 두어 분리를 해보았다. 처음에 이 실습을 하면서 CellState는 그냥 enum으로 하면 안될까 고민을 하였고 추후에도 이렇게 변경이 없으면 한번 질문해봐야 겠다. Value Object Value Object는 훌륭한 추상화 기법 중 하나다. 기본 타입을 객체로 감싸서 의미 부여 및 추상화를 하는 것이다.도메인의 어떤 개념을 추상화하여 표현한 값 객체값으로 취급하기 위해서 불변성, 동등성, 유효성 검증등을 보장불변성: final 필드, setter금지동등성: 서로 다른 인스턴스여도(동일성이 달라도) 내부의 값이 같으면 같은 값 객체로 취급, ```equals()``` & ```hashCode()``` 재정의가 필요하다.유효성 검증: 객체가 생성되는 시점에 값에 대한 유효성 보장 그래서 우빈님께서는 만원 지폐의 일련번호로 이에 대한 예시를 들어주셨다. 일련번호가 달라도 하나의 만원으로 보는것과 같다고 하셨다. 🙋🏻 동등성 vs 동일성동등성은 객체간 메모리 주소가 달라도 내부의 값이 같다면 같은 객체로 취급을 하자는 것이며 동일성은 메모리 주소 값이 같냐는 의미이다. 동일성 비교는 ```==``` 연산자로 비교하며 동등성 비교는 재정의한 ```equals()```로 해결한다. VO vs EntityEntity는 식별자가 존재한다. 식별자가 아닌 필드의 값이 달라도 식별자가 같으면 종등한 객체로 취급equals() & hashCode()로 식별자 필드만 가지고 재정의 할 수 있다.식별자가 같은데 식별자가 아닌 필드의 값이 서로 다른 두 인스턴스가 있다면 같은 Entity가 시간이 지남에 따라 변화한것으로 이해할 수 있다.VO는 식별자 없이 내부의 모든 값이 다 같아야 동등한 객체로 취급한다. 개념적으로 전체 필드가 다 같이 식별자 역할을 한다고 생각하자. 그래서 우리의 예제 프로젝트를 리팩토링해보았다. rowIndex와 colIndex는 하나의 세트로 움직이니 이것을 CellPosition이라는 VO를 만들어 리팩토링을 진행하였고 이에 대해 세부적인 로직들을 개선해보았다. 예를 들어 재귀로직을 RelativePostion으로 두어서 stream API를 이용하여 해결을 하였다.이처럼 코드가 점점 개선되니 뭔가 조금은 많은 부분이 느껴졌다. 실무에서도 한번 신규 프로젝트를 진행할때 도입해볼만한 생각이 듣게 되었다. 하지만 아직까지 능수능란하게 해결을 할지는 고민이 되는 것 같다. 일급 컬렉션 일급 컬렉션이란 무엇일까? 일단 컬렉션은 List, Map, Set같은 것들이다. 그럼 일급은 무엇일까? 해당 용어에 파생된것이 일급시민이다. 일급 시민다른 요소에게 사용가능한 모든 연산을 지원하는 요소변수로 할당될 수 있다.파라미터로 전달 될 수 있다.함수의 결과로 반환될 수 있다. 일급함수함수형 프로그래밍 언어에서 함수는 일급시민이다.함수형 프로그래밍 언어에서 함수는 일급시민이다.함수는 변수에 할당될 수 있고 인자로 전달될 수 있고 함수결과로 함수가 반환될 수 있다. 일급 컬렉션컬렉션을 포장하면서 컬렉션만을 유일하게 필드로 가지는 객체컬렉션을 다른 객체와 동등한 레벨로 다루기 위함단 하나의 컬렉션 필드만 가진다.컬렉션을 추상화하며 의미를 담을 수 있고 가공로직의 보금자리가 생긴다.가공로직에 대한 테스트도 작성할 수 있다.만약 getter로 컬렉션을 반환할 일이 생긴다면 외부조작을 피하기 위해 꼭 새로운 컬렉션으로 만들어서 반환. 이것을 이용해 우리는 체크했는지 유무 메서드의 ```Cell[][]``` stream API를 이용한 부분을 Cells라는 일급 컬렉션을 만들어 변경을 해보았으며 또한 우리는 빈 셀, 숫자 셀, 지뢰 셀을 보드에 넣어주는 것을 CellPositions라는 일급컬렉션을 통해 리팩토링 및 버그 수정도 해보았다. 아직 일급컬렉션을 처음 공부해봐서 많아 와 닿지는 않지만 이 부분을 한번 다른 곳에도 적용해봄으로 익숙해져야겠다. Enum의 특성과 활용Enum은 상수집합이며 상수와 관련된 로직을 담을 수 있는 공간이다.상태와 행위를 한 곳에서 관리할 수 있는 추상화된 객체이다.특정 도메인 개념에 대해 그 종류와 기능을 명시적으로 표현해줄 수 있다.만약 변경이 정말 잦은 개념은 Enum보다 DB로 관리하는 것이 좋다. 그래서 우리는 기존에 SIGN들을 OutputConsoleHandler쪽에 이관하면서 enum을 활용해 리팩토링 과정을 거쳐보았다. 다형성 활용하기이번에는 예제에 있는 반복된 if문을 다형성을 통해 해결해보았다. 해당 if문들에서 변화하는것(조건, 행위 -> 구체)과 변화하지 않은 것(틀 -> 추상)을 나누기로 하였고 그를 위해 인터페이스를 만들어 처리를 하였고 해당 인터페이스를 만들어 스펙들을 정리하였다. 그리고 스펙들을 하나의 클래스에 두어 해당 객체의 메서드만 호출해서 해결하게 하였다. 하지만 해당 문제는 클래스가 많아지면 즉, 스펙이 더 많아 질경우 소스코드를 빈번히 해결해야하는 문제가 있었고 그래서 enum을 통해 해결했다. enum에 인터페이스를 구현시키고 각기 다른 행위 자체를 enum안에 상수에 별도로 구현하는 법을 알았다. 조금 신박했고 유용한 방법인것 같았다. 뭔가 실무에도 한번 써볼법한 방법이였다. 이를 통해 변하는 것과 변화하지 않은 것을 분리하여 추상화하고 OCP를 지키는 구조로 만들었다. 숨겨져 있는 도메인 개념 도출하기도메인 지식은 만드는 것이 아니라 발견하는 것이다.객체지향은 현실을 100% 반영하는 도구가 아니라 흉내내는 것이다.현실세계에서 쉽게 인지하지 못하는 개념도 도출해서 사용할 때가 있다.설계할때는 근시적, 거시적 관점에서 최대한 미래를 예측하고 시간이 지나 만약 틀렸다는 것을 인지하면 언제든 돌아올 수 있도록 코드를 만들어야 한다.완벽한 설계는 없다. 그 당시의 그들의 최선이 있을뿐 해당부분을 가지고 우리의 예시코드를 리팩토링해봤다. 만약 다양한 설정기능들이 추가가 될 경우 변경할 곳이 많아졌다. 그래서 우리는 config관련 클래스를 만들고 설정부분들을 변경해주는 것을 해보았다.해당 강의를 듣고 나는 조금 반성했다. 이전에 조상님들이 작성한 레거시 코드를 보고 많은 비판을 했기 때문이다. 그 당시에는 그게 최선일텐데 또한 설계관련해서 한번 생각 나는 영상이 인프콘에 재민님께서 발표한 영상인데 지금 다시 한번 봐보고 공부해봐야겠다. 📚 추가 참조https://johnlock.tistory.com/405https://maily.so/trendaword/posts/52a9a219 

백엔드인프런워밍업스터디클럽백엔드클린코드테스트코드발자국

두부

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

학습 내용자료구조와 알고리즘 면에서는 스택, 연결리스트, 큐 등 기본적인 자료구조에 대한 내용을 학습했습니다.운영체제 면에서는 운영체제의 전체적인 개요와 프로세스, CPU 스케줄링에 관해서 배웠습니다. 회고 (피드백 및 목표)여러 일정이 겹쳐서 강의 수강 속도가 느려졌던 점이 조금 아쉬웠습니다. 그러나 정해진 기간 내에 목표치를 달성했다는 점은 스스로 칭찬해 주고 싶습니다.강의를 몰아 듣는 과정에서 깨달은 것이라서 조금.. 그렇지만 ^^; 저는 역시 작은 단위를 나눠서 들을 때보다 많은 양을 몰아서 볼 때 더 몰입되고, 이해가 깊어지는 것 같습니다. 다음 주부터는 시간을 정해두고 자료구조 및 알고리즘, 운영체제를 몰입해서 공부해 봐야겠습니다. 미션미션은 운영체제 미션과 자료구조 미션을 다르게 접근해서 해결했습니다. 운영체제 미션은 개념에 대한 문제라서 강의를 통해 학습한 내용을 바탕으로 최대한 자세히 풀어쓰려고 노력했습니다. 자료구조 미션은 문제 해결에 관한 것이었기 때문에 문제의 제약조건을 파악하고, 해당 제약조건을 지키면서 문제를 해결할 수 있는 최적의 대안을 찾으려고 노력했습니다. 회고 (피드백 및 목표)운영체제 미션을 해결하면서 강의를 다시 돌려보게 되는 부분이 있었습니다. 물론 그 과정을 통해서 해당 개념에 대해서 더 깊게 이해하게 된 부분도 분명 있지만, 다음부터는 그 빈도를 줄여나가기 위해서 강의를 볼 때 더 몰입해서 볼 수 있는 환경을 조성하려고 합니다.

채널톡 아이콘