connecting dots

Beginner 9회차 (8/7) | 콜스택(Call Stack)과 이벤트루프(Event Loop), 리액트 라우터(React Router)를 이용한 프로젝트 페이지 관리, 라우팅의 종류(기본/중첩/동적 라우팅) 본문

Live Class/Beginner

Beginner 9회차 (8/7) | 콜스택(Call Stack)과 이벤트루프(Event Loop), 리액트 라우터(React Router)를 이용한 프로젝트 페이지 관리, 라우팅의 종류(기본/중첩/동적 라우팅)

dearsuhyun 2024. 8. 7. 21:43

콜스택과 이벤트루프

출처: 박영웅 강사님 강의자료

 

콜스택(LIFO: Last In, First Out)

콜 스택은 함수 호출이 쌓이는 곳

JavaScript는 단일 스레드 언어로, 한 번에 하나의 작업만 수행할 수 있는데, 콜 스택은 이러한 작업들을 순서대로 처리한다

 

콜스택이 꽉 찬 경우 이러한 에러 메세지가 발생함. 동시에 너무 많은 실행이 되고 있음.

 

이벤트 루프(FIFO:First In, First Out)

이벤트 루프는 JavaScript 런타임 환경에서 비동기 작업을 처리하는 메커니즘

콜 스택이 비어 있는지 확인하고, 비어 있으면 큐(Queue)에 대기 중인 콜백 함수를 콜 스택으로 이동시킨다

 

예제

 

--> 실행 순서

1. console.log('Start')가 호출되어 콜 스택에 추가되고 실행됩니다.

2. setTimeout 함수가 호출되어 콜 스택에 추가됩니다. setTimeout 함수는 Web API를 통해 타이머를 설정하고, 콜백 함수를 큐로 전달합니다. setTimeout 함수는 콜 스택에서 제거됩니다.

3. console.log('End')가 호출되어 콜 스택에 추가되고 실행됩니다.

4. 1초 후, 타이머가 완료되면 setTimeout의 콜백 함수가 큐로 이동합니다.

5. 콜 스택이 비어 있으면 이벤트 루프가 큐에서 콜백 함수를 가져와 콜 스택에 추가하고 실행합니다.

 

Web API

비동기 작업을 처리하고, 콜백 함수를 큐에 추가

Web APIs

• Fetch API: 서버와의 네트워크 통신을 비동기적으로 처리하는 API.
fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));​

1. fetch(‘https://api.example.com/data’):

fetch 함수는 주어진 URL로 HTTP 요청을 보내고, Promise 객체를 반환합니다. 이 요청은 비동기적으로 처리됩니다.

URL은 https://api.example.com/data입니다.

2. .then(response => response.json()):

첫 번째 then 메서드는 fetch 요청이 완료되고 응답이 도착했을 때 호출됩니다.

response 객체는 HTTP 응답을 나타내며, response.json() 메서드를 호출하여 JSON 형식의 응답 본문을 JavaScript 객체로 변환합니다.

response.json()Promise를 반환하므로, 다음 then 메서드로 연결됩니다.

3. .then(data => console.log(data)):

두 번째 then 메서드는 response.json()이 완료된 후 호출됩니다.

data는 변환된 JSON 데이터입니다.

console.log(data)를 통해 데이터를 콘솔에 출력합니다.

4. .catch(error => console.error(‘Error:’, error)):

catch 메서드는 요청 중 발생한 오류를 처리합니다.

네트워크 오류나 JSON 변환 오류가 발생할 경우, catch 블록이 실행되어 오류 메시지를 콘솔에 출력합니다.



• Timeout: 일정 시간이 지난 후에 함수를 실행하는 API.
setTimeout(() => {
  console.log('This will run after 2 seconds');
}, 2000);​
// 0초가 기본 값


cf. node.js 에서 사용 가능할까 ? YES !
Node API(명령)라는 것이 따로 있어서 작동 가능

// node API 예시

import fs from 'fs'
fs.writeFileSync('test.txt', 'Hello, world')

// node test.js 터미널에서 실행 가능


(참고: node js에는 DOM API가 없어서 document.querySelector('html') 동작 안함)
--> 자바스크립트라는 프로그래밍 언어가 동작하는 환경은 1) 웹 브라우저, 2) node js가 설치된 컴퓨팅 환경


• Interval: 일정한 시간 간격으로 함수를 반복적으로 실행하는 API.
setInterval(() => {
  console.log('This will run every 1 second');
}, 1000);​

• Location: 현재 문서의 URL을 가져오거나 변경하는 객체.
// 현재 URL을 가져오기
console.log(window.location.href);

// URL을 변경하기
window.location.href = 'https://example.com';​

• History: 브라우저의 세션 히스토리를 조작하는 API.
// 뒤로 가기
window.history.back();

// 앞으로 가기
window.history.forward();

// 특정 페이지로 이동
window.history.go(-2); // 두 페이지 뒤로 이동​

• Navigation: 페이지 간의 이동 이벤트와 상태를 관리하는 API.
navigation.addEventListener('navigate', (event) => {
  console.log("사용자가 이동하려는 주소:", event.destination.url);
  if (event.destination.url.includes('restricted')) {
    event.preventDefault(); // 특정 페이지로의 이동을 막음
    console.log("이 페이지로는 갈 수 없습니다!");
  }
});​

• DOM: 웹 페이지의 구조를 조작하고 스타일을 적용하며 이벤트를 처리하는 API.
// 요소 선택
const element = document.getElementById('myElement');

// 텍스트 변경
element.innerText = 'Hello, World!';

// 클래스 추가
element.classList.add('active');​

 

 

큐(Queue)

비동기 작업의 콜백 함수들이 대기하는 곳

 

1. 매크로 태스크 큐 (Macrotask Queue):
   - 큰 작업들을 담는 주머니
   - 예: setTimeout, setInterval, I/O 작업, UI 렌더링 등

2. 마이크로 태스크 큐 (Microtask Queue):
   - 작고 빠른 작업들을 담는 작은 주머니
   - 예: Promise, process.nextTick, queueMicrotask 등

--> 둘 다 콜백 함수 이벤트 핸들러를 일시 저장한다는 점에서 동일하지만, 태스크 큐보다 마이크로태스크 큐가 더 우선순위가 높다.
즉, 이벤트 루프는 콜 스택이 비면 먼저 마이크로태스크 큐에서 대기하고 있는 함수를 가져와 실행한다.
이후 마이크로태스크 큐가 비면 태스크 큐에 대기하고 있는 함수를 가져와 실행한다.

 

** 자바스크립트 엔진은 매크로태스크 하나를 처리할 때마다

또 다른 매크로태스크나 렌더링 작업을 하기 전에 마이크로태스크 큐에 쌓인 마이크로태스크 전부를 처리합니다.

setTimeout(() => alert("timeout"));

Promise.resolve()
  .then(() => alert("promise"));

alert("code");

얼럿 창엔 아래 순서대로 문자열이 출력됩니다.

  1. code – 일반적인 동기 호출이므로 가장 먼저 매크로태스크 큐에 들어간 후 실행됩니다.
  2. promise  .then은 마이크로태스크 큐에 들어가 처리되기 때문에, 현재 코드(alert("code"))가 실행되고 난 후에 실행됩니다.
  3. timeout  setTimeout에서 설정한 시간이 끝난 후 콜백 함수를 실행하는 것은 매크로태스크이기 때문에 가장 마지막에 출력됩니다.

매크로태스크와 마이크로태스크 처리 로직을 첨가하면 위에서 살펴본 그림을 좀 더 고도화 할 수 있습니다. 그림을 위에서부터 아래로 봅시다. 매크로태스크(script, mousemove, setTimeout 등) 하나가 처리되고 난 후 마이크로태스크 전부(microtasks)가 처리되고 그 이후 렌더링이 진행되는 것을 확인할 수 있습니다.

 

https://velog.io/@minyoung22222/%ED%83%9C%EC%8A%A4%ED%81%AC-%ED%81%90%EB%A7%A4%ED%81%AC%EB%A1%9C%ED%83%9C%EC%8A%A4%ED%81%AC-%ED%81%90-VS-%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%ED%83%9C%EC%8A%A4%ED%81%AC-%ED%81%90

 

리액트 기본 세팅 이해

main.tsx

ReactDOM.createRoot(document.getElementById('root')!).render(<App />)

 

root요소 생성

root라는 아이디를 가진 요소를 찾아서 App 컴포넌트 출력 할거야 !

'!' 삭제하면 에러남 --> 타입스크립트는 요소가 null일 수도 있다고 생각함. 개발자가 타입 단언으로 root 있다고 해주는 것

 

리액트 라우터(React Router)

주소 제어 장치

(route는 page를 의미, routes는 page들, router는 page와 관련된 것들을 제어하는 기능이라고 이해해도 됨 !)

 

1) HashRouter

https://도메인/#/movies/:id

 

HashRouter는 URL의 해시(#) 부분을 사용하여 클라이언트 측 라우팅을 관리한다.

URL의 해시 부분은 서버에 전송되지 않으므로, 서버 설정을 변경할 필요가 없다 !

HashRouter는 주로 간단한 애플리케이션이나 서버 설정을 수정할 수 없는 환경에서 사용됩니다.

import { createHashRouter } from 'react-router-dom'

 

2) BrowserRouter

https://도메인/movies/:id

BrowserRouter는 HTML5의 History API를 사용하여 클라이언트 측 라우팅을 관리한다.

이 방식은 URL이 일반적인 웹 애플리케이션의 URL과 동일하게 동작하며, 보다 직관적이고 깔끔한 URL을 제공한다.

BrowserRouter를 사용하려면 서버 설정이 필요할 수 있다 !

import { createBrowserRouter } from 'react-router-dom'

 

프로젝트에 라우터 설정하기

 

페이지 단위로 사용할 컴포넌트 App.tsx 파일은 routes 폴더 안으로 넣어주는 것이 좋음.

--> import 절대경로 설정 --> vite로 !

(상대경로로 설정하면 작은 규모의 프로젝트에서는 괜찮지만 큰 프로젝트에서는 ../../../../ 등 너무 많이 ../를 써야하는 문제가 존재

또한 파일을 옮기게 되더라도 수정해야 할 필요가 없어지므로 편리함 !)

'~' 틸드 기호도 많이 사용함

 

--> App.tsx에서 @로 바꾸면 에러 발생 (빌드했을 때는 정상적으로 작동하지만 타입스크립트에서 에러 발생)

--> 타입스크립트에도 설정을 해줘야 함

tsconfig.app.json

 

--> 설정해도 안 되면 command + shift + p --> restart ts server(타입스크립트 서버 다시 시작) 해주면 됨

 

--> 이제 App.tsx 이 최상위 컴포넌트가 아니기 때문에(이제는 RouterProvider) Main.tsx로 이름 변경

main.tsx 파일

App 컴포넌트 대신 RouterProvider 컴포넌트를 써주기

router라는 prop이 있어서 routes 폴더에 정의해놓은 index.tsx 파일을 넣어주면 되는데 위에서 가져오고 있으니

route={router} 이렇게 넣어주면 됨 --> react router로 폐이지가 관리된다는 뜻

// index.tsx 파일
import { createBrowserRouter } from 'react-router-dom'
import Main from './Main'

export const router = createBrowserRouter([
  {
    path: '/',
    element: <Main />,
    children: []
  }
])

 

 

index.tsx 파일에 메인 페이지(랜딩 페이지)를 띄우는 걸 설정해줌 ! element에 <Main /> 컴포넌트 넣어주기

 

페이지 추가하기

routes 폴더에 출력하고 싶은 컴포넌트 만들어서 연결 !

메인 주소 뒤에 /dashboard 넣으면 위 컴포넌트 페이지로 이동함

 

하위 페이지 설정

dashboard 페이지의 하위페이지를 어디에 출력할지 결정할 수 있음 !

--> { Oulet } 컴포넌트를 사용해서 지정해줌

 

<Dashboard /> 밑에 하위페이지가 뜨는 것을 볼 수 있음

 

여러가지 라우팅 방식

1. 중첩 라우팅

--> <Dashboard />에는 '분석 페이지' 라는게 없고, 하위 페이지에는 'Hello Dashboard page'가 없지만

dashboard 페이지에 들어가면 둘 다 화면에 표시됨 = dashboard의 하위 페이지로 설정했기 때문에 !

children 속성 안에 또 children 속성 만들 수 있음

모달을 띄우는 경우 이 방식을 사용

{
    path: '/dashboard',
    element: <Dashboard />,
    children: [{
      path: 'analytics',
      element: <Analytics />,
    }]
  }

 

2. 기본 라우팅(별개의 객체로 설정해주는 방식) dashboard 페이지에 접속해도 '분석 페이지 !' 표시 되지 않음

{
    path: '/dashboard',
    element: <Dashboard />,
  },
  {
    path: '/dashboard/analytics',
    element: <Analytics />,
  }

 

3. 동적 라우팅

/dashboard/:heropy

--> 이 주소에 들어올 수 있는 모든 동적인 주소는 heropy라는 이름으로 받아서 컴포넌트에서 쓸 수 있게 해주는 방식 !

주로 :id, ({id})로 지정함.

{
    path: '/dashboard',
    element: <Dashboard />,
    children: [{
      path: ':heropy',
      element: <Analytics />,
    }]
  }
// DashboardAnalytics.tsx

import { useParams } from 'react-router-dom'

export default function DashboardAnalytics() {
  const { heropy } = useParams()
  return <h2>분석 페이지! ({heropy})</h2>
}

 

--> 지금 주소 /dashboard/analytics

but 123으로 바꾸면 ?

 

동적 라우팅(dynamic routing)은 URL의 일부가 변할 수 있는 라우팅 방식으로, URL 경로의 특정 부분을 변수로 취급하여 다양한 URL 패턴을 처리할 수 있게 해줍니다. 이를 통해 단일 라우트 정의로 여러 경로를 처리할 수 있습니다.

동적 라우팅의 예
예를 들어, 블로그 애플리케이션에서 각 블로그 게시물의 ID에 따라 다른 페이지를 보여주어야 한다고 가정해봅시다. 동적 라우팅을 사용하면 이러한 경로를 간단히 정의할 수 있습니다.

 

설정해주지 않은 페이지로 접근하면 나오는 404 페이지 ! vite에서 제공해주는 기본 페이지이고 우리가 custom 할 수 있고, 해야 함 !

 

 


* promise 객체 공부해보고 질문하기

* Redux 개념을 이해하는 느낌으로 공부해보기 (너무 깊게 말고)

* git switch -h (명령어 뭔지 알고 싶을때)

* 정규표현식 (기호와 기능을 연관지어 생각하기 어렵기 때문에 암기해야 해요 ,,)
* = 0개 이상 모두 일치, wildcard
+ = 1개 이상 모두 일치
초격차 패키지 - 정규표현식 강의 있는 정도는 알아두기

* routes 폴더를 만드는 이유 ? 관리를 편리하게 하기 위함 !
components 폴더 --> 재사용 혹은 캡슐화를 목적으로 하는 컴포넌트에서 관리
routes 폴더 --> 페이지를 출력하는 컴포넌트를 관리 (pages 대신 routes로 씀)

* 나중에 node api 공부도 해보기 !

 

 

https://reactrouter.com/en/main

 

Home v6.26.0 | React Router

 

reactrouter.com

 

https://heropy.blog/2018/10/28/regexp/

 

정규표현식, 이렇게 시작하자!

매일 쓰는 것도, 가독성이 좋은 것도 아니지만, 모르면 안되는 정규표현식. 저는 이렇게 공부하기 시작했습니다! (자바스크립트를 기준으로 설명합니다)

heropy.blog

https://velog.io/@yejineee/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84%EC%99%80-%ED%83%9C%EC%8A%A4%ED%81%AC-%ED%81%90-%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C-%ED%83%9C%EC%8A%A4%ED%81%AC-%EB%A7%A4%ED%81%AC%EB%A1%9C-%ED%83%9C%EC%8A%A4%ED%81%AC-g6f0joxx

 

이벤트 루프와 태스크 큐 (마이크로 태스크, 매크로 태스크)

자바스크립트는 싱글 스레드 기반의 언어이고, 자바스크립트 엔진은 하나의 호출 스택만을 사용한다. 이는 요청이 동기적으로 처리되어, 한 번에 한 가지 일만 처리할 수 있음을 의미한다. 만약

velog.io

 

https://ko.javascript.info/event-loop

 

이벤트 루프와 매크로태스크, 마이크로태스크

 

ko.javascript.info

https://www.jsv9000.app/

 

JS Visualizer 9000

 

www.jsv9000.app

 

반응형