- 강의 노트는 날짜나 요일 별로 구분하지 않고 큰 주제별로 분리할 생각입니다. 그렇게 하는 편이 나중에 찾아보기에 좋을것 같습니다 -안혁준
- 저의 주관적인 부분이 많이 들어 갈수 있으므로 부족하다 생각되는 부분은 채워주세요.
- 강의 노트는 같이 만들어 나가는 것이므로 모두들 함께 채워나갑시다.
2. JavaScript란? ¶
2.1. Prototype 기반 언어 ¶
- prototype언어?
- oop의 흐름은 class와 prototype으로 나늰다.
- prototype은 클래스가 들고 있어야하는 함수들을 특정 인스턴스가 들고 있게 만드는 것이다.
- 이 특정 인스턴스를 prototype이라 부른다.
- oop의 흐름은 class와 prototype으로 나늰다.
2.2. 함수형 언어 ¶
- 함수를 일급객체로 다루는 언어
- 일급객체란?
- 변수 안에 담을수 있고,
- 파라미터로 전달할수 있으며,
- 반환값을 사용할수 있고
- 할당된이름과 관계없이 구분할수 있다
- 변수 안에 담을수 있고,
- 일급객체란?
- 함수를 마치 일반적인 인스턴스처럼 다루는 언어
3.2. Excuteion Context ¶
- this
- p.do() 에서 p가 실행문맥이다. 그러나 이 함수를변수로 받으면 var f = p.do; f(); 이런식으로 그러면 f는 실행문맥이 없기 때문에 전역객체가 실행문맥으로 간주된다.
- p.do() 에서 p가 실행문맥이다. 그러나 이 함수를변수로 받으면 var f = p.do; f(); 이런식으로 그러면 f는 실행문맥이 없기 때문에 전역객체가 실행문맥으로 간주된다.
- 결론적으로 함수 앞 마지막 . 앞에 있는 것이 중요하다.
- func.apply(ec, arguments) 나 func.call(ec, arg1, arg2, ... )으로 func안에서의 실행문맥(this)를 명시적으로 변경할수 있다.
3.3. new의 동작 ¶
- new Person();
- 1. create instance
- 2. instance.proto = Person.prototype;
- 이때의 proto는 프로토타입 체인이라 할수있다.(엔진별로 다를수 있다.)
- 이때의 proto는 프로토타입 체인이라 할수있다.(엔진별로 다를수 있다.)
- 3. 실행문맥을 instance로 한 생성자를 호출한다.
- 1. create instance
3.4.1. Class vs Prototype ¶
- Class : 함수와 맴버 변수가 각각 class와 인스턴스에 나누어 져있는것.
- prototype : 함수와 맴버 변수 모두 인스턴스에 저장되있는것
- 단지 함수는 다른 인스턴스에 존재한다.
- 그 다른 인스턴스는 prototype이라 부른다.
class <-----------------> prototype VTable <-----------------> prototype chain (proto)
- 단지 함수는 다른 인스턴스에 존재한다.
3.4.2. dispatch ¶
- 실제 호출해야 하는 함수를 찾는 과정
- javascript에서는 실행시간에 프로토타입 체인에 의해 실행한다.
- instance의 proto에서 찾고 없으면 그위에 proto에서 찾고...
- instance의 proto에서 찾고 없으면 그위에 proto에서 찾고...
- 코드로 나타내보면..
for (var _proto = a; _proto; _proto = _proto.__proto__) { if (("f" in _proto) && typeof _proto["f"] === "function") _proto["f"].apply(a, arguments]); }
- 자바스크립트는 함수와 일반 변수와의 구분이 없기때문에 변수 또한 dispatch가 된다.
3.4.3. 상속 ¶
- 상속을 위해서는 prototype chain에 등록하면 된다.
function People(){}; function Man(){}; Man.prototype = new People(); m = new Man();
3.5. same origin policy ¶
- 자바 스크립트에서는 XSS를 막기(?)위해 동일한 도메인이 아니면 javascript문맥에 접근할수 없다.
- iframe이나 XHR요청은 이것의 적용을 받는다.
- document.domain 을 조정함으로써 동일한 도메인의 범위를 바꿀수 있다.
- wiki.zeropage.org 와 www.zeropage.org 를 동일한 도메인으로 취급하기 위해 document.domain을 zeropage.org로 설정할수 있다.
- 단, 이것을 하위 도메인. 앞에서 부터만 짜를수 있으며 붙이는 것은 허용되지 않는다.
- wiki.zeropage.org 와 www.zeropage.org 를 동일한 도메인으로 취급하기 위해 document.domain을 zeropage.org로 설정할수 있다.
3.5.1. Same Origin Policy를 극복하기 위한 방법 ¶
- proxy
- 다른 도메인에 접근하기 위해 동일 도메인 서버에 다른 페이지의 결과를 그대로 읽어와 내려주는 proxy를 설치한다.
- 부하가 많이 걸리고(요청마다 서버에 요청을 보내고 그걸 다시 내려주므로 네트워크 비용및 기타 비용이 증가)
- 인증 문제가 걸릴경우 보안이 약화될수 있다.
- 다른 도메인에 접근하기 위해 동일 도메인 서버에 다른 페이지의 결과를 그대로 읽어와 내려주는 proxy를 설치한다.
- Image
- 원래 same origin policy를 적용받지 않음으로 극복할수 있으나 바이너리므로 애시당초 우리가 쓸수 없다.
- 원래 same origin policy를 적용받지 않음으로 극복할수 있으나 바이너리므로 애시당초 우리가 쓸수 없다.
- Ifreame
- 내부에서 다른 자바스크립트 코드가 작동할수 있으나 다른 도메인이라면 접근이 불가하다.
- 플래쉬로 극복할수 있으나 클라이언트에 부하가 있고 자바스크립트 고유한 방식으로 해결하는것이 아니라서 좋지않다.
- 내부에서 다른 자바스크립트 코드가 작동할수 있으나 다른 도메인이라면 접근이 불가하다.
- Script tag
- Same origin policy를 적용받지 않고 자바스크립트를 불러올수 있으나 바로 실행이 되므로 다른 방식을 써야한다.
- script tag를 읽어 로딩이 끝나면 바로 실행 하기 때문에 여러개를 동시에 불러올경우 전역변수를 이용한 방식은 불가.
- 따라서 callback함수로 해결한다.
- 이때 내려줄 응답은 JSON과는 조금 다르다.
- Same origin policy를 적용받지 않고 자바스크립트를 불러올수 있으나 바로 실행이 되므로 다른 방식을 써야한다.
__callback({ "json" : "data"});
- 위와 같은 형식으로 내려줄경우 클라이언트(요청한 쪽)에서 _callback함수만 정의해두면 로딩이 끝남과 동시에 불리게 된다.
- 이 응답은 마치 JSON에 함수만 감싼형식이기 떄문에 JSON with Padding, JSONP라 부른다.
4.1. 종류 ¶
- Apache http server (httpd)
- 널리 쓰이고 있는 서버이고 가장 안전성이 뛰어나다.
- 널리 쓰이고 있는 서버이고 가장 안전성이 뛰어나다.
- IIS
- windows 에서 쓰이고 역시 안정성이 뛰어나고 GUI관리가 가능하다.
- windows 에서 쓰이고 역시 안정성이 뛰어나고 GUI관리가 가능하다.
- lighttpd
- event driven 방식의 서버
- event driven 방식의 서버
- nginx
- evnet driven 방식이며 nodejs 때문에 유명해졌다.
- evnet driven 방식이며 nodejs 때문에 유명해졌다.
4.2. 초기의 웹서버 ¶
- static 한 파일을 내려준다.
- 확장자를 파악해서 또는 파일의 헤더를 읽어 맞는 MIME TYPE를 헤더에 적어준다.
- static 한 파일을 업로드 받는다.
4.3.1. Unix File ¶
- Unix에서 File이라함은 다음을 모두 의미한다.
- 우리가 알고 있는 그 파일 (Process - Disk)
- 프로세스간 통신에 사용되는 Pipe
- 원격 머신에 존재하는 프로세스와 통신하는 Socket
- 기계장치와 통신하는 드라이버
- 우리가 알고 있는 그 파일 (Process - Disk)
- Unix는 C임에도 불구하고 강력한 추상화를 통해 뭔가를 읽고 쓰는 것으로 File을 만들었다.
- 마치 다음과 같은 느낌이다.
FILE f = new Pipe();
4.3.2. CGI ¶
- Common Gateway Interface
- Unix에서는 Pipe도 File이므로 static한 file 대신 Pipe를 쓰면 뭔가 다이나믹한게 되지않을까?
- 웹서버는 두고 거기에 다른 프로세스를 실행해서 그 실행 결과를 읽어들이자.
- 이때의 규약을 CGI라 부른다.
- standard Input에는 request body을 준다.
- standard Output에는 response body를 넘긴다.
- 그외에 기타 등등의 정보는 환경변수로 넘긴다.
- standard Input에는 request body을 준다.
- 표준은 RFC3875이며 IETF에서 관리한다.
- 매 실행시마다 새로운 프로세스를 생성하기때문에 메모리 소모가 심하고 disk접근이 많다.
4.4. 좀 괜찮은 웹 서버 ¶
- 새로운 프로세스를 만드는 비용을 줄여보자.
- 공용라이브러리는 프로세스가 실행될때 한번만 불러와진다.
- ISAPI(ISS) : DLL이용)
- mod (apache : so이용)
- ISAPI(ISS) : DLL이용)
- 현재 가장 많이 사용되는 방식
- process per request 방식이어서 fork 비용은 여전히 존재하고 요청마다 메모리를 많이 먹는다.
- 하지만 모듈을 요청마다 디스크에서 읽지 않기 때문에 조금은 나아졌다.
4.5.1. MPM ¶
- fork하는 부분을 module로 만들어 여러 방식을 선택할수 있다.
- fork 대신 Thread를 쓸수도 있고 운영체제별로 다른 방식을 쓸수도 있고 fork를 그대로 쓸수도 있다.
- 기존에 하던 방식은 pre-fork방식
- mpm-worker 방식은 프로세스 대신에 쓰레드를 쓰는 방식이다.
- 하나의 프로세스에 여러개의 쓰레드를 만들어 대기하다가 요청이 오면 하나씩 대응하는 방식
- thread per request 방식
- 다만 모듈이 Thread안전해야 한다.
- 하나의 프로세스에 여러개의 쓰레드를 만들어 대기하다가 요청이 오면 하나씩 대응하는 방식
- 여전히 CPU 자원을 많이 쓴다.
- Servlet도 같은 방식이다.
- context switch가 많이 일어나서 효율적이지 않고 평균 응답시간이 길어진다.
4.5.2. MPM + Queue ¶
- 큐를 만들어서 context switch비용을 줄여보려고 노력했다.
- connection을 큐에 쌓아두고 worker가 하나씩 꺼내어 처리
- 기존에도 하고 있는 방식이긴 하나 여전히 context switch는 일어난다.
4.6. 정말 미치도록 괜찮은 웹서버 ¶
- 한 커넥션 (=job)을 자세히 살펴보았더니...File I/O DB접근 등등 대기만 하는 시간이 길더라.
- 그럼이 I/O부분만 비동기로 처리합시다.
- 로직이 최소 단위로 나뉘어지고 시간이 오래 걸리는 작업은 비동기 처리.
- 순서는 존재해야하기 때문에 Event-driven의 탄생.
- 시간이 오래걸리는 작업은 비동기로 처리해야 하기 때문에 시간이 오래 걸리는 작업은 다른 프로세스로 넘기는것이 낫다.
- 그래서 fork의 악몽이 시작되는 줄 알았으나.
4.6.1. fast CGI ¶
- 그 프로세스를 demon으로 만듭시다!
- 이전에는 CGI들도 단독 실행이 가능했다!
- fast CGI는 단독실행 대신 deamon(service)로 실행된다.
- 한번 실행되어 대기하기 때문에 프로세스를 매 요청마다 다시 디스크에서 불러오지 않아도 된다.
- 통신방식은 socket
- 따라서 프로세스가 무엇이던 간에 소켓만 만드면 되므로 웹서버의 모듈갯수가 확연히 줄어든다.
- 소켓이므로 CGI가 다른 서버에 존재해도 된다.
- 로드밸런싱이 편해진다. (CGI가 다른데 있어도 되니까.)
- 각 CGI모듈이 따로 따로 있어도 된다.
- 이건 엄연히 다른 프로세스이므로 모듈이 쓰레드 안전 하지 않아도 된다!
- 따라서 프로세스가 무엇이던 간에 소켓만 만드면 되므로 웹서버의 모듈갯수가 확연히 줄어든다.
- 현존하는 가장 빠른 방식.
nginx + nodejs
더이상의자세한설명은생략한다.