내가 처음 개발을 시작할 땐, 내 수준에 맞게 조언을 해주는 사수가 없었다. 학교에서 배운 많은 것들이 일할 땐 별다른 도움이 되지 않았고, 도움을 얻을 수 있는 건 내 동기들 뿐이었다.(그리고 걔네도 몰랐다.) 어떻게든 주어진 일은 조금씩 해나간다고 해도, 이 방향이 옳게 가고 있는 건지는 몰랐고, 뭘 공부해야할지 몰랐었다.

백엔드와 프론트를 구분하지 말자

웹 개발자에게 기본 지식이라는 건 백엔드와 프론트엔드를 나누었다고 해서 다르지 않다. 구축의 단계부터 운영의 단계까지 발생하는 모든 난관은 영역을 가리지 않는다. 웹 서비스를 이용하려는 사용자의 환경에서 출발해 DB에 도착하고, 다시 사용자에게 돌아오는 일련의 과정에 필요한 모든 지식을 순서대로 이해하고 쌓아가는 것, 그 과정에서 어느 단계가 부족한지 알아내는 것 이 두가지를 목표로 공부를 시작해보면 좋겠다.

디바이스 환경 – 하드웨어부터 브라우저까지

우리가 만든 제품을 사용할 사용자가 어떠한 환경에서 접근하는지 이해하기 위해서 갖춰야 할 지식은 아래와 같다.

  • 디바이스의 환경적 특성
    • 모니터의 출력 방식
    • 해상도의 특성
    • 디바이스 성능
  • 디바이스의 OS 특성
    • Windows, Mac OS와 Android, iOS의 차이
    • Windows와 Mac OS의 차이
    • Android, iOS의 차이
  • 브라우저별 특성과 차이
    • 메이저 브라우저의 사용 비율 변화
    • Chrome, Safari, Firefox, Edge 등 메이저 브라우저의 특성 이해
    • In App Browser에 대한 이해
  • 브라우저 엔진에 대한 이해
    • Webkit Engine의 탄생과 변화 과정
    • Blink와 Chromium, V8
    • 고대의 Trident, 과거의 EdgeHTML
    • Gecko
  • Web 기술에 대한 이해
    • HTML
    • Javascript
    • CSS

사용자의 환경을 이해하는 것은 내가 만들 제품, 서비스가 내가 의도하는 대로 사용자에게 전달되는지 명확하게 예측하는데 필수적인 요소다. 사용자의 환경을 더 깊게 이해하고자 한다면, 위에 언급된 내용에서 CS적인 지식 확장을 시도해보는 것이 좋다. 같은 Chromium 기반의 브라우저가 Windows와 Mac OS 환경에서 어떻게 다르게 작동하는지 확인해보거나, 개별 OS 내에서 각 브라우저 프로세스와 탭의 자원 할당 구조 등을 공부해보는 것도 좋다.

위 내용은 크게 3개 챕터로 나누어 ‘하드웨어와 OS’, ‘브라우저와 브라우저 엔진’, ‘Web 기술 3종’으로 세부적으로 공부해야할 내용을 추가로 정리할 예정이다.

네트워크 환경 – 브라우저부터 서버까지

제품 사용자의 환경을 이해했다면 사용자의 환경이 어떻게 우리에게 요청을 보내는지 이해해야한다. 이 과정은 네트워크의 기본 지식부터, DNS, IP 에 대한 이해가 필요하고, 네트워크 계층내에 존재하는 다양한 개념들을 순서대로 학습하는 것이 좋다.

  • URL의 각 구성요소
    • URL, URI, URN 각각의 구성과 의미
    • HTTP와 HTTPS
      • SSL 인증서와 암호화
      • HTTP Method
    • Host
      • TCP 와 TCP Handshake
      • 도메인과 DNS의 역할
      • IPv4, IPv6
  • 패킷의 전달 과정
    • Packet의 의미
    • DNS Resolution과 DNS Query
    • ISP, Firewall, Router, Hob
    • OSI 모델
    • TCP/IP protocol

    일반적으로 제품을 제공하는 주소는 URL로 제공한다. 이는 검색엔진 혹은 광고 시스템 등에 노출되고, 노출된 URL에 접속을 시도할 경우 브라우저가 서버로 요청을 보내기 위해 준비하는 전처리 과정과 packet 생성 과정을 거쳐 인터넷으로 보내진다.

    전처리 과정에서는 사용자의 정보를 패킷에 담기 전에, URL을 변환하는 과정을 거친다. 이 과정에서 DNS Query 요청하는데 이를 통해 브라우저는 Domain 정보를 Host IP 정보로 변환한다. DNS가 어떤 계층적 구조를 가졌는지에 따라 여러 DNS를 거칠 수 있는데, DNS를 아무리 많이 거치더라도 브라우저가 packet 도착 지점의 IP 주소를 확보한 이후에는 별도의 요청이 이루어지지 않는다.

    브라우저가 URL의 파싱을 모두 완료하면 패킷 구성을 시작한다. 여기서 구성된 패킷은 정해진 정보구조에 따라 정해진 크기의 데이터가 들어있으며, packet header 안에 있는 정보들은 순서가 정해져있다. 패킷이 완성되면 OS의 네트워크를 기반으로 라우터 또는 모뎀 등 브라우저가 실행중인 디바이스의 네트워크 망에 패킷을 전달하고, 이 단계의 끝에는 ISP(Internet Service Provider)가 위치한다. ISP가 구성해놓은 라우터망에 의해 최종 도착지에 보내진다. 대부분의 데이터센터에는 ISP가 연결해놓은 라우터가 존재하며, 이 라우터 장비들의 계층에 따라 게이트웨이가 지정된다.

    네트워크 개념은 평소에 크게 관심을 갖지 않는 경우가 많지만, 백엔드와 프론트엔드 환경 모두 제품 사용자가 정상적으로 요청을 잘 보내고 있는지, 잘 받았는지를 상호 확인해야하는 의존성이 있는 영역이기 때문에 원활한 커뮤니케이션을 위해서는 기초 지식정도는 항상 기억하고 있는 것이 좋다.

    서버 환경 – 서버에서 우리의 코드까지

    브라우저가 패킷을 우리 서버에 전달할때 까지의 과정을 잘 이해했다면, 서버 내부에서 우리 코드까지 접근 과정을 이해할 단계다.

    • Infra
      • LoadBalancer
      • Server Instance, public IP
      • private IP, VPC with Cloud
    • OS
      • packet parsing
      • Web Server & Web Applciation Server
      • socket
      • gateway
      • 쓰레드 & 프로세스
    • 웹 어플리케이션
      • python -> wsgi, asgi, gunicorn
      • java -> tomcat, jBoss, WebLogic
      • php -> X
      • javascript -> node.js (node.js가 웹 요청을 처리할 수 있는 플랫폼 역할을 한다)

    Infra의 경우 아래의 프로세스 환경에서 추가적으로 다루겠지만, 네트워크 단위에서의 Infra 개념은 이 단계에서 이해하는 것이 좋다. OS 안에서도 packet을 우리가 아는 web server로 전달해주는 과정에 여러 계층이있으며, 이 과정에서 개발 환경에서는 잘 구현된 서비스가 배포 환경에서 다른 작동을 보여주는 경우가 발생한다. MS 기반의 환경이라면 IIS를, linux 기반의 환경이라면 Apache, Nginx 를 기초적인 수준에서 공부해두는 것이 좋겠다.

    웹 어플리케이션 (서버) 영역은 개발 언어 및 프레임워크마다 선호와 제약이 다르기 때문에, 주 언어를 기반으로 공부하는게 좋겠다. WAS가 필요하지 않는 언어적 환경과 프레임워크가 존재하기 때문에(PHP) WAS의 역할이 무엇인지를 이해하고, 해당 언어 환경에서 어떤 WAS가 많이 활용되는지를 바탕으로 공부하면 좋다.

    프로세스 환경 – 코드가 자원을 활용하기 까지

    우리가 사용하는 프레임워크 영역까지 도달한다면 이 영역에 수많은 계층적 구조가 존재한다는 것을 알아야 한다. 우리가 작성한 코드까지 도달하는데만 해도 이미 최소 20개 이상의 계층이 패킷을 건드렸거나, 영향을 주었다. 프레임워크 영역으로 내려온다면 이러한 과정은 더 많은 계층으로 나뉘어져 있다.

    내가 Python이 주언어이기 때문에, Python에서 보편적인 개념으로 표현했지만, 다른 언어 환경에선 해당 개념을 다른 계층이 처리하기도 하고, 부르는 용어가 다른 경우도 있다. 이러한 계층적 차이를 이해하기 위해서 사용할 프레임워크의 web request, web response 다이어 그램을 그려보는 것을 추천한다.

    아래는 Django를 기준으로 핵심적인 요소에 대해 다이어그램을 그리기 위해 필요한 순서성을 구체화 한 내용이다.

    1. Web Server에 도달한 Packet은 HTTP Request로 전환되어 WSGI에 전달된다.
    2. Gunicorn/uWsgi 프로세스는 request를 worker에 전달해 프레임워크에 정의된 계층으로 내린다.
    3. Django의 경우 Request를 Middleware 계층으로 전달하며, request는 Middleware 내에서 정의된 순서대로 처리된다.
    4. middleware를 모두 거친 request는 url router를 통해 URN 정보에 해당하는 View 코드로 전달된다.
    5. View 계층에서는 HTTP Method에 해당하는 함수가 실행되고 이 과정에서 ORM을 통해 데이터베이스와 통신한다.
    6. View는 이후 context processor를 통해 데이터를 전처리하고 이를 Template 계층으로 넘긴다.
    7. Template 내에서는 Template Engine을 기반으로 context processor 내의 데이터를 바인딩하며, 이 과정에서 추가적으로 필요한 데이터는 ORM을 통해 호출한다.
    8. View는 Template의 처리가 끝나면 이를 HTTP Response로 포장하여 Middleware에게 반환을 넘긴다.
    9. Middleware는 request의 역순으로 response를 처리하며, 모든 Middleware를 거친 response는 다시 Gunicorn/uWsgi 에게 전달된다.

    이러한 과정을 다이어그램으로 그려준 사람들이 많으니 한번 찾아보면 좋겠다.

    브라우저 환경 – 응답이 보여지기 까지

    브라우저가 사용자 대신 서버에게 요청한 첫 데이터의 일부를 전달받으면 Parsing이 진행된다. 파싱이 완료되면 렌더링 과정을 거친다. 이후 응답이 보여진 결과물에서 브라우저가 interaction을 사용자로부터 받아 서버와 일부 재통신하거나 페이지의 전환(서버로 새로운 URI 요청)이 진행된다.

    MDN에서는 이 과정을 크게 Parsing -> Render -> Interactivity로 나누어두었는데 각각의 과정에서 무슨 일이 이루어지는 지 잘 이해할 필요가 있다. 흔히 서버는 정상적인 응답을 주었는데 브라우저에서 오류가 난다면, 어느 과정에서 부터 디버깅을 해야하는지 이 과정에서 추론해볼 수 있다.

    다만 요즘의 웹 환경에서는 정적 웹 컨텐츠 보다는 동적으로 화면을 구성하는 경우가 많고, react.js를 활용하는 경우 next.js없이 단독으로 쓰거나, client component 위주로 구성할 경우에는 디버깅이 쉽지 않으니 프레임워크 레벨에서 제공하는 디버깅 환경을 구성하는 것이 좋다.

    따라서 알아두어야 할 각각의 과정과 내용은 적은 편이다. 브라우저의 렌더링 방식은 기본적으로 5개의 과정을 거친다. 특히 React.js 나 Vue.js와 같이 DOM을 직/간접적으로 컨트롤하는 방식의 프레임워크는 작성한 코드 의존성대로 렌더링이 이루어지지 않는 경우가 많기 때문에, 왜 이게 안되는지/어떤 단계에 문제가 있는지 파악하는 연습이 이루어지면 좋다.

    • DOM 트리 빌드
      • 프리로드 스캐너
    • CSSOM 빌드
    • DOM트리와 CSSOM 병합 – 렌더 트리 빌드
    • Layout 렌더링
    • 페인팅
    • Compositing

    정리

    지금까지 나온 용어들 중 대부분은 실제로 코드를 작성할 때 생각하지 않아도 되는 경우가 많다. 하지만, 개념을 이해하고 이를 토대로 코드를 작성하는 것과, 존재 여부를 모르는 채 코드를 작성하는 것은 결과물에 큰 차이가 있다. 내가 지금 작성하는 코드가 어느 단계에 어느 영향을 주는지 잘 이해할 수 있다면, 빠른 시간 내에 코드를 작성할 때 주의해야할 점을 체화할 수 있다.

    Categorized in:

    개발,