# 6/2 면접 스터디 ## 임태현 logical address: 프로세스마다 독립적인 주소 공간이 생기는데, 이 때 프로세스마다의 각각의 주소를 일컫는다. 메모리는 프로그램이 실행하는 도중에도 물리적 메로리 상의 주소가 변경될 수 있기 때문에 해당 데이터가 Physical Memory의 어느 위치에 존재하는지를 매핑해주는 테이블을 관리한다. 그리고 Base Register와 Limit Register, MMU라는 하드웨어 지원을 받는다. MMU = Logical Address를 Physical Address로 변환해주는 하드웨어 장치 MMU를 사용하면 프로그램이나 CPU는 Physical Address를 직접알지 못한다. MMU는 프로세스마다 시작 physical address를 가진 테이블을 가지고 있다. 그리고 각 CPU 명령은 Logical Address를 갖고 있어서 MMU를 통해 프로세스의 시작 Physical Address를 가지고 있는 Logical Address와 더해 실질적으로 접근하는 Physical Address를 알 수 있다. - Dynamic loading - 여러 프로그램을 한 메모리에 동시에 올리는 멀티 프로그래밍에서 효율성을 높이는 기법 - 프로세스가 시작될 때 모든 것을 실행하지 않고 필요한 루틴만 메모리에 적재한다. ### Virtual Memory --- <br> ## 최지수 ### 쿠키와 세션을 사용하는 이유 HTTP프로토콜은 connectionless, stateless 특성이 있기 때문이다. **connectionless** - 클라이언트가 요청을 한 후 응답을 받으면 그 연결을 끊어버리는 특징 **stateless** - 통신이 끝나면 상태를 유지하지 않는 특징 - 연결을 끊는 순간 상태 정보를 유지하지 않는다. 쿠키와 세션을 사용하게 되면 사용자에 대한 인증을 유지하게 된다. ### 쿠키 클라이언트 로컬에 저장되는 키와 값이 들어있는 작은 데이터 파일이다. 사용자가 따로 요청하지 않아도 브라우저가 Reqeuest시에 Header에 넣어서 자동으로 서버에 전송한다. 장바구니, 자동로그인 등에 사용된다. **구성 요소** - 이름 : 쿠키를 구별하는데 사용하는 이름 - 값 : 쿠키의 이름과 관련된 값 - 유효시간 : 쿠키 유지 시간 - 도메인 : 쿠키를 전송할 도메인 - 경로 : 쿠키를 전송할 요청 경로 **동작 방식** 1. 서버에서 쿠키를 생성 2. HTTP 헤더에 쿠키를 포함시켜 응답 3. 브라우저가 종료되어도 쿠키 만료 기간이 남아있으면 클라이언트에서 보관하고 있음 4. 같은 요청을 할 경우 HTTP 헤더에 쿠키를 같이 보냄 5. 서버에서 상태 정보를 변경할 필요가 있을 때는 쿠키를 업데이트하여 변경된 쿠키를 HTTP 헤더에 포함시켜 응답 ### 세션 방문자가 웹 서버에 접속해 있는 상태를 하나의 단위로 보고 그것을 세션이라고 한다. 쿠키를 기반하지만 서버에서 관리한다. 일정 시간동안 같은 브라우저로부터 들어오는 요구를 하나의 상태로 보고 그 상태를 일정하게 유지시키는 것 서버에서는 클라이언트를 구분하기 위해 세션ID를 부여하여 웹 브라우저가 서버에 접속해서 브라우저를 종료할 때까지 인증상태를 유지한다. 사용자 정보를 서버에 두기 때문에 쿠키보다 보안에 좋지만 서버 메모리를 많이 차지하게 된다. 로그인 같이 보안상 중요한 작업을 수행할 때 사용한다. 세션은 브라우저가 종료되면 만료시간에 상관없이 삭제된다. **동작 방식** 1. 서버에 접속 시 세션 ID를 발급받음 2. 클라이언트는 세션 ID에 대해 쿠키를 사용하여 저장 3. 클라이언트는 서버에 요청할 때, 쿠키의 세션 ID를 서버에 전달하여 사용 4. 서버는 세션 ID를 전달 받아 별다른 작업없이 세션 ID로 세션에 있는 클라이언트 정보를 가져옴 5. 클라이언트 정보를 가지고 서버 요청을 처리하여 응답 --- <br> ## 문예지 ### 동기 vs 비동기 카페에서 필요한 task: 주문 받기, 음료 제조 - **동기적 카페**: 주문을 받고 음료를 완성하면 다음 주문을 받는다(주문 작업이 block됨) - **비동기적 카페**: 주문을 다 받은 후 음료는 완성되는 순서대로 나간다 **동기식 처리 모델** 직렬적으로 task 수행 ![](https://i.imgur.com/SCMixKF.png) task는 순차적으로 실행되며 어떤 작업이 수행 중이면 다음 태스크는 대기(block) <br> **비동기식 처리 모델** 병렬적으로 task 수행 ![](https://i.imgur.com/Fd9hOgD.png) task가 종료되지않더라도 대기하지 않고 다음 task 수행(non-block) ex. 서버에서 데이터를 가져와서 화면에 표시하는 작업 수행 1. 서버에 데이터를 요청(task1) 2. 서버로부터 데이터가 응답될 때까지 대기하지 않고(Non-Blocking) 즉시 다음 작업(task2)을 수행 3. 서버로부터 데이터가 응답되면 이벤트가 발생하고 이벤트 핸들러가 데이터를 가지고 수행할 작업(task1)를 계속해 수행 #### callback vs Promise vs async/await > 사용하는 이유 > task1이 끝나기 전 task1의 결과를 요구하는 task2가 진행되는걸 막을 수 있음 <br> > **callback** > 맛집가서 대기 명단에 이름 적어놓고 딴 곳 구경하다가 전화오면(callback) 밥 먹으러 가는 그런 느낌.. ```javascript step1(function(value1) { step2(value1) { ... } }) ``` 단점 1. callback hell callback 바깥은 task의 순서를 보장하지 않음 :arrow_right: 순서를 보장하기 위해 callback 함수를 자꾸 중첩 :arrow_right: 복잡도 올라감 ```javascript= step1(function(value1) { step2(value1, function(value2) { step3(value2, function(value3) { step4(value3, function(value4) { step5(value4, function(value5) { // value5를 사용하는 처리 }); }); }); }); }); ``` 2. 가독성 나쁨 3. 여러 개의 비동기 로직을 한번에 처리하기 어려움 4. 예외처리가 어려움 <br> > **Promise** > "비동기에서 성공과 실패를 분리해서 메소드를 실행한다!" callback 패턴의 단점을 개선하기위해 등장 비동기적으로 실행하는 task의 상태를 가지고 있는 **객체** :arrow_right: 비동기 작업의 시점을 정확하게 표현 가능 ![](https://i.imgur.com/B4GnZvR.png) ```javascript= const promise = new Promise((resolve, reject) => { // 비동기 작업을 수행한다. if (/* 비동기 작업 수행 성공 */) { resolve('result'); } else { /* 비동기 작업 수행 실패 */ reject('failure reason'); } }); ``` 체이닝을 이용해 후속 함수 실행 가능 ```javascript= const resolvedPromise = Promise.resolve([1, 2, 3]); resolvedPromise.then(console.log); const rejectedPromise = Promise.reject(new Error('ERROR!!!')); rejectedPromise.catch(console.log); ``` > **async/await** > **promise를 반환** promise보다 가독성이 좋음 (동기코드와 유사해보임) try/catch로 에러 핸들링이 가능 어디서 에러가 났는지 정확하게 알 수 있음 ```javascript= function goWork(time1, timeStartWork) { return wakeUp(time1) .then(time2 => tackSubway(time2)) .then(time3 => takeOffSubway(time3)) .then(time4 => arriveWork(time4)) .then(arrivalTime => { if (arrivalTime > timeStartWork) { fire() } }) } async function goWork(time1, timeStartWork) { const time2 = await wakeUp(time1) const time3 = await takeSubway(time2) const time4 = await takeOffSubway(time3) const arrivalTime = await arriveWork(time4) if (arrivalTime > timeStartWork) { fire() } } ``` <br> ### JavaScrpit Engine ![](https://i.imgur.com/l0namXZ.png) - JavaScript로 된 코드를 해석하고 실행하는 인터프리터 - Nodejs는 V8엔진 사용 > 인터프리터 vs 컴파일러 > - 인터프리터: 소스 코드를 바로 실행하는 환경 또는 컴퓨터 프로그램 - 컴파일러: 소스 코드를 기계어로 번역 > Call Stack > - 딱 하나의 call stack만 가짐 - 요청이 들어올 때마다 순차적으로 호출스택에 담아서 처리 - 메소드가 실행될 때 Call Stack에 새로운 프레임이 생기고 이를 push 실행 완료되면 pop하는 방식 > Task Queue(Event Queue) > - 자바스크립트 런타임시 처리되어야할 task들을 임시 저장하는 큐 - call stack이 비었을 때 먼저 대기열에 들어온 순서대로 실행 > Heap > - 인스턴스 할당 > Event Loop > - 현재 실행 중인 테스크의 유무 + event queue에 대기 중인 테스크의 유무 반복적으로 확인 > **Promise는 Timer 보다 우선시 된다?** > - Promise 스케쥴링 1. 작업을 만나면 call stack 에 넣음 2. call stack 에서 작업을 꺼내고 처리 3. 처리중 callback 을 만나면, event queue 에 등록 4. promise 를 만나면, call stack 에 넣음 5. call stack 에서 promise 작업을 꺼내고 처리 6. 이때, then 을 만나면 MicroTask queue 에 등록 7. 모든 스크립트의 call stack 작업이 끝나면 우선적으로, MicroTask queue 를 확인하고 call stack 에 넣음 8. call stack 에서 작업을 꺼내고 처리 9. microtask queue 작업이 없다면, event queue를 확인하고 call stack에 넣음 - Event Loop는 MicroTask qeue가 비어야 event queue를 확인 - MicroTask에 쌓이는 task - Promise - Object.observer - process.nextTick - MutationObserver - 그외 Event queue에 쌓임