REVIEW오늘은 가지우삼겹 솥밥을 먹었다. 푸짐하고 굿
제네릭이나 인터페이스, type 사용 연습이 필요할 듯;; 타입스크립트…어색한걸…화살표 함수도..
프로젝트 캠프 5일차
타입스크립트🍍
node_modules와 package-lock.json 는 npm이 관리하기 때문에 직접 변경 절대 금지. 항상 git ignore에 등록해두기
npx tsc // tsconfig.json 수정 후 해당 명령어로 ts > js 변환(src와 dist 폴더 생성)타입스크립트에서 추가된 기본 타입
string / number / boolean / object / Array / tuple / any / null / undefined;타입 추론 : 타입스크립트가 자동으로 타입을 추론
// 타입스크립트에서 사용할 수 있는 타입
// 타입 연산자 - | &
const a: string = "hi";
const b: number = 30;
const c: boolean = true;
const d: null = null;
const e: undefined = undefined;
const f: symbol = Symbol("symbol");
const h: number[] = [1, 2, 3];
const i: Array<string> = ["a", "b", "c"];
const x: Array<string | number> = [10, "apple", "banana", 20];
const j: [string, number] = ["hello", 10]; // tuple
const k: { name: string; age: number } = { name: "Alice", age: 25 };
const q: (x: number, y: number) => number = (x, y) => x + y;❇️ 옵셔널 파라미터
타입스크립트에서 함수의 매개변수를 옵션으로 설정하려면 매개변수 뒤에 ?를 붙이면 됩니다. 이렇게 하면 해당 매개변수가 전달되지 않았을 때 undefined로 간주됩니다. 이를 통해 함수 호출 시 매개변수를 생략할 수 있습니다.
+.(a: number, b: number = 0)처럼 디폴트값을 줄 수도 있다.
function sum(a: number, b: number): number {
return a + b;
}
sum(10); // 오류: 2개의 인자가 필요합니다.
function sum(a: number, b?: number): number {
return a + (b ?? 0); // b가 undefined일 경우 0을 더합니다.
}
console.log(sum(10)); // 10
console.log(sum(10, 5)); // 15❇️ type 키워드
type 키워드를 사용하여 타입 별칭(type alias)을 정의할 수 있습니다. 타입 별칭은 기본 타입, 복합 타입, 유니언 타입, 인터섹션 타입 등을 더 간결하게 표현할 수 있게 해줍니다.
type GreetFunction = (a: number, b: string) => string;
const greet: GreetFunction = (a, b) => {
return `Hello, ${b}! You have ${a} new messages.`;
};
console.log(greet(5, "Alice")); // Hello, Alice! You have 5 new messages.type Person = {
name: string;
age: number;
gender?: string; //옵션이므로 파라미터 생략해도 괜찮음
};
// 타입을 준수하는 객체 생성
const person1: Person = {
name: "Alice",
age: 30,
};타입은 객체에서 속성 구분을 ;으로 한다. , 를 쓰지 않는다.
type Person = {
name: string;
age: number;
gender?: string;
};
type myWorker = {
readonly company: string;
doWork: () => void;
};
type Employee = Person & myWorker;
// 올바른 속성을 포함하여 employee 타입의 객체 생성
const temployee: Employee = {
name: "Alice",
age: 25,
company: "Example Inc.",
doWork: () => {
console.log("Working...");
},
};❇️ 인터페이스
코드의 구조를 정의하고 타입을 명시하는 역할을 합니다. 즉, 어떤 객체가 해당 인터페이스를 따르는지를 명시적으로 선언합니다.
// Person 인터페이스 정의
interface Person {
name: string;
age?: number; // readonly도 가능
}
interface Person {
redefine: number;
}
// Person 인터페이스를 준수하는 객체 생성
const user: Person = {
name: "Alice",
age: 30,
};
// Person 인터페이스를 준수하지 않는 객체는 오류를 발생시킴
// const user2: Person = {
// name: "Bob",
// age: "30" // 'age'의 값이 문자열이기 때문에 오류 발생
// };interface Person {
name: string;
age?: number; // readonly도 가능
}
// Person 인터페이스를 준수하는 객체 생성
const user: Person = {
name: "Alice",
age: 30,
redefine: 1,
};
interface Person {
redefine: number;
}-.인터페이스의 재정의가 객체 위치에 영향을 미치지 않습니다. 예를 들어, 인터페이스를 재정의하기 전에 이미 정의된 객체가 있더라도 해당 객체는 변경되지 않습니다. 즉, 객체가 선언된 위치와 인터페이스가 재정의된 위치는 서로 독립적입니다.
ㅤ
-.여러 인터페이스를 | & 를 사용해 선택적으로 속성을 사용하게 하거나 모두 필요하도록 정의할 수 있다.
ㅤ
interface Person {
name: string;
age?: number;
gender: "male" | "female" | string;
}
// Person 인터페이스를 준수하는 객체 생성
const user = {
name: "Alice",
age: 30,
gender: "male",
};
const user2: Person = user;
// 오류 왜? 젠더가 현재 string로 자동추론된 상태이므로
// sol) '|string 를 추가한다.interface IUser {
name: string;
age: number;
}
interface IUserAddress extends IUser {
// 부모 속성 사용 가능
zipcode: string;
address: string;
}
const user: IUserAddress = {
name: "jack",
age: 25,
zipcode: " 12345",
address: "seoul",
};
// 2
interface IWorker {
company: string;
pos: number;
}
const user: IUserAddress = {
name: "jack",
age: 25,
zipcode: " 12345",
address: "seoul",
company: "han",
pos: 123,
};객체는 인터페이스로 다른 자료형은 타입으로 쓰는게 제일 대중적이긴 함
interface SignupUser {
name: string;
age: number;
gender: string;
address: string;
}
interface IUser {
name: SignupUser["name"]; // 이런 방법도 가능, 상속처럼
age: SignupUser["age"];
}
interface IUser2 extends Pick<SignupUser, "name" | "age"> {}
type TUser = Pick<SignupUser, "name" | "age">;
interface IUserO extends Omit<SignupUser, "gender" | "address"> {}
type TUserO = Omit<SignupUser, "gender" | "address">;Pick 메서드를 사용해 특정 인터페이스의 지정된 속성을 가져올 수 있다.
Omit 메서드를 이용하면 해당 속성을 제외한 나머지 속성을 가져올 수 있다.
// 덧셈 함수 선언식
function add(a: number, b: number): number {
return a + b;
}
type Tnn = (a: number, b: number) => number;
// 덧셈 함수 표현식
const addExp: Tnn = function (a, b) {
return a + b;
};
// 화살표 함수
const addArr: Tnn = (a, b) => a + b;함수 선언식은 타입을 생략할 수 없지만, 함수 표현식은 가능
❇️ 제네릭 함수
제네릭 함수를 사용하면 함수를 호출할 때마다 다른 유형의 매개변수를 사용할 수 있습니다.
function getSize1(values: number[] | string[] | (number | string)[]) {
return values.length;
}
function getSize<T>(values: T[]): number {
return values.length;
}
getSize<number>([1, 2, 3]);
getSize(["1", "2", "3"]); // 타입 자동추론
getSize([1, 2, 3, "1", "2", "3"]);function getSize<T>(values: T[] | T): number {
if ("string" == typeof values || Array.isArray(values)) {
return values.length;
}
return 0;
}
getSize<string>("Hello, world");// 화살표 함수
type getSize2<T> = (values: T[] | T) => number;
const arrFunc: getSize2<T> = (values) => {
return "string" === typeof values || Array.isArray(values)
? values.length
: 0;
};type Tuser<T> = {
name: string;
age: number;
likeFood: T;
};
interface IUser<T> {
name: string;
age: number;
likeFood: T;
}
const person1: Tuser<string[]> = {
name: "hoo",
age: 23,
likeFood: ["banana", "apple"],
};❇️기타 유틸리티
// Partial
type Person{
name : string;
age:number;
address : string;
}
const person1 : Partial<Person> = {
name : "kk",
age : 22,
address : "NY",
}interface User {
id?: number;
name?: string;
email?: string;
}
type RequiredUser = Required<User>;
function printUser(user: RequiredUser) {
console.log(`ID: ${user.id}`);
console.log(`Name: ${user.name}`);
console.log(`Email: ${user.email}`);
}
const user: RequiredUser = {
id: 1,
name: "Alice",
email: "alice@example.com",
};
printUser(user); // 모든 프로퍼티가 존재하므로 오류 없음
// 다음 객체는 오류를 발생시킵니다.
const incompleteUser: RequiredUs;// Pick
type TUser = Pick<Person, "name">;
// Omit
type TUsername = Omit<Person, "address">;
// Record
const person2: Record<string, string | number> = {
name: "ja",
age: 22,
address: "seoul",
};
type Scores = Record<string, number>; // 키가 문자열이고 값이 숫자인 객체 타입Pick 는 기존 타입에서 특정 속성만 선택해 새로운 타입을 생성한다.
Omit 는 기존 타입에서 특정 속성을 제외한 새로운 타입을 생성한다.
Record 는 특정 키 타입과 값 타입을 가지는 객체 타입을 생성한다. 주로 매핑 타입을 정의
// 실습 정답
interface ITodo {
id: number;
text: string;
completed: boolean;
}
// todos 배열 정의
const todos: ITodo[] = [];
const addTodo = (text: string) => {
const todo = {
id: todos.length + 1,
text,
completed: false,
};
todos.push(todo);
};
const removeTodo = (id: number) => {
const findIndex = todos.findIndex((todo) => todo.id === id);
todos.splice(findIndex, 1);
};
const toggleTodo = (id: number) => {
const find = todos.find((todo) => todo.id === id);
if (find) find.completed = !find.completed;
};REACT
NPM, NPX, YARN 🍍
❇️ NPM(Node Package Manager)
Node.js의 기본 패키지 관리자입니다. Node.js 패키지 생태계를 관리하고, JavaScript 라이브러리 및 모듈을 설치, 업데이트, 삭제하는 데 사용됩니다. 로컬 또는 전역(-g)으로 설치할 수 있습니다.
npm install <package-name> # 로컬 설치
npm install -g <package-name> # 전역 설치
npm run <script-name> # package.json 파일에 정의된 스크립트 실행
package.json 및 package-lock.json 파일을 통해 프로젝트의 의존성을 관리합니다.
❇️ NPX (Node Package Executor)
NPM 5.2.0 이후에 포함된 도구로, 패키지를 설치하지 않고도 일시적으로 실행할 수 있게 해줍니다. Node.js를 설치하면 자동으로 설치됩니다. 주로 전역 설치 없이 특정 패키지를 실행하고자 할 때 유용합니다.
npx <package-name> # 패키지를 일회성으로 실행
npx <package-name>@<version> # 특정 버전의 패키지 실행
❇️ Yarn
Yarn은 Facebook에서 개발한 JavaScript 패키지 관리자입니다. NPM과 유사한 기능을 제공하면서 성능과 보안, 신뢰성을 개선한 도구입니다.
yarn add <package-name> # 로컬 설치
yarn global add <package-name> # 전역 설치
yarn run <script-name> # package.json에 정의된 스크립트를 실행
Node.js 패키지 버전 🍍

순서대로 주요 릴리즈 / 새로운 기능 추가 / 버그 수정 / 옵셔널
리액트 프로젝트 생성하기 🍍
npm create vite@latest
npm create vite@latest my-vue-app -- --template react // react-tsJSX, TSX 등 🍍
JSX는 리액트 애플리케이션에서 UI를 작성할 때 사용되는 JavaScript와 XML을 결합한 문법이며, TSX는 TypeScript와 JSX를 결합하여 정적 타입 검사를 포함한 리액트 애플리케이션을 개발할 때 사용됩니다.
❇️ package.json
“scripts”
npm 스크립트 명령어들을 정의
“dependencies”
프로젝트가 의존하는 라이브러리들
“devDependencies”
개발 시에만 필요한 라이브러리들
리액트 장점
❇️ DOM과 가상돔
기존의 DOM은 하나를 수정하면 그와 연결된 모든 DOM을 업데이트해야 했다. 그래서 DOM 트리가 깊을수록 작업 비용이 커진다.
이를 대비하기 위해 가상돔 을 만든다. 가상돔은 기존의 DOM을 복사해 리액트 내부 메모리에 저장한다. 변경사항이 생기면 가상돔에서 변경 사항을 처리 후 실제 DOM과 비교해 변경된 부분만 업데이트한다. 기존 방법보다 작업 비용이 낮아진다.
변경 사항이 일어날 때마다 전체 DOM을 다시 그리는 대신, 이 가상 DOM에서 변경 사항을 먼저 처리하고, 그 후에 실제 DOM에 적용하는 방법을 쓴다.

디핑(diffing)은 가상 DOM과 실제 DOM 간의 변경 사항을 비교하고 식별하는 프로세스를 말합니다. 이 과정에서 가상 DOM에서 발생한 변경 사항을 찾아내고, 해당 변경 사항을 반영하여 실제 DOM을 업데이트배치 업데이트는 변경 사항을 실제 DOM에 적용하는 과정을 말합니다. 디핑을 통해 변경된 부분을 식별한 후, 이를 반영하여 DOM을 업데이트하는 과정을 의미
❇️ CSR VS SSR ⭐
CSR (Client-Side Rendering - 클라이언트 사이드 렌더링)
초기 페이지 요청 시 서버는 빈 HTML 파일을 반환하고, 클라이언트에서 JavaScript를 사용하여 동적으로 데이터를 가져와 렌더링
SSR (Server-Side Rendering - 서버 사이드 렌더링)
초기 페이지 요청 시 서버는 완전한 HTML 페이지를 생성하여 반환하므로, 클라이언트는 별도의 렌더링 작업이 필요하지 않습니다.
컴포넌트🍍
❇️ HMR
[vite] hmr update /src/App.tsx // 자동 업데이트, 페이지 새로고침 필요없HMR은 “Hot Module Replacement”의 약자로, 개발자가 애플리케이션을 개발하는 동안 코드 변경을 실시간으로 반영할 수 있는 기술입니다. 이는 코드를 수정할 때마다 전체 페이지를 새로고침할 필요 없이 변경된 모듈만 업데이트하여 빠르게 반영할 수 있도록 합니다.
❇️ JSX 규칙
JSX는 Javascript XML의 약자로 자바스크립트를 확장한 문법
-. 컴포넌트의 첫글자는 항상 대문자로 한다.
-. React Fragment는 <></> 구문으로도 사용할 수 있다.
-. 카멜케이스를 사용한다.
<button onClick={handleClick}>Click me</button>본 후기는 본 후기는 [유데미x스나이퍼팩토리] 프로젝트 캠프 : Next.js 1기 과정(B-log) 리뷰로 작성 되었습니다.


