회원가입시 랜덤 닉네임 부여하기

Jeonghun·2023년 11월 30일
1

React

목록 보기
17/21


프로젝트 진행 중 회원가입시 특별히 본인의 닉네임을 설정하지 않은 유저들에게 랜덤으로 닉네임을 부여하는 기능을 추가했다.

이는 그리 어렵지 않은 작업이었지만, 다음에 재사용할 상황이 찾아올 수 있으니, 구현 과정을 기록하고자 한다.

닉네임에 들어갈 텍스트 배열 만들기

랜덤 닉네임의 경우 우선 닉네임을 어떤 형식으로 부여해둘 것인지 생각해야한다. 이번 프로젝트의 경우 에브리타임 과 비슷한 대학생들을 타겟으로 한 커뮤니티 사이트가 주제인 만큼, ex) 서울대123 과 같이 학교 이름과 숫자를 조합해 부여하면 좋을 것 같다고 생각했다.

이를 위해 학교 부분에 들어갈 텍스트를 배열로 만들어준다.

const names = [
    '서울대',
    '한양대',
    '고려대',
    '서강대',
    '연세대',
    '중앙대',
    '부산대',
    '경북대',
    '충남대',
    '전북대',
    'Harvard',
    'Yale',
    'Stanford',
    'MIT',
    'Princet',
    'Oxford',
    'Camb',
    'Caltech',
    'UCLA',
    'Berkeley',
  ];

세상에 존재하는 학교의 이름은 무수히 많지만, 국내외 대학교 중 생각나는 학교들의 이름을 가져왔다. 양이 적다고 생각될 수 있는데, 실제로 서비스하지 않는 사이드 프로젝트이기에 유저의 수가 적으며 뒤에 랜덤한 숫자를 부여한다고 했을 때 이 정도의 학교명으로도 충분히 많은 수의 닉네임을 뽑아낼 수 있다.

배열에서 인덱스로 텍스트 뽑아내기

텍스트가 담긴 배열을 만들었다면, 이제 이 배열에서 랜덤으로 하나의 텍스트를 뽑아 닉네임으로 사용해줘야한다.

이를 위해서 자바스크립트의 Math.randomMath.floor 메소드를 사용할 수 있다. random 메소드는 0 ~ 1 사이의 부동소수점의 난수를 랜덤으로 생성하며, floor 의 경우 숫자를 내림차순 한다. 참고 : MDN

두 메소드를 이용해 배열 내에서 랜덤한 인덱스를 뽑아 출력해보자.

const getRandomItem = (arr: string[]): string => 
  arr[Math.floor(Math.random() * arr.length)];

함수의 이름은 getRandomItem 이라고 지정하고, string 문자열로 이루어진 배열 arr 를 인자로 받는다.

이후 random 메소드를 사용해 랜덤한 수를 생성하고, arr 의 length를 곱해주면, 0 부터 length - 1 까지의 랜덤한 부동소수점 난수를 생성하게 되고, 이를 floor 를 통해 내림차순 하여 정수로 만들어준다.

이를 실행하면 다음과 같이 랜덤한 텍스트를 출력하게 되고, 이를 namePart 라는 변수에 저장해준다.

랜덤 숫자 붙이기

이제 랜덤한 텍스트를 뽑아냈으니, 숫자를 생성해 텍스트 뒤에 붙여주기만 하면 끝이다.

그 전에, 프로젝트 내에서 닉네임의 validation은 최소 2글자 ~ 최대 8글자만을 허용했기에 텍스트의 길이를 제외하고 남은 길이를 계산해줘야 했다.

const remainingLength = 8 - namePart.length;

8에서 랜덤 텍스트를 저장한 변수 namePart 의 length를 빼주면 간단하게 남은 자릿수를 계산할 수 있다.

텍스트가 '부산대' 라면 8 - 3 = 5 라는 결과값이 나올것이다.

이제 이를 이용해 남는 부분에 랜덤한 숫자를 부여해보자

// 랜덤 숫자 생성하는 함수
const generateRandomNumber = (min: number, max: number): string =>
	Math.floor(min + Math.random() * (max - min + 1)).toString();

// 남는 길이가 1 이상일 경우 남는 자릿수를 이용해 랜덤한 숫자 생성
const numberPart =
    remainingLength > 0
      ? generateRandomNumber(Math.pow(10, remainingLength - 1), Math.pow(10, remainingLength) - 1)
      : '';

// 최종 결과 값 리턴
return `${namePart}${numberPart}`;

remainingLength 의 길이에 맞게 최소값과 최대값을 계산하고, 그 범위 내에서 랜덤한 정수를 반환해 이를 문자열로 변환한다.

최종적으로 namePartnumberPart 를 붙여 리턴해 랜덤한 닉네임을 반환해준다.

랜덤 닉네임 함수 최종 코드

// getRandomNick.ts

export const generateRandomNickname = (): string => {
  const names = [
    '서울대',
    '한양대',
    '고려대',
    '서강대',
    '연세대',
    '중앙대',
    '부산대',
    '경북대',
    '충남대',
    '전북대',
    'Harvard',
    'Yale',
    'Stanford',
    'MIT',
    'Princet',
    'Oxford',
    'Camb',
    'Caltech',
    'UCLA',
    'Berkeley',
  ];

  const getRandomItem = (arr: string[]): string => arr[Math.floor(Math.random() * arr.length)];

  const generateRandomNumber = (min: number, max: number): string =>
    Math.floor(min + Math.random() * (max - min + 1)).toString();

  const selectNamePart = (): string => getRandomItem(names);

  const namePart = selectNamePart();

  const remainingLength = Math.max(0, 8 - namePart.length);

  const numberPart =
    remainingLength > 0
      ? generateRandomNumber(Math.pow(10, remainingLength - 1), Math.pow(10, remainingLength) - 1)
      : '';

  return `${namePart}${numberPart}`;
};

닉네임 설정 페이지에서 함수 사용하기

이제 만들어진 함수를 닉네임 페이지에서 사용해보자.

import React, { useState, useEffect, useRef, ChangeEvent } from 'react';
import { generateRandomNickname } from '@/utils/randomNick';
// import ...

const SetupProfileInfo = ({ user }: { user?: UserDataInterface | undefined }) => {
  const { register: imageUrlRegister, setValue: setImageUrlValue } = useSetupInput('imageUrl');

  const {
    register: nicknameRegister,
    errors,
    status: nicknameStatus,
    setValue: setNicknameValue,
  } = useSetupInput('nickname', nicknameValidation);

  const [profileImageUrl, setProfileImageUrl] = useState<string | undefined>(
    URL.DEFAULT_PROFILE_IMG,
  );

  const [nickname, setNickname] = useState<string>('');

  useEffect(() => {
    if (user) {
      setProfileImageUrl(user.imageUrl || URL.DEFAULT_PROFILE_IMG);
      setImageUrlValue('imageUrl', user.imageUrl || URL.DEFAULT_PROFILE_IMG);
      setNickname(user.nickname);
      setNicknameValue('nickname', user.nickname);
    } else {
// 기존 user data가 없을 경우 (즉, 새로 가입하는 회원의 경우) 기본 프로필 이미지와 랜덤 닉네임 부여
      const defaultImageUrl = URL.DEFAULT_PROFILE_IMG;
      const randomNickname = generateRandomNickname();

      setProfileImageUrl(defaultImageUrl);
      setImageUrlValue('imageUrl', defaultImageUrl);
      setNickname(randomNickname);
      setNicknameValue('nickname', randomNickname);
    }
  }, [user, setImageUrlValue, setNicknameValue]);

  return (
    <>
      {!user && (
        <MainComment
          style={{ fontSize: '20px', textAlign: 'center' }}
          comment='프로필을 설정해주세요'
        />
      )}
      <InputWrapper>
        <Input
          type='text'
          status={nicknameStatus}
          {...nicknameRegister('nickname')}
          defaultValue={nickname}
          errorMessage={
            errors.nickname && typeof errors.nickname.message === 'string'
              ? errors.nickname.message
              : undefined
          }
          placeholder='사용하실 닉네임을 입력해주세요.'
        />
      </InputWrapper>
      <ButtonContainer>
        <Button $isFullWidth type='submit' disabled={nicknameStatus !== 'success'}>
          {user ? '변경하기' : '회원가입'}
        </Button>
      </ButtonContainer>
    </>
  );
};

export default SetupProfileInfo;

// styled-components ...

SetupProfileInfo 컴포넌트는 react-hook-form을 이용하여 사용자의 프로필 사진과 닉네임을 관리한다. 이 때 해당 컴포넌트는 회원가입과 회원수정 단계에서 중복으로 사용되기에 user 를 props로 전달받아 기존에 가입된 user 의 데이터가 존재할 경우 해당 유저의 이미지와 닉네임을 불러와 회원수정 페이지에 적용하고, 그 외의 경우 (신규 가입) 에는 기본 이미지와 랜덤 닉네임을 부여한다.

결과물

useEffect 를 사용해 컴포넌트가 마운트 될 때 마다 새로운 랜덤 닉네임이 적절하게 부여되는 것을 확인할 수 있다.

profile
안녕하세요, 프론트엔드 개발자 임정훈입니다.

0개의 댓글