서버

Node.js Event Loop

_soboro 2023. 7. 9. 06:38

들어가며

회사에서 Node.js를 레거시로 쓰고있다. 그러나 nodejs에 대해서는 매우 대강 알고 있었다. 그래서 이번 기회에 nodejs의 event loop에 공부하고 적어보려한다

 

 

Libuv

Node.js의 이벤트 루프는 Libuv를 기반으로 동작한다. https://nodejs.org/ko/docs/guides/dont-block-the-event-loop (노드 공식문서)  Libuv는 리눅스에서 epoll를 기반으로 동작한다. 결국은 node js의 이벤트 루프 동작방식을 이해하려면 epoll에 대해서 알아야 한다.

 

epoll 기반지식

epoll를 이해하려면 file descriptor, i/o select function에 대해서 알아야 한다.

 

File descriptor

file descriptor는 POSIX 기반 운영체제가 만든 파일을 구분하기 위한 일종의 숫자이다. 리눅스가 POSIX에 속한다는것만 기억하자.

서버 기술 얘기하는데 왜 파일이 나오는지 의문이 들 수 있다. 리눅스는 소켓도 파일로 본다.

 

i/o select function

file descriptor를 알면 이건 쉽다. file descriptor에 0, 1, 2 값이 있으면 특정 상태 값을 가진다고 생각하면 된다. 0은 파일 입력 1은 파일 출력 2는 파일 에러다. 예를들어, 커넥션을 맺기 위해 소켓이 차있으면 select 함수를 통해 어떻게 알 수 있을까? select 함수는 일단 감시하고자 하는 파일의 file descriptor를 자료구조에 집어 넣는다.

 

그리고 자료구조에 들어있는 file descriptor 값이 바뀌는지 감시한다. 만약에 바뀌면 소켓에 입력값이 들어온것이다. 이런 방식을 사용하면 I/O Blocking이 안생긴다. 예를들어, 비어있는 소켓을 들리면서 Blocking이 될 일이 없는것이다. 그리고 c10k 문제를 해결할 수 있다. 단일 스레드에서 여러 파일의 입출력을 동시에 처리할 수 있기 때문이다.

 

epoll

epoll은 select를 이해하면 쉽다. select는 자료구조에 file descriptor를 저장하고 감시한다. 그러나 이 방법은 O(n) 시간 복잡도를 가지는 문제가 있다. 이를 해결하기 위해 epoll를 통해서 자료구조에 fd를 넣는 과정을 없앤다. 대신 커널이 fd 세트를 관리한다.

 

그래서 event loop 동작 방식은?

커널에서 epoll 방식으로 클라이언트 요청이 들어오면 순차적으로 nodejs 서버에게 알려준다. 이렇게 알려주는걸 이벤트라고 하나보다.. 코드가 이해하기 편할 수 있으니 코드로도 간략하게 알아보자!

struct epoll_event_events[10];

while((int max = epoll_wait(eventfd, events, 10))) {
    for(n = 0; n < max; n++) {
        if(events[n].data.fd.fd == server) {
            //Server socket has connection!!
            int connection = accept(server);
            ev.events = EPOLLIN;
            ev.data.fd = connection;
            epoll_ctl(eventfd,EPOLL_CTL_ADD, connection, &ev);
        } else {
            //Connection socket has data
            char buf[4096];
            int size = read(connection, buffer, sizeof buf);
            write(connection, buffer, size);
        }
    }
}

 

결론

epoll를 이해했으면 Redis도 이해할 수 있다. nodejs 이벤트 루프와 흡사하다. 이래서 운영체제 공부하나보다 (한방에 여러개 이해 가능..)