juni
Next.js / React ( usePathname, event.origin, z.object, z.infer, aria-disabled, animate-spin, form.watch, _, FormField, trim, replace) 본문
Next.js / React ( usePathname, event.origin, z.object, z.infer, aria-disabled, animate-spin, form.watch, _, FormField, trim, replace)
juni_shin 2024. 11. 11. 19:33usePathname
Next.js의 내장 훅 중 하나로, 현재 페이지의 경로(pathname)를 가져오는 데 사용됩니다. Next.js 13부터 도입된 App Router 기능과 함께 사용할 수 있으며, 페이지의 경로를 쉽게 얻을 수 있게 도와줍니다.
주요 용도
- 현재 경로에 따른 동적 UI 렌더링: 예를 들어, 특정 페이지 경로에 따라 다른 콘텐츠를 표시하거나, 경로에 맞는 메뉴나 네비게이션을 강조하는 등의 작업을 할 수 있습니다.
- 라우팅 로직 구현: 현재 경로를 기반으로 페이지를 리다이렉트하거나, 조건에 따라 동작을 달리할 수 있습니다.
현재 페이지가 https://example.com/about/team이라면, usePathname()은
"/about/team"
event.origin
웹 브라우저에서 postMessage API로 메시지를 주고받을 때, **메시지를 보낸 출처(origin)**를 나타내는 속성입니다. event.origin을 사용하면 메시지를 보낸 창, 프레임 또는 도메인의 출처가 무엇인지 알 수 있습니다.
origin의 의미
origin은 웹 페이지의 프로토콜, 도메인, 포트 번호를 포함하는 URL의 일부분입니다. 예를 들어, 웹 페이지 URL이 https://example.com:443/some-page이라면, 이 페이지의 origin은 https://example.com입니다.
event.origin의 역할
- 보안 강화: postMessage를 통해 서로 다른 도메인 간에 메시지를 주고받을 때, 메시지를 수신하는 쪽에서는 event.origin을 확인하여 신뢰할 수 있는 출처에서 온 메시지만 처리할 수 있습니다.
- 크로스 도메인 통신: 서로 다른 도메인 간에도 안전하게 데이터를 주고받을 수 있도록 돕습니다.
// 메시지를 받는 쪽
window.addEventListener("message", (event) => {
// 메시지 출처 확인
if (event.origin !== "https://trusted.com") {
return; // 신뢰할 수 없는 출처라면 무시
}
// 안전한 출처에서 온 메시지라면 처리
console.log("메시지를 받았습니다:", event.data);
});
다른 도메인에서 메시지를 받을 때 event.origin을 확인하여, **https://trusted.com**에서 온 메시지만 처리하고, 그렇지 않은 출처에서 온 메시지는 무시합니다.
event.origin의 값
- event.origin은 메시지를 보낸 페이지의 프로토콜 + 호스트 + 포트로 구성됩니다.
- 예시: https://example.com 또는 http://localhost:3000
보안 고려 사항
- **postMessage**는 서로 다른 도메인 간에 메시지를 전송할 수 있기 때문에, 메시지를 수신할 때 반드시 event.origin을 확인하여 신뢰할 수 있는 출처에서 온 메시지인지 검증해야 합니다. 그렇지 않으면 클릭재킹(Clickjacking), XSS(교차 사이트 스크립팅) 같은 보안 문제가 발생할 수 있습니다.
요약
event.origin은 postMessage API를 사용하여 메시지를 주고받을 때, 메시지를 보낸 출처를 나타내는 속성입니다. 이 속성을 확인하여 신뢰할 수 있는 출처에서 온 메시지만 처리함으로써 보안을 강화할 수 있습니다.
const emailValidationFormSchema = z.object({
email: z.string().email({
message: "이메일을 확인해주세요.",
}),
});
type EmailValidationValues = z.infer<typeof emailValidationFormSchema>;
zod 라이브러리를 사용하여 이메일 입력 값을 검증하는 스키마를 정의하고, 그 스키마로부터 타입을 추론하는 예입니다.
const emailValidationFormSchema = z.object({ ... })
- z.object: zod에서 객체 스키마를 정의할 때 사용하는 함수입니다. 여기서는 이메일 필드를 포함한 객체를 정의합니다.
- email: z.string().email({...}):
- z.string()은 이 필드가 문자열이어야 한다는 것을 정의합니다.
- email() 메서드는 해당 문자열이 유효한 이메일 형식인지 검증합니다.
- { message: "이메일을 확인해주세요." }는 이메일 형식이 올바르지 않을 때 보여줄 오류 메시지입니다.
- 즉, 이 필드는 올바른 이메일 형식이어야 하며, 그렇지 않으면 오류 메시지가 표시됩니다.
type EmailValidationValues = z.infer<typeof emailValidationFormSchema>;
- z.infer: zod에서 제공하는 함수로, 정의된 스키마로부터 타입을 추론합니다.
- **typeof emailValidationFormSchema**는 emailValidationFormSchema의 타입을 가져옵니다.
- 결과적으로 EmailValidationValues는 emailValidationFormSchema에서 정의한 스키마에 맞는 타입을 자동으로 생성합니다.
- 여기서는 email 필드가 문자열로 정의되었기 때문에 EmailValidationValues 타입은 { email: string }이 됩니다.
코드 요약:
- 이 코드는 이메일 검증용 스키마를 zod로 정의하고, 그 스키마에 맞는 타입을 추론해서 TypeScript 타입으로 사용합니다.
- 만약 이 폼에 이메일을 입력할 때 이메일 형식이 잘못되면 "이메일을 확인해주세요."라는 메시지가 사용자에게 보여집니다.
const schema = emailValidationFormSchema; // 이메일 검증 스키마 사용
const { register, handleSubmit, formState: { errors } } = useForm<EmailValidationValues>({
resolver: zodResolver(schema),
});
const onSubmit = (data: EmailValidationValues) => {
console.log(data);
};
// JSX 안에서
<input {...register("email")} placeholder="Enter your email" />
{errors.email && <p>{errors.email.message}</p>}
위와 같은 방식으로 이 스키마와 타입을 폼에서 활용할 수 있습니다.
aria-disabled="true"
**웹 접근성(Accessibility, a11y)**을 위한 속성입니다. 이는 사용자가 보조 기술(예: 화면 읽기 프로그램, 스크린 리더)을 사용할 때, 해당 요소가 현재 비활성화되어 있음을 알리기 위해 사용됩니다.
역할:
aria-disabled="true"는 HTML 요소가 비활성화(disabled) 상태임을 의미하며, **인터랙션(클릭, 포커스 등)**이 불가능함을 시각적이거나 기술적인 방식으로 사용자에게 전달합니다. 주로 버튼이나 링크 등과 같이 사용자가 상호작용할 수 있는 요소에 적용됩니다.
차이점:
- disabled 속성: 실제로 요소의 동작을 비활성화합니다. 예를 들어, disabled가 설정된 버튼은 아예 클릭이 불가능해집니다.
- aria-disabled 속성: 시맨틱(의미론적)으로만 요소가 비활성화되었음을 나타내며, 물리적인 동작은 여전히 가능할 수 있습니다. 이 속성은 주로 접근성 목적으로, 사용자에게 요소가 비활성화되었음을 알리기 위한 것입니다.
<button aria-disabled="true">Submit</button>
화면 읽기 프로그램을 사용하는 사람들에게 이 버튼이 현재 비활성화 상태임을 알립니다. 하지만, disabled 속성이 없으므로 버튼 자체는 여전히 클릭이 가능할 수 있습니다.
언제 사용하나요?
- 접근성 향상: 요소가 시각적으로 비활성화된 것처럼 보이지만, 물리적으로는 여전히 클릭 가능한 경우(예: JavaScript에서 관리하는 동적 비활성화) 사용합니다.
- 보조 기술 지원: 스크린 리더 사용자들이 버튼이나 링크가 활성화되지 않았다는 정보를 받을 수 있도록 도와줍니다.
className="animate-spin"
Tailwind CSS에서 제공하는 유틸리티 클래스 중 하나입니다. 이 클래스는 요소에 회전 애니메이션을 적용하는 역할을 합니다. 주로 로딩 스피너처럼 계속 회전하는 애니메이션을 보여주고 싶을 때 사용됩니다.
기능:
- animate-spin: 이 클래스는 요소를 360도 회전시키는 애니메이션을 적용합니다. CSS의 @keyframes와 transform: rotate() 속성을 사용하여 요소가 일정 시간 동안 계속 회전하는 동작을 구현합니다.
- 지속적인 회전: 요소가 지속적으로 **회전(스핀)**하기 때문에, 사용자는 이 동작을 통해 작업이 진행 중임을 알 수 있습니다.
<div className="animate-spin w-8 h-8 border-4 border-blue-500 border-t-transparent rounded-full"></div>
원형 스피너를 구현한 예시입니다. animate-spin 클래스를 사용하여 이 요소는 계속해서 회전하는 애니메이션을 가지게 됩니다.
언제 사용하나요?
주로 로딩 상태를 표시할 때, 버튼이나 화면 일부에 로딩 스피너로 회전하는 애니메이션을 추가하고 싶을 때 사용됩니다.
form.watch("email")
React Hook Form에서 제공하는 메서드로, 현재 폼 필드(email)의 값을 실시간으로 관찰하고 반환합니다. 즉, 사용자가 입력한 값이 "email" 필드에 반영될 때마다 그 값을 추적할 수 있게 해줍니다.
watch()의 역할:
- form.watch("email")는 폼에서 "email" 필드의 현재 값을 가져옵니다.
- 사용자가 이메일 입력란에 무엇을 입력하고 있는지, 현재 입력된 값이 무엇인지를 실시간으로 확인할 수 있습니다.
<Button
size="lg_block"
loading={loading}
disabled={loading || !form.watch("email")}
>
다음
</Button>
- form.watch("email"):
- 이메일 입력 필드에 값이 입력되었는지 확인합니다.
- form.watch("email")가 빈 값일 경우(""), !form.watch("email")는 true가 되어 버튼이 비활성화됩니다.
- disabled={loading || !form.watch("email")}:
- 버튼은 loading 중이거나(비동기 작업 진행 중), 이메일 입력 필드가 비어 있을 경우에 비활성화됩니다.
- 즉, 사용자가 이메일을 입력하지 않았거나, 로딩 중일 때는 버튼을 클릭할 수 없도록 설정합니다.
요약:
- form.watch("email")는 이메일 입력 필드의 현재 값을 실시간으로 추적하는 역할을 합니다.
- 이를 통해 버튼을 동적으로 활성화하거나 비활성화하는 조건으로 활용됩니다.
_ (언더스코어)
프로그래밍에서 변수명이나 함수명에 특별한 의미를 부여하거나, 특정 관습에 따라 사용되는 기호입니다. 문맥에 따라 다양한 용도로 사용되는데, _data에서의 언더스코어는 일반적으로 특별한 의미를 부여하거나, 특정 목적으로 구분하기 위해 사용되었을 가능성이 큽니다. 이 문맥에서는 몇 가지 가능성을 설명할 수 있습니다.
언더스코어(_)의 일반적인 사용 예:
- 내부 데이터 또는 비공개 데이터:
- 언더스코어로 시작하는 변수명(예: _data)은 종종 내부적으로 사용되거나, 외부에서 직접 접근하지 않는 것을 권장하는 데이터를 나타냅니다.
- 이런 경우, 관습적으로 비공개(private) 변수를 나타내는 방식입니다. 비록 JavaScript는 실제로 접근 제한이 있는 변수를 지원하지 않지만, 언더스코어로 표시해 개발자에게 경고하는 용도로 사용됩니다.
class Example {
constructor() {
this._data = "This is private data";
}
}
- 이름 충돌 방지:
- 언더스코어는 변수명이나 함수명이 다른 이름과 충돌하는 것을 방지하기 위해 사용될 수 있습니다. 예를 들어, data라는 이름이 이미 사용 중이거나, 특정 의미를 가지고 있을 때 _data를 사용해 충돌을 피할 수 있습니다.
- 무시되는 값 또는 임시 변수:
- 언더스코어 자체가 종종 값을 무시하거나 임시로 사용되는 변수를 나타내는 경우도 있습니다. 예를 들어, 콜백 함수에서 특정 인자는 필요하지 않을 때 _로 이름을 붙여 무시할 수 있습니다.
array.map((_, index) => {
console.log(index);
});
_data의 의미:
- **_data**는 일반적으로 내부에서만 사용하는 데이터 또는 외부에서 직접 사용하지 않도록 권장되는 데이터를 나타낼 가능성이 큽니다.
- 코드 작성자의 의도는 이 변수를 구분하거나 특별한 의미를 부여하기 위해 언더스코어를 사용했을 수 있습니다.
FormField
React Hook Form과 UI 컴포넌트를 연동하여 폼 필드의 상태를 관리하고, 유효성 검사, 값을 입력받는 등의 역할을 하는 컴포넌트입니다. 이 컴포넌트는 React Hook Form의 Controller 컴포넌트를 감싸서 사용하며, 폼 필드에 대한 제어를 React Hook Form이 처리할 수 있도록 돕습니다.
역할 및 기능
- FormField의 역할:
- React Hook Form의 상태 관리: FormField는 Controller 컴포넌트를 통해 React Hook Form이 각 필드의 값을 제어하고, 폼 상태와 유효성 검사를 관리할 수 있도록 연결합니다.
- UI 컴포넌트와 폼 필드의 연결: render 함수로 제공된 UI 컴포넌트(Input, TextArea 등)를 Hook Form과 연결해, 해당 컴포넌트가 폼 상태와 값의 변화를 감지할 수 있도록 돕습니다.
- Controller의 역할:
- Controller는 React Hook Form에서 사용하는 컴포넌트로, 비제어 컴포넌트(입력 필드 등)를 제어 컴포넌트로 만들어줍니다. 즉, React Hook Form의 상태를 폼 필드와 연결해 **폼의 상태(값, 에러, 유효성 검사 등)**를 쉽게 관리할 수 있습니다.
- 폼 필드(input, select, textarea 등)와 Hook Form 사이에서 양방향 바인딩을 도와주는 역할을 합니다.
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>이메일</FormLabel>
<FormControl>
<Input
type="email"
placeholder="이메일을 입력해주세요"
{...field} // React Hook Form과 연결된 필드
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
- control: useForm에서 반환된 control 객체를 사용해 React Hook Form이 폼 필드의 상태를 관리할 수 있게 됩니다.
- name: 폼 필드의 이름을 email로 지정하여, 이 필드가 폼의 어떤 값을 다루고 있는지 알려줍니다.
- render 함수: 필드의 렌더링을 제어합니다. render 함수 안에서 React Hook Form이 제공하는 field 객체를 사용해 Input 컴포넌트와 연결합니다. field 객체는 폼 필드의 값, onChange, onBlur 등의 이벤트 핸들러를 포함하고 있어, 폼 필드가 React Hook Form의 상태와 동기화되도록 합니다.
정리:
- **FormField**는 React Hook Form과 UI 컴포넌트를 연결하는 역할을 합니다. Controller를 통해 React Hook Form이 폼 필드의 상태를 제어하고, 유효성 검사와 값을 추적할 수 있게 해줍니다.
- render 함수는 폼 필드를 어떻게 렌더링할지 정의하고, field 객체를 통해 입력 필드와 React Hook Form을 연결합니다.
1. trim() 메서드
- **trim()**은 문자열의 양 끝에 있는 공백(스페이스)을 제거하는 함수입니다.
" John Doe ".trim(); // 결과: "John Doe"
2. replace(/\s\s+/g, " ") 부분
- **replace()**는 문자열에서 특정 패턴을 찾아서 다른 값으로 대체하는 메서드입니다.
- 여기서 사용된 정규식 /\s\s+/g는 2개 이상의 연속된 공백(스페이스)을 찾는 패턴입니다.
- \s: 공백 문자(스페이스, 탭, 줄바꿈 등)를 의미합니다.
- \s\s+: 2개 이상의 연속된 공백 문자를 의미합니다.
- g 플래그: 문자열 전체에서 패턴을 찾겠다는 의미 (전역 검색).
- " ": 발견된 연속된 공백을 하나의 공백 " "으로 대체합니다.
즉, 2개 이상의 공백을 하나의 공백으로 변환하는 역할을 합니다.
3. 전체 흐름
- userInfo.name.trim().replace(/\s\s+/g, " ")는 다음과 같이 동작합니다:
- trim()으로 이름 양쪽 끝에 있는 공백을 제거합니다.
- replace(/\s\s+/g, " ")로 이름 내부에 있는 2개 이상의 공백을 하나의 공백으로 바꿉니다.
예를 들어, userInfo.name 값이 " John Doe "이라면:
- trim()으로 양쪽 끝의 공백이 사라져서 "John Doe"가 됩니다.
- replace(/\s\s+/g, " ")로 이름 내부의 연속된 공백이 하나의 공백으로 바뀌어 "John Doe"가 됩니다.
'CS' 카테고리의 다른 글
프론트엔드 CS 정리 1~5 (0) | 2025.01.14 |
---|---|
Next.js / React ( translate, translate3d, duration, cva, quill에디터 폰트 흐려짐[미해결] ) (0) | 2024.11.11 |
Next.js / React ( 타입, json 응답 구조, 토큰, OAuth, postAPI, FormData, JSON 객체, expires ) (0) | 2024.11.11 |
Next.js / React 라이브러리 ( Toastify, ToastPrimitives, Lucide-React, next-themes, DialogPrimitive, zod, useForm, cookies-next ) (0) | 2024.11.11 |
Jest / Vitest (1) | 2024.10.11 |