Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[15팀 이규리] [Chapter 1-1] 프레임워크 없이 SPA 만들기 #17

Open
wants to merge 35 commits into
base: main
Choose a base branch
from

Conversation

9yurilee
Copy link

@9yurilee 9yurilee commented Dec 18, 2024

과제 체크포인트

기본과제

  • History API를 사용하여 SPA 라우터 구현
    • '/' (홈 페이지)
    • '/login' (로그인 페이지)
    • '/profile' (프로필 페이지)
  • 각 라우트에 해당하는 컴포넌트 렌더링 함수 작성
  • 네비게이션 이벤트 처리 (링크 클릭 시 페이지 전환)
  • 주소가 변경되어도 새로고침이 발생하지 않아야 한다.

2) 사용자 관리 기능:

  • LocalStorage를 사용한 간단한 사용자 데이터 관리
    • 사용자 정보 저장 (이름, 간단한 소개)
    • 로그인 상태 관리 (로그인/로그아웃 토글)
  • 로그인 폼 구현
    • 사용자 이름 입력 및 검증
    • 로그인 버튼 클릭 시 LocalStorage에 사용자 정보 저장
  • 로그아웃 기능 구현
    • 로그아웃 버튼 클릭 시 LocalStorage에서 사용자 정보 제거

3) 프로필 페이지 구현:

  • 현재 로그인한 사용자의 정보 표시
    • 사용자 이름
    • 간단한 소개
  • 프로필 수정 기능
    • 사용자 소개 텍스트 수정 가능
    • 수정된 정보 LocalStorage에 저장

4) 컴포넌트 기반 구조 설계:

  • 재사용 가능한 컴포넌트 작성
    • Header 컴포넌트
    • Footer 컴포넌트
  • 페이지별 컴포넌트 작성
    • HomePage 컴포넌트
    • ProfilePage 컴포넌트
    • NotFoundPage 컴포넌트

5) 상태 관리 초기 구현:

  • 간단한 상태 관리 시스템 설계
    • 전역 상태 객체 생성 (예: 현재 로그인한 사용자 정보)
  • 상태 변경 함수 구현
    • 상태 업데이트 시 관련 컴포넌트 리렌더링

6) 이벤트 처리 및 DOM 조작:

  • 사용자 입력 처리 (로그인 폼, 프로필 수정 등)
  • 동적 컨텐츠 렌더링 (사용자 정보 표시, 페이지 전환 등)

7) 라우팅 예외 처리:

  • 잘못된 라우트 접근 시 404 페이지 표시

심화과제

1) 해시 라우터 구현:

  • location.hash를 이용하여 SPA 라우터 구현
    • '/#/' (홈 페이지)
    • '/#/login' (로그인 페이지)
    • '/#/profile' (프로필 페이지)

2) 라우트 가드 구현:

  • 로그인 상태에 따른 접근 제어
  • 비로그인 사용자의 특정 페이지 접근 시 로그인 페이지로 리다이렉션

3) 이벤트 위임:

  • 이벤트 위임 방식으로 이벤트를 관리하고 있다.

과제 셀프회고

기술적 성장

  • SPA 라우팅 구현 학습
    history.pushState를 동작하도록 설계한 점에서 많은 기술적 도전을 느꼈습니다. 과제 이후 React-Router 문서를 읽으니 어떤 원리로 동작하는지 좀 더 이해가 이해할 수 있었습니다.
  • 상태 관리와 이벤트 위임 학습
    간단한 상태 관리와 이벤트 위임을 활용하여 DOM 구조가 변경되더라도 안정적으로 동작하도록 구현한 점에서, 기존 지식의 심화와 새로운 학습을 모두 경험할 수 있었습니다.

코드 품질

  • 해시 라우터의 학습 필요성
    아직 해시 라우터가 불안정한 상황이라 해시 라우터에 대한 개선이 필요합니다.

학습 효과 분석

  • useState의 동작 원리 학습
    React를 사용하면서 수없이, 쉽게 사용했던 useState를 바닐라 자바스크립트로 지 직접 작성하며 React의 상태 관리 원리를 학습할 수 있었습니다. 단순한 상태 객체와 구독 함수(subscribe)를 만들어 상태 변경 시 특정 DOM 요소가 다시 렌더링되도록 구현했는데, 이를 통해 React의 useState가 어떻게 값을 변경하고, 어떻게 콜백 함수를 실행하는지를 알 수 있었습니다.
  • 가장 큰 배움
    SPA의 동작 흐름을 깊이 이해하게 되었습니다.
    1. 브라우저 요청 (GET) → 서버 응답 (index.html)
    2. JavaScript 실행 → 라우터 확인 (현재 경로 파악)
    3. 초기 렌더링 (Home Page) → DOM에 삽입
    4. 사용자 링크 클릭 → 라우터 동작 → 새 페이지 렌더링
    5. 상태 변경 → 필요한 컴포넌트 다시 렌더링
      이와 같은 흐름을 파악하면서, 문제가 발생했을 때 동작 흐름을 기준으로 디버깅하는 방법을 학습할 수 있었습니다.

과제 피드백

  • 좋았던 점
    React로 바로 개발을 시작했던 과거와 달리, 이번 과제를 통해 바닐라 JS로 상태 관리와 라우팅을 직접 구현해 보며, 리액트의 내부 동작 원리를 체험해볼 수 있었습니다. 특히, 상태 관리와 컴포넌트 재렌더링의 원리를 직접 구현해 본 점이 인상 깊었습니다.

리뷰 받고 싶은 내용

  1. router.js의 관심사 분리
    router() 함수에서 UI 렌더링과 초기화 함수 실행을 분리하는 것이 적절했을지 구분이 잘 안갑니다. subscribe도, main에서도 전부 router를 다루고 있어서 router에서 라우트 가드 기능을 체크하는게 좋다고 판단해서 넣었는데 말씀하셨던 관심사 분리가 안되는 것 같아서요.. 또 따로 분리하자니 어디로 떼어내야 할 지 감이 안잡히기도 했구요.! 조언 부탁드립니다!
  2. 폴더 구조의 적합성
    router.js를 독립된 파일로 관리한 점이 적절한지 판단이 잘 서지 않습니다. 만약 아니라면 일반적으로 라우터 파일은 어떤 위치에 배치하는 것이 좋은지 조언 부탁드립니다.
  3. 로그아웃 이벤트의 적합성
    로그아웃 이벤트가 네비게이션에 달려있어서 네비게이션에서 다루는걸로 했는데, 이러면 프로필 페이지에서 작동 안 될 가능성도 있지 않을까? 생각이 들더라구요. 그리고 로그인 이벤트와 성격이 유사해 보여서 고민이 되기도 했었구요. 네비게이션 관련 이벤트에 묶는게 맞는 방법일지, 다른 좋은 위치가 있다면 어디가 있을 지 조언 부탁드립니다!
  4. 해시 라우터의 문제점
    사실 e2e랑 유닛 테스트는 통과했지만 자체 테스트 중에 과제 요구사항대로 구현되지 않았음을 발견했습니다. hashChange로 hash 변경 이벤트 감지해서 Router 발생시키고, hash path는 location.hash로 판단해서 잘라서 브라우저 라우터랑 통합해서 사용해보려고 하는데, 잠깐 보였다가 사라지더라구요. main.js에서 브라우저 라우터랑 해시 라우터를 동시에 호출하고 있는게 문제일지 , 다른 부분이 문제인건지 조금 헤매고 있습니다..! 호옥시.. 힌트를 받을 수 있다면 정말정말 좋을 것 같습니다..!

9yurilee and others added 30 commits December 15, 2024 14:50
const selected = e.target.closest("a");
if (!selected) return;

const isLogoutBtn = selected.hasAttribute("id") && selected.id === "logout";

Choose a reason for hiding this comment

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

isLogoutBtn을 함수로 만들면 어떨까요?

  const isLogoutBtn = (x => x.hasAttribute("id") && x.id === "logout";

  if (isLogoutBtn(selected)) {

Copy link
Author

Choose a reason for hiding this comment

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

아이고 석호님- 2주차 후딱 끝내고 리뷰해주신거 확인해야지 했는데 2주차를 꽉꽉 채워버렸네요..!
오 한 곳에서만 쓰인다는 생각에 함수로 뺄 생각은 한 번도 못해본 것 같아요!
단순히 변수로만 생각했었는데, 의견 감사합니다!

Comment on lines +27 to +37
// 비로그인 사용자는 프로필 접근 불가 → 로그인 페이지로 이동
if (!state.user && path === "/profile") {
root.innerHTML = LoginPage();
return;
}

// 로그인 사용자는 로그인 페이지 접근 불가 → 메인 페이지로 이동
if (state.user && path === "/login") {
root.innerHTML = HomePage();
return;
}

Choose a reason for hiding this comment

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

렌더링 뿐만 아니라 라우트도 실제로 바꿔야할 것 같습니다!

Copy link
Author

Choose a reason for hiding this comment

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

어우.. 고작 한 주인데 왜 이렇게 코드가 부끄럽나요..!

라우트를 변경하는 것은 handleNavigation 함수에서 다루고 있었어요
그래서 handleNavigation 실행 => Navigate To 실행 => 라우트 변경 => 렌더링 변경 이렇게 코드를 짜놨네요......😃🔫...으악... 라우터를 다시 한 번 들여다 볼 수 있는 기회를 주셔서 감사함다......🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants