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

[Mission5/김효리] Project_Notion_VanillaJs 과제 #53

Open
wants to merge 107 commits into
base: 4/#5_kimhyori
Choose a base branch
from

Conversation

hyoribogo
Copy link
Member

@hyoribogo hyoribogo commented Jul 6, 2023


🔗 배포 링크

image

📌 과제 설명

기본 요구사항

  • 글 단위를 Document라고 합니다. Document는 Document 여러개를 포함할 수 있습니다.
  • 화면 좌측에 Root Documents를 불러오는 API를 통해 루트 Documents를 렌더링합니다.
    • Root Document를 클릭하면 오른쪽 편집기 영역에 해당 Document의 Content를 렌더링합니다.
    • 해당 Root Document에 하위 Document가 있는 경우, 해당 Document 아래에 트리 형태로 렌더링 합니다.
    • Document Tree에서 각 Document 우측에는 + 버튼이 있습니다. 해당 버튼을 클릭하면, 클릭한 Document의 하위 Document로 새 Document를 생성하고 편집화면으로 넘깁니다.
  • 편집기에는 기본적으로 저장 버튼이 없습니다. Document Save API를 이용해 지속적으로 서버에 저장되도록 합니다.
  • History API를 이용해 SPA 형태로 만듭니다.
    • 루트 URL 접속 시엔 별다른 편집기 선택이 안 된 상태입니다.
    • /documents/{documentId} 로 접속시, 해당 Document 의 content를 불러와 편집기에 로딩합니다.

보너스 요구사항

  • 기본적으로 편집기는 textarea 기반으로 단순한 텍스트 편집기로 시작하되, 여력이 되면 div와 contentEditable을 조합해서 좀 더 Rich한 에디터를 만들어봅니다.
  • 편집기 최하단에는 현재 편집 중인 Document의 하위 Document 링크를 렌더링하도록 추가합니다.
  • 편집기 내에서 다른 Document name을 적은 경우, 자동으로 해당 Document의 편집 페이지로 이동하는 링크를 거는 기능을 추가합니다.
  • 그외 개선하거나 구현했으면 좋겠다는 부분이 있으면 적극적으로 구현해봅니다!

👩‍💻 요구 사항과 구현 내용

시간이 많이 부족해서 기본 구현만 다 했습니다. 이후에도 계속 수정해서 업데이트 하겠습니다!

구현 완료

  • vite, eslint, prettier, jest 등 초기 세팅을 했습니다.
  • 로컬 스토리지를 통해 토글 상태를 저장하고, 이를 반영합니다.
  • 상태는 한꺼번에 관리하지 않고, 사이드바와 에디터 두 개로 나누어서 관리합니다.
  • App.js, 페이지, 컴포넌트 파일에서 각각 상태를 전달하고 업데이트하기 위해 함수를 분리해 구현했습니다.
    • App.js는 상태 관리를 하고, 라우팅을 처리해줍니다.
    • MainPage.js에서는 이벤트와 업데이트 된 상태를 전달합니다.
    • 각 컴포넌트 파일에서는 dom과 dom 이벤트를 관리합니다.
  • 불필요한 브라우저 렌더링을 방지하려고 노력했습니다.
    • 토글 되어있는 리스트들만 렌더링을 합니다.
    • 링크 이동이나 이벤트 발생 시, 업데이트가 필요한 부분(사이드바 혹은 에디터)만 렌더링 합니다.
  • 불필요한 네트워크 요청을 줄였습니다.
    • 초반에 토글만 눌러도 데이터를 다시 받아와 비효율적이었습니다. 이후에는 토글 이벤트는 요청을 하지 않도록 했습니다.
    • 해당 링크에 있을 때 삭제하면 데이터를 전부 받아오지만, 해당 id가 아닌 문서 삭제 시 사이드바 데이터만 다시 받아오도록 했습니다.
    • 데이터 요청도 상태관리와 똑같이 두 개의 케이스로 나누어서 요청을 보내도록 구현했습니다.
  • html 템플릿 함수를 구현해서 적용했습니다.
  • vercel 배포와 라우트 환경 설정했습니다.
  • vite 환경 변수 설정 후 storage key와 api endpoint에 적용했습니다.
  • 낙관적 업데이트 (에디터에서 title 수정하면 사이드바 title도 바로 바뀌도록)
  • 자동저장 관련 로컬스토리지 삭제
  • 에디터 저장 시 focus 문제 해결
  • css 미흡한 부분들
  • 에디터에서는 api 요청 보내지 않도록 수정
  • utils 폴더에서 불필요한 파일들 다 분리하기
  • 404 페이지 디자인 + 기능
  • 유효성 검사 함수 추가
  • jest 테스트 코드 작성

아직 구현 못한 기능들 + 추가로 하고싶은 기능들

체감 난이도 ⭐로 표시

  • document url로 이동 시 사이드바 해당 리스트 더 진하게 적용 .. (눌렸다는 표시) ⭐⭐⭐⭐⭐

✅ 피드백 반영사항

(추후 수정)

✅ PR 포인트 & 궁금한 점

  • 며칠 동안 밤새면서 구현했는데 아직 못한 부분들이 많습니다. 시간 관리를 어떤 식으로 해야할지 궁금합니다 ..
  • 디렉토리 구조가 이상한 부분이 있다면 알려주셨으면 좋겠습니다.
  • 코드가 지저분해 보이거나 꼭 수정했으면 좋을 부분들도 말씀해 주세요!
  • 클래스로 구현하고 싶었는데, 아직 클래스 개념이 익숙치 않아 적용하지 못했습니다. 클래스로 구현했다면 더 추상화가 잘 되었을지 궁금합니다.
  • 이후 어떤 방향으로 수정하면 좋을지 궁금합니다 .... 감사합니다!

➕ 404 페이지를 구현하기 위해 에러 전파를 마구마구 했는데, 코드가 엄청 지저분해졌습니다 ㅠ 이를 해결할 때 어떻게 해야할지 궁금합니다.

vite, eslint, prettier, jest 적용
메인 페이지가 notionPage이고, 다른 페이지가 존재하지 않으므로 App.js에 모두 구현하도록 변경
Comment on lines +71 to +101
.documents .document {
padding-left: 5px;
}

.documents .depth1 {
padding-left: 15px;
}

.documents .depth1 p {
width: 125px;
}

.documents .depth2 {
padding-left: 25px;
}

.documents .depth2 p {
width: 115px;
}

.documents .depth3 {
padding-left: 35px;
}

.documents .depth3 p {
width: 105px;
}

.documents .depth4 {
padding-left: 45px;
}
Copy link

Choose a reason for hiding this comment

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

scss나 postcss를 사용했으면 좋았을 것 같아용

src/api/api.js Outdated
Comment on lines 3 to 4
const request = async (url = '', options = {}) => {
const res = await fetch(`${ENV.API_END_POINT}${url}`, {
Copy link

Choose a reason for hiding this comment

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

url보단 pathname과 같은 명명이 좋지 않을까 싶어요~!

])
return { documents, content }
default:
return null
Copy link

Choose a reason for hiding this comment

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

있을 수 없는 케이스라면 throw를 하면 어떨까 싶어요~!

// editor
export function contentTemplate({ content, documents }) {
let html = `<textarea placeholder='새로 글을 작성해 보세요.'>${
content ? content : ''
Copy link

Choose a reason for hiding this comment

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

content || ''로 작성할 수 있을 것 같네요~


function renderDocument({ id, title, documents }, depth) {
const toggleState = getItem(ENV.TOGGLE_STATE_SAVE_KEY)
const isToggled = toggleState?.[id] ? 'open' : ''
Copy link

Choose a reason for hiding this comment

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

boolean값을 가질 것 같은 변수인데 string 값이 대응되네욤
boolean값으로 처리되고 이 변수를 사용하는 쪽에서 대응되면 좋을 것 같습니다:-)


expect(() => {
TestComponent()
}).toThrow('TestComponent 컴포넌트 생성 시 new 연산자를 붙이지 않았습니다.')
Copy link

Choose a reason for hiding this comment

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

에러메시지를 상수화 해서 validation에서 같이 export 하면 좋을 것 같네요ㅎㅎ

vite.config.js Outdated
@@ -0,0 +1,5 @@
export default {
build: {
target: 'es2015',
Copy link

Choose a reason for hiding this comment

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

css 처리를 위해 구체적인 정의를 하면 좋을 것 같아요~

<head>
<meta charset="utf-8" />
<title>효리의 노션 클로닝 사이트</title>
<link rel="stylesheet" type="text/css" href="/styles/style.css" />
Copy link

Choose a reason for hiding this comment

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

스타일을 js 내에서 import 하는 방식도 고려하면 좋을 것 같습니다

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

Successfully merging this pull request may close these issues.

7 participants