[미니 프로젝트] Jelog 만들기 #4

박제현·2023년 7월 25일
1

jelog 만들기

목록 보기
4/15

📮 로그인 화면 만들기.

Velog의 로그인 화면을 보면, 모달 팝업 형태로 만들면 될 것 같다.

내가 구성한 로그인 모달 팝업이다.
처음으로 svg 파일을 직접 넣어서 사용했다.
그 동안 대부분 아이콘들을 svg 파일을 직접 사용하는 것이 아니라, FontAwesome에서 받아와서 사용했기 때문에.. img 태그를 사용한 것은 이번이 처음이었다.

그런데 자꾸 엑스박스로 이미지가 깨지는 오류가 있었다.
처음에는 파일 경로를 잘못 지정한 줄 알았으나, 그건 아니었고.. 그러면 svg 파일을 읽지 못하는 것인가 싶어 PNG 파일로 변환해서 사용했으나, 여전히 엑스박스...
구글링 해본 결과 이미지 경로에 require() 함수를 사용하면 해결 된다고 한다.

	<img
		src={require("../images/loginImage.png")}
        alt="Login Image"
        className="image"
    />

require() 함수를 붙여도 엑스박스가 뜬다면 default를 붙이면 해결된다.

require() 함수를 사용하면 해결되는 이유는 img 태그의 소스로 이미지를 직접 보내주는 것이 아니라, require() 함수에서 return 된 객체가 보내지기 때문이다.

하단의 회원가입 버튼을 클릭하면 모달 창이 새로 띄워지는 것이 아니라 내용만 변하는 것을 볼 수 있었다.
처음에는 로그인 전용 모달, 회원가입 모달을 따로 만들어서 버튼을 누를 때 마다 해당 모달이 켜지고 꺼지는 방식으로 만들려고 했었다.
근데, 생각해보니까 굳이...? 라는 생각이 들더라, 그래서 그냥 내부 텍스트만 변경해주기로 코드를 짰다.

  const onClickRegisterButton = () => {
    if (modalState === "login") {
      setModalState("register");
      modalTags.title.current.innerText = "회원가입";
      modalTags.method.current.innerText = "이메일로 회원가입";
      modalTags.mainButton.current.innerText = "회원가입";
      modalTags.subTitle.current.innerText = "소셜 계정으로 회원가입";
      modalTags.message.current.innerText = "계정이 이미 있으신가요?";
      modalTags.messageButton.current.innerText = "로그인";
    } else if (modalState === "register") {
      setModalState("login");
      modalTags.title.current.innerText = "로그인";
      modalTags.method.current.innerText = "이메일로 로그인";
      modalTags.mainButton.current.innerText = "로그인";
      modalTags.subTitle.current.innerText = "소셜 계정으로 로그인";
      modalTags.message.current.innerText = "아직 회원이 아니신가요?";
      modalTags.messageButton.current.innerText = "회원가입";

      modalTags.userIDInputRef.current.style.backgroundColor = "white";
      modalTags.userIDInputRef.current.style.color = "black";
      modalTags.userIDInputRef.current.style.fontWeight = "400";

      modalTags.userIDInputRef.current.value = "";
      modalTags.userIDInputRef.current.removeAttribute("readOnly");
      modalTags.mainButton.current.style.display = "";

      console.log(modalTags.userIDInputRef.current);
    }
  };

modalState를 상태로 설정하여, 현재 modal 이 로그인 화면인지, 회원가입 화면인지 파악하고, 그에 맞는 텍스트로 설정한다.

좀 무식한 방법인 것 같긴 한데.. 더 나은 방법을 생각해내지 못했다. 😅

정상적인 이메일로 판단되면 위와 같이 이메일 input이 하나의 div 태그로 변하는 것 같다.

이 부분에서 조금은 애를 먹었던 것 같다.
일단 css-module을 이용하면 classList.toggle()이 정상적으로 동작하지 않았다.
새로운 클래스가 등록돼도 좀 이상하게 동작하는 것 같아서.. header.js 는 그냥 css 로 작성하기로 결정했다.

hide 클래스를 지정하여 정상적인 이메일이 제출되면 input과 button에 hide 클래스를 지정하여 안보이게 숨기고, 성공 메세지의 hide 클래스를 제거하여 보여지게 하는 방법으로 코드를 짰다.

그런데.. 이상하게 Link 태그가 hide 가 안되더라.. 이유를 모르겠다. 지금 다시 구현하려고 하니까 또 된다. 나한테 왜 그러는거야...

아무튼 그래서 처음 구상했던 새로운 성공 메세지 div를 만들지 않고, 기존의 input과 button을 이용해서 성공메세지를 띄우기로 했다.

	modalTags.userIDInputRef.current.style.backgroundColor = 
      "var(--velog-white-green)";
   	modalTags.userIDInputRef.current.style.color = "var(--velog-green)";
    modalTags.userIDInputRef.current.style.fontWeight = "600";

    modalTags.userIDInputRef.current.value ="✔️ 회원가입 링크가 이메일로 전송되었습니다.";
    modalTags.userIDInputRef.current.readOnly = "true";
    modalTags.mainButton.current.style.display = "none";

위 코드 처럼 input 태그의 backgroundColor 수동으로 지정하고, button은 display: "none"으로 감춰버렸다.

그렇게 만들어진 내 jelog 회원가입 화면이다.
꽤나 그럴싸 하게 만든 것 같다... 껍데기 뿐이지만..ㅎㅎ

😶‍🌫️ 유효 계정 체크하기.

지금까지는 껍데기만 만들었다면, 이제는 제대로 동작하는 로그인 기능을 만들어야지 않겠나..
일단, 아직 DB가 없기 때문에.. 리액트의 useState() 를 사용해서 계정을 등록하는 방식으로 구현해봤다.

	setAccountList([
      ...accountList,
      { id: userID.split("@")[0], account: userID },
    ]);

위 코드와 같이 input으로 들어오는 userID는 전제 이메일이 들어오기 때문에, @ 앞으로 id를 지정하고, account는 전제 이메일을 지정해서 accountList에 넣어주었다.

Regular Expression // RegExp

정규 표현식은 특정한 패턴의 문자열을 찾거나 매치하는데 사용되는 문자열의 집합이다.
정규 표현식은 다양한 문자와 메타 문자들로 구성되고, 각 문자와 메타 문자들은 특정한 의미를 갖는다.

정규 표현식에서 자주 사용되는 문자와 메타 문자의 예시

  • .: 어떤 문자와 일치한다. 예를 들어, /a.c/ 는 "abc", "aac", "a1c" 등과 일치한다.
  • *: 바로 앞에 있는 패턴이 0회 이상 반복되는 문자열과 일치한다. 예를 들어, /ab*c/는 "ac", "abc", "abbc", "abbbc" 등과 일치한다.
  • +: 바로 앞에 있는 패턴이 1회 이상 반복되는 문자열과 일치한다. 예를 들어, /ab+c/는 "abc", "abbc", "abbbc" 등과 일치하지만 "ac"와 일치하지 않는다.
  • ?: 바로 앞에 있는 패턴이 0회 또는 1회 반복되는 문자열과 일치한다. 예를 들어, /ab?c/는 "ac"와 "abc"와 일치하지만 "abbc"는 일치하지 않는다.
  • []: 괄호 안에 있는 문자 중 하나와 일치한다. 예를 들어, /[abc]/는 "a", "b", "c"와 일치한다.
  • [^]: 괄호 안에 있는 문자를 제외한 다른 문자와 일치한다. 예를들어, [^abc]는 "d", "e", "f"와 일치한다.
  • (): 괄호 안에 있는 패턴을 그룹으로 묶는다. 예를 들어, /(ab)+c/는 "abc", "ababc"와 일치한다.
	const foundResult = accountList.find((item) => item.account === userID);
	if (foundResult) {
      setUserID(userID.split("@")[0]);
      setShowModal(false);
      setIsLogin(true);
    } else {
      modalTags.alertPopUP.current.style.display = "flex";
      showAlertPopUp();
    }

array.find() 함수를 사용해서 accountList에 사용자가 입력한 계정이 존재하는지 확인하고, 존재하면 로그인, 그렇지 않으면 경고창을 띄운다.

Array.prototype.find()

JavaScript의 배열 메서드 중 하나로, 배열에서 주어진 조건을 만족하는 첫 번째 요소를 찾아 반환한다.
조건을 만족하는 요소가 없을 경우 'undefined'를 반환한다.

벨로그의 경우 로그인이나 회원가입에서 잘못된 입력이 있을 경우, 우측 상단에 알림이 띄워진다.
이 부분은 어떻게.. 구현할까 생각하다. modal 태그에 넣기로 결정했다.

평상시에는 hide 클래스로 보여지지 않지만, 잘못된 입력이 제출되면 hide 클래스를 삭제하여 사용자에게 노출되도록 하는 방법으로 코드를 짰다.

	else {
        console.log("올바른 이메일 형식이 아닙니다.");
        modalTags.alertPopUP.current.style.display = "flex";
        showAlertPopUp();
      }

====================================================================
  
  	const showAlertPopUp = () => {
    setTimeout(() => {
      modalTags.alertPopUP.current.style.display = "none";
    }, 2000);
  };

약 2초정도 알림 팝업이 보여지고 사라지기 때문에, setTimeout 함수를 사용하여 2초가 지나면 팝업이 보이지 않도록 속성을 수정한다.

그렇게 만들어진 나의 결과물이다. 아직 애니메이션은 없지만, 그래도 동작은 완벽하게 하는 모습이다.

👀 포스트 URL에 사용자 ID 연동하기.

로그인 구현을 완료하고.. 기존에 포스트 페이지 URL이 그냥 /post/index 였던 것을, /post/userID/index 로 수정해야 그 게시글을 누가 작성했는지, 권한을 판단할 수 있으니.. 포스팅 URL을 수정했다.

	<Link
       to={`/post/${item.userID}/${item.id}`}
       key={index}
       className="postBox"
    >
    <div className="innerBox">
       <div className="thumbnail">THUMBNAIL</div>
       <span className="title">{item.title}</span>
       <span className="content">{item.content}</span>
    </div>
    <span className="date">{item.date}</span>
   </Link>
==========================================================
	<Route
       path="/post/:userID/:id"
       element=
        { <PostPage
			postList={postList}
            setPostList={setPostList}
            userID={userID}
			/>
		}
    />

위와 같이 Link와 Route 태그를 수정하였다.


정상적으로 URL이 사용자 ID에 맞게 설정된 것을 볼 수 있다.

이제 앞으로 할 것은, 게시글의 작성자와 현재 로그인된 사용자를 서로 비교하여 같으면 게시글을 수정, 삭제 할 수 있게하는 기능, 그리고 사용자마다 like 버튼은 한 번만 가능 하도록 하는 기능을 구현 해 보면 좋을 것 같다.

포스트에 이미지를 첨부하는 기능도 구현해야하고.. 생각보다 벨로그에 기능이 꽤나 많았구나...

📚 오늘의 챗 GPT

  • React에서 컴포넌트 속성을 변경하는 방법은 setAttribute(), removeAttribute() 로 변경할 수 있다.
  • JavaScript의 배열에서 특정 값이 있는지 확인하려면 some() 메소드를 사용하면된다. some() 메소드는 배열의 요소 중에서 주어진 조건을 만족하는 요소가 하나라도 있는지 확인한다.
profile
닷넷 새싹

0개의 댓글