Skip to content

Comments

Refactor/#249: 회원가입 페이지 리팩토링#144

Merged
SwimmingRiver merged 33 commits intodevelopfrom
refactor/#249-page-signup
Jun 20, 2025
Merged

Refactor/#249: 회원가입 페이지 리팩토링#144
SwimmingRiver merged 33 commits intodevelopfrom
refactor/#249-page-signup

Conversation

@SwimmingRiver
Copy link
Collaborator

변경 사항

  • 서버사이드 렌더링으로 변경하여 로그인한 유저가 접근하지 못하게 변경했습니다.
  • 유효성 검사 함수로 분리했습니다.
  • 로그인 페이지에서도 사용할 수 있도록 입력 폼 필드 분리하였습니다.

구현결과(사진첨부 선택)

(내용)

@netlify
Copy link

netlify bot commented Jun 16, 2025

Deploy Preview for we-write ready!

Name Link
🔨 Latest commit a116110
🔍 Latest deploy log https://app.netlify.com/projects/we-write/deploys/6853c3a5b429e4000822c158
😎 Deploy Preview https://deploy-preview-144--we-write.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사소한 네이밍이긴한데
이미 컴포넌트라는것을 알고 있는데 Component라는 네이밍을 굳이 한번더 명시하지 않아도 될거 같아요!
그 대신 조금 더 이 컴포넌트가 무슨 역할을 하는지 명확한 네이밍되 면 좋을 거 같습니다!
LinkToSignIn 이런식으로?!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

처음에 footer 같은 이름을 쓰려다가 링크라는 역할이 모호한거 같아서 컴포넌트라고 했는데
좀 더 명확하게 할 수 있겠네요!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기 내부에 useForm이 들어가도 괜찮겠네요!

import Button from '@/components/common/Button/Button';

import { useForm } from 'react-hook-form';
import { singUpValidate } from '@/utils/validators/auth';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오타발견!!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 컴포넌트를 구현한 이유가 궁금합니다!!
왜냐하면 이미 추상화가 되어서 사용하는 컴포넌트를 한번더 추상화한 느낌이라서 말씀드리는겁니다!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validate를 분리하면서 validate에 맞춘 공용 컴포넌트가 필요할 거 같다는 생각으로 개발했습니다.

}
};

export const emailValidation = (email: string): string | true => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

유효성 검사를 통과하면 true를 반환하는 구조군요! 큰 차이는 없겠지만, 함수들의 반환 값이 전부 동일해서
타입 별칭을 사용하는 방법도 있을 것 같네요!
지금의 인라인 방식이 더 직관적이긴 해서 편하신데로 해주셔도 상관없을 것 같습니다

Comment on lines +48 to +49
<div className="flex flex-col gap-2">
<div className="flex flex-col gap-2">
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flex 컨테이너 내부에 요소가 하나뿐이라서 해당 스타일이 실제로 적용되고 있을까요?

@@ -0,0 +1,70 @@
import { SignUpValidateProps } from './type';

export const singUpValidate = ({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오타인 것 같네요~! singUp

label="닉네임"
placeholder="닉네임을 입력해주세요"
register={register}
validate={singUpValidate}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분의 동작 방식을 잘 이해하지 못했는데 설명해주실 수 있을까요?

  • 외부 함수를 통채로 넘기는 이유?(호출한 반환 값을 넘기는 것과의 차이)
  • FormField내부에서 validate: (value) => validate({ value, name }) 가 동작하는 방식 (좌측의 validate는 register의 프로퍼티이고, 우측의 validate는 props? value를 넘기는 방식?)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

내부에서 함수가 필요할때만 동작하는 것을 생각하고 함수를 넘기는 방식으로 개발했습니다.

말씀하신대로 validate로 커스텀한 검증 함수를 넘겨줍니다.
props로 넘겨준 register의 안에서 validate에서 커스텀 검증함수를 이름과 값을 받아 유효성 검사를 하는 구조입니다.

Comment on lines 68 to 71
register={register}
validate={singUpValidate}
password={getValues('password') ?? ''}
errors={errors}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

지금의 구조도 문제는 없지만 확장성과 가독성 측면에서 useFormContext를 사용하는 방법도 있을 것 같네요!

}}
suffixIcon={
<button
aria-label="암호 표시 버튼"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

스크린 리더 사용자가 의미를 파악할 수 있는 label 문구로 변경해보면 좋을 것 같아요!
예를 들면 aria-label={isShowPassword ? '비밀번호 숨기기' : '비밀번호 보이기'} 같이 현재 버튼의 역할을 명확하게
전달하는 방법이 있을 것 같습니다.
현재의 suffixIcon에 적용하는 것이 의미가 적절할 지 고민이 필요할 것 같은데,
버튼의 눌림 상태(활성화 여부, 선택 여부)를 사용자에게 전달하는 aria-pressed라는 속성도 존재하니
한번 찾아보셔도 좋을 것 같습니다!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aria-pressed 라는게 있었군요
접근성은 공부할 게 많네요
감사합니다

<button
aria-label="암호 표시 버튼"
type="button"
className="flex items-center justify-center"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flex-center 커스텀 클래스를 사용하는 방법도 있을 것 같네요!

import { APP_ROUTES } from '@/constants/appRoutes';
import Link from 'next/link';

const LinkComponent = () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이건 개발자 개인의 취향일텐데
저는 개인적으로는 컴포넌트명에 Component 네이밍을 사용하지 않는 것이 좋은 것 같아요

LinkComponent를 기준으로 보면 앞에 있는 'Link'란 단어만으로 이게 어떤 역할을 하는 컴포넌트일 지 유추해야 되서
의미가 명시적이지 않은 느낌이 있는 것 같습니다

return true;
};

export const favoriteValidation = (favorite: string): string | true => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

emailValidation, favoriteValidation 등의 함수들이 각각 import되서 사용하는 경우를 고려해서 export 해주신걸까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

최초에는 별도로 호출하려고 했는데 변경이후에 수정을 안했네요 수정하겠습니다!

import { useRouter } from 'next/navigation';
const SignUp = async () => {
const { isSignIn } = await getMyInfoOnServer();
const referer = (await headers()).get('referer');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호 refereruseParamsawait params 등으로 가져오지 않고 처음 보는 문법으로 가져오는군요!
만약에 URL에 referer가 없으면 변수에는 null이나 undefined가 담기게 되는걸까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null로 반환됩니다
한옥님이 만들어주신 훅 사용가능하면 반영하도록 하겠습니다

Copy link
Collaborator

@hoxey2Front hoxey2Front left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다, 페이지를 컴포넌트 단위로 분리하셨군요!
엇 근데 PR 리뷰 제목에 오타가 있네요! (패이지 => 페이지)

@SwimmingRiver SwimmingRiver added the Review-Applied 모든 리뷰를 반영완료하였음을 의미합니다. label Jun 18, 2025
@SwimmingRiver SwimmingRiver changed the title Refactor/#249: 회원가입 패이지 리팩토링 Refactor/#249: 회원가입 페이지 리팩토링 Jun 18, 2025
Comment on lines 31 to 32
toast.success('회원가입이 완료되었습니다.');
router.push(APP_ROUTES.signin);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분 구현하면서 궁금했는데
toast 호출과 router.push를 연이어서 실행하면
페이지가 넘어간 뒤에 toast가 출력되나요? 아니면 페이지 전환되는 순간 toast가 사라지나요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

페이지가 전환돼도 설정했던 시간동안 유지되고 사라지는 걸로 확인했어요

Comment on lines +17 to +22
toast({
type: 'error',
title: '회원가입에 실패했습니다.',
message: error.message,
duration: 5,
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

혹시 error.message가 어떤 문자열로 들어올까요?
만약에 '회원가입에 실패했습니다.'라고 들어온다면 title과 message가 중복되서 어색할 수도 있고,
그럴 가능성은 별로 없어보이지만 영어로 된 에러 메시지가 들어온다면 title은 한글인데 message는 영어인 문제가
생길 수 있을지 궁금하네요
어떤 message가 들어오냐에 따라서 만약 부자연스러울 것 같다면
error.message를 아예 toast내부에 띄우지 않는 방법도 있을 것 같아요

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image
이런 형태로 나옵니다.
title에 메시지를 넣는 게 나을까요?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호 그렇군요! 지금처럼 타이틀이 핵심 설명, 메시지가 부가 설명인 구조가 좋아보이는 것 같아요!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

나중에 유저 관리를 DB로 옮기게 되면 회원가입 버튼을 누르기전에 '이메일 중복확인' 같은 버튼을 눌러야 되도록
하는 것도 좋을 것 같네요!

Copy link
Collaborator

@hoxey2Front hoxey2Front left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다~! 코드가 훨씬 가독성이 좋아진거 같네요!!

@SwimmingRiver SwimmingRiver merged commit 15e4973 into develop Jun 20, 2025
5 checks passed
@SwimmingRiver SwimmingRiver deleted the refactor/#249-page-signup branch June 20, 2025 06:42
myeongheonhong added a commit that referenced this pull request Jun 20, 2025
…rators

Feat: 모임 참여에 성공하면 DB 테이블에 사용자 정보가 입력되는 기능 구현
@SwimmingRiver SwimmingRiver restored the refactor/#249-page-signup branch September 23, 2025 13:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Review-Applied 모든 리뷰를 반영완료하였음을 의미합니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants