타입스크립트 사용기 📘

Seokho·2022년 6월 17일
0

Westagram Project

목록 보기
2/4

타입스크립트

타입스크립트.. 올해 초 취업을 준비할때까지만 해도 공고를 봤을때 타입스크립트가 필수역량이라는 생각은 들지 않았다. 솔직히 학습의 우선순위에 급하지 않았다! 하지만 하루, 한달 시간이 흐르면서 모든 프론트엔드 공고에 타입스크립트를 필수역량으로 보는 회사가 많아졌습니다. 두둥.

그래서 일단 부족했던 자바스크립트와 기본적인 CS지식을 학습하고 여러번의 면접 이후 타입스크립트를 당장 학습해야겠다는 생각이 들었습니다! 그래서 토이프로젝트를 진행하기로 결정했습니다.

일단 기초지식을 학습 후 프로젝트를 진행했고, 아래의 링크를 통해 학습 내용을 볼 수 있습니다.

타입스크립트 학습 링크

타입스크립트 사용 이유

Typescript는 자바스크립트의 타입 부분을 업그레이드해서 사용하고 싶을 때 설치해서 쓰는 일종의 자바스크립트의 대용품입니다. 자바스크립트는 Dynamic typing을 지원하는 언어로, 타입에 대해 상당히 관대합니다. 하지만 서비스의 규모가 커질수록 이는 단점이 되고 type관련 에러를 자주 만나게 될 것입니다. 이를 해결하기 위해 Typescript를 사용합니다.

정리

언어의 기본 사용법과 문법은 자바스크립트와 동일, 하지만 타입을 추가적으로 선언

결론

  1. 동적인 자바스크립트를 정적으로!

    • 타입 선언으로 컴파일 시, 에러를 사전에 잡아줍니다.
  2. 에러 메시지가 구체적이고 명확하게 나온다!

프로젝트에서의 타입스크립트 활용

타입스크립트의 기본적인 사용법을 익힌 후 프로젝트를 시작했습니다. 솔직히 처음에는 어려움 없이 진행했습니다. 하지만 중간중간에 학습하지 못했던 파트가 등장했고, 애매하고 쉽게 해결되지 않았던 파트 위주로 정리했습니다!

스타일컴포넌트와 타입스크립트

참고: 스타일컴포넌트+타입스크립트

스타일컴포넌트를 사용하는 이유는 컴포넌트 관리와 스타일링을 동시에 사용할 수 있기 때문입니다. 특히 스타일컴포넌트에서 props를 스타일링할때 편하게 사용할 수 있기에 더욱 많이 사용되는데, props를 받을때도 타입을 지정해야 했습니다.
이 부분에서 어려웠던 점은 하나의 props를 받을 때, 다수의 props를 받을 때의 방식이 다르다는 점 입니다.

1개 props

props를 1개만 받을 시 간단합니다. 아래의 코드와 같이 받는 props의 타입을 지정해주면 됩니다.

const Container = styled.div< { age : number } >`
  color: ${(props) => (props.age > 20 ? 'red' : 'gray')};
`;

다수의 props

다수의 props를 받을 시 Interface를 꼭 사용해야 합니다.

// 상속컴포넌트의 타입 상속받기
interface Container {
  isActive: boolean;
  age: number;
  프롭스명: 타입지정;
}

// 상속받은 컴포넌트에 타입 추가하기
const Container = styled(상속받을 컴포넌트명)<Container>`
  color: ${(props) => (props.age > 20 ? 'red' : 'gray')};
  background-color: ${(props) => (props.isActive ? 'red' : 'gray')};
`;

부모 컴포넌트 -> 자식 컴포넌트로 전달하는 props

리액트를 사용하면 props를 전달하며 타입지정에 어려움을 느꼈습니다. 처음이라 방법을 몰라서 어려웠지만 익숙해지니 간단하게 해결할 수 있었습니다.

일단 기본적으로 부모 컴포넌트에서 자식 컴포넌트로 props를 전달할때, 자식 컴포넌트에서 props의 타입을 지정해줘야 합니다. 처음에 아래와 코드와 같이 작성했었는데, 이렇게 작성하면 안됩니다. props는 자식컴포넌트에서 타입을 지정해줘야 하기 때문이죠.

export default function MainComments(props: { comment: string }) { 
  return (
    <li>
      Seokho__lee {commentItem}
      <FiHeart></FiHeart>
    </li>
  );
}

그렇다면 어떻게 작성해야할까요? props가 1개일때와 다수일때가 다릅니다.

1개 props

매우 간단합니다. 받아오는 props를 자식 컴포넌트에서 직접 타입을 지정해주면 됩니다.

export default function MainComments({ commentItem }: { comment: string }) { 
  return (
    <li>
      Seokho__lee {commentItem}
      <FiHeart></FiHeart>
    </li>
  );
}

다수의 props

1개의 props는 직접 타입을 지정해주면 되지만, 여러개의 props를 받는다면 다른 형태로 작성해야 합니다. 물론 1개의 props를 받을때처럼 작성해도되긴 하지만 가독성 측면에서 아주 좋지 않습니다.
결론적으로 다수의 Props를 받을때는 Interface를 사용합니다! (type도 사용 가능)

아래의 코드는 type을 사용했을 때의 예시 입니다.

export type UserType = {
  name: string
  age: number
  position: string
}

export default function User ({name, age, position}: UserType) {
  
  return (
    <div>
      <p>이름: {name}</p>
      <p>나이: {age}</p>
      <p>포지션: {position}</p>
    </div>
  )
}

다수의 props + 함수

사실 1개 혹은 다수의 props를 받는 것은 매우 간단합니다. 형태만 알면 쉽게 작성할 수 있습니다. 다만 함수를 props로 받을 때 약간 헷갈릴 수 있기 때문에 정리해봅니다!

일단 자식컴포넌트에서 props의 타입을 지정할때 Interface를 자주 사용하게 되는데, Interface의 이름 앞에 'I' 를 통상적으로 사용합니다. I의 뜻은 Interface라는 뜻입니다.

또한, 함수를 받을때의 형태가 어색한데, '파라미터'의 유무에 따라 따라서 형태가 달라집니다.

import { CommentsType } from '../../../Type/Interface';

interface IProps {
  commentList: CommentsType;
  removeComments: () => void; // 파라미터와 함수의 return이 없을 경우
  removeComments: (id: number) => void; // 파라미터가 있고 함수의 return이 없을 경우
}

export default function MainComments({ commentList, removeComments }: IProps) {
  return ()
};

Evnet 사용 시 타입 지정

타입스크립트로 프로젝트를 진행하며 가장 난감하고 제일 골치 아팠던 부분이 Event 부분이었습니다. Event를 작성할때마다 리서칭을 통해서 어떤 타입을 지정해줘야할지 알아보면서 해결했습니다.
물론 마우스 오버하면 타입을 알려줍니다만, 저와 같이 타입스크립트를 처음 공부하는 사람들은 열심히 리서칭해서 여러 참고 문서와 글을 보면서 지정하는게 좋다고 생각합니다.

onChange

onChange의 경우 React.ChangeEvent<HTMLInputElement> 로 이벤트가 사용됩니다.

const updateComment = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      setComment(e.target.value);
    },
    [setComment]
  );

onClick

onClick의 경우 React.MouseEventHandler<HTMLButtonElement> 로 이벤트가 사용됩니다.

const updateComment = useCallback(
    (e: React.MouseEvent<HTMLButtonElement>) => {
      setComment(e.target.value);
    },
    [setComment]
  );

onKeyPress

onKeyPress의 경우 React.KeyboardEvent<HTMLInputElement> 로 이벤트가 사용됩니다.

const keyEnter = useCallback(
    (e: React.KeyboardEvent<HTMLInputElement>) => {
      if (e.key === 'Enter') {
        addFeedComment();
      }
    },
    [addFeedComment]
  );

타입 정리 및 리팩토링

Interface 자주 사용하며 느낀점은 Interface도 재사용하면 되지 않을까..? 라는 생각이었습니다. 전역 상태관리처럼 따로 폴더를 만들어 재사용하면 코드의 가독성 측면에서 훨씬 좋을 것으로 예상되었습니다.
결론적으로 관심사 분리를 통해 효율적으로 Type 관리를하며 재사용성을 높이고, 가독성을 보다 좋게 코드를 작성했습니다.

// Interface.tsx

export interface ImageType {
  id: number;
  image: string;
  description: string;
}

export interface CommentsType {
  id: number;
  name: string;
  comments: string;
}

export interface IgetData {
  url: string;
}

export interface IResponse {
  id: number;
  image: string;
  name: string;
  description: string;
}

정리

타입스크립트를 처음 써보고 느낀점은 귀찮지만 유용하고 꼭 필요하다 라는 느낌이었습니다. 아직 완벽하게 친숙하진 않기에 너무 좋다! 는 아니지만, 타입을 디테일하고 명확하게 지정해줌으로써 현업에서 팀원들과 함께 프로젝트를 진행함에 있어 생산성을 높여줄 것으로 예상됩니다🔥

profile
같이의 가치를 소중하게 생각하는, 프론트엔드 개발자 이석호 입니다.

0개의 댓글