재사용 가능한 컴포넌트들이 위치하는 폴더로 컴포넌트는 매우 많아질 수 있기 때문에 이 폴더 내부에서 하위폴더로 추가로 분류합니다
assets
컴포넌트 내부에서 사용하는 이미지 파일인 경우 이 assets 폴더에 위치시킵니다
hooks
커스텀훅이 위치하는 폴더입니다
pages
라우팅을 적용할 때 페이지 컴포넌트를 이 폴더에 위치시킵니다
enums
enum 관련 파일이 들어갑니다
constants
공통적으로 사용되는 상수들을 정의한 파일들이 위치하는 폴더입니다
config
config 파일이 따로 있는 경우 둡니다
styles
css 파일이 포함되는 폴더입니다
service
외부 API와 상호작용하는 모든 코드들을 넣으며 auth와 같이 인증과 관련된 파일을 포함합니다
utils
정규표현식 패턴이나 공통함수 등 공통으로 사용하는 유틸 파일들이 위치하는 폴더
redux
리덕스 폴더가 들어갑니다
프로젝트 구조의 정답은 없다 React의 경우 feature으로 분리하는 방식을 많이 이야기한다 이걸 사용하면 ToDo 기능, 인증 등으로 기능별로 분리할 수 있다 feature/ToDo안에 ToDo관련 components, ToDo.tsx, css 등 관련된 걸 다 넣는다 이럴 경우 기능별로 딱 깔끔하게 되겠지만 양이 엄청 많아질 거고 A라는 페이지에서 쓰는 ToDo랑 B라는 페이지에서 쓰는 ToDo가 살짝 다를 수도 있다 특징별로 분리한 건 어떤 기능이 있는지 확인하고 기능별로 분리가 철저해 보이지만 실제 프로젝트를 하면 재활용성을 완벽하게 하는 경우가 그렇게 많지 않다
그럴바에 그냥 DDD구조처럼 중복되더라도 (Auth같이 무조건 공통인 경우는 따로 분리 필요) 살짝 달라서 안에서 분기태우고 이럴바에야 그냥 또 다른 이름으로 제대로 만드는게 좋아보인다
또한 업무도 페이지의 어떤 영역을 맡게 될테고 백엔드도 DDD구조로 가면 프론트에서도 찾기 쉽게 DDD로 가져가는게 프로젝트 이해와 해당 페이지를 찾는게 더 쉬워보인다 그래서 개인적으로는 DDD의 구조를 가져가는게 좋아보인다
→ 물론 프론트랑 백엔드랑 확실히 구분되어있어서 프론트는 백엔드 프로젝트를 볼 일이 없을 경우는 제
이진 데이터의 경우 따로 매핑이 필요하다 → GraphQL의 경우 applicaiton/json으로만 통신하게 되어있기 때문에 나머지는 막아놨다 허용하게 하려면 Header에 값을 붙여서 보내야 mutlipart/form-data도 허용이 된다
자세한 내용들은 아래 참고 및 출처를 확인 하길 바랍니다
!!!
근데 해보니까 이진데이터를 보내서 받아 DB에 저장까지는 되었다만 DB 이진 데이터를 다시 GraphQL로 return이 안 된다 GraphQL은 application/json 타입으로만 return하는 형태로 만들어져있기 때문에 Response 객체를 얻어서 조작하는 행위가 안 됨 → Response에 Buffer를 담고 어떤 파일 형식인지 Header에 보내면 호출 시 해당 파일 보내질텐데 그게 안 됨 이럴바에 그냥 base64로 보내고 base64로 받자
스트림 데이터를 조금씩 저장하며 처리하고 비우기를 반복하는 메모리 공간으로 이러한 행위를 버퍼링이라고합니다
📝스트림 + 버퍼
동영상의 경우 전부 다운 받은 후에 영상을 재생시킨다면 엄청나게 오래 기다려야할 수도 있다 이럴 경우 스트림을 이용하며 버퍼에 처리된 걸 담은 후에 사용자에게 보내주면 사용자는 모든 영상이 로드될 때까지 안 기다려도 볼 수 있다
📝Blob (Binary Large Object)
이진 데이터를 저장하기 위한 데이터 형식으로 주로 이미지, 오디오, 비디오, 문서 등의 바이너리 데이터를 저장하는 사용됩니다
멀티미디어 파일들은 대다수 용량이 큰 경우가 많기 때문에, 이를 데이터베이스에 효과적으로 저장하기 위해 고안된 자료형으로 바이너리 데이터를 다루기 위해 객체(Object) 저장한다
📝ArrayBuffer
객체는 이미지, 동영상과 같은 멀티미디어 데이터 덩어리를 표준 자바스크립트(브라우저)에서 다루기 위해 도입됐다 즉, 자바스크립트에서 원시 데이터(바이너리 데이터)를 직접 다루는 수단이다
이러한 이진데이터를 직접 보거나 수정하기 위해서는 위해서는 TypedArray가 따로 필요하다
TypedArray에는 여러개가 있다
Uint8Array
0 ~ 255 범위를 다룬다
Uint16Array
0 ~ 65535 범위를 다룬다
Uint32Array
0 ~ 4294967295 범위를 다룬다
Float64Array
8바이트 단위로 부동 소수점 방식으로 접근 가능한 view 객체
let buffer = new ArrayBuffer(16);
let view = new Uint8Array(buffer);
view[0] = 255;
console.log(buffer);
console.log(view);
ArrayBuffer에 데이터 넣어서 확인해볼 수 있다 Unit8Array이기 때문에 255까지 표현이 가능하기 때문에 256이 들어오면 0이 된다
콘솔창에 메모리 아이콘을 누르면 바이너리를 확인할 수 있다 FF 즉 255가 들어간 걸 확인 가능
📝 ArrayBuffer로 데이터 보내기
<input type="file" id="fileInput">
document.getElementById('fileInput').addEventListener('change', async (event) => {
const file = event.target.files[0];
const reader = new FileReader();
reader.onloadend = async () => {
const arrayBuffer = reader.result;
// fetch API를 사용하여 서버로 데이터 전송
const response = await fetch('your-backend-endpoint-url', {
method: 'POST',
headers: {
'Content-Type': 'application/octet-stream',
},
body: arrayBuffer,
});
// 서버로부터의 응답 처리
const result = await response.text();
console.log(result);
};
// File To ArrayBuffer
reader.readAsArrayBuffer(file);
});
<input type="file">에서 등록된 파일의 정보를 읽어 ArrayBuffer로 바꾼 뒤 octet-stream이라는 이진형태로 보내겠다는 Content-Type을 설정하고 보내면 된다
문제사항은 얘가 이미지인지 텍스트인지 동영상인지 등에 대한 정보가 없기 때문에 Base64로 인코딩 및 MIME-TYPE을 Json에 담아서 보낸다 이럴 경우 ArrayBuffer로 못 보낸다 근데 굳이 ArrayBuffer로 어렵게 보내는 것보다는 아래에 설명하는 방법으로 하는게 더 적합하다
물건을 먼저 사는 것에서 유래했으며 예를 들면 A라는 떡가게가 있고 B라는 농부가 있다 A는 이번년도말에 쌀 가격이 오를 거라 생각해 B에게 연말에 15,000원에 쌀을 받기로 계약을 한다 쌀가격이 오른 경우 떡가게는 이득을 보고 쌀가격이 내린 경우에는 떡가게는 손해를 보게 된다
대부분 선물옵션이라고 하는 것은 지수선물을 의미한다 국장에서 코스피200 선물매수라는 건 코스피200 지수가 상승한다에 배팅하는 것을 의미하고 코스피200 선물매도는 지수가 하락한다에 배팅하는 것을 의미한다
📝상품선물
원유, 금, 은, 구리 등에 투자하는 선물거래 상품
📝금융선물
지수, 채권, 달러 등에 투자하는 선물거래 상품
📝신용거래
물건을 먼저 받고 돈을 나중에 주게 되는 거래
📝시장가격
수요와 공급에 따라 결정수요가 많을수록 비싸지고 수요가 없을수록 싸진다 희귀하고 가치있을 수록 비싸지고 (메시 유니폼) 가치가 없고 흔할 수록(내가 입은 유니폼) 싸진다
📝IPO
기업공개로서상장해도 될지를 심사하고상장된 주식이 거래될 수 있도록 기업의 주요정보를 공개하는 절차이다.
📝M&A
기업합병과 경영권 인수를 뜻하는 기업인수를 의미한다.
📝시리즈A
최초 투자금을 받는 단계로서약 100억의 기업 가치를 의미합니다.
📝시리즈B
제품이 상품화 되는 단계로서 기업 가치는약 400억의 기업 가치를 의미합니다.
📝시리즈C
상품화 된 제품을 여러 시장의 확장하는 수준으로서단기간에 크게 키울 수 있는 방법으로는 M&A가 있습니다. 시리즈C정도면 이미 국내에서 크게 성공을 거뒀고 해외로 확장할 시기입니다.
참고로 간단하게 정리한 내용이고 각 단계에 대한 투자자의 생각, 창업자의 생각 등에 대한 요소는 들어가있지 않습니다.
클라이언트 요청 → NIC Buffer → Socket Buffer → Application Buffer → 클라이언트 요청 정보 해석 (파일 읽기일 때) → OS에 파일읽기 요청 → Read Buffer 저장 → Application Buffer로 전송 → Socket Buffer로 전송 → NIC Buffer로 전송 → 네트워크를 이용해 클라이언트에게 전송
Read Buffer
파일 시스템이나 데이터베이스로부터 데이터를 읽을 때 사용됩니다
Application Buffer
보통 사용자가 HTTP로 데이터를 요청하기 때문에 WAS에 Read Buffer 내용이 들어가게 됩니다
필요한 형식으로 변환하거나 추가 데이터 작업을 할 수 있습니다
Socket Buffer
네트워크에 전송되기 전에 임시적으로 저장됩니다
TCP/IP 프로토콜을 통해 데이터를 전송하기 전에 이곳에 저장되게 됩니다
NIC Buffer
데이터가 네트워크를 통해 전송되기 위해서는 먼저 NIC Buffer로 이동하게 됩니다
DMA copy
DMA(Direct Memory Access Copy)로 CPU의 개입 없이 메모리간 데이터를 직접 선송할 수 있는 컴퓨터 시스템 기능입니다
OS 커널 영역에서는 DMA Copy를 한다
CPU Copy
CPU를 이용해 데이터를 메모리에서 다른 메모리로 이동하는 방법으로 WAS로 읽어들이는 경우 사용된다
✅ OS, WAS, DB가 다른 서버에 설치되어있는 경우
클라이언트 요청 → NIC Buffer로 전송 → Socket Buffer로 전송 → Application Buffer로 전송 → DB 호출 → Socket Buffer에 DB 요청 정보 보내기 → NIC Buffer로 전송 → DB 설치 서버에 NIC Buffer로 접근 → Socket Buffer로 전송 → DB에서 처리 후 Socket Buffer로 전송 → NIC Buffer로 전송 → NIC Buffer에서 받기 → Socket Buffer로 전송 → WAS 추가 작업 진행 끝낸 후 Socket Buffer로 전송 → NIC Buffer로 전송 → 네트워크를 이용해 클라이언트에게 전송
✅ OS, WAS 같은 서버에 설치되어있는 경우 (DB Connection X)
클라이언트 요청 → NIC buffer → Application Buffer로 전송 → Socket Buffer로 전송 → NIC Buffer로 전송 → 네트워크를 이용해 클라이언트에게 전송
📝Zero Copy
맨 위에 설명한 OS, WAS, DB가 같은 서버에 있는 경우 WAS에서 따로 처리가 필요 없는 경우 Read Buffer를 바로 Socket Buffer를 이용하는게 좋다
굳이 Socket에 담을 필요 없이 NIC Buffer로 바로 보내면 더 성능에 이점을 가지게 된다 이럴 경우 Buffer에 담는 행위가 줄어들기 때문에 Copy의 과정이 Zero에 가까워진다