Messenger앱에서 처음에는 로그인 페이지를 만드는 것을 진행했다.
프로젝트 시작
일단 처음에는 아래의 명령어를 사용해서 프로젝트를 시작했다. 리액트의 create-react-app과 다를 건 없다.
npm create-next-app --typescript
typescript를 사용할 것이기에 --typescript를 붙여서 명령어를 작성했다.
생성된 프로젝트의 파일구조를 확인해보면 app파일에는 page.tsx와 layout.tsx파일이 존재한다.
page.tsx
page.tsx는 각 페이지의 메인 콘텐츠를 정의하는 파일이다. next.js에서 page.tsx파일은 URL경로와 직접 연결이 되는데 예를 들어, app/about/page.tsx파일이 있다면 /about경로에 대응하는 페이지가 생성된다. 이 파일에는 해당 페이지에서만 필요한 컴포넌트와 콘텐츠가 들어가고, React컴포넌트로 작성된다. 또한 이곳에 API데이터를 가져오거나 페이지 렌더링과 관련된 로직을 추가할 수 도있다.
layout.tsx
layout.tsx는 페이지의 공통 레이아웃을 정의하는 파일이다. 여기에는 모든 페이지에서 공통으로 사용되는 UI요소를 포함할 수 있다. layout.tsx파일은 특정 폴더에 위치한 모든 페이지에 적용되는 레이아웃 역할을 하며, page.tsx에서 정의된 개별 컨텐츠가 layout.tsx의 children을 통해서 삽입된다. 예를 들어 app/about/layout.tsx파일이 있다면 about폴더의 모든 페이지에 이 레이아웃이 적용된다.
이 프로젝트에서는 app/(site)/page.tsx 형태로 진행이 되었다. 여기서 page.tsx는 index의 역할을 하게된다.
AuthForm.tsx
이 파일은 app/(site)/components/AuthForm.tsx에 위치한다.
클라이언트 컴포넌트
이 페이지의 상단에 "use client"라는 녀석이 있는데 클라이언트 컴포넌트라는 친구이다.
이 친구는 서버에서 렌더링하는 대신브라우저에서 실행되는 컴포넌트로 , React의 상태와 훅을 사용할 수 있다. 브라우저의 동적인 상호작용을 필요로 할 때 사용된다.
리터럴 타입
type Variant = "LOGIN" | "REGISTER";
이건 typescript에서 타입을 별도로 지정하는 문법이다. 여기서는 variant타입이 지정되면 LOGIN값 또는 REGISTER 중 하나의 값만 가질 수 있게 된다. 이러한 경우에는 코드의 가독성이 좋아지고 잘못된 값을 갖지 않도록 타입검사를 해주는 역할도 한다.
상태관리
variant: 현재 컴포넌트가 로그인 상태인지 회원가입 상태인지를 관리합니다.
isLoading: 요청 중인 상태를 나타내며, 로딩이 완료될 때까지 일부 UI요소를 비활성화합니다.
toggleVariant()
useCallback을 사용하여 variant상태를 토글하는 함수이다. useCallback을 사용해서 variant상태를 토글한다.
- 로그인 중이면 회원가입 상태를 변경하고, 회원가입 상태라면 로그인 상태로 변경한다.
- variant를 의존성으로 지정해서 variant가 변경될 때만 새로 생성되도록 한다.
const toggleVariant = useCallback(() => {
if (variant === "LOGIN") {
setVariant("REGISTER");
} else {
setVariant("LOGIN");
}
}, [variant]);
FieldValues
- FieldValues는 폼의 입력 데이터 형태를 정의하는 TypeScript 타입입니다.
- 각 폼 필드가 어떤 데이터를 포함할 수 있는지 유연하게 지정할 수 있도록 합니다. FieldValues를 기본 타입으로 사용하여 폼 입력 필드의 다양한 값을 저장할 수 있습니다
- 예시 { name: string, email: string, password: string } 등의 형태로 입력 데이터가 저장될 수 있습니다.
SubmitHandler
- 폼이 제출되었을 때 호출되는 함수의 타입을 정의하는 타입이다.
- 폼 제출 이벤트에 맞는 데이터 타입을 보장하기 위해 사용된다. 폼의 데이터 타입이 FieldValues일 때 submitHandler로 이 타입을 설정해주면, 폼 제출 시 해당 데이터가 onSubmit함수의 매개변수로 전달된다.
useForm
- useForm은 react-hook-form라이브러리 훅으로, 폼 데이터를 다루고 유효성 검사를 돕는다.
- register는 입력필드를 useForm에 등록하며, handleSubmit는 폼제출을 처리한다.
- formState.error는 입력값 유효성 검사 오류를 담고 있다.
- defaultValues를 통해 폼 초기 값을 지정한다.
const { register, handleSubmit, formState: { errors } } = useForm<FieldValues>({
defaultValues: { name: "", email: "", password: "" },
});
onSubmit함수
handlesubmit로 호출되는 폼 제출함수이다.
- variant가 register면 회원가입 login이면 로그인 처리한다.
const onSubmit: SubmitHandler<FieldValues> = (data) => {
setIsLoading(true);
if (variant === "REGISTER") {
// 회원가입 로직 추가
}
if (variant === "LOGIN") {
// 로그인 로직 추가
}
};
SubmitHandler에 대해서 공부해보자.. 이게 뭘까
JSX렌더링 부분
여긴 뭐 전부다 설명할 필요는 없을 거 같다.
중요하거나 새로운 부분들만 정리.
사용된 tailwind CSS
#전체 레이아웃 컨테이너
mt-8: 상단 여백 (margin-top) 적용.
sm:mx-auto: 작은 화면 이상에서 수평 중앙 정렬.
sm:w-full: 작은 화면 이상에서 너비 100%.
sm:max-w-md: 작은 화면 이상에서 최대 너비 md (768px)
#내부 카드 레이아웃
bg-white: 배경색을 흰색으로 설정.
px-4: 좌우 패딩 1rem.
py-8: 상하 패딩 2rem.
shadow: 기본 그림자 효과.
sm:rounded-lg: 작은 화면 이상에서 큰 모서리 반경.
sm:px-10: 작은 화면 이상에서 좌우 패딩을 2.5rem로 설정.
#폼 레이아웃
space-y-6: 각 자식 요소 사이에 수직 여백 1.5rem 적용
#입력 필드 상단 구분선
relative: 상대 위치 설정.
flex: Flexbox로 레이아웃 설정.
justify-center: 가운데 정렬.
text-sm: 텍스트 크기를 작게 설정.
#구분선
w-full: 너비 100%.
border-t: 상단 테두리만 적용.
border-gray-300: 회색 톤의 테두리 색상 적용.
#버튼 스타일
mt-6: 상단 여백 1.5rem 적용.
flex: Flexbox 레이아웃 설정.
gap-2: Flexbox 자식 요소 간 0.5rem 간격 설정.
#로그인/회원가입 전환링크
flex: Flexbox로 레이아웃 설정.
gap-2: 요소 간 간격을 0.5rem 적용.
justify-center: 자식 요소를 가운데 정렬.
text-sm: 텍스트 크기를 작게 설정.
mt-6: 상단 여백 1.5rem 적용.
px-2: 좌우 패딩 0.5rem 적용.
text-gray-500: 회색 톤의 텍스트 색상.
#전환링크 스타일
underline: 텍스트 밑줄 추가.
cursor-pointer: 마우스 커서를 포인터 모양으로 설정.