Index

컴포넌트, props, data, prev, el, graphql-variables의 실체
함수 관련 용어
rest-api의 문제점과 endpoint
언더페칭&오버페칭
graphql - restapi 의 관계
글로벌 스테이트
fetchPolicy
Recoil
정규표현식

intro

리액트를 사용하는 이유에 대해 생각해보자(재사용성)

컴포넌트, props, data, prev, el, graphql-variables의 실체

함수 관련 용어

// 함수의 선언
const func1 = (param)=>{
		console.log(param)
	}
	

// 함수의 실행
func1(argu)

// 결과
// param.argu

argu가 함수로 들어가게 되고 함수의 parameter는 arguments를 받아 옴. 따라서 함수에 들어가는 것은 인자(argu), 뭘로 받을지 기다리는 것은 매개변수(param)

// 함수의 선언
const func2 = (param) => {
		console.log(param.count)
	}

// 함수의 실행
func2({count : 123})

// 결과
	// 123

💡 함수의 매개 변수 작명 : 아무렇게나 지어도 상관 없으나 관례를 따라 사용하는 것이 좋다.

props 의 실체

함수형 컴포넌트 = 함수 ->

<Presenter count={123}/>를 {Presenter({count:123})}과 같이 사용

Presenter 함수를 해당 위치에서 실행시키겠다는 뜻

Presenter 함수의 argument를 보면 count가 함수의 인자 부분에 들어가 있으며 aaa로 넘겨준 인자를 받ㄷ고 있는데 aaa는 props의 자리였고 따라서 props는 함수의 파라미터였다.

💡함수와 컴포넌트의 차이점 -> 컴포넌트는 리턴 값으로 JSX가 반환되어야 한다.

el의 실체

//함수의 선언
const getProfile = (aaa,bbb)=>(
		console.log(`${aaa}는 ${bbb}입니다.`)
	)
    
//함수의 실행
getPrfile("훈이",2)

// <----실행 결과----->
// 훈이는 2입니다.

aaa 부분에 "훈이"가 들어오고 bbb에는 2가 들어와 결과적으로 "훈이는 2입니다."가 나오는데 인자로 넘겨주는 것이 여러 개일 경우 파라미터도 인자의 갯수만큼 늘어나며 넘겨준 순서대로 들어오게 된다.

["철수","영희","훈이"].map((el,index)=>(console.log(`${el}는 ${index}번째 입니다.`)))

위의 코드는 위의 map을 ("철수", 0) ("영희", 1) ("훈이", 2) 이렇게 실행하는 것인데 map에서 넘겨주는 인자의 순서는 배열의 밸류값 ->, 해당 밸류의 인덱스 값 순서로 들어가게 됨.

매개 변수의 이름은 뭐가 들어가도 상관이 없는데 아래의 인덱스는 어떤 것을 의미하는가?

이름만 index였을 뿐, 배열의 각각의 원소 철수, 영희, 훈이를 의미함. 즉, map도 함수였으며 el, index는 함수의 파라미터였다.

prev의 실체

state의 prev도 마찬가지로 함수의 파라미터였다.
setCount(prev -> prev + 1)
setCount((prev) => {return prev + 1})

setCount 함수의 인자로 화살표 함수가 들어가고 화살표 함수 안의 prev는 함수의 파라미터

graphql-variables의 실체

const CREATE_BOARD = gql`
mutation createBoard($writer: String){
		createBoard(writer: $writer){
			_id
		}
	}
`

$가 붙은 것들은 변수였으므로 writer가 아닌 hello가 되어도 상관이 없었다.

쿼리를 날릴 때 두 번 적어주는 이유는 뭘까?
-> 한 요청에서 여러 가지의 api 요청을 날릴 수 있기 때문이다.

const REQUEST = gql`
mutation 한번에요청할그룹이름 ($변수 : String){
	원하는API1(백엔드지정:$변수){
		//받아올 것
	}

	원하는API2(백엔드지정:$변수){
		//받아올 것
	}
}
`

위처럼 request 한번에 여러 api를 묶어 한번에 요청할 수 있도록 되어 있기 때문에 겉에 적어주는 부분은 그룹화를 위한 부분, 백엔드에 보내지는 부분은 내부에 적힌 api들을 보내개 된다. 이 말은 한번의 mutation에 createProduct와 createBoard를 동시에 보낼 수 있다는 말이다.

그룹명은 상관 없고 API명, 백엔드 지정 이름은 정해져 있다.

rest-api의 문제점과 endpoint

endpoint? API 가 서버에서 리소스에 접근 가능하게 하는 url

graphql이 없었을 때(Rest-api를 사용하던 시점) 가장 큰 문제점은 너무 많은 endpoint가 만들어진다는 점이었다. rest-api에서는 Post, get, put, delete, update 방식만 해도 이미 5개의 엔드포인트가 생성되기 때문에 이외의 엔드포인트를 추가하게 되면 상당히 많은 endpoint가 생긴다.

언더페칭과 오버페칭 : rest-API에서 발생하는 문제들

오버페칭
graphql은 api 요청 이후 결과로 필요한 것만 받아오는 반면 rest-api는 결과값을 모두 받아오는데 필요 없는 것까지 모두 받아오는 과정을 "오버페칭"이라 한다.

너 못골라! 내가 주는 거 그냥 다 받아~ (쓸데없이 오버해서 많이 받아옴)

언더페칭
rest-api는 endpoint에 body를 넣어 보내기 때문에 하나의 엔드포인트에 하나의 바디만 들어가게 된다. 따라서 한번에 여러 개의 api를 요청할 수 있는 gql과 다르게 rest-api는 한번에 하나의 api만을 요청할 수 있다.

내가 필요한 것은 3개의 api인데 한 개씩 여러 번 받아오는 것을 "언더페칭"이라고 한다.

graphql과 rest-api의 관계

위의 문제점을 개선하기 위해 나온 것이 gql이다.
graphql은 rest-api의 post 방식에서 data를 넣을 수 있음을 이용해 만들어낸 방식으로 완전히 새로운 방식이 아닌 rest-api의 응용이다.

즉, graphQL도 사실은 REST-API의 연장선상에 있다!

gql은 post 방식의 body에 내가 실행할 함수의 이름을 적어 endpoint를 요청한다. 그러면 이미 만들어진 함수들 중 매칭된 함수가 실행되고 원하는 결과값을 받을 수 있게 되어 endpoint 문제와 언더페칭, 오버페칭 문제까지 모두 해결하게 된다..

GraphQL의 응답은 항상 성공(200), 실패한 것은 query문 오류일 것이다... 각각 클릭해서 들어가 보면 성공, 실패가 나뉘어 있긴 함.

GraphQL만 쓰는가? 아직까지는 rest-API가 더 많고, openAPI는 대부분이 rest-API이다. 또, graphQL은 cache(임시 저장)가 어렵다. => graphQL은 보통 큰 서비스에서 주로 사용한다

cache? 임시 저장? 주소가 /graphql 한개라서 생기는 문제
ex. 계속 10번 게시글을 요청하는데 계속 DB까지 가서 10번 게시글을 가져옴(백엔드에서 데이터베이스에 가기 전에 백엔드에서 qqq={10: {data}} 형식으로 임시 저장해두면 다른 10번 게시글 요청에도 데이터베이스까지 가지 않고 데이터를 반환할 수 있음)

글로벌 스테이트

백엔드에서 받은 데이터를 몰래 저장해 놓자~!

하나의 state가 여러 페이지에서 필요한 경우, isLogined같은 state는 게시글 목록이나 결제 컴포넌트같이 여러 컴포넌트에서 사용되는데 매번 props로 내려주는 것이 아닌 글로벌 스테이트를 사용한다.

store에 name이라는 state를 저장해 두고 필요한 컴포넌트에서 import 해서 사용하기 때문에 props drilling을 하지 않아도 된다. 이런 전역상태 관리 툴로는 context-Api, Redux, Recoil 등이 있다. Redux는 어렵고 비효율적이기 때문에 context-Api, recoil을 주로 사용한다.

fetchPolicy

apollo-client의 고급 기능으로 여러 컴포넌트가 있고 여러 컴포넌트가 공유할 수 있는 글로벌 스테이트가 있을 때 apollo-client로 global state를 만들게 되면 Apollo-Cache라는 곳에 저장되게 된다.

만일 2번 컴포넌트에서 useQuery를 해오게 되면 useQuery를 해서 받아온 데이터가 APollo-Cache에 저장된 후 컴포넌트로 들어오게 된다.


이후에 3번 컴포넌트에서 같은 데이터를 요청하게 되면 아폴로-캐쉬에 먼저 가서 데이터가 있는지 확인하고 없으면 백엔드에 요청을, 있으면 요청을 하지 않고 컴포넌트로 바로 보내주게 되는데 이를 바로
Apollo-client의 fetchPolicy라고 한다.
fetch 정책에는 여러 기능("cache-first" default -> 캐시에 있는지 먼저 확인; 글로벌 스테이트부터 확인, "network-only" -> 캐시에 있든 없든 무조건 백엔드에 요청; 글로벌 스테이트 확인 안함)이 있으며 변경 또한 가능하다.

Recoil
프론트에서 자체적으로 생성되는 데이터는 어디다 넣어두냐? 라고 했을 때 몇 가지 방안들이 나왔지만 그 중 recoil이라는 라이브러리가 헤비하지 않고 적당하다.

참고) 몇가지 방안들 Redux-toolkit, RTK-Query, Recoil(기존에는 리덕트) 골라 씀

설치) yarn add recoil

//app.tsx 파일 
import {
  RecoilRoot,
  atom,
  selector,
  useRecoilState,
  useRecoilValue,
} from 'recoil';

function App() {
  return (
    <RecoilRoot>
		//RecoilRoot로 모든 컴포넌트를 묶어주세요
      <Component />
    </RecoilRoot>
  );
}

Recoil의 사용

Recoil에서는 Atom으로 state의 일부를 보여준다. 그리고 컴포넌트들은 자신이 필요한 Atom을 참조하고 있다. 따라서 자신이 참조하는 Atom에 변화가 있으면 해당 atom을 참조하는 모든 컴포넌트에서 리렌더가 일어난다.

// Atom
const textState = atom({
  key: 'textState', // state의 이름
  default: '', //초기값
});

Atom은 꼭 파일로 따로 뺄 필요는 없으나 파일을 분리하게 되면 반드시 export해주어야 한다.

위의 아톰을 실제로 사용하기 위해서는 useRecoilState를 사용해야 하는데 이는 useState와 비슷하다.

// TextInput 컴포넌트 
function TextInput() {
  const [text, setText] = useRecoilState(textState);

  const onChange = (event) => {
    setText(event.target.value);
  };

  return (
    <div>
      <input type="text" value={text} onChange={onChange} />
      <br />
      Echo: {text}
    </div>
  );
}

위처럼 사용하게 되면 textState를 참조하고 있는 모든 컴포넌트에서 리렌더가 일어난다.

Recoil은 결국 context-api의 단점을 보완한 상태 관리 라이브러리이기 때문에 context-api를 기반으로 하고 있다.

정규 표현식

기존에 회원 가입이나 로그인 시에 무언가를 포함하고 있는지 확인할 때 사용하던 includes 메소드를 대신해 정규 표현식을 사용하면 조금 더 편하게 확인할 수 있다.

사용 방법
/ 조건 /.test("검사하고 싶은 것")

정규 표현식에서 Test라는 메서드를 사용할 수 있는데 이 메서드의 인자값으로 체크할 비밀번호 문자열을 넣어주게 되면 조건에 해당하는 경우(비밀번호 체크 사항에 하나라도 일치하지 않는 경우)에는 false를, 해당되지 않으면 true를 리턴한다.

// 정규표현식 예제
/\w+@\w+.\w+/.test("codecamp@ccc.com")

//결과
true

위의 코드에서 정규 표현식의 조건은 \w+@\w+.\w+ 이다.

💡정규 표현식에서 조건이 검사하고 싶은 문자열에 하나라도 포함되어 있다면 true를 반환하므로 시작점(^)과 끝점($)을 정해주면 된다.

MDN 공식 문서 링크
https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_Expressions

profile
Strive for greatness

0개의 댓글