티스토리 뷰
2023년 8월, 원티드 프리온보딩 프론트엔드 챌린지 요약
지역변수와 전역변수
프로그래밍을 하다보면, 지역변수와 전역변수를 어떻게 사용해야 할 지 고민할 때가 있다.
여기서 알아가야 할 것은, 가급적이면 "지역변수"를 사용하는 것이 권장된다. "전역변수"는 가독성에도 불편함을 줄 수 있고, 나중에 에러가 발생할 가능성도 존재한다. 그래서 꼭 필요한 경우에만 전역변수를 사용해야 한다.
Context API
이는, 상태관리에 필요한 기술로 리액트 내장 패키지로 추가 라이브러리 설치할 필요가 없다.
관심사가 여러 개라면, 숫자에 맞는 "Provider"를 선언해야 한다.
그러나, Context API를 사용하게 되면 불필요한 렌더링이 발생할 가능성이 있으니, 이를 유의해서 사용해야 한다.
Recoil
이는, 리액트와 유사한 "syntax"이다.
"atom"이라는 "state"를 사용하며, "atom"을 조작하는 "selector"를 사용하게 된다.
최근, 많은 회사에서 사용하고 있으니 프론트엔드 개발자를 준비한다면 사용해봐야 한다고 생각이 든다.
가끔, Recoil을 사용할 때면, atom을 공통함수에서 사용하기 어려울 때가 있다는 이야기가 있다.
이러면 안 된다!
const calculateTotalPrice = (price: number) => {
const count = useRecoilValue(countState);
return price * count;
}
위 처럼 사용할 때, 그런 이야기가 나올 수 있는데, 함수가 Pure Function이 아니며, 같은 Input이 들어와도 항상 같은 output을 반환할 수 없는 구조이기 때문이다.
그래서 아래와 같이 수정해서 사용할 수가 있다.
let count = 1;
const calculateTotalPrice = (price: number) => {
return price * count;
}
또한, Recoil은 Context API보다 효율이 좋다. 디테일(필요한 부분)만 불러오기 때문에 렌더링에 효율적이다.
Context API는 Provider부터 요소들을 불러오기 시작하지만, Recoil은 감지된 페이지만 불러오기 때문에 렌더링면에서 효율성이 좋다.
React Query
이는, "서버 상태 관리"를 말한다.
일반적으로 "staleTime"과 "CacheTime"을 사용하게 되며, "Optimistic Update"을 한다.
Optimistic UI With React Query 정리
Implement Optimistic UI for insert/update/delete mutations with React Query
uncertainty.oopy.io
Test Agenda
- 무엇을 테스트 할 것인가?
- 어디까지 테스트 할 것인가?
- 어떻게 테스트 할 것인가?
우리는 위의 질문들을 생각해봐야 한다.
또한, 테스트에는 여러가지가 존재한다.
- 유닛 테스트
- 통합 테스트
- E2E 테스트
- 테스트 자동화
- 프론트엔드 TDD
무엇을 테스트 할 것인가?
테스트를 진행할 때, UI 테스트는 진행하지 않는다.
로그인 화면에서 비밀번호를 입력하는 것과 버튼 사이의 거리를 재는 것은 의미가 없기 때문이다.
또한, UI는 기기의 크기에 따라 달라질 것이기 때문에 테스트가 크게 의미가 있지 않다.
그리고 컴포넌트 렌더링의 순서도 의미가 크게 없다.
JSX는 선언한대로 렌더링이 되기 때문이다. 인풋이 버튼 위에 존재하는지는 테스트할 필요가 없다는 것이다.
우리는, 요구사항의 "사용자 시나리오"에 집중해야 한다.
아이디, 비밀번호를 입력했을 때, 버튼이 활성화가 되는지는 크게 중요하지 않다.
그보다 중요한 것은, "로그인이 성공했는가?", "로그인이 실패했는가?"가 중요하다.
즉, "기능"에 중점을 두고 테스트를 진행해야 한다.
특정 태그가 스타일이 어떻게 되었는지 테스트 할 필요는 없다. 의미가 크지 않기 때문이다.
타이틀이 렌더링이 되고 버튼이 렌더링이 되는 것 등 이런 테스트도 크게 의미가 없다. 프로그램을 검증한다는 것에서 의미가 없다는 것이다.
사용자 입장에서 어떤 점이 중요한 지 생각하고 테스트를 진행해야 한다.
제대로 입력해서 다음 페이지로 가느냐, 잘못 입력해서 에러가 발생하느냐가 중요한 것이다.
무엇을 테스트 할 것인가?
테스트를 진행하게 될 때, 무엇을 테스트할 지 고민할 필요가 있다.
로그인 화면에서 버튼 테스트를 진행할 수 있을 것이다.
또는, 테스트 시나리오를 생각할 수 있을 것이다.
- 버튼이 잘 보이는가?
- 버튼이 요구조건에 맞게 활성화가 되는가?
- 활성화가 된 버튼을 클릭하면 이벤트가 제대로 발생하는가?
무엇을 테스트 할 것인가?
테스트를 진행할 때, 추가적으로 생각해야 할 것은 "무엇을" 테스트할 지 고민하는 것이다.
다음과 같은 것들을 테스트할 수 있을 것이다.
- 로그인 화면에서 버튼 테스트
- 버튼이 잘 보이는가?
- 버튼이 요구조건에 맞게 활성화가 되는가?
- 활성화가 된 버튼을 클릭하면 이벤트가 제대로 발생하는가?
- 로그인 유효 테스트
- 제대로 된 계정정보로 로그인이 잘 되는가?
- 잘못된 계정정보로 로그인이 실패하는가?
- 로그인 실패 여부가 "에러 메시지"로 확인이 가능한가?
- 해당 항목은 확인이 가능한가?
여기서 가장 중요한 것은, "테스트를 위한 테스트를 하지 말아야 한다"는 것이다.
테스트 코드를 제대로 작성되어 있는지 테스트하는 것은 의미가 퇴색되는 것이기 때문이다.
다시 무엇을 테스트 할 것인지 고민하는 과정으로 돌아가서,
- 다시 로그인으로 되돌아가 로그인이 제대로 동작하는지 확인하려면
- 이벤트 핸들러가 제대로 동작하는가?
- 버튼이 잘 그려지는가?
만약, "로그인 성공"이라는 간단한 기능에 유닛테스트를 진행하고 있다면, 그리고 로그인 성공을 테스트한다면
- 인풋이 제대로 작동하는가?
- 버튼이 제대로 작동하는가?
- HTTP Request도 제대로 이루어져 있는가?
위의 과정이 과연 통합 테스트일까?
프론트엔드는 유닛 테스트와 통합 테스트의 경계가 애매하기 때문에 확정짓기 어렵다.
어떻게 테스트 할 것인가?
그렇다면, 테스트를 어떻게 해야 할까? 중요한 것은 다음과 같다.
- Given - When - Then
- True 또는 False 반환
- 결과값을 Expectation Value와 비교
- 테스트는 한 번에 하나씩 진행
단위 테스트
단위테스트는 코드의 가장 작은 단위를 테스트하는 것이다.
- 각 컴포넌트
- 각 함수
- Jest를 많이 사용
로그인을 예로 들자면,
- 아이디와 비밀번호 입력 필드가 존재하는가?
- 아이디와 비밀번호 입력 필드가 적절한 속성(Type, Name 등)을 가지고 있는가?
- 로그인 버튼이 존재하고, 활성화된 상태인가?
- 아이디, 비밀번호가 없을 때, 로그인 버튼을 클릭하면 에러 메시지가 표시되는가?
- 로그인 함수가 예상대로 동작하는가?
위에서 작성되었듯이, 단위 테스트와 통합 테스트의 경계는 모호하다.
통합 테스트
통합 테스트는 여러 컴포넌트나 모듈이 함께 작동하는 경우를 테스트하는 것을 말한다.
컴포넌트 간 상호작용을 확인
단위테스트보다 넓은 범위
로그인으로 예를 들면,
- 아이디와 비밀번호를 입력하고 로그인 버튼을 클릭했을 때, 올바른 요청이 서버로 전송되는가?
- 서버에서 응답이 오면 적절하게 UI가 업데이트 되는가?
- 로그인이 성공한 후에 사용자를 적절한 페이지로 리디렉션을 하는가?
E2E 테스트
이는, 사용자 관점에서 어플리케이션 플로우를 전체적으로 테스트를 말한다.
- 사용자의 실제 흐름을 테스트
실제 환경에서 테스트를 한다면,
- 모든 컴포넌트
- 데이터베이스
- 네트워크
- 사용자 인터페이스
로그인으로 예를 들면,
- 사용자가 실제 환경과 같은 상황에서 웹 사이트를 방문하여 아이디와 비밀번호를 입력하고, 로그인 버튼을 클릭하는 과정을 시뮬레이션
그러나, E2E 테스트는 애자일에 부적합하다. 물론 사람마다 의견이 다르겠지만, 이는 빠른 대응과 수정이 불가능하기 때문에 부적합한 것에 가까울 것이다.
프론트엔드 TDD
완벽한 TDD는 사실상 불가능하다.
Component UI를 먼저 작성한다면, 비즈니스 로직에 대한 테스트를 먼저 작성하고 비즈니스 로직을 작성하는 것은 가능할 것이다.
하지만, 이는 완벽한 TDD라고 볼 수는 없다. 그렇기 때문에 완벽한 TDD는 불가능하다고 생각할 수 있다.
무엇을 공부해야 할까?
- 최신동향 파악
- 채용공고 분석
- 기술면접 대비
- 프로그래머스
- Leetcode
- 면접 스터디
- 실전 면접 경험
면접 스터디는 면접을 많이 본 사람과 한다면 자주 나오는 면접 질문들을 미리 파악 가능하다.
테스트 코드의 필요성
테스트 코드 작성은 리팩토링할 때 가장 큰 의미가 있다.
대규모 프로젝트를 하거나, 이주를 할 경우에 테스트 코드 작성을 하는 게 좋다.
Jest
Jest에서 "it"과 "test"는 차이가 없다.
Jest 코드 작성할 때, "act"를 작성하고 "nock"을 작성해야 에러가 발생하지 않는다.
describe("로그인 페이지", {
...
fireEvent.change(emailInput, { target: { value: "email" } });
fireEvent.change(passwordInput, { target: { value: "password" } });
act(() => {
// 실행된 화면의 name이 로그인인 버튼을 가져오기
const loginBtn = screen.getByRole("button", { name: /로그인/ });
userEvent.click(loginBtn);
});
nock("https://wanted.hong.com")
.post(`/user/login`, {
username: "registered",
password: "password",
})
.reply(200, { token: "AUTH_TOKEN" });
await waitFor(async () => {
// expect(result.current.isSuccess).toBe(true); => 가상의 결과를 가져오는 테스트로 무조건 true이기 때문에 가능한 테스트
// 실제 화면에서 가져온 요소들로 테스트하기 때문에 위의 expect를 사용하면 에러, 아래처럼 실제 location의 path 값을 활용해야 한다.
expect(history.location.pathname).toBe("/");
});
test("로그인 실패 시 에러메시지", async () => {
render(
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={theme}>
<MemoryRouter initialEntries={["/login"]}>
<Routes>
<Route ...>...</Route>
</Routes>
</MemoryRouter>
</ThemeProvider>
</QueryClientProvider>
)
})
})
프론트엔드 필요 학습
프론트엔드 CS는 네트워크 등을 공부하고, 아래의 레퍼런스들을 확인하면 좋다.
웹에서의 웹 소켓(Web-Socket), 핸드쉐이크(Hand-Shake), HTTP, HTTPS, TCP/IP 등의 CS를 알고 있어야 한다.
GitHub - Integerous/goQuality-dev-contents: { 고퀄리티 개발 컨텐츠 모음 }
{ 고퀄리티 :zap: 개발 컨텐츠 모음 }. Contribute to Integerous/goQuality-dev-contents development by creating an account on GitHub.
github.com
JS 정리
1. var, let, const에 대해
cheryl-yena-yun.notion.site
프론트엔드 CS 정리
1. 브라우저 주소창에 www.google.com을 입력하면?
cheryl-yena-yun.notion.site
추가 질문
- AccessToken은 어디에 저장하면 좋을까?
- accessToken은 localStorage에 넣는 경우가 많다.
- 그러나, 보안을 생각한다면 최소한의 저장소인 HttpOnly 쿠키 또는 메모리에 저장하는 방식을 고려해야 한다.
- accessToken이 만료되었을 때의 refreshToken은 어디에 저장하면 좋을까?
- sessionStorage는 브라우저가 종료될 때, 삭제되기 때문에 불편함이 발생할 수 있다.
- localStorage는 영구적인 저장소로 보안면에서 위험할 수 있다.
- accessToken과 마찬가지로 httpOnly 쿠키 또는 메모리에 저장하는 방법이 좋다.
'여러가지 활동 > 프리온보딩 프론트엔드 챌린지' 카테고리의 다른 글
React 최적화 (0) | 2023.08.08 |
---|---|
프론트엔드 아토믹 디자인 패턴 (0) | 2023.08.07 |
디자인의 간격 요소와 반응형을 위한 그리드 그리고 텍스트 (0) | 2023.08.02 |
UI/UX와 디자인 시스템 정의, 사례 (0) | 2023.08.01 |
원티드 프리온보딩 프론트엔드 챌린지 후기 (0) | 2023.06.24 |
- Total
- Today
- Yesterday
- 신입개발자가 준비해야 할 것들
- 포스텍애플디벨로퍼아카데미
- 스프링
- 설명회느낌점
- javascript
- PostechAppleDeveloperAcademy
- 원티드 프리온보딩 챌린지
- if(kakao)dev2022
- 싱글톤
- 개발자이력서꿀팁
- 자바스크립트
- Singleton
- LottieFiles
- 코딩테스트 대비
- 고민한 부분
- node
- 포스텍애플아카데미
- DB Error MongooseServerSelectionError
- 프론트엔드 챌린지
- 원티드 프리온보딩
- Express
- #포스텍애플디벨로퍼아카데미
- 최종추가합격
- 개발 이력서 지원 팁
- 조코딩과함께
- 깃허브 Merge
- 그룹인터뷰후기
- Default Branch
- Frontend
- React
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |