• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    해결됨

타입스크립트로 리액트 프로젝트 만들면서 궁금한 사항이 있습니다. (이미지 파일 import, 타입 추론 어디까지?)

23.12.29 11:44 작성 23.12.29 11:57 수정 조회수 329

1

안녕하세요. 이정환 강사님:)

타입스크립트 강의를 듣고, 리액트에 적용하고 있는중 궁금한 사항이 생겨 질문을 올립니다.

오늘도 많은 자료들을 찾아보고, 고민하는 시간도 가져봤는데 궁금증이 풀리지 않아서 글을 남깁니다 ㅠㅠ...

 

이미지 파일 import 질문

리액트에서 이미지 파일(jpg, png 등...)을 사용할 떄는 크게 2가지 방법이 있다고 들었습니다.

public폴더에 image폴더를 관리할 것인가, src폴더에 image폴더를 관리할 것인가에서 시작합니다.

 

public 폴더에서 image폴더 관리

  • 아래 코드처럼 index.html에서 기준이 되어 절대경로로 바로 불러오기 편합니다.

<img src="../image/이미지파일1.png">

 

src폴더에서 image폴더 관리

  • 아래 코드처럼 절대경로로 불러온 파일을 이미지파일1에 담아 src속성안에 객체로 형태로 전달해 사용합니다.

import 이미지파일1 from "../image/이미지파일1.png"

<img src={이미지파일1}>

 

위에 예시 이외에 많은 방법들이 존재하겠지만 제가 조사한 결과 두개가 대표적이며, 코드만 놓고 봤을때는 "public에서 관리하는게 편한거 아니야?" 라고 생각할 수 있지만 각각의 장단점이 있더라구요. 과연 어디에서 관리하는게 맞을까요? 라고 질문을 드리고 싶고 추가적으로 아래 코드에서 질문이 하나더 있을 예정입니다...

 

(어디에서 관리하는게 좋을까? 참고사이트)

https://velog.io/@rimo09/React-Create-react-app-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90%EC%84%9C-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EA%B2%BD%EB%A1%9C%EB%A5%BC-%EC%84%A4%EC%A0%95%ED%95%98%EB%8A%94-4%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95

 

src폴더에서 image폴더 관리 ... 타입스크립트 적용

  • 우리는 src폴더에서 이미지 관리를 하며 타입스크립트를 적용할 떄 2가지를 신경 써줘야 할 것 같습니다. 첫번쨰는 확장자이고, 두번쨰는 타입입니다. 아래코드를 확인해봐주시면 감사하겠습니다.

import 이미지파일1 from "../image/이미지파일1.png"
import 이미지파일2 from "../image/이미지파일2.png"
import 이미지파일3 from "../image/이미지파일3.png"

type Item = {
  [key: string]: {
    name: string;
    src: ?(어떤 타입이 들어가야 할까요?);
    alt: string;
  };
};

const item: Item = {
  image1: {
    name: "이미지1입니다.",
    src: 이미지파일1,
    alt: "이미지1",
  },

  image2: {
    name: "이미지2입니다.",
    src: 이미지파일2,
    alt: "이미지2",
  },

  image3: {
    name: "이미지3입니다.",
    src: 이미지파일3,
    alt: "이미지3",
  },
};

 

위에 예시를 보면 타입스크립트가 아니기 떄문에 오류를 발생시키지 않고 있지만... 처음 저렇게 import해서 불러온다면 경로에서 오류를 발생시킵니다. 그것은 png, jpg같은 확장자를 인식하지 못하기 떄문인데요 그래서 저희는 가장 최상위 루트 폴더에 d.ts파일안에 확장자를 추가해주고 시작해야합니다. 그 후 import한 이미지파일들을 객체에 담아서 사용하고 싶을 경우 const item과 같이 작성할 수 있을것 같습니다. 이제 우리는 item의 타입을 정해줘야하는데 저같은 경우 인덱스 시그니처 문법을 사용했습니다. 그러면 src의 타입은 뭐라고 해줘야할까요? 타입 추론으로 두어도 상관은 없지만 어떤 타입으로 추론했는지 마우스를 올려보니 any...타입으로 추론하더라구요... 이것이 저의 두번쨰 질문이였습니다.

 

(확장자 오류 해결방법 참고사이트)

https://velog.io/@gabdol/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EA%B2%BD%EB%A1%9C-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95

 

타입추론 어디까지? 질문

다음 질문입니다... 질문이 너무 많아서 죄송합니다ㅠㅠ...

보통 저희가 수업에서 배울 떄 정말 많은 타입을 정해줬어야 합니다... 변수, 함수, 리액트에 적용한다면 Hook까지도요... 하지만 타입스크립트에는 타입추론 기능이 있기떄문에 모든곳에 다 적용할 필요는 없다고 배웠는데 과연 어디까지 그게 적용이 될지 궁금합니다... 아래코드를 확인해주시면 감사하겠습니다.

const randomItem = (): string => {
  // 아이템 key 배열
  let itemKey: string[] = Object.keys(item);

  // 랜덤 숫자 출력
  let randomNumber: number = Math.floor(Math.random() * itemKey.length);

  // 아이템 key배열 중 랜덤 숫자에 해당하는 인덱스 아이템을 반영한다.
  return itemKey[randomNumber];
};

 

위에 예시는 item이라는 객체에 key를 배열에 담아서, 랜덤 숫자에 해당하는 아이템을 반환하는 함수입니다.

함수에 반환타입 string부터 함수 안에 모든 변수들에 타입을 지정해주었는데 안써줘도 코드에는 문제가 생기지 않았습니다. 과연 어디까지 써주고 안써줘도 되는지 알 수 있을까요??

 

useState Hook 타입질문

이제 마지막 질문입니다... 여기까지 읽어주셔서 감사합니다 ㅠㅠ

저희는 useState가 동일한 값을 가질떄 객체로 담아서 사용하는 방법을 배웠습니다.

const [Item, setItem] = useState({
  userItem: null, // string 값이 들어올 예정
  computerItem: null, // string 값이 들어올 예정
});

 

위에 코드처럼 Item이라는 변수안에는 user와 computer에 해당하는 동일한 string값을 가지고 처음에는 빈값인 null값을 가집니다. 그러면 useState에 제네릭을 사용해줘야하는데 아래 코드처럼 작성해주면 되는 걸까요?

 

const [item, setItem] = useState<string | null>({
  userItem: null, // string 값이 들어올 예정
  computerItem: null, // string 값이 들어올 예정
});

 

그리고 만약 useState값을 로컬스토리지에서 가져와야 할 경우 어떻게 해줘야할지도 궁금합니다.

아래코드는 useState에 삼항연산자를 작성한 형태입니다. 로컬스토리지에서 가지고 올 값이 없다면 null값을 반영하고 있다면 로컬스토리지값을 가지고 오는건데 아래같은 경우에는 타입을 어떻게 지정해주면 좋을까요?

 

const [item, setItem] = useState(
  !JSON.parse(localStorage.getItem("item"))
    ? {
        userScore: null,
        computerScore: null,
      }
    : JSON.parse(localStorage.getItem("item"))
);

 

질문이 너무 많았습니다... 감사합니다 ㅠㅠ

답변 1

답변을 작성해보세요.

1

안녕하세요 이정환입니다.

1번 질문

우선 이미지 파일 관리는 가급적 src에서 진행해주시는걸 권장하고 있어요! 한입 리액트 강의에서는 숫자에 따라 이미지를 동적으로 불러오는 기능을 보여드리기 위해 public 디렉토리 내에서 관리 했었는데요 src 디렉토리 내에 이미지를 보관한 다음 import로 불러와 사용하면 빌드 과정에서 번들에 포함되고 또 DataURI 형식으로 압축도 되기 때문에 특별한 경우가 아닌 이상 (이미지가 엄청 많다거나하지 않으면) src 디렉토리 내에 보관하시는걸 추천드려요!

더 자세한 내용을 확인하시려면 아래의 공식문서를 방문해보시면 좋을 것 같아요!

https://create-react-app.dev/docs/adding-images-fonts-and-files/

 

2번 질문

타입추론을 어디까지 이용할 것인지에 대한 범위는 사실 팀바팀, 케바케 인 것 같아요
기본적으로는 타입추론이 가능한 부분은 추론되게 두고 타입을 직접 명시하지 않는것이 권장되는 걸로 알고 있어요 그래서 올바른 타입으로 잘 추론 되도록 코드를 작성하는것이 권장됩니다. 그러나 함수의 반환값 타입같은 부분은 협업 관점에서 가독성을 위해 일부로 명시하는 경우도 꽤 있습니다.

 

3번 질문

state에 담길 값이 { userItem: string, computerItem: string } 형식의 객체라면 useState의 제네릭 타입도 { userItem: string; computerItem: string} 타입으로 정의해주셔야합니다.

로컬스토리지에서 보내주신 코드와 같이 값을 가져오고 있다면 { userScore: string | null; computerScore: string | null} 혹은 { userScore:string; computerScore:string} | { userScore:null; computerScore:null} 로 설정해주시는게 좋아보입니다.

그러나 보통은 로컬스토리지에서 데이터를 불러올 때 null 이거나 데이터가 있거나 형식으로 불러오는 경우가 많기 때문에 null | {userScore:string; computerScore:string} 형식으로 불러오도록 수정하시는것도 좋아보입니다.

 

PS.

질문이 여러개여도 괜찮습니다. 다만 다른 분들도 올려주신 질문을 보고 학습하실 수 있도록 질문을 항목별로 분리해 여러개로 올려주시면 더 좋을 것 같습니다 👍

한상윤님의 프로필

한상윤

질문자

2023.12.29

앗 감사합니다! 혹시 이미지 import 질문에서 import한 이미지를 객체에 담고 싶을떄는 어떤 타입으로 지정하는게 좋을지 여쭤봤는데 어떤 타입으로 지정하는게 좋을까요?