본문 바로가기

메가테라 FE 생존코스 12기

[메가테라 FE 생존코스] 8주차 회고

3L 회고

👍 Liked

  • 지난 주에 라우터 테스트를 배웠는데 이번 주에 직접 실습을 통해 테스트 코드를 추가 및 리팩토링 해볼 수 있어서 좋았다.
    • 지난 주 과제에서는 해당 라우터 경로일 때, 지정된 컴포넌트가 렌더링 되는지만 확인했더라면 이번 과제를 하면서 query-string 값으로 undefined 값이 전달되었을 때에 대한 라우트 테스트 코드도 추가하여 여러가지 상황에 대한 고려를 해줄 수 있었다.

📘 Learned

  • Pure CSS를 사용하면서 불편했던 점들에 대해 알게 되었고 이를 위한 해결책으로 CSS-In-JS가 등장했다는 것을 배웠다.
    • CSS-In-JS를 사용하면 컴포넌트와 동일한 레벨에서 CSS를 관리하여 각 CSS는 지역변수로서 사용되어 개발의 유지보수성이 좋아진다.
    • 별도의 CSS 파일 없이 JS만으로도 스타일링을 할 수 있다. 그러므로 JS 변수를 사용하기 용이하다.
  • ThemeProvider로 defaultTheme을 설정하여 디자인 시스템의 기초를 배웠다.
    • 더 나아가 darkTheme을 정의하여 라이트 모드와 다크모드 설정을 간편하게 하는 방법을 배워서 나중에 잘 써먹을 수 있을 것 같다.
    • 나는 defaultTheme에 컬러, 폰트사이즈, 폰트 패밀리, 폰트굵기 등을 정의해두어 매번 스타일링을 할 때마다 이들을 참조하여 스타일링 하였다. 하지만 해설코드에서는 컬러와 사이즈(폰트, 패딩, 레이아웃)을 지정해두었다.
    • 생각해보니 추후에 반응형을 적용한다고 하면 layout 사이즈에 각 화면별 사이즈를 지정해두고 스타일링할 때 break-point를 사용하여 스타일링하면 편할 것 같다고 생각된다.
  • CSS input의 돋보기 모양 스타일링할 때 항상 img 태그를 포함하여 구현했었는데, 이번에 input 태그의 배경에 추가하는 방법을 배웠다.
    • 배경으로 추가하게 되면 img를 사용했을 때와는 달리 img를 클릭해도 input이 정상 클릭되는 것을 처리할 수 있다.
    • img로 넣게 되면 img 클릭 시 input이 클릭되지 않는 이슈가 있었다.
  • Jest 환경에서 테스트할 때, RouterProvider 및 themeProvider를 사용한 것에 대한 렌더링 환경도 갖춰줘야 하는 것을 배웠다.
  • styled-components를 사용하여 디자인 시스템의 여러가지 버튼의 생김새를 어떻게 표현할 수 있는지 배웠다.
const StyledButton = styled.button.attrs<ButtonProps>(
  (props) => ({ type: props.type ?? 'button' }),
)<ButtonProps>`
  width:230px;
  height:84px;
  border-radius: 20px 20px 0 0;
  font-size:${(props) => props.theme.fontSize.lg};
  color:${(props) => (
    props.active
      ? props.theme.colors.primary
      : props.theme.colors.title)};
  background-color:${(props) => (
    props.active
      ? props.theme.colors.restaurant_bg
      : 'transparent')};
`;

위 코드에서는 active props에 대해서만 삼항연산자로 조건부 스타일링을 적용해주고 있다. 하지만 만약에 button 컴포넌트에 primary, secondary 등 조건이 다양할 때, 해당 조건에 맞는 스타일링을 해주기로는 위 방법으로는 삼항연산자가 복잡해지므로 부적절하다.

 

const StyledButton = styled.button.attrs<ButtonProps>(
  (props) => ({ type: props.type ?? 'button' }),
)<ButtonProps>`
  width:230px;
  height:84px;
  border-radius: 20px 20px 0 0;
  font-size:${(props) => props.theme.fontSize.lg};
  
  ${(props) => props.active && css`
    color: #FF8400;
    background: ${props.theme.colors.secondary};
    transition: .3s;
  `}
`;

그럴 때는 위와 같은 방법으로 각 props에 대해 && 연산자로 적용할 스타일을 따로 지정해주는 것이 편리하다.

  • Jest 환경에서 외부 라이브러리 함수의 mock 함수를 테스트 하는 방법을 배웠다.
import { fireEvent, screen } from '@testing-library/react';
import DarkModeToggle from '.';
import renderWithThemeProvider from '../../../renderWithThemeProvider';

const mockedUsedToggle = jest.fn();

jest.mock('usehooks-ts', () => ({
  ...jest.requireActual('usehooks-ts'),
  useDarkMode: () => ({
    toggle: mockedUsedToggle,
  }),
}));

const context = describe;
describe('DarkModeToggle', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    renderWithThemeProvider(<DarkModeToggle />);
  });

  it('it renders 밝게, 어둡게 button', () => {
    const light = screen.getByText('밝게');
    const dark = screen.getByText('어둡게');

    expect(light).toBeInTheDocument();
    expect(dark).toBeInTheDocument();
  });

  context('if user click button', () => {
    it('toggle function will be called', () => {
      const toggleBtn = screen.getByRole('button');
      fireEvent.click(toggleBtn);

      expect(mockedUsedToggle).toHaveBeenCalled();
    });
  });
});

usehooks-ts 라이브러리의 useDarkMode hook을 사용했는지 테스트 하기 위해 위와 같이 설정해줬다. 이 뿐만 아니라 React-Router의 useNavigation hook 테스트도 할 수 있다.

😅 Lacked

  • 그동안 자바스크립트 위주로 테스트 코드를 작성하고 간단한 HTML만 사용하다가 styled-components를 사용하여 CSS 문법을 작성하려니 어려웠다.
  • Jest 코드를 작성할 때, 절대 경로를 사용하지 못하고 상대경로로 mock 함수를 불러오니 불편했다. 다음에 쇼핑몰 프로젝트에 들어갈 때는 Jest에 절대 경로를 설정해보자.
  • 디버깅 능력이 부족한 것 같다. 어떤 에러가 발생하면 그 에러가 어떤 원인 때문에 발생했는지 생각이 딱 떠오르지 않는다. 이는 에러 메시지를 꼼꼼히 읽어보면서 어떤 에러인지 정확히 판단하는 것이 중요한 것 같다.

느낀점

이번주는 CSS-In-JS 등장 배경에 대해 배우고 대표적인 CSS-In-JS 라이브러리인 Styled-Components 를 사용하여 스타일링을 해봤다. 그동안 JS 위주로 테스트 코드를 작성하고 간단한 HTML만 작성하다가 CSS로 스타일링하려니 어려웠다. CSS는 자바스크립트 처럼 뭔가 사람마다 작성하는 방식도 다르고 캐스캐이딩이 되기 때문에 스타일이 생각대로 되지 않을 때 디버깅하기가 어려운 것 같다.

 

그래도 pure css의 단점들을 보완하여 CSS-In-JS를 사용하니 편리한 점을 느낄 수 있었다. 예를 들면 props 값이나 JS 변수를 사용하여 조건부 스타일링을 적용하기도 편리하고 지역 변수처럼 스타일이 적용되니 스타일 명명 규칙도 생각할 고민도 적어지니 편리했다. 하지만 이런 CSS-In-JS에 대해서도 성능 이슈가 있다는 것도 간과하면 안된다. CSS-In-JS는 브라우저 렌더링에서 JS 파일의 용량의 줄여 성능 최적화를 추구하려는 목적과 반한다. JS에 CSS 코드 까지 작성고 라이브러리가 자동적으로 해주는 로직들이 포함되어 있어 JS 용량이 늘어나기 때문이다.

 

때문에 이러한 장점과 단점을 고려하여 개발자의 경험을 높이는데 중점을 맞추느냐 사용자의 경험을 높이는데 중점을 맞추느냐에 따라 어떤 방법으로 CSS를 사용할 것인지 결정해야한다. 그리고 이러한 결정을 내리는 주체는 개발자들이고 이런 결정을 내리기 위해서는 해당 라이브러리의 구조와 방식에 대한 명확한 이해가 필요하므로 새로운 라이브러리를 도입할 때에는 그 라이브러리에 대한 이러한 이해가 뒷받침 되어야 한다.