-
Notifications
You must be signed in to change notification settings - Fork 77
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
[2팀 노정우] [Chapter 1-1] 프레임워크 없이 SPA 만들기 #36
Open
melroh629
wants to merge
8
commits into
hanghae-plus:main
Choose a base branch
from
melroh629:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
17c44b7
README 추가
melroh629 b072547
모듈 분리
melroh629 c667e81
fix: 프로필 페이지 변경
melroh629 8ebf1db
모듈 분리
melroh629 6e1869a
컴포넌트 분리
melroh629 31abf23
로그인 로직 변경
melroh629 5373a8d
Merge branch 'dev'
melroh629 928448c
router파일 수정
melroh629 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
## 과제 체크포인트 | ||
|
||
### 기본과제 | ||
|
||
#### 1) 라우팅 구현: | ||
|
||
- [x] History API를 사용하여 SPA 라우터 구현 | ||
- [x] '/' (홈 페이지) | ||
- [x] '/login' (로그인 페이지) | ||
- [x] '/profile' (프로필 페이지) | ||
- [x] 각 라우트에 해당하는 컴포넌트 렌더링 함수 작성 | ||
- [x] 네비게이션 이벤트 처리 (링크 클릭 시 페이지 전환) | ||
- [x] 주소가 변경되어도 새로고침이 발생하지 않아야 한다. | ||
|
||
#### 2) 사용자 관리 기능: | ||
|
||
- [x] LocalStorage를 사용한 간단한 사용자 데이터 관리 | ||
- [x] 사용자 정보 저장 (이름, 간단한 소개) | ||
- [x] 로그인 상태 관리 (로그인/로그아웃 토글) | ||
- [x] 로그인 폼 구현 | ||
- [x] 사용자 이름 입력 및 검증 | ||
- [x] 로그인 버튼 클릭 시 LocalStorage에 사용자 정보 저장 | ||
- [x] 로그아웃 기능 구현 | ||
- [x] 로그아웃 버튼 클릭 시 LocalStorage에서 사용자 정보 제거 | ||
|
||
#### 3) 프로필 페이지 구현: | ||
|
||
- [x] 현재 로그인한 사용자의 정보 표시 | ||
- [x] 사용자 이름 | ||
- [x] 간단한 소개 | ||
- [x] 프로필 수정 기능 | ||
- [x] 사용자 소개 텍스트 수정 가능 | ||
- [x] 수정된 정보 LocalStorage에 저장 | ||
|
||
#### 4) 컴포넌트 기반 구조 설계: | ||
|
||
- [ ] 재사용 가능한 컴포넌트 작성 | ||
- [ ] Header 컴포넌트 | ||
- [ ] Footer 컴포넌트 | ||
- [x] 페이지별 컴포넌트 작성 | ||
- [x] HomePage 컴포넌트 | ||
- [x] ProfilePage 컴포넌트 | ||
- [x] NotFoundPage 컴포넌트 | ||
|
||
#### 5) 상태 관리 초기 구현: | ||
|
||
- [ ] 간단한 상태 관리 시스템 설계 | ||
- [ ] 전역 상태 객체 생성 (예: 현재 로그인한 사용자 정보) | ||
- [ ] 상태 변경 함수 구현 | ||
- [ ] 상태 업데이트 시 관련 컴포넌트 리렌더링 | ||
|
||
#### 6) 이벤트 처리 및 DOM 조작: | ||
|
||
- [ ] 사용자 입력 처리 (로그인 폼, 프로필 수정 등) | ||
- [ ] 동적 컨텐츠 렌더링 (사용자 정보 표시, 페이지 전환 등) | ||
|
||
#### 7) 기본적인 에러 처리: | ||
|
||
- [ ] 잘못된 라우트 접근 시 404 페이지 표시 | ||
- [ ] 로그인 실패 시 에러 메시지 표시 | ||
|
||
### 심화과제 | ||
|
||
#### 1) 해시 라우터 구현 | ||
|
||
- [ ] location.hash를 이용하여 SPA 라우터 구현 | ||
- [ ] '/#/' (홈 페이지) | ||
- [ ] '/#/login' (로그인 페이지) | ||
- [ ] '/#/profile' (프로필 페이지) | ||
|
||
#### 2) 라우트 가드 구현 | ||
|
||
- [ ] 로그인 상태에 따른 접근 제어 | ||
- [ ] 비로그인 사용자의 특정 페이지 접근 시 로그인 페이지로 리다이렉션 | ||
|
||
#### 3) 이벤트 위임 | ||
|
||
- [ ] 이벤트 위임 방식으로 이벤트를 관리하고 있다. | ||
|
||
## 과제 셀프회고 | ||
|
||
<!-- 과제에 대한 회고를 작성해주세요 --> | ||
|
||
### 기술적 성장 | ||
|
||
<!-- 예시 | ||
- 새로 학습한 개념 | ||
- 기존 지식의 재발견/심화 | ||
- 구현 과정에서의 기술적 도전과 해결 | ||
--> | ||
|
||
### 코드 품질 | ||
|
||
<!-- 예시 | ||
- 특히 만족스러운 구현 | ||
- 리팩토링이 필요한 부분 | ||
- 코드 설계 관련 고민과 결정 | ||
--> | ||
|
||
### 학습 효과 분석 | ||
|
||
<!-- 예시 | ||
- 가장 큰 배움이 있었던 부분 | ||
- 추가 학습이 필요한 영역 | ||
- 실무 적용 가능성 | ||
--> | ||
|
||
### 과제 피드백 | ||
|
||
<!-- 예시 | ||
- 과제에서 모호하거나 애매했던 부분 | ||
- 과제에서 좋았던 부분 | ||
--> | ||
|
||
## 리뷰 받고 싶은 내용 | ||
|
||
<!-- | ||
피드백 받고 싶은 내용을 구체적으로 남겨주세요 | ||
모호한 요청은 피드백을 남기기 어렵습니다. | ||
|
||
참고링크: https://chatgpt.com/share/675b6129-515c-8001-ba72-39d0fa4c7b62 | ||
|
||
모호한 질문의 예시) | ||
- 무엇을 질문해야 할지 몰라서 코치님이 보시기에 고쳐야할것들 전반적으로 피드백 부탁드립니다. | ||
- 코드 스타일에 대한 피드백 부탁드립니다. | ||
- 코드 구조에 대한 피드백 부탁드립니다. | ||
- 개념적인 오류에 대한 피드백 부탁드립니다. | ||
- 추가 구현이 필요한 부분에 대한 피드백 부탁드립니다. | ||
|
||
구체적인 질문의 예시) | ||
- 파일A의 함수B와 그 안의 변수명을 보면 직관성이 떨어지는 것 같습니다. 함수와 변수 이름을 더 명확하게 지을 방법에 대해 조언해 주실 수 있나요? | ||
- 현재 파일 단위로 코드를 분리했지만, 이번 주차 발제를 기준으로 봤을 때 모듈화나 계층화에서 부족함이 있는 것 같습니다. 특히 A와 B 부분에서 모듈화를 더 진행할지 그대로 둘지 고민하였습니다. (...구체적인 고민 사항 적기...). 코치님의 의견이 궁금합니다. | ||
- 옵저버 패턴을 사용해 상태 관리 로직을 구현해 보려 했습니다. 제가 구현한 코드가 옵저버 패턴에 맞게 잘 구성되었는지 검토해 주시고, 보완할 부분을 제안해 주실 수 있을까요? | ||
- 컴포넌트 A를 테스트 할 때 B와의 의존성 때문에 테스트 코드를 작성하려다 포기했습니다. A와 B의 의존성을 낮추고 테스트 가능성을 높이는 구조 개선 방안이 있을까요? | ||
--> |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,5 +42,8 @@ | |
"prettier": "^3.4.2", | ||
"vite": "^6.0.3", | ||
"vitest": "^2.1.8" | ||
}, | ||
"dependencies": { | ||
"playwright": "^1.49.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export const Footer = () => { | ||
const template = ` | ||
<footer class="bg-gray-200 p-4 text-center"> | ||
<p>© 2024 항해플러스. All rights reserved.</p> | ||
</footer> | ||
`; | ||
|
||
const init = () => { | ||
console.log("Footer init"); | ||
}; | ||
|
||
return { template, init }; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { router } from "../router/router.js"; | ||
import { userStore } from "../store/userStore.js"; | ||
|
||
const navItems = [ | ||
{ label: "홈", path: "/" }, | ||
{ label: "프로필", path: "/profile" }, | ||
{ label: "로그아웃", path: "/", action: "logout", authRequired: true }, | ||
{ label: "로그인", path: "/login", guestOnly: true }, | ||
]; | ||
|
||
export const Header = () => { | ||
const getNavItems = () => { | ||
const isLoggedIn = userStore.isLogin(); | ||
return navItems.filter((item) => { | ||
if (item.authRequired && !isLoggedIn) return false; | ||
if (item.guestOnly && isLoggedIn) return false; | ||
return true; | ||
}); | ||
}; | ||
|
||
const template = ` | ||
<header class="bg-blue-600 text-white p-4 sticky top-0"> | ||
<h1 class="text-2xl font-bold">항해플러스</h1> | ||
</header> | ||
<nav class="bg-white shadow-md p-2 sticky top-14"> | ||
<ul class="flex justify-around"> | ||
${getNavItems() | ||
.map( | ||
(item) => ` | ||
<li> | ||
<a href="${item.path}" | ||
${item.action ? `data-action="${item.action}"` : ""} | ||
class="text-gray-600" | ||
>${item.label}</a> | ||
</li> | ||
Comment on lines
+30
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PR에 리뷰 받고 싶은내용 중 테스트 통과가 되지 않는다고 하셔서 살펴보는데 자세히 더 살펴보고 싶은데 시간이 부족해서 아쉽네요 ㅠㅠㅠ // basic.test.js
const logoutButton = document.getElementById("logout");
logoutButton.click();
expect(localStorage.getItem("user")).toEqual(null); |
||
`, | ||
) | ||
.join("")} | ||
</ul> | ||
</nav> | ||
`; | ||
|
||
const init = () => { | ||
const nav = document.querySelector("nav"); | ||
if (nav) { | ||
nav.addEventListener("click", (e) => { | ||
if (e.target.tagName === "A") { | ||
e.preventDefault(); | ||
const path = e.target.getAttribute("href"); | ||
const action = e.target.dataset.action; | ||
|
||
if (action === "logout") { | ||
userStore.logout(); | ||
router.navigate("/"); | ||
return; | ||
} | ||
|
||
if (path === "/profile" && !userStore.isLogin()) { | ||
alert("로그인이 필요한 서비스입니다."); | ||
router.navigate("/login"); | ||
return; | ||
} | ||
|
||
router.navigate(path); | ||
} | ||
}); | ||
} | ||
}; | ||
|
||
return { template, init }; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from "./Header.js"; | ||
export * from "./Footer.js"; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
헤더에서 로그인 여부에 따른 각 네비게이션 노출을 이렇게 관리하니 직관적이고 좋은것 같습니다 👍👍
data-set에 action을 통해 로그아웃을 처리하는 부분도 좋아요 배워갑니다 ㅎㅎㅎ