원티드 온보딩: 마무리, 이것저것

윤뿔소·2023년 3월 16일
0

Wanted

목록 보기
4/4

현업에서 많이 사용하는 것들

useCallback

모든 fetcher들한테 많이 쓴다. useEffect보다 이걸로 fetcher마다 써주는 것이 좋을듯? + await도 같이 써줘 항상 fetch 데이터가 뒤처지지않게 만들어주자!

const GeneralLayout: React.FC<GeneralLayoutProps> = ({children, isAdminPage}) => {
  {/* TODO 4-2: Recoil atom `UserAtom`을 이용해 userProfile props 대체 및 삭제 */}
  const [ userProfile, setUserProfile ] = useState<User | null>(null)
  const {routeTo} = useRouter()

  const fetchUserProfile = useCallback(async () => {
    const userProfileResponse = await getCurrentUserInfo()

    if (userProfileResponse === null) {
      routeTo('/login')
      return
    }

    {/* TODO 4-2: Recoil atom `UserAtom`을 이용해 setUserProfile props 대체 및 삭제 */}
    setUserProfile(userProfileResponse)
  }, [])
// TODO 4-2: getItems를 호출하여 userItem을 가져온 경우 상태 업데이트
  const fetchUserItems = useCallback(async () => {
    const userItem = await getItems();

    if (userItem !== null) setItems(userItem);

    isUserItemsFetched.current = true;
  }, []);

이렇게 말이다.

물론 성향마다 다르긴 하지만 useCallback으로 하나씩 관리하는 게 더 편할 수도 있다. 물론 배우고 있는 react-query를 쓰면 더 좋다^^

WebStorm

인텔리제이를 만든 IDE 회사, JetBrain에서 만든 JS 전용 IDE이다.

  • 가끔 서버 돌리거나 할 때 변수 주입하기 편함
  • 라이브 템플릿 만들어서 쓰는 기능
  • 백링크 타고 들어가는 기능

이정도가 되게 좋다고 한다. 유료라고 한다,, ㅠㅠ 회사에서 사줬으면 좋겠다.

토큰의 리프레쉬

현업에 많이 사용한다. axios의 instance와 같이 사용하자

// CASE 1 - Refresh token 이 로컬스토리지에 저장되어 있을 때, 서버에 refresh token 을 보내 access token 을 재발급 받는다
const refreshToken = async () => {
  const token = getLocalStorageAuthToken ()
  const response = await axios.post ('${ BASE_URL }/auth/refresh', { token })
  const newToken = response.data.token
  localStorage.setItem('access_token', newToken)
}
// CASE 2 - Refresh token 이 쿠키에 저장되어 있을 때, 서버 정책에 맞게 요청을 보내 access token 을 재발급 받는다.
const refreshToken = async () => {
  const response = await axios-post ('${BASE_URL}/auth/refresh', {}), {withCredentials: true})
  const newToken = response. data. token
  localStorage.setItem('access_token', newToken)
}
const axiosClient = (() => {
  const axiosInstance = axios.create({ baseURL: BASE_URL });
  axiosInstance.interceptors.response.use(
    (response) => { ... },
    async (error: AxiosError) => {
      if (error.code === "ECONNABORTED") {
        alert("서버에 이상이 있습니다.");
      }
      switch (error.response?.status) {
        case 401:
          console.info("401: 인증정보 없음 - refresh token으로 access token 재발급 시도");
          // 서버 구현에 따라 Invalid access token 문제였는지 확인하는 적절한 조건문 작성.
          if (error.message === "invalid access token") {
            try {
              // refresh token으로 access token 재발급을 시도하고
              // 에러가 난 요청의 config를 가져와서 다시 요청을 보낸다.
              await refreshToken();
              const config = error.config;
              return await axiosClient({
                method: config?.method,
                url: config?.url,
                data: config?.data,
              });
            } catch (e) {
              // 재발급에 실패한 경우에는 로그인 페이지로 보낸다.
              return (window.location.href = "/login");
            }
          }
          ...
      }
    }
  );
  ...
})();

이런 식으로 refreshToken을 발급 받는다.

OAuth

Open Authorization, 허가된 다른 서비스를 통해
기존 서비스(Google 등)의 권한을
“위임”하는 것

권한에 따라 OAuth 원본 서버(예제에서의 구글)의 유저 정보를 가져와 사용하거나 권한을 위임받은 동작을 할 수 있으며(ex. Calendly - 캘린더에 일정 등록)인증 자체만을 사용할 수도 있다.

동작 원리

구글, 카카오, 네이버, 페이스북 등을 통틀어 OAuth 로그인 이라고 칭하겠다.

  1. 사용자가 클라이언트에서 OAuth 로그인 요청을 보냄, 클라이언트는 OAuth 로그인 링크를 리다이렉트하여 확인받고 오라고 함
  2. 사용자는 OAuth 링크에서 자기 계정을 로그인하고, 성공시 임시 값(암호)을 내어줌
  3. 그 임시값을 들고 사용자는 클라이언트에 전달, 클라는 OAuth 로그인 서버에 임시값을 대조하려고 전달
    3-5. 통신할 때 클라와 OAuth 로그인 서버가 가지고 있는 시크릿 키가 같으니 중간에 다른 방해가 불가
  4. 서비스 공급자, 임시 암호, 유저 이름, 접근한 페이지 정보가 올바르다면 OAuth 로그인 서버에서 승인하고, 클라는 사용자에게 인증 성공을 했다고 알림
  5. 토큰을 받아 관련 권한을 얻고 사용자는 활동 가능

이런 식의 동작 원리가 있다.

프론트엔드와 싱글톤 패턴

되게 가벼운 얘끼이니 그냥 보고 넘기자.

싱글톤 패턴

들어 봤나? 난 아니.. 바로 수행했던 과제 안의 라우터 엘리먼트가 가진 패턴이다.

const routerData: RouterElement[] = [
  {
    id: 0,
    path: "/",
    label: "Home",
    element: <Home />,
    withAuth: false,
  },
  {
    id: 1,
    path: "/login",
    label: "로그인",
    element: <Login />,
    withAuth: false,
  },
  {
    id: 2,
    path: "/page-a",
    label: "페이지 A",
    element: <PageA />,
    withAuth: true,
  },
]

즉, 중요한 것은 섞이지 않는 데이터다. 관련 데이터 소스를 하나 생성하고 이 데이터 하나만 여러개를 만들고, 다양한 곳에 사용하는 것이다.

마치 OOP 처럼 하나를 추상화하여 만들고 그것을 인스턴스처럼 새끼들에게 나눠 사용하는 것이다. 이게 프론트엔드한테 왜 중요할까?

싱글톤이 아니라면?

하나의 앱에서 이렇게 관리하는데 만약 나눠져 있다면 라우터의 페이지들과 뷰포트 상의 페이지의 값이 달라질 수도 있다. 정확히 얘기하자면 'Origin'이 다르다는 것. 만약 API 호출까지 겹친다면,, 난리가 날 것이다.

출처가 다르니 어떤 식을 수행하면 여기는 되고 저기는 안되고 그럴 수도 있다. 그러므로 애초에 기획할 때 싱글톤을 사용해야할 땐 하나의 Origin에서 분화시켜 가져가야한다.

알아두면 좋을 것

트러블슈팅 중 충돌

다른 직군과 ‘잘’ 이야기하려면 어떻게 해야될까?

서로의 지식&작업 범위를 크로스하는 작업들을 아는 것이 중요하다. 특히 로그인도 논쟁의 주제로 많이들 나오는데, 어떤 건 백엔드가 해야되고 어떤 건 프론트가 해야한다. 이 점을 알고 생각할 것, 떠넘길 것을 제대로 구분하는 것이 서로 일하는데 편하다.

그렇다고 '역할 나누기 != 책임범위 나누기' 가 아니다. 서로 각자의 분야라고 하더라도 모를수 있다는 것 이해해야하는 것도 있다. 그래서 어떤 오류든 같이 보고 같이 해결하도록 노력해야된다.

'알고있다는 것'

리액트 함수형 컴포넌트가 무엇인가요?

라는 질문을 받았을 때 어떻게 생각해야할까?

우리는 '정의'를 내릴 때 제대로 '하는 것'이라든지, '한다는 특징'이라고 말하는 것은 정의를 내리는 것이 아니다. 즉, 정확히 모른다는 뜻이다.
'~하는 것 === ~하는 무언가' 에서 알 수 있듯이 어떤 대상에게서 일어나는 현상은 대상을 정의하는 것이 아니다.

다시 대답해보자.

리액트 함수형 컴포넌트는
JSX.Element 형태의 값을 반환하는
순수 자바스크립트 함수입니다.

추가

리액트 함수형 컴포넌트는 어떤 기능이 있나요?

리액트 함수형 컴포넌트는
useState같은 hook을 사용할 수 있고
내부에 JSX 문법을 사용할 수 있으며
props 를 전달받을수도 있어요

라고 대답을 해야 좀 더 좋은 대답을 할 수 있다. 꼭 유의유의 유ㅠ이하자!

참고: 면접 팁?

  1. 명확하게 아는 건 아닌데 사용해본 적이 있다면

    명확하게 아는 건 아니지만, 사용해본 경험에 의하면 ~~~한 것입니다.
    라고 답하기 물론 명확하게 아는게 최고

  2. 질문의도 잘 파악해서 같은 주제로 답하기
    당연한 거지만 만약 모른다면 이렇게 되묻기

    ~~한 질문인 거 같은데 맞습니까?

최대한.. 바로 투입될 수 있는 실력을 기르자..

profile
코뿔소처럼 저돌적으로

6개의 댓글

comment-user-thumbnail
2023년 3월 16일

다양한 주제로 정리하셨네요 유용한 팁도 알아가고 감사합니다

답글 달기
comment-user-thumbnail
2023년 3월 19일

알아두면 좋은 것도 진짜 알차네용ㅎㅎ 잘 보고 갑니다..

답글 달기
comment-user-thumbnail
2023년 3월 19일

마지막 적어주신 팁 잘 가져가겠습니다!

답글 달기
comment-user-thumbnail
2023년 3월 19일

오늘도 알찬 내용 즐감하고갑니다 ~

답글 달기
comment-user-thumbnail
2023년 3월 19일

마지막에 깨알 면접 팁까지.. 알찬 포스트 잘 읽었습니다 😃

답글 달기
comment-user-thumbnail
2023년 3월 19일

온보딩을 끝까지 완주하시다니 그것만으로도 엄청 나십니다!

답글 달기