우당탕탕 개발log
RallitLinkedin
  • About
  • Markup lanuage
    • HTML
  • 💻Programming Lanuage
    • Rust
      • Rust가 떠오른 이유 안전성, 쾌적한 사용 - 우아한 스터디 및 잇츠 스터디
      • Chater 06. 오류 처리
      • Chater 12. 연산자 오버로딩
      • 재미 있는 리포지토리
    • 자바
      • 문법 정리
        • 자바 문법 한눈에 정리 1편
        • 자바 문법 한눈에 정리 2편
        • NullPointException에 대해 알아보자.
        • Call by value vs Call by Reference과 기본형과 참조형
        • StringBuffer vs String vs StringBuilder
      • 김영한님 자바 강의 모음
        • 자바 입문 강의 정리
      • 이펙티브 자바
        • 2장 : 객체 생성과 파괴
          • item 01. 생성자를 대신 정적 팩토리 메서드를 고려하라
          • item 02. 생성자에 매개변수가 많다면 빌더를 고려하라
          • item 03 : private 생성자나 열거 타입으로 싱글턴임을 보증하라.
          • item 04 : 인스턴스화를 막으려거든 private 생성자를 사용하라
          • item 05 : 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
          • item 06 : 불필요한 객체 생성을 피하라
          • item 07 : 다 쓴 객체 참조를 해제하라
          • item 08 : finalizer와 cleaner 사용을 피하라
          • item 09 : try-finally보다는 tiy-with-resources를 사용하라
        • 3장 : 모든 객체의 공통 메서드
          • item10 : equals는 일반 규약을 지켜 재정의하라
          • item 11 : equals를 재정의하려거든 hashCode도 재정의하라
          • item 12 : toString을 항상 재정의하라
          • item 13 : clone 재정의는 주의해서 진행해라
          • item 14 : Comparable 을 구현할지 고려하라
        • 4장 : 클래스와 인터페이스
          • item 15 : 클래스와 멤버의 접근 권한을 최소화하라
          • item 16 : public 클래스에서는 public 필드가 아닌 접 근자 메서드를 사용하라
          • item 17 : 변경 가능성을 최소화하라
          • item 18 : 상속보다는 컴포지션을 사용하라
          • item 19 : 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라
          • item 20 : 추상클래스보다는 인터페이스를 고려하라
          • item 21 : 인터페이스는 구현하는 쪽을 생각해 설계하라
          • item 22 : 인터페이스는 타입을 정의하는 용도로만 사용하라
          • item 23 : 태그 달린 클래스보다는 클래스 계층구조를 활용하라
          • item 24 : 멤버 클래스는 되도록 static으로 만들라
          • item 25 : 톱레벨 클래스는 한 파일에 하나만 담으라
          • item 18 - item 19의 확장 : 🤔 자바 기초 배울 때 앞쪽에 나오는 상속 왜 현업에서는 잘 안쓴다고 하는 걸까? (feat. 코틀린에서 상속은?)
        • 5장 : 제네릭
          • item 26 : 로 타입은 사용하지 말라
          • 와일드 카드에 대한 정리
          • item 27 : 비검사 경고를 제거하라
          • 제네릭 배열에 대한 정리
          • item 28 : 배열보다는 리스트를 사용하라
          • item 29 : 이왕이면 제네릭 타입으로 만들라.
          • item 30 : 이왕이면 제네릭 메서드로 만들라
          • item 31 : 한정적 와일드카드를 사용해 API 유연성을 높이라
          • 도우미 메서드
          • item 32 : 제네릭과 가변인수를 함께 쓸 때는 신중하라
          • item 33 : 타입 안전 이종 컨테이너를 고려하라
        • 6장 : 열거 타입과 애너테이션
          • item 34 : int 상수 대신 열거 타입을 사용하라
          • item 35 : ordinal 메서드 대신 인스턴스 필드를 사용하라
          • item 36 : 비트 필드 대신 EnumSet을 사용하라
          • item 37 : ordinal 인덱싱 대신 EnumMap을 사용하라
          • item 38 : 확장할 수 있는 열거 타입이 필요하면 인터페이스를 사용하라
          • item 39 : 명명 패턴보다 애너테이션을 사용하라
          • item 40 : @Override 애너테이션을 일관되게 사용하라
          • item 41 : 정의하려는 것이 타입이라면 마커 인터페이스를 사용하라
          • 보충 : 리플렉션과 애너테이션
        • 7장 : 람다와 스트림
          • item 42 : 익명 클래스보다는 람다를 사용하라
          • item 43 : 람다보다는 메서드 참조를 사용하라
          • item 44 : 표준 함수형 인터페이스를 사용하라
          • item 45 : 스트림은 주의해서 사용하라
          • item 46 : 스트림에서는 부작용 없는 함수를 사용하라
          • item 47 : 반환타입으로는 스트림보다는 컬렉션이 낫다.
          • item 48 : 스트림 병렬화는 주의해서 적용하라
        • 8장 : 메서드
          • item 49 : 매개변수가 유효한지 검사하라
          • item 50 : 적시에 방어적 복사본을 만들라
          • item 51 : 메서드 시그니처를 신중히 설계하라
          • item 52 : 다중정의는 신중히 사용하라
          • item 53 : 가변인수는 신중히 사용하라.
          • item 54 : null이 아닌, 빈 컬렉션이나 배열을 반환하라
          • item 55 : 옵셔널 반환은 신중히 하라
          • item 56 : 공개된 API 요소에는 항상 문서화 주석을 작성하라
        • 10장 : 예외
          • item 69 : 예외는 진짜 예외 상황에만 사용하라
          • item 70 : 복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라
          • item 71 : 필요 없는 검사 예외 사용은 피하라
          • item 72 : 표준 예외를 사용하라
          • item 73 : 주상화 수준에 맞는 예외를 던지라
          • item 74 : 메서드가 던지는 모든 예외를 문서화하라
          • item 75 : 예외의 상세 메시지에 실패 관련 정보를 담으라
          • item 76 : 가능한 한 실패 원자적으로 만들라
          • item 77 : 예외를 무시하지 말라
        • 11장 : 동시성
          • item 78 : 공유 중인 가변 데이터는 동기화해 사용하라
          • item 79 : 과도한 동기화는 피하라
          • item 80 : 스레드보다는 실행자, 태스크, 스트림을 애용하라.
          • item 81 : wait와 notify보다는 동시성 유틸리티를 애용하라
          • item 82 : 스레드의 안정성 수준을 문서화하라
          • item 83 : 지연 초기화는 신중히 사용하라
          • item 84 : 프로그램의 동작을 스레드 스케줄러 에 기대지 말라
        • 스터디에서 알아가는 것
      • 모던 자바 인 액션
        • chaper 1. 자바 8, 9, 10, 11 : 무슨 일이 일어나고 있는가?
      • 그 외 용어 정리
        • 불변 클래스
        • 정적 멤버 클래스
        • 무상태(stateless) 객체란
        • 콜백(callback)
        • @PreDestroy 어노테이션
        • AutoCloseable 인터페이스
        • Object 클래스에 대한 정리
        • 인스턴스 통제 클래스
        • Transactional
        • AssertionError
        • 스레드 안전성
        • 어댑터란?
    • Python
      • 파이썬 프롤로그
      • 정보처리기사 실기를 위한 파이썬 정리(약간의 접수 후기를 곁드린)
    • Javascript
      • 알아가는 것들
  • 🍓Spring
    • 기본 지식
      • MVC
      • 스프링의 핵심은 무엇인가
      • 스프링 빈을 등록하는 두 가지 방법(@Component, @Bean)
      • 의존성 주입 3가지 방법 - (생성자 주입, Field 주입, Setter 주입)
      • 스프링부트 동작원리
      • JPA란 무엇인가요
      • messageConverter가 무엇인가요
      • 어노테이션 정리 하기
    • spring 관련 책
      • 사람을 사랑한 기술
    • spring 관련 강의
      • 스프링 부트 서버 개발
        • 스프링 부트 서버 개발 프롤로그
  • 🔭CS
    • 모르는 용어 그때 그때 정리하기
    • CS 관련 BOOKMARK
    • 한권으로 읽는 컴퓨터 구조와 프로그래밍
      • 들어가며
      • 1장 : 컴퓨터 내부의 언어 체계
      • 2장 : 전자 회로의 조합 논리
      • 3장 : 메모리와 디스크의 핵심: 순차 논리
      • 4장 : 컴퓨터 내부 구조
      • 3장 - 4장 DeepDive 5개만 발표용
      • 프로그래밍 언어 처리 – 코드가 컴퓨터에서 실행되기까지의 여정
      • 웹 브라우저
      • 🔟애플리케이션 프로그래밍과 시스템 프로그래밍
      • deepdive 지식 - 1장
      • DeepDive 지식 : 2장
      • 컴퓨터 구조 9-10장 DeepDive 지식
    • Network
      • 네트워크 공부하기 프롤로그
      • Story 01. HTTP 리퀘스트 메세지를 작성한다.
    • 운영체제
      • 프로세스, 스레드, 멀티태스킹, 멀티스레딩, 멀티프로세싱, 멀티프로그래밍과 스레드를 많이 쓸수록 항상 성능이 좋을까..?
      • 비동기에서 각 맥락에 따른 의미를 설명
      • 컴퓨터 구조와 운영체제를 알아야 하는 이유 - 운영체제 개념
      • 메모리와 메모리 관리
      • Call by value vs Call by Reference + 기본형과 참조형
    • Linux
      • 그림으로 배우는 리눅스 구조
        • 1장 리눅스 개요
        • 2장 : 프로세스 관리(기초편)
        • 6장 : 장치접근
        • 7장 : 파일시스템
    • 보안
      • 우리나라 보안의 실태
    • HTTP 웹 지식
      • 인터넷 네트워크
      • URI와 웹 브라우저의 요청 흐름
      • HTTP의 기본
      • HTTP 메서드
      • HTTP 메서드 활용
      • HTTP 상태코드
      • HTTP 헤더 1 - 일반 헤더
      • HTTP 헤더 2 - 캐시와 조건부 요청
      • 응답 206 partial content
    • SEVER
      • 톰켓이란 무엇인가
    • 그 외
      • 멀티캠퍼스에서 배운 cs 지식
  • Algorithm-DataStructure
    • Algorithm 관련 bookmark
    • 자료구조
      • Big O
      • 연결 리스트
      • BigInteger에 대한 정리
      • 배열(array)
      • 스택과 큐
      • Array vs ArrayList vs LinkedList 차이
      • 재귀함수
      • 트리
      • 우선순위 큐와 힙의 차이
      • 값이 중복되는 객체를 제거할 목적으로 hash set을 쓰려면
    • Algorithm
      • 그리디
      • 구현
      • 그래프 알고리즘
      • 버블 정렬, 삽입 정렬, 선택 정렬
      • 동적 계획법과 분할정복
  • 🐋backend
    • database
      • 팀 프로젝트 시 데이터베이스는 어떻게..? mysql과 h2, jpa와 mybatis
  • ⛏️CI-CD
    • github
      • github 자주 쓰는 명령어
      • github.io 블로그 만들기
        • Jekyll Chirpy 테마를 연동 및 Github 블로그 만들기 1탄 - 로컬 테스트 및 확인
        • Jekyll Chirpy 테마를 연동 및 Github 블로그 만들기 2탄 - fork한 것 mirror 해오기
        • Jekyll Chirpy 테마를 연동 및 Github 블로그 만들기 3탄 - github에 도메인 적용
        • Jekyll Chirpy 테마를 연동 및 Github 블로그 만들기 4탄 - 세부사항
      • 팀프로젝트때 알아낸 github 지식
      • Git에서 알게 된 지식
    • Github Action
      • Github Action 링크 모음
      • OAuth 앱에 대한 범위 및 gitbook과 github.io를 자동화를 위한 작업 1탄
      • gitbook과 github.io를 자동화를 위한 gitaction 연동 - 워크플로우 작성과 문제
    • docker
    • SVN
  • 📔Book
    • 에러가 무서워지지 않는 책
      • 1장 에러가 왜 무서울까?
      • 2장 에러를 잘 읽는 방법
      • 3장 효율적으로 에러의 원인 찾기
    • 요즘 개발자 요약 및 신입 개발자의 방향성 찾기(feat. 커피챗)
    • 필독 개발자 온보딩 가이드
      • 필독 개발자 온보딩 가이드 1장
      • 필독 개발자 온보딩 가이드 2장
      • 필독 개발자 온보딩 가이드 3장
      • 필독 개발자 온보딩 가이드 4장
        • 개발자 온보딩 가이드 4장 -(1)
        • 필독 개발자 온보딩 가이드 4장 -(2)
        • 개발자 온보딩 가이드 4장 - (3)
    • 객체지향의 오해와 사실
      • 1장 협력하는 객체들의 공동체
  • 🌸회고록
    • 2023년
      • 2023년 7월 회고 겸 8월 목표와 생각의 전환
      • 2023년 8월 회고 및 9월 목표
      • 2023년 9월, 10월 회고글 및 11월 목표
      • 2023년 11월 회고록
      • 변화 Change의 2023 늦은 회고 진화 level up 2024
    • 2024년
      • 쌩 신입개발자 취준기 회고+ 1주일 출근 겸 1월 회고
      • 중소 신입 개발자 한 달 출근 겸 2024년 2월 회고 ( feat. 국비 비전공자 친구 취업소식)
      • 2024년 3월 회고록 및 4월 계획
      • 2024년 4월, 5월 중간 회고록 및 5월, 6월 목표
      • 2024년 6월 회고록
      • 2024년 7월 회고록
      • 2024년 8월 회고록 - 새로운 인연들, 커피챗, 지침, 불안에 몸부림 중
      • 다양한 경험을 쌓아가며, 자바 카페 스터디, 튜사콘, 글또와 함께 하는 나를 되돌아본 2024년 9월 회고록
      • 글또 시작하고 스터디 마무리 지은 2024년 10월 회고록 (티스토리도 시작😶, 약간 당황한 일...문자로 질문?)
  • 🌟TIP, bookmark, 유용한 정보 모음
    • Bookmark
    • 블로그 테마 모아보기(tistory, github.io)
    • 강연 및 컨퍼런스 후기
      • 점핏 강연 센스있는 BE 되기
    • 커피챗
      • 커피챗이란
      • 인프런 멘토 우연님 후기이자 방향성 - 초보개발자의 고민과 방안
    • 잘 정리된 tech blog
  • 👓트러블슈팅
    • 로그 파일 관련
  • ⚡그 외
    • 자격증
      • 정보처리기사
        • 필기
          • 1과목
            • 1. 소프트웨어 생명 주기 SDLC(Software Development Life Cycle)
            • 2. 스크럼(Scrum) 기법
            • 3. XP(eXtreme Programming : 익스트림) 기법과 린(Lean)
        • 실기
        • 대학생, 취준생, 신입개발자의 과정과 함께한 정보처리기사 4트 2024년 1회 실기 후기
      • SQLD
      • ADsP
    • 템플릿 나눔
      • 노션 팀 스터디 템플릿 공유
      • 팀프로젝트 관련 노션 템플릿 공유
    • 신입개발자 > 주니어 개발자의 취업과 이직, 업무 이야기
      • 신입개발자의 중소, SI 취준기 및 성장
        • 애매한 신입개발자의 중소, si 취준기(feat. 이력서 및 포트폴리오 작성법, 면접 후기) - 간추린 버전
        • 애매한 쌩신입개발자 중소, si 취준기 1탄 이력서 및 포트폴리오 작성법 및 후기
        • 애매한 쌩신입개발자 중소, si 취준기 2탄 면접 후기, 질문, 취업 관련 사이트 모음, 결과
        • 주니어가 첫 회사 다니면서 깨달은(?깨달아가는) 20가지
    • 살아가는 이야기
      • 대학 입학 - 취업 전까지의 아르바이트 회고
    • 얻은 지식 모음
      • 트위터를 통한 모르는 지식을 얻어가기
    • 2025년도에 해보고 싶거나 해야하는 것들 간단 정리
Powered by GitBook
On this page
  • 🧠 1. 브라우저는 어떻게 ‘작은 운영체제’가 되었는가 – 이벤트 루프와 비동기 처리의 탄생
  • 1) 📜 이야기는 이렇게 시작됩니다 – 클릭 한 번으로 바뀌는 세계
  • 2) 🧩 브라우저 내부는 어떻게 생겼을까?
  • 3) 🔁 이벤트 루프란 무엇인가?
  • 4) 🛠️ 이벤트 루프는 브라우저 안에서 어떻게 동작할까?
  • 5) 🌍 브라우저는 왜 ‘작은 운영체제’인가?
  • 6) ⚙️ 개발자의 관점 – 비동기 프로그래밍이란?
  • 7) 📦 Node.js의 등장은 어떻게 이벤트 루프를 확장했는가?
  • 8) 🧩 실시간성과 이벤트 루프 – 메타버스, 게임, 채팅 앱
  • 9) 🧮 브라우저 성능을 높이기 위한 루프 최적화 기법
  • 🔚 마무리 요약
  • 2. 웹 프론트엔드의 역사와 진화 좀 더 자세히 알아보기
  • 1) 검색 엔진과 포털, e-커머스의 발전
  • 2) Internet Explorer와 웹의 상업화 (1995~2004)
  • 3) Web 2.0과 RIA (Rich Web Application)의 탄생 - Flash의 등장과 웹 애니메이션의 진화
  • 5) 구글의 도전: 웹을 OS로!
  • 6) Ajax의 대중화와 JS의 재발견
  • 7) 웹 표준, 접근성, 시맨틱, 크로스브라우징의 등장
  • 8) jQuery의 등장과 프론트엔드 재정의
  • 9) 크롬 브라우저와 V8 엔진의 탄생
  • 10) Node.js와 npm의 등장
  • 11) 페이스북과 React의 등장
  • 12) 디지털 전환과 하이브리드 앱 시대
  • ✅ 요약: 웹 프론트엔드는 이제 하나의 독립 생태계
  • 3. V8에 대해 좀 더 자세히 알아보자.
  • 1) 일단, Node.js란?
  • 2) V8 JavaScript 엔진의 작동 원리와 최적화 과정
  • 🔄 전체 흐름 요약
Edit on GitHub
  1. CS
  2. 한권으로 읽는 컴퓨터 구조와 프로그래밍

컴퓨터 구조 9-10장 DeepDive 지식

더 깊게 정리하고 싶은 내용 정리하기

🧠 1. 브라우저는 어떻게 ‘작은 운영체제’가 되었는가 – 이벤트 루프와 비동기 처리의 탄생

1) 📜 이야기는 이렇게 시작됩니다 – 클릭 한 번으로 바뀌는 세계

여러분이 웹페이지에서 버튼을 클릭하면 어떤 일이 벌어질까요?

단순히 글씨가 바뀌거나, 이미지가 나타나는 걸로 보일 수 있지만, 이 작디작은 변화 하나를 위해 브라우저 내부에서는 어마어마한 일이 벌어집니다. HTML이 펼쳐지고, JavaScript가 실행되고, DOM이 조작되고, 스타일이 다시 계산되고, 레이아웃이 조정되며, 마지막에 다시 그려지는 과정을 거칩니다. 그런데 여기서 가장 핵심적인 건 뭘까요?

바로 브라우저는 사용자의 요청을 "기다리고", 응답하는 "이벤트 기반 구조"를 갖춘 일종의 작은 운영체제처럼 행동한다는 사실입니다.

2) 🧩 브라우저 내부는 어떻게 생겼을까?

일단 브라우저는 단순히 웹페이지를 보여주는 도구가 아닙니다. 다음과 같은 요소들이 합쳐진 거대한 프로그램입니다:

구성 요소
설명

HTML 파서

마크업 언어를 파싱해서 DOM 트리를 구성

CSS 파서

스타일을 파싱해서 렌더 트리 생성

JavaScript 엔진 (예: V8)

JS 코드를 해석하고 실행

렌더링 엔진

DOM, CSSOM을 기반으로 실제 레이아웃과 픽셀 출력

네트워킹 스택

요청과 응답을 처리하는 통신 모듈

이벤트 루프

사용자 인터랙션과 스케줄된 작업을 처리하는 구조

이 모든 것을 조화롭게 연결하는 핵심은 무엇일까요?

바로 이벤트 루프(Event Loop)입니다.

3) 🔁 이벤트 루프란 무엇인가?

브라우저가 한 번에 하나의 작업만 할 수 있는 단일 스레드(single-threaded) 환경이라면, 우리는 어떻게 동시에 여러 가지 일을 할 수 있을까요?

바로 "이벤트 루프" 덕분입니다.

브라우저의 동작 타이밍을 제어하는 관리자라고 보면 됩니다.

이벤트 루프의 동작 과정을 간단히 살펴보자면, 자바스크립트의 setTimeout이나 fetch 와 같은 비동기 자바스크립트 코드를 브라우저 Web APIs에게 맡기고, 백그라운드 작업이 끝난 결과를 콜백 함수 형태로 큐(Callback Queue)에 넣고 처리 준비가 되면 호출 스택(Call Stack)에 넣어 마무리 작업을 진행합니다.

이벤트 루프를 이용한 프로그램 방식을 이벤트 기반(Event Driven) 프로그래밍이라고 합니다.

이벤트 기반 프로그래밍은 프로그램의 흐름이 이벤트에 의해 결정되는 방식이에요. 예를 들어 사용자의 클릭이나 키보드 입력과 같은 이벤트가 발생하면, 그에 맞는 콜백 함수가 실행하는데. 대표적으로 자바스크립트의 addEventListener(이벤트명, 콜백함수) 입니다.

이벤트 기반 프로그래밍은 비동기 작업을 쉽게 처리할 수 있고, 멀티 스레드 언어에 비해 단순하고 직관적인 코드 작성을 가능하게 하며, 브라우저와 같은 환경에서도 안정적인 실행을 가능하게 하여 사용자와의 상호작용을 높일 수 있습니다.

따라서 이를 이해하고 적절한 방식으로 비동기 작업을 처리하는 것은, 자바스크립트를 이용한 웹 애플리케이션 개발에 있어서 매우 중요합니다.

이벤트 루프를 알기 전 자바 스크립트의 특징을 알아보자

자바스크립트는 HTML에 종속되어있는 언어입니다. HTML 조작과 변경을 위해 사용합니다.

💡 HTML은 웹페이지에 글쓰고, 그림넣는 언어이다. 특징 ) 안 움직임, 글 넣고 그림 넣고 끝

정적 언어인 HTML을 조작해서 웹페이지를 다이나믹하게 바꿔주는 기능을 하는게 자바스크립트입니다.

JavaScript는 싱글쓰레드 언어라고 많이 알려져 있습니다. 싱글쓰레드라고 한다면 여러 개의 작업이 있더라도 한 번에 하나의 작업만 수행할 수 있습니다. 하지만 JavaScript를 사용해 보면 멀티쓰레드처럼 동시에 여러 작업을 수행할 수 있다는 것을 알 수 있습니다.

그렇다면 JavaScript는 정말 싱글쓰레드 언어가 맞을까요?

맞습니다. 그 이유는 JavaScript의 메인쓰레드인 이벤트 루프가 싱글 쓰레드이기 때문입니다. 반면 Java 나 Python은 멀티 스레드를 지원하여 원하는 코드 로직을 동시에 수행 시키는 멀티 작업이 가능합니다.

하지만 JavaScript 이벤트 루프만 독립적으로 실행되는것이 아닌 웹 브라우저나 NodeJS 같은 멀티쓰레드 환경에서 실행되고 이를 적절하게 사용함으로써 멀티쓰레드처럼 사용이 가능한 것입니다.(다만 Web worker 최신 기술을 통해 자바스크립트도 멀티 스레드 구현이 가능해졌습니다. )

🤔HTML은 자바스크립트가 조작한다면 자바스크립트 해석은 누가할까요?

바로 브라우저입니다. 브라우저에는 자바스크립트 해석 엔진이 있습니다. 기존에는 자바스크립트를 인터넷 브라우저 위에서만 실행할 수 있었습니다. 그러나 2008년에 구글이 V8 엔진을 사용하여 크롬을 출시했습니다. V8 엔진은 엄청 빨랐고, 오픈 소스로 코드도 공개되었습니다. V8 엔진이 너무 뛰어나서 기능을 좀 더 더해서 V8 엔진 기반에 노드 프로젝트를 시작했고, Node.js(V8)이 등장했습니다. Node.js는 브라우저 내에서 말고도 다른 환경에서 자바스크립트를 사용할 수 있게 해줍니다.

따라서 Node.js는 JavaScript 실행 환경(=런타임)입니다. (V8과 Node.js에 대한 설명은 뒤에서)

웹 애플리케이션에서는 네트워크 요청이나 이벤트 처리, 타이머와 같은 작업을 멀티로 처리해야 하는 경우가 많은데.. 만일 싱글 스레드로 브라우저 동작이 한번에 하나씩 수행하게 되면, 우리가 파일을 다운로드 받을 동안 브라우저는 파일을 다 받을 때까지 웹서핑도 못하고 멈춰 대기해야 할 것입니다.

따라서 파일 다운, 네트워크 요청, 타이머, 애니메이션 이러한 오래 걸리고 반복적인 작업들은 자바스크립트 엔진이 아닌 브라우저 내부의 멀티 스레드인 Web APIs에서 비동기 + 논블로킹으로 처리됩니다.

비동기 + 논블로킹(Async + Non blocking)Visit Website는 메인 스레드가 작업을 다른 곳에 요청하여 대신 실행하고, 그 작업이 완료되면 이벤트나 콜백 함수를 받아 결과를 실행하는 방식을 말합니다.

비동기로 동작하는 핵심요소는 자바스크립트 언어가 아니라 브라우저라는 소프트웨어가 가지고 있다고 보면 됩니다. Node.js 에서는 libuv 내장 라이브러리가 처리합니다.

이벤트 루프는 브라우저 내부의 태스크 스케줄러 역할을 합니다. 비동기적인 요청과 사용자 인터랙션을 큐에 넣어 하나씩 처리하며, 이로써 동시성을 흉내낼 수 있게 해줍니다.

이벤트 루프는 JavaScript의 실행 컨텍스트와 콜백 큐, 마이크로태스크 큐, 태스크 큐를 조율합니다.

먼저, JavaScript 엔진이란?

자바스크립트(JavaScript)는 그 자체로는 "명령어의 나열일 뿐"입니다. 이걸 실제로 실행시켜주는 게 바로 JavaScript 엔진입니다.

JavaScript 엔진은 코드를 이해하고 실행을 도와주는 역할을 합니다.

💡 마치 "배우가 대본을 해석하고 연기하는 것"처럼, 엔진은 JS 코드를 해석하고 실행해줍니다.

브라우저는 각자 자신만의 JS 엔진을 가지고 있는데요:

  • Chrome / Edge → V8 (구글 제작)

  • Firefox → SpiderMonkey

  • Safari → JavaScriptCore (또는 Nitro)

그중에서도 가장 유명한 엔진이 바로 V8 엔진입니다. 구글이 만든 이 엔진은 빠른 실행 속도와 효율적인 메모리 처리로 유명하죠.

📦 자바스크립트 엔진 내부 구조

엔진은 코드를 실행할 때 내부적으로 두 개의 핵심 구조를 사용합니다:

1. 🧠 Memory Heap (메모리 힙)

  • 말 그대로 "어디에 무엇을 저장해둘지 결정하는 공간"입니다.

  • 자바스크립트에서 변수, 객체, 배열 등을 선언하면 이곳에 저장됩니다.

  • 동적으로 메모리를 할당하는 공간이며, 크기가 유동적입니다.

📦 예시: const cat = { name: "복이", age: 3 } → 이 객체는 메모리 힙에 저장됩니다.

2. 🧾 Call Stack (호출 스택)

  • 함수 호출이 일어날 때마다, 실행 순서를 기억하는 작업 목록이라고 볼 수 있어요.

  • 후입선출 (LIFO) 구조로 작동하며, 가장 나중에 호출된 함수가 먼저 실행되고 끝나면 그다음 함수로 넘어갑니다.

📞 예시:

function hello() {
  console.log("안녕!");
}
hello();

→ hello()가 호출되면 Call Stack에 쌓이고, 실행 후 제거됩니다.

둘의 관계는?

  • Memory Heap은 "무엇을 저장할까?"

  • Call Stack은 "무엇을 언제 실행할까?"

예를 들어, 여러분이 add(2, 3) 같은 함수를 호출하면:

  1. Call Stack에 add()가 올라가고

  2. 내부 연산을 위해 필요한 변수는 Memory Heap에 저장됩니다

  3. 함수 실행이 끝나면 Call Stack에서 제거되고, 메모리도 정리됩니다 (Garbage Collection)

🔥 부가 설명: 왜 이걸 알아야 할까요?

이 구조를 알면 다음과 같은 자바스크립트 동작을 이해하기 쉬워집니다:

  • 왜 함수 안에서 선언한 변수는 밖에서 접근할 수 없을까? (→ 스코프 + 스택 구조 이해)

  • 왜 무한 재귀 호출을 하면 Maximum call stack size exceeded 에러가 뜰까?

  • 메모리 누수는 왜 발생할까?

시각적 정리

┌───────────────┐
│  Memory Heap │ ← { name: '복이' }
└───────────────┘

┌───────────────┐
│   Call Stack  │ ← hello()
│               │ ← main()
└───────────────┘

Memory Heap & Call Stack

먼저 Memory Heap에 있는 사용자가 작성한 코드들은 Call Stack에서 Stack 방식으로 쌓이며 코드를 실행하게 되는데 이때 동기 함수들은 그대로 실행하게 되고 비동기 함수들은 Web API로 처리하게 되며 일을 분배합니다.

  • Stack : 후입선출(LIFO)로 마지막에 들어간 것이 먼저 나가는 방식

브라우저 내부 구성도

브라우저 전체 구성도를 보면 위와 같다.

구성 요소
역할

Call Stack

현재 실행 중인 코드의 함수 호출이 쌓이는 공간 (LIFO 구조)

Memory Heap

동적으로 생성된 객체, 함수 등 데이터가 저장되는 공간

Web APIs

브라우저가 제공하는 비동기 API 집합 (AJAX, Timer 등)

Callback Queue

완료된 비동기 작업의 콜백들이 대기하는 큐 (setTimeout 등)

Microtask Queue

Promise와 같은 고우선 비동기 작업의 콜백 대기 공간

Event Table

이벤트와 콜백의 관계를 관리하는 ‘주소록’ 역할

Event Loop

Call Stack이 비어 있는지 감시 → Queue에서 콜백 실행

Web API – 브라우저의 비동기 도우미들

Javscript를 사용하면서 우리가 많이 사용하는 API 들은 사실 JavaScript에서 지원하는 것이 아닌 웹 브라우저에서 제공하는 API로 DOM ,AJAX, Timeout 등이 있습니다.

자바스크립트 자체에는 비동기 기능이 없음 → 브라우저가 비동기 동작을 Web API로 제공함

Call Stack에서 실행된 비동기 함수는 Web API에서 처리를 하게 되고 그동안에 Call Stack은 나머지 동기 함수들을 처리하게 됩니다.

Web API는 비동기 함수들을 처리하며 작업이 완료된 비동기 함수들을 Callback Queue로 넘겨주게 됩니다.

주요 예시

API 종류
설명
동기/비동기

DOM API

요소 선택, 조작 등

동기

Timer API

setTimeout, setInterval

비동기

XHR / Fetch

서버와 비동기 통신

비동기

Canvas API

그래픽 렌더링

동기

Geolocation

위치 정보 제공

비동기

Console API

로그 출력

동기

구조 상 비동기 Web API는 별도의 스레드로 작동 → 메인 스레드를 블로킹하지 않음

Callback Queue

  • Web API가 작업을 마치면 콜백을 Queue에 넣음

  • 이 Queue는 Event Loop가 Call Stack이 비면 하나씩 꺼내 실행함

Callback Queue는 비동기 함수들을 보관하는 장소로 Event Loop에서 비동기 함수를 꺼내기 전까지는 계속 Queue방식으로 보관하게 됩니다.

  • Queue : 선입선출(FIFO)로 먼저 들어간 것이 먼저 나가는 방식

Event Loop

Event Loop는 Call Stack과 Callback Queue를 상태를 계속 감시하며 Call Stack에 함수들이 존재하지 않는다면 Callback Queue에 있는 비동기 함수들을 Call Stack에 밀어 넣게 됩니다. 그 후 Call Stack에서 비동기 함수를 실행시키게 됩니다.

Microtask Queue

  • 비동기 중에서도 우선순위가 높은 큐

  • Promise.then, process.nextTick, MutationObserver 등이 여기에 들어감

  • Call Stack이 비자마자 가장 먼저 실행됨

Promise가 setTimeout보다 먼저 실행되는 이유는 이 구조 때문입니다

예시로 살펴보는 이벤트 루프

console.log('A');

setTimeout(() => {
  console.log('B');
}, 0);

Promise.resolve().then(() => {
  console.log('C');
});

console.log('D');

출력 순서는 어떻게 될까요?

A
D
C
B

왜 이런 순서로 출력될까요?

단계
설명

A, D

동기 실행 – 콜 스택에서 바로 실행

C

마이크로태스크 큐 → 이벤트 루프는 스택이 비면 우선 처리

B

setTimeout의 콜백 → 태스크 큐에 들어가고, 마이크로태스크 다음에 실행

결국, Event Loop은 전체를 연결하는 조율자입니다.

  • Call Stack이 비었는지 계속 감시

  • Stack이 비면 Microtask Queue → Callback Queue 순서로 콜백 실행

  • 매 프레임마다 한 번씩 돌면서 애플리케이션을 부드럽게 실행

4) 🛠️ 이벤트 루프는 브라우저 안에서 어떻게 동작할까?

이벤트 루프의 동작 순서를 간단히 그림으로 표현해보면 다음과 같습니다:

1. 콜 스택 실행
2. 마이크로태스크 큐 처리
3. 렌더링 단계
4. 태스크 큐에서 콜백 처리 (setTimeout, 이벤트 등)
5. 다시 반복

이 구조는 CPU 스케줄러와 유사하게 작동하며, 태스크 간 우선순위와 대기열을 관리합니다.

이를 통해 브라우저는 다음과 같은 일을 효율적으로 처리할 수 있습니다:

  • 마우스 클릭 이벤트

  • setTimeout / setInterval

  • XMLHttpRequest / fetch

  • DOM 조작 / 렌더링

  • Promise.then

비유: "자바스크립트의 오케스트라"

역할
구성 요소
설명

지휘자

Event Loop

큐와 스택을 관리하며 타이밍을 조율함

무대 위 배우

Call Stack

현재 실행되는 함수들

대기실

Task Queue, Microtask Queue

순서에 따라 무대에 오를 콜백들

조명/효과팀

Web APIs

타이머, 네트워크, 이벤트를 처리하는 브라우저 기능들

브라우저 성능 최적화를 위한 팁

최적화 항목
설명

Promise를 활용해 순차 실행

Microtask로 빠르게 처리 가능

requestAnimationFrame

애니메이션 최적 타이밍에 실행됨

setTimeout(..., 0) 남용 자제

Task Queue는 한 프레임 지연됨

대량의 DOM 조작은 DocumentFragment 사용

Stack이 과도하게 쌓이지 않도록 조절

  • 자바스크립트는 싱글 스레드지만, 브라우저는 멀티 스레드 구조

  • Web API, Event Loop, Queue가 협업하여 비동기 코드를 처리

  • Microtask가 Task보다 먼저 실행된다는 점은 반드시 기억!

5) 🌍 브라우저는 왜 ‘작은 운영체제’인가?

운영체제는 다음과 같은 역할을 합니다:

운영체제 기능
브라우저의 대응

I/O 처리

네트워크 요청 처리 (XHR, fetch)

이벤트 관리

클릭/입력 이벤트 처리

메모리 관리

가비지 컬렉션 (GC), 힙/스택 구조

프로세스/스레드 스케줄링

이벤트 루프와 태스크 큐

사용자 인터페이스 처리

DOM 렌더링과 뷰 업데이트

즉, 브라우저는 시스템 콜 없이도, 자바스크립트 단 하나만으로 사용자의 요구에 반응하고, 계산하고, 렌더링하고, 응답합니다. 그 자체로 고도로 복잡한 운영체제의 축소판이라 볼 수 있습니다.

6) ⚙️ 개발자의 관점 – 비동기 프로그래밍이란?

과거에는 이런 구조를 직접 다뤄야 했습니다. 콜백 헬(callback hell)이 그 대표적인 예입니다:

doSomething(function(result) {
  doSomethingElse(result, function(next) {
    doMore(next, function(finalResult) {
      console.log(finalResult);
    });
  });
});

그러다 등장한 것이 Promise와 async/await입니다.

async/await를 통한 간단한 구조

async function run() {
  const result = await doSomething();
  const next = await doSomethingElse(result);
  console.log(next);
}

이 문법 덕분에 이벤트 루프를 직접 관리하지 않아도 비동기 흐름을 읽기 쉽게 구현할 수 있게 되었습니다.

7) 📦 Node.js의 등장은 어떻게 이벤트 루프를 확장했는가?

브라우저에서 탄생한 이벤트 루프는 Node.js에서 서버 측 비동기 처리에도 활용됩니다. Node.js도 이벤트 루프를 기반으로 하며, libuv라는 라이브러리를 통해 파일 시스템 I/O, 네트워크, 타이머, OS 이벤트를 처리합니다.

Node.js의 이벤트 루프 구조는 다음과 같은 단계로 이루어져 있습니다:

  1. timers

  2. pending callbacks

  3. idle, prepare

  4. poll

  5. check

  6. close callbacks

8) 🧩 실시간성과 이벤트 루프 – 메타버스, 게임, 채팅 앱

이벤트 루프는 특히 다음과 같은 실시간성이 중요한 영역에서 활약합니다:

  • 채팅 애플리케이션 (ex. Slack, Discord)

  • 실시간 공동작업 (ex. Figma, Google Docs)

  • 게임 (ex. Phaser.js, Babylon.js)

  • 메타버스 / 3D 인터랙션 (ex. Three.js + WebSocket)

매 프레임마다 사용자 입력, 네트워크 수신, 물리 계산, 화면 그리기 등을 반복 수행하기 위해선 이벤트 루프 기반의 구조가 필수적입니다.

9) 🧮 브라우저 성능을 높이기 위한 루프 최적화 기법

이벤트 루프는 무한 반복 구조이기에 성능 저하 요소가 많습니다.

개발자들은 다음과 같은 기법으로 성능을 개선합니다:

  • Debounce & Throttle

  • requestAnimationFrame

  • Web Workers (멀티스레딩 유사 구현)

  • Microtask와 Macrotask의 적절한 분리

  • Virtual DOM (React의 예)

🔚 마무리 요약

"브라우저는 더 이상 단순한 문서 뷰어가 아니다. 브라우저는 작은 운영체제다."

이벤트 루프는 그 운영체제의 CPU 스케줄러 같은 역할을 합니다. 단일 스레드임에도 마치 여러 작업이 동시에 일어나는 것처럼 동작할 수 있는 비결이기도 합니다.

우리가 사용하는 웹 앱은 단순히 HTML과 CSS의 조합이 아니라, 운영체제처럼 동작하는 브라우저와 그 안의 이벤트 루프 덕분에 동작하는 복합 시스템입니다.

2. 웹 프론트엔드의 역사와 진화 좀 더 자세히 알아보기

1) 검색 엔진과 포털, e-커머스의 발전

문서를 공유하고자 만들어진 웹에서 양질의 문서들을 찾아서 공유하는 것은 당연한 일이었습니다.

초창기 이러한 유용한 링크들을 아카이브 하는 웹 디렉토리라는 서비스들이 생겨나고 이는, 웹 디렉토리 → 검색엔진 → 포털 → 전자상거래 (e-커머스)로 진화하게 됩니다.

웹의 보급 = 정보의 유통 = 상품 판매 수단으로 변화하였어요.

2) Internet Explorer와 웹의 상업화 (1995~2004)

Windows에 IE 기본 탑재로 인해 웹은 기업의 필수 명함이 되었어요. 웹 디자이너 + 서버스크립트(게시판, 방명록) 필요했졌습니다.

솔루션 기반의 홈페이지 제작이 보편화, HTML/CSS만 다루는 웹 개발자에 대한 저평가되었습니다. 디자인 중심 웹 수요 급증, 기능보단 시각 효과가 핵심이던 시절이었어요.

웹페이지 개발의 수요는 올라갔으나 디자인과 데이터 솔루션을 제외한 로직의 영역이 중요하지 않았던 시기였습니다. HTML와 CSS는 다른 개발에 비해 상대적으로 쉬웠고, Javascript나 Flash등의 동적 스크립트의 영역이 엔터프라이즈급 비지니스 모델과 거의 연관이 없던 시절이었다고 합니다.

3) Web 2.0과 RIA (Rich Web Application)의 탄생 - Flash의 등장과 웹 애니메이션의 진화

2000년대 초 닷컴 버블로 여러가지 웹 비지니스가 망하고 웹 생태계가 재편이 되면서 web 2.0이라는 용어가 생겨 납니다. web 2.0에는 여러가지 개념들이 있지만 프론트엔드와 가장 밀접한 키워드는 RIA(Rich Web Application) 입니다.

기존의 정적인 문서 구조에서 벗어나 사용자와 적극적으로 인터렉션을 하며 화면이 동적으로 변하는 것들로 나아가야 한다고 했습니다.

기존 브라우저의 성능 부족으로 정교한 애니메이션 표현 어려움 이를 보완하기 위해 등장한 Flash는 디자인, 애니메이션, 인터랙션에서 압도적인 성능 제공하였어요.

웹 디자이너 중심의 Flash 활용이 확대되며 "화려한 웹사이트의 시대" 도래 그러나 검색 불가, 보안 문제, 무거운 리소스 로딩 등의 한계로 점차 퇴출되었습니다.

특히 Apple의 아이폰에서 Flash 비지원 선언 이후 몰락되었습니다.

5) 구글의 도전: 웹을 OS로!

구글은 검색엔진 성공 후 웹을 새로운 OS로 만들기 위해 Chrome OS 등 시도했습니다.

OS라면 어떠한 것들을 제공해야 할까요? OS만 있어서는 아무것도 할 수 없습니다. OS가 성공하기 위해서는 좋은 Software가 필요합니다. 그래서 구글은 Microsoft에 있는 Office를 웹으로 옮겨오는 시도를 하게 됩니다. Office → Google Docs로, MS에 대항하기 위한 웹 기반 소프트웨어 개발 시작했어요.

이를 위해 Internet Explorer 보다 더 좋은 브라우저가 필요했고 웹 개발에 용이해야 했기에 디버그 기능에 엄청 공을 들였습니다.

뿐만 아니라 javascript 성능을 올리기 위해 자체적인 V8 자바스크립트 엔진도 만들게 됩니다.

구글 뿐만 아니라 MS의 Internet Exploer의 독점적 위치가 대항하기 위한 여러가지 브라우저들이 이 시기에 만들어지기 시작했습니다. 이는 후술할 웹 표준과 웹 접근성의 토대가 된다고 합니다.

6) Ajax의 대중화와 JS의 재발견

웹에서도 Application과 같은 소프트웨어가 동작하기를 바랬습니다. 그전까지는 열악한 브라우저 컴퓨팅 환경에서 굳이 javascript로 이런 것들을 만들 이유가 없었습니다. 훨씬 더 나은(?) ActiveX와 Flash, Java Applet과 같은 대체재가 얼마든지 있었습니다. 그래서 ActiveX 범벅이었죠. 굳이 웹으로 만들 필요도 없습니다. 하지만 구글은 다른 vendor에 의존하지 않는 방법이 필요했습니다.

javascript를 통해서 비동기로 화면을 동적으로 구성하는 방법을 통해서 Google Maps라는 서비스를 만들었고 이것은 웹 개발 생태계에 새로운 파장을 일으켰습니다.

페이지 새로고침 없이 동적으로 UI 변경 가능 → 웹 생태계에 있는 자원을 그대로 활용해서 동적인 화면들을 만들 수 있다는 것은 상당한 가치였으며 이를 통해서 javascript가 재평가를 받게 됩니다.

7) 웹 표준, 접근성, 시맨틱, 크로스브라우징의 등장

다양한 브라우저 생태계로 인해 웹 표준화의 필요성 대두되었고 ActiveX, Flash 비표준 기술 최소화 + IE 크로스브라우징 고려하였습니다.

접근성, 시맨틱 HTML 강조하게 되었고 디자이너/개발자의 역할 분리 시작었습니다.

8) jQuery의 등장과 프론트엔드 재정의

기존 DOM API의 한계

  1. 브라우저 간 호환성 문제

    • 같은 DOM 함수를 사용해도 브라우저마다 다르게 동작하는 경우가 많았음

    • 개발자는 이를 고려해 조건문과 예외 처리를 별도로 구현해야 했음

  2. 불편한 문법

    • 예: document.getElementsByTagName("big")[0].style.background = "green";

    • DOM 조작이 직관적이지 않고 지저분하고 복잡함

2008년 등장한 jQuery: DOM 제어, Ajax, 크로스 브라우징 문제 해결

열악했던 개발환경에서 대체재가 없는 이 javascript는 많은 사람들의 손을 거쳐가며 라이브러리가 발전하고 사용법이 발전을 하게 됩니다.

이러한 노력의 결과로 2008년 웹표준 API를 모두 포함하면서 훨씬 더 쉬운 문법과 IE 크로스브라우징, Ajax까지 해결해버린 jQuery가 탄생을 하게 되면서 웹개발은 제2의 전성시대를 맞이하게 됩니다. 이때 만들어진 jQuery의 대부분의 문법들은 실제 웹 표준의 API 기능으로 대거 포함이 됩니다.

HTML/CSS를 시멘틱하게 구성하고 JS로 동적 처리하는 역할 분리 체계 형성하였습니다.

jQuery의 한계와 이후의 흐름

jQuery는 웹 개발의 표준 도구가 되었지만, 너무 많은 개발자들이 서로 다른 jQuery 유사 라이브러리를 만들기 시작했어요.

  • 결과적으로 라이브러리 난립과 호환성 문제 발생

  • 이는 훗날 프레임워크(React, Vue 등) 시대의 도래로 이어짐

9) 크롬 브라우저와 V8 엔진의 탄생

  • Google의 V8 JS 엔진 + Webkit → Chrome 브라우저 개발

  • 빠른 성능 + 강력한 디버깅 환경 → 웹 개발자들의 희망

  • 디버깅이 가능해지면서 대형 서비스 개발 가능 환경 조성

10) Node.js와 npm의 등장

V8의 오픈소스는 새로운 국면을 맞이합니다. javascript를 가지고 서버사이드 환경을 개발할 수 있는 Node가 탄생합니다. 이는 javascript 성장에 박차를 가해줍니다.

javascript만 할 줄 알던 사람도 새로운 언어의 학습없이 서버개발을 할 수가 있게 되었고 서버개발자 역시 javascript를 하면 겸사겸사 브라우저 개발도 할 수 있도록 영역을 넓혀주게 됩니다.

  • V8을 활용한 Node.js의 등장으로 JS의 서버 확장 가능해짐

  • 프론트/백 통합 개발자 등장 + module 시스템 도입

  • npm을 통한 모듈 생태계 확장 → 공통 라이브러리와 DevOps 도구(webpack, babel 등)로 발전

11) 페이스북과 React의 등장

  • Facebook의 초거대 단일 서비스 운영 필요 → React Framework 탄생

  • JSX, Virtual DOM 등 새로운 개발 철학 도입

  • 이 시점부터 프론트엔드가 명확히 독립된 전문 분야로 분화됨

12) 디지털 전환과 하이브리드 앱 시대

  • 기업과 비IT 업계의 디지털 전환 가속화 → 백오피스 시스템 수요 증가

  • 정형화된 쇼핑몰 외에도 데이터 유통 구조를 시각화/조작하는 도구로 웹 프론트엔드 사용 증가

  • 서비스 프로토타이핑, 관리자 도구, CMS 등에서 프론트엔드의 중요성 증대

  • 하이브리드 앱의 성장: 한 번의 개발로 여러 플랫폼 대응 가능

✅ 요약: 웹 프론트엔드는 이제 하나의 독립 생태계

  • 문서 중심 → 데이터 중심으로 전환

  • 설치 없이 브라우저만으로 동작 가능한 강력한 앱 플랫폼

  • 크롬 + V8 + Node.js + npm + React로 이어지는 혁신 덕분

  • 프론트엔드는 더 이상 HTML/CSS만 다루는 직무가 아니라, 복잡한 데이터 흐름과 UX를 책임지는 핵심 분야

3. V8에 대해 좀 더 자세히 알아보자.

1) 일단, Node.js란?

Node.js는 Chrome V8 JavaScript 엔진으로 빌드된 JavaScript 런타임입니다. -Node.js는 공식 홈페이지-

런타임은 특정 언어로 만든 프로그램들을 실행할 수 있는 환경을 뜻합니다.

브라우저에는 자바스크립트 해석 엔진이 있습니다. 기존에는 자바스크립트를 인터넷 브라우저 위에서만 실행할 수 있었습니다. 그러나 2008년에 구글이 V8 엔진을 사용하여 크롬을 출시했습니다. V8 엔진은 엄청 빨랐고, 오픈 소스로 코드도 공개되었습니다. V8 엔진이 너무 뛰어나서 기능을 좀 더 더해서 V8 엔진 기반에 노드 프로젝트를 시작했고, Node.js(V8)이 등장했습니다. Node.js는 브라우저 내에서 말고도 다른 환경에서 자바스크립트를 사용할 수 있게 해줍니다.

따라서 Node.js는 JavaScript 실행 환경(=런타임)입니다.

Node.js를 설치하면 브라우저를 키지 않아도 자바스크립트를 컴퓨터에서 수행할 수 있게됩니다.

Node.js가 자바스크립트를 컴퓨터에서 쉽게 실행시켜줬기 때문에 자바스크립트를 프로그래밍 언어처럼 사용하기 시작했습니다.

많은 사람들이 Node로 서버를 만듭니다.

왜하필 Node.js로 서버를 만들어 쓸까?

두 개의 서버(=요청을 처리하는 기계)가 있습니다. Node.js로 만들어 진 거 하나, 일반 서버 하나 이렇게 두 개가 있다고 가정해봅시다. 이 서버는 동일한 작업을 수행하는 서버입니다. 예를 들어 CGV 페이지라고 생각해봅시다.

손님이 예매할 영화의 티켓 수를 얘기(요청)하면 CGV 페이지의 서버가 요청을 받고 티켓을 줍니다(응답). 손님은 서버가 준 티켓을 받습니다.

일반 서버의 경우

손님이 4명 있다고 생각해봅시다. 1번째 손님은 티켓 1장을 요구해서 서버가 티켓 1장을 줬습니다. 2번째 손님은 1번째 손님이 가기를 기다렸다가 차례가 되면 예매를 합니다. 1장을 요구하고 서버에게 1장을 받고 갑니다. 그런데 3번째 손님이 200장을 예매합니다. 그러면 서버는 200장의 티켓을 준비하고, 3번째 손님은 기다립니다. 근데 문제는 4번째 손님도 3번째 손님이 마무리될 때까지 기다려야한다는 겁니다.

Node.js로 개발한 서버인 경우

모든 손님의 요청을 한번에 받습니다. 그리고 순서와 상관없이 처리 속도가 빠른 것부터 결과를 가져다줍니다. 처리 속도가 빠른 것부터 처리하기 때문에 요청을 놓치지 않고, 4번째 손님이 굳이 3번째 손님의 요청이 끝날 때까지 기다리는 문제도 사라졌습니다. 이게 Node.js의 Non-blocking I/O의 개념입니다.

2) V8 JavaScript 엔진의 작동 원리와 최적화 과정

컴퓨터는 0과 1밖에 이해하지 못하는 낮은 수준의 언어입니다. 하지만 고수준 언어인 자바스크립트 파일을 이해하고 명령을 수행할 수 있습니다. 인간이 작성한 자바스크립트 파일을 컴퓨터가 읽을 수 있는 것은 자바스크립트 엔진이 있기 때문에 가능합니다. 자바스크립트 엔진은 일련의 과정을 거쳐서 컴퓨터에게 최적화된 코드로 변환하여 전달하게 되고, 이러한 과정으로 인해서 컴퓨터가 자바스크립트 파일을 이해하고 수행할 수 있는 것입니다.

즉, 자바스크립트 엔진은 자바스크립트 코드를 마이크로프로세서가 이해할 수 있게 기계어로 변환해서 실행하는 프로그램 또는 인터프리터를 말합니다.

컴파일러와 인터프리터

V8엔진이 어떻게 작동하는지 알아보기 전, 프로그래밍에서 사용하는 두 가지 번역 방식에 대해 먼저 알아봅시다.

구분
인터프리터
컴파일러

방식

한 줄씩 바로 실행

전체 코드를 읽고 변환 후 실행

장점

빠른 초기 실행

반복 작업의 최적화 가능

단점

반복 시 느려짐

초기 실행 시간 소요

V8 엔진이란?

V8 엔진은 Google에서 개발한 오픈소스 자바스크립트 엔진으로, 다음과 같은 환경에서 사용됩니다:

  • Chrome 브라우저

  • Node.js 런타임

⚙️ 핵심 개념: 자바스크립트 코드를 기계어로 변환해서 CPU가 이해하고 실행할 수 있게 만들어주는 엔진

V8 엔진이 만들어진 이유

V8은 웹 브라우저 내부에서 자바스크립트 수행 속도의 개선을 목표로 처음 고안되었습니다. 이전에 여러 자바스크립트 엔진이 사용되고 있었지만 다른 자바스크립트 엔진은 웹 특성상 유저와 상호작용을 위해 즉시성이 있는 인터프리터 방식을 사용하는데, 이는 코드가 많아질수록 속도가 느려진다는 단점이 있습니다.

이 점을 보완해서 속도 향상을 위해 v8엔진은 인터프리터를 사용하는 대신 JIT(Just In Time) 컴파일러를 구현함으로써 코드 실행 시에 자바스크립트 코드를 머신 코드로 컴파일합니다.

왜 머신 코드로 컴파일해야할까?

우리가 사용하는 컴퓨터 안에는 마이크로프로세서라는 작은 기계가 있는데, 이것은 CPU의 핵심 기능을 통합한 집적 회로(IC)입니다. 프로그래머가 어떤 코드를 짜서 컴퓨터에게 일을 시키려면 결국 이 마이크로프로세서가 해석할 수 있는 언어로 전달해야 합니다. 마이크로프로세서는 이것을 만든 회사나 버전에 따라 각자 다른 언어를 사용합니다. 이 언어들은 하드웨어와 직접적으로 소통할 수 있는 코드들이고 그래서 기계어, 머신 코드라 불립니다. 그러니까 결국 프로그래머들은 프로그래밍 효율을 위해 추상화 수준이 높은 고수준 언어를 사용해서 코딩을 하지만 이는 결국 머신 코드로 컴파일되어야만 CPU가 이해하고 처리를 할 수 있다는 말입니다.

V8 엔진의 작동 방식 (JIT 컴파일)

V8은 전통적인 인터프리터 방식 대신, JIT(Just-In-Time) 컴파일 방식을 채택하여 성능을 최적화합니다.

📚 전체 흐름 요약

1. 자바스크립트가 태어나는 순간 – Parser와 토큰화

웹 브라우저가 자바스크립트 파일을 받으면, "V8 엔진"이라는 아주 똑똑한 두뇌가 그 파일을 읽기 시작합니다.

이 엔진 안에는 먼저 Parser(파서)라는 친구가 등장합니다.

🧩 역할:

Parser는 소스코드를 읽으며, 글자를 잘게 잘게 나눠 **토큰(Token)**으로 만듭니다. 예를 들어 아래 코드를 보면요,

var a = 5;

Parser는 이렇게 자릅니다:

["var", "a", "=", "5", ";"]

마치 문장을 단어 단위로 끊어서 문법적으로 구조를 분석하기 위한 준비를 하는 것이죠.

2. 구조를 이해하는 법 – AST, 추상 구문 트리

Parser가 만든 토큰을 바탕으로 AST(Abstract Syntax Tree)라는 나무구조를 만들어냅니다.

이 구조는 “이 변수는 어디서 정의됐고, 어떤 값이 할당되었고, 어떤 연산이 이뤄지는가” 등을 트리 구조로 시각화한 것입니다.

즉, 컴퓨터가 코드의 ‘의미’를 이해할 수 있는 형태로 바꾸는 단계입니다.

3. 실행 준비! – Ignition이 바이트코드를 점화하다

이제 V8 엔진 안의 또 다른 인물이 등장합니다. 이름은 Ignition. 이름처럼, 이 친구는 "점화기"입니다. 코드를 ‘실행’할 준비를 하죠.

AST를 받으면, Ignition은 **바이트코드(Bytecode)**라는 중간 코드를 만들어냅니다.

var a = 5;

이라는 고수준 코드를 컴퓨터가 이해할 수 있는 형태로 중간 번역하는 과정이에요.

🛠 바이트코드란?

  • 가상머신이 이해할 수 있는 중간 코드

  • 완전한 기계어는 아니지만, V8 엔진 내부에서 실행 가능한 최소 단위

  • 실행 속도와 메모리 사용을 동시에 고려한 효율적 구조

이 중간 번역은 빠르게 이루어지고, 해석된 바이트코드가 바로 실행되기 시작합니다.

4. 뜨거운 코드를 감지하는 감시자 – Profiler의 등장

V8은 똑똑합니다. 단순히 코드를 실행하는 걸로 끝나지 않죠.

Ignition이 실행하는 동안, Profiler라는 감시자가 프로그램을 계속 분석합니다.

“어? 이 함수 계속 쓰이네?” “이 변수 너무 자주 호출되는데?” 이런 "Hot Spot", 즉 자주 쓰이는 부분을 체크해 나갑니다.

5. 진짜 컴파일 시작 – TurboFan의 등장

감시자 Profiler가 "여기 뜨거워요!" 하고 보고하면, V8 엔진의 터보 부스터인 TurboFan이 등장합니다.

이 최적화 컴파일러는 바이트코드를 기반으로, 컴퓨터가 바로 실행할 수 있는 진짜 기계어로 코드를 변환합니다.

TurboFan의 최적화 전략:

  • Hidden Class: 객체 구조를 예측해서 자주 쓰이는 형태를 빠르게 참조할 수 있게 만듭니다.

  • Inline Caching: 자주 호출되는 메서드나 함수는, 아예 그 위치에 코드 자체를 넣어버립니다. 호출 없이 실행하겠다는 거죠.

6. 하지만, 너무 과열되면? – Deoptimization

자바스크립트는 동적 언어다 보니, 값의 타입이나 구조가 중간에 바뀔 수 있어요.

TurboFan이 최적화한 코드도 때로는 “어라? 조건이 바뀌었네?” 하고 다시 비최적화(Deoptimization)를 하기도 합니다.

하지만 V8은 이조차도 잘 관리합니다. 필요하다면 언제든 다시 최적화 → 비최적화 → 재최적화를 반복하면서 효율적 실행을 유지하려고 해요.

7. 마침내 실행 – 최적화된 코드가 주인공이 된다

이제 최적화된 코드가 준비되었고, 실행할 차례가 오면, 더 이상 느린 바이트코드가 아닌 TurboFan이 변환한 기계어가 메모리에서 직접 실행됩니다.

이게 바로 우리가 "브라우저에서 빠르게 돌아가는 웹 앱"을 느낄 수 있는 이유예요.

🔄 전체 흐름 요약

JS 코드 작성
    ↓
Parser → Token으로 분해
    ↓
AST(Abstract Syntax Tree) 생성
    ↓
Ignition 인터프리터 → Bytecode 생성 및 실행
    ↓
Profiler가 자주 실행되는 Hot Spot 코드 감지
    ↓
TurboFan이 해당 코드를 최적화(기계어로 변환)
    ↓
최적화된 코드를 실행

💬 비유로 정리하면…

  • Parser: 자바스크립트 책을 받아 문장을 토막내는 국어 선생님

  • AST: 토막을 문법 구조로 나누는 독해 트리

  • Ignition: 트리에 불을 붙여 즉시 실행하는 점화기

  • Profiler: 주변에서 불이 얼마나 뜨거운지 감지하는 열 감지기

  • TurboFan: "이 불은 오래 쓸 거니까 아예 화로를 만들어!" 하고 만드는 최적화 장치

📌 V8 네이밍의 의미

  • V8: 실제 자동차 엔진에서 유래된 이름 (8기통 엔진)

  • Ignition: 점화 장치 → JS 코드 실행의 시동

  • TurboFan: 고성능 제트엔진 → 최적화로 속도 향상

V8 엔진은 단순한 인터프리터가 아닌, 복잡한 JIT 컴파일 파이프라인을 통해 JavaScript 성능을 극한까지 끌어올립니다.

  • 처음에는 빠르게 실행 가능한 바이트코드로 실행

  • 반복 사용되는 코드는 분석 후 기계어로 최적화

  • 예상과 다르면 Deoptimization

이러한 설계는 사용자 경험을 부드럽게 하면서도, 자바스크립트를 현대적인 고성능 언어 수준으로 끌어올린 핵심 기술이라고 할 수 있습니다.


PreviousDeepDive 지식 : 2장NextNetwork

Last updated 3 days ago

잘 svg 형태로 정리 되어 있는 곳 :

내용 출처 :

내용 출처 :

출처 :

(출처: )

출처 :

내용 출처 :

사진 출처 :

📎 참고: ,

🔭
https://inpa.tistory.com/entry/%F0%9F%94%84-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84-%EA%B5%AC%EC%A1%B0-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC
https://inpa.tistory.com/entry/%F0%9F%94%84-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84-%EA%B5%AC%EC%A1%B0-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC
https://blog.toktokhan.dev/t-767eb0fa38f3
https://www.flickr.com/photos/50114361@N00/3702942040
https://velog.io/@remon/V8-%EC%97%94%EC%A7%84%EC%9D%B4-%EB%8C%80%EC%B2%B4-%EB%AD%90%EC%95%BC
https://velog.io/@remon/%EA%B0%9C%EB%B0%9C-%EA%B8%B0%EB%B3%B8-%EC%A7%80%EC%8B%9D-Node.js%EB%9E%80
V8 공식 블로그
JSConf EU 2017 발표
How JavaScript works: an overview of the engine, the runtime, and the call stack
https://blog.naver.com/tipsware/221041215416
https://inpa.tistory.com/entry/%F0%9F%94%84-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84-%EA%B5%AC%EC%A1%B0-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC
https://blog.toktokhan.dev/t-767eb0fa38f3
https://inpa.tistory.com/entry/%F0%9F%94%84-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84-%EA%B5%AC%EC%A1%B0-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC#%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8_%EB%B9%84%EB%8F%99%EA%B8%B0%EC%99%80_%EC%9D%B4%EB%B2%A4%ED%8A%B8_%EB%A3%A8%ED%94%84
https://velog.io/@remon/%EA%B0%9C%EB%B0%9C-%EA%B8%B0%EB%B3%B8-%EC%A7%80%EC%8B%9D-Node.js%EB%9E%80