2024/05/11 리액트 입문 2

YIS·2024년 5월 11일
post-thumbnail

Short Circuit Evaluation(단축 평가)

논리 연산자를 사용하여 조건문을 처리할 때,
전체 표현식을 평가하지 않고 최소한의 평가로 결과를 도출하는 방식
주로 && (논리곱), || (논리합) ?? (null 병합 연산자)를 사용할 때 발생

  • falsy 값 : false, 0, "", null, undefined, NaN
  • truthy 값 : Falsy 값이 아닌 모든 값은 truthy로 간주

논리합 (||) 연산자

좌변의 피연산자가 falsy값일때만 우변의 피연산자를 평가.
좌변의 피연산자가 truthy일때 그값을 바로반영후 우변은 평가되지 않음.

// 유저 정보가 제공되지 않았을 때 기본 이름 제공
function getUsername(user) {
    return user.name || '신원미상'; 
}
const person = {
  age: 30,
  name: "mike",
};
console.log(getUsername(person)); //John
console.log(getUsername({})); //신원미상

논리곱 (&&) 연산자

좌변의 피연산자가 truthy일때만 우변을 평가함(우변을 실행한다).

let loggedIn = true;
let username = 'John';
loggedIn && console.log('환영합니다! ' + username); //환영합니다! John

loggedIn = false;
loggedIn && console.log('환영합니다! ' + username); //아무것도 출력되지 않음

Optional Chaining(?.)

객체의 속성에 접근할 때 해당 경로에 속성이 존재하지 않아도 에러를 발생시키지 않고,
대신 undefined를 반환.

  • 장점
    중첩된 객체 접근의 안정성 보장, 코드의 간결성, 선택적 기능의 실행, 오류처리의 간소화
const user = {
    profile: {
        name: "John",
        details: {
            age: 30,
            location: "서울시 강남구"
        }
    },
    printHello: () => console.log("Hello"),
};
console.log(user.profile?.details?.age); // 출력: 30
user.printHello(); //Hello
user.printHello1?.(); //undefined
//profile이나 details 중 하나라도 undefined나 null이면, 
//?. 연산자는 그 시점에서 평가를 멈추고 undefined를 반환

Null 병합 연산자 (??)

좌변이 null이나 undefined일 경우에만 우변을 평가,실행
논리합 연산자와 비슷하나 null,undefined을 제외한 falsy값들을 유효한 값으로
처리하고 싶을때 사용

 const displayPreferences = (preference) =>{
  const textLength = preference.textLength || 50;
  console.log(textLength); // 50 논리합연산자에서 0은 falsy한 값

  const itemsPerPage = preference.itemsPerPage ?? 10;
  console.log(itemsPerPage); //0 병합연산자에서 0은 유효한 값
}

const userPreference = {
  textLength: 0,
  itemsPerPage: 0,
};

displayPreferences(userPreference);



Modules

코드를 분리된 파일로 관리하고, 필요한 부분만을 임포트하여 재사용 할 수 있음.
자바스크립트의 실행 환경은 브라우저 환경과 Node 환경이 존재하는데
Node환경 모듈 import 방식은 CommonJS 방식과 ES6 방식이 있음.
브라우저 환경에서의 React는 대두분 ES6제시한 방법을 사용(지금 설명부분도)

모듈의 기본 및 사용방법

사용방법

export 키워드를 사용하여 모듈을 만들고, 다른 파일에서 사용할 수 있게 함.
import 구문을 사용하여 다른 파일에서 함수를 불러와 사용.

// math.js
export const add = (a, b) => a + b;
export const multiply = (a, b) => a * b;
export const ONE = 1;
export const sample = {
	one: 1,
	two: 2
}
------------------------------------------
// app.js
import { add, multiply, ONE, sample } from './math.js';
//math.js에서 가져온 함수, 객체, 원시값
console.log(add(2, 3)); //5
console.log(multiply(2, 3)); //6
console.log(ONE); //1
console.log(sample.two); //2

모듈을 사용해야 하는 이유

명확한 종속성 관리

// 전통적인 스크립트 로딩 방식
<script src="jquery.js"></script>
<script src="plugin.js"></script> //이 스크립트는 jquery.js에 의존 
<script src="app.js"></script> //이 스크립트는 plugin.js와 jquery.js에 의존
//파일 간의 종속성과 로딩 순서를 수동으로 관리.
//프로젝트 규모가 커질수록 종속성을 추적하고 관리하기 어려워짐.
// ES6 모듈 사용 예시
import $ from 'jquery';
import plugin from 'plugin'; // 자동으로 jQuery에 대한 의존성을 처리
import app from 'app'; // 모든 의존성이 충족되면 실행
//파일을 로드하는 순서에 신경쓸필요가 없음

코드 캡슐화와 충돌 방지

//모듈은 자체적인 스코프를 가지므로 전역변수의 오염, 이름 겹침을 막을수 있음
//여러스크립트에서 동일한 함수 이름사용하더라도 as 키워드를 사용해 
//불러온 js파일에서 사용할 이름으로 바꾸면 안전하게 충돌없이 임포트해서 사용 가능.
// module1.js
export function conflictFunction() {
  console.log('Module 1의 함수');
}
// module2.js
export function conflictFunction() {
  console.log('Module 2의 함수');
}
// app.js
import { conflictFunction as function1 } from './module1';
import { conflictFunction as function2 } from './module2';

function1(); // "Module 1의 함수"
function2(); // "Module 2의 함수"

효율적인 코드 로딩

//현재 이해안됨. then, catch 모름.

//필요한 기능만을 선택적으로 불러올 수 있음.
//코드 스플리팅을 사용하면 사용자의 현재 요구에 따라 필요한 코드만 동적으로 로드하면서
//성능과 자원사용을 최적화 할수 있음.
// 동적으로 모듈 로드하기 (예: 사용자가 특정 기능을 활성화했을 때)
button.addEventListener('click', event => {
  import('./heavyModule.js')//버튼클릭시 heavyModule.js모듈 동적으로 로드
    .then(module => { //모듈이 로드되면 then메서드로 로드된 무듈에 접근
      module.heavyFunction();
    })
    .catch(err => { //모듈로딩과정에서 오류 발생시 catch메서드로 에러 처리부분
      console.error("모듈 로딩에 실패했습니다.", err);
    });
});

고급 모듈 기능

이름 바꾸기, 기본 내보내기

  • 별칭사용
    import시 특정 요소에 별칭을 지정하여(as) 충돌을 미연에 방지
import { square as sqr } from './utils.js'; //sqr로 별칭지정
console.log(sqr(4));  // 16
  • 기본 내보내기와 가져오기
    한 모듈에서 하나의 핵심적인 기능이나 값만을 내보낼때 (export default)
    모듈당 하나의 주요 기능을 내보낼 때 유용.
    import로 가져올 때 원하는 이름으로 지정할 수 있음.
// export default 시 모듈이름 변경은 자유!
// utils.js
export default function square(x) {
  return x * x;
}
// main.js
import mySquare from './utils.js';
console.log(mySquare(4));  // 출력: 16

전체 모듈 내용 가져오기

import * as구문으로 모듈의 모든 내보내기(exported) 값을 한 번에 가져오는 방법
모듈 내에서 내보내진 모든 함수, 객체, 변수 등을 하나의 객체(이름변경가능)로 묶어서 가져옴.

// app.js
import * as MathFunctions from './math.js';

console.log(MathFunctions.add(10, 5));       // 15
console.log(MathFunctions.multiply(10, 5));  // 50



Async / Await

비동기 작업을 보다 쉽게 다룰 수 있도록 도와주는 문법
Promise를 기반으로 작동하지만,
Promise의 then()과 catch() 메서드를 사용하는 것보다 훨씬 읽기 쉬움.

Promise

비동기 작업의 최종 완료 또는 실패를 나타내는 객체.
비동기 작업이 수행될 때 그 결과값을 나중에 받기 위한 약속.
비동기 작업의 결과에 따라 콜백 함수를 연결할 수 있으며
.then(), .catch(), 그리고 .finally() 메소드를 이용해 연속적으로 결과를 처리할 수 있음.
Promise는 세 가지 상태 중 하나를 가짐.

  • Pending (대기중) : 성공 또는 실패가 결정되지 않은 상태
  • Fulfilled (이행됨) : 연산이 성공적으로 완료되어 프로미스가 결과 값을 반환.
    then메서드가 호출됨. 여러개 호출가능
  • Rejected (거부됨) : 연산이 실패하거나 오류가 발생한 상태
    catch메서드가 호출됨. 보통 메서드 체인의 끝에 위치.
const myPromise = new Promise(function(resolve, reject) {
  // 비동기 작업을 수행하고
  if (/* 작업 성공 */) {
    resolve('Success!');
  } else {
    reject('Error!');
  }
});

myPromise.then(function(value) {
  // 성공(resolve)한 경우 수행
  console.log(value);  // 'Success!'
}).catch(function(error) {
  // 실패(reject)한 경우 수행
  console.error(error);  // 'Error!'
});

Async

async 키워드를 함수 선언 앞에 붙여 정의.
이 함수는 항상 Promise를 반환.
함수 내부에서 리턴하는 값은 자동으로 성공한 약속(resolve된 Promise)으로 바뀜.
=> 약속한 결과대로 값을 주겠다.

문제생겨서 실패시 실패한 약속(reject된 Promise)으로 바뀜
=> 약속을 지키지 못해서 원하는 값을 못준다.

async function fetchData() {
  return 'Data loaded';
}
// 아래 코드와 같음
// async function fetchData() {
// 	return Promise.resolve('Data loaded');
// }
fetchData().then(console.log); // 'Data loaded'

Await

await 키워드는 async 함수 내부에서만 사용할 수 있음.
Promise의 완료(성공적으로 resolve되거나 reject됨)를 기다림.
await 키워드 다음에 오는 표현식은 Promise를 반환해야 함.
해당 Promise가 성공적으로 resolve되면, await는 resolve된 값으로 평가,
reject되면, reject된 값으로 예외가 발생하며,try...catch 문을 사용하여 처리

await 사용의 이점

프로미스의 완료를 기다리는 동안 함수의 실행을 일시적으로 중단하고,
프로미스가 해결되면 자동으로 함수의 실행을 재개
=> 비동기 코드의 동기적 표현이 가능

async function fetchData() {  //비동기 함수선언
  try {
    const data = await fetch('https://api.example.com/data');
    //1.fetch가 반환하는 Promise가 완료될 때까지 기다림
    const json = await data.json();// 2.그값을 json할당후 기다림
    console.log(json); //3. 출력
  } catch (error) { //fetch 호출이나 .json() 메서드에서 오류가 발생시 출력
    console.error("Data loading failed", error);
  }
}
fetchData();

await를 사용하지 않았을 때 문제

.then()과 .catch() 메서드를 사용하여 프로미스 체인을 구성해야됨.
코드 가독성, 유지보수의 아쉬움

function fetchData() {
  return fetch('https://api.example.com/data')//fetch로부터 받은 응답 객체를 인자로 받음
    .then(response => response.json())
  //응답 본문을 JSON으로 파싱하는 작업수행, Promise를 반환
    .then(data => console.log(data))// JSON 데이터를 인자로 받은후 console.log로 출력
    .catch(error => console.error("Data loading failed", error));
  //json파싱 과정중 오류시 catch블록 실행.
}

fetchData();

JSON(JavaScript Object Notation)

(잘모르겠는데 나와서 검색해봄)
경량의 데이터 교환 형식

  • 이름/값 쌍의 집합 : 객체는 중괄호 {}로 둘러싸여 있으며,
    각 이름 뒤에는 콜론(:)이 오고, 이름/값 쌍은 쉼표(,)로 구분

  • 값의 순서화된 리스트 : 배열은 대괄호 []로 둘러싸여 있으며, 값은 쉼표(,)로 구분

JSON파싱

JSON 형식의 문자열을 JavaScript 객체로 변환하는 과정.
웹 애플리케이션에서 서버와 클라이언트 간에 데이터를 주고받을 때 주로 사용.

profile
엉덩이가 무거운 사람

0개의 댓글