🗓️ day2 (230920)
변수
변수(variable)는 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름을 말한다.
const num = 29;
// 변수명(식별자) : num
// 해당 값의 위치(메모리 주소) : 0012CCGWH80
// 변수 값(저장된 값) : 29
변수명(num)는 변수의 값이 아닌 메모리 주소를 바라보고 있다. 변수명을 사용하면, 자바스크립트 엔진이 변수명과 매핑된 메모리 주소를 통해 메모리 주소에 저장된 값(29)을 반환한다.
변수에 값을 저장하는 것을 할당(assignment), 변수에 저장된 값을 읽어들이는 것을 참조(reference), 변수명을 자바스크립트 엔진에 알리는 것을 선언(declaration)이라 한다.
변수 선언(var, let, const)
변수의 선언은 var, let, const 키워드로 할 수 있으며, ES6에서 let과 const가 추가되었다.
var | let | const | |
변수 선언 방식 | 동일한 변수명으로 중복 선언 가능 재할당 가능 |
동일한 변수명으로 중복 선언 불가 재할당 가능 |
동일한 변수명으로 중복 선언 불가 재할당 불가 |
유효한 참조 범위 | 함수 레벨 스코프 | 블록 레벨 스코프 | 블록 레벨 스코프 |
var 키워드를 권장하지 않는 이유 : 호이스팅, 함수 레벨 스코프
호이스팅(hoisting)이란 스코프 안에 존재하는 모든 선언들을 해당 스코프의 최상단으로 끌어올리는 자바스크립트의 특성이다. 즉, 변수를 선언하기 이전에 참조할 수 있다.
console.log(foo); // undefined
var foo;
console.log(bar); // ReferenceError
let bar;
변수 호이스팅 : var
console.log(a); // undefined
var a = 10;
console.log(a); // 10
뒤에서 선언된 변수 a가 앞에서 참조되었음에도 에러를 발생시키지 않는다. var로 선언한 변수는 선언 단계와 초기화 단계가 동시에 실행된다. 즉, 변수가 선언되면 동시에 초기화가 이루어져 undefined가 할당된다. 따라서, 호이스팅으로 선언 단계가 이루어지고 동시에 초기화 단계도 이루어져서 에러가 발생하지 않는다.
변수 호이스팅 : let, const (변수 호이스팅이 발생하지 않는 것처럼 보이나 발생한다.)
console.log(a); // ReferenceError : a is not defined
let a = 10;
// let 키워드
console.log(value); // 선언 -> TDZ에 접근
let value = "hellosonic"; // 초기화 -> 할당
// const 키워드
console.log(value); // TDZ에 접근
const value = "hellosonic"; // 선언 -> 초기화 -> 할당
// ReferenceError: Cannot access 'name' before initialization
let 키워드의 경우 var 키워드와는 다르게 선언 단계와 초기화 단계가 분리되어 있고, 그 사이에 TDZ(Temporal Dead Zone)이 존재한다. const 키워드의 경우 let과 달리 선언 단계와 초기화 단계가 동시에 실행되나, 그전에 TDZ가 생성되어 TDZ에 접근할 경우 역시 Reference Error를 발생시킨다.
* TDZ(일시적 사각지대) : 변수의 선언과 초기화 사이에 일시적으로 변수 값을 참조할 수 없는 구간
즉, let, const 키워드는 변수 호이스팅은 발생하나, TDZ에 접근하기 때문에 참조 에러가 발생하게 되고, 마치 변수 호이스팅이 발생하지 않는 것처럼 보인다. 반면, var 키워드는 let, const 키워드와는 다르게 TDZ가 존재하지 않아 에러가 발생하지 않는다.
var n = 4;
function funcHoisting(){
console.log(n); // undefined
var n = 6;
console.log(n); // 6
}
var i = "BOOM!";
for (var i = 3; i > 0; i--){
console.log(i); // 3 2 1
}
console.log(i) // 0
또한, var는 함수 레벨 스코프를 가진다. 이는 전역 변수가 남발될 수 있음을 의미한다. 이처럼 var는 사용이 편리하다는 장점이 있지만, 변수가 의도와는 다르게 사용될 수 있다. 이에 ES6는 이러한 var 키워드의 단점을 보완하기 위해 let과 const 키워드를 도입하였다.
가비지 콜렉터
가비지 콜렉터는 가비지 콜렉션이라는 자동 메모리 관리 알고리즘을 통해 만들어진 객체로, 사용하지 않는 메모리를 해제하는 역할을 한다. JavaScript는 가비지 콜렉터가 사용하지 않는 메모리를 해제하며 자동으로 메모리를 관리해준다.
원시타입
- 자바스크립트 원시타입은 number, string, boolean, null, undefined, symbol 이다.
- 원시타입 데이터는 불변하는 데이터로, 메모리를 한 번 할당 받으면 값이 변경되지 않는다. 만약 원시타입의 값을 변경할 때에는 새로 메모리를 할당하게 된다.
- 자바스크립트에 값을 재할당하면 새로운 메모리 공간을 할당받아 값을 넣고, 변수가 가리키는 메모리 주소를 변경한다.
- 이전 값은 더 이상 사용되지 않으므로 가비지 컬렉션의 대상이 된다.
콜 스택(Call Stack)과 힙(Heap)
자바스크립트 엔진이 자바스크립트를 실행할 때 원시타입 및 참조 타입을 저장하는 메모리 구조로 콜 스택과 힙을 가진다.
- 콜 스택 : 원시타입 값과 함수 호출의 실행 컨텍스트를 저장하는 곳이다.
- 힙 : 객체, 배열, 함수와 같이 크기가 동적으로 변할 수 있는 참조타입 값을 저장하는 곳이다.
let a = 10; // 순차적으로 콜 스택에 변수가 쌓인다
const b = 20; // 순차적으로 콜 스택에 변수가 쌓인다
const arr = [];
// 배열의 경우, 객체타입이기 때문에 참조 타입으로 분류.(힙에 생성)
- 콜 스택에 생성된 배열 변수(arr)는 힙에서 생성된 배열의 메모리 주소를 참조한다.
- 힙 영역의 메모리는 동적으로 크기가 변할 수 있다.
- 따라서, 배열에 값을 추가(push)하면 힙 메모리 영역에 그대로 할당이 된다.
- 즉, 배열을 상수(const 키워드)로 선언했는데도 정상적으로 동작하는 이유는, 콜 스택에 할당된 메모리를 변경하는 것이 아닌, 힙에 할당된 메모리를 변경하는 것이기 때문이다.
- 사용을 마친 메모리는 가비지 컬렉터에 의해 사라진다.
스코프
변수에 접근할 수 있는 유효 범위를 말한다. 어디서나 접근 가능한 전역 스코프(Global Scope), 해당 컨텍스트 내에서만 접근 가능한 지역 스코프(Local Scope)로 나뉜다.
클로저
함수가 선언된 환경의 스코프를 기억하여 함수가 스코프 밖에서 실행될 때에도 기억한 스코프에 접근할 수 있게 만드는 문법이다. 즉, 부모함수 안에서 자식함수를 선언하면 자식함수를 어디에서 호출하더라도 자식함수 안에서 부모함수의 변수에 접근할 수 있다.
/* 예시 1 */
var d = 'x'
function outer(){
var a = 1;
var b = 'B';
function inner() {
var a = 2;
console.log(a); // inner 함수에 a가 있다. 2 출력.
console.log(b); // inner 함수에 b가 없다. -> outer 함수 확인
console.log(d); // x 출력
}
return inner;
}
const func = outer();
func();
// 2
// B
// x
/* 예시 2 */
let l0 = 'l0';
function fn2() {
let l2 = 'l2';
console.log(l0,l1,l2);
}
function fn1() {
let l1 = 'l1';
console.log(l0, l1);
fn2();
}
fn1();
// 에러 발생. fn2에서 l1을 찾을 수가 없다.
/* 예시 3 */
let l0 = 'l0';
function fn1() {
function fn2() {
function fn3() {
let l3 = 'l3';
console.log(l0, l1, l2, l3); // 함수를 함수 안에 정의하면, 그 함수의 부모 함수의 스코프에 접근할 수 있다.
}
let l2 = 'l2';
console.log(l0,l1,l2);
}
let l1 = 'l1';
console.log(l0, l1);
fn2();
}
fn1();
// l0 l1
// l0 l1 l2
// l0 l1 l2 l3
🗓️ day3 (230921)
브라우저에 URL을 입력한다면 무슨 일이 일어날까
STEP 1. URL 해석
- scheme://<user>:<password>@<host>:<port>/<url-path>
- scheme : 프로토콜이 들어가는 영역
- 계정정보 : 인증이 요구되는 경우, 아이디와 패스워드를 입력하면 접속 허가를 받을 수 있다.(ftp 프로토콜)
STEP 2. DNS(Domain Name System) 조회
- 도메인을 IP 주소로 변환해준다.
- DNS로 요청을 보내기 전에 브라우저 캐시를 확인한다.
- 브라우저 캐시에 해당 웹사이트의 DNS 기록이 있다면 IP를 반환한다.
- 브라우저 캐시에 해당 웹사이트의 DNS 기록이 없다면 로컬 컴퓨터의 hosts 파일을 참조한다.
- 그래도 DNS 기록을 찾아볼 수 없다면, DNS를 조회한다.
* Browser Cache : 브라우저는 특정 기간동안 유저가 방문한 웹사이트의 DNS 기록을 보관한다. 따라서 브라우저는 DNS를 조회하기 전 가장 먼저 Browser Cache를 찾아본다.
STEP 3. 해당 IP가 존재하는 서버로 이동
- 네트워크 장비인 라우터를 통해 해당 서버가 존재하는 대역으로 이동한다.
STEP 4. ARP를 이용하여 MAC 주소로 변환
- ARP(Address Resolution Protocol) : 논리 주소인 IP 주소를 물리 주소인 MAC 주소로 변환하는 프로토콜
- 실제 통신을 위해 변하지 않는 고유한 MAC 주소가 필요하다.
- 네트워크 내에 ARP를 Broadcasting하면 해당 IP 주소를 가지고 있는 기기가 자신의 MAC 주소를 반환한다.
STEP 5. TCP 통신을 위해 서버의 Socket을 연다
- 실제 Socket을 열어야 데이터를 전달할 수 있다.
- 네트워크를 통해 해당 기기로 패킷을 전달한다.
- TCP 연결을 허락받기 위해 3-way handshake를 실행한다.
- 요청이 수락되면 기기는 패킷을 받아 처리한다.
* 3-way handshake : 신뢰성 있는 데이터 전송을 보장하는 프로토콜인 TCP 프로토콜에 있어서, 장치간 서로 연결이 잘 되어 있는지 확인하는 과정이다.
STEP 6. 서버는 응답을 반환
- HTTP 프로토콜로 들어온 패킷을 읽고 처리한다.
- 요청에 따른 응답 값(HTML)을 반환한다.
STEP 7. 브라우저는 렌더링 한다
- 브라우저는 받은 HTML을 읽어 DOM Tree를 구축한다.
- 만들어진 DOM Tree를 기반으로 화면에 렌더링한다.
- 스크립트가 있다면 스크립트를 실행한다.
암호화
평문을 해독할 수 없는 암호문으로 변환하는 것을 의미하며 단방향(해싱)과 양방향 암호화가 존재한다.
단방향 암호화
- 해시 알고리즘을 이용하여 평문을 복호화할 수 없는 형태로 암호화한다.
- MD5, SHA 알고리즘
- 사용자 비밀번호를 저장할 때 자주 사용된다.
- 복호화가 불가능하지만, Rainbow Table을 통해 원문을 알아낼 수 있다.
- 따라서 암호화된 데이터를 탈취당하더라도 원문을 알아낼 수 없도록 조치해야 하며, Salt, Key streching을 이용하여 해결할 수 있다.
* Rainbow Table : 평문과 해시 함수로 만든 문자열을 모두 저장시켜 놓은 표
양방향 암호화
- 평문을 복호화할 수 있는 형태로 암호화한다.
- 대칭키와 비대칭키 알고리즘
- 대칭키 : AES, 비대칭키 : RSA
대칭키 암호 알고리즘
- 대표적으로 AES가 있다.
- 같은 키를 이용하여 암호화, 복호화가 가능하다.
비대칭키 암호 알고리즘
- 대칭키만으로는 다수를 대상으로 암호문을 받기 힘들기 때문에 비대칭키 암호 알고리즘이 탄생했다.
- 대표적으로 RSA가 있다. RSA는 소인수 분해를 기반으로 만들어진 알고리즘이다.
- 공개키와 개인키
객체 생성 방법
// 객체 리터럴
const person = {
name: "황",
age: "29",
move : function(destination) {
console.log(`${destination}(으)로 이동합니다.`);
},
};
// Object 생성자 함수
const person = new Object();
person.name = "황";
person.age = "29";
person.move = function(destination) {
console.log(`${destination}(으)로 이동합니다.`);
};
// 생성자 함수
function Person(name, age, move) {
this.name = name;
this.age = age;
this.move = function(destination) {
console.log(`${destination}(으)로 이동합니다.`);
};
}
프로토타입
자바스크립트의 모든 객체는 자신의 부모 역할을 담당하는 객체와 연결되어 있다. 그리고 이것은 마치 객체 지향의 상속 개념과 같이 부모 객체의 프로퍼티 또는 메소드를 상속받아 사용할 수 있게 한다. 이러한 부모 객체를 프로토타입(Prototype) 객체 또는 줄여서 프로토타입이라 한다. 프로토타입을 '유전자'라고 생각하면 이해하기 편리하다. 부모의 유전자를 자식이 물려받는 것처럼 부모 객체의 프로토타입을 자식 객체가 물려받을 수 있다.
function Person(name, age, move) {
this.name = name;
this.age = age;
this.getName = function() {
return this.name;
}
this.setName = function(name) {
this.name = name;
}
}
const kim = new Person("kim", "29");
const lee = new Person("lee", "29");
console.log(kim);
// Person { name: 'kim', age: '29', getName: [Function (anonymous)], setName: [Function (anonymous)]}
console.log(lee);
// Person { name: 'lee', age: '29', getName: [Function (anonymous)], setName: [Function (anonymous)]}
// 두 객체 다 메서드가 따로 정의되어있다 -> 메모리 낭비
이러한 경우에 프로토타입을 이용하면 된다. 프로토타입을 이용하게 되면 상위 객체를 참조할 수 있고, 객체를 이용하여 새로운 객체를 추가적으로 만들어 나갈 수 있다.
function Person(name, age, move) {
this.name = name;
this.age = age;
Person.prototype.getName = function() {
return this.name;
}
Person.prototype.setName = function(name) {
this.name = name;
};
}
const kim = new Person("kim", "29");
const lee = new Person("lee", "29");
console.log(kim.__proto__); // 상위 객체를 링크한다.
// { getName: [Function (anonymous)], setName: [Function (anonymous)] }
JavaScript 비동기 처리의 동작 구조
필수 개념 : JavaScript 엔진, 콜 스택, 힙, Web API, Task Queue, 이벤트 루프
JavaScript 엔진
자바스크립트 엔진은 콜 스택과, 힙으로 구성되어 있다.
콜 스택(Call Stack)
콜 스택에 작업이 하나씩 쌓이고(push) 쌓인 작업을 하나씩 실행(pop)하는 곳
function a() {
b();
console.log("a");
}
function b() {
console.log("b");
}
a();
위의 코드를 실행하면 아래의 순서대로 콜 스택에 push, pop이 수행된다. 참고로 콜 스택이 완전히 비었을 때만 Task Queue의 작업들을 넘겨 받을 수 있다.
- [a()]
- [a(), b()]
- [a(), b(), console.log("b")]
- console.log("b") POP
- [a(), b()]
- b() POP
- [a(), console.log("a")]
- console.log("a") POP
- [a()]
- a() POP
- []
메모리 힙(Memory Heap)
메모리 할당이 이루어지는 곳으로, 동적으로 생성된 객체는 이 곳에 할당된다.
Web API
Web API는 브라우저에서 제공되는 API이다. AJAX나 Timeout 등의 비동기 작업을 실행한다.
예를 들어, 자바스크립트에서 setTimeout 함수를 실행하면 자바스크립트 엔진은 Web API에 setTimeout을 요청하고 동시에 setTimeout에 넣어준 콜백 함수까지 전달한다. 자바스크립트 엔진의 콜 스택에서는 Web API 요청 이후(작업을 넘긴 이후) setTimeout에 대한 작업이 완료되어 제거된다. 즉, 자바스크립트 엔진 입장에서는 setTimeout을 Web API에 요청하는 것까지만 본인의 작업이라고 치고 요청을 넘기는 순간 콜 스택의 다음 작업으로 넘어가게 된다.
Web API는 방금 요청받은 setTimeout을 완료하고, 동시에 전달받은 콜백 함수를 Task Queue에 넘겨준다.
Task Queue(Callback Queue)
Task Queue는 큐 형태로, Web API에서 넘겨받은 콜백 함수를 저장한다. 이 콜백 함수들은 자바스크립트 엔진의 콜 스택의 모든 작업이 완료되면(스택이 비어있을 때) 순서대로 콜 스택에 추가된다.
이벤트 루프(Event Loop)
자바스크립트 엔진의 콜 스택의 모든 작업이 완료되면 Task Queue의 작업을 순서대로 콜 스택에 옮기는 작업을 반복해서 실행한다. 콜 스택이 비어있지 않은지(작업이 남아있는지) Task Queue에 작업이 존재하는지를 판단 후, Task Queue의 작업을 콜 스택에 추가한다.
이벤트 루프는 이 작업을 처음부터 끝까지 반복하여 수행한다.
EX) setTimeout이 0초로 지정되어 있다면
콜 스택에 저장된 setTimeout이 바로 실행되는 것이 아니라 Web API에 setTimeout를 무조건 요청하게 된다. Web API에 의해 Task Queue에 저장된 setTimeout의 콜백함수는 콜 스택이 반드시 비었을 때만 콜 스택에 추가가 가능하기 때문에 setTimeout의 시간과는 무관하게 이벤트 루프가 수행된다.
모듈
웹사이트는 여러 개의 JavaScript로 이루어져 있다. 이전에는 스크립트 파일 간 통신을 위해 전역 스코프에 있는 변수와 함수를 사용했다. 하지만 웹사이트가 하는 일이 많아지면서 스크립트 파일이 증가하였다. 즉시 실행 함수 등을 통해 전역 스코프가 오염되는 것을 어느정도 막을 수 있었지만, 스크립트 파일 간 의존도를 확인하기 어렵고 실행 순서를 제어해야 한다는 한계점이 존재했다. 이에 모듈이 등장하였다.
- 항상 엄격 모드로 실행된다.
- 모듈 레벨 스코프가 있다. 따라서 import 하지 않으면 다른 스크립트를 참조할 수 없다.
- 단 한 번만 평가된다.
- 지연 실행된다. 모듈 스크립트는 모든 DOM이 만들어진 이후 실행된다.
정규표현식
정규표현식은 패턴을 이용하여 문자열에서 원하는 문자를 검색(search), 대체(replace), 추출(extract)할 수 있다.
- test(문자열) : 정규표현식 객체의 test 함수는 입력받은 문자열에 찾는 패턴이 있는지 찾은 후, 있다면 true, 없다면 false를 반환한다.
- exec(문자열) : 정규표현식 객체의 exec 함수는 입력받은 문자열에 찾는 패턴이 있는지 찾은 후, 일치한 패턴 정보를 반환하고 없으면 null을 반환한다. 문자 추출에 해당한다.
- match(정규표현식 객체) : String 객체의 match 함수는 정규표현식 객체를 파라미터로 받아 패턴이 있는지 찾은 후, 일치한 패턴 정보를 반환하고 없으면 null을 반환한다. 문자 추출에 해당한다.
- replace(정규표현식 객체, 변경 문자열) : String 객체의 replace 함수는 정규표현식 객체를 파라미터로 받아 패턴이 있는지 찾은 후 일치한 패턴 정보를 원하는 문자열로 바꿀 수 있다.
- search(정규표현식 객체) : String 객체의 search 함수는 정규표현식 객체를 파라미터로 받아 패턴이 있는지 찾은 후 일치한 패턴 정보의 위치를 반환한다. 무조건 처음 찾은 위치를 반환한다. 문자 검색에 해당한다.
네이버가 브라우저를 닫아도 설정을 기억하려면 어떻게 해야할까
HTTP 통신
- HTTP Request는 기본적으로 상태가 존재하지 않는다. 단발성이다.
- 따라서, 서버는 어떤 브라우저에서 요청이 온 것인지 알 수 없다.
- 이 때, 헤더에 쿠키를 담으면 서버가 쿠키를 읽어 어디서 온 것인지 알 수 있다.
Cookie
- 클라이언트에서 저장하고 관리하는 데이터들이다. 브라우저를 닫아도 데이터를 유지할 수 있다.
- 서버에서 Set-Cookie를 응답 헤더로 내려주면 클라이언트는 받아서 저장한다.
- 클라이언트 자체적으로 조작할 수 있다.
- 각 상태에 수명을 정할 수 있다.
Set-Cookie
- Response에 Set-Cookie 헤더를 추가해서 보내면 브라우저에 쿠키가 저장된다.
- Set-Cookie : 키=값; 옵션
- 각 데이터에는 여러 옵션이 존재한다.
- Expires : 쿠키 만료 날짜를 지정한다.
- Secure : HTTPS에서만 쿠키를 전송한다.
- HttpOnly : JavaScript에서 쿠키에 접근 못하도록 막는다.
- Max-Age : 쿠키 수명을 정한다. 이 때, Expires 옵션은 무시된다.
- Domain : 도메인이 일치하는 요청만 쿠키가 전송된다.
- Path : 패스와 일치하는 요청만 쿠키가 전송된다.
Cookie의 취약점
- XSS(Cross-Site Script) 공격을 당할 수 있다.
- JavaScript를 이용해 악의적인 사용자가 다른 사용자의 쿠키값을 탈취할 수 있다.
- 쿠키를 암호화하지 않고 보내면 쿠키값을 중간에 탈취 당할 가능성이 있다.
- HTTPS 이용하여 해결
* XSS : 권한이 없는 사용자가 악의적인 용도로 웹 사이트에 스크립트를 삽입하는 공격 기법
Session
- Session을 통해 서버가 쿠키의 주인이 누구인지 알 수 있다.
- 쿠키에 HTTP Session ID를 담아 서버와 클라이언트 간 통신이 가능하다.
- HTTP Session ID를 식별자로 사용자를 구분한다.
- 클라이언트는 HTTP Session ID를 쿠키 형태로 저장한다.
- 서버 자체적으로 기록하고 관리한다.
Session의 문제점
- 세션은 서버에 파일로 저장된다. 만약 사용자가 엄청 많아진다면, 저장공간이 없어 서버가 정상적으로 동작하지 않을 수 있다.
- 만약 서버가 여러 대라면, 각 인증 정보가 퍼져있기 때문에 제대로 된 값을 응답하지 못할 수 있다.
- 따라서, 이제 서버와 클라이언트 간 인증은 별도 토큰(JWT...)을 사용하고, 쿠키는 클라이언트 자체적인 지속적인 데이터 관리 용도로 많이 사용된다.
* JWT(Json Web Token) : 인증에 필요한 정보들을 암호화시킨 Json 토큰
웹 스토리지
- 클라이언트에 데이터를 저장하기 위한 새로운 방법이다. 쿠키 대신 로컬 데이터를 관리한다.
- HTML5부터 등장했으며, 쿠키가 하기 힘든 것들을 지원하기 위해 등장했다.
- 로컬 스토리지와 세션 스토리지가 있다.
로컬 스토리지
- 로컬 스토리지에 데이터를 저장하면 반영구적으로 데이터가 저장된다.
- 브라우저를 종료해도 계속해서 데이터가 남는다.
- 저장했던 도메인과 이용하는 도메인이 다른 경우엔 접근할 수 없다.
- 쿠키와 마찬가지로 Key-Value 형태로 저장한다.
세션 스토리지
- 새 창, 새 탭을 생성할 때마다 개별적으로 저장되는 데이터를 관리한다.
- 브라우저를 닫는 순간 사라진다.
- 같은 도메인이어도 세션이 다르면 데이터에 접근할 수 없다.
- 쿠키와 마찬가지로 Key-Value 형태로 저장한다.
🗓️ day4 (230922)
자료구조
메모리를 효율적으로 사용하여 빠르고 안정적으로 데이터를 처리하는 것이 궁극적인 목표로, 상황에 따라 유용하게 사용할 수 있도록 특정 구조를 이루고 있다. (스택, 큐, 그래프, 트리..)
- 선형구조 : 한 원소 뒤에 하나의 원소만이 존재하는 형태, 자료들이 선형으로 나열 (배열, 연결리스트, 스택, 큐)
- 비선형구조 : 계층적 구조나, 망형 구조를 가지고 있다. (트리, 그래프)
알고리즘
특정 문제를 효율적이고 빠르게 해결하는 것이 궁극적인 목표로 정해진 일련의 절차나 방법을 공식화한 형태로 표현한 것이다.
시간복잡도
알고리즘을 평가하는데 있어 수행시간과 메모리 사용량을 평가 기준으로 둔다. 수행시간에 해당하는 것이 시간 복잡도(Time Complexity), 메모리 사용량에 해당하는 것이 공간 복잡도(Space Complexity)이다. 시간 복잡도는 보통의 경우 빅오표기법(big-O notation)을 사용한다.
- 성능비교 : O(1) < O(log n) < O(n) < O(n log n) < O(n²) < O(2ⁿ) < O(n!) < O(nⁿ)
연결리스트
- 각 요소를 포인터로 연결하여 관리하는 선형 자료구조
- 각 요소는 노드라고 부르며, 데이터 영역과 포인터 영역으로 구성된다.
연결리스트는 왜 배워야 할까
다량의 선형 데이터를 다루기 위해 배열을 많이 사용했지만 배열은 연속적으로 데이터가 저장된다는 단점을 가지고 있다. 즉, 배열은 데이터의 요소들이 메모리에 인접한 위치에 저장되거나 연이어 저장된다. 연결리스트에서 요소의 추가, 삭제 연산에 대한 시간 복잡도는 O(1)인 반면, 배열에서의 추가, 삭제 연산의 시간 복잡도는 O(n)이고 이 과정에서 큰 오버헤드를 가져올 수 있기 때문에 연결리스트를 반드시 학습해야 한다.
- 데이터가 자주 추가되거나 가변적으로 자주 변한다면 연결리스트를, 주로 데이터의 변경이나 탐색을 위한 것이라면 배열을 쓰는 것이 좋다.
배열 | 연결리스트 | |
탐색 시간복잡도 | O(1) | O(n) |
추가, 삭제 시간복잡도 | O(n) | O(1) |
메모리 영역 | 메모리 영역을 연속적으로 사용 | 데이터가 퍼져 있고, 퍼져있는 데이터의 영역을 알기 위해 포인터를 사용하고 각 영역을 참조 |
스택
데이터를 차곡차곡 쌓아올린 형태의 후입선출(Last In First Out)의 개념을 가진 선형 자료구조이다.
- 예를 들어, 함수 호출은 스택 자료구조를 통해 메모리에 추가되고 제거된다.
피드백
첫 WIL 작성을 이렇게 끝냈다. 한 주 간의 강의에서 아는 내용도 있었지만 대부분 겉핥기 수준의 지식이었고, 누군가에게 설명하라고 했으면 못했을 것 같다. 나만의 표현법으로 자신있게 설명하기 위해 반복 학습해야겠다.
강의 내용을 완벽히 이해하려고 노력하다보니 모르는 것이 나오면 파고들게 되었고, 시간이 예상보다 많이 소요되었다. 어쩌면 나는 TIL이 더 맞을지도.. 궁금한 게 있으면 그때 그때 정리해야겠다.
클로저, 네트워크 기초, js 비동기처리 동작구조 등 중요하고 더 심화된 학습이 필요한 부분은 따로 포스팅하면서 더 공부해야겠다.
📚
https://poiemaweb.com/js-data-type-variable
https://negabaro.github.io/archive/js-async-detail
https://velog.io/@yjw8459/정규표현식-regex
https://jocoma.tistory.com/entry/시간-복잡도-공간-복잡도
'프로그래머스 데브코스' 카테고리의 다른 글
[JavaScript] Map 과 Set (0) | 2023.10.13 |
---|---|
[JavaScript] JavaScript의 10가지 코드 트릭 (0) | 2023.10.03 |
[모딥다/스터디] 39장. DOM(Documents Object Model) (0) | 2023.10.03 |
[특강] 코딩테스트 문제풀이 꿀팁 (0) | 2023.10.02 |
Git & GitHub / init, add, commit, push, pull, clone, fetch, fork, branch (2) | 2023.09.30 |