병렬 쿼리에 대한 게시글을 찾아보던 도중,  

 

If the number of queries you need to execute is changing from render to render, you cannot use manual querying since that would violate the rules of hooks.

 

어떤 게시글에서 위 글의 `violate the rules of hooks` 가 'Hooks 의 어떤 규칙을 위반한 것인지는 모르겠지만' 이라고 포스팅을 해두었길래 무엇을 의미하는 것인지 적어본다.

 

React 의 가장 중요한 기초 개념 중에 하나가

'Hook 은 최상위 레벨에서 동작해야한다' 이다.

 

'If the number of queries you need to execute is changing from render to render'

렌더마다 실행해야하는 쿼리(Hooks)의 수가 변경된다면

'you cannot use manual querying'

수동으로 쿼리를 작성할 수 없다

 

쉽게 이해해보자면,

Hooks 를 숫자타입을 가지는 상태값에 따라 조건적으로 실행할 수 없다는 뜻으로 설명할 수 있다

방금한 설명을 코드로 표현해본다면

 

const [cnt, setCnt] = useState<number>(...);
const [value, setValue] = useState<any>();

if (cnt == 1) {
	useEffect(() => {
    	(async() => {
        	const response = await fetch(...);
            setValue(response.data);
        })()
    }, [])
}

...

return <... />

 

위 코드의 문제점이 무엇일까

cnt 값에 따라 if 문 내에서 실행되는 useEffect 는 과연 정상적으로 실행될까?

 

정답은 당연히 x 이다.

React 의 상태관리 메커니즘은 실행될 Hooks 의 순서를 기억한다.

if 문 등의 특정 '조건' 이 상태관리 메커니즘에 저장된 순서를 동적으로 변경할 수 없다는 의미가 된다.

 

React 의 기초개념 'Hook 은 최상위 레벨에서 동작해야한다' 의 가 위 설명을 포함하고 있다고 보면 된다. 

'web > React' 카테고리의 다른 글

digital envelope routines::unsupported  (0) 2023.06.20
React Context API  (0) 2023.04.01
제너레이터(Generator)  (1) 2021.01.11
Redux 비동기(redux-saga)  (0) 2021.01.11
리액트 내장 훅  (0) 2021.01.01

ssh private key 파일이 암호로 보호되어있어서 자동으로 엑세스해야하는 경우(ex: yaml)에 엑세스 할 수 없어서 발생하는 에러

 

자동화된 작업을 수행하는 경우 ssh 를 사용하려면 ssh private key 의 암호가 제거된 상태이어야 함

아래의 순서를 따라가면됨

$ ssh-keygen -p
$ Enter file in which the key is...: SSH private key 파일의 경로를 입력
$ Enter old passphrase: SSH private key 의 암호
$ key has comment ...

위 key has comment ... 까지 왔으면 새로운 비밀번호를 입력하지 말고 그냥 Enter 를 누르고 넘김

비밀번호가 없는 상태로 SSH private key 를 사용할 수 있게 되므로 이제 자동화 작업에서도 이용할 수 있음

'cloud' 카테고리의 다른 글

GCE ssh-keys  (0) 2023.04.26

GCE(Compute engine) 인스턴스를 외부에서 접근해야하는 일이 있어 설정할 겸 기록해둔다

 

기본적으로 VM 인스턴스에 접근하는 방법에는 2가지가 있다

https://cloud.google.com/compute/docs/instances/access-overview?hl=ko 

 

액세스 방법 선택  |  Compute Engine 문서  |  Google Cloud

의견 보내기 액세스 방법 선택 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Google Cloud에서 Linux 가상 머신(VM) 인스턴스를 실행하는 경우 VM에 대한 사용자

cloud.google.com

OS 로그인 방법과 metadata에서 ssh-key 를 관리하는 방법인데,

OS 로그인 방법의 경우 계정 IAM 권한과 여러가지 설정을 통한 조직 수준의 엑세스를 관리할 수 있다고 하는데,

아직 확실한 경험이 없어서 metadata 에서 ssh-key 를 관리하는 방법을 선택했다

 

metadata 에서 ssh-key 를 관리하는 방법은 aws ec2 와 같은 방식으로

인스턴스에 public key 를 설정해두고 비공개키를 이용해 ssh 방식으로 인스턴스에 접근한다

 

다음과 같은 간단한 과정을 거친다

1. ssh-key pair 생성

2. gce instance metadata-ssh-key 셋팅

3. ssh 를 통한 접속

 

1. ssh-keys pair 생성

https://cloud.google.com/compute/docs/connect/create-ssh-keys?hl=ko#create_an_ssh_key_pair 

 

SSH 키 만들기  |  Compute Engine 문서  |  Google Cloud

SSH 키 생성 방법

cloud.google.com

ssh-keygen -t rsa -f ~/.ssh/생성할SSH-KEY파일이름 -C VM사용자이름 -b 2048

생성할 ssh-key 파일이름 의 경우

test-ssh 라고 정하게 되면 공개키과 비공개키가 각각 test-ssh.pub, test-ssh 으로 생성된다

 

VM사용자이름 의 경우 철자 실수를 하지말자

GCP 의 compute engine 의 경우 접근하는 유저마다 인스턴스의 환경이 독립적으로 생성되기 때문에 기존에 인스턴스에 접근하는 사용자이름으로 설정해야 같은 환경으로 접근 가능하다

사용자 이름을 쉽게 확인하려면.. 인스턴스에 접속했을 때 test_user@인스턴스명 으로 접근될텐데, test_user 가 사용자이름이다

 

명령어가 실행되면 pub 키와 비공개 키가 각각 만들어져 있을 것이다

현재 사용중인 환경에서 비공개 ssh 키를 이용해 접근하려면 파일의 모드를 400으로 수정해준다

chmod 400 ~/.ssh/방금생성한비공개키

 

2. GCE instance metadata-ssh-key 셋팅

2-1. 인스턴스에서 설정

설정할 인스턴스 -> 속성 -> ssh key 등록에서 방금 추가한 ssh public key를 등록한다

cat ~/.ssh/방금생성한ssh키.pub

출력된 키값을 복사해서 ssh에 등록

2-2. Google CLI 를 통한 설정

(아주 가끔 구글형들이 플랫폼관리에서 손을 떼시는듯 하다)

(인스턴스 속성이고 뭐고 들어가지질 않는 에러폭탄 상황이 발생해서 cli 로 직접 설정해줬다..)

 

https://cloud.google.com/compute/docs/connect/add-ssh-keys?hl=ko#add_ssh_keys_to_instance_metadata 

 

VM에 SSH 키 추가  |  Compute Engine 문서  |  Google Cloud

VM 인스턴스에 SSH 키를 추가하는 방법

cloud.google.com

 

(혹여나 설정 과정에서 버전문제로 안된다면 google cli (gcloud) 를 업데이트하자)

1. 다음 명령어를 통해 기존 인스턴스의 SSH 키를 가져온다

gcloud compute instances describe 인스턴스명

출력값 중간쯤에 metadata > ssh-keys 값이 있다

value: |- 아래의 모든 ssh-key 값을 복사한다

 

2. 공식문서에 적혀있지만, ssh-key 를 업데이트하려면 키 텍스트가 포함된 파일을 통해서 등록해야한다

vi new-ssh-keys

다음과 같이 파일을 만들고 방금 복사한 값들을 넣는다

그리고 기존에 만들었던 ssh pub 키를 추가한다

 

3. metadata sshkey update

gcloud compute instances add-metadata 인스턴스명 --metadata-from-file ssh-keys=new-ssh-keys

기억이 정확하지는 않은데 위 명령어를 실행했을 때 에러가 났던 것 같다

파일모드 때문이었던 것 같은데 chmod 를 통해 new-ssh-keys 파일을 400으로 변경해주고 재시도하니 잘 동작했었다

 

3. ssh를 통한 접속

ssh 로 접속한다는건 보통 그 이후에도 ssh으로 접속할 일이 많다는 뜻이기에 alias 를 설정해주면 편하다

alias awesome="ssh -i ~/.ssh/ssh비공개키 유저명@인스턴스접속경로"

alias 를 .zshrc 에 설정해줬다면 source 를 통해 적용해주자

source ~/.zshrc

이제 awesome 명령어로 설정한 인스턴스에 접속할 수 있다

'cloud' 카테고리의 다른 글

ssh: this private key is passphrase protected  (0) 2023.04.27

전역 상태가 아닌 특정 컴포넌트의 상태를 관리할 때는 context API를 많이 활용한다.

이를 좀 더 편하게 사용하기 위해 아래와 같은 형태로 context 를 만들어서 사용한다.

 

// context/management

import React, { useContext, useEffect } from "react"
import { SOME_TYPE } from "./type/management";

interface IManagementState {}
interface IManagementAction {
  type:string;
  payload?:any;
}

const initState:IManagementState = {};

export const managementReducer = (state:IManagementState, action:IManagementAction) => {
  switch(action.type) {
    case SOME_TYPE : {
      // do something
      // ..
      return state;
    }
    default:
      return state;
  }
}

const managementContext = () => {

  const ctx = React.createContext<{
    state:IManagementState
    dispatch:React.Dispatch<IManagementAction>
  }>({
    state:initState,
    dispatch:() => null
  })

  const useCtx = () => {
    const c = useContext(ctx);
    return c;
  }

  return [
    ctx.Provider,
    useCtx,
    initState
  ] as const;
}

export default managementContext;


// context/type/management

export const SOME_TYPE = 'SOME_TYPE';


// page

import managementContext, { managementReducer } from '@/context/state'
import { useReducer } from 'react';

export const [ManagementContextProvider, useManagementContext, initManagementContextState] = managementContext();

export default function Page() {

  const [state, dispatch] = useReducer(managementReducer, initManagementContextState);

  return (
    <ManagementContextProvider 
    value={{
      state, 
      dispatch
    }}>
      {/* ... */}
    </ManagementContextProvider>
  )
}

 

Context Provider 를 state, dispatch 2개 각각 만들어서 성능최적화를 시켜줄 수 있지만.. 패스

 

context 의 상태는 reducer 를,

useCtx 함수를 통해 useContext 객체를 외부로,

useReducer 를 통해 context reducer 와 context initState 를,

이를 Provider를 통해 Context API 를 사용할 수 있도록 하는 구조이다  

 

하위 컴포넌트에서는 아래와 같이 export 한 useContext 객체를 손쉽게 사용할 수 있다

 

const { state, dispatch } = useManagementContext()

 

최근에 서로 다른 페이지에서 동일한 형태의 뷰를 갖는 컴포넌트를 추가해야 했는데,

기존의 컴포넌트는 위의 구조로 상태관리를 하고 있었다

 

기존에 사용하던 view 단의 context 가 위와 같이 managementContext 였다면

사실 managementContext2 로 복사해서 사용하면 그만이지만..

또 언제 같거나 비슷한 형태의 뷰를 추가해야할지 모르기에

HOC 를 이용하면 아래와 같이 간단한 수정으로 컨텍스트의 중복 없이 같은 구조의 Context 를 사용할 수 있다

 

// hoc/management.tsx

import managementContext, { managementReducer } from "@/context/state";
import { PropsWithChildren, useReducer } from "react";

export const [ManagementContextProvider, useManagementContext, initManagementContextState] = managementContext();

const ManagementContextHOC = ({ children }:PropsWithChildren<{}>) => {

  const [state, dispatch] = useReducer(managementReducer, initManagementContextState);

  return (
    <ManagementContextProvider
    value={{state, dispatch}}>
      {children}
    </ManagementContextProvider>
  )
}

export default ManagementContextHOC;

 

// page1.tsx
import ManagementContextHOC from '@/hoc/management';

export default function Page1() {

  return (
    <ManagementContextHOC>
      <SomeComponent />
    </ManagementContextHOC>
  )
}

 

// page2.tsx
import ManagementContextHOC from '@/hoc/management';

export default function Page2() {

  return (
    <ManagementContextHOC>
      <SomeComponent />
    </ManagementContextHOC>
  )
}

 

context api + useReducer + HOC 를 이용한 위와 같은 구조는

무분별한 전역 상태 관리가 아닌

필요한 뷰 단에서의 상태관리를 구분짓기에 좋은 구조라고 생각한다

'web > React' 카테고리의 다른 글

digital envelope routines::unsupported  (0) 2023.06.20
React-Query Dynamic Parallel Queries  (0) 2023.06.06
제너레이터(Generator)  (1) 2021.01.11
Redux 비동기(redux-saga)  (0) 2021.01.11
리액트 내장 훅  (0) 2021.01.01

+ Recent posts