[JS]아랍어 단어장 페이지 구현해보기 - 1.Plan & Routing

CHO WanGi·2023년 5월 13일

Javascript

목록 보기
3/20

계기

지금까지 해왔던 코딩 공부는 영상을 보고 개념을 정리하고 이를 공부하는 수준에 지나지 않았다.
사실 내가 코딩실력이 언제 제일 늘었는가를 생각해보면, 멋사활동을 하면서 JS에 대한 개념이 제대로 없는 상태에서 가위바위보 페이지를 만들고, 틀린 글자 찾기를 만들었을때 라고 생각이 들었다.

나는 개발공부의 핵심인 나의 힘으로 만들어보는 것을 하지 않고 있었다.

(사실 리액트로 한번 만들어봤었는데, JS로만 먼저 만들어보고, 나중에 리액트를 공부하고 리액트로 다시 만들어보고 차이점이 무엇인지, 왜 JS로만 만들지 않고 굳이 리액트를 사용하는지 알아보는 시간을 가지면 뭔가 실력이 더 향상되지 않을까 하는 기대가 있다... pls)

계획

여러 유튜브를 보니, 설계 후 코딩을 시작하라고 한다.
여기서 설계는 Design, 어떻게 예쁘게 만들지의 Design 이 아닌,
어떤 기능이 필요하고, 이러한 기능을 어떻게 JS를 활용하여 만들어 내는가의 Design 이다.

Function Structure

필요한 기능

  • Main Page
    사용자가 마주할 첫 화면이 될 페이지이다.
  1. Header에 Navigation Bar 가 필요하다
    • 메인페이지, 명사,동사,About 페이지로 이동하는 기능
  2. 단어를 검색할 수 있는 SearchBar 가 필요하다
    • 한글을 검색하면 일치하는 뜻을 가진 아랍어 단어를 보여주는 기능
  3. 품사에 관계없이 단어와 그 단어가 가진 뜻을 보여주는 것이 필요하다
    • 단어 : 의미 형태의 데이터를 HTML상에 렌더링 하는 기능
  • Noun/Verb Page
    Main 과 비슷한 구조를 갖는다.
    그러나 차이는
  1. 명사/동사만 보여주는 것이 필요하다
    • 명사/동사를 전체 단어에서 분류하여 이를 보여주는 기능
  • About Page
  1. 역시나 다른 페이지로 이동하기 위해 NavBar 가 필요하다.
  2. 내 깃헙으로 넘어갈 수 있어야 한다.
  3. 메일 주소를 클릭하면 바로 구글 메일을 작성할 수 있어야 한다.

단어 데이터

Gist Link

  • 데이터 형식은 이렇다
 {
    "id": 1,
    "mean": "방향,방면",
    "single": "نحو",
    "plural": "أَنْحَاء",
    "example": "وبذلك كان قد توجه من جديد في طريقه نحو المدينة",
    "exmean": "다시 새롭게 도시를 향해 길에서 걸어갔다",
    "part": "noun",
    "appendix": ""
  },

일단 single과 mean 에 해당하는 value만 보여주는 것이 1차 목표이다.
그리고 단어 데이터 파일에서 단어를 가져오는 형식으로 만들어보고,

그다음 Gist 에 올린이상 주소를 활용해서 API 처럼 활용이 가능하기 때문에
추후 개선을 하는 방향으로 진행할 예정이다.

SPA(Routing)

FastCampus에서 배운 걸 활용할 예정이다.
각 페이지의 해쉬값을 받아와서 그에 맞는 컴포넌트를 렌더링하는 형식이 될 것이다.

참고

SPA

SPA 원리

만난 ERR

  1. innerHTML 에 null 값이 들어가는 현상
function routeRender(routes){
  // 예외처리
  if(!location.hash) {
    history.replaceState(null,'','/#/')
  }

  const routerView = document.querySelector('router-view')
  const [hash, querystring = ''] = location.hash.split('?')
  // 넘어오는 routes 로부터 hash 값 가져오기
  const currentRoute = routes.find(route => new RegExp(`${route.path}/?$`).test(hash))
  
  // 각 객체의 실제 출력물은 속에 component 속성
  // routerview 내용을 컴포넌트의 인스턴스의 el을 밀어넣기
  routerView.innerHTML = `` // 🚨 TypeERROR!
  routerView.append(new currentRoute.component().el)
  //페이지 변경시 스크롤 최상단 고정
  window.scrollTo(0,0)
}

참조링크

  • 원인: CoreComponent의 constructor 함수 내에서 render 함수를 실행하지 않았음

참고한 링크 에서 이런 에러가 발생하는 이유는
1. null 값이 변수에 들어가는 경우
2. DOM 에 없는 요소에 설정하는 경우
3. JS script 태그가 HTML 위에 있는 경우

그러나 2번같은 경우 <div id='root'></div> 가 index.html 안에 분명히 존재했고,
3번같은 경우 defer 키워드를 사용해서 HTML 파싱 후 실행하도록 했기 때문에
1번이 원인이겠다 생각하고 찾아보았다.

constructor(payload ={}){
    const { 
      tagName = 'div', 
      state= {},
      props = {}
    } = payload
    this.el = document.createElement(tagName)
    this.state = state
    this.props = props
    //🚨this.render()
  }

이를 수도 코드로 바꾸어보면
1. payload를 받아서
2. tagName, state, props를 정의하고 이를 payload라고 사용
3. 이 함수의 요소는 tagName을 사용해서 HTML의 태그를 만든다
4. 이 함수에서 사용할 state는 받아온 state
5. 이 함수에서 사용할 props는 받아온 props

이게 빠졌다
6. 이 함수에서 받아온 payload 데이터를 활용해 "렌더링 하는 함수를 호출 해!"

이게 빠지면 당연히 null 값이 innerHTML로 들어가는게,
예를 들어서 App.js 를 살펴보면

import { CoreCompoent } from "./core/coreComponent";
import TheHeader from "./components/TheHeader";

// coreComponent를 확장(동일한 구조)
export default class App extends CoreCompoent{
  render(){
    // router-view 태그 생성
    const routerView = document.createElement('router-view')
    // this.el은 tagName에 따라 만들어지는 태그, 그안에 router-view 태그를 삽입
    this.el.append(
      new TheHeader().el,
      routerView
    )
  }
}

이렇게 되면 App.js는 coreComponent.js를 확장해서 사용한다.
render() 함수를 호출할때 할 행동들을 정의해 놓았다.

App.js 의 render 함수가 동작할 것들을 아무리 만들어 놓아도,
coreComponent의 constructor 함수에서 render() 함수를 호출하지 않았기 때문에,
innerHTML 로 들어갈 데이터가 아무것도 없어서 Null 이 할당되어 에러를 만든 것이다.

다음 계획

이제 라우팅 구현이 끝났으니,
메인페이지에 단어 데이터 출력을 구현할 예정이다.

GitHub Repo

profile
제 Velog에 오신 모든 분들이 작더라도 인사이트를 얻어가셨으면 좋겠습니다 :)

0개의 댓글