블로그

SK

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

[인프런 워밍업 클럽 2기] FE 1주차 발자국1주차 학습 요약강의 - 따라하며 배우는 자바스크립트 A-Zhttps://www.inflearn.com/course/따라하며-배우는-자바스크립트 - John Ahn1일차 OT 2일차 JS 기초, window, DOM, EventJS 기초 강의에서는 console 객체들, 변수 선언, 호이스팅, 타입, 타입 변환, 연산, 반복, window 객체, DOM, Event 등을 배움중요호이스팅var, let, const 가 모두 호이스팅 된다.예시 코드console.log(a) // undefined var a = 123 console.log(a) // 123JS 는 위에서 부터 순차적으로 읽어 내려오는 방식으로 코드를 읽는다. 위의 코드 같은 경우 var 의 선언된 a 를 메모리에 먼저 undefined 로 할당된 뒤 console.log(a) 를 읽어온다. 그러므로 undefined 라는 결과가 출력이 되고 그 뒤에 a 에 123이 할당된다.반대로 let과 const 는 어떨까.console.log(a) // ReferenceError: a is not defined let a = 123 // let 이나 const console.log(a) // 위의 log 에서 에러가 나므로 접근 안됨메모리에 먼저 a 를 할당 하는건 var 와 방식이 같다. 하지만 var 는 undefined 를 할당 하지만 let 과 const 는 undefined를 할당하지 않는다. 그러므로 변수 선언 위에 있는 log 에서 오류가 발생 한다.직접 보고 싶을 경우 about:blank 로 접속해서 개발자 모드의 콘솔창에 입력해보기 바란다.필자가 애용하는 브라우저 콘솔 테스트 환경1번 과제 - Food Menu Apphttps://food-menu-app-kappa.vercel.app/ - 완성본.. title 안바꿧네https://github.com/ygvbhy/food-menu-app.git - 코드빌드 도구 ViteCSS Bootstrap 5 (CDN)js Vanilla배포도구 Vercel해결 과정디자인은 똑같이 안했고 엇비슷하게 진행. css 보단 js 가 더 중요했으므로 css 는 신경 쓰지않음.메뉴 리스트는 데이터로 활용이 가능함. 그래서 json 파일로 따로 정리 import 해오는 방식으로 진행. 추후 api 도 json 방식으로 object 값이 반환 되는 경우가 많기 때문에 이런 방식으로 진행기초 틀 작업 - bootstrap 5 를 활용하여 전체적인 틀을 잡은 뒤 내부에 들어가는 메뉴정보를 js 에서 반복하여 작성 후 innerHTML 를 활용하여 내용 삽입All 과 각 메뉴의 구분 필요하고 로딩시 All 을 기준으로 메뉴들을 표기 해야 하므로 script 로딩 될때 해당 함수 실행. window.onload 사용해도 됨.3일차 자바스크립트 중급 1 ~ 8this, bind, call, apply, 삼항 연산자, Event loop, Closure, 구조 분해 할당, 전개 연산자, map, filter, reducethis 메소드 ⇒ 해당 객체를 가리킨다.(참조한다.) 함수 ⇒ window 객체를 참조 constructor ⇒ 빈 객체를 가리킨다.화살표 함수 (Arrow Function) 은 항상 상위 스코프의 this 를 참조함.삼항 연산자if (a) a = 'a' else a = 'b' // => a ? a = 'a' : a = 'b' Event Loop// 두 번째 인수가 시간 값. 밀리세컨드 값으로 1초 = 1000 으로 생각 하면 된다. // 내부 함수는 비동기이다. setTimeout(() => {}, 1000) 동기/비동기동기 ⇒ 시간을 맞춤비동기 ⇒ 시간을 맞추지 않음차이 : 동기는 먼저 이전의 것이 끝나야 다음 것을 함. 비동기는 1번을 하면서 2번도 가능하고 3, 4번도 가능함.JS 는 동기 언어임 그래서 JS 이외의 도움을 받는다. 브라우저 실행 → 브라우저 api 를 사용 (window object) Node 에서 실행 → Node api 사용 (global object)비동기 처리 과정브라우저 내부 : JS 엔진, web APIs, Callback Queue, Event LoopJS 엔진 : 메모리 힙, Call Stack메모리 힙 : 변수 저장 창고Call Stack : 함수 호출시 함수가 줄 서는 곳Closure다른 함수 내부에 정의된 함수(innerFunction)가 있는 경우 외부 함수 (outerFunction) 가 실행을 완료하고 해당 변수가 해당 함수 외부에서 더 이상 액세스 할 수 없는 경우에도 해당 내부 함수는 외부 함수의 변수 및 범위에 액세스할 수 있다.function outerFunction(outerVariable) { return function innerFunction (innerVariable) { console.log('Outer Variable: ', outerVariable) // Outer Variable: outside console.log('Inner Variable: ', innerVariable) // Inner Variable: inside } } const newFunction = outerFunction('outside'); newFunction('inside') outerFunction(’outside’) 은 변수 “newFunction” 에 할당되는 즉시 호출호출되면 outerFunction 은 변수 “newFunction” 을 outerFunction(outerVariable) 대신 innerFunction(innerVariable)을 반환 한다.그럼 다음 변수 newFunction(’inside’)으로 호출하여 innerFunction(’inside’)을 호출한다. 클로저는 innerFunction 이 원래 outerFunction(’outside’) 으로 설정한 outerVariable 매개변수를 기억하고 액세스 할 수 있는 것. 따라서 ‘inside’로만 호출되었더라도 ‘outside’와 ‘inside’ 를 모두 console.log() 할 수있다.구조 분해 할당let address = { city: '1234', zipCode: '12345' } const {city, zipCode} = address let a = [1, 2, 3, 4, 5] const [n1, n2, n3, n4, n5] = a 전개 연산자let a = [1, 2, 3, 4, 5] [...a, 123] // [1, 2, 3, 4, 5, 123] // 문자열도 가능 let a = "askdjhfqkwejhr" [...a] // ['a', 's', 'k', 'd', 'j', 'h', 'f', 'q', 'k', 'w', 'e', 'j', 'h', 'r'] // 문자열 분할 함수 - 위와 같은 효과 (배열에는 사용 못함) a.split('') // ['a', 's', 'k', 'd', 'j', 'h', 'f', 'q', 'k', 'w', 'e', 'j', 'h', 'r'] map, filter, reducemap → 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환filter → 주어진 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열로 반환reduce → 배열의 각 요소에 대해 주어진 리듀서 함수를 실행 하고, 하나의 결괏값을 반환 4개의 인자 ⇒ 누산기 (acc), 현재 값 (cur), 현재 인덱스 (idx), 원본 배열 (src)2번 과제 - 가위바위보 게임https://rsp-game-five.vercel.app/ - 완성 화면https://github.com/ygvbhy/rsp-game.git - 코드빌드 도구 ViteCSS Bootstrap 5 (CDN)js Vanilla배포도구 Vercel해결 과정 전 과제와는 다르게 js 작동이 많아서 TODO 파일에 작동을 하나하나 작성 하면서 작업컴퓨터가 고른 가위 바위 보는 Math.random() 함수를 이용해 3가지중 랜덤값을 뽑아서 진행1,2,3중 1이면 가위 2면 바위 3이면 보사용자가 고른 값을 id 에 저장 해 두고 이 값과 랜덤으로 가져온 값을 비교 하여 판단.4일차 자바스크립트 중급 9 ~ 17undefined, null, 얕은 비교, 깊은 비교, 얕은 복사, 깊은 복사, 함수 표현식, 함수 선언문, IIFE(Immediately Invoked Function Expression), Intersection observer, 순수 함수, 커링, strict modestructuredClone : 깊은 복사를 지원하는 내부 함수IIFE(Immediately Invoked Function Expression) 정의되자마자 즉시 실행되는 함수( function () { } )() // 첫번째 소괄호 => 전역 선언 막고, IIFE 내부 안으로 다른 변수 접근 막기 // 두번째 소괄호 => 즉시 실행 함수를 생성하는 괄호 이를 통해 js 엔진은 함수를 즉시 해석 및 실행 목적 : 전역으로 선언하는 것을 피하기 위해. 또한 IIFE 내부 안으로 다른 변수들이 접근하는 것을 막을 수도 있다.Intersection observer기본적으로 viewport 와 설정한 요소의 교차점을 관찰하며, 요소가 뷰포트에 포함되는지 포함되지 않는지, 더 쉽게는 사용자 화면에 지금 보이는 요소인지 아닌지 구별하는 기능무한 스크롤 또는 이미지 레이지 로딩에 사용 됨순수 함수함수형 프로그래밍 패러다임의 한 부분이며, 순수 함수는 두 가지 규칙을 가지고 있다.같은 입력값이 주어졌을 때, 언제나 같은 결과값을 리턴사이드 이펙트를 만들지 않는다.사용 하는 이유클린 코드를 위해테스트를 쉽게 하기 위해디버그를 쉽게 하기 위해독립적인 코드를 위해커링 (Currying)f(a,b,c) 처럼 단일 호출로 처리하는 함수를f(a)(b)(c) 와 같이 각각의 인수가 호출 가능한 프로세스로 호출된 후 병합될 수 있게 변환하는 것커링은 함수를 호출하는 것이 아닌 변환 하는 것3번 과제 - 퀴즈 앱https://quiz-app-mauve-beta.vercel.app/ - 완성 화면https://github.com/ygvbhy/quiz-app - 코드빌드 도구 ViteCSS Bootstrap 5 (CDN)js Vanilla배포도구 Vercel해결 과정 TODO 에 동작을 하나하나 써가며 작업문제는 3개 정답은 2 ~ 3개 로 나눠져서 json 으로 데이터를 정리 해서 사용각 문제를 반복하여 innerHTML 로 문제를 삽입한 뒤 id 값으로 정답 값 구분정답의 구분을 위해 각 문제가 담긴 배열을 반복을 돌려 확인.이후 정답 버튼들은 각 정답 여부에 맞게 색상 입히고 배경은 정답일 경우 초록, 오답일경우 빨강으로 색 변경다음 문제 클릭시 색상 및 문제, 정답 버튼 새롭게 로딩5일차 OOP, 비동기OOP, 다형성, js prototype, ES6 classes, Sub Class(Inheritance), super(), Callbacks, ES6 Promise, Async, AwiatOOP : object oriented programming - 객체 지향 프로그래밍프로그래밍 언어의 기본이 되는 프로그래밍의 패러다임. 여러개의 독립된 단위 객체들의 모임특징자료 추상화불필요한 정보는 숨기고 중요한 정보만을 표현함으로써 프로그램을 간단히 만드는것. 객체안의 자세한 내용을 몰라도 중요 정보를 이용해서 해당 객체를 사용할 수 있게 됨.상속새로운 클래스가 기존의 클래스의 자료와 연산을 이용할 수 있게 하는 기능다형성다형성. 다양한 형태를 가질 수 있다.어떤 한 요소에 여러 개념을 넣어 놓은 것.캡슐화클래스 안에 관련 메서드, 변수 등을 하나로 묶어줌. 이 매커니즘을 이용해서 바깥에서의 접근을 막아 보안이 강화되고 잘 관리되는 코드를 제공.prototypejs 객체가 다른 객체로부터 메서드와 속성을 상속받는 매커니즘을 말한다. 이것을 프로토타입 체인이라 한다. 이렇게 하므로 인해 더 적은 메모리를 사용하고 코드를 재사용 할 수 있다.callbacksjs 는 싱글 스레드. 하나의 일을 할때 다른 일은 하지 못함.데이터를 가져오는데 10초가 걸린다면 10초동안 페이지에선 아무것도 못함. 그래서 이러한 문제를 해결하기 위해 비동기 요청을 사용함. 병렬작업 가능Promisejs 비동기 처리에 사용 되는 객체new 키워드와 생성자를 사용해 만든다. 생성자는 매개변수로 “실행 함수” 를 받는다. 이 함수는 매개 변수로 두 가지 함수를 받아야 하는데 첫 번째 함수(resolve) 는 비동기 작업을 성공적으로 완료해 결과를 값으로 반환할 때 호출해야 하고, 두 번째 함수는(reject) 작업이 실패하여 오류의 원인을 반환할 때 호출하면 된다. 두 번째 함수는 주로 오류 객체를 받는다.Promise 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타낸다.4번 과제 - 책 리스트 나열 앱https://book-list-app-three.vercel.app/ - 완성 화면https://github.com/ygvbhy/book-list-app - 코드빌드 도구 ViteCSS Bootstrap 5 (CDN)js Vanilla배포도구 Vercel해결 과정책 리스트를 저장 하는 방법으로 배열을 선택. 로컬 스토리지와 고민 하다가 1회성으로 보여주는 방향으로 결정삭제 버튼 클릭 부분에서 헷갈렸지만, 부모 요소를 선택하여 이벤트를 추가하는 걸로 해결알림 출력 부분도 출력 후 지우는건 가능한데 연속적으로 진행 했을 경우 나타나지 않는 오류로 인해 Math 함수를 사용해 임의 숫자를 id 값으로 부여 한 뒤 setTimeout 으로 랜덤 숫자의 id 를 찾아 해당 부분을 삭제하는 것으로 진행알림은 없지만 아무런 정보를 입력하지 않고 저장시 함수에서 return5번 과제 - Github Finder 앱https://github-finder-app-rose.vercel.app/- 완성 화면https://github.com/ygvbhy/github-finder-app - 코드빌드 도구 ViteCSS Bootstrap 5 (CDN)js Vanilla배포도구 Vercellibrary Axios해결 과정GitHub API 를 활용 하여 데이터를 받아와서 화면에 표기해주는 작업api 는 axios 를 사용하여 동기/비동기 작업 진행작업 도중 도중 ip 에 할당된 api 사용횟수 초과로 인해 힘들었다..  같은 내용이지만 노션 정리 내용https://skpost.notion.site/2-FE-1-1103a6f79dfb80da94ffd00752c9f9dd

프론트엔드워밍업클럽스터디프론트엔드JS1주차

SK 1개월 전
Taeho

인프런 워밍업 클럽 - CS Day 4

그림으로 쉽게 배우는 자료구조와 알고리즘(기본편)StackLIFO(Last-in First-out)가장 먼저 들어온 데이터가 가장 나중에 나가는 자료 구조가장 나중에 들어온 데이터가 가장 먼저 나가는 자료 구조Linked List를 사용하여 Stack을 구현할 수 있다.출처 : https://www.geeksforgeeks.org/stack-data-structure/?ref=header_outindLinked List를 사용한 구현head를 사용하여 스택을 간단하게 구현할 수 있다.데이터 삽입을 무조건 첫 번째 인덱스에 수행한다.⇒ 한쪽으로만 데이터를 삽입하고, 삭제하면 간단하게 구현할 수 있다.Stack을 사용하는 상황웹 브라우저 방문 기록 (뒤로 가기 기능)프로그램의 실행 취소(Undo) 기능 구현역순 문자열 만들기수식의 괄호 검사후위 표기법 계산함수 호출 관리 (프로그램의 함수 호출 스택)깊이 우선 탐색(DFS) 알고리즘 구현Stack ADTpush() - 데이터 삽입pop()- 데이터 제거peek() - 데이터 참조isEmpty() - 비었는지 체크QueueFIFO(First-in First-out)가장 먼저 들어온 데이터가 가장 먼저 나가는 자료 구조가장 나중에 들어온 데이터가 가장 나중에 나가는 자료 구조Linked List를 사용하여 Queue를 구현할 수 있다.출처 : https://www.geeksforgeeks.org/queue-data-structure/Linked List를 사용한 구현head를 사용하여 Queue를 간단하게 구현할 수 있다.데이터를 뒤에서 제거하는 것을 구현해야 한다.→ 단방향 Linked List의 경우에는 가장 마지막에 있는 Node에 접근하기 위해서는 head에서부터 순차적으로 접근해야 한다.→ O(n)의 시간이 소요된다.⇒ tail을 사용하여 가장 마지막의 노드 정보를 저장한다.→ tail을 사용하더라도 가장 마지막의 노드 정보를 갱신하기 위해서는 head에서부터 순차 접근해야 한다.→ O(n)의 시간이 소요된다.⇒ 이중 연결 리스트를 사용하여 구현하면 O(n)을 O(1)로 개선할 수 있다.Queue를 사용하는 상황프린터의 인쇄 대기열 관리OS에 작업 요청이 들어오면 들어온 순서대로 큐에 넣고, CPU가 순서대로 꺼내서 처리한다.→ FIFO 스케쥴링네트워크의 데이터 패킷 전송 관리실시간 시스템의 인터럽트 처리너비 우선 탐색(BFS) 알고리즘 구현캐시(Cache) 구현은행 창구와 같은 대기열 시스템 모델링동시성 프로그래밍에서의 작업 큐Queue ADTenqueue() - 데이터 삽입dequeue() - 데이터 제거front() - 데이터 참조(Tail 참조)isEmpty() - Queue가 비었는지 확인Deque데이터의 삽입과 제거를 head와 tail에서 자유롭게 할 수 있는 자료구조Deque을 사용하여 Stack과 Queue를 구현할 수 있다.출처 : https://www.geeksforgeeks.org/deque-in-python/?ref=header_outindDeque ADTprintAll() - 리스트의 모든 데이터 출력addFirst() - head에 데이터 삽입removeFirst() - head에서 데이터 제거addLast() - tail에 데이터 삽입removeLast() - tail에서 데이터 제거isEmpty() - 리스트가 비었는지 체크그림으로 쉽게 배우는 운영체제Context Switching프로세스를 실행하는 중에 다른 프로세스를 실행하기 위해 실행중인 프로세스의 상태를 저장하고, 다른 프로세스의 상태값으로 전환하는 작업Context Switching이 발생할 때 PCB의 내용이 변경된다.프로세스 상태, 프로그램 카운터, 레지스터 정보, 메모리 관련 정보 등이 변경된다.발생하는 이유CPU 점유 시간의 종료I/O 요청인터럽트가 발생한 경우프로세스 생성OS가 부팅되고 0번 프로세스가 생성될 때 딱 한 번만 수행된다.→ 그 이후에 생성되는 프로세스는 fork()를 사용하여 복사해서 사용된다.→ 새로 생성하는 것보다 복사를 하는 것이 더 빠르기 때문실행 파일(.exe)실행OS는 해당 프로그램의 코드 영역과 데이터 영역을 메모리에 로드빈 스택과 빈 힙을 만들어 공간을 확보프로세스를 관리하기 위한 PCB 생성 및 초기화exec()부모를 복사한 자식 프로세스의 코드와 데이터 영역을 원하는 값으로 덮어쓸 수 있다.→ 부모 프로세스와 다른 방식으로 동작할 수 있다.좀비 프로세스부모 프로세스가 자식 프로세스보다 먼저 종료되거나 자식 프로세스가 비정상적으로 종료돼 exit()신호를 주지 못해서 Exit Status를 읽지 못해 메모리에 계속 살아있는 상태Thread프로세스 내에 존재하고, 1개 이상이 존재할 수 있다.하나의 프로세스 내에 있는 쓰레드들은 프로세스의 PCB, Code, Data, Heap 영역을 공유한다.Stack은 공유하지 않고, 쓰레드마다 하나씩 갖고 있다.OS에서 작업을 처리하는 단위Thread 구분자Thread IDTCB(Thread Control Block)Process vs Thread안정성Process는 독립적이기 때문에 서로 영향을 받지 않는다.Thread는 하나의 Process를 공유하기 때문에 하나의 Thread에 이상이 생기면 다른 Thread에도 이상이 전파될 수 있다.⇒ Process가 유리속도와 자원각각의 Process는 서로 고유한 자원을 갖는다.코드, 데이터, 힙, 스택 영역을 전부 따로 두고 있다.Process간에 통신을 하려면 IPC를 사용해야 해서 오버헤드가 크고 속도가 느리다.쓰레드는 하나의 Process의 자원을 스택 영역을 제외한 영역을 모두 공유하기 때문에 오버헤드가 느리다.

알고리즘 · 자료구조DAY3워밍업클럽CS전공지식

Taeho

인프런 워밍업 클럽 - CS Day 5

Hash TableHash Function해시 함수는 키(key)를 입력받아 해당 키의 저장 위치(버킷 또는 인덱스)를 결정하는 계산을 하는 함수좋은 해시 함수 ⇒ 데이터를 골고루 분배시켜주는 함수장점빠른 데이터 읽기, 삽입, 삭제단점메모리를 많이 차지한다.좋은 해시 함수의 구현이 필수적이다.Hash Collision해시 충돌은 해시 함수가 서로 다른 두 개 이상의 입력 값에 대해 동일한 해시 값을 출력하는 상황을 의미Hash 충돌이 발생한 곳의 Value들을 연결리스트로 구성하여 데이터들을 연결한다.기존값과 새로운 값을 동시에 저장할 수 있다.찾고자 하는 Value가 나올 때까지 연결리스트를 탐색한다.→ O(n)의 성능을 갖는다.해결 방법체이닝 (Chaining)각 버킷에 연결 리스트를 사용하여 충돌된 항목들을 저장한다.장점: 구현이 간단하고, 해시 테이블의 확장이 필요 없다.단점: 최악의 경우 검색 시간이 O(n)이 될 수 있다.개방 주소법 (Open Addressing)충돌 발생 시 다른 빈 버킷을 찾아 데이터를 저장한다.유형:선형 탐사 (Linear Probing)제곱 탐사 (Quadratic Probing)이중 해싱 (Double Hashing)장점: 추가적인 메모리 사용이 없다.단점: 클러스터링 현상이 발생할 수 있다.재해싱 (Rehashing)해시 테이블의 크기를 동적으로 조정하여 충돌 가능성을 줄인다.Tip.Java의 HashMap의 경우에는 기본적으로 체이닝 방식을 사용한다.But. 성능 최적화를 위해 다음과 같이 구현된다.- 하나의 버킷에 8개 이상의 항목이 저장되면 연결 리스트를 트리 구조로 변환한다.- 버킷의 항목 수가 6개 이하로 줄어들면 다시 연결 리스트로 변환한다.참조 : https://d2.naver.com/helloworld/831311시간 복잡도읽기, 삽입, 수정, 삭제 : Key만 알고 있으면 Value에 O(1)로 읽기가 가능HashTable ADTset() - 데이터 삽입get() - 데이터 읽기remove() - 데이터 삭제Set데이터의 중복을 허용하지 않는 자료구조HashTable을 사용하여 구현할 수 있다.→ HashTable을 사용하기 때문에 HashSet이라고도 한다.→ HashTable의 value 값은 사용하지 않고 key만 사용하여 구현한다.(key가 key와 value의 역할을 수행한다.)Set ADTadd(data) - 데이터 삽입isContain(data) - 데이터 체크remove(data) - 데이터 제거clear() - 셋 비우기isEmpty() - 셋이 비었는지 확인printAll() - 모든 데이터 출력CPU Scheduling스케줄러가 고려해야 할 사항어떤 프로세스에게 CPU를 할당해야 하는가?CPU를 할당받은 프로세스가 얼마의 시간동안 CPU를 점유해야 하는가?→ 컴퓨터의 성능에 굉장히 큰 영향을 미친다.CPU BurstCPU를 할당받아 실행하는 작업I/O BurstI/O 작업목표목표들을 전부 만족할 수는 없다.→ 목표들에 따라 Trade-Off가 있기 때문ex) 처리량 ↑ ⇒ CPU 오래 할당, 응답시간 ↓ ⇒ 여러 프로세스에 CPU를 골고루 할당⇒ 처리량과 응답시간 사이에 Trade-Off가 발생한다.리소스 사용률CPU 사용률 높이기I/O 디바이스의 사용률 높이기오버헤드의 최소화Context Switching시에 발생하는 오버헤드를 최소화하는 것공평성모든 프로세스에게 우선순위에 따라 공평하게 CPU가 할당되어야 한다.처리량같은 시간내에 더 많은 처리를 할 수 있게 하는 것대기시간작업을 요청하고 실제 작업이 실행되기 전까지 대기하는 시간이 짧은 것응답시간사용자의 요청이 얼마나 빨리 요청하는지다중 Queue프로세스가 대기하고 있는 준비상태와 대기상태는 Queue라는 자료구조로 관리된다.OS는 해당 프로세스의 우선순위를 보고, 그에 맞는 준비 큐에 PCB를 넣는다.CPU 스케줄러는 준비상태의 다중 큐에 들어있는 프로세스들 중에 프로세스를 선택해서 실행상태로 전환시킨다.프로세스가 실행상태에서 I/O 요청을 받아 대기상태로 전환되는 경우 I/O 작업 종류에 따라 분류된 큐에 PCB가 들어간다.I/O 작업이 완료되어 인터럽트가 발생되면 분류된 큐에서 프로세스를 꺼낸다.FIFO(First-In First-Out)먼저 들어온 작업이 먼저 나간다.스케쥴링 큐에 들어온 순서대로 CPU를 할당받는 방식단점먼저 들어온 프로세스가 완전히 종료되어야만 다음 프로세스가 실행될 수 있다.→ I/O 작업이 발생하면 CPU는 I/O 작업이 끝날 때까지 쉬기 때문에 CPU 사용률이 떨어진다.→ 작업이 빠르게 종료될 수 있는 간단한 프로세스가 작업이 무거운 프로세스 뒤에 들어오면 무거운 프로세스가 완료될 때까지 기다려야 한다.프로세스의 Burst Time에 따라 성능의 차이가 심하게 나기 때문에 현대 OS에서 사용되지 않고, 주로 일괄 처리 시스템에서 사용된다.스케줄링의 성능평균 대기 시간스케줄링 성능 평가의 척도프로세스 여러개가 실행될 때 해당 프로세스들이 모두 실행되기까지 대기시간의 평균값ex)

알고리즘 · 자료구조워밍업클럽CS전공지식DAY5

Taeho

인프런 워밍업 클럽 - CS Day 3

그림으로 쉽게 배우는 자료구조와 알고리즘(기본편)Array배열의 인덱스 참조는 길이에 상관없이 한 번에 가져온다. → O(1)의 성능을 갖는다.삽입, 삭제의 성능이 좋지 않다. → 데이터를 추가, 제거하려면 내부적으로 필요한 단계가 많다.데이터 추가, 제거 시 내부적으로 수행해야 하는 단계연속된 메모리 할당배열은 메모리상에 연속적으로 저장되어 있다.→ 중간에 요소를 삽입하거나 삭제할 때 문제가 발생요소 이동 필요배열의 중간에 새로운 요소를 삽입하거나 기존 요소를 삭제할 경우, 해당 위치 이후의 모든 요소들을 이동시켜야 한다.→ 오버헤드가 발생한다.고정된 크기정적 배열의 경우 크기가 고정되어 있어, 삽입 시 공간이 부족하면 새로운 더 큰 배열을 생성하고 모든 요소를 복사해야 한다.삽입/삭제 위치에 따른 성능 차이배열의 끝에서 삽입/삭제하는 경우는 O(1)로 빠르지만, 최악의 경우(배열의 시작 부분에서 삽입/삭제) O(n)의 시간이 소요된다.메모리 재할당동적 배열의 경우, 크기를 늘릴 때 새로운 메모리 공간을 할당하고 기존 데이터를 복사해야 하므로 추가적인 시간이 소요된다.JS의 Array상황에 따라서 연속적, 불연속적으로 메모리를 할당한다.일반적으로 불연속적으로 할당한다.불연속적으로 할당된 메모리는 내부적으로 연결해서 사용자에게는 배열처럼 느껴진다.Linked List배열의 단점인 삽입, 삭제의 성능을 보완하기 위한 자료구조저장하려는 데이터들을 메모리(힙 영역)에 분산하여 할당하고, 해당 데이터를 서로 연결한다.노드를 사용하여 데이터들을 저장하고, 각 노드가 다음 노드를 가리키도록 한다.첫 노드의 주소만 알고 있으면 그 이후의 모든 노드에 접근할 수 있다.장점데이터 추가 및 삭제빈 메모리 공간 아무 곳에 데이터를 생성하고, 연결만 해주면 데이터 추가가 완료된다.중간에 데이터가 삽입/삭제 된다고 한다면 배열은 해당 데이터 이후의 모든 데이터들을 이동시켜야 하지만 연결리스트는 해당 데이터와 그 이전, 이후의 데이터만 수정하면 된다.단점특정 데이터를 찾고 싶다면 노드를 순회해야 한다. → O(n)의 성능을 갖는다. Array vs Linked List데이터의 참조가 많은 경우 ⇒ Array 사용데이터의 삽입과 삭제가 많은 경우 ⇒ Linked List 사용추상 자료형(ADT, Abstract Data Type)어떠한 데이터와 그 데이터에 대한 연산을 표기하는 방법→ 데이터의 논리적인 동작을 정의한다.구현 방법을 명시하지 않고, 자료구조의 특성과 연산만을 설명한다.데이터의 타입과 해당 타입에 수행할 수 있는 연산들만을 정의한다.내부 구현 세부사항은 숨기고 인터페이스만을 제공한다.Linked List의 ADT모든 데이터 출력 → printAll()모든 데이터 제거 → clear()인덱스 삽입 → insertAt(index, data)마지막 위치에 데이터 삽입 → insertLast(data)원하는 인덱스의 데이터 삭제 → deleteAt(index)마지막 데이터 삭제 → deleteLast()특정 인덱스 데이터 읽기 → getNodeAt(index)그림으로 쉽게 배우는 운영체제Program(= Application, App)저장장치에 저장된 명령문의 집합체Windows에서는 .exe의 형식저장 장치만 사용하는 수동적인 존재Process실행중인 프로그램저장장치에 저장된 프로그램이 메모리에 올라갔을 때 프로세스라고 한다.메모리, CPU, I/O 작업을 수행하는 능동적인 존재구조Code자신을 실행하는 코드가 저장되어 있는 영역Data전역 변수와 Static 변수가 저장되어 있는 영역Stack지역 변수와 함추 호출을 했을 때 필요한 정보들이 저장되는 영역함수 호출시 매개변수와 돌아갈 주소가 저장된다.Heap프로그래머가 동적으로 메모리를 할당하는 데 사용되는 영역→ 프로그래머가 런타임시 할당할 수 있는 메모리 공간Program → Process가 되는 과정(C 언어 기준)전처리기를 거쳐서 매크로로 정의한 숫자를 치환하고 필요한 파일을 불러온다.전처리기를 거치면 파일의 확장자는 .i가 된다.컴파일러가 컴파일 수행고수준인 C언어를 저수준인 Assembly어로 치환해준다.파일의 확장자는 .s가 된다.어셈블러가 어셈블리어를 기계어로 치환한다.파일의 확장자는 .o가 된다.링커가 링킹을 수행하여 여러 가지 라이브러리나 다른 소스 코드를 연결한다.파일의 확장자는 .exe가 된다.저장장치에 저장된 .exe파일을 실행하면 메모리에 올라가게 된다.→ 프로세스가 된다.프로세스는 운영체제에 의해 관리된다.Uni-Programming메모리에 오직 하나의 프로세스가 올라온 상태메모리 관점으로 정의Multi-Programming메모리에 여러개의 프로세스가 올라온 상태메모리 관점으로 정의Multi-ProcessingCPU 관점으로 정의CPU가 여러 개의 프로세스를 처리하는 것을 의미한다.Swapping메모리에 있는 데이터를 다른 저장장치로 보내고 다른 저장장치에서 데이터를 메모리로 올리는 방법PCB(Process Control Block)프로세스가 만들어지면 운영체제는 해당 프로세스의 정보를 갖고 있는 PCB를 만들고 저장한다.PCB들은 연결리스트라는 자료구조로 저장된다.OS는 프로세스가 종료되면 연결리스트에서 해당 프로세스의 PCB를 제거한다.구조Pointer부모와 자식 프로세스에 대한 포인터할당된 자원에 대한 포인터프로세스의 한 상태에서 다른 상태로 전환될때 저장하는 포인터Process Status현재 프로세스의 5가지 상태를 의미생성, 준비, 실행, 대기, 완료Process ID : 프로세스를 식별하기 위한 숫자Program Counter다음에 실행될 명령어의 주소를 포함한다.특정 프로세스가 CPU를 사용하다가 다른 프로세스에게 CPU를 반납하고 다시 CPU를 사용할 때 이전 상태의 명령어가 실행되어야 하기 때문에 반드시 필요하다.Register Info프로세스가 실행될 때 사용했던 레지스터의 정보PC와 마찬가지로 CPU를 뺏기고 다시 시작할 때 이전에 사용하던 값을 복구하기 위한 용도로 사용Memory Info프로세스가 메모리에 있는 위치 정보경계 레지스터 값이 저장CPU Scheduling InfoCPU 스케줄링에 필요한 우선순위, 최종 실행시간, CPU 점유시간등이 저장된다.Process Status시분할 처리를 위한 5가지 상태값New(생성)PCB를 생성하고 메모리에 프로그램 적재를 요청한 상태메모리에 프로그램 적재를 승인받으면 준비상태로 넘어간다.Ready(준비)CPU를 사용하기 위해 대기하고 있는 상태CPU 스케줄러에 의해 CPU가 할당된다.Waiting(대기)프로세스가 I/O 요청을 하면, I/O가 완료될때까지 기다리는 상태I/O 작업은 무거운 작업이기 때문에 I/O 작업이 완료될 때까지 CPU를 놀리는 것은 비효율적→ I/O 요청을 한 프로세스는 I/O 작업이 완료될 때까지 대기 상태로 두고 다른 프로세스에게 CPU를 할당한다.→ I/O 작업이 완료되면 대기 상태에 있던 프로세스에게 CPU 할당 기회를 준다.Running(실행)준비상태에 있는 프로세스가 CPU 스케줄러에 의해 CPU를 부여된 시간만큼 할당받아 실행되는 상태실행상태에 있는 프로세스의 수는 CPU의 개수이다.부여된 시간이 종료되면 CPU 스케줄러가 강제로 CPU를 빼앗는다.→ 준비 상태로 돌아간다.Terminated(완료)프로세스가 종료된 상태프로세스가 사용했던 데이터를 메모리에서 제거하고 PCB도 제거한다.

알고리즘 · 자료구조워밍업클럽CS전공지식DAY2

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

강의 : Readable Code: 읽기 좋은 코드를 작성하는 사고법1주차 진도섹션 2. 추상섹션 3. 논리, 사고의 흐름섹션 4. 객체 지향 패러다임 (SOLID) SRP(Single Responsibility Principle) : 단일 책임 원칙클래스는 단 하나의 책임을 가져야 한다.변경하는 이유는 단 하나여야 한다.SRP 원칙을 잘 지키면, 유지보수가 필요한 상황이 생겼을 때 수정할 대상이 명확해진다.클래스를 분리할 때 주의점어떤 파라미터를 전달할지 객체 입장에서 고민하기예) 익셉션 핸들러에게 e를 줄까? e.getMessage를 줄까? ⇒ e ( ∵ e를 가지고 뭘 할지는 핸들러가 알아서 해 ~ )클래스에게서 get으로 필드를 가져오는 건 무례하다구! Rude! ⇒ 메서드로 필요한 정보만을 요청하자예) 지뢰찾기 게임‘게임의 진입점’과 ‘지뢰찾기 실행’ 부분 분리입출력 관련한 것 분리게임보드 분리 OCP(Open Closed Principle) : 개방 폐쇄 원칙확장에는 열려 있고, 수정에는 닫혀 있어야 한다.새로운 요구사항이 생겼을 때, 기존 코드의 수정은 최소화 되고 새로운 기능 확장은 손쉽게 되도록 해야 한다.인터페이스를 활용하면 새로운 기능을 추가할 때기존 코드를 수정하지 않고새로운 구현체 클래스를 생성하면 된다.예) 지뢰찾기 게임 : 난이도에 따라 보드의 크기를 달리 하는 기능 추가상수로 박아둔 크기를 변수 처리GameLevel 인터페이스 사용각 난이도는 각 구현체로 LSP(Listov Substitution Principle) : 리스코프 치환 원칙부모 클래스의 인스턴스를 자식 클래스의 인스턴스로 치환할 수 있어야 한다. 상속 구조로 리팩토링할 때, 타입 체크를 하는 방향은 좋은 설계가 아니다.기존 패턴을 유지하면서 통합하는 방식으로 인터페이스를 만들면 타입 체크가 생기게 돼 ⇒ 더 추상화된 관점에서 새로운 설계를 떠올릴 수 있어야 해예) 지뢰찾기 게임 : 지뢰 Cell, 숫자 Cell, 빈 Cell을 Cell을 상속 받는 구조로 리팩토링지뢰 Cell을 구현체로 만들었으므로 플래그를 세우는 turnOn 메서드 삭제숫자 Cell을 구현체로 만들었으므로 주변부 지뢰 개수를 세서 update하는 메서드 삭제 ⇒ 생성자로 넣기 ISP(Interface Segregation Principle) : 인터페이스 분리 원칙클라이언트는 자신이 사용하지 않는 인터페이스에 의존해서는 안 된다. 예) 지뢰찾기 말고 다른 게임이 추가되는 상황새로운 게임은 initialize 메서드 사용하지 않아 ⇒ Game 인터페이스를 GameInitial과 GameRunnable로 분리 DIP(Dependency Inversion Principle) : 의존 역전 원칙상위 수준의 모듈은 하위 수준의 모듈에 의존해서는 안 된다. ⇒ 둘 다 추상화에 의존해야 한다.의존성의 순방향 : 고수준 모듈이 저수준 모듈을 참조하는 것의존을 역전시킨다 = 고수준, 저수준 모듈 모두 추상화에 의존한다.저수준은 구체 쪽에 가깝기 때문에 수정이 잦으므로 고수준이 추상화 된 스펙만 참조하도록 한다.저수준 모듈이 자유롭게 변경되어도 고수준 모듈에는 영향이 가지 않게 설계해야 한다. 예) 콘솔 외의 다른 I/O가 추가되는 상황현재 코드에서 수정하려 한다면, 마인스위퍼의 수정 불가피 해 (저수준 모듈의 변경이 고수준 모듈에 영향을 미치는 것)콘솔 핸들러를 구현체로 가지는 인풋,아웃풋 핸들러 인터페이스 생성해서 마인스위퍼에서 사용기존 메서드명이 어색해진다면 이것도 더 추상화 된 메서드 명으로 수정 : printXXX → showXXX  회고칭찬하고 싶은 점 : 워밍업 클럽의 미션을 성실히 수행했다.아쉬웠던 점 : 진도를 따라잡기 위해 리팩토링을 직접 고민해보는 과정은 생략했다.보완하고 싶은 점 : 강의에서 질문거리가 나오면 잠시 멈춰두고 혼자 고민하는 시간을 가지면 좋을 것 같다. 미션As Is public boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } else { if (order.getTotalPrice() > 0) { if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } else { return true; } } else if (!(order.getTotalPrice() > 0)) { log.info("올바르지 않은 총 가격입니다."); return false; } } return true; }To Beif - else 문은 else 대신 return을 사용해서 Early return중첩 조건문은 메서드로 추출해서 사고의 depth 줄이기의미 단위로 공백 주기부정어 줄이기public boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } if (order.getTotalPrice() > 0) { return checkCustomerInfo(order); } log.info("올바르지 않은 총 가격입니다."); return false; } public boolean checkCustomerInfo(Order order) { if (order.hasCustomerInfo()) return true; log.info("사용자 정보가 없습니다."); return false; }   

이준우

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

운영체제1.while(true){wait(1); // 1초 멈춤bool isActivated = checkSkillActivated(); // 체크}Q1 > 위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다. 이 방식은 폴링 방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다. 이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요? A1 > 인터럽트이다.인터럽트 방식은 하드웨어 장치에서 많이 사용되고 소프트웨어적(Python에서는)으로는 asyncio를 사용한다. 위 코드에서는플레이어가 스킬을 사용했을때, 인터럽트를 발생시키는 방식이 좀더 효율적이라는 것.(flag와 같은 역할을 한다고 생각함.) 그렇다고 풀링 방식이 안좋은 건 아니다. 실시간 데이터를 모니터링하거나 수집해야 할 경우 폴링 방식을 사용한다면 원활하게 데이터 수집이 가능해지기 때문이다.Q2 > 프로그램과 프로세스가 어떻게 다른가요? A2 > 프로그램은 하드디스크에 저장된 명령문의 집합체이다. 즉, 애플리케이션이라고도 불린다.프로세스는 프로그램이 메모리에 올라가서 실행되는 활동 단위이다. 즉, 실행 중인 프로그램을 의미한다.Q3 > 멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요? A3 > 메모리 관점, CPU 관점으로 나뉘게 된다.멀티프로그래밍은 메모리에 여러개의 프로세스가 올라와 있는 상황을 말한다.-> 이렇기 때문에 우리는 컴퓨터에 여러 개의 프로그램을 실행(프로세스)할 수 있게 된다.멀티프로세싱은 CPU가 시분할 처리로 각각의 프로세스를 짧은 시간동안 교대로 실행하는 것을 말한다.-> 이렇기 때문에 우리는 컴퓨터가 동시에 여러 개의 프로그램을 실행(프로세스)하는 것처럼 보인다.Q4 > 운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요? A4 > PCB(Process Control Block)를 사용한다.우리가 햄버거, 라면 등과 같은 인스턴스 음식을 먹을때, 영양정보를 확인한다.(해당 제품의 구성 확인 가능)PCB도 영양정보와 같은 역할을 담당한다. 운영체제는 프로세스의 정보를 PCB에 저장한다.PCB는 포인터, 프로세스 상태, 프로세스 ID, 프로그램 카운터, 레지스터 정보, 메모리 관련 정보, CPU 스케쥴링정보를 담는다.Q5 > 컨텍스트 스위칭이란 무엇인가요? A5 > 컨텍스트 스위칭이란 프로세스를 실행하는 중에 다른 프로세스를 실행하기 위해 실행중인 프로세스의 상태를저장하고 다른프로세스의 상태로 저장하는 작업이다. 여기서 프로세스의 시분할 처리를 위한 다섯가지 상태를 알고 있으면 좋은데, 1. 생성 2. 준비 3. 실행 4. 대기 5. 완료로 나뉜다. 예를 들어, 내가 롤이라는 게임을 하고 있다가 크롬을 켜서 웹툰을 본다면 롤이라는 프로세스는 실행 상태에서 준비상태로 돌입하고 크롬이라는 프로세스는 준비 상태에서 실행 상태로 바뀌게 된다. 이때 CPU는 롤이라는 프로세스의 PCB는 저장하고 크롬 프로세스의 PCB로 다시 세팅하는 것이다.자료구조와 알고리즘 Q1 > 여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다. 이때 여러분이라면 학생의 정보를저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요. A1 > 딕셔너리를 사용한다. 해시테이블이라고도 한다.딕셔너리의 장점은 시간복잡도가 O(1)이다. 시간 복잡도가 O(1)이기 때문에 빠르게 접근할 수 있으며, key와 value 형식이기 때문에 관리하기도 용이하며 해당 필드에 쉽게 추가, 삽입도 가능하다.Q2 > 여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다.이때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요. A2 > FIFO의 자료구조를 갖는 큐를 사용하는 것이 적합하다.문제에 직면할 때, LIFO, FIFO, LIFO&FIFO 중 어떤 문제인지 정확하게 아는 것이 중요하다.이 질문에선 '주문이 들어 온 순서대로 처리한다' 가 핵심이며, 처음 들어온 것이 가장 처음으로 나가는 구조를 갖는큐를 사용하는 것이 가장 적절하다.

워밍업

워밍업클럽2기-Backend 클린코드-#2_Day4 발자국 미션-SOLID

SOLID- 나의 언어로 정리하기 SRP- Single Responsible Principle 단일 책임 원칙객체는 단 하나의 책임만 가지고 있어야 한다. 책임을 분리하면 읽기 쉽고 유지보수하기 쉬운 코드가 된다.책임을 분리해서 서로 상호작용하며 기계 부품들 처럼 굴러가는 어플리케이션 만들기!객체들간에 서로의 코드가 어떻게 작동 하는지를 알수없게 책임을 나눠 메서드 안에 넣고 깔끔하게 숨긴다.-(뇌메모리 적게 쓰기) OCP- open closed principle -개방 폐쇠 원칙확장에는 열려있고 변경에는 닫혀있다. 인터페이스를 사용해서 다양한 확장 가능성을 열어둔다. 객체는 인터페이스만 알면 어떤 클래스가 들어오는지 몰라도 사용할수있게 코드 짜기.지뢰찾기 게임에서 처음에는 난이도가 하나밖에 없었는데 나중에 난이도 여러개를 만든다면 코드에 직접 적어서 변경하지 않고 난이도 인터페이스로 만들고 easy, normal, hard 클래스들을 만들어준다. 객체는 난이도 인터페이스는 알지만 어떤 난이도의 클래스가 들어오는지 모른다(변경X). LSP- Liskov Substitution Principle 리스코프 치환 원칙자식 클래스 는 상속 받은 부모 클래스가 가진 책임의 틀안에서 확장되어야 한다.부모클래스의 기능을 존중하지 않으면 필요하지않는 예외처리가 필요하다.예) 새 (부모 클래스) 안에 fly()메서드가 있는다 자식 클래스가 팽귄이라서 fly()에 수영하는 기능이 추가되어있다면 이건 LSP를 위반하는거고 에러가 뜰수있다. IPS- Interface Segregation Principle 인터페이스 분리 원칙인터페이스를 분리하기- 인터페이스가 너무 무거우면 사용하지않는 코드들이 많아지고 불필요한 결함도 높아진다.인터페이스를 잘게 쪼개어서 쓰지않는 기능들은 클라이언트가 가지고 있지않게 한다.텔레토비들이 먹는 쿠키를 찍어낼때 필요한 쿠키 틀을 만들때 눈과 입 모양의 쿠키 틀 인터페이스를 만드는게 아니라 쿠키의 모양 틀 인터페이스(a), 쿠키의 눈만 찍어낼수있는 인터페이스(b), 쿠키의 입만 찍어낼수있는 인터페이스(c) 이렇게 따로 분리해서 만들면 a,b 를 사용해서 눈만 있는 쿠키, a,b,c를 사용해서 눈과 입이 있는 쿠키처럼 인터페이스를 따로 분리해서 깔끔하고 다양하게 쿠키 들을 찍어낼수있다. DIP- Dependency Inversion Principle 의존역전 원칙구체적인 클래스가 아닌 추상화된 인터페이스에만 의존하게 설계하고, 실제 구현체는 외부에서 주입받아 사용하도록 한다. 이렇게 하면 어떤 구현체가 들어오더라도 기존 코드를 변경할 필요가 없고, 확장성이 크게 증가한다.쿠키 찍어내는 기계는 쿠키틀의 모양만 알면 다양한 구현체 모양의 쿠키틀의 표정은 몰라도 모양을 맞으니 그냥 끼워서 사용할수있다 😀   리팩토링 public boolean validateOrder(Order order) { if (order.getItemSize() == 0) { log.info("주문 항목이 없습니다."); return false; } if(order.getTotalPrice() <0){ log.info("올바르지 않은 총 가격입니다."); return false; } if (order.doesntHaveCustomerInfo()) { log.info("사용자 정보가 없습니다"); return false; } return true; } 추가로 변경하기 예의를 갖추어 오더에게 여쭈어보라고 강사 선생님이 그러셨당.  public boolean validateOrder(Order order) { if (lacksOfUserInfor(order)) { log.info("사용자 정보가 없습니다"); return false; } if (isOrderEmpty(order)) { log.info("주문 항목이 없습니다."); return false; } if(hasInvalidOrderPrice(order)){ log.info("올바르지 않은 총 가격입니다."); return false; } return true; } private static boolean hasInvalidOrderPrice(Order order) { return order.getTotalPrice() < 0; } private static boolean isOrderEmpty(Order order) { return order.getItemSize() == 0; } private static boolean lacksOfUserInfor(Order order) { return order.doesntHaveCustomerInfo(); }

인프런

김예지

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

 1주차JavaScript와 React를 더 공부하고 싶어서 워밍업클럽이 좋은 기회라고 생각해 신청하게 됐다. 혼자 하는 것보다 여러 명이 함께하면 더 동기부여가 되기 때문이다. 커리큘럼을 봤을 때 회사와 병행하기에 빡빡하다고 느꼈지만, 10월에 휴일이 많아 완주할 수 있을 것이라 생각했다. 막상 해보니 예상보다 빠듯하지만 완주를 목표로 하고 있다. 학습 (자바스크립트 A-Z 섹션 2~6)자바스크립트 기초를 다시 학습하면서 몰랐던 부분이나 대충 알고 있던 부분들을 확실하게 짚고 넘어갈 수 있었다. 특히 섹션 5가 재미있었는데, 구조 분해 할당, Intersection Observer를 사용한 lazy-loading, 커링 함수 등 새롭게 접한 개념들이 좋았다.  미션미션 전체 코드는 깃허브에 올렸습니다. 01 음식메뉴 앱GitHub : 01-food-menu개요객체 및 DOM, Event 다루기 필요한 기능각 카테고리별로 메뉴 항목을 HTML 요소로 동적으로 생성하여 추가탭을 클릭하면 활성화된 탭의 메뉴를 보여주기초기 상태에서는 첫 번째(0번째) 카테고리 메뉴를 기본으로 보여주기구현data.js 파일에 필요한 데이터 정리 poke: [ { name: '클래식 참치 포케', englishName: 'Classic Tuna Poke', mainIngredient: 'Tuna', description: '특제 간장 베이스와 클래식 소스가 어우러진 참치', img: 'https://www.slowcali.co.kr/data/file/main_menu/3b25130ffa2b782b388a0db95e8c1b6f_ofB4aSuQ_855bd95ad4a7a0acd9c9e0d2ca708eab2b96d5cf.png', }, ...예쁜 메뉴판을 만들고 싶어서 슬로우캘리 홈페이지에서 메뉴와 이미지를 가져다 사용했다.const categories = ['poke', 'bowl', 'wrap', 'side'];각 카테고리를 설정하고 forEach를 사용해 메뉴 생성하고 탭 클릭 이벤트를 준다..tab-content { display: none; } .tab-content.active { display: flex; }// 탭 클릭 이벤트 function handleTabClick() { const tabItems = document.querySelectorAll('.tab-item'); const tabContents = document.querySelectorAll('.tab-content'); tabItems.forEach((tab, index) => { tab.addEventListener('click', () => { // 탭 활성화 tabItems.forEach((item) => item.classList.remove('active')); tab.classList.add('active'); // 콘텐츠 활성화 tabContents.forEach((content) => content.classList.remove('active')); const selectedCategory = categories[index]; document.getElementById(selectedCategory).classList.add('active'); }); }); }탭 & 메뉴 활성화 방법 : css에서 미리 설정한 active class로 현재 선택된 메뉴를 보여준다. 회고html을 생성하는 방법은 여러가지가 있는데 이번 미션을 하면서 innerHTMl과 DOM 요소 직접 생성 방법에 대해서 더 알게된 사실이 있다.단순히 둘 다 HTML을 생성한다고 생각했는데 innerHTML은 문자열로 HTML을 삽입하기 때문에 외부 입력을 그대로 반영할 경우 악성 스크립트가 실행될 수 있어 XSS 공격에 취약하고 DOM 요소를 직접 생성하는 방법은 데이터가 HTML 구조로 변환되는 과정을 명시적으로 제어하기 때문에 잠재적인 악성 스크립트가 삽입될 가능성을 줄여준다고 한다.   02 가위 바위 보 앱GitHub : 02-rock-paper-scissors개요객체 및 DOM, Event 다루기 + 삼항 연산자 사용하기필요한 기능플레이어가 입력한 게임 횟수를 바탕으로 게임 시작하기플레이어가 가위,바위,보 중 하나를 선택하면 컴퓨터가 랜덤으로 선택최종 승리자 판별게임이 끝난 후 다시 시작하기구현let win = [0, 0]; //플레이어와 컴퓨터의 승리 횟수 let remainingGames = 0; //남은 게임 const options = ['✌', '✊', '✋']; //컴퓨터가 무작위로 선택할 배열 //게임 초기화 const resetGame = () => { win = [0, 0]; remainingGames = 0; playerMeWin.textContent = '0'; playerComputerWin.textContent = '0'; playerMeSelect.textContent = '?'; playerComputerSelect.textContent = '?'; gameCount.textContent = '0'; gameResult.textContent = '-'; };게임 상태 관리const handlePlayerChoice = (playerChoice) => { return function () { const computerChoice = options[Math.floor(Math.random() * options.length)]; playerMeSelect.textContent = playerChoice; playerComputerSelect.textContent = computerChoice; determineWinner(playerChoice, computerChoice); remainingGames--; gameCount.textContent = remainingGames; if (remainingGames === 0) { endGame(); } }; };플레이어가 가위, 바위, 보 중 하나를 선택하면 handlePlayerChoice() 함수를 호출하고 컴퓨터도 랜덤한 값을 선택하게 된다.function determineWinner(player, computer) { gameResult.textContent = player === computer ? '무승부 입니다!' : (player === '✌' && computer === '✋') || (player === '✊' && computer === '✌') || (player === '✋' && computer === '✊') ? '플레이어가 이겼어요!' : '컴퓨터가 이겼어요!'; gameResult.textContent.includes('플레이어') ? (win[0]++, (playerMeWin.textContent = win[0])) : gameResult.textContent.includes('컴퓨터') && (win[1]++, (playerComputerWin.textContent = win[1])); }determineWinner() 함수에서는 플레이어와 컴퓨터의 선택값을 비교해 삼항연산자로 승패를 결정하고 승리한 쪽의 승리 횟수를 증가시키고 화면에 반영한다. 모든 게임이 끝나면 endGame(); 함수를 호출해 최종 승리 횟수를 비교하고 결과를 팝업을 통해 알려준다. 다시하기 버튼을 누르면 resetGame() 함수를 호출해 게임을 초기화 시키고 다시 시작할 수 있다. 회고10번은 많아보여서 플레이어가 직접 게임 횟수를 정하는 기능도 추가해봤다. 컴퓨터와 플레이어 게임 횟수를 단순히 [0, 0] 이렇게 배열로 지정했는데 명확한 변수명으로 구분하는 것이 가독성 면에서는 더 좋을 것 같다.    03 퀴즈 앱GitHub : 03-quiz개요객체 및 DOM, Event 다루기 , Curry Function필요한 기능문제 1개씩 출력하기문제 번호 보여주기정답 확인 및 문제 설명 출력Next 버튼 눌렀을 때 다음 문제로 이동구현data.js 파일에 필요한 데이터 정리 { question: '다음 중 JavaScript의 데이터 타입이 아닌 것은 무엇일까요?', options: ['Number', 'String', 'Boolean', 'Character'], answer: 3, // Character explanation: 'JavaScript의 기본 데이터 타입에는 Number, String, Boolean 등이 있지만, Character 타입은 존재하지 않습니다.', },data.js에 문제들을 정리하고 이 데이터들을 바탕으로 DOM을 생성하여 문제를 보여준다.const handleAnswer = (correctAnswer, explanation) => (selectAnswer) => { quizResult.classList.add('active'); if (selectAnswer == correctAnswer) { quizMessage.textContent = '🎉 정답입니다. 🎉'; } else { quizMessage.textContent = '❌ 오답입니다. ❌'; } quizExplanation.textContent = explanation; }; // 정답 선택 quizContainer.addEventListener('click', (event) => { if (event.target.tagName === 'BUTTON') { const answerItem = event.target.parentElement; const allAnswerItems = Array.from(answerItem.parentElement.children); const index = allAnswerItems.indexOf(answerItem); allAnswerItems.forEach((item) => item.classList.remove('active')); answerItem.classList.add('active'); selectAnswer = index; // 정답 여부 확인 const correctAnswer = quizQuestions[currentQuestionIndex].answer; const explanation = quizQuestions[currentQuestionIndex].explanation; const checkAnswer = handleAnswer(correctAnswer, explanation); checkAnswer(selectAnswer); nextButton.classList.add('active'); } });handleAnswer(correctAnswer, explanation)에서 퀴즈의 정답과 설명을 받고 이후 선택된 답을 처리하고 정답 여부와 문제의 해설을 출력해준다. 회고강의에서 들은 것을 잘 활용하고 이게 맞는지 잘 모르겠다.추가해서 넣은 부분은 문제 총 갯수, 현재 풀고 있는 문제 번호 보여주기, 정답여부 보여줄 때 문제 해설도 같이 출력하기, 문제 답을 선택하기 전에는 button 비활성화 처리 선택 후 활성화하기가 있다. 문제 데이터를 더 많이 만들어서 문제를 랜덤으로 출력하고 정답률을 보여주는 부분을 추가해도 좋을 것 같다.   04 책 리스트 나열 앱GitHub : 04-display-book-list 개요기능별 클래스와 메서드 사용하기필요한 기능책 리스트 추가사용자가 값 입력 후 input 필드 초기화 하기책이 추가&삭제될 때 메세지 1초 보여주기구현class BookManager 에서는 데이터를 추가,삭제하고 목록을 관리한다.class BookUI { // constructor, init , showToast, handleDelete, createTableRow, handleAddBook 메서드 사용 }class BookUI는 책을 추가하거나 삭제할때 이를 UI에 반영하고 이벤트를 처리한다. constructor() { this.bookTitle = document.querySelector('.book-title'); this.bookAuthor = document.querySelector('.book-author'); this.submitButton = document.querySelector('button.submit'); this.tableTbody = document.querySelector('.table .tbody'); this.toastsArea = document.querySelector('.toasts'); this.bookManager = new BookManager(); this.init(); }DOM 요소들을 선택하고 BookManager 인스턴스를 생성init() { this.submitButton.addEventListener('click', this.handleAddBook.bind(this)); }사용자가 책을 추가하는 버튼을 누르면 handleAddBook 연결handleAddBook() { const titleValue = this.bookTitle.value; const authorValue = this.bookAuthor.value; if (titleValue && authorValue) { this.bookManager.addBook(titleValue, authorValue); this.createTableRow( titleValue, authorValue, this.bookManager.getBooks().length - 1 ); this.showToast('add'); this.bookTitle.value = ''; this.bookAuthor.value = ''; } else { alert('책 이름과 저자 모두 입력해야 합니다.'); } }BookManager class 에 책 추가createTableRow 메서드에서 해당 값을 받아 책 이름 / 저자 / 행 삭제 버튼 UI를 만들어준다.showToast 메서드를 통해 책 추가 메세지 출력하고 input 필드를 초기화 한다.showToast(actionType) { const messageDiv = document.createElement('div'); messageDiv.classList.add('toasts-message'); if (actionType === 'add') { messageDiv.classList.add('add'); messageDiv.textContent = '책이 추가되었습니다.'; } else if (actionType === 'delete') { messageDiv.classList.add('delete'); messageDiv.textContent = '책이 삭제되었습니다.'; } this.toastsArea.appendChild(messageDiv); setTimeout(() => { this.toastsArea.removeChild(messageDiv); }, 1000); }showToast 메서드는 현재 책이 추가된건지 삭제된건지 파라미터를 통해 받아 해당 메세지를 출력한다. handleDelete(button, rowElement, index) { button.addEventListener('click', () => { this.tableTbody.removeChild(rowElement); this.bookManager.removeBook(index); this.showToast('delete'); }); }삭제 메서드에서는 delete를 전달해 책이 삭제되었다는 메세지를 출력한다. 회고처음에는 생각 없이 앞에 했던 미션과 같은 흐름으로 코드를 작성했지만, 섹션 6, 7에 해당하는 미션이기 때문에 클래스로 구조를 변경했다. 익숙한 방식대로 작성하려는 경향이 있는 것 같다. 앞으로는 조금 더 생각하고 코드를 짜야겠다. 배운건 활용해야 하니까.하나의 책임을 가지는 클래스와 명확한 역할을 수행하는 메서드를 쓰고 싶었는데 하나의 클래스에서 너무 많은 메서드를 썼나 싶다.미션을 하는 건 재밌는데 이렇게 해도 되는 게 맞는가 하는 생각이 든다.  05 Github Finder앱GitHub : 05-github-finder  개요API 사용하기, 비동기필요한 기능사용자가 input에 입력하는 값 실시간으로 받기github API를 통해 유저 정보 보여주기사용자 명(input 값)이 비어있을 때는 copyright를 보여줌구현userID.addEventListener('input', (event) => { const username = event.target.value.trim(); if (username === '') { copyright.classList.add('active'); user.classList.remove('active'); } else { copyright.classList.remove('active'); user.classList.add('active'); getUserProfileAndRepos(username); } });유저 id에는 공백이 들어가지 않기 때문에 input에서 사용자가 실수로 입력한 공백은 삭제해준다. getUserProfileAndRepos()함수로 입력된 값을 전달.async function getUserProfileAndRepos(username) { /* profileUrl , reposUrl 링크에서 username 받음 블로그에서 자꾸 이상하게 입력되어서 코드는 아래에 따로 뺐다. */ try { const [profileResponse, reposResponse] = await Promise.all([ fetch(profileUrl), fetch(reposUrl), ]); if (profileResponse.ok && reposResponse.ok) { const profileData = await profileResponse.json(); const reposData = await reposResponse.json(); userImageElement( '.user-profile-img img', profileData.avatar_url, profileData.login ); userTextElement('.user-profile-link', profileData.html_url, true); userTextElement('.user-repos span', profileData.public_repos); userTextElement('.user-gists span', profileData.public_gists); userTextElement('.user-followers span', profileData.followers); userTextElement('.user-following span', profileData.following); userTextElement('.user-company span', profileData.company); userTextElement('.user-website span', profileData.blog); userTextElement('.user-location span', profileData.location); userTextElement( '.user-member span', new Date(profileData.created_at).toLocaleDateString() ); // 저장소 목록 최대 4개 projectArea.innerHTML = ''; reposData.slice(0, 4).forEach((repo) => { const projectElement = createProjectListElement(repo); projectArea.appendChild(projectElement); }); } else { handleError(); } } catch (error) { handleError(); } }const profileUrl = https://api.github.com/users/${username};const reposUrl = https://api.github.com/users/${username}/repos; Promise.all()을 사용해 프로필 정보와 저장소 목록을 동시에 요청한다. response.ok를 통해 두 요청이 모두 성공했는지 확인하고 .json() 메서드를 호출해 응답된 값을 자바스크립트에서 사용 가능하도록 JSON 형식에서 자바스크립트 객체로 변환해준다.요청이 실패하면 handleError()가 호출되어 에러 메세지가 표시된다. handleError() 함수에는 사용자 정보를 보여주는 UI를 초기화 하는 clearUserProfileAndProjects()함수와 User not found 메세지를 출력하는 toggleActiveClass() 함수가 들어있어 두 함수가 같이 호출된다.function userTextElement(selector, value, isLink = false) { const element = document.querySelector(selector); if (element) { if (isLink) { element.href = value; } else { element.textContent = value || 'N/A'; } } } function userImageElement(selector, src, alt) { const image = document.querySelector(selector); if (image) { image.src = src; image.alt = alt; } }유저의 저장소 목록이 몇 개 있을지 모르기 때문에 하단의 저장소 목록은 createProjectListElement() 함수를 통해 데이터를 전달 받아 DOM을 생성해 보여주고 상단의 유저 정보는 미리 생성된 el에 값을 넣어 보여준다.유저 정보를 보여주기 위해 불러오는 document가 많아서 어떤 곳에 어떤 값이 들어가는지 한눈에 보고 싶어서 userTextElement()와 userImageElement() 함수를 만들고 userTextElement('.user-repos span', profileData.public_repos); 이런식으로 코드를 써봤다. 회고깃허브 API는 비인증 요청의 경우 시간당 60회 요청이 가능하기 때문에 따로 토큰 발급 받는 부분은 생략했다. API를 사용해 데이터를 받아 보여주는 작업이 재미있었다. 주차 회고와 미션에 대한 내용을 같이 쓰다보니 글이 길어졌다. 다음 미션도 힘내서 해야겠다. 🙂 

워밍업클럽

hoonti06

인프런 워밍업 클럽 스터디 2기 백엔드 클린 코드, 테스트 코드 - Day4 미션

 아래 코드와 설명을 보고, [섹션 3. 논리, 사고의 흐름]에서 이야기하는 내용을 중심으로 읽기 좋은 코드로 리팩토링[before]public boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } else { if (order.getTotalPrice() > 0) { if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } else { return true; } } else if (!(order.getTotalPrice() > 0)) { log.info("올바르지 않은 총 가격입니다."); return false; } } return true; } [after]public boolean validateOrder(Order order) { if (order.isItemCountEqualTo(0)) { log.info("주문 항목이 없습니다."); return false; } if (order.isTotalPriceLessThanOrEqualTo(0)) { log.info("올바르지 않은 총 가격입니다."); return false; } if (order.hasCustomerInfo()) { return true; } return false; } SOLID에 대하여 자기만의 언어로 정리해 봅시다.SRP하나의 클래스는 변경의 이유가 하나여야 한다.변경의 파급력이 작아야 한다.OCP수정에는 닫혀 있고, 확장에는 열려 있다.새로운 기능을 추가할 때, 기존 코드의 수정이 최소화되어야 한다. LSP부모 인스턴스가 사용되는 위치에 자식 인스턴스가 와도 의도대로 동작해야 한다.자식 클래스는 선행 조건이 더 까다로우면 안 된다.기존 부모 인스턴스에서는 사전 과정에서 유효했던 것들이 자식 인스턴스에서는 유효하지 않게 될 수 있어, 자식 인스턴스가 왔을 때 의도와 다르게 동작할 수 있다.자식 클래스는 후행 조건이 느슨해선 안 된다.기존 부모 인스턴스에서는 사후 과정에서 통과되었던 범위보다 자식 인스턴스에서 더 큰 범위가 통과되면 클라이언트 입장에서 대응이 어렵다.ISP클래스 자신이 이용하지 않는 메서드에 의존하지 않아야 한다.인터페이스를 잘게 쪼개는 것이 좋다DIP상위 모듈과 하위 모듈은 추상화(인터페이스)에 의존해야 한다.상위 모듈은 하나의 기능이라고 보면, 하위 모듈은     

Taeho

인프런 워밍업 클럽 - CS Day 2

그림으로 쉽게 배우는 자료구조와 알고리즘(기본편)What is Data Structure?자료구조 : 데이터가 어떤 구조로 저장되고 어떻게 사용되는지를 나타낸다.변수 : 가장 단순한 자료구조배열 : 숫자나 문자열 등을 연속적으로 저장하는 자료구조인덱스를 통해 특정 숫자나 문자열에 접근할 수 있다.자료구조에 따라서 결과를 얻기 위한 처리 방법이 달라진다.What is Algorithm?어떤 문제를 해결하기 위한 확실한 방법문제를 해결할 수 있는 알고리즘은 하나만 존재하는 것이 아니라 여러가지 방법이 있을 수 있다.더 좋은 알고리즘이란?사용자에 따라 다를 수 있음메모리 사용률메모리를 더 사용하더라도 속도가 더 빠른 경우일반적으로 알고리즘 성능의 척도를 시간 복잡도로 표현한다.시간 복잡도란?특정 알고리즘이 어떤 문제를 해결하는 데 걸리는 시간Bit-Ω : 최선의 시간 복잡도Big-O : 최악의 시간 복잡도가장 많이 사용된다.Big-θ : 평균의 시간 복잡도코드에서 성능에 많은 영향을 주는 부분코드의 속도를 판가름 하는 부분→ 반복문특정 알고리즘의 성능을 평가할 때는 알고리즘의 반복문을 보고 성능을 평가한다.Big-O선형시간 알고리즘입력의 크기(n)에 대비해 걸리는 시간을 그래프로 그렸을 때 정확히 직선이 된다.시간 복잡도 : O(n)입력의 크기가 증가함에 따라 실행 시간이 일정한 비율로 증가하는 알고리즘상수시간 알고리즘입력의 크기와 관계없이 항상 일정한 시간 내에 실행되는 알고리즘시간 복잡도 : O(1) Big-O 표기법은 성능을 정확하게 표기할 수는 없다.→ 해당 알고리즘의 입력이 늘어날 때 단순히 계산량이 얼마나 늘어나는지를 표현하는 방법이기 때문→ 계산에 가장 많은 영향을 끼치는 연산만 표기한다.그림으로 쉽게 배우는 운영체제OS개인용 컴퓨터 : Windows, MacOS대형 컴퓨터 / 서버 : Linux, Unix스마트폰 / 태블릿 : Android, iOS내비게이션, 스마트 워치, 냉장고, 세탁기 등 : 임베디드 운영체제싱글 스트림 배치 시스템한 번에 하나의 작업만 실행한다.사용자는 컴퓨터와 직접 상호작용하지 않는다.작업은 일괄적으로 처리되며, 순차적으로 실행된다.작업 결과는 나중에 출력된다.시분할 시스템여러 사용자가 동시에 컴퓨터 자원을 공유할 수 있게 해주는 방식CPU 시간을 짧은 시간 단위로 나누어 여러 작업에 할당한다.사용자는 시스템과 상호작용할 수 있다.메모리 침범 이슈가 발생UNIXAT&T벨 연구소에서 탄생한 C언어 기반의 OS멀티 프로그래밍, 다중 사용자, 파일 시스템을 지원한 OSOS가 하는 일프로세스 관리프로세스를 관리하지 않는다면 여러 개의 프로그램들을 동시에 수행할 수 없다.메모리 관리모든 프로그램은 메모리에 올라가서 동작한다.H/W 관리사용자가 H/W에 대한 직접 접근을 막는다.File System 관리OS의 핵심 → Kernel커널은 프로세스와 메모리, 저장장치를 관리하는 핵심적인 기능을 담당한다.사용자는 OS의 커널에 직접 접근할 수 없고, Interface를 통해서 접근할 수 있다.Interface : GUI, CLIGUI(Graphic User Interface)Graphic을 통해서 사용자와 커널이 상호작용한다.CLI(Command Line Interface)Unix, Linux가 기본적으로 제공하는 인터페이스Text를 이용하여 사용자와 커널이 상호작용한다.System CallApplication이 커널과 상호작용하기 위한 인터페이스커널에서 제공하는 write()를 사용한다.→ OS가 저장장치의 빈 공간에 자동으로 저장한다.DriverH/W와 Kernel의 인터페이스각각의 H/W에 대한 프로그램을 커널이 전부 알고 있을 수 없음→ H/W 제조사에서 드라이버를 제작하여 커널에 제공한다.폰 노이만 구조현대 컴퓨터의 기본이 되는 중요한 아키텍처로, 그 단순성과 범용성으로 인해 여전히 널리 사용되고 있다.그 한계를 극복하기 위해 캐시 메모리, 병렬 처리 등 다양한 기술이 개발되어 적용되고 있다.CPU와 메모리를 Bus로 연결한다.Bus : 데이터를 전달하는 통로프로그램 내장 방식프로그램은 메모리에 올려서 실행된다.프로그램을 메모리에 내장했다고 하여 프로그램 내장 방식이라고 한다.주요 구성 요소중앙처리장치(CPU)메모리입출력 장치핵심 특징프로그램 내장 방식: 프로그램과 데이터를 동일한 메모리에 저장한다.순차적 처리: CPU가 메모리로부터 명령어를 순차적으로 읽어 실행한다.단일 버스 구조: CPU와 메모리 사이에 하나의 버스를 사용하여 데이터와 명령어를 전송한다.장점범용성: 하드웨어 변경 없이 소프트웨어만 교체하여 다양한 작업을 수행할 수 있음.편의성: 프로그램 변경이 용이하여 컴퓨터의 활용도를 크게 높임단점폰 노이만 병목 현상: 단일 버스 구조로 인해 CPU와 메모리 간의 데이터 전송에 병목 현상이 발생할 수 있다.순차 처리의 한계: 한 번에 하나의 명령어만 처리하므로 CPU 활용이 비효율적일 수 있다.최근의 컴퓨터 H/W메인보드다른 하드웨어를 연결하는 장치장치 간에 데이터를 전송하는 버스가 존재한다.CPUMemoryCPU(Central Processing Unit, 중앙 처리 장치) 구조Control Unit(제어 장치)모든 장치들의 동작을 지시하고 제어한다.ALU(Arithmetic and Logic Unit, 산술논리 연산장치)실제로 데이터 연산을 수행한다.Register프로그램 카운터메모리 주소 레지스터메모리 버퍼 레지스터명령어 레지스터CPU 내에서 계산을 위해 임시로 데이터를 저장한다.Memory 종류RAM(Random Access Memory)랜덤으로 데이터를 읽어도 저장된 위치와 상관 없이 동일한 읽는 속도를 갖는다.전력이 끊기면 데이터를 잃어버린다.메인 메모리로 사용된다.ROM(Read Only Memory)전력이 끊겨도 데이터를 보관할 수 있다.데이터를 한 번 쓰면 수정할 수 없다.BIOS를 저장하는데 주로 사용한다.Computer의 부팅 과정전원 인가ROM에 저장된 BIOS 실행BIOS가 컴퓨터에 연결된 장치들(CPU, RAM, 키보드, 마우스, 저장장치, etc...)에 이상이 없는지 체크한다.이상이 있으면 오류를 반환하면서 부팅이 이루어지지 않는다.H/W에 있는 마스터 부트 레코드에 저장된 부트로더를 메모리로 가져와서 실행시킨다.OS를 메모리로 올린다.CPU의 I/O 작업CPU는 입출력 작업이 들어오면 입출력 관리자에게 입출력 명령을 내린다.PollingCPU는 입출력 명령이 언제 완료될지 알 수 없기 때문에 입출력 관리자에게 주기적으로 신호를 보내어 종료 여부를 확인한다.→ 주기적으로 CPU가 확인해야 해서 성능이 좋지 않다.InterruptPolling 방식의 단점을 해결한 방식CPU가 입출력 관리자에게 명령을 내리고, CPU는 다른 작업을 수행한다.입출력 관리자는 입출력이 완료되었을 때 CPU에게 신호를 준다. CPU는 해당 신호를 받아서 ISR(인터럽트 서비스 루틴)을 실행시켜 작업을 완료한다.비동기적으로 동작하기 때문에 성능에 이점이 있다.ISR(Interrupt Service Routine)특정 인터럽트가 들어오면 해당 인터럽트를 처리하는 함수Interrupt의 종류H/W Interrupt외부 하드웨어 장치(키보드, 마우스, 타이머 등)에 의해 발생시스템 버스를 통해 CPU에 전달됨예기치 못한 상황에 대응하기 위해 사용S/W Interrupt사용자 프로그램에서 발생한 인터럽트프로그램 실행 중 특정 명령어에 의해 발생주로 시스템 콜(system call)을 구현하는 데 사용됨예외 처리나 오류 상황에 대응하기 위해 사용

알고리즘 · 자료구조워밍업클럽CS전공지식DAY1

박지원

[인프런 워밍업 클럽 스터디] Day 4 미션

1. 아래 코드와 설명을 보고, [섹션 3. 논리, 사고의 흐름]에서 이야기하는 내용을 중심으로 읽기 좋은 코드로 리팩토링해 봅시다.public boolean validateOrder(Order order) { if (order.checkItemsNone()) { log.info("주문 항목이 없습니다."); return false; } if (order.getTotalPrice() <= 0) { log.info("올바르지 않은 총 가격입니다."); return false; } if (order.hasNotCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } return true; } 2. SOLID에 대하여 자기만의 언어로 정리해 봅시다.SOLID객체지향 설계를 더 이해하기 쉽고 유연한 형태로, 유지 보수를 쉽게 만드는 데 도움을 주는 원칙 SRP: Single Responsibility Principal 단일 책임 원칙하나의 클래스가 하나의 책임만 갖도록 설계함객체의 공개 메서드, 필드, 상수 등이 객체의 단일 책임에 의해서만 변경되어야 한다. 상수: 동일한 퍼블릭 상수를 두 가지 객체가 사용하는 경우를 고려한다.관심사의 분리와도 일맥상통높은 응집도(클래스, 모듈 등이 긴밀하게 연결되어 있는 정도), 낮은 결합도(협력 관계의 2개 이상 객체에서, 한 객체가 변경될 때 다른 객체가 영향 받는 정도/ 의존성의 최소화라고도 함)*책임의 경계선을 인식하기 위해서는 계속해서 질문을 던져 보는 경험적 측면이 필요. OCP: Open-Closed Principle 개방-폐쇄 원칙새로운 요구 사항의 추가와 같은 변동 사항 발생 시, 기존 코드 변경 없이 시스템의 기능을 확장한다.추상화와 다형성을 통해 지킬 수 있다.*난이도 조절 기능이 추가된다면> (1) 숫자 변경되었을 때 그 숫자에 맞춰 게임이 정상 진행되도록 한다 (2) 난이도 조절에 대한 요구사항에 대응한다의 순서로 기능을 추가해 나간다. LSP: Liskov Substitution Principle 리스코프 치환 원칙상속 구조에서 부모 클래스 인스턴스를 자식 클래스 인스턴스로 치환할 수 있어야 한다.일반적으로부모 클래스보다 자식 클래스의 기능이 더 많다. 이때 부모 클래스가 기능하는 것을 자식 클래스가 해도 동일하게 동작해야 한다는 것.LSP를 위반하면 상속 클래스 사용 시 예외가 발생하거나, 불필요한 타입 체크가 필요할 수 있다. ISP: Interface Segregation Principle 인터페이스 분리 원칙클라이언트는 자신이 사용하지 않는 인터페이스에 의존해서는 안된다. 즉 인터페이스를 기능 단위로 잘게 나눠야 한다.ISP를 위반하면 결합도가 높아지고, 특정 기능 변경이 여러 클래스에 영향을 미칠 수 있다.  DIP: Dependency Inversion Principle 의존성 역전 원칙상위 수준 모듈이 하위 수준 모듈에 직접 의존하지 않고, 두 개 모두 추상화에 의존해야 한다.상위 수준 모듈: 추상화 레벨이 높은 쪽하위 수준 모듈: 구체에 가까운 쪽 *의존성: 하나의 모듈이 다른 하나 모듈을 알고 있거나 직접 사용하는 모든 것들의존성의 순방향: 고수준 모듈이 저수준 모듈을 참조하는 것의존성의 역방향: (고수준 모듈) 기능을 추상화해서 추상화된 스펙을 만족하는 것을 이용해 요구사항을 해결할 수 있는 것. (저수준 모듈) 인터페이스를 구현한 구현체가 얼마든지 바뀔 수 있는 것.즉, 추상화를 가운데 두고 의존하도록 하는 것 *DIP, DI, IoCDIP(Dependency Inversion Principle): 고수준 모듈과 저수준 모듈은 직접적 의존이 아닌 추상화에 의존해야 한다.DI(Dependency Injection): 필요한 의존성을 외부에서 주입받는다. "3"의 숫자를 기억할 것. 객체 a, b가 있는 상황에서 a가 b를 필요로 할 때 직접 생성자를 통해 주입 받는 것이 아닌, 제3자가 둘 사이의 의존성을 맺어준다. 스프링에서는 스프링 컨텍스트(**IoC 컨테이너)가 한다.IoC(Inversion of Control): 프로그램 제어 주도권이 개발자가 아닌 프레임워크에 있다.**IoC 컨테이너: 객체의 생명주기를 관리하고 의존성 주입까지 해 준다.

인프런워밍업클럽스터디

jin02019

인프런 워밍업 클럽 2기(클린코드/테스트 코드)_day4 미션

1. 아래 코드와 설명을 보고, [섹션 3. 논리, 사고의 흐름]에서 이야기하는 내용을 중심으로 읽기 좋은 코드로 리팩토링해 봅시다.✔ 사용자가 생성한 '주문'이 유효한지를 검증하는 메서드. ✔ Order는 주문 객체이고, 필요하다면 Order에 추가적인 메서드를 만들어도 된다. (Order 내부의 구현을 구체적으로 할 필요는 없다.) ✔ 필요하다면 메서드를 추출할 수 있다.public boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } else { if (order.getTotalPrice() > 0) { if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } else { return true; } } else if (!(order.getTotalPrice() > 0)) { log.info("올바르지 않은 총 가격입니다."); return false; } } return true; }리팩토링 후 public boolean validateOrder(Order order) { if (order.getItems().isEmpty()) { log.info("주문 항목이 없습니다."); return false; } if (order.getTotalPrice() > 0) { if (order.hasCustomerInfo()) { return true; } log.info("사용자 정보가 없습니다."); return false; } if (order.getTotalPrice() <= 0) { log.info("올바르지 않은 총 가격입니다."); return false; } return true; } }!(부정 연산자) 줄이기dept 줄이기공백 라인 추가 2. SOLID에 대하여 자기만의 언어로 정리해 봅시다.단일 책임 원칙하나의 클래스는 하나의 책임만 가져야 한다. 하나의 역할에 집중하면 코드를 수정할 때 다른 부분에 영향을 주지 않고 유지보수가 쉬워진다.개방 - 폐쇄 원칙확장에는 열려 있고 수정에는 닫혀있어야 한다.기존의 코드를 변경하지 않고 새로운 기능을 추가할 수 있어야 한다. 이미 작동하는 코드가 손상될 위험이 줄어들고 확장도 수월하다.리스코프 치환 원칙부모 클래스 대신 자식 클래스를 사용해도 문제가 없어야 한다. 자식 클래스가 부모 클래스의 기능을 대신할 수 있다면 코드의 안정성을 높일 수 있다.인터페이스 분리 법칙인터페이스는 필요한 기능만을 나누어 제공해야 한다.큰 인터페이스보다는 작은 인터페이스 여러 개로 설계해야 한다.불필요한 의존성을 줄이고 코드의 유연성을 높일 수 있다.의존 역전 법칙고수준 모듈은 저수준 모듈에 의존하지 않아야 한다.추상화된 인터페이스에 의존해야 한다.변화에 강한 구조를 만들고 코드의 재사용성을 높일 수 있다. 

프로그래밍 언어읽기좋은코드를작성하는사고법day4미션

bbcc

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

**운영체제**1.while(true) { wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 }위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다.이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다.이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요?: 인터럽트 방식 2. 프로그램과 프로세스가 어떻게 다른가요?프로그램: (컴퓨터가 이해할 수 있는) 명령문의 집합체프로세스: 실행 중인 프로그램 3. 멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?멀티프로그래밍: 메모리에 여러 개의 프로세스 올라온 것.CPU 사용률을 극대화 시키는 것이 목적.멀티프로세싱: 여러 CPU 코어나 프로세서를 사용하여 동시에 여러 작업을 처리하는 것 4. 운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?: 정보를 관리하기 위해 프로세스 제어 블록(PCB)을 사용합니다. 프로세스ID, 레지스터 값, 프로세스 상태 등이 저장되어 있습니다. 5. 컨텍스트 스위칭이란 뭔가요?운영 체제가 한 프로세스에서 다른 프로세스로 CPU 할당을 전환하는 과정.기존 프로세스 문맥을 PCB에 백업하고, 새로운 프로세스를 실행하기 위해 문맥을 PCB로부터 복구하여 새로운 프로세스를 실행하는 것.여러 프로세스가 CPU를 번갈아가며 사용하는 '멀티 태스킹' 과정에서, 프로세스끼리 작업이 스위칭되는 것.  **자료구조**1. 여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다. 이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요. : 배열. 교실에 있는 총 학생의 수는 예측이 가능하고저장, 열람 기능만 필요하다면 데이터의 삽입/삭제가 이루어지지 않음. 2. 여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다.주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요.: 선입선출(FIFO) 구조를 가진 '큐'를 선택하겠습니다.

워밍업 클럽 2기 BE 클린코드&테스트코드 DAY 4 미션

public boolean validateOrder(Order order) { if (hasNoItems(order)) { log.info("주문 항목이 없습니다."); return false; } if (hasInvalidTotalPrice(order)) { log.info("올바르지 않은 총 가격입니다."); return false; } if (hasNoCustomerInfo(order)) { log.info("사용자 정보가 없습니다."); return false; } return true; }SOLID단일 책임 원칙 (Single Responsibility Principle):클래스는 오직 하나의 책임만 가져야 하며, 변경의 이유도 하나여야 합니다.이를 통해 클래스는 더 작고 관리하기 쉬운 단위로 나누어질 수 있습니다.여러 책임을 가진 클래스는 수정 시 영향 범위가 커지고, 유지보수성이 낮아질 수 있습니다.개방-폐쇄 원칙 (Open/Closed Principle):소프트웨어는 기능을 확장할 수 있어야 하지만, 기존 코드를 수정하지 않아야 합니다.이는 주로 인터페이스나 추상화를 통해 달성되며, 코드 수정 없이 새로운 기능을 추가할 수 있게 합니다.이 원칙을 지키면 기존 기능이 안정적으로 유지되고, 새로운 요구사항에 대응하기 쉬워집니다.리스코프 치환 원칙 (Liskov Substitution Principle):자식 클래스는 부모 클래스에서 기대되는 기능을 모두 수행할 수 있어야 합니다.자식 클래스가 부모 클래스 대신 사용되더라도 프로그램의 기능은 변하지 않아야 합니다.이를 지키면 클래스 간 상속 구조에서 예기치 않은 오류를 방지할 수 있습니다.인터페이스 분리 원칙 (Interface Segregation Principle):클라이언트는 자신이 사용하지 않는 인터페이스나 메서드에 의존하지 않아야 합니다.큰 인터페이스를 작게 분리함으로써 클라이언트가 필요하지 않은 기능에 의존하는 것을 피할 수 있습니다.이렇게 하면 불필요한 코드 의존성을 줄이고 유지보수성을 높일 수 있습니다.의존성 역전 원칙 (Dependency Inversion Principle):고수준 모듈은 저수준 모듈에 의존해서는 안 되며, 둘 다 추상화에 의존해야 합니다.이는 구체적인 구현보다는 인터페이스나 추상 클래스를 통해 모듈 간 의존성을 줄이는 방식입니다.이 원칙을 따르면 시스템이 유연하고 확장 가능해지며, 변경에 더 잘 대응할 수 있습니다.

백엔드

[워밍업 클럽 2기] Day4 - 논리, 사고의 흐름 & SOLID

워밍업 클럽 2기 [Clean Code & Test Code](https://www.inflearn.com/roadmaps/5699) 로드맵의 Day4 미션입니다. 1. 코드 리팩토링As-Ispublic boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } else { if (order.getTotalPrice() > 0) { if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } else { return true; } } else if (!(order.getTotalPrice() > 0)) { log.info("올바르지 않은 총 가격입니다."); return false; } } return true; } To-Bepublic boolean validateOrder(Order order) { if (order.itemsIsEmpty()) { log.info("주문 항목이 없습니다."); return false; } if (order.customerInfoIsEmpty()) { log.info("사용자 정보가 없습니다."); return false; } if (order.totalPriceIsNegative()) { log.info("올바르지 않은 총 가격입니다."); return false; } return true; }고려한 내용!를 쓰지 않고 부정어구를 사용해서 처리일찍 return할 수 있는 부분은 return을 해서 이전 내용을 신경 쓰지 않아도 된다else 지양분기문 중첩 depth 줄이기 2. SOLID(객체 지향의 5대 원칙)SRP(단일 책임)SRP는 하나의 클래스 또는 모듈은 하나의 책임을 가져야 한다는 원칙이다. Q. 그럼 책임이라는 것은 무엇일까? 여기서 책임은 "변경의 이유"라고 표현할 수 있다. 만약 하나의 클래스가 여러 가지 이유로 변경되어야 한다면, 그 클래스는 여러 가지 책임을 가지고 있다는 뜻이다. 이렇게 여러가지 책임이 하나의 클래스에 존재한다면, 추후에 유지보수하기 어려워질 가능성이 높다. Q. 그러면 책임의 범위를 어떻게 정하는 것이 좋을까?책임의 범위라는 것은 문맥과 상황에 따라 다를 수 있다. 이런 책임의 범위를 잘 정하는 것은 경험적인 영역이 많이 포함된다. (한마디로 책임을 보는 눈을 기르기 위해서는 경험을 많이 쌓자!)확실한 것은 어떤 변경이 있을 때 파급 효과가 적다면 SRP를 잘 따른 것으로 볼 수 있다. 정리하자면 SRP는 변경의 이유를 하나로 만들어서 코드의 응집성을 높이고, 결합도를 낮추면서 유지보수성을 개선하는 것 이다. 이때 책임(변경의 이유)의 범위를 잘 정할수 있는 능력을 기르는 것이 중요하다. OCP(개방 폐쇄)OCP는 소프트웨어가 확장에는 열려있고, 변경에는 닫혀 있어야 한다는 원칙이다. 쉽게 말해서, 새로운 기능이나 요소를 추가할 때 기존의 코드 변경 없이 추가가 가능해야 한다. Q. OCP는 어떻게 구현할까?인터페이스를 구현한 새로운 클래스를 만들어서 새로운 기능을 구현하거나 추가하는 다형성을 활용해서 구현한다. 조금더 자세히 설명하자면, 구현체가 아닌 인터페이스를 의존하도록 하고, 단순히 구현체를 변경하는 방식으로 기능의 변경이 가능하도록 설계하는 것이다. LSP(리스코프 치환)LSP는 프로그램의 객체는 프로그램을 깨트리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다는 원칙이다. 쉽게 말해서 상속 관계에서 자식 클래스의 객체가 부모 클래스의 객체를 완전히 대체해도 정상적으로 동작해야 한다는 의미다. ISP(인터페이스 분리)ISP는 클라이언트는 자신이 사용하지 않는 인터페이스(메서드)에 의존하면 안된다는 원칙이다. 쉽게 말해서, 인터페이스를 명확한 기준을 가지고 더 작은 인터페이스로 분리하자는 원칙이다. Q. 사용하지 않는 인터페이스에 의존하지 말자는 것이 무슨 의미인가?인터페이스가 너무 광범위하면 인터페이스를 구현하는 클래스들이 사용하지도 않을 메서드를 오버라이딩 해야하는 상황이 발생한다. 이를 방지하기 위해서, 명확한 기준을 가지고 인터페이스를 더 작게 분리하자는 것이 ISP 원칙이다. 불필요한 메서드 오버라이딩 외에도, 변경으로 인한 파급 효과를 줄이기 위해서 ISP를 적용할 수 있다.쉽게 말해서, 특정 클라이언트를 위한 인터페이스(좁은 범위의 책임을 가지는 인터페이스) 여러개가 범용적인 인터페이스 하나보다 낫다는 것이다. DIP(의존 관계 역전)DIP는 구체화에 의존하면 안되고, 추상화에 의존해야 한다는 원칙이다. 더 자세히 말하자면 고수준 모듈과 저수준 모듈 모두 추상화에 의존해야 한다는 뜻이다. 쉽게 말해서, 구현 클래스에 의존하지 말고 인터페이스에 의존하라는 뜻이다. Q. 구체적인 요소의 의존을 피하는 이유는?구체적이라는 것은 변동 가능성이 높다는 것이다. 저수준 모듈의 변경 사항이 있을 때 마다 해당 모듈을 사용하는 모듈도 변경이 필요할 가능성이 높아진다. 반면에, 추상화에 의존하게 되면 저수준 모듈이 변경되어도, 고수준의 모듈에는 영향이 가지 않는다(의존 관계의 역전). DIP는 DI(의존성 주입)과 IoC(제어의 역전)이라는 개념과 자주 다루어진다. IoC(제어의 역전)IoC는 프로그래머가 작성한 코드가 프레임워크의 제어를 받게 되는 패턴을 이야기 한다. 전통적인 프로그램에서의 흐름은 프로그래머가 작성한 프로그램이 라이브러리의 코드를 호출해 이용한다. 하지만 제어의 역전이 적용된 구조에서는 프레임워크의 코드가 프로그래머가 작성한 코드를 호출한다.DI(의존성 주입)DI는 클라이언트의 생성에 대한 의존성을 클라이언트의 행위로부터 분리하는 것이다. 쉽게 말해서, 필요한 의존성을 외부로 주입을 받는 것이라고 생각하면 된다. 의존성이라는 것은 동작하기 위해 필요한 클래스 또는 객체이다. Q. 그러면 주입(의존 관계 연결)은 누가 해주는 것인가?주입 받는 쪽이나 주입하는 의존성이 아닌 제 3자가 해준다. 이를 보통 IoC 컨테이너, DI 컨테이너, 등의 표현을 사용한다.스프링을 예시로 들자면, ApplicationContext가 이를 해준다.  

백엔드ReadableCode워밍업클럽2기Day4

워밍업 클럽 2기(클린코드 & 테스트) 2번째 미션(DAY 4)

SOLDS - Single Responsibility Principle (SRP): 클래스는 하나의 책임만 가져야 하며, 변경이 필요할 때 그 책임 하나만 변경되어야 한다는 원칙이며, 해당 원칙을 고수 했을 때 클래스가 더 간단하고 유지보수가 용이해진다.O - Open/Closed Principle (OCP): 확장에 대해서는 열려 있어야 하지만, 수정에 대해서는 닫혀 있어야 한다는 원칙으로 기존 코드를 수정하지 않고도 새로운 기능을 추가할 수 있어야 한다.L - Liskov Substitution Principle (LSP): 자식 클래스는 부모 클래스의 기능을 대체할 수 있어야 한다는 원칙으로 자식 클래스가 부모 클래스를 대체해도 프로그램의 동작에는 문제가 없어야 한다.I - Interface Segregation Principle (ISP): 클라이언트는 자신이 사용하지 않는 인터페이스에 의존하지 않아야 한다는 원칙으로 하나의 인터페이스 보단 여러개의 구체적인 인터페이스로 나눠 사용하는게 더 바람직 하다.D - Dependency Inversion Principle (DIP): 고수준 모듈은 저수준 모듈에 의존해서는 안 되며, 둘 다 추상화에 의존해야 한다는 원칙으로 추상은 구현체에 의존해서는 안 되고, 구현체가 추상에 의존해야 한다.리펙터링public boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } else { if (order.getTotalPrice() > 0) { if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } else { return true; } } else if (!(order.getTotalPrice() > 0)) { log.info("올바르지 않은 총 가격입니다."); return false; } } return true; }해당 코드를 리펙터링 해보자.public class OrderValidator { private static final Logger log = LoggerFactory.getLogger(OrderValidator.class); public boolean validate(Order order) { return hasItems(order) && hasValidTotalPrice(order) && hasCustomerInfo(order); } private boolean hasItems(Order order) { if (order.getItems().isEmpty()) { log.info("주문 항목이 없습니다."); return false; } return true; } private boolean hasValidTotalPrice(Order order) { if (order.getTotalPrice() <= 0) { log.info("올바르지 않은 총 가격입니다."); return false; } return true; } private boolean hasCustomerInfo(Order order) { if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } return true; } }

허수빈

[인프런 워밍업 클럽 2기 클린코드 & 테스트 코드] Day4 과제

해당 글은 [인프런 워밍업 클럽 2기 클린 코드 & 테스트 코드]에 참가하여 박우빈님의 <Readable Code: 읽기 좋은 코드를 작성하는 사고법> 강의를 듣고 작성한 글입니다. 1. 코드 리팩토링/* * 주문 검증 메서드 * 1. 주문 항목이 0 이상이어야 한다. * 2. 총 금액이 0 이상이어야 한다. * 3. 주문을 하는 사용자 정보가 있어야 한다. */ public boolean validateOrder(Order order) { return hasItems(order) && hasCustomerInfo(order) && isTotalPriceInvalid(order); } private static boolean hasItems(Order order) { if (order.getItems().size() > 0) { return true; } log.info("주문 항목이 없습니다."); return false; } private static boolean isTotalPriceInvalid(Order order) { if (order.getTotalPrice() > 0) { return true; } log.info("올바르지 않은 총 가격입니다."); return false; } private static boolean hasCustomerInfo(Order order) { if (order.hasCustomerInfo()) { return true; } log.info("사용자 정보가 없습니다."); return false; } 2. SOLID를 자기만의 언어로 정리하기SRP : Signle Responsibility Principle단일 책임 원칙하나의 클래스는 하나의 책임만 가진다.하나의 일 & 하나의 주제만 가져야 한다!OCP : Open - Closed Principle개방 폐쇄 원칙확장에 열려 있고 수정에 닫혀 있다.기존 코드를 변경하지 않고 새로운 기능을 추가할 수 있다.LSP : Liskov Substitution Principle리스코프 치환 원칙자식 클래스는 부모 클래스를 대체할 수 있어야 한다.부모 클래스의 인스턴스를 자식 클래스의 인스턴스로 변경했을 때, 프로그램이 잘 작동해야 한다.자식이 부모의 기능을 잘 물려 받아야 한다. -> 자식은 부모의 의지를 잘 담고 있어야 한다.ISP : Interface Segregation Principle인터페이스 분리 원칙사용하지 않는 기능을 의존하지 않도록 인터페이스를 여러 개로 분리한다. -> 필요한 기능만 구현하게 한다.인터페이스를 잘게 쪼개자!DIP : Dependency Inversion Principle의존 관계 역전 원칙고수준 모듈(추상화 레벨 높음)이 저수준 모듈(추상화 레벨 낮음)에 의존하면 안된다. 추상화에 의존해야 한다. -> 둘다 인터페이스에 의존해야 한다.고수준 모듈이 저수준 모듈에 직접적으로 의존하지 않고 인터페이스만 의존시켜 구현체를 쉽게 갈아끼울 수 있도록 한다. 전부 결합도를 낮추고 응집도를 높인다!

백엔드인프런워밍업클럽

jinjanic91

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

CS 1주차 미션[운영체제]질문 1. 아래 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다. 이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다. 이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요?while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 }답변인터럽트 방식을 이용합니다.인터럽트 방식이란?CPU가 입출력 명령을 내리고 다른 작업을 진행하며, 입출력이 발생하면 입출력 관리자가 CPU에게 신호를 보내주고, CPU는 해당 신호를 받아 ISR (인터럽트 서비스 루틴)을 실행하여 작업을 완료합니다. 질문 2. 프로그램과 프로세스가 어떻게 다른가요?답변프로그램하드디스크와 같은 저장장치(HDD, SSD)에 저장된 명령문의 집합체.애플리케이션 또는 앱이라고도 불립니다.윈도우 운영체제에서는 .exe 확장자를 가지고 있습니다.컴퓨터 관점에서는 저장장치만 사용하는 수동적 존재프로세스실행 중인 프로그램입니다.하드디스크에 저장된 프로그램이 메모리에 올라갔을 때 실행 중인 프로그램 즉, 프로세스가 됩니다.컴퓨터 관점에서 메모리와 CPU를 사용하며, 필요에 따라 입력과 출력도 하는 능동적 존재프로세스의 구성 요소는 다음과 같습니다code자신을 실행하는 코드가 저장되어 있음data전역 변수와 스태틱 변수가 저장되어 있음heap프로그래머가 런타임 시 동적으로 할당할 수 있는 메모리 공간stack지역변수와 함수 호출 시 필요한 매개변수와 돌아갈 주소가 저장됨 질문 3. 멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?답변멀티 프로그래밍메모리에 여러 프로세스가 올라온 것 (메모리 관점)멀티 프로세싱CPU가 시분할 처리로 여러 개의 프로세스를 처리하는 것 (CPU 관점)단, 오늘 날의 OS에서는 멀티 프로그래밍과 멀티 프로세싱이 공존합니다. 질문 4. 운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?답변프로세스가 만들어지면 운영체제는 PCB (Process Control Block)을 만들어 저장합니다.운영체제는 PCB를 이용하여 프로세스를 관리하며, CPU가 프로세스 상태, 프로그램 카운터 등 PCB 내 정보들을 이용하여 프로세스를 처리할 수 있도록 합니다.여러 프로세스가 있는 경우 PCB 또한 여러 개 만들어지게 되는데, 이 PCB들은 연결 리스트 구조로 저장이 됩니다.프로세스가 종료되면 운영체제는 이 연결리스트에서 종료된 프로세스의 PCB를 제거합니다. 질문 5. 컨텍스트 스위칭이란 뭔가요?답변프로세스를 실행하는 중에 다른 프로세스를 실행하기 위해 실행중인 프로세스의 상태를 저장하고, 다른 프로세스의 상태값으로 교체하는 작업을 컨텍스트 스위칭이라고 합니다. PCB에 상태를 저장하기 때문에 컨텍스트 스위칭이 발생하면 PCB 내 프로세스 상태, 프로그램 카운터 및 레지스터 정보 등의 값이 변경됩니다. [ 자료구조와 알고리즘 ]질문 1. 여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다. 이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요.답변자료구조를 선택하기 전에 좀 더 조건(요구사항)을 다듬어야 할 것 같습니다.다음은 임의로 정한 조건입니다.교실에 최대 40명의 학생까지 존재할 수 있다.학생의 정보는 자주 변경되지 않는다. (1년 주기로 변동) 위 조건에서는 해시 테이블을 이용하여 정보를 저장할 것 같습니다.선택 이유는 다음과 같습니다.성능 상 이점을 얻을 수 있습니다.key만 알면 value를 바로 구할 수 있기 때문에 정보 열람 시 O(1)의 성능을 보입니다.정보가 자주 변경되지는 않겠지만, 변경 발생 시(추가, 변경, 삭제)에도 O(1)의 성능을 보입니다.각각의 학생은 고유한 데이터이기 때문에 중복되는 데이터가 없어 key-value 형태로 관리하기에 유리합니다.   질문 2. 여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요.답변 주문이 들어온 순서대로 처리되어야 하기 때문에, FIFO(First-in-First-out)의 특징을 가진 큐(Queue) 자료구조를 선택하겠습니다.      

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

세뇨르

워밍업 클럽 2기(클린코드, 테스트코드) 과제 (Day 4)

Readable Code: 읽기 좋은 코드를 작성하는 사고법(링크)코드 리팩토링기존 코드public boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } else { if (order.getTotalPrice() > 0) { if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } else { return true; } } else if (!(order.getTotalPrice() > 0)) { log.info("올바르지 않은 총 가격입니다."); return false; } } return true; }리팩토링 코드public boolean validateOrder(Order order) { if (order == null) { log.info("주문 정보가 없습니다."); return false; } if (order.hasNoItems()) { log.info("주문 항목이 없습니다."); return false; } if (order.isInvalidTotalPrice()) { log.info("올바르지 않은 총 가격입니다."); return false; } if (order.hasNoCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } return true; }public class Order { private List<Item> items; private double totalPrice; private CustomrInfo customerInfo; public boolean hasNoItems() { return items == null || items.isEmpty(); } public boolean isInvalidTotalPrice() { return totalPrice <= 0; } public boolean hasNoCustomerInfo() { return customerInfo == null; } }SOLID 정리SOLIDSRPSingle Responsibility Principle (단일 책임 원칙)하나의 클래스는 단 한 가지의 변경 이유만을 가져야 한다.객체가 가진 공개 메서드, 필드, 상수 등은 해당 객체의 단일 책임에 의해서만 변경 되어야 함.관심사의 분리높은 응집도, 낮은 결합도OCPOpen-Closed Principle (개방-폐쇄 원칙)확장에는 열려 있고, 수정에는 닫혀 있어야 한다.기존 코드의 변경 없이, 시스템의 기능을 확장할 수 있어야 한다.추상화와 다형성을 활용해서 OCP를 지킬 수 있다.LSPLiskov Substitution Principle (리스코프 치환 원칙)상속 구조에서, 부모 클래스의 인스턴스를 자식 클래스의 인스턴스로 치환할 수 있어야 한다.자식 클래스는 부모 클래스의 책임을 준수하며, 부모 클래스의 행동을 변경하지 않아야 한다.LSP를 위반하면, 상속 클래스를 사용할 때 오동작, 예상 밖의 예외가 발생하거나, 이를 방지하기 위한 불필요한 타입 체크가 동반될 수 있다.ISPInterface Segregation Principle (인터페이스 분리 원칙)클라이언트는 자신이 사용하지 않는 인터페이스에 의존하면 안 된다.인터페이스를 잘게 쪼개야 함ISP를 위반하면, 불필요한 의존성으로 인해 결합도가 높아지고, 특정 기능의 변경이 여러 클래스에 영향을 미칠 수 있다.DIPDependency Inversion Principle (의존성 역전 원칙)상위 수준의 모듈은 하위 수준의 모듈에 의존해서는 안 된다. 둘 모두 추상화에 의존해야 한다.의존성의 순방향 : 고수준 모듈이 저수준 모듈을 참조하는 것 의존성의 역방향 : 고수준, 저수준 모듈이 모두 추상화에 의존하는 것저수준 모듈이 변경되어도, 고수준 모듈에는 영향이 가지 않는다.

백엔드클린코드SOLID리팩토링

미션 Day4

미션 Day4 리팩토링하기 public boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } else { if (order.getTotalPrice() > 0) { if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } else { return true; } } else if (!(order.getTotalPrice() > 0)) { log.info("올바르지 않은 총 가격입니다."); return false; } } return true; }public boolean validateOrder(Order order) { if (isEmptyOrder(order)) { log.info("주문 항목이 없습니다."); return false; } if (hasNoCustomerInfo(order)) { log.info("사용자 정보가 없습니다."); return false; } if (isInValidTotalPrice(order)) { log.info("올바르지 않은 총 가격입니다."); return false; } return true; } private boolean isInValidTotalPrice(Order order) { return !(order.getTotalPrice() > 0); } private boolean hasNoCustomerInfo(Order order) { return !order.hasCustomerInfo(); } private boolean isEmptyOrder(Order order) { return order.getItems().size() == 0; } SOLID에 대해 나의 언어로 정의하기 SRP : 하나의 클래스는 하나의 책임만을 가져야 한다. OCP : 기능 추가에는 열려있고, 수정에는 닫혀있어야 한다. LSP : 상속관계에서 자식클래스는 부모클래스의 기능을 대신할수있다. ISP : 인터페이스는 필요한 기능만 가지게 만들어야한다. DIP : 추상클래스에 의존하도록 만들어 교체가 쉽게 이루어질수있게 한다.

wisehero

[워밍업 클럽 2기 BE 클린코드 & 테스트코드] BE 2기

 첫 번째 미션 : 아래 코드를 읽기 좋은 코드로 변경하기아래의 코드는 물론 기능 구현상에서 오작동을 일으키는 코드는 아니겠지만 이번 섹션에서 배운 내용을 토대로 읽는 사람으로하여금 과부하까진 아니더라도 부하를 겪을 수 있습니다. 아래의 코드는 그럼 어떤 문제를 가지고 있을까요?public boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } else { if (order.getTotalPrice() > 0) { if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } else { return true; } } else if (!(order.getTotalPrice() > 0)) { log.info("올바르지 않은 총 가격입니다."); return false; } } return true; }첫 번째는 캡슐화가 잘 지켜지지 않고 있습니다. 객체의 값을 지속적으로 getter 메서드를 가져오면서 확인하고 있습니다.이는 TDA(Tell, Don't Ask) 원칙을 지켜지지 않고 있고 객체가 그 자체의 역할을 하게끔 만들지 않았습니다. 두 번째는 읽는 사람으로 하여금 머리를 많이 쓰게 하고 있습니다. 머리를 많이 쓰게 한다는 것은 다음과 같은 이유에서 입니다.모든 조건문이 한 호흡에 이어져 있다.공백으로 각 작업간의 STEP을 구분하지 않았다.Depth가 깊다.부정 연산자 사용으로 인해서 조건을 한 번 더 이해해야 한다.이를 리팩토링 한다면 어떻게 할 수 있을까요? public boolean validateOrder(Order order) { // 주문 항목 확인 if (order.hasNoItems()) { log.info("주문 항목이 없습니다."); return false; } // 총 가격 확인 if (order.isTotalPriceInvalid()) { log.info("올바르지 않은 총 가격입니다."); return false; } // 사용자 정보 확인 if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } return true; } 리팩토링한 코드는 위와 같습니다. Order 객체 스스로 판단할 수 있는 메서드로 조건문을 처리하여 TDA 원칙을 따랐습니다.공백을 둚으로서 각 작업의 STEP을 구분했습니다.3-Depth 까지 타고 들어가야하는 코드를 전부 1-Depth 이내에 처리했습니다.부정 연산자를 사용하기보단 더 의미있는 이름의 메소드를 만들어 직관적으로 조건문을 판단할 수 있도록 했습니다.과제를 수행하면서 느꼈던 것은 좋은 코드란 좋은 글을 작성하는 것과 마찬가지라는 느낌이었습니다. 좋은 글을 쓰는 첫 출발점은 단문 쓰기를 통해 호흡을 짧게하여 읽는 사람으로 하여금 부하를 느끼지 않게 하는 것이 중요했습니다. 문장의 마침표가 문장의 시작으로부터 너무 멀리 있게되면 이는 읽는 사람을 배려하지 않은 글쓰기이기 때문입니다. 클린 코드는 나만의 만족을 위한 것이 아니라 이타적인 마음을 다시 한번 갖게 되는 좋은 원칙인 것 같습니다. 두 번째 미션 : SOLID를 자신의 언어로 정리하기 SRP : Single Responsibility Principle단일 책임 원칙은 클래스 혹은 메서드, 함수는 한 가지 책임만 가져야 한다는 것입니다. 자동차를 예로 들어볼까요? 자동차 클래스를 작성한다면, 우리는 이 원칙을 지키기 위해 엔진, 연료, 네비게이션, 에어컨 조절, 음악 재생과 관련된 변수와 메서드를 전부 넣어놓으면 안됩니다. 자동차는 그저 여러 가지 요소의 조립이 끝난 채로 존재해야합니다. 그래서 우리는 엔진, 연료 시스템, 네비게이션, 오디오 클래스를 별도로 분리하고 그에 맞는 기능들을 작성해야 합니다. OCP - Open/Closed PrincipleOCP는 소프트웨어는 구성에 있어서 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다는 원칙입니다. 솔직히 많은 사람들이 이 이야기를 처음에 들었을 때 의구심을 품습니다. '어떻게 확장을 하는데 수정을 안할 수가 있어?' 라고요. 하지만 적어도 소프트웨어 세상에서는 가능합니다. 앞서 말했던 SRP를 지킨다면 말이죠. 만약 자동차 클래스에 오디오 관련 기능들을 전부 다 작성했다면 어떻게 되었을까요? 우리의 자동차에는 보스의 것도, 뱅앤올룹슨의 것도, 하만 카돈의 것도 들어갈 수 있습니다. 하지만 자동차 클래스에 오디오 관련 코드를 전부 작성했다면 자동차 클래스는 늘어나는 오디오 업체의 코드를 계속해서 생산해내야 합니다. 그러나 이전에 별도의 객체로 만들고 추상화까지 더했다면? 확장에 있어서 기존 코드를 수정하는 일은 없을 것이고 우리는 단순히 '추가'만 하면 될 것입니다. LSP - Liskov Substitution Principle리스코프 치환 원칙은 자식이 언제든지 부모를 대체할 수 있어야 한다는 원칙입니다. 다시 차량의 오디오 기능을 생각해봅시다. 오디오 인터페이스가 있고 오디오 인터페이스에 명세되어 있는 기능은 볼륨 켜키, 볼륨 끄기 입니다. 하지만 어느 한 회사의 특정 제품 클래스는 볼륨 켜키 기능이나 볼륨 끄기 기능이 기대한대로 동작하지 않는다면 어떻게 될까요? 예를 들어서 볼륨 끄기를 1씩 끄는게 아니라 한번에 0으로 만들어버린다거나 말이죠. 이렇게 되면 프로그램이 균일하게 동작하지 않을 것이고 서로가 서로를 완벽하게 대체할 수 없을 것입니다. 따라서 인터페이스를 준수하는 것이 LSP가 전달하고자 하는 메세지입니다. ISP - Interface Segregation PrincipleISP는 클라이언트가 사용하지 않는 인터페이스에 의존하지 않도록 하는 것입니다. 모든 자동차들은 구매할 때 고객이 원하는 옵션을 가지고 있습니다. 하지만 내 자동차에 내가 고르지 않은 옵션을 동작하는 버튼이 자리만 차지하고 있다면 어떻게 될까요? 이는 운전자에게 혼동을 줄 수 있고 불필요한 공간 낭비를 발생시킬 수 있습니다. 코드에서는 어떤가요? 특정 클래스가 구현하지 않아도 되는 부분을 구현해야할 것처럼 개발자에게 혼동을 줄 수 있고 이는 장애를 유발하거나 불필요한 용량 차지로 이어질 수 있습니다. 인터페이스는 가능한 범용적이 아닌 세부적으로 분리해야한다는 것이 ISP가 전하고자 하는 메세지입니다. DIP - Dependency Inversion PrincipleDIP는 고수준 모듈은 저수준 모듈에 의존해서는 안되고, 고수준 모듈과 저수준 모듈 모두 추상화에 의존해야 한다는 원칙입니다.이 역시 말이 어렵습니다. 저도 처음에 OCP 다음으로 어려웠던 것 같습니다. 하지만 위에서 자동차 예시로 다 말씀을 드렸습니다.자동차 클래스는 여러 인터페이스의 조합으로 이뤄져야 한다고 했습니다. 자동차 클래스는 가솔링 엔진, 전기 엔진과 같은 구체 클래스에 의존해서는 안됩니다. Engine 인터페이스가 있고 이를 구현한 가솔린 엔진과 전기 엔진이 있어야 합니다. 오디오 역시 오디오라는 인터페이스만 있을 뿐, 이를 구현한 각 제조사의 오디오가 있을 뿐이죠. 자동차 클래스는 따라서 어떤 특정 엔진이나 특정 오디오의 정보는 알 수 없습니다. 그저 인터페이스만 갖고 있을 뿐입니다.   

백엔드워밍업클럽백엔드

[클린 코드 & 테스트 코드 가이드 로드맵, 미션 Day4] 코드 리팩토링 및 SOLID

[미션]1. 아래 코드와 설명을 보고, [섹션 3. 논리, 사고의 흐름]에서 이야기하는 내용을 중심으로 읽기 좋은 코드로 리팩토링해 봅시다.#TO-BEpublic boolean validate(Order order) { if (Objects.isNull(order)){ return false; } if (order.isItemsEmpty()) { log.info("주문 항목이 없습니다."); return false; } if (order.notValidateTotalPrice()) { log.info("올바르지 않은 총 가격입니다."); return false; } if (order.notHasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } return true; }메서드 시그니처메서드명 변경 (validateOrder -> validate)파라미터 타입이 있어서 Order 삭제 구현부파라미터 검증 추가order이 null인 경우에도 유효하지 않다고 응답추상화 레벨에 맞춰 order == null이 아닌 Objects.isNull(order) 적용Early Return 적용실제 검증항목은 아이템 개수, 아이템 가격합계, 고객 정보 유무 3가지이고, 각각 독립적이므로 불필요한 else, else if 구문 삭제부정연산자(!) 대신 메서드명에 명시반환타입수정 없음 #AS-ISpublic boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } else { if (order.getTotalPrice() > 0) { if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } else { return true; } } else if (!(order.getTotalPrice() > 0)) { log.info("올바르지 않은 총 가격입니다."); return false; } } return true; }2. SOLID에 대하여 자기만의 언어로 정리해 봅시다.SRP공통적인 것들로 묶어주기같은 기능 : 메서드같은 도메인 : 클래스OCP동적으로 활용할 수 있게 설계LSP부모의 기능을 자식들이 공통으로 쓸 수 없다면 분리하기ISP인터페이스는 최소 단위별로 생성DIP추상에 의존 

백엔드

도호

[인프런워밍업클럽2기] DAY 4 미션

코드 리팩토링요구사항 사용자가 생성한 '주문'이 유효한지 확인해야한다.주문 항목은 1개 이상이어야한다.주문 전체 가격은 1원 이상이어야 한다.주문한 사용자 정보는 필수 정보이다.Order는 주문 객체이고, 필요하다면 Order에 추가 메서드를 만들 수 있다.필요하다면 메서드를 추출할 수 있다.public boolean validate(Order order) { if (order.isEmpty()) { log.info("주문 항목이 없습니다."); return false; } if (order.isInvalidPrice()) { log.info("올바르지 않은 총 가격입니다."); return false; } if (order.isInvalidUser()) { log.info("사용자 정보가 없습니다."); return false; } return true; }SOLIDSingle Responsibility Principle (단일 책임 원칙)하나의 모듈은 하나에 대한 책임만을 가져야한다.클래스 내부 private 메서드가 많거나 단위테스트가 애매한 경우에는 책임을 분리하는 것을 고려할 수 있다. Open-Close Principle (개방-폐쇄 원칙)확장에 열려있고 수정엔 닫혀있어야한다.새로운 기능을 추가할 때 기존 기능에 영향 없이 추가할 수 있어야한다. 즉 서로간의 의존 관계를 최소화해야한다.이 원칙은 B기능을 추가하였는데 A기능 테스트가 깨짐으로써도 확인할 수 있다.Liskov Substitution Principle (리스코프 치환 원칙)부모 클래스의 역할을 자식이 대체할 수 있어야한다.List 인터페이스의 구현체를 LinkedList에서 ArrayList로 변경하더라도 결과가 동일해야한다.Interface Segregation Principle (인터페이스 분리 원칙)하나의 인터페이스가 많은 책임을 가지고 있다면 인터페이스를 분리해야한다.Dependency Inversion Principle (의존관계 역전 원칙)구현체를 직접 사용하는 것 보다 추상화 된 것을 바라보는 것이 확장에 용이하다.List를 사용하는 것이 ArrayList를 사용하는 것 보다 확장에 유리하다.

백엔드인프런워밍업클럽2기

채널톡 아이콘