[TIL] 2022-03-22 / 2일차
미음제
·2022. 3. 22. 22:54
오늘 배운 내용
네트워크 기초
브라우저에 URL 주소를 입력했을 때 무슨 일이 발생하는가?
- URL 해석
- DNS 조회 : DNS이 도메인은 IP주소로, IP주소는 도메인으로 변환
- IP가 존재하는 서버로 이동 : 라우터를 통해 해당 서버가 있는 대역으로 접근하는 것
- ARP를 이용해 MAC 주소 변환 : 논리 주소인 IP를 물리 주소인 MAC 주소로 변환
- TCP 통신을 통해 Socket을 Open : Socket을 열어야 데이터를 주고받을 수 있다. 이때 3 way handshake로 연결.
- 서버에서 응답을 반환 : 데이터를 읽고 요청에 따라 처리를 해준다. 브라우저에 URL을 입력하면 응답 결과는 HTML
- 브라우저가 렌더링 : 읽어온 HTML을 통해 DOM Tree를 구축, 스크립트가 있다면 실행
선택 과제 1 : https가 생겨난 이유? / https의 탄생으로 기존 과정에 무엇이 추가 되었는지?
컴퓨터 시간
어떤 원리로 동작을 하는지? 꽤 많은 조건을 고려해 시간을 표시하게 된다(문화, 지역 등). 전 세계 시간은 협정 세계시를 통해 표준화했다.
컴퓨터가 시간을 표시하는 방법은? 각각의 컴퓨터는 시스템 클럭을 갖고 있고, 특정 시간을 기준으로 시스템 클럭의 틱을 세서 시간을 구하게 된다. 이때 만들어진 시간은 시스템 시간이고, 값으로 표현한 것이 타임스탬프다.
표준적으로 많이 사용하는 것은 Unix Time.
- Unix Time : 1970년 01월 01일 0시 0분 0초가 기준 시간이다. 초 단위로 시간이 증가
시스템 클럭의 원리? RTC 모듈을 사용한다. RTC 모듈은 메인보드에 부착되어 있어 전원이 꺼지더라도 동작할 수 있다.
그렇다면 컴퓨터가 현 시간을 알아내는 방법은? NTP(Network Time Protocol)를 통해 확인한다. NTP 서버에 네트워크를 요청하고 시간을 확인해 현 시간을 알아내기 때문에 인터넷이 없다면 확인할 수 없게 된다. NTP 서버는 트리구조로 이루어져 있고 각 계층은 Stratum이라고 한다.
다양한 시간대가 있는데, 시간대를 고려하는 방법은? 모든 데이터(Time Zone)를 데이터베이스에 저장해 이용하는 것이다. Summer Time이 적용되면 변경된 시간을 데이터베이스에 반영하고 그 정보를 이용하는 것이다.
- Time Zone 표기법 : 대륙/도시, 이것을 ZoneId라고 부른다.
어떤 기준으로 시간을 정해 사용하는지? 서비스에 사용되는 시간을 용도에 맞추어 기록해야 한다.
- 순수한 시간 : 시간대, 사회적 합의를 고려하지 않고 순수한 시간대를 기록(생일, 기념일, 국경일 등)
- UTC : TimeZone 없이 UTC Zulu Time으로만 기록, 사건이 발생한 시각을 나열하는 주식과 같은 경우에 사용(시계열)
- TimeZone이 적용된 시간 : 역사, 사회, 문화를 고려해 이용한 시간을 정확히 알아야 할 때 사용, (UI에 표시하는 시간, 결제 시간 등)
JS에서는 어떻게 사용하는가? 간단하게는 Date 객체를 사용하고, 복잡한 시간의 경우 TimeZone을 적용한다. moment.js가 있는데(Deprecated 되어 사용이 권장되지 않는다고 한다. 대체로 date-fns, luxon을 사용한다고 한다.)
암호화 기초
암호화
인터넷에서 개인 정보를 전송할 때 중간에 해킹되지 않도록 암호화 기법을 사용한다. 평문을 해독할 수 없는 암호문으로 변환하는 것을 암호화라고 한다.
- 단방향(해싱) 암호화
- 양방향 암호화
단방향 암호화
해시 알고리즘을 이용해 평문을 복호화할 수 없는 형태로 암호화하는 것이다. 대표적 알고리즘은 다음과 같다.
- MD5
- SHA
비밀번호 등을 저장할 때 주로 이용하고, 복호화가 불가능하도록 저장하는 이유는 저장하는 측에서도 데이터를 알지 못하게 하기 위함이다. MD5, SHA-0, SHA-1은 해시 충돌 발생의 취약점이 있어 권장되지 않는다.
암호화된 데이터를 탈취당했을 때, 해커들은 미리 평문 데이터를 해시 알고리즘을 통해 데이터베이스에 저장해 둔 것을 사용, 그 후 탈취한 데이터 대입하여 원문을 알 수 있다. 따라서 원문을 알아낼 수 없도록 조치를 취해야 하는데 Salt, Key stretching을 이용해 해결할 수 있음
- Salt : 평문에 임의의 문자열을 추가해 암호화하는 방법 / 128bit 이상으로 만드는 것을 권장 / 사용자마다 다른 Salt를 만드는 것이 효과적
- Key stretching : 해시를 여러 번 반복해 원문을 알기 힘들게 만드는 방법 / 해시 알고리즘을 여러번 반복하여 돌리는 방법 / 일반적인 시스템에서 0.2초 이상 반복되도록 돌리는 게 안전
양방향 암호화
단방향과 달리 평문을 복호화할 수 있는 형태로 암호화하는 방법이다.
- 대칭키 : AES, 같은 키를 이용해 함호화하고 복호화한다.
- 비대칭키 : RSA, 공개키와 개인키로 보안 문제를 해결할 수 있다. HTTPS에서도 사용된다.
직접 암호화 알고리즘을 구현하는 것보다 이미 검증된 알고리즘을 사용하는 것이 좋다.
- PBKDF2
- bcrypt
두 알고리즘 모두 Salt와 Key Stretching 그리고 특정 해시 알고리즘을 이용해 해시값을 만들어낸다.
자바스크립트에서 암호화를 사용하는 방법
빌트인으로 제공되는 것은 없기 때문에 라이브러리를 이용해야 한다. crypto-js를 이용하면 대부분의 암호화를 사용할 수 있지만, bcrypt는 없기 때문에 별도의 라이브러리를 사용해야 한다.
함수형 프로그래밍
함수형 패러다임
패러다임이라는 것은 무엇을 해야 할지 말하기보다 무엇을 해서는 안되는지를 말한다. 프로그램은 순차, 분기, 반복, 참조의 4가지 요소로 구성되어 있는데 패러다임은 이 4가지 요소를 어떻게 이용할 것인가를 다룬다.
객체지향은 객체란 것을 통해 데이터와 메서드를 묶고 객체 간 메시지를 주고받으며 프로그램이 작동한다.
이와 달리 함수형은 데이터를 함수를 이용해 새로운 데이터를 만들어 나가는 데이터 파이프 형태로 프로그램이 작동한다. 객체지향은 순차, 분기, 반복, 참조의 전환을 객체를 통해 간접적으로 통제하지만, 함수지향은 변수 할당을 통해 흐름을 제어한다.
함수형에서는 함수가 최소 단위, 객체지향에서는 객체가 최소 단위가 된다.
객체보다 더 작은 단위(함수)로 추상화가 되기 때문에 재사용성이 높고, 데이터의 불변성을 지향해 동작을 예측하기 쉽고 사이드 이펙트를 방지할 수 있다.
함수형 프로그래밍의 장단점
- 상태가 없기 때문에 사이드 이펙트가 없다
- 재사용성이 높다
- 코드가 짧고 간결하다
장단점이라 적고 3개 항목만 적어놨는데, 장점이 곧 단점이 될 수 있기 때문이다. "상태가 없기 때문에 사이드 이펙트가 없다."는 것은 상태를 조작할 수 없어 다른 방법을 찾아야 한다는 것(쓸데없이 메모리와 성능을 사용)이고, "재사용성이 높다(함수 단위로 나뉘어 있기 때문에)."는 함수를 더 작게 작게 나누어서 복잡해질 수 있다는 것이고, "코드가 짧고 간결"하다는 것은 높은 숙련도를 요구할 수 있다는 것이다.
함수형 프로그래밍, 선언형 프로그래밍
함수형 프로그래밍은 선언형 프로그래밍과 가깝다.
- 명령형 프로그래밍 : 문제를 어떻게 해결한 것인지? 컴퓨터에게 명령을 내리는 것
- 선언형 프로그래밍 : 무엇을 해결할 것인지? 방법은 컴퓨터에게 위임
객체지향과 함수형 프로그래밍
객체지향과 함수형을 분리해 사용할 필요성은 없다. 각각의 장점을 극대화하기 위해 적절히 둘 다 사용하는 것이 바람직하다. 자바스크립트는 멀티 패러다임이 가능하기 때문에 잘 활용하는 것이 중요하다.
객체지향과 프로토타입
객체
현실에 있는 것을 추상화한 것을 의미한다. 이 말이 현실에 있는 것을 코드로 옮기는 것과는 다르다는 것을 유의한다.
추상
사물이 지닌 여러 측면 중에서 특정 부분만(당장 필요한 것, 불필요한 것은 제거)을 보는 것을 말한다.
객체지향
객체 위주로 설계하고 프로그래밍하는 패러다임을 말한다. 추상화의 최소 단위는 당연히 객체이다. 각 객체들은 서로 메시지를 주고 받을 수 있고, 객체가 데이터를 관리하고 메세지를 통해 절차를 간접적으로 통제한다.
객체지향의 오해
C언어에서 객체지향 프로그래밍이 불가능한가? 객체지향은 단순히 '패러다임'일뿐이지 언어와는 관계가 없다. 클래스가 없는 자바스크립트, C 등으로도 충분히 가능하다. 자바스크립트는 프로토타입으로 객체지향을 표현할 수 있다.
패러다임의 우위
객체지향이 절차지향보다 좋고 나쁜 것은 없다. 프로그램 by 프로그램. 적합한 곳에 적합한 패러다임이 있는 것이다. 간단한 프로그램일수록 절차지향이 직관적으로 보이고 간단하다. 복잡한 프로그램은 객체 단위로 나눠 관리하는 것이 좋다.
프로토타입
프로토타입이 필요한 이유는? 프로토타입을 이용하면 상위 객체를 참조할 수 있고 객체를 이용해 새로운 객체를 만들 수 있다. 기존 객체를 효율적으로 사용할 수 있는 방법으로 메모리 낭비를 줄일 수 있다.
이벤트 루프
자바스크립트 싱글 스레드
자바스크립트 엔진에는 하나의 Call Stack만 존재하기에 싱글 스레드가 맞다. 그런데 브라우저에서 실행되는 스크립트는 어떻게 비동기적으로 데이터를 불러오고 애니메이션을 실행하고, 어떤 원리로 애니메이션과 클릭 이벤트를 같이 처리할 수 있는가?
브라우저의 이벤트 루프라는 시스템 때문이다. 이벤트 루프는 자바스크립트 엔진에 포함되지 않고 브라우저나 node.js에서 자체적으로 관리된다. DOM Events(클릭 이벤트 등), 네트워크 호출, Timer 등(웹 APIs)은 실행시키면 브라우저에 위임된다. 웹 APIs는 콜백 함수를 넘기는데 콜백 함수는 비동기 작업이 끝나면 Task Queue에 넣어져 순차적으로 꺼내 Call Stack에 Push 한다. 이 과정은 멀티 스레드로 동작한다.
자바스크립트 엔진이 싱글 스레드 일 뿐이고 브라우저는 멀티 스레드라 가능해지는 것이다.
선택 과제 2 : Microtask Queue, Animation frames가 무엇인가?
모듈
일반적으로 웹 사이트는 여러 개의 자바스크립트로 이루어져 있다. 자바스크립트는 파일들을 별개의 프로그램으로 취급하는데, 웹 사이트가 하는 일이 많아지며 스크립트 파일이 많아졌고 스크립트 간 의존도와 실행 순서를 제어하기가 어려워졌다. 이를 해결하기 위해 등장한 것이 모듈이다.
모듈과 컴포넌트
모듈 | 컴포넌트 |
설계 시점에 의미있는 요소 | 런타임 시점에 의미 있는 요소 |
즉, 모듈은 의식적으로 나누어 놓은 요소이고 컴포넌트는 나눠 놓은 요소에 포함되어 실행되는 요소이다.
자바스크립트의 모듈은 직접적으로 런타임에 실행되는데 이름이 모듈인 이유는? 파일 하나가 프로그램이기 때문에 모듈이라 지었을 것으로 추측된다고 한다.
자바스크립트에서는 디렉터리 단위를 모듈 개념에 가깝게 사용하는 경우가 많다고 한다.
모듈의 특징
- 항상 엄격 모드(use strict)로 실행된다 : 일반 스크립트는 키워드를 생략하고 변수 선언이 가능하고 전역 스코프에 저장되어 사용되지만 모듈 스크립트는 불가능하다.
- 모듈 레벨 스코프가 있다 : 일반 스크립트는 최상위에 선언하면 전역 스코프에 선언되어 다른 스크립트에서 참조가 가능하지만, 모듈 스크립트에서는 import 하지 않으면 서로 참조가 불가능하다.
- 단 한 번만 평가된다 : 두 번 import 되더라도 한번만 실행된다.
- 지연 실행된다 : 일반 스크립트는 바디 tag에 넣을 경우 순서에 따라 DOM이 생성되기 전에 실행되는 경우가 있지만, 모듈 스크립트는 자동으로 지연 실행되어 모든 DOM이 만들어진 후에 실행된다.
유니코드
전 세계 문자를 컴퓨터에서 다룰 수 있도록 만든 표준 시스템이다. 유니코드 없이도 각 나라의 문자를 잘 표현했었는데, 서로 다른 인코딩 방식을 사용해 호환성과 확장성 문제가 있었다. 그래서 유니코드가 탄생했고 2010년 이후 이모티콘이 포함되었고 계속해서 추가되고 있다.
정규 표현식
정규표현식은 패턴을 이용해 문자를 검색, 대체, 추출할 수 있는 간단한 방법이다. 그러나 성능은 좋지 못하기에 짧은 문자열에 사용한다.
기본 형태 = /regexr/i
- / / : 시작, 종료
- regexr : 패턴
- i : 플래그
전화번호 찾기 : \d{3}-\d{3,4}-\d{4}
이메일 주소에서 중간 문자열 찾기
.+@.+\..+ : 이메일 찾기
.+@(.+)\..+ : 중간 문자열 찾기
캡처는 여러 번이 가능하다.
자바스크립트에서 정규 표현식 다루기
RegExp 객체로 정규 표현식을 제공하고, 배열이나 객체처럼 Literal로 생성이 가능하다.
const regExp1 = new RegExp("^\d+");
conset regExp2 = new RegExp("^\d+", "gi"); // 표현식, 플래그
// Literal 방식
const regexp1 = /^\d+/;
const regexp2 = /^\d+/gi; // 표현식, 플래그
- test 함수 : 입력받은 문자열에 찾는 패턴이 있는지 찾고 결과로 true, false를 반환
- exec 함수 : 패턴이 있는 경우 패턴 정보를 반환(패턴이 일치한 문자열과 인덱스) 아니면 null 반환
- match 함수 : String 객체에서 사용하는 정규식, exec 함수와 동일하다. matchAll의 경우 일치한 모든 정보를 반환
- replace 함수 : String 객체에서 사용하는 정규식, 패턴이 일치한 경우 원하는 문자열로 변환, 모두 변경하고 싶은 경우 'g' 플래그를 사용
- search 함수 : 매칭 된 문자열의 위치를 반환해준다. 처음 매칭된 것만 반환해주기에 모든 정보를 파악하고 싶다면 matchAll을 사용
- capture : 캡처가 적용된 정규표현식을 이용하면 match 반환 값의 1번 인덱스부터 순차적으로 결과가 들어온다.
regExp.test(message) // message 문자열에서 찾기
regExp.exec(message) // message 문자열에서 패턴 찾기
message.match(regExp)
message.replace(regExp, "바꾸고 싶은 문자열");
선택 과제 3 : 개미 수열을 정규표현식으로 풀기
쿠키와 세션, 웹 스토리지
HTTP 통신
HTTP Request는 기본적으로 상태가 존재하지 않고 항상 단발성이다. 따라서 서버는 어떤 브라우저에서 요청을 보냈는지 알 수가 없는데 이때 헤더에 쿠키를 담아 보내게 되면 쿠키를 읽고 어디서 요청을 보내왔는지 알 수 있다.
쿠키
쿠키는 프론트엔드에서 저장하고 관리하는 데이터를 말한다. 쿠키는 브라우저를 닫아도 데이터를 유지할 수 있다. 서버에서 Set-Cookie를 응답 헤더로 내려주면 클라이언트는 받아서 저장하기도 하고, 클라이언트 자체적으로 조작도 할 수 있다.
쿠키는 document 객체로 관리하는데 String 형태로 관리되어 값을 추가하거나 제거하는데 번거로움이(파싱 로직 혹은 알고리즘을 이용해야 하는) 있다.
Set-Cookie
형태는 키-값의 형태이다. 클라이언트는 값을 파싱 해 알아서 쿠키에 데이터를 추가한다. 쿠키의 각 데이터에는 여러 옵션이 존재할 수 있고 옵션은 다음과 같다.
- Expires : 쿠키 만료 날짜 지정
- Secure : HTTPS에서만 쿠키를 전송하게 함
- HttpOnly : 자바스크립트에서 쿠키에 접근하지 못하도록 막는 것(XSS 공격을 예방).
- Max-Age : 쿠키의 수명을 지정하는 것으로 Max-Age가 있는 경우 Expires는 무시된다.
- Domain : 도메인이 일치하는 요청만 쿠키가 전송
- Path : 패스와 일치하는 요청만 쿠키가 전송
Session
쿠키에 HTTP Session Id를 식별자로 담아 사용자를 구분한다. 서버는 식별자로 사용자를 구분하고 그에 맞게 데이터를 응답해 준다.
Session의 문제점
세션은 서버에 파일로 저장되어 관리되기 때문에 사용자가 많아지면 정상 동작을 하지 못할 수 있고, 서버가 2대라면 각 인증 정보가 퍼져있어 올바른 응답을 못할 수 있다.
따라서 서버와 클라이언트 간 인증은 별도 토큰(JWT)를 사용하고 쿠키는 자체적인 데이터 관리 용도로 많이 사용된다.
웹 스토리지
쿠키 대신 로컬 데이터를 관리한다.
로컬 스토리지
데이터를 저장하면 반영구적으로 데이터가 저장된다. 데이터는 키-값 형태로 저장된다. 브라우저를 종료해도 데이터가 남아있기 때문에 유효기간이 필요 없는 데이터를 저장할 때 유용하다. 쿠키와 마찬가지로 저장했던 도메인과 이용하는 도메인이 다르면 접근할 수 없다.
세션 스토리지
새로운 창, 새로운 탭을 생성할 때마다 개별적으로 저장되는 데이터를 관리하기 때문에 브라우저를 닫는 순간 사라지게 된다. 데이터는 키-값 형태로 저장된다. 로컬 스토리지와는 달리 세션 스토리지는 같은 도메인이더라도 세션이 다르면 데이터에 접근할 수 없다.
localStorage.setItem("key","value");
localStorage.getItem("key");
localStorage.removeItem("key");
localStorage.clear();
sessionStorage.setItem("key","value");
sessionStorage.getItem("key");
sessionStorage.removeItem("key");
sessionStorage.clear();
선택 과제 4 : IndexedDB란?
부족했던 점
- 시간 분배와 계획 수립
- 이벤트 루프
- 함수형 패러다임
- 이벤트 루프
느낀 점
"계획을 잘 세우자. 내가 할 수 있는 정도가 어느 정도 인지를 잘 파악하자." 1일 차가 지나고 호기롭게 2일 차 계획을 세웠다. 복습, 그리고 원래 하려던 공부 계획까지. 아침엔 특강을 오후엔 커피 챗을 하며 시간이 부족할 거라고 생각 못했다. 전혀..
내용적으로도 머리가 아파오기 시작했다.. 정처기 자격증을 취득할 때 공부했던 내용들이라 쉽게 이해가 되는 부분도 있지만, 1일 차에 부족했던 부분은 여전히 어렵게 다가왔다(콜 스택).
3일 차부터는 꼭 오전에 강의를 시작해 점심시간 이후로 강의를 다 들을 수 있도록 하고, 1일 차와 2일 차 부족했던 부분을 꼭 추가적으로 학습할 수 있도록 노력해야겠다!
그리고 정규 표현식은 늘 할 때마다 새롭게 느껴진다. 강의에서도 모두 외우지 않고 필요할 때마다 찾아 쓴다고 하셨지만, 정말 볼 때마다 새로운 느낌이다.
참고
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String/match
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec
'프로그래머스 > 데브코스 프론트엔드' 카테고리의 다른 글
[TIL] 2022-03-23/24 / 3, 4일차 (0) | 2022.03.24 |
---|---|
[자바스크립트] 이벤트 루프(Event Loop) (0) | 2022.03.23 |
[자바스크립트] 클로저(Closure) (0) | 2022.03.23 |
[자바스크립트] 원시타입(Primitive Type)과 참조타입(Reference Type) (0) | 2022.03.23 |
[TIL] 2022-03-21 / 1일차 (0) | 2022.03.21 |