React JS 마스터클래스 (2. TYPE SCRIPT)

짜스의 하루 ·2024년 5월 31일

TYPESCRIPT

타입스크립트란 ? 자바스크립트의 단점을 보완하기 위해 만들어진 정적 타입 언어라고 생각하면 될 것 같다.

자바스크립트가 확장된 언어이기 때문에 기존 자바스크립트의 기능을 모두 사용할 수 있고 브라우저에서 실행하기 위해서 컴파일(complile)이라는 변환 과정을 거쳐야 한다.

왜 타입스크립트를 사용해야 할까? (사실 아직까지도 왜 사용하는지 이해가 안되긴 한다.. 이제 익숙해져야 할 시간인가 ..)

  • 에러의 사전 방지
  • 코드 가이드 및 자동 완성(개발 생산성 향상)

자바스크립트의 큰 특징 중 하나라고 생각이 들었던 것 중 하나가 되게 유연하다(?) 였다.
자바를 공부하고 넘어와서 그런지 되게 꽉 막혀있던 것들이 좀 유연해졌다! 싶었는데 이걸 이제 타입스크립트로 다시 꽉 막아야 한다.. 오히려 더 좋을지도 ㅎㅎ

Interface 사용

인터페이스는 객체가 가져야 할 속성, 속성의 타입, 메서드 등을 명시하여 코드의 명확성과 타입 안전성을 높이는 데 도움을 준다.

이렇게 말로만 설명하면 이해가 되지 않으니까 ! 예제로 살펴보겠다

interface Person {
	name : string,
	age : number,
	address?: string
}

let user = Person {
	name : '서연',
	age : 25
}

address? 속성은 선택적 속성을 나타낸다. 즉, Person을 정의할 때, addrress는 정의해도 되고 안해도 된다!

interface에 Person 객체에 대한 속성과 타입을 명시해두면, 타입에 맞지 않을 때 (만약 내가 age에 '25살' 이라고 string 타입을 명시했다면), 코드가 실행되기 전에, 타입 오류라는 오류 메시지를 나에게 제공해준다.

interface Employee extends Person {
	 employeeId: number
}

let employee = Employee {
	name : '원식', 
    age : 27,
    employeedId : 123,
    address : '우면동'
}

Employee 인터페이스는 Person 인터페이스를 확장하여 추가적인 employeeId 속성을 정의한다.
--> 인터페이스 확장

이렇게 명시하면 :

  • 객체의 구조와 타입을 명확히 정의할 수 있다.
  • 타입 오류를 사전에 방지하여 코드의 안정성을 높일 수 있다.
  • 코드를 더 읽기 쉽고 유지보수하기 쉽게 만들 수 있다.


현재, Circle 컴포넌트에 bgColor 를 props로 넘겨주어 배경색을 설정하려고 하고 있다.
--> Circle 컴포넌트가 받아서 Container 컴포넌트에 전달하며, 해당 색상으로 배경색이 설정되게 된다.

그렇다면, Circle 컴포넌트와 관련 코드를 살펴보자!


인터페이스 정의:

  • ContainerProps와 CircleProps 인터페이스를 통해 bgColor가 문자열 타입임을 명시한다.

Container 컴포넌트:

  • styled-components를 사용하여 스타일을 정의한다. ContainerProps 인터페이스를 통해 bgColor props를 받아 배경색을 설정한다.
  • <ContainerProps> 형태로 받았다.

Circle 컴포넌트:

  • CircleProps 인터페이스를 사용하여 bgColor를 props로 받아, Container 컴포넌트에 전달한다.

App 컴포넌트:

  • Circle 컴포넌트를 사용하여 bgColor를 props로 전달하고, 이를 통해 배경색이 서로 다른 원을 렌더링한다.

이렇게 정의할 수 있을 것 같다!


Optional Props

위에서 간단하게 언급하고 넘어갔었던 것 같은데,
typeScript에서는 선택적 속성을 적용할 수 있다.

자, 위의 코드에서 border-color 속성을 준다고 가정해보자.

첫번째 Circle에는 borderColor 속성을 주었고, 두번째 Circle에는 주지 않았다.

먼저, Circle 컴포넌트는 borderColor를 props로 받아오고, Container 컴포넌트로 넘겨주었다.

여기서, CircleProps에서는 borderColor?:string 으로 ? 를 사용해서 선택적 속성을 적용해 주었다. 즉, borderColor는 string 타입이거나, undefined이다! 를 의미한다.
이렇게 친절하게도 string | undefined 알려주고 있다.

하지만, Circle 컴포넌트를 통해서 받는 Container 컴포넌트의 경우, borderColor:string 으로 무조건! string 타입으로 명시를 해주어야 하기 때문에,

현재 저 빨간색 밑줄이 나면서 오류가 발생하고 있다.
이때,
default props를 지정해두면 된다.
borderColor ?? 'bgColor' --> borderColor이 있으면, borderColor로, 없으면 'bgColor'로 기본값을 주겠어~ 를 의미한다고 이해하면 된다.


출력값을 보면, borderColor를 준 첫번째 원은 yellow로 테두리가 생겼지만, borderColor를 주지 않은 두번째 원은 기본 값인 bgColor와 같은 색깔로 테두리가 생긴 것을 확인할 수 있다.

default Props 주는 다른 방법 (타입스크립트 아님)

요렇게 {text} 값을 가져오려고 하는데, CircleProps에서 text를 text?:string 으로 명시해두면서, 선택적 속성을 주었다.

여기서, 간단하게 default 값을 전달할 수 있는데, 전달 받은 props 옆에
text = 'default text' 와 같이 default 값을 지정해 주는 것이다.

이렇게 지정해 두면, 명시안한 첫 번째 원에는 default 값인 default text 가,
두 번째 원에는 Im here이 적혀져 있을 것이다.

따란~ 진짜다

이는 타입스크립트 방식이나 타입스크립트에서 제공하는 방식이 아닌 간단한 자바스크립트의 기능이다.
유용하게 쓰이니까 꼭 알아두자!!


State

우리는 useState()훅을 사용하고, setState()를 사용해서 값을 변경한다.

그럼 그 값을 변경할 때, 타입스크립트를 사용해서 타입을 지정해줘야 할까?
--> 굳이 지정을 안해주어도 된다.
--> useState()를 사용해서 지정한 default값으로, 타입스크립트가 유추해서 타입을 지정해주기도 하고, default로 지정한 타입에서 왠만하면 타입이 변경되지 않기 때문이다.

그럼 간단한 counter 를 만든다고 가정해보자

counter의 타입을 명시해 둔 적이 없지만 타입스크립트가 알아서 counter= number로 판단해주어서, string 타입이나, boolean 타입으로 값을 주게 되면, 오류가 발생하는 것을 확인할 수 있다.

그래도 타입을 number, string 두개를 사용해야 하는 경우가 있을 수 있지 않을까 ?
그럴 경우에는 어떻게 해야할 까?

const [counter, setCounter] = useState<number | string>(0)으로 명시해두었다.

useState<number | string> 으로 명시를 해두면, counter의 타입을 number, string 두개 모두 받을게~ 를 의미해 setCounter(0), setCounter('hello')가 오류가 나지 않는 것을 확인할 수 있다.

타입입을 바꿀 일이 정말 드물긴 하지만, 그래도 이렇게 변경된다는 것을 알아두면 좋을 것 같다!

Forms

useState()는 크게 신경을 안써도 된다고 해도, Form 즉, 이벤트는 어떻게 주어야 할 까?

이러한 Input 태그와 Button 태그가 있다고 가정해보자.


이제, Input에서 받아오는 value의 값을 가져와야 한다. 이때 우리는 useState()를 사용할 수 있다.

const [username, setUsername] = useState('')
기본값을 '' 빈 값을 주어 string 타입으로 명시해 두었다.

이제 해야할 것들이 두가지 남아있다.
1 . onChange 이벤트
2 . onSubmit 이벤트

TypeScript 를 사용해서 이벤트 함수를 생성해보자.

먼저, onChange 함수를 생성해보자
const onchange = (e.React.ChangeEvent<HTMLInputElement>)

  • React.ChangeEvent<HTMLInputElement> 타입의 이벤트 객체이다.
    즉, 입력 요소()의 값이 변경될 때 발생하는 이벤트이다.
  • e.currentTarget는 이벤트가 발생한 요소를 가리킨다. 여기서는 입력 필드(<input>)를 가리킨다.
    --> e.currentTarget.value는 사용자가 입력한 텍스트를 의미한다.

const onSubmit = (e: React.FormEvent<HTMLFormElement>)

  • React.FormEvent<HTMLFormElement><form> 요소에서 발생하는 이벤트에 대한 정보를 포함하는 React의 이벤트 객체의 타입을 나타낸다.
    이것은 주로 <form> 요소의 제출(submit) 이벤트나 유효성 검사(validation)와 같은 폼 관련 이벤트에서 사용한다.

React.FormEvent는 React에서 제공하는 이벤트 객체의 일종,
<HTMLFormElement>는 폼 요소를 가리키는 HTML 태그--> DOM에서 <form> 요소의 타입을 나타낸다.

React에서는 다양한 종류의 이벤트가 발생할 수 있는 다양한 요소들이 있다. 예를 들어, <input> 요소에서는 텍스트가 입력될 때마다 ChangeEvent가 발생하고, <form> 요소에서는 폼이 제출될 때 FormEvent가 발생한다.


Themes

이전에 했던 darkmode, lightmode를 기억하는가 ?!
타입스크립트와 Themes을 결합해서 darktheme, lighttheme을 만들어보자!

자 먼저, styled.d.ts 파일을 생성해줄 것이다.
--> TypeScript와 styled-components를 함께 사용해서 커스텀 테마를 정의하는 것이다.


import 'styled-components';:
styled-components 라이브러리를 가져온다. 이는 styled-components를 TypeScript 프로젝트에서 사용하겠다는 것을 의미한다.

declare module 'styled-components':
*TypeScript에서 모듈을 선언하는 구문.
이 부분은 styled-components의 타입을 확장(extend)하고자 할 때 사용된다.

export interface DefaultTheme:
styled-components의 기본 테마를 정의하는 부분이다.
DefaultTheme은 styled-components 패키지에 이미 정의되어 있는 인터페이스
여기서는 기본 테마에 새로운 속성을 추가하여 확장하고 있다.

{ textColor: string; bgColor: string; btnColor: string; }:
DefaultTheme 인터페이스를 확장하여 새로운 속성을 추가한다.

두번째로는 theme.ts 파일을 생성해준다.

import { DefaultTheme } from 'styled-components';:
styled-components 패키지에서 기본 테마(DefaultTheme) 를 가져온다. 이는 위에서 선언한 DefaultTheme 인터페이스를 가져오는 것이다.

export const lightTheme: DefaultTheme = { ... };:
lightTheme이라는 이름의 변수를 선언하고, 이를 DefaultTheme 인터페이스와 함께 타입으로 지정한다.

--> styled-components를 사용하여 두 가지의 테마를 정의하고, 이를 각각 lightTheme과 darkTheme으로 내보낸다. 이를 통해 React 애플리케이션에서 두 가지 다른 테마를 사용할 수 있다.

이제 index.jsx 에서 사용해보자

ThemeProviderstyled-components에서 제공하는 컴포넌트 중 하나로, React 애플리케이션에서 테마를 쉽게 관리하고 적용할 수 있도록 도와준다.

ThemeProvider의 theme prop에는 darkTheme 객체가 전달되었으므로, 애플리케이션 전체적으로 어두운 테마가 적용된다.

이제 App.jsx에서 적용해보자!

간단하게, styled-components를 사용하여 Container와 H1 컴포넌트를 정의했다.

여기서 중요한 테마와의 연동:
styled-components를 사용하여 스타일을 정의할 때, ${(props) => props.theme.XXX} 형태로 테마의 속성을 사용할 수 있다.

여기서 props.theme.XXX는 테마 객체에서 가져온 값을 나타낸다.
예를 들어, props.theme.bgColor는 테마 객체에서 정의된 bgColor 속성의 값을 의미한다.

이를 통해 테마에 따라 동적으로 스타일을 적용할 수 있다.


이렇게 Dark 모드 적용이 잘 된 것을 확인할 수 있다!

profile
2024. 01. 02 ~ 백앤드 공부 시작, 2024. 04.01 ~ 프론트 공부 시작

0개의 댓글