오늘은 EPL 리그 성적 업데이트를 하는 것 만들었습니다. 
간단한 API를 만들 때 플로우나 어떤 데이터를 가지고 가공을 해야하는지 정리해두고 하는게 일을 효과적으로 빠르게 처리할 수 있습니다. (개인적인 생각)

목적 

- 크롤링 해온 데이터와 기존의 DB 정보에서 오늘 진행한 경기가 끝날 때마다
  (스케줄러{현재 - 24:00 기준으로 진행중}) 클럽별 총 전적을 업데이트함.

PremierLeaugeData :  EPL 리그에 대한 상세 내용이 기재되어 있는 사이트에서 데이터를 크롤링해서 필요한 정보만 가져옵니다.
DatabaseData : 데이터베이스 내에 업데이트 되어야하는 테이블에서 기본키값과 클럽ID, 클럽명(LEFT JOIN 클럽) 을 가져옵니다. 

let query = "INSERT INTO [테이블 명] [컬럼들]... VALUES";
for (const [index, premierLeagueData] of premierLeagueList.entries()) {
  for (const clubData of clubList) {
    if (clubData.club_name.includes(premierLeagueData.team)) {
      query += `(${clubData.participating_club_id}, ${premierLeagueData.ranking}, ${premierLeagueData.totalMatches}, ${premierLeagueData.win}, ${premierLeagueData.draw}, ${premierLeagueData.lose}, ${premierLeagueData.score}, ${premierLeagueData.conceded}, ${premierLeagueData.gainLossDifference}, ${premierLeagueData.point}, "${premierLeagueData.last5Matches}")`;
      // 구분을 해주지 않으면 구문 에러가 납니다!!
      if (index + 1 !== premierLeagueList.length) {
        query += ',';
      }
    }
  }
  
query += ` ON DUPLICATE KEY UPDATE 
  				ranking = VALUES(ranking) ...

return query;

Q) 데이터 가공되어질 때마다 query를 DB에 보내면 되지 않나요?
A) 저는 데이터베이스 연결을 요청하는 작업이 많은 자원을 소모하기 떄문에, 한번에 query를 만들어서 보내는게 좋다고 생각했습니다.

Q) INSERT INTO ... ON DUPLICATE KEY UPDATE 가 아니라 UPDATE 구문을 사용해도 되는 것 아닌가요?
A) 저도 성능을 직접 측정해보지 않아서 정확하게는 모르겠습니다. 추후에 정리한 뒤 어떤 것이 더 효율적인지 비교하려고합니다.

'개발일지 > 설계' 카테고리의 다른 글

[Node.js] 채팅 설계 Q&A  (2) 2024.02.14

Javascript


Javascript 란?


자바스크립트 엔진 - V8


자바스크립트 엔진은 자바스크립트 코드를 이해하고 실행을 도와줍니다. 대표적인 엔진으로 V8 Engine (Chrome, Node.js 에서 사용)이 있으며, 각 브라우저 별로 여러가지 엔진들이 존재합니다.


V8 엔진이란?

  • Google이 주도하여 개발한 오픈소스임.
  • C++로 작성된 고성능의 자바스크립트 & 웹 어셈블리 엔진임.
  • Call Stack 과 Memory Heap으로 구성되어 있음.
  • 웹 브라우저의 성능 향상 메커니즘으로 도입되었으며 다른 엔진보다 훨씬 향상된 인터프리터가 되었음.

⇒ V8과 다른 엔진의 가장 큰 차이점은 V8 엔진의 JIT(Just In Time) 컴파일러임.

     - JIT 컴파일러는 런타임에 모든 자바스크립트를 기계어 코드도 컴파일하고 중간 코드를 생성하지 않음.

V8 엔진의 동작 과정


  1. 소스코드 파싱
  2. 자바스크립트 소스코드를 가져와서 먼저 파서(Parser)에 넘기면, 소스코드를 분석한 후 AST(Abstract Syctax Tree,추상 구문 트리) 로 변환합니다.
  3. Ignition 바이트코드(ByteCode)로 변환
  4. Ignition은 자바스크립트 코드를 바이트코드로 변환하는 인터프리터이다. 원본 소스 코드보다 컴퓨터가 해석하기 쉬운 바이트 코드로 변환하여, 수시로 코드를 파싱하는 작업을 최소화하고 코드의 양도 줄임으로써 메모리 공간도 효율적으로 관리할 수 있게 된다.
  • 인터프리터(Interpreter)란?
  • 컴파일러와 반대로 인터프리터는 프로그램 실행시 한 번에 한문장씩 번역한다. 그렇기 때문에 한번에 전체를 스캔하고 실행파일을 만들어서 실행하는 컴파일러보다 실행시간이 더 걸린다. 인터프리터는 메모리 효율이 좋다. 대표적인 언어로 Python,Ruby,Javascript 등이 있음.
  • 컴파일러란(Compiler)?
  • 프로그램 전체를 스캔하여 이를 모두 기계어로 번역한다. 전체를 스캔하기 때문에 대개 컴파일러는 초기 스캔 시간이 오래 걸린다. 하지만 전체 실행 시간만 따지고 보면 인터프리터보다 빠르다. 대표적인 언어로 C,C++,JAVA 등이 있음.
  • 자바스크립트는 정적 타이핑 언어가 아닌 동적 타이핑 언어입니다. 소스코드가 실행되기 전에는 알 수 없는 값들이 너무 많아 최적화가 힘들다는 단점이 있습니다. 때문에 모든 소스를 한 번에 해석하는 컴파일 방식이 아닌 코드 한 줄씩 실행될 때마다 해석하는 인터프리트 방식을 채택하여 세 가지 이점을 가져가고자 하였습니다.
  • 메모리 사용량 감소 : 자바스크립트 코드에서 기계어로 컴파일하는 것보다 바이트 코드로 컴파일 하는 것이 더 편하다.
  • 파싱 시 오버헤드 감소 : 바이트 코드는 간결하기 때문에 다시 파싱 하기 편하다.
  • 컴파일 파이프라인의 복잡성 감소 : TurboFan을 통한 Optimizing 혹은 Deoptimizing 처리시에도 바이트코드가 편하다.
  1. TurboFan으로 자주 사용하는 바이트코드를 컴파일
  • TurboFan이란?
    • TurboFan은 V8 v5.9 버전 이전에 사용되었던 Crankshaft 컴파일러를 완전히 대체한 최적화 담당 컴파일러임.
    • TurboFan은 바이트 코드로 수시로 변환하는 과정을 최소화하기 위해 사용됨.
    • V8 런타임 중에 Profiler에게 함수나 변수들의 호출 빈도와 같은 데이터를 모으라고 시키며 이 데이터를 이용하여 TurboFan이 자기 기준에 맞는 코드를 가져와서 최적화를 시킴.

TurboFan 최적화 기법

  • Hidden Class
    • 자바스크립트는 기본적으로 클래스가 없고 대신 Prototype이라는 개념이 있다. 자바스크립트 내에서 사용되는 Number,Boolean 등과 같은 정적 타입 데이터 외 모든 데이터를 객체로 취급됨.
    • 자바스크립트 엔진 내부의 Hidden Class라는 개념을 이용하여 각 객체에 대한 속성 값의 포인터만 가지고, 해당되는 구조를 참조함.
  • Inline Caching

Javascript 엔진 구조도

V8 엔진의 구조도를 간단히 나타낸 그림

출처 : https://joshua1988.github.io/web-development/translation/javascript/how-js-works-inside-engine/

 

엔진의 주요 두 구성요소는

  • Memory Heap : 메모리 할당이 일어나는 곳
  • Call Stack : 코드 실행에 따라 호출 스택이 쌓이는 곳

출처 : https://joshua1988.github.io/web-development/translation/javascript/how-js-works-inside-engine/

 

참고 자료: 참고 자료:

컴파일러(compiler)와 인터프리터(interpreter)의 차이

[2020.10.16] Google Chrome V8 엔진을 파헤쳐보자

자바스크립트의 동작원리: 엔진, 런타임, 호출 스택

'Web > JavaScript' 카테고리의 다른 글

[Node.js] 이벤트 디멀티플렉싱  (0) 2024.03.05
Node.js 란?  (0) 2024.03.05
[Javascript] 얕은 복사와 깊은 복사  (0) 2024.02.05

OSI 7계층을 나눈 이유는?

흐름을 한눈에 알아보기 쉽고 7단계 중 특정한 곳에 이상이 생기면 다른 단계의 장비 및 소프트웨어를 건들이지 않고도 이상이 생긴 단계만 고칠 수 있기 때문임.

OSI Model 전송 단위

Physical(물리 계층) 비트(Bits)
Data link(데이터 링크 계층) 프레임(Frames)
Network(네트워크 계층) 패킷(Packets)
Transport(전송 계층) 세그먼트(Segment)
Session(세션 계층) 데이터(Data)
Presentation(표현 계층) 데이터(Data)
Application(응용 계층) 데이터(Data)

전송 시 7계층에서 1계층으로 각각의 층마다 인식할 수 있어야 하는 헤더를 붙임(캡슐화)

수신 시 1계층에서 7계층으로 헤더를 떼어냄(디캡슐화)

출발지에서 데이터를 전송할 때 헤더가 추가되는데 2계층에서만 오류제어를 위해 꼬리부분에 추가됨.

물리 계층(Physical Layer)

  • 전기적, 기계적, 기능적인 특성을 이용하여 데이터를 전송하는 계층임.
  • 단지 데이터를 전달만 할뿐, 전송하려는 데이터가 무엇인지, 어떤 에러가 있는지 등에는 전혀 신경 X.
  • 데이터 전송 단위 : 비트(Bit)
  • 대표적인 장치 : 통신 케이브, 허브, 리피터 등

데이터 링크 계층(Data link Layer)

  • 물리적인 연결을 통해 인접한 두 장치 간의 신뢰성 있는 정보 전송을 담당(Point-to-Point)
  • 물리계층을 통해 송수신되는 정보의 오류와 흐름을 관리하여 안전한 정보의 전달을 수행할 수 있도록 도와주는 역할을함 → 통신에서의 오류도 찾아주고 재전송하는 기능도 가지고 있음.
  • Mac주소를 통해 통신함.
  • 데이터 전송 단위 : 프레임(Frame)
  • 대표적인 장치 : 스위치, 브릿지
  • Mac 주소란?예 : 12:34:56:78:90:AB
  • : 무선 LAN 카드 또는 무선 LAN 기능 내장 기기에 개별적으로 부여되는 16진수 12자리의 단말 식별 번호

네트워크 계층(Network Layer)

  • 주요 기능은 데이터를 목적지까지 가장 안전하고 빠르게 전달하는 기능(라우팅)
  • 이 계층은 경로를 선택하고 주소를 정하고 경로에 따라 패킷을 전달해줌.
  • 여러 개의 노드를 거칠 때마다 경로를 찾아주는 역할을 하는 계층으로, 다양한 길이의 데이터를 네트워크를 통해 전달하며 그 과정에서 전송 계층이 요구하는 서비스 품질(QoS)을 제공하기 위한 기능적,절차적 수단을 제공함.
  • 라우팅, 흐름 제어, 세그멘테이션, 오류 제어 등을 수행함.
  • 데이터 전송 단위 : 패킷(Packet)
  • 대표적인 장치 : 라우터
  • ⇒ 여러 개의 노드를 거쳐 경로를 찾기 위한 주소는 IP임.

전송 계층(Transport Layer)

  • 계층 구조의 네트워크 구성요소와 프로토콜 내에서 송신자와 수진자를 연결하는 통신 서비스를 제공함.
  • 양쪽의 end to end 간의 데이터 전송을 담당하는 역할을 하는 계층임.
  • 대표적인 프로토콜 : TCP & UDP
  • 상위 계층들이 데이터 전달의 유효성이나 효율성을 생각하지 않도록 해줌.
  • 헤더에 송신지와 수신지의 포트 번호를 포함하여 데이터를 특정 단위로 쪼개어 전달함.

세션 계층(Session Layer)
표현 계층(Presentation Layer)
응용 계층(Application Layer)

'CS(Computer science) > 네트워크' 카테고리의 다른 글

사설 ip, 공인 ip, localhost 구분하기  (0) 2023.08.08

이벤트 디멀티플렉싱은 무엇인가?

이 매커니즘은 감시된 일련의 리소스들로부터 들어오는 I/O 이벤트를 수집하여 큐에 넣고 처리할 수 있는 새 이벤트가 있을 때까지 차단함.

socketA,pipeB
wahchedList.add(socketA, FOR_READ); // [1]
while(events = demultiplexer.watch(watchedList)){ //[2]
	foreach(event in events){
		//read는 블록되지 않으며 비어있을지언정, 항상 데이터를 반환함.
		data = event.resource.read();
		if(data === RESOURCE_CLOSED) demultiplexer.unwatch(event.resource);
		else resolve(data);
	}
}

[2]에서 디멀티플렉서에 감시할 것들을 추가. 이 호출은 동기식이며, 감시 대상 중 하나라도 데이터를 리턴하기 전까지 차단됨. 이때 이벤트 디멀티플렉서는 호출로부터 복귀하여 새로운 이벤트들을 처리할 수 있게됨(비동기)

[3]에서 디멀티플렉서가 반환한 이벤트가 처리됨. 여기를 Event Loop라고 부르며, 이곳에 도달했다는 것은 역으로 읽기 작업이 완료되었다는 것이므로 차단되지 않은 상황이라고 보증됨.

구체적으로, 바로 값을 가져올 수 없는 작업형 함수를 만날 경우(I/O) 일단 약속된 상수 값을 리턴시키고 해당 함수를 디멀티플렉서에 추가함. 이때 완료 후 호출될 핸들러(callback)와 이벤트가 디멀티플렉서에 들어감. 이벤트가 완료될 경우 디멀티플렉서가 이벤트를 반환함. 반환된 이벤트는 큐에 push되고, 이벤트 루프는 이벤트 큐를 순회하며 각각의 이벤트들에 대한 핸들러를 실행합니다.

출처 : 이벤트 디멀티플렉싱과 Reactor 패턴 그리고 Node.js의 구조

이벤트 디멀티플렉싱 패턴을 사용하면 Busy-waiting을 사용하지 않고도 단일 스레드 내에서 여러 I/O 작업을 처리할 수 있습니다. 기존의 동기식 블로킹 I/O가 스레드를 만들어 다중 I/O 작업을 처리했다면 이는 하나의 스레드만 사용하여 시간에 따라 작업을 분리해 처리합니다. 따라서 위의 그림처럼 유휴시간(파란색)을 최소로 줄일 수 있습니다. 또한 프로세스 간의 경쟁 혹은 여러 스레드들의 동기화 걱정이 없는 훨씬 간단한 동시성 전략을 사용할 수 있습니다.

반응자 패턴 (Reactor Pattern)

리엑터 패턴의 핵심은 각 I/O 작업과 관련된 핸들러(callback)를 갖는 것입니다. 이 핸들러는 이벤트 루프에 의해 처리되는 즉시 호출됩니다. 리엑터 패턴은 위에서 설명한 이벤트 디멀티플렉싱을 활용하는 패턴입니다.

출처 : 이벤트 디멀티플렉싱과 Reactor 패턴 그리고 Node.js의 구조

 

  1. 애플리케이션이 요청을 이벤트 디멀티플렉서에 제출하여, 새로운 IO 작업을 생성한다. 애플리케이션은 또한 작업이 완료되면 호출할 핸들러(콜백)를 지정한다. 새로운 요청을 이벤트 디멀티플렉서에 제출하는 것은 논블로킹 요청으로, 즉시 애플리케이션에 통제권을 반환한다.
  2. IO 작업 세트가 완료되면, 이벤트 디멀티플렉서가 해당 이벤트 세트를 이벤트 큐로 푸시 한다.
  3. 이 때, 이벤트 루프는 이벤트 큐 항목에서 반복된다.
  4. 각 이벤트에 연결된 핸들러가 호출된다.
  5. a. 애플리케이션 코드의 일부인 핸들러(콜백) 실행이 완료되면, 이벤트 루프를 다시 제어한다. 5b. 콜백이 실행되는 동안, 새로운 비동기 작업을 요청할 수 있으며, 이는 이벤트 디멀티플렉서에 새로운 항목 추가를 야기한다.
  6. 이벤트 큐의 모든항목이 처리되면, 이벤트 루프는 이벤트 디멀티플렉서를 다시 차단하며, 이 경우 새로운 이벤트가 가능해질 때 다시 트리거한다.

즉, 리엑터 패턴은 관찰 대상 리소스가 반응(콜백)하면 해당 이벤트의 핸들러를 추적해 실행하는 디자인 패턴입니다. 노드의 전신이라 할 수 있는 패턴입니다.

출처 : 이벤트 디멀티플렉싱과 Reactor 패턴 그리고 Node.js의 구조

Node.js는 Reactor 패턴을 사용하며 JS Core API, V8 및 libuv에 의존하는 구조라고 할 수 있습니다.

  • Binding: libuv 외 로우레벨 기능들을 JS에 랩핑하고 사용 가능하게 만들어 줌.
  • V8: 구글에서 만든 크롬용 JS 엔진. V8 덕에 Node.js 가 매우 빠르고 효율적으로 작동한다.
  • JS Core API: Node.js API 를 구현하는 자바스크립트 코어

 

참고 사이트 : Plus Ultra

'Web > JavaScript' 카테고리의 다른 글

JavaScript란?  (0) 2024.03.05
Node.js 란?  (0) 2024.03.05
[Javascript] 얕은 복사와 깊은 복사  (0) 2024.02.05

Node.js란?


  • 오픈 소스 Javascript 엔진인 Chrome V8에 비동기 이벤트 처리 라이브러리인 libuv를 결합해 만든 플랫폼임.

  • 즉, Javascript 로 브라우저 밖에서 서버를 구축하는 등의 코드를 실행할 수 있게 해주는 런타임 환경임.

  • Node.js는 단일 프로세서에서 작동하기 때문에 멀티코어를 완전히 사용하려면 코어갯수만큼의 프로세스를 띄우고 라우터나 로드 밸런서 등으로 요청을 각 프로세스로 분산시켜주어야함.

  • Node 의 핵심 철학은 비동기로 동작하여 I/O 작업일 경우 워커스레드에 던져두고 이벤트 루프는 다른일을 한다는 것이며 이때 I/O작업 처리는 libuv가 담당함.

  • 그러면, Node.js 싱글 스레드일까요?

    보통 Javascript는 싱글 스레드라고 합니다. 그럼 자바스크립트가 실행되는 환경인 노드는 싱글일까?

    ⇒ 정확하게 말하면 노드는 싱글스레드가 아닙니다.

    “자바스크립트를 실행하는 스레드는 단 하나이므로…”

  • 그러면, libuv는 뭔가요?

    libuv란 C/C++로 작성된, Node.js가 사용하는 비동기 I/O 라이브러리입니다.

    이는 사실 운영체제의 커널을 추상화한 Wrapping된 라이브러리로 커널이 어떤 비동기 API로 지원하는지 알고 있다고합니다.

    • 그러면, 어떻게 처리를하나요?

      우리가 libuv에게 파일 읽기와 같은 비동기 작업을 요청하면 libuv는 이 작업을 커널이 지원하는지 확인합니다. 만약 지원한다면 libuv가 커널에게 비동기적으로 요청했다가 응답이 오면 그 응답을 우리에게 전달해줌. 만약 요청한 작업을 커널이 지원하지 않는다면 자신만의 워커스레드가 담긴 스레드 풀을 사용함.

      libuv는 기본적으로 4개의 스레드를 가진 스레드 풀을 생성함.

      결국에는, 이벤트 루프가 싱글 스레드이며, 블로킹 I/O 관련된 작업을 처리하는 백그라운드는 멀티스레드로 이루어져있다. I/O관련 블로킹 작업은 OS또는 libuv의 thread pool에서 처리하여 이벤트 루프가 blocking되지 않게 함.

      여기서 그러면, libuv와 Event loop와의 관계가 뭐길래, 어떻게 싱글 스레드로 논블로킹 비동기 작업을 지원하는가에 대해 궁금증이 생깁니다.

      간단하게 정리하자면, Node.js는 I/O작업을 자신의 메인 스레드가 아닌 다른 스레드에 위임함으로써 싱글 스레드로 논 블로킹 I/O를 지원함. 다시 말해, Node.js는 I/O작업을 libuv에 위임함으로써 논 블로킹 I/O를 지원하고 그 기반에는 이벤트 루프가 있음.

  • 그러면, 싱글 스레드라면서 비동기 작업은 어떻게 가능할까요?

    스레드가 하나라면 동시에 하나의 작업만 처리할 수 있습니다. 어떻게 비동기 처리가 가능할까요?

    비동기란 먼저 실행된 코드의 작업이 끝나기 전에 더 나중에 실행된 코드의 작업이 끝날 수 있음을 의미합니다. 즉, 동시성을 가지고 있는 코드들이죠.

    스레드가 하나임에도 동시성이 지원되는 이유는 바로 “이벤트 루프” 라는 친구 때문입니다.

    그렇다면 이벤트 루프는 무엇일까요?

    • 이벤트 루프

      • 이벤트 루프는 Node.js가 여러 비동기 작업을 관리하기 위한 구현체입니다.

      • 이벤트 루프는 싱글 스레드이며 메인 쓰레드이며 비즈니스 로직을 수행합니다.

        console.log(’…’) 와 같은 동기 작업이 아니라 file.readFile(’test.txt’,callback)과 같은 비동기 작업들을 모아서 관리하고 순서대로 실행할 수 있게 해주는 도구임.

        Timer Phase, Pending Callbacks Phase, Idel,Prepare Phase, Poll Phase, Check Phase, Close Callbacks Phase로 구성되어있음.

        한 페이즈에서 다음 페이즈로 넘어가는 것을 틱(Tick)이라고 합니다.

'Web > JavaScript' 카테고리의 다른 글

JavaScript란?  (0) 2024.03.05
[Node.js] 이벤트 디멀티플렉싱  (0) 2024.03.05
[Javascript] 얕은 복사와 깊은 복사  (0) 2024.02.05


컴퓨터는 H/W, Kernel, User 로 크게 3가지로 구분지어 볼 수 있습니다.

운영체제는 소프트웨어로서 App이 잘 동작하도록 Support하며 H/W를 제어및 관리를 합니다.

  • 인터럽트 (Interrept) : 쉽게 말해, 집에서 일을 하고 있는데 초인종을 눌러 일을 중단하게 됨.
    • 내부 인터럽트와 외부 인터럽트로 나눌 수 있음.
  • 즉, CPU가 프로그램을 실행하고 있을 때, 입출력 하드웨어 등의 장치에 예외상황이 발생하여 처리가 필요한 경우 CPU에 알려 처리할 수 있도록 하는 것.
  • 인터럽트 동작 순서
  • 1. 인터럽트 요청 2. 프로그램 실행 중단 : 현재 실행중이던 Micro option까지 수행함 3. 현재의 프로그램 상태 보존 : PCB, PC 등 4. 인터럽트 처리 루틴 실행 : 인터럽트를 요청한 장치를 식별함 5. 인터럽트 서비스 루틴 실행 : 인터럽트 원인을 파악하고 실질적인 작업을 수행함. 처리기 레지스터 상태 보존, 서비스 루틴 수행 중 우선순위 높은 것, 인터럽트 발생 재귀적으로 1~5과정 수행 6. 상태 복구 : 인터럽트 발생 시 저장해둔 PC를 다시 복구함 7. 중단된 프로그램 실행 재개 : PC의 값을 이용하여 이전에 수행 중이던 프로그램을 재개함.
  • DMA(Direct Memory Access)Hello.. 라는 Data 가 prinft()라는 함수 내에서 Write()를 함. 이때의 정보가 RAM으로 Hello가 전달됨여러 단계를 거치는 과정이 복잡하다보니 성능이 떨어짐(비효율적임).DMA Controller를 이용하면 하드디스크와 메모리를 직접 연결하여 CPU는 제어신호만 주고받을 뿐 데이터 전송에서 제외시킬 수 있다. 따라서 입출력 시 CPU는 제어를 위해 데이터 전송 시작과 완료에만 할당되어 CPU 자원의 낭비를 줄 일 수 있게됨.
  • 위의 방식의 단점을 개선한 것이 DMA방식입니다. 이름 그래도 입출력장치가 메모리에 직접 접근한다는 뜻임.
  • 이때 인터럽트가 발생됨. 이것을 주변기기로 옮기면서 또 인터럽트가 발생할수 있음. hello를 띄우는데
  • 예를 들어, “Hello World!”라는 Data를 화면에 띄우려고 한다.

'CS(Computer science) > 운영체제' 카테고리의 다른 글

CPU 스케줄링 (1)  (0) 2024.03.05

+ Recent posts