오전
코어 자바스크립트 챕터 1 복습
코어 자바스크립트 챕터 2 공부
운영체제 복습
오후
자료구조, 알고리즘 공부 1문제 풀기
node js 챕터2 최대한 많이 진도 나가기 (최소 2-10까지 하기)
밤
네트워크 공부
참고 자료:
https://reese-dev.netlify.app/javascript/execution-context/
코어자바스크립트 책
https://poiemaweb.com/js-execution-context
https://meetup.toast.com/posts/86
실행 컨텍스트(Execution context)는 짧게 ‘컨텍스트’라고도 하며 스코프, 호이스팅, this, 함수, 클로저 등의 동작 원리를 담고 있는 자바스크립트의 핵심 원리이다. 실행 컨텍스트를 정확하게 이해하면 스스로 작성한 코드 뿐만 아니라 다른 사람이 작성한 코드를 이해하고 활용하거나 디버깅하는 일이 수월해질 것이다.
실행 컨텍스트 execution context: 실행한 코드에 제공할 환경 정보를 모아놓은 객체
1. 동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성
2. 콜스택에 쌓음
3. 가장 위에 쌓여 있는 컨텍스트와 관련 있는 코드를 실행
-> 전체 코드의 환경과 순서를 보장함
JS는 어떤 실행 컨텍스트가 활성화되는 시점에 선언된 변수를 위로 끌어올리고 (호이스팅 Hoising), 외부 환경 정보를 구성하고, this 값을 설정하는 등의 동작을 수행.
-> 자스만의 특이한 부분이 있음
실행 컨텍스트는 실행되는 코드의 종류에 따라 세 가지로 나눌 수 있다.
전역 실행 컨텍스트 (Global Execution Context): 가장 기본적이고 베이스가 되는 실행 컨텍스트이다. 어떠한 함수에도 속해있지 않은 코드가 전역 실행 컨텍스트에 포함된다. 전역 실행 컨텍스트는 전역 객체(브라우저의 경우 window 객체)를 생성하고 this를 전역 객체에 할당한다. 프로그램 하나당 하나의 전역 실행 컨텍스트가 있다. = 전역 공간 (자동 생성)함수 실행 컨텍스트 (Functional Execution Context): 함수가 실행될 때 마다 해당 함수를 실행하기 위한 새로운 실행 컨텍스트가 생성된다. 각각의 함수는 자기 자신만의 실행 컨텍스트를 가지는 셈이다. 실행 컨텍스트는 함수가 실행(호출)될때만 생성된다.eval 함수 실행 컨텍스트 (Eval Function Execution Context): eval함수 내부의 코드가 실행될 때에도 이들만의 실행 컨텍스트가 생성된다. -> 악마 취급 받는다함 (이유 모름, 반박 의견도 많음)
아무튼 주로 2번 따라서 생김 (함수!!)
실행컨텍스트는 자스에서 중요함!
클로저를 사용하는 대부분 언어에서 비슷비슷하니까 알아두는 것이 좋다.
// * (1) 전역 콘텍스트 콜스택
var a = 1;
// *(3) outer 함수 콜스택 -> 함수 내부 실행
// *(7) outer 함수 마저 실행
const outer = () => {
const inner = () => { // *(5)
console.log(a); // undefined
var a = 3;
// *(6) a 변수에 3 할당하고 함수 끝! 콜스택에서 inner함수 빠짐 -> outer 함수 실행
};
inner(); // *(4) inner 함수 콜스택 쌓이고 실행
console.log(a); // 1 *(8) a = 1 출력하고 outer 함수 끝!
};
outer(); // *(2) outer 함수 콜스택 쌓이고 실행
console.log(a); // 1 // *(9) a = 1 출력하고 콜스택 텅 빙
*(5)일 때 콜스택 상태: 전역 콘텍스트 -> outer -> inner
*(8)일 때 콜스택 상태: 전역 콘텍스트 -> outer
-> outer 함수 실행

근데.. 변수 선언을 var 대신 let이라 하면 오류 뜸

왜인지는 잘 모르겠음.
(var, let 차이에서 나온 것 같은데.. var가 전역변수, 스코프 밖으로 나간다는 특징이 있다고 봤는데 그것때문이라고 추측 중) 글고 var a = 3 선언한건 어디갔나 했는데 inner 함수 끝나면서 스코프 밖으로 못나가서인듯

실행 컨텍스트는 활성화되는 시점에 세 가지를 수집한다.
VariableEnvironment: 선언 시점의 LexicalEnvironment의 스냅샷
LexicalEnvironment: VariableEnvironment과 처음엔 같지만 변경사항이 실시간으로 변경
=> 공통점) 내부는 environmentRecord와 outer-EnvironmentReference로 구성돼 있음
ThisBinding: this 식별자가 바라봐야 할 대상 객체 (-> 실행 컨텍스트 활성화 당시에 this가 지정되지 않은 경우 this에는 전역 객체가 저장된다. 함수를 호출하는 방법에 따라 this에 저장되는 대상이 다르다.)
내용은 LexicalEnvironment(이하 Lexical, 사전적인)과 같지만 최초 실행 시 스냅샷 유지
실행컨텍스트 생성할 때 VariableEnvironment에 정보 담은 다음 -> Lexical을 만들고 주로 활용
초기화 과정에는 사실상 완전 동일하고 코드 진행에 따라 Lexical이랑 달라짐
렉시컬 환경은 식별자(identifier)와 특정 변수(variable)의 맵핑을 지속적으로 트래킹하는 엔진의 내부 구조이다. 간단히 얘기하면 식별자와 변수의 맵핑이 이루어지는 공간이다.
컨텍스트 내부 전체를 처음부터 끝까지 쭉 훑어가며 순서대로 수집한다.
전역 실행 컨텍스트
자바스크립트 구동 환경이 별도로 제공하는 객체 (= 전역 객체 global object) 활용
브라우저 window, node.js의 global 객체 등이 있다. 이들은 자바스크립트 내장 객체 (native object)가 아닌 호스트 객체 (host object)로 분류
렉시컬 환경은 함수, if문이나 for문과 같은 블록문, 그리고 catch절이 평가될 때 생성된다. 여기서 함수에 의해 생성되는 렉시컬 환경은 함수가 호출될 때 생성되는 것이 아니라, 그에 앞서 함수 선언 코드가 평가될 때 생성된다는 점을 기억하자. (클로저 개념과 연결된다.)
이를 통해 코드가 실행되기 전인데도 js엔진은 이미 해당 환경에 속한 코드 변수명들을 알고 있음!
그러면 엔진 실제 동작 방식 대신 자바스크립트 엔진은 식별자들을 최상단으로 끌어올려 놓은 다음 실제 코드를 실행한다 생각해도 문제될게 없다. -> 호이스팅 (Hoisting) 개념 등장!
렉시컬 환경의 구성
렉시컬 환경은 2개의 컴포넌트로 이루어져 있다.
Environment Record (Hoisting)
Outer Environment Reference (Scope Chain)
변수 정보를 수집하는 과정을 더 이해하기 쉬운 방법으로 대체한 추상적 개념임.
environmentRecord는 현재 실행될 컨텍스트 대상 코드 내에 어떤 식별자들이 있는지에만 관심이 있고 각 식별자에 무엇이 할당될지에는 관심 없음
-> 변수 호이스팅할 때 변수명만 끌어올리고, 할당 과정은 원래자리에 냅둠
const aboutHoisting = (x) => {
console.log(x);
var x; // 2
console.log(x);
var x = 2; // 3
console.log(x);
};
aboutHoisting(1); // 1
보통 사람들: 함수에 1 넣은걸 호출했으니까
1출력하고 그런 다음 x에 아무것도 할당 안했으니undefined나오고 다시 x에 2 할당했으니2가 출력되겠지? (매개변수를 변수 선언/할당과 같다고 생각함)
근데 실제로는 안그럼

const aboutHoisting = (x) => {
var x; // 1, ~ 변수 x 선언 저장할 공간 확보 & 해당 공간 주솟값을 변수 x에 연결
var x; // 2 ~ 다시 변수 선언 but 이미 선언된 변수 있으니 무시
var x; // 3 ~ 다시 변수 선언 but 이미 선언된 변수 있으니 무시
var x = 1; // 1 할당 부분
console.log(x);
console.log(x);
var x = 2; // 3 할당 부분
console.log(x);
};
aboutHoisting(1);
const a = () => {
console.log(b);
var b = "bbb";
console.log(b);
function b() {
return 0;
}
console.log(b);
};
a();
- 호이스팅 개념 없이 흐름대로 따라가면
undefined, "bbb", b함수 출력 될 것 같아보임
const a = () => {
var b;
var b = function b() {
return 0;
};
console.log(b); // f 출력
var b = "bbb";
console.log(b); // "bbb" 출력
console.log(b); // "bbb" 출력
};
a();

const a = () => {
var b; // 변수 b 선언
var b = function b() { // 변수 b에 함수 할당
return 0;
};
console.log(b);
var b = "bbb";
console.log(b);
console.log(b);
};
a();
참고: 자스에서 함수는 값이기도 함! (화살표함수로 나타내면 더 직관적으로 이해 가능)

함수 선언(문)방식으로 함수를 생성하면, 함수가 독립된 구문 형태로 존재
함수 선언문은 코드 블록이 실행되기도 전에 처리됩니다. 따라서 블록 내 어디서든 활용 가능
함수 표현식방식으로 함수를 생성하면, 함수가 표현식의 일부로 존재
함수 표현식은 실행 흐름이 표현식에 다다랐을 때 만들어짐
함수 표현식 관련 문서 꼭 보기 https://ko.javascript.info/function-expressions -> 함수 선언문 ,익명 함수 표현식, 기명 함수 표현식
함수 선언문
function showMessage() {
alert( '안녕하세요!' );
}
함수 표현식
let sayHi = function() {
alert( "Hello" );
};
예제 코드
console.log(sum(1, 2));
console.log(muliply(3, 4));
function sum(a, b) {
return a + b;
}
// 화살표 함수 ~ const multiple = function (a, b) {} 와 같음
const muliply = (a, b) => {
return a * b;
};
// 함수 선언문은 전체를 호이스팅
var sum = function sum(a, b) {
return a + b;
}
// 함수표현식 (변수)는 선언부만 끌어올림
const multiply;
console.log(sum(1, 2));
console.log(muliply(3, 4));
// 변수 할당부는 원래 자리에 남겨둠
const multiply = (a, b) => {
return a * b;

변수 할당부 이전에 multipy 출력시키므로 오류가 뜬다
sum 함수는 선언 전에 호출해도 문제없이 실행!!
반대로 multiply는 할당 이후 출력해야 함!
원활한 협업을 위해서라면 전역 공간에 함수를 선언하거나 동명의 함수를 중복 선언하는 경우는 없어야 함
하나 전역 공간에 동명의 함수가 여럿 존재하는 상황이라 하더라도 모든 함수가함수 표현식으로 정의돼 있다면 그나마 안전함
스코프 체인이라고 하는 것은 ES3에서는 스펙에 정식으로 존재했던 용어인데, ES6에서는 스코프 체인이라는 용어는 존재하지 않는다. 대신 ES5부터
Lexical nesting structure또는Logical nesting of Lexical Environment values등으로 표현하고 있다.
Outer Environment Reference는 스코프 체인에 상응하는 개념으로, 중첩된 스코프 내에서 변수를 검색하는 메커니즘이라고 할 수 있다. 물리적으로는 Lexical Environment를 원소로 하는 단방향 연결 리스트로 구현되어 있다.
스코프란 식별자에 대한 유효 범위다.
ES5까지 자스는 전역 공간 제외하면 오직 함수에 의해서만 스코프가 생성됐었음
(다행히 ES6부터는 블록에 의해서도 스코프 경계 생김... var로 선언한 변수에 대해서는 적용 안하고 let, const, class, strict mode에서의 함수 선언에 대해서만 수행)
ES6에서는 둘을 구분하기 위해 함수 스코프, 블록 스코프 용어 사용함

outerEnvironmentReference는 현재 호출된 함수가 선언될 당시의 LexicalEnvironment를 참조함

엔진은 가장 먼저 현재 렉시컬 환경에서 해당 변수를 찾아보고 검색에 실패하면 다음 리스트가 가리키는 상위 렉시컬 환경을 참조하여 변수를 검색하는 식으로 탐색을 이어나간다.
이러한 탐색은 해당 변수의 식별자를 찾거나 상위 렉시컬 환경의 Outer Environment Reference 참조가 null일 경우(Global Lexical Environment) 종료된다. 만약 Global Lexical Environment에서도 변수를 찾지 못할경우 정의되지 않은 변수에 접근하는 것으로 판단하여 Reference 에러를 발생시킨다.
여러 스코프에서 동일한 식별자를 선언한 경우에는 무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근 가능하게 된다.
전역 컨텍스트의 LexicalEnvironment에 담긴 변수를 전역변수라고 하고, 그 밖의 함수에 의해 생성된 실행컨텍스트 변수들은 모두 지역변수임! (=> 전역 공간에서 선언한 변수는 전역변수, 함수 내부에서 선언한 변수는 무조건 지역변수
this에는 실행 컨텍스트를 활성화하는 당시에 지정된 this가 저장됨. 함수를 호출하는 방법에 따라 그 값이 다르다~

스코프 개념을 배웠으니 클로저에 대해서도 궁금한데 책에 아예 따로 챕터로 나뉘어져 있어서 그때 다시 공부할 예정..! 그때 https://meetup.toast.com/posts/86 글 다시 읽으면 더 이해 잘 갈 것 같다!
else if (pathname === "/create_process") {
var body = "";
request.on("data", function (data) {
body = body + data;
});
request.on("end", function () {
var post = qs.parse(body);
db.query(
`
INSERT INTO topic (title, description, created, author_id)
VALUES(?, ?, NOW(), ?)`,
[post.title, post.description, 1],
function (error, result) {
if (error) {
throw error;
}
response.writeHead(302, { Location: `/?id=${result.insertId}` });
response.end();
}
);
});
}
SQL문으로 데이터를 DB에 저장!
웹페이지 응답 정상적으로 진행되었을 경우, 새롭게 넣은 Id값으로 이동 result.insertId 코드 이용함
https://github.com/mysqljs/mysql#getting-the-id-of-an-inserted-row
여기서도 확인 가능함
https://www.npmjs.com/package/mysql
connection.query('INSERT INTO posts SET ?', {title: 'test'}, function (error, results, fields) {
if (error) throw error;
console.log(results.insertId);
});

else {
db.query(`SELECT * FROM topic`, function(error, topics) {
if(error) {
throw error;
}
db.query(`SELECT * FROM topic LEFT JOIN author ON topic.author_id=author.id
WHERE topic.id=?`,[queryData.id], function(error2, topic) {
if(error2) {
throw error2;
}
console.log(topic);
var title = topic[0].title;
var description = topic[0].description;
var list = template.list(topics);
var html = template.HTML(title, list,
`<h2>${title}</h2>
${description}
<p>by ${topic[0].name}</p>
`,
` <a href="/create">create</a>
<a href="/update?id=${queryData.id}">update</a>
<form action="delete_process" method="post">
<input type="hidden" name="id" value="${queryData.id}">
<input type="submit" value="delete">
</form>`
);
response.writeHead(200);
response.end(html);
});
});
}
}
html 코드 치는거 개빢치;ㅁ
SQL 다 까뭇따...
두 개의 테이블 간에 교집합을 조회하고 한쪾 테이블에만 있는 데이터도 포함시켜서 조회
빈 곳은 NULL값으로 출력
WHERE 조건절에서 한쪽에만 있는 데이터를 포함시 킬 테이블 쪽으로 (+)를 위치 → 실무에선 잘 안사용
SELECT firstName, lastName, city, state
from Person left join Address
ON Person.personId = Address.personId;
하루 한 것 ❌ 🔺✅
내일 할 것
오전
코어 자바스크립트 챕터 1 복습 ✅
코어 자바스크립트 챕터 2 공부 ✅
운영체제 복습 ❌
오후
자료구조, 알고리즘 공부 1문제 풀기 ❌
node js 챕터2 최대한 많이 진도 나가기 (최소 2-10까지 하기) ✅
밤
네트워크 공부 ❌
월수금 알고리즘 & 자료구조 + 운영체제 + 구현
화목토 SQL + 네트워크 + 코어자스 + 구현