유튜브 링크 유효성 검사하기

chichi·2023년 5월 23일
0

motion 프로젝트를 조금씩 수정 하면서, 이번에는 유효성 검사를 진행하기 위해 유튜브 부분의 코드를 다시 살펴봤다.

이미지 첨부 부분의 유효성 검사는 이미지 파일인 경우에만 올릴 수 있어서 문제가 없었는데, 유튜브 링크의 유효성 검사는 조금 까다로웠고, 원하는 동작을 만들기 위해 총 3번의 시행착오가 있었는데 그 과정을 기록하고자 한다.

먼저 주어진 링크가 유효한 YouTube 링크인지를 판별하기 위한 코드가 필요해, 검색을 통해 작성했다.

const isValidYouTubeLink = (link: string): boolean => {
    // 유효한 YouTube 도메인 패턴
    const youtubeDomainPattern = /^(https?:\/\/)?(www\.)?youtube\.com(\/.*)?$/;
    const shortLinkPattern = /^(https?:\/\/)?(www\.)?youtu\.be(\/.*)?$/;

    // 정규식 패턴을 이용하여 링크를 검증
    if (youtubeDomainPattern.test(link) || shortLinkPattern.test(link)) {
      // 도메인 패턴 또는 짧은 링크 패턴에 일치하면 유효한 링크로 판단
      return true;
    }
    return false;
  };

// 테스트
console.log(isValidYouTubeLink("https://www.youtube.com/watch?v=NpEaa2P7qZI")); // true
console.log(isValidYouTubeLink("https://www.google.com")); // false

이제 이 함수를 이용해서

  • 유효한 유튜브 링크인지, 아닌지 구분하고
  • 올바르지 않은 유튜브 링크일 때 별도 처리

를 하려고 한다.


1. 올바르지 않은 유튜브 링크일 때 placeholder 유튜브가 뜨게 만들기

  • 주어진 링크가 유효한 Youtube 도메인 패턴인지 확인한 뒤, 유효하면 true를 유효하지 않다면 false를 반환하는 함수를 만들어준다.
  • input의 onChange에 연결한 handleVideoChange 함수에서는 입력된 값을 (event: React.ChangeEvent)로 받아온 뒤
  • 유효한 링크라면, (isValidYouTubeLink(event.target.value) === true)
  • setVideoUrlState(event.target.value)로 videoUrlState에 입력값을 저장하고, 등록 버튼을 누르면 함께 전송할 수 있도록 설정
  • 유효한 링크가 아니라면, (isValidYouTubeLink(event.target.value) === false)
  • setVideoUrlState("https://youtu.be/NpEaa2P7qZI")로 video placeholder 영상이 뜨도록 설정

위 과정으로 올바르지 않은 유튜브 링크일 때 바로 placeholder 유튜브가 뜨도록 만들었는데, 막상 완성하고 나니 UX가 좋지 못하다는 느낌을 받았다.

const isValidYouTubeLink = (link: string): boolean => {
    // 유효한 YouTube 도메인 패턴
    const youtubeDomainPattern = /^(https?:\/\/)?(www\.)?youtube\.com(\/.*)?$/;
    const shortLinkPattern = /^(https?:\/\/)?(www\.)?youtu\.be(\/.*)?$/;

    // 정규식 패턴을 이용하여 링크를 검증
    if (youtubeDomainPattern.test(link) || shortLinkPattern.test(link)) {
      // 도메인 패턴 또는 짧은 링크 패턴에 일치하면 유효한 링크로 판단
      return true;
    }
    return false;
  };

const handleVideoChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    if (isValidYouTubeLink(event.target.value)) {
      setVideoUrlState(event.target.value);
    } else setVideoUrlState("https://youtu.be/NpEaa2P7qZI"); // ** 해당 부분
  };

// ...

// 등록 버튼을 누르면 실행되는 함수. 입력값을 dispatch로 보냄
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();

    const newPost = {
      id: Date.now(),
      title,
      content,
      imageUrl: imageFile,
      videoUrl: videoUrlState,
      task: taskState,
      category,
    };

    console.log("newPost 객체", newPost);

    if (imageFile || videoUrlState) {
      dispatch(setImage(imageFile));
      dispatch(setPreviewImage(imageFile));
      dispatch(addPost(newPost));
      setTitle("");
      setContent("");
    } else {
      dispatch(addPost(newPost));
      setTitle("");
      setContent("");
    }
    console.log("taskState :", taskState);
    console.log("category :", category);
    onClose(); 
  };

// .. 아래로 리턴문

{category === "video" && (
            <>
              <label>
                <input
                  placeholder="YouTube video URL"
                  type="text"
                  value={videoUrlState}
                  onChange={handleVideoChange}
                />
              </label>
              <YouTubeIframe url={videoUrlState} />
            </>
          )}

이렇게 작성하면 ‘올바르지 않은 유튜브 링크’일 때 바로 placeholder 유튜브가 떠서 사용자 입장에서 뜬금없이 느껴질 수도 있을 것 같다.

차라리 보편적인 방법으로 ‘올바르지 않은 링크입니다. 링크를 다시 확인해 주세요.’ 라는 문구가 아래에 뜨는 것이 좋을 것 같아 그렇게 수정하기로 했다.


2. 올바르지 않은 유튜브 링크일 때 <p> 태그로 경고 문구 띄우기

올바르지 않은 유튜브 링크인지 구분하기 위해 [invalidLink, setInvalidLink] = useState(false) 를 설정하고,

handleVideoChange 함수 안에 올바르지 않은 링크가 들어와서 false값이 리턴되면

invalidLink 상태를 true로 변경,

아래 리턴문에서 invalidLink가 true이면 <p>올바르지 않은 링크입니다. 링크를 다시 확인해 주세요.</p> 문구를 추가한다

const Modal = () => {
  const [title, setTitle] = useState("");
  const [content, setContent] = useState("");
  const [imageFile, setImageFile] = useState("");
  const [videoUrlState, setVideoUrlState] = useState("");
  const [taskState, setTaskState] = useState(false);
  const [invalidLink, setInvalidLink] = useState(false);
// ...

const isValidYouTubeLink = (link: string): boolean => {
    // 유효한 YouTube 도메인 패턴
    const youtubeDomainPattern = /^(https?:\/\/)?(www\.)?youtube\.com(\/.*)?$/;
    const shortLinkPattern = /^(https?:\/\/)?(www\.)?youtu\.be(\/.*)?$/;

    // 정규식 패턴을 이용하여 링크를 검증
    if (youtubeDomainPattern.test(link) || shortLinkPattern.test(link)) {
      // 도메인 패턴 또는 짧은 링크 패턴에 일치하면 유효한 링크로 판단
      return true;
    }
    return false;
  };

const handleVideoChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    if (isValidYouTubeLink(event.target.value)) {
      setInvalidLink(false);
      setVideoUrlState(event.target.value); // 수정해야 할 부분**
    } else setInvalidLink(true);
  };

// ...

{category === "video" && (
            <>
              <label>
                <input
                  placeholder="YouTube video URL"
                  type="text"
                  value={videoUrlState} // 수정해야 할 부분**
                  // 특정한 값을 넣는 것이 아닌 이상 value는 필요하지 않다. ex) id 기억하기 -> value값 기억하는 경우
                  onChange={handleVideoChange}
                />
                {invalidLink ? (
                  <p className="text-xs text-red-200">
                    올바르지 않은 링크입니다. 링크를 다시 확인해 주세요.
                  </p>
                ) : null}
              </label>
              <YouTubeIframe url={videoUrlState} />
            </>
          )}

그런데 이렇게 입력하니 옳은 링크를 입력한 뒤 백스페이스로 링크 지우기를 시도했을 때

아래 gif 처럼 youtu.be 까지만 지워지고, 그 이후로 지워지지 않는 문제가 발생했다.
앗, 큰일이당

3. 올바르지 않은 유튜브 링크일 때 백스페이스로 input 내용 전부 지울 수 있게 만들기

원인은 위 코드에서 주석 표기한 두 곳인

  1. handleVideoChange 함수 안의 setVideoUrlState(event.target.value) 위치와
  2. input 태그 안의 value에 있었다.

앞서 잘못 쓴 코드에서는 gif 사진처럼 유튜브 링크를 옳게 넣었을 때

  • isValidYouTubeLink 함수 = true 리턴
  • invalidLink = false
  • videoUrlState = 입력값
  • value = 입력값

인 상태,

백스페이스로 지우기를 시도했을 때 (유튜브 링크가 옳지 않을 때)

  • isValidYouTubeLink = false 리턴
  • invalidLink = true
  • videoUrlState = setVideoUrlState로 바꾸지 않아서 isValidYouTubeLink가 true를 반환하는 값,
    유효한 도메인 패턴까지만 설정되어 있고 이후로 변경되지 않음
  • else 문 뒤로는 setInvalidLink(true)만 있기 때문

그래서 유튜브 링크가 옳지 않을 때도, 입력값에 따라 input 안의 내용이 변경되려면

handleVideoChange를 통해 setVideoUrlState(event.target.value)가 작동되어야 하고

input 태그 안의 value를 지워야 한다

input 태그 안의 value는 특정한 값을 넣는 것이 아닌 이상 추가할 필요가 없었다.

예를 들면 로그인 화면에서 “아이디 기억하기” 처럼 value 값을 기억해야 하는 경우에 쓰이기 때문에

지금 같은 경우 value가 필요하지 않으므로 input 안의 value를 지워준다


const isValidYouTubeLink = (link: string): boolean => {
    // 유효한 YouTube 도메인 패턴
    const youtubeDomainPattern = /^(https?:\/\/)?(www\.)?youtube\.com(\/.*)?$/;
    const shortLinkPattern = /^(https?:\/\/)?(www\.)?youtu\.be(\/.*)?$/;

    // 정규식 패턴을 이용하여 링크를 검증
    if (youtubeDomainPattern.test(link) || shortLinkPattern.test(link)) {
      // 도메인 패턴 또는 짧은 링크 패턴에 일치하면 유효한 링크로 판단
      return true;
    }
    return false;
  };

  const handleVideoChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    if (isValidYouTubeLink(event.target.value)) {
      setInvalidLink(false);
      // ** setVideoUrlState(event.target.value) : 해당 부분을 지워준다
    } else setInvalidLink(true);
    // ** 계속 input에 넣는 값을 업데이트 할 수 있게 밖으로 빼낸다
    setVideoUrlState(event.target.value);
  };

// .. 아래로 리턴문

{category === "video" && (
            <>
              <label>
                <input
                  placeholder="YouTube video URL"
                  type="text"
                  // value={videoUrlState}
                  // 특정한 값을 넣는 것이 아닌 이상 value는 필요하지 않다. ex) 아이디 기억하기 -> value 값 기억하는 경우
                  onChange={handleVideoChange}
                />
                {invalidLink ? (
                  <p className="text-xs text-red-200">
                    올바르지 않은 링크입니다. 링크를 다시 확인해 주세요.
                  </p>
                ) : null}
              </label>
              <YouTubeIframe url={videoUrlState} />
            </>
          )}

위 코드처럼 수정했더니 의도한 대로 유효성 검사와 함께 백스페이스가 잘 작동하는 것을 확인할 수 있었다 :)

0개의 댓글