한 입 크기로 잘라먹는 React

이안이다·2023년 5월 14일
0

React

목록 보기
2/6
post-thumbnail

Section 3. Jacascript 응용

지난 시간까지 js의 기본적인 문법들과 자주 쓰는 내장 함수들 몇 가지까지 공부했다.
아는 내용이 대다수이긴 했지만 내장함수들은 처음 보는 게 많았고 파이썬에서 자주 쓰던 메소드들이랑 비슷해서 반갑기도 했고 되려 헷갈리기도 했다. sort()같은건 js에서 문자열을 기준으로 정렬하는거라 숫자를 오름차순 or 내림차순으로 정렬하려면 내가 따로 계산식을 작성해줘야 한다는 번거로움이 있었다... 아무튼 공부한 내용들을 바탕으로 이제부턴 js응용 섹션 ! 아자아자 ! ! !


Truthy, Falsy의 개념을 이해해야하는데
예를들어 선언되기만 하고 값이 초기화되지 않은 변수는 js가 false라고 판단한다.
근데 비어있는데 선언되기만 한 배열은 또 true라고 판단한다.
이런 js의 특성을 Truthy, Falsy라고 한다 !

const getName = (person) => {
  return person.name;
};

let person = { name: "김이안" };

const name = getName(person);
console.log(name);

getName이라는 함수에 전달되는 person이라는 파라미터가 "김이안"이라는 name을 갖고있는 객체를 전달하는 거고 에러 없이 "김이안"이라는 출력값이 console에 찍히게 된다.

하지만 만약 여기서 person이라는 값을 undefined으로 전달한다면 어떻게 될까?

위와 같은 에러가 발생한다. 왜그럴까?
undefined은 객체가 아니기 때문이다.

따라서 이런 코드를 작성할 때는 전달 받아오는 파라미터가 객체인지 아닌지, undefined이나 null인지 아닌지를 판단하는 조건문이 붙어줘야 한다.

const getName = (person) => {
  if (person === undefined || person === null) {
    return "객체가 아닙니다";
  }
  return person.name;
};

let person = { name: "김이안" };

const name = getName(person);
console.log(name);

이렇게 하는게 정석이다. 근데 매번 이렇게 조건문 코드를 달 수는 없지 당연히. 귀찮잖아 !!!

if (person === undefined || person === null) 이 조건문을
if (!person) 이라고 하면 된다.

undefined 와 null은 조건문에서 false를 갖는 js의 성격 때문에 이렇게 처리가 가능한거임

따라서

if (!person) {} //이거는 falst에다가 NOT을 붙여서 True를 만들어내서 "객체가아니다"를 리턴해내는 방법임

이게 Falsy !!!



자 삼항 연산자 이거 또 군대에서 열심히 공부했던 것들 중 하나지
예를들어 아래와 같이 배열이 비었는지 안비었는지 판단하는 코드가 있다고 할 때

let a=[];
if (a.length===0){
  console.log("배열 비었다 !!");
}
else {
  console.log("배열에 뭐가 들어있다 !!");
}

이런 코드가 있다고 할 때, 삼항 연산자를 쓰면 한 줄로 줄여버릴 수 있음.

a.length === 0? console.log("배열 비었다 !!") : console.log("배열에 뭐가 들어있다 !!");

물음표를 조건으로 쓰고 그 뒤에 콜론(:)을 기준으로 왼쪽에 True일 때 실행될 명령, 오른쪽이 False일 때 실행될 명령을 입력하는 방식.

근데 꼭 이렇게 명령문을 다 각각 적어주지 않고 하나의 변수에다가 그냥 값을 저장하게 하는 방법도 있음

const isEmpty = a.length === 0? "배열 비었다 !!" : "배열에 뭐가 들어있다 !!";
//이렇게 해놓고 나서
console.log(isEmpty);

이렇게 !
아유 쉽다 쉬워 ~

그리고 삼항연사자는 중첩으로 여러개 붙여 쓸 수도 있긴한데 가독성이 떨어지기 때문에
딱 true일 때, false일 때를 기준으로 (if문 하나)쓸 때가 아니라면, 그냥 if elseif else로 사용하는게 낫다.



자 이번엔 단락 회로 평가!
논리회로는 알아도 단락회로는 첨 들어보는데...

일단 단락회로는 왼쪽에서 오른쪽으로 연산하게되는 연산자의 논리 순서를 이용하는 문법이다.

예를들어서

console.log(false && true);

라는 코드가 있다고 했을 때, 피연산자 두 개가 모두 true여야 true를 반환 할 수 있는 거잖아?
근데 앞에 있는 피연산자가 이미 false야. 그럼 뒤에있는 피연산자는 볼 필요도 없이 그냥 저건 어차피 false란 말이지?
이게 바로 단락 회로 평가이다.

Truthy랑 Falsy를 이용해서 좀 더 섹시하게 단락회로평가 쓰긴 하던데 굳이...? 같아서 그냥 이해만 하고 넘어가겠음.
졸려서 그냥 넘어가는 거 아님. 아무튼 아님.



자 예를들어서

const getMeal = (mealType) => {
  if(mealType==='한식') return "불고기";
  if(mealType==='일식') return "내사랑초밥밥";
  if(mealType==='중식') return "멘보샤";
  if(mealType==='양식') return "파스타";
  return "넌 그냥 굶어라";
};

console.log(getMeal("한식"));
console.log(getMeal("중식"));

이렇게 한식, 중식 등의 카테고리를 getMeal에 보내면 mealType이라는 파라미터를 이용해서 한식인지 중식인지 양식인지를 받아와서 함수 안에서 각각 처리를 했다고 쳐.

서너개만 돼도 슬슬 더티한데 더 많아지면 진짜 지저분해지겠지?
이럴 땐

const meal = {
  한식: '불고기',
  중식: '멘보샤',
  일식: '초밥',
  양식: '파스타',
  인도식: '카레'
};

const getMeal = (mealType) => {
  return meal[mealType] || "굶어라 !!";
};

console.log(getMeal("일식"));
console.log(getMeal());

이렇게 쓸 수 있음. meal이라는 객체 하나 만들어서 음식카테고리랑 메뉴 각각 묶어놓고,
화살표함수로 getMeal 만들어서 이렇게 ..
js는 참 똑똑한 것 같아 신기하기도 하고



자 이번에는 비구조화 할당 !
이거 이름만 어렵지 조넨 쉬움

C언어로 bubble sort할 때 많이 하던 전형적인 swap방식처럼 아래와 같은 코드가 있다고 쳐

let a = 10;
let b = 20;
let tmp = 0; //임시변수 템쁘

tmp = a;
a = b;
b = tmp;

console.log(a,b);

이렇게 하면

이렇게 a랑 b가 뒤집어진 거 알 수 있는데 이렇게 정석대로 하지 않아도 !
비구조화 할당을 통해서 쇼쇼쇼쇽 바꿀 수 있음! 파이썬처럼 그냥 swap()안 안되더라도,

let a = 10;
let b = 20;
[a,b] = [b,a]; //비구조화 할당
console.log(a,b);


짜라란 이렇게 똑같이 a랑 b를 스왑해버릴 수 있다 .
딱 이정도만 이해하고 넘어가도 될 듯 !
다음 강의 레츠고레츠고



간단해서 굳이 코드 안 적고 사진만 따오도록 하겠음ㅎ
여러개의 객체에서 반복되는 프러퍼티와 밸류는 ...이 spread연산자를 이용할 수 있다.
예제 속에서 두 개의 배열을 하나로 묶을 때도 spread 연산자를 사용하고 있는데 예전 강의시간에 배운 concat()을 써도 되지만 이렇게 하면 중간에 "함정쿠키"와 같은 값을 추가로 입력 할 수도 있다는 장점이 있다.

근데 낯설기도 하고 ...
이게 뭔가 코딩이 ... 이래도 되나 싶기도 하고 ...
이게 자바스크립트 ... ?
엄...



Thread는 코드를 한 줄 한 줄 작동시켜주는 친구라고 그냥 이해하면 됨.
taskA, taskB, taskC라는 세 가지의 일을 동기 방식으로 처리하는 방식을 나타낸 그림.

동기적 방식 : 앞 task가 끝날 때까지 기다렸다가 그 다음 task를 순서대로 처리하는 방식
그리고 멀티태스킹이 안 됨 ! -> 블로킹 방식

단점 : 하나의 작업이 너무 오래 걸리게 될 시, 모든 작업이 그 한 놈이 처리될 때까지 기다려야되기 때문에 프로그램의 전반적인 속도가 너무 느려진다.

그렇다면 Thread를 여러개로 늘려서 멀리 쓰레드를 사용한다면 ?
안 된다 ~~ javascript는 쓰레드 하나만 쓰는 싱글쓰레드 방식으로 작동한다.


그렇다면 요렇게 하나의 Thread가 요리조리 다니면서 동시에 여러개의 작업을 실행시킬 수 있게 한다면?

이렇게 CallBack함수를 붙여주면 됨 !!!

이번엔 직접 코드로 실습을 해보자.

function taskA() {
  console.log("A 작업 끝");
};

taskA();
console.log("코드 끝");

자 이런 동기 방식의 코드가 있었다고 해보자. taskA()가 끝나기 전까지 console.log("코드 끝");은 실행될 수 없어서 기다려야만 함. 이 코드를 비동기 방식으로 바꾸는 방법은 아래와 같다.

function taskA(a,b,cb) {
  setTimeout(() => {
    const res = a+b;
    cb(res);
  }, 3000); //ms라서 3000이 3초 !
}

taskA(3,4,(res) => {
  console.log("A Task Result : ", res);
});
console.log("코드 끝");

이렇게 비동기식으로 처리할 수 있음!


동기 방식 작동 원리


자바스크립트의 엔진은 이렇게 Heap과 Call Stack 두 가지로 구성되어 있다.
힙은 다음에 다시 자세히 다루고, Call Stack에 대해 살펴보장


one() two() three()라는 function이 만들어져있는데 얘네는 함수를 선언만 한 거지 실행하는 건 아니니까 넘어가고
Call Stack에는 console.log()라는 Main Context부터 쌓이기 시작한다. 근데 Main Context에서 three()를 먼저 호출했네? 그래서 Stack에는 three()가 쌓임. 근데 또 three()라는 함수는 two()라는 함수를 호출하니까 그 위로 two()가 쌓이고 마찬가지로 위에 one()이 쌓임.

자 이제 호출돼서 Call Stack에 쌓일 애들은 다 쌓였음. 그러면 마지막에 실행된 one()을 보면, 1을 리턴하게 돼있는데 지정된 값을 return하는 순간 그 함수는 역할을 다 한 거기 때문에 Call Stack에서 빠지게 됨. 따라서,

이렇게 one()함수가 stack에서 out되고, 그 다음인 two()가 아웃되고, 그 다음인 three()도 아웃 됨.
그래서 결과적으로는

이렇게 3이라는 최종 값을 내면서 Main Context까지 아웃되고 얘가 아웃되면서 Call Stack이 다시 비는 순간이 프로그램이 종료되는 순간임. 이게 js에서 엔진이 작동하는 원리 ! 별 거 없구만 ???


비동기 방식 작동 원리

이번에는 비동기를 처리할 때의 원리를 보겠음.

비동기 방식으로 동작할 때는 동기 방식일 때랑은 다르게 추가적인 요소들이 등장함.
웹 브라우저와 js의 상호작용을 위해서 존재하는 친구들임.
각각 어떤 것을 위해 존재하고 작동되는지 알아보자 !!!


음 설명 들어보니까 별 거 없음.
비동기 방식의 대표적인 예시였던 setTimeout()이라는 함수를 보면 얘는 Call Stack에 머무르는 애가 아니야.
하나뿐인 Thread가 멀티태스킹은 할 수 없기 때문에 setTimeout()은 Stack이 아니라 Web API로 들어가게 되는건데 얘는 거기서 지정된 시간이 지나면 자동으로 다음 cd()함수가 실행되게끔 해버리기 때문에 Thread가 얘를 기다리거나 하지 않아. 그렇기 때문에 멀티태스킹이 되는 것처럼 동시에 작동할 수 있게 되는거지.


자 이렇게 Web API에서 setTimeout()에 묶여있던 cb()는 Callback Queue로 넘어오게 되고 얘는 Event Loop를 통해서 언제든지 Call Stack으로 불려들어갈 수 있는 상태가 되는거야.

이런 원리로 JS에서 비동기 코드가 작동되는거임.
앞으로 비동기 방식 코드를 많이 작성하게 될 거라 잘 이해하고 넘어가면 훨씬 수월할거임 !!

근데 이렇게 비동기 방식으로 얻은 결과값을 또 다른 함수에 비동기 방식으로 넣고 넣고 하면 콜백지옥이 발생함.

이런식으로!
다음 강의에서 이런 콜백 지옥에서 우리를 구원해줄 Promise라는 친구를 배울 예정임.

(와 어려워진다. 일단 무슨 말인지 이해는 되는데 앞으로 내가 코드 짤 때 이건 동기방식 이건 비동기방식 이건 이러니까 콜백지옥에 빠질 수 있고 그러니까 이렇게 해결해야지 이런 생각 하면서 코드 절대 못 짤 것 같음 나 무서움 나 두려움)



먼저 비동기 작업이 가질 수 있는 3가지 상태에 대해 이해하자

이렇게 3가지가 있고 일단 이런게 있다! 정도 이해만 하고 패쓰

이제 본격적으로 ...

다음은 입력 받은 값이 양수인지 음수인지 2초 뒤에 판단해주는 비동기 방식 코드이다.

function isPositive(number, resolve, reject) {
  setTimeout(() => {
    if (typeof number === "number") {
      //성공 -> resolve
      resolve(number >= 0 ? "양수" : "음수");
    } else {
      //실패 -> reject
      reject("주어진 값이 숫자형 값이 아닙니다.");
    }
  }, 2000);
}

isPositive(
  10,
  (res) => {
    console.log("성공적으로 수행됨 : ", res);
  },
  (err) => {
    console.log("실패 하였음. ", err);
  }
);

isPositive()에 10이라는 숫자가 넘겨졌고, 당연히

"성공적으로 수행됨 : 양수"

라는 출력값을 확인 할 수 있음.

근데 10 대신에 [ ] 이렇게 빈 배열을 넣으면

"실패하였음: 주어진 값이 숫자형 값이 아닙니다"

라는 출력값을 확인 할 수 있음.


function isPositive(number, resolve, reject) {
  setTimeout(() => {
    if (typeof number === "number") {
      //성공 -> resolve
      resolve(number >= 0 ? "양수" : "음수");
    } else {
      //실패 -> reject
      reject("주어진 값이 숫자형 값이 아닙니다.");
    }
  }, 2000);
}
  
//promise를 사용해서 다시 만든 함수
function isPositiveP(number) {
  const executor = (resolve, reject) => {
    //executor는 실행자라는 뜻
    setTimeout(() => {
      if (typeof number === "number") {
        //성공 -> resolve
        console.log(number);
        resolve(number >= 0 ? "양수" : "음수");
      } else {
        //실패 -> reject
        reject("주어진 값이 숫자형 값이 아닙니다.");
      }
    }, 2000);
  };

  const asyncTask = new Promise(executor);
  return asyncTask;
}

isPositiveP(101);

아니근데 진짜 모르겠음. 열심히 이해하려고 하면서 따라서 코드 짜긴 했는데... 엄,,
.then이랑 .catch에 대해서랑, 쩌 위에 쓴 코드랑 바로 위 코드랑 뭐가 다르다는건지 다시 공부해야겠음..

@@다시 공부해야 하는 부분@@

강의 다시 듣고 제대로 이해해야겠다.
무리데스 ~


3-9 async / await | 직관적인 비동기 처리


아니 사진으로 소제목 정리하고 있었는데 갑자기 이번 강의에서는 소제목 사진 안보여주는 거 뭐지 ?? 어 ??
function delay(ms) {
   return new Promise((resolve) => {
      setTimeout(resolve, ms);
   });
}

async function helloAsync() {
   await delay(3000); //이 부분 주목 !!!!!!
   return "hello async";
}

async function main() {
   const res = await helloAsync();
   console.log(res);
 
}

main();

자 주석으로 표시해놓은 부분을 자세히 보자.
await이라는 키워드를 비동기함수의 코드 앞에 붙이면, 비동기 함수가 마치 동기적으로 작동하게 된다.
무슨 말이냐면,
await이라는 키워드가 붙은 함수의 호출은 뒤에 있는 함수가 끝나기 전까지 그 아래에 있는 코드를 수행하지 않는다 뜻 !
그러니까 await이 있는 줄은 다 동기적으로 수행이 되게 되는 것.

그리고 중요한 거 하나 더 ,

await은 async가 붙어있는 함수에서만 사용할 수 있다.

[ 정리 ]
async와 await을 활용해서 비동기 코드 promise를 반환하는 함수를 동기적인 함수를 마치 호출한 것처럼 사용할 수 있도록 만들어주는 방법에 대해 배움.



JS응용 챕터에서 마지막 API 호출에 대해서 배워보자!!!
아래 그림을 통해 한 번에 이해 할 수 있다.


여기서 가장 중요한 건 1.Request, 4.Response 이렇게 두 개임.
왜냐하면

우리가 공부할 부분은 이렇게 딱 데이터를 요청하고, 그 데이터를 다시 가져와 전달하는 부분이 전부이기 때문.

API는 결국 쉽게 말해서 클라이언트와 서버의 연결 다리이자 방법이라고 이해하면 됨.

https://jsonplaceholder.typicode.com/
여기 들어가서 내려보면 Resources부분이 있는데 개발자들을 위해서 무료로 공개해놓은 API들을 볼 수 있음
이런걸 Open API라고 부름.

let response = fetch("https://jsonplaceholder.typicode.com/posts").then((res) =>
  console.log(res)
);

이렇게 하면 fetch가 저 주소를 통해서 API에 접근을 하고, 결과값이 성공했다면 res가 반환되는데

강사는 이런 Response가 콘솔에 뜨나본데 나는 왜 안뜨지...?

저 복잡해보이는 Response는 포장지야. 우리가 원하는 편지를 보려면 이제 뜯어봐야 함.
뜯는 방법은 아래 코드처럼 하면 됨 !

async function getData() {
  let rawResponse = await fetch("https://jsonplaceholder.typicode.com/posts");
  let jsonResponse = await rawResponse.json();
  console.log(jsonResponse);
}

getData();

그러면 아래와 같은 출력을 콘솔에서 얻을 수 있음.

100개가 넘어가는 객체들이 뜨는데 하나씩 뜯어보면 우리가 원하는 API의 그 내용들이 다 들어있음.

이런식으로 API를 불러오고 사용할 수 있다 !


profile
주식하는 개발자랄까나..

0개의 댓글