์๋ฐ์คํฌ๋ฆฝํธ์ ํ์ ์ ๊ฐ์ ์ํค๋ ์ธ์ด!
์๋ฐ์คํฌ๋ฆฝํธ์ ๋ฌ๋ฆฌ ๋ณ์์ ์๋ฃํ์ ์ง์ ํด์ฃผ๋ ํน์ฑ
๋ณ์์ ๋ฌธ์์ด์ ํ ๋นํ๋ค๊ฐ ์ดํ์ ์ซ์์ด์ ํ ๋นํด์ฃผ๋ฉด ๋ฌธ์ ๊ฐ ์๊ธด๋ค.-> let aaa(์์):string(์์์ด๋ฆ) = "์๋ ํ์ธ์"
aaa = 123let hello:string = "hello" // โ ๋ถ๊ฐ๋ฅ hello = 12345 // โญ๏ธ ๋ฌธ์์ด๋ง ํ ๋น ๊ฐ๋ฅํฉ๋๋ค. hello = "12345"
โ ๋ธ๋ผ์ฐ์ ๊ฐ ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ฝ๋ ๋ฐฉ๋ฒโ๏ธ
๋ธ๋ผ์ฐ์ ๋ HTML,CSS,Javascript๋ง ์ฝ์ ์ ์๊ธฐ์ ์คํ ์์ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ๋ณ๊ฒฝ๋์ด ์คํ๋๋ค.
-> ์ปดํ์ผ๊ณผ ํธ๋์คํ์ผ ์์ ์ด ํ์!
์ปดํ์ผ
: ํ๋์ ์ธ์ด๊ฐ๋ค๋ฅธ ์ธ์ด๋ก ๋ณ๊ฒฝ
๋๋ ์์ํธ๋์คํ์ผ
: ํ๋์ ์ธ์ด๊ฐ๊ฐ์ ์ธ์ด์ ๋ค๋ฅธ ๋ฒ์ ์ผ๋ก ๋ณ๊ฒฝ
๋๋ ์์
๋๊ตฌ๋ฅผ ์ปดํ์ผ๋ฌ ๋๋ ํธ๋์คํ์ผ๋ฌ ๋ผ๊ณ ํ๋ค.
์๋ฐ์คํฌ๋ฆฝํธ๋ ์ ์ฐํ ์ธ์ด์ด๊ธฐ ๋๋ฌธ์
๋ณ์๋ ์์์ ํ ๋น ๊ฐ์ด ์์ ์์ฌ๋ก ๋ณํ์ด ๊ฐ๋ฅํ๋ค.
ํ์ง๋ง ์ด๋ฐ ์ ์ด ํฐ ์๋น์ค๋ฅผ ๊ฐ๋ฐ ํ ๋๋ ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์๋ค.
ํ์ ์คํฌ๋ฆฝํธ์ ๊ฒฝ์ฐ ์ซ์๋ณ์์๋ ์ซ์๋ง, ๋ฌธ์์๋ ๋ฌธ์๋ง ๋ฃ์ด์ ์์ ์ฑ์ ๋์ฌ์ค๋ค!
-> interface์
I + ๋ณ์๋ช
์ ํฉ์ณ์ ๊ฐ์ฒดํ์ ์ ๋ง๋ค์ด์ฃผ๋ ๊ฒ์ด ๋ค์ด๋ฐ ๊ด๋ก!
๊ฐ ๋ณ์์ ํ์ ์ ์ง์ ํด์ฃผ๊ณ ๋๋ฉด, ํ์ ์ ๋ง์ง ์๋ ๊ฐ์ ํ ๋น ์ ์๋ฌ๊ฐ ๋๊ฒ ๋๋ค.
โ ์ค์น
typescript
1๏ธโฃ ๋ช ๋ น์ด (package.json ํ์ผ ์๋ ์์น)
yarn add typescript --dev
yarn add @types/react@17.0.2 @types/node@17.0.2 --dev
2๏ธโฃ typescript ์ค์ ํ์ผ(tsconfig.json)๋ง๋ค๊ณ yarn dev ํ๋ฉด ์๋์ผ๋ก ์ฑ์์ง
3๏ธโฃ strict์ true๋ก ๋ฐ๊พธ๊ธฐ(์๊ฒฉํ ํ์ ์คํฌ๋ฆฝํธ)
โ ํ์ผ ํ์ฅ์
- JSX ๋ฅผ return ํ๋ ์ปดํฌ๋ํธ : tsx
- ์๋ฐ์คํฌ๋ฆฝํธ๋ง ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ : ts
โ ํ์ ์ถ๋ก
๋ณ์์ ํ์ ์ ๋จผ์ ์ ํ์ง ์๊ณ ํ ๋น์ ํ๊ฒ ๋๋ฉด ํ์ ์คํฌ๋ฆฝํธ๋ ํ ๋น๋ ๊ฐ์ ์๋ฃํ์ ํ์ ์ผ๋ก ์ถ๋ก ํ๊ฒ ๋๋ค.-> string์ ํด์ฃผ์ง ์์๋ ์๋ฌ๋ฅผ ์ก์๋
ํ์ ์ด ์ถ๋ก ๋ซ๊ธฐ ๋๋ฌธ์โ ํ์ ์คํฌ๋ฆฝํธ ๋ฐฐ์ด, ๊ฐ์ฒด ์ค์ต
/* ๋ฐฐ์ดํ์ */ // ๋ฌธ์์ด๋ง ์๋ ๋ฐฐ์ด let aaa:string[] = ["์๋","์์ ","ํ์"] // ๋ฐฐ์ด์ ๋ฌธ์์ด๊ณผ ์ซ์์ด์ ๊ฐ์ด ๋ฃ์ด๋๊ณ ์ถ์ ๋ let fff:(string | number)[] = [1,2,3,"์ฒ ์","์ํฌ"] // ๋ชจ๋ ์ซ์์ด๊ฑฐ๋ ๋ชจ๋ ๋ฌธ์์ธ ๋ฐฐ์ด let hhh: string[] | nuber[] =[ "์ํฌ","์ฒ ์" ] hhh=[1,2,3] /* ๊ฐ์ฒดํ์ */ interface IPropfile { name : string age : number school : string } const profile:IPropfile = { name : "์๋" age : 8 school : "์ฝ์บ ์ด๋ฑํ๊ต" } //age์ ํ์ ์ด ๋ฌธ์์ด์ด๊ฑฐ๋ ์ซ์์ด์ผ ๋ interface IPropfile{ name : string age : string | number school : string } const profile:IPropfile = { name : "์๋" age : 8 or "8์ด" school : "์ฝ์บ ์ด๋ฑํ๊ต" }
โ๏ธย ํ์ ์คํฌ๋ฆฝํธ์์์ ๋๋, ๊ทธ๋ฆฌ๊ณ
๋๋ : |
๊ทธ๋ฆฌ๊ณ : &
โ๏ธ ๊ฐ์ฒด์์ ํด๋น key์ value๊ฐ ์์ผ๋ฉด ๋ณด๋ด์ฃผ๊ณ ์ถ์ ๋
โ ? ๋ฅผ ์ด์ฉ
? ๋ โ์์ผ๋ฉดโ ์ด๋ผ๋ ๋ป
strict๋ฅผ true๋ก ๋๊ฒ๋๋ฉด props์ชฝ์์ ๋นจ๊ฐ์ค์ด ๊ทธ์ด๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
๋ฐ๋ผ์ interface๋ก props์ ํ์ ์ ์ง์ ํด์ค์ผ ํ๋ค.
props์์๋ ์ฃผ๋ ์ ์ฅ๊ณผ ๋ฐ๋ ์ ์ฅ์ด ์๋ค.
ํ์ ์คํฌ๋ฆฝํธ๋ ํญ์ ๋ฐ๋ ์ชฝ์ด ์ค์ฌ!
๋ฐ๋ผ์ ๋ณด๋ด์ฃผ๋ ์ชฝ์์๋ ๋ฐ๊ฒ ๋ค๊ณ ํ ํ์ ๊ทธ๋๋ก๋ฅผ ๋ณด๋ด์ค์ผ ํ๋ค.
โ๏ธย ํจ์์ ํ์ ์ง์ ํด์ฃผ๊ธฐ
โ ํ๋ผ๋ฏธํฐ์ ํ์ ๋ํ ์ง์ ํด์ผ ํ๋ค./* props๋ฅผ ์ฃผ๋ ์ชฝ ์ปดํฌ๋ํธ */ // ํ๋ผ๋ฏธํฐ์ ํ์ ์ ์ง์ ํด์ฃผ์ ์ผ ํฉ๋๋ค. const add = (a: number, b: number) => { return a + b; }; return ( // ์ปดํฌ๋ํธ์ JSX๋ถ๋ถ <Component add={add} /> ); ------------------------------------------------------------------------ /* props๋ฅผ ๋ฐ๋ ์ชฝ ์ปดํฌ๋ํธ */ // ํจ์์ ํ์ ์ง์ ํด์ฃผ๊ธฐ // ๋ฆฌํด๋๋ ๊ฐ์ ํ์ ์ ์ ์ฉํด์ฃผ๋ฉด ๋ฉ๋๋ค. ๋ง์ผ ๋ฆฌํด๋๋ ๊ฐ์ด ์๋ค๋ฉด void๋ฅผ ์ ์ด์ฃผ์๋ฉด ๋ฉ๋๋ค. interface IProps { add: (a: number, b: number) => number; } const Component2 = (props: IProps) => { props.add(1, 2); return ( //์ปดํฌ๋ํธ์ JSX๋ถ๋ถ ); };
โ ํ์ ์ผ๋ก ๋ญ ๋ฐ์์ค๋ ์ง ์ ๋ชจ๋ฅผ ๋์ธ๋ถ์ ํต์ ํด์ ๋ฐ์์ค๋ api๊ฐ์ ๋ฐ์ดํฐ๋ ๋ญ ๋ฐ์์ค๋์ง ์ ๋ชจ๋ฅผ ์ ์๋ค
๊ทธ๋ด ๋๋ ์ผ๋จ ํ์ ์ any๋ฅผ ์ฃผ๊ณ ๋์ด๊ฐ๊ธฐ!
ํ์ ์คํฌ๋ฆฝํธ์์์ any๋ ๋ชจ๋ ํ์ ์ ์๋ฏธํ๋ค.
โ๏ธ ์ด๋ฒคํธ ํธ๋ค๋ฌ ํจ์์ ํ๋ผ๋ฏธํฐ(event) ํ์ ์ง์ ํ๊ธฐ
// HTML ํ๊ทธ๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ ํจ์๊ฐ ์ ์ฉ๋ ํจ์๊ฐ ๋ญ์ง์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ์ ํ๋ค. const onChangeMyWriter = (event: ChangeEvent<HTML inputelement>)=>{ setMywriter(event.target.value) }
ChangeEvent๋ ๋ฆฌ์กํธ์์ ์ ๊ณตํด์ฃผ๋ ํ์ ์ผ๋ก import๋ฅผ ํด์ ์ฌ์ฉํด์ผ ํ๋ค.
: ๋ด๊ฐ ์ํ๋ ํ์ ์ ์กฐ์ํด์ ํ์ํ ํ์ ๋ง ๋ฐ๋ก ๋นผ๋๊ฑฐ๋, ํ์์๋ ํ์ ๋ง ์ ๊ฑฐํ๋ ํ์ ์ ์๋ฏธ
export interface IProfile { name: string; age: number; school: string; hobby?: string; }
1. Partial
-> ์ ๋ถ ๋ฌผ์ํ์ฒ๋ฆฌ ํด์ฃผ๊ณ ์ถ๋ค๋ฉด
type aaa = Partial<IProfile>;
2. Required
type bbb = Required<IProfile>;
3. Pick
-> ์ ์ฒด ํ์ ์์ ์ํ๋ ํ์ ๋ง ์ง์
type ccc = Pick<IProfile, "name" | "age">; // name๊ณผ age ํ์ ๋ง ์ง์
4. Omit
-> ์ํ๋ ํ์ ๋ง ์ ๊ฑฐ
type ddd = Omit<IProfile, "school">; // school ํ์ ๋ง ์ ๊ฑฐ = name๊ณผ age ํ์ ๋ง ์ง์
5. Union Type / Record
//5. Record ํ์ ํ๋ํ๋๊ฐ ๋ค ๊ฐ๋ณ๋ ์ฝ๋์ type eee = "์ฒ ์" | "์ํฌ" | "ํ์ด"; //Unionํ์ - ์ํ๋ ํ์ ์ง์ ์ง์ const child1: eee = "์ฒ ์"; //์ฒ ์,์ํฌ,ํ์ด๋ง ๊ฐ๋ฅํจ. const child2: string = "apple"; // apple,banana,์ฒ ์,ํ์ด ๋ค ๋จ type fff = Record<eee, IProfile>; //Record ํ์ - union์ผ๋ก ์ง์ ๋ ํ์ ์ ์ํํ์ฌ ํ์ ์ง์ ------------------------------------------ //6. ๊ฐ์ฒด์ key๋ค๋ก Unionํ์ ๋ง๋ค๊ธฐ type ggg = keyof IProfile; //"name" | "age" | "school" | "hobby" let myprofile: ggg = "name"; ------------------------------------------ //7. type vs interface ์ฐจ์ด => interface๋ ์ ์ธ๋ณํฉ์ด ๊ฐ๋ฅ export interface IProfile { candy: number; //์ ์ธ๋ณํฉ์ผ๋ก ์ถ๊ฐ๋จ } ------------------------------------------ //8. ์์ฉํ๊ธฐ let profile: Partial<IProfile> = { candy: 10, };
rest-api๋ ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ ์ฉํ๊ฒ ๋๋ฉด ์ด๋์ ๋ ์ผ์ผํ ์์ผ๋ก ๋ง๋ค์ด์ผ ํ๋ ๋ถ๋ถ์ด ๋ง๋ค.
ํ์ง๋ง graphql ๊ฐ์ ๊ฒฝ์ฐ๋ graphql-codegen์ ์ด์ฉํด ๋ช ๋ น์ด ํ๋๋ก ๋ง๋ค์ด์ฃผ๊ธฐ ๋๋ฌธ์ ๊ต์ฅํ ๊ฐํธํ๊ฒ ๋ง๋ค ์ ์๋ค.โ graphql์ codegen ์ค์นํ๊ธฐ
1๏ธโฃ ์ค์น
graphql-codegen
yarn add -D @graphql-codegen/cli
yarn add -D @graphql-codegen/typescript
yarn add ts-node2๏ธโฃ codegen.yaml ํ์ผ์ ๋ง๋ค๊ณ ์๋ ๋ด์ฉ ์ ๋ ฅ(โ๏ธ์ธ๋ดํธ ์ฃผ์)
//codegen.yaml ํ์ผ (yml, yaml ๋ ๋ค ์๊ด ์์ต๋๋ค.) schema: http://backend-example.codebootcamp.co.kr/graphql generates: ./src/commons/types/generated/types.ts: plugins: - typescript config: typesPrefix: I
3๏ธโฃ package.json ํ์ผ์ ์๋ ์ฝ๋๋ฅผ ์ถ๊ฐ ํ ์ ์ฅ
4๏ธโฃ yarn generate ๋ช ๋ น์ ์คํ
โ graphql์ codegen ์ ์ฉํด๋ณด๊ธฐ
1๏ธโฃ mutation์ ํ์ ์คํฌ๋ฆฝํธ ์ ์ฉํด๋ณด๊ธฐ
// ๊ฒฐ๊ณผํ์ ๊ณผ ๋ณ์ํ์ ์ types.ts ํ์ผ์์ importํด์ ๋ฐ๋ฆฌ๊ณ ์จ๋ค. const [ํจ์] = useMutation<๊ฒฐ๊ณผํ์ ,๋ณ์ํ์ >(์ฟผ๋ฆฌ); /* ์ค์ ์ฝ๋์ ์ ์ฉํด๋ณด๊ธฐ */ // ๋ค์ด๋ก๋๋ ํ์ ๋ค ์ค ๋ง๋ ํ์ ์ ๋ฐ๋ฆฌ๊ณ ์ฌ๋๋ Pick์ ์ด์ฉํ๋ฉฐ ํด๋น ํ์ ์ importํด์จ๋ค. const [createBoard] = useMutation<Pick<IMutation, "createBoard">, IMutationCreateBoardArgs>(CREATE_BOARD); const onClickUpload = async () => { const result = await createBoard(CREARTE_BOARD); console.log(result.data?.createBoard?.message); }
2๏ธโฃ query์ ํ์ ์คํฌ๋ฆฝํธ ์ ์ฉํด๋ณด๊ธฐconst { data } = useQuery<Pick<IQuery,"fetchBoard">,IQueryFetchBoardArgs>(FETCH_BOARD,{ variables: {number: Number(router.query.mynumber)} })
โ๏ธ input tag์ readOnly ์์ฑ
input tag์ readOnly ์์ฑ์ boolean ํ์ ์ด๋ค. ๋๋ฌธ์ ์ด ํ์ ์ด string ํ์ ์ด ๋๋๋ก ๋ง๋ค์ด์ค์ผ ํ๋ค.
์ด์ค๋ถ์ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํด ํด๊ฒฐ์ด ๊ฐ๋ฅํ๋ค.
data?.fetchBoard.writer์ string ํ์ ์ด์ง๋ง boolean ํ์ ์ผ๋ก ๋ณด๋ฉด string์ด ์๊ธฐ ๋๋ฌธ์ true์ด๋ค.
์ฌ๊ธฐ์ !data?.fetchBoard.writer ํด์ฃผ๋ฉด false๊ฐ ๋๊ณ ,
ํ ๋นํด์ค ๋ฐ์ดํฐ๋ฅผ ๊ทธ๋๋ก ๊ฐ์ ธ์ค๊ณ ์ถ์ ๊ฒฝ์ฐ์๋ !!data?.fetchBoard.writer ์ฒ๋ผ ์ด์ค๋ถ์ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ๋ฉด true์ธ ์ํ ๊ทธ๋๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค.
- disabled : ์์ ํ์ด์ง์์ ์์ ์๋๊ฒ๋ ํ ์ ์์.
- early-exitํจํด: ์๋ชป๋ ๋ด์ฉ๋ค์ ๋จผ์ ์ข ๋ฃ์ํจ๋ค.
- ๋ฆฌํฉํ ๋ง ์กฐ๊ฑด! ๊ฒฐ๊ณผ๊ฐ์ ๋ณํจ์ด ์์ด์ผ ํ๋ค.