diff --git "a/week-07/\352\271\200\354\244\200\354\227\264.md" "b/week-07/\352\271\200\354\244\200\354\227\264.md"
new file mode 100644
index 0000000..302682c
--- /dev/null
+++ "b/week-07/\352\271\200\354\244\200\354\227\264.md"
@@ -0,0 +1,402 @@
+# 프론트엔드 개발에 유용한 도구 및 라이브러리
+
+코드의 품질을 향상시키고 안정적인 애플리케이션을 개발하는데 도움이 되는 도구들을 다음과 같이 정리하였다.
+
+## ESLint
+
+- What: 코드의 품질을 검사하고, 문제가 있는 부분을 찾아내는 도구.
+- Why: 일관된 코드 스타일을 유지하고, 정적 분석을 통해 오류를 미리 발견하여 코드의 품질을 향상시킬 수 있다.
+- How: 프로젝트에 ESLint를 설정하고 필요한 규칙을 추가하여 코드를 검사하고 수정할 수 있다.
+
+## Jest
+
+- What: JavaScript 및 TypeScript 코드를 테스트하는 도구.
+- Why: 코드의 동작을 자동으로 확인할 수 있으며, 이를 통해 개바자는 코드 변경으로 인한 오류를 미리 발견할 수 있다.
+- How: Jest를 사용하여 `test` 파일을 작성하고 `npm test` 명령을 사용하여 테스트를 실행한다.
+
+## Zod
+
+- What: 데이터 유효성 검사와 스키마 정의를 위한 라이브러리로, 데이터의 유효성을 검사하고 정의하는 데 사용된다.
+- Why: 데이터의 유효성을 쉽게 검사하고, 안전하게 다룰 수 있다. 이를 통해 개발자는 더욱 안정적이고 신뢰할 수 있는 애플리케이션을 개발할 수 있다.
+- How: Zod를 사용하여 데이터 스키마를 정의하고, 데이터를 검증하거나 변환하는 메서드를 사용하여 데이터를 다룬다.
+
+# 예시 코드
+
+## ESLint
+
+- 코드 스타일 검사: 일관된 코드 스타일을 유지하기 위해 사용된다.
+- 문법 오류 확인: Javascript 및 TypeScript 코드의 문법 오류를 검사한다.
+- 코드 품질 향상: 잠재적인 오류를 미리 방지하여 코드의 품질을 향상시킨다.
+
+```jsx
+// .eslintrc.js
+
+module.exports = {
+ extends: ["eslint:recommended", "plugin:react/recommended"],
+ parserOptions: {
+ ecmaVersion: 12,
+ sourceType: "module",
+ ecmaFeatures: {
+ jsx: true,
+ },
+ },
+ rules: {
+ // 여기에 필요한 규칙을 추가한다.
+ "no-console": "warn",
+ "no-unused-vars": "warn",
+ },
+};
+```
+
+## Jest
+
+### 유닛 테스트
+
+각각의 함수나 컴퓨넌트가 독립적으로 분리된 환경에서 의도된 대로 정확히 작동하는지 검증하는 테스트
+
+```tsx
+const sum = (a: number, b: number): number => {
+ return a + b;
+};
+
+export default sum;
+```
+
+```tsx
+import sum from "./unitTest";
+
+test("adds 1 + 2 to equal 3", () => {
+ expect(sum(1, 2)).toBe(3);
+});
+```
+
+### 통합 테스트
+
+유닛 테스트를 통과한 여러 컴포넌트가 묶여서 하나의 기능으로 정상적으로 작동하는지 확인하는 테스트
+
+```tsx
+interface ButtonProps {
+ onClick: () => void;
+ label: string;
+}
+
+const Button = (props: ButtonProps) => {
+ return ;
+};
+
+export default Button;
+```
+
+```tsx
+// 컴포넌트를 import 하고 사용하게 될 때부터는 jsx 파일 확장자로 작성해야한다.
+
+import { fireEvent, render } from "@testing-library/react";
+import Button from "./integrationTest";
+
+test("renders button with correct label", () => {
+ const handleClick = jest.fn();
+ const { getByText } = render(
+
+ );
+ const buttonElement = getByText(/Click me/i);
+ expect(buttonElement).toBeInTheDocument();
+});
+
+test("calls onClick prop when button is clicked", () => {
+ const handleClick = jest.fn();
+ const { getByText } = render(
+
+ );
+ const buttonElement = getByText(/Click me/i);
+ fireEvent.click(buttonElement);
+ expect(handleClick).toHaveBeenCalledTimes(1);
+});
+```
+
+### 엔드 투 엔드(End to End Test)
+
+E2E 테스트라 하며, 실제 사용자처럼 작동하는 로봇을 활용해 애플리케이션의 전체적인 기능을 확인하는 테스트
+
+- Cypress 라이브러리를 활용한 E2E test GUI
+
+ [Cypress GUI 보기](https://file.notion.so/f/f/a43c8b7f-e77d-47de-a59c-f74de1fb0eee/9ef47294-5d88-4601-87ef-e7a0fe554dc4/Untitled.png?id=0406d564-ff48-4aac-93af-2779b2228bb2&table=block&spaceId=a43c8b7f-e77d-47de-a59c-f74de1fb0eee&expirationTimestamp=1712016000000&signature=yPRBLTA2U3-BqVrqfDeo2FkRLd1pWfgLuCy2fxaiC3Y&downloadName=Untitled.png)
+
+- Cypress를 사용하여 웹 페이지의 DOM 요소와 상호작용하는 다양한 액션을 수행하는 테스트
+
+ - `cy.visit`으로 테스트를 실행할 브라우저를 열고 페이지를 로드하며, 해당 페이지에 있는 요소들에 접근하여 테스트를 수행
+ - `.type()`: 실제로 웹 페이지에서 사용자가 키보드로 텍스트를 입력하는 것과 유사한 동작을 시뮬레이트
+ - 입력 지연 설정: `{ delay: 100 }` 옵션을 사용하여 입력 간격을 지연시킴으로써 실제 사용자의 타이핑과 유사한 경험 제공
+ - 에러 무시: `{ force: true }` 옵션을 사용하여 입력 필드가 비활성화되어 있거나 화면에 보이지 않더라도 액션을 수행
+
+ ```jsx
+ // Cypress에서는 테스트를 그룹화하는 context 함수를 제공
+ context('Actions', () => {
+ // beforeEach(() => { ... }): 각 테스트가 실행되기 전에 실행될 함수를 정
+ beforeEach(() => {
+ cy.visit('http://localhost:8080/commands/actions')
+ })
+
+ // https://on.cypress.io/interacting-with-elements
+
+ it('.type() - type into a DOM element', () => {
+ // https://on.cypress.io/type
+ cy.get('.action-email').type('fake@email.com')
+ cy.get('.action-email').should('have.value', 'fake@email.com')
+
+ // .type() with special character sequences
+ cy.get('.action-email').type('{leftarrow}{rightarrow}{uparrow}{downarrow}')
+ cy.get('.action-email').type('{del}{selectall}{backspace}')
+
+ // .type() with key modifiers
+ cy.get('.action-email').type('{alt}{option}') //these are equivalent
+ cy.get('.action-email').type('{ctrl}{control}') //these are equivalent
+ cy.get('.action-email').type('{meta}{command}{cmd}') //these are equivalent
+ cy.get('.action-email').type('{shift}')
+
+ // Delay each keypress by 0.1 sec
+ cy.get('.action-email').type('slow.typing@email.com', { delay: 100 })
+ cy.get('.action-email').should('have.value', 'slow.typing@email.com')
+
+ cy.get('.action-disabled')
+ // Ignore error checking prior to type
+ // like whether the input is visible or disabled
+ .type('disabled error checking', { force: true })
+ cy.get('.action-disabled').should('have.value', 'disabled error checking')
+ })
+
+ ```
+
+ [예시 코드 출처: cypress github](https://github.com/cypress-io/cypress-example-kitchensink/blob/master/cypress/e2e/2-advanced-examples/actions.cy.js)
+
+## Zod
+
+### **Zod를 사용하지 않은 경우**
+
+- **복잡성**: Zod를 사용하지 않으면 수동으로 데이터 유효성을 검사해야 하므로 코드가 복잡해진다.
+- **가독성**: 여러 조건문을 작성해야 하므로 가독성이 떨어질 수 있다.
+- **유지보수성**: 수동으로 검사할 때는 여러 곳에서 검사 로직이 중복되어 유지보수성이 감소할 수 있다.
+
+```jsx
+// 데이터 유효성 검사를 수행하는 함수
+function validateUserData(userData) {
+ if (
+ typeof userData.username !== "string" ||
+ userData.username.length < 3 ||
+ userData.username.length > 20 ||
+ typeof userData.email !== "string" ||
+ !userData.email.includes("@") ||
+ typeof userData.age !== "number" ||
+ userData.age <= 0 ||
+ !Number.isInteger(userData.age)
+ ) {
+ throw new Error("Invalid user data");
+ }
+}
+
+// 사용자 정보를 입력받는 함수
+function createUser(userData) {
+ try {
+ // 데이터 유효성 검사 수행
+ validateUserData(userData);
+
+ // 데이터베이스에 저장
+ saveUserToDatabase(userData);
+
+ console.log("User created successfully:", userData);
+ return userData;
+ } catch (error) {
+ // 유효성 검사 실패 시 예외 처리
+ console.error("Failed to create user:", error.message);
+ throw new Error("Failed to create user: Invalid data");
+ }
+}
+
+// 사용자 정보
+const userData1 = {
+ username: "john_doe",
+ email: "john@example.com",
+ age: 30,
+};
+
+const userData2 = {
+ username: "j",
+ email: "notAnEmail",
+ age: -10,
+};
+
+createUser(userData1); // 유효한 데이터
+createUser(userData2); // 유효하지 않은 데이터
+```
+
+### **Zod를 사용한 경우**
+
+- **복잡성**: Zod를 사용하면 간단한 **메서드 체인을 사용하여 데이터 유효성 검사**를 정의할 수 있다.
+ 또한, Zod로 정의한 데이터 스키마를 추론하여 **타입스크립트 인터페이스도 정의**할 수 있다.
+- **가독성**: **정의한 데이터 스키마**로 parse 메서드를 통해 **유효성 검사**를 하기 때문에, 가독성이 높다.
+- **유지보수성**: 유효성 검사 규칙을 한 곳에서 관리할 수 있으므로 유지보수가 쉽다.
+
+```jsx
+import { z } from "zod";
+
+// 사용자 데이터 스키마 정의
+const userSchema = z.object({
+ username: z.string().min(3).max(20),
+ email: z.string().email(),
+ age: z.number().int().positive(),
+});
+
+// ** Zod 스키마를 활용하여 타입도 함께 정의할 수 있다. **
+type UserType = z.infer;
+
+// 사용자 정보를 입력받는 함수
+export function createUser(userData: UserType) {
+ try {
+ const validatedUserData = userSchema.parse(userData);
+
+ // 유효한 데이터인 경우 데이터베이스에 저장
+ // saveUserToDatabase(validatedUserData);
+
+ console.log("User created successfully:", validatedUserData);
+ return validatedUserData;
+ } catch (error) {
+ return error;
+ }
+}
+
+const userData1 = {
+ username: "john_doe",
+ email: "john@example.com",
+ age: 30,
+};
+
+const userData2 = {
+ username: "j",
+ email: "notAnEmail",
+ age: -10,
+};
+
+createUser(userData1); // 유효한 데이터
+createUser(userData2); // 유효하지 않은 데이터
+```
+
+**zod를 적용한 코드의 test**
+
+```tsx
+import { createUser } from "./zodecode";
+
+describe("createUser function", () => {
+ // 유효한 사용자 데이터
+ const validUserData = {
+ username: "john_doe",
+ email: "john@example.com",
+ age: 30,
+ };
+
+ // 유효하지 않은 사용자 데이터
+ const invalidUserData = {
+ username: "j",
+ email: "notAnEmail",
+ age: -10,
+ };
+
+ it("creates a user with valid data", () => {
+ const createdUser = createUser(validUserData);
+
+ expect(createdUser).toEqual(validUserData);
+ });
+
+ // 유효하지 않은 데이터를 입력했을 때
+ it("throws an error with invalid data", () => {
+ try {
+ expect(() => {
+ createUser(invalidUserData);
+ });
+ } catch (error) {
+ expect(error).toBeInstanceOf(Error);
+ }
+ });
+});
+```
+
+
+
+# FID의 대체 지표: INP(Interaction to Next Paint)
+
+
+
+원문: https://web.dev/blog/inp-cwv-launch
+
+기존Core Web Vitals에서 상호 작용 응답성을 측정하는 방식인 First Input Delay(FID)의 단점을 개선하여, Interaction to Next Paint(INP)가 앞으로 대체되게 된다.
+
+# INP(Interfaction to Next Paint): 다음 페인트와의 상호작용
+
+INP는 Event Timing API의 데이터를 사용하여 페이지 응답성을 평가하는 Core Web Vitals 측정 항목이다.
+
+INP는 페이지 수명 동안, 페이지와의 모든 클릭, 탭, 키보드 상호작용의 지연 시간을 관찰하고 이상점을 무시하고 가장 긴 기간을 보고한다.
+
+그래서 INP가 낮으면 페이지가 대다수의 사용자 상호작용에 일관되게 빠르게 반응할 수 있다는 것을 의미한다.
+
+## INP의 목적
+
+INP의 목표는 사용자가 시작하는 모든 상호작용 또는 대부분의 상호작용에서 사**용자가 상호작용을 시작한 시점부터 다음 프레임이 그려질 때까지의 시간을 최소화**하는 것입니다.
+
+INP는 상호작용의 모든 최종 효과(예: 다른 비동기 작업의 네트워크 가져오기 및 UI 업데이트)가 아니라 **다음 페인트가 차단되는 시간을 측정하는 것**이다.
+
+## 좋은 INP 점수
+
+
+
+- INP가 **200밀리초** 이하: 페이지의 **응답성이 양호하다.**
+- INP가 **200밀리초**에서 **500밀리초** 사이: 페이지의 응답성을 **개선해야 한다**.
+- INP가 **500밀리초**보다 클 경우: 페이지의 **응답성이 좋지 않다.**
+
+## 상호작용
+
+
+
+상호작용의 수명이다. 입력 지연은 이벤트 핸들러가 실행될 때까지 지속되며, 기본 스레드의 장기 작업과 같은 요인으로 인해 발생할 수 있다. 그런 다음 상호작용의 이벤트 핸들러가 실행되고 다음 프레임이 표시되기 전에 또 다른지연(페이지가 새로운 정보나 상태를 갱신하고, 화면에 변경 사항을 반영하기 위한 시간)이 발생할 수 있다.
+
+INP의 경우에는 다음 상호작용 유형만 관찰된다.
+
+- 마우스로 클릭한다.
+- 터치스크린이 있는 기기를 탭한다.
+- 물리적 키보드 또는 터치 키보드의 키 누르기
+
+INP는 사용자가 페이지를 떠날 때 계산되며, 그 결과로 전체 수명 주기 동안 페이지의 전반적인 응답성을 나타내는 단일 값이 생성된다.
+
+## INP와 FID(First Input Delay)과의 차이점
+
+INP는 최초 입력 반응 시간(FID)의 후속 측정항목이다.
+
+둘 다 **반응성 측정항목**이라는 공통점이 있지만,
+
+FID는 페이지에서 **첫 번째 상호작용의 입력 지연**만 측정하는 반면,
+
+INP는 **입력 지연부터 이벤트 핸들러를 실행하는 데 걸리는 시간, 마지막으로 브라우저가 다음 프레임을 그릴 때까지의 모든 페이지 상호작용**을 고려하여 FID를 개선한다.
+
+FID: 사용자에 대한 페이지의 첫 번째 노출을 평가하기 위해 설계된 로드 반응성 측정항목
+
+INP: 페이지 상호작용이 발생하는 시점과 관계없이 전반적인 응답성을 더 신뢰할 수 있는 지표
+
+## INP 값이 보고되지 않는 경우
+
+- 페이지가 로드 되었으나, 사용자가 상호작용한 적 없을 때
+- 페이지가 로드 되었으나, 사용자가 측정되지 않는 동작(예: 스크롤 또는 요소 위로 마우스 오버)를 사용하여 페이지와 상호작용만 했을 때
+- 페이지와 상호작용하도록 스크립트를 작성하지 않은 봇(예: 검색 크롤러 또는 헤드리스 브라우저)이 페이지에 액세스하는 경우
+
+## Web Vitals 확장 프로그램으로 INP를 포함한 지표 측정
+
+[웹 바이탈 Chrome 확장 프로그램](https://chrome.google.com/webstore/detail/web-vitals/ahfhijdlegdabablpippeagghigmibma?hl=ko)은 상호작용 지연 시간을 수동으로 테스트할 때 용이하다.
+
+Web Vitals 확장 프로그램이 설치 및 수행 과정
+
+1. Chrome에서 주소 표시줄 오른쪽에 있는 확장 프로그램 아이콘을 클릭한다.
+2. 오른쪽에 있는 아이콘을 클릭하여 확장 프로그램의 설정을 연다.
+3. **옵션**을 클릭한다.
+4. 결과 화면에서 **콘솔 로깅** 체크박스를 사용 설정한 후 **저장**을 클릭한다.
+
+ 
+
+5. 콘솔에서 각 지표들의 값을 확인할 수 있다.
+
+ 