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

[1주차] 강다혜 미션 제출합니다. #5

Open
wants to merge 72 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
bcfcb93
docs: make feature list
psst54 Sep 5, 2024
9b52a99
chore: add prettier config
psst54 Sep 5, 2024
2ffbddf
chore: add gitignore
psst54 Sep 5, 2024
a247959
Merge pull request #1 from psst54/feature/setup
psst54 Sep 5, 2024
810a850
feat: make HTML structure
psst54 Sep 5, 2024
2a32b4f
chore: reorganize project directory structure & add reset.css
psst54 Sep 5, 2024
4efb3f6
style: write css files to style entire page
psst54 Sep 5, 2024
c451d18
Merge pull request #2 from psst54/feature/basic-layout
psst54 Sep 5, 2024
868e2af
feat: define basic subject, task model
psst54 Sep 5, 2024
56b80ad
feat: render subject card
psst54 Sep 5, 2024
5e17bce
feat: render subject tasks
psst54 Sep 5, 2024
7c45c22
docs: edit terms
psst54 Sep 5, 2024
424a4a7
Merge pull request #3 from psst54/feature/class-definitions
psst54 Sep 5, 2024
7f85572
feat: make add subject button
psst54 Sep 5, 2024
85242f1
chore: rename component
psst54 Sep 5, 2024
16f8fd7
feat: add new subject
psst54 Sep 5, 2024
a8ce087
feat: add in-progress column
psst54 Sep 5, 2024
d9542b3
refactor: change subjectList to map
psst54 Sep 5, 2024
503ed8c
Merge pull request #4 from psst54/feature/add-subject
psst54 Sep 5, 2024
8f289c2
feat: make remove button
psst54 Sep 5, 2024
7cf1077
feat: remove subject
psst54 Sep 6, 2024
b0c5e6a
chore: rename variable for clarity
psst54 Sep 6, 2024
c162e6d
Merge pull request #5 from psst54/feature/delete-subject
psst54 Sep 6, 2024
c259475
Merge remote-tracking branch 'origin/master' into refactor/class-priv…
psst54 Sep 6, 2024
5504925
chore: set class properties to private
psst54 Sep 6, 2024
2d4a796
chore: change variable names for clarity
psst54 Sep 6, 2024
a654df1
chore: set class methods to private
psst54 Sep 6, 2024
b68de26
chore: add constant string
psst54 Sep 6, 2024
bf526f7
dcos: add comments
psst54 Sep 6, 2024
132e3b2
Merge pull request #6 from psst54/refactor/class-private-properties
psst54 Sep 6, 2024
0d03723
feat: add task input form
psst54 Sep 6, 2024
a4da6c5
feat: add submit event handler to add task
psst54 Sep 6, 2024
f98becd
feat: fix task style
psst54 Sep 6, 2024
f644949
refactor: change method
psst54 Sep 6, 2024
0ce7230
Merge pull request #7 from psst54/feature/add-task
psst54 Sep 6, 2024
c4c4478
refactor: make createElement function
psst54 Sep 6, 2024
5dc3e9f
refactor: improve taskViewModel
psst54 Sep 6, 2024
3403d08
Merge pull request #8 from psst54/refactor/codebase
psst54 Sep 6, 2024
5524c18
style: edit subject add button
psst54 Sep 6, 2024
d4183ba
Merge pull request #9 from psst54/feature/add-subject
psst54 Sep 6, 2024
a4ab27b
feat: add button to delete task
psst54 Sep 6, 2024
dd985b6
Merge remote-tracking branch 'origin/master' into feature/delete-task
psst54 Sep 6, 2024
00b7815
feat: add delete event handler
psst54 Sep 6, 2024
2c96c51
Merge pull request #10 from psst54/feature/delete-task
psst54 Sep 6, 2024
d045049
feat: add change event handler to checkbox & isCompleted prop to Task…
psst54 Sep 6, 2024
b47174a
feat: toggle task
psst54 Sep 6, 2024
39a9724
feat: add custom event to re-render
psst54 Sep 6, 2024
b89fb7a
refactor: edit constructor props
psst54 Sep 6, 2024
4a25022
refactor: remove useless prop
psst54 Sep 6, 2024
b332485
refactor: add string constant
psst54 Sep 6, 2024
9fcc04a
refactor: remove useless prop
psst54 Sep 6, 2024
7eae8e6
refactor: add getRandomId function
psst54 Sep 6, 2024
5f3b90e
Merge pull request #11 from psst54/feature/toggle-state
psst54 Sep 6, 2024
35dc943
fix: fix function call with wrong props
psst54 Sep 6, 2024
842f675
docs: add comment for constant
psst54 Sep 6, 2024
eb9ef18
chore: rename css file
psst54 Sep 6, 2024
1e0c467
fix: edit css file
psst54 Sep 6, 2024
1ba6be6
refactor: split functions in subjectViewModel
psst54 Sep 6, 2024
7fdc9f7
docs: add comment & jsdoc
psst54 Sep 6, 2024
9c70161
style: add form width
psst54 Sep 6, 2024
ee16790
feat: show title date
psst54 Sep 6, 2024
5ae4943
chore: rename setIsCompleted method
psst54 Sep 6, 2024
4983c45
docs: add comment for createElement function
psst54 Sep 6, 2024
40e8b36
style: change styles
psst54 Sep 6, 2024
37e1af8
refactor: dispatchTaskChangeEvent function
psst54 Sep 6, 2024
75ca24e
chore: rename function and variables & add comments
psst54 Sep 6, 2024
ebbc851
refactor: refactor taskViewModel
psst54 Sep 6, 2024
ada47c8
Merge pull request #12 from psst54/refactor/codebase
psst54 Sep 6, 2024
2fe4a0d
hotfix: fix missing prop issue in function call
psst54 Sep 6, 2024
d9679ef
hotfix: remove subject form in in-progress, done column
psst54 Sep 7, 2024
2727fb9
docs: write readme
psst54 Sep 7, 2024
5660245
Merge pull request #13 from psst54/master
psst54 Sep 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.vscode
12 changes: 12 additions & 0 deletions .prettierrc
Copy link

Choose a reason for hiding this comment

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

prettier로 작성한 코드를 보기 좋게, 또 일관성 있게 포맷팅을 해주는 작업 해주신 게 좋은 거 같아요 ! 저도 다음에는 prettier 설정 파일을 사용해보겠습니다

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
"bracketSpacing": true,
"arrowParens": "always",
"htmlWhitespaceSensitivity": "css",
"cssWhitespaceSensitivity": "css"
}
80 changes: 37 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,54 @@
# 1주차 미션: Vanilla-Todo

# 서론
# 결과물

안녕하세요 🙌🏻 20기 프론트엔드 운영진 **이지인**입니다.
배포 링크 :
https://vanilla-todo-20th-lovat.vercel.app/

이번 미션은 개발 환경 구축과 스터디 진행 방식에 익숙해지실 수 있도록 간단한 **to-do list** 만들기를 진행합니다. 무작정 첫 스터디부터 React를 다루는 것보다는 왜 React가 필요한지, React가 없으면 무엇이 불편한지 느껴 보고 본격적인 스터디에 들어가는 것이 React를 이해하는 데 더 많은 도움이 될 것이라 생각합니다.
## 기능 구현

비교적 가벼운 미션인 만큼 코드를 짜는 데 있어 여러분의 **창의성**을 충분히 발휘해 보시기 바랍니다. 작동하기만 하면 되는 것보다 같은 코드를 짜는 여러가지 방식과 패턴에 대해 고민해 보시고, 본인이 생각한 가장 창의적인 방법으로 코드를 작성해 주세요. 여러분이 미션을 수행하는 과정에서 겪는 고민과 생각의 깊이만큼 스터디에서 더 많은 것을 얻어가실 수 있을 것입니다.
- Open, In Progress, Done column별로 목표를 확인할 수 있다.
- 각 Column에서 input field를 통해 새로운 목표를 추가할 수 있다.
- 목표는 X 버튼을 통해서 삭제할 수 있다.
- 목표 내에서 input field를 통해 새로운 할 일을 추가할 수 있다.
- 할 일은 삭제 버튼을 통해서 삭제할 수 있다.
- 할 일 요소의 체크박스틀 통해 할 일을 완료/해제할 수 있다.

막히는 부분이 있더라도 우선은 스스로 공부하고 찾아보는 방법을 권고드리지만, 운영진의 도움이 필요하시다면 얼마든지 프론트엔드 카톡방에 편하게 질문을 남겨 주세요!
# Key Questions

# 미션
## DOM은 무엇인가요?

## 미션 목표
DOM(Document Object Model)은 HTML 또는 XML 문서의 구조를 표현하는 인터페이스로, 프로그래밍 언어가 DOM 구조에 접근할 수 있는 방법을 제공합니다.

- VSCode, Prettier를 이용하여 개발 환경을 관리합니다.
- HTML/CSS의 기초를 이해합니다.
- JavaScript를 이용한 DOM 조작을 이해합니다.
- Vanilla Js를 이용한 어플리케이션 상태 관리 방법을 이해합니다.
예를 들어서, JS라는 프로그래밍 언어로 HTML 문서의 구조, 스타일, 내용을 변경할 수 있습니다.

## 기한
 

- 2024년 9월 7일 토요일
HTML 문서가 있다면, 브라우저는 HTML 문서를 읽어들이고 HTML의 각 요소(element)를 Node라는 객체로 표현합니다. `<h1>`~`<h6>` 태그는 `HTMLHeadingElement` 객체로, `<p>`는 `HTMLParagraphElement` 객체로 표현하며, 이런 `HTMLElement` 인터페이스를 통해서 HTML의 element를 수정할 수 있습니다.

## Key Questions
## 이벤트 흐름 제어(버블링 & 캡처링)이 무엇인가요?

- DOM은 무엇인가요?
- 이벤트 흐름 제어(버블링 & 캡처링)이 무엇인가요?
- 클로저와 스코프가 무엇인가요?
- **이벤트 버블링**이란, HTML 문서에서 이벤트가 발생했을 때, 하위 element에서부터 상위 element로 이벤트가 전달되는 방식입니다.
- **이벤트 캡처링**이란, HTML 문서에서 이벤트가 발생했을 때, 하위 element까지 이벤트가 전달되는 방식입니다.
- 이벤트는 캡처링 단계, 타깃 단계, 버블링 단계를 거칩니다.
- **캡처링 단계**에서는 이벤트가 최상위 조상(window또는 document)에서부터 하위 element로 전달됩니다. 기본적으로 캡처링 단계에서는 이벤트 핸들러가 실행되지 않지만, 이벤트 핸들러에 옵션을 주어 이 단계에서 이벤트를 핸들링할 수 있습니다.
- **타깃 단계**에서는 이벤트가 실제 타깃 요소에 전달됩니다. 이벤트가 타깃 element에 도착하면 타깃 element에 부착된 이벤트 핸들러가 동작합니다.
- **버블링 단계**에서는 이벤트가 상위 element로 전달됩니다. `focus`, `blur` 등의 일부 이벤트는 버블링 단계를 거치지 않습니다.

## 필수 요건
## 클로저와 스코프가 무엇인가요?

- [결과 화면](https://vanilla-todo-19th-dh.vercel.app/)의 기능을 구현합니다. (날짜, 요일별 todo 개수)
- 결과 링크의 화면 디자인 그대로 구현해도 좋고, 자신만의 디자인을 적용해도 좋습니다.
- CSS의 Flexbox를 이용하여 레이아웃을 구성합니다.
- JQuery, React, Bootstrap 등 외부 라이브러리를 사용하지 않습니다.
- 함수와 변수의 이름은 lowerCamelCase로 짓습니다.
- 코딩의 단위를 기능별로 나누어 Commit 메세지를 작성합니다.
- Semantic tag를 활용하여 HTML 구조를 완성합니다.
- 스코프는 값과 표현식이 참조될 수 있는 컨텍스트를 의미합니다.
- 하위 스코프에서는 상위 스코프에 접근할 수 있지만, 상위 스코프에서는 하위 스코프에 접근할 수 없습니다.
- JS에는 3가지 종류의 스코프가 있습니다.
- Global scope(전역 스코프)
- Module scope(모듈 스코프)
- Function scope(함수 스코프)
- Block scope(블록 스코프)
- 클로저는 함수와 그 함수가 선언될 때의 lexical environment의 조합입니다. 함수가 생성될 때마다 클로저도 생성되며, 함수는 클로저를 통해 자신이 선언된 시점의 lexical environment(변수나 함수들)을 참조할 수 있습니다.

## 선택 요건
## 참고

- 외부 폰트 Pretendard를 적용합니다.
- 브라우저의 `localStorage` 혹은 `sessionStorage`를 이용하여 다음 번 접속 시에 기존의 투두 데이터를 불러옵니다.
- 이 외에도 추가하고 싶은 기능이 있다면 마음껏 추가하셔도 됩니다.
- 미디어쿼리를 이용해서 반응형을 적용합니다.

# 링크 및 참고자료

- [HTML/CSS 기초](https://heropy.blog/2019/04/24/html-css-starter/)
- [HTML 태그](https://heropy.blog/2019/05/26/html-elements/)
- [FlexBox 가이드](https://heropy.blog/2018/11/24/css-flexible-box/)
- [JS를 통한 DOM 조작](https://velog.io/@bining/javascript-DOM-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0#append)
- [localStorage, sessionStorage](https://www.daleseo.com/js-web-storage/)
- [git 사용법](https://wayhome25.github.io/git/2017/07/08/git-first-pull-request-story/)
- [좋은 코드리뷰 방법](https://tech.kakao.com/2022/03/17/2022-newkrew-onboarding-codereview/)
- [MDN 공식문서-createElement()](https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement)
- [MDN 공식문서-appendChild()](https://developer.mozilla.org/ko/docs/Web/API/Node/appendChild)
- [DOM 개념,HTML 요소 조작](https://poiemaweb.com/js-dom#3-dom-query--traversing-%EC%9A%94%EC%86%8C%EC%97%90%EC%9D%98-%EC%A0%91%EA%B7%BC)
- https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction
- https://ko.javascript.info/bubbling-and-capturing
- https://developer.mozilla.org/en-US/docs/Glossary/Scope
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
5 changes: 5 additions & 0 deletions assets/addIcon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions assets/deleteIcon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions css/global.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
* {
color: var(--text-color);
}

body {
background-color: var(--background);
}

h1 {
font-size: 4rem;

color: transparent;
-webkit-text-stroke: 1px var(--text-color);
}

form {
display: flex;
gap: 0.5rem;
width: 100%;
}

input[type='text'] {
flex: 1;

background: transparent;

border: none;
border-bottom: 1px solid var(--border);
outline: none;
}
73 changes: 73 additions & 0 deletions css/kanban.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
.wrapper {
display: flex;
justify-content: center;
}

.container {
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;

padding: 2rem;
width: 100%;
max-width: 1200px;
}

.kanban-board {
display: flex;
gap: 1rem;

width: 100%;
}

.kanban-board section {
display: flex;
flex-direction: column;
gap: 1rem;

flex: 1;

height: fit-content;
padding: 1rem;

border: 3px solid;
border-radius: 1rem;
}

@media (max-width: 1000px) {
.container {
max-width: 600px;
}

.kanban-board {
flex-direction: column;
}
}

#open-column {
background-color: var(--open-column-background);
border-color: var(--open-column-border);
}

#in-progress-column {
background-color: var(--in-progress-column-background);
border-color: var(--in-progress-column-border);
}

#done-column {
background-color: var(--done-column-background);
border-color: var(--done-column-border);
}

.open-hr {
border: 1px solid var(--open-column-border);
}

.in-progress-hr {
border: 1px solid var(--in-progress-column-border);
}

.done-hr {
border: 1px solid var(--done-column-border);
}
14 changes: 14 additions & 0 deletions css/reset.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* 기본 margin, padding 제거 */
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}

/* 리스트 스타일 제거 */
ul,
ol {
list-style: none;
}
33 changes: 33 additions & 0 deletions css/subject.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.subject-list {
display: flex;
flex-direction: column;
gap: 1rem;
}

.subject {
padding: 1rem;

background: var(--subject-background);

border: 2px solid var(--border);
border-radius: 1rem;
}

.subject header {
display: flex;
justify-content: space-between;
}

.add-subject-card button,
.delete-subject-button {
background: transparent;
border: none;
outline: none;
cursor: pointer;
}

.add-subject-card button img,
.delete-subject-button img {
width: 2rem;
height: 2rem;
}
34 changes: 34 additions & 0 deletions css/task.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
.task-list {
display: flex;
flex-direction: column;
gap: 0.5rem;
}

.task-list button {
padding: 0.25rem 0.5rem;
background: transparent;

border: 1px solid var(--button-border);
border-radius: 1rem;
outline: none;

color: var(--text-color);
white-space: nowrap;

cursor: pointer;
}

.task {
display: flex;
align-items: center;
gap: 0.5rem;
}

.task p {
flex: 1;
}

.isCompleted > p {
color: var(--cancel-text-color);
text-decoration: line-through;
}
18 changes: 18 additions & 0 deletions css/variables.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
:root {
Copy link

Choose a reason for hiding this comment

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

미리 theme화 시켜서 자주 쓰는 색깔을 지정해 주신게 많이 고민하신 것 같다는 생각이 들어요!

--background: #121212;

--open-column-background: #31627e1a;
--in-progress-column-background: #7267451a;
--done-column-background: #2a5f2d1a;
--open-column-border: #0d5580;
--in-progress-column-border: #785e17;
--done-column-border: #0b5c18;

--subject-background: #121212ee;

--text-color: #ffffff;
--cancel-text-color: #505050;

--border: #505050;
--button-border: #ffffff;
}
Comment on lines +1 to +18

Choose a reason for hiding this comment

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

variable.css파일을 만들어주시고, 필요한 css 파일 여기저기에서 var()을 활용하여 시스템화 해주셨네요!
순수 css 만으로도 tailwindCSS의 디자인 시스템화 같은 방식을 볼 수 있어 좋았습니다.

45 changes: 41 additions & 4 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,14 +1,51 @@
<!DOCTYPE html>
<html lang="en">
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vanilla Todo</title>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="css/reset.css" />
<link rel="stylesheet" href="css/global.css" />
<link rel="stylesheet" href="css/kanban.css" />
<link rel="stylesheet" href="css/subject.css" />
<link rel="stylesheet" href="css/task.css" />
Comment on lines +9 to +11

Choose a reason for hiding this comment

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

스타일링을 전반적인 칸반, 목표를 담은 subject, subject 안의 각각의 아이템인 task 로 나누어서 모듈화를 해주셨네요! 👍

<link rel="stylesheet" href="css/variables.css" />

Choose a reason for hiding this comment

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

저도 궁금한 것이 있어 여쭤봅니다! 현재 여러 css 파일에서 사용되는 variable.css 파일이 가장 마지막 순서로 로드되고 있네요! 현재 프로젝트가 너무 잘 작동하고 있는데, 직관으로 생각해보면 마지막에 로드 되는 것이라 다른 css 파일에서 css 변수를 가져다 쓸 때 제대로 동작하지 않을 수도 있겠다는 생각이 듭니다.

혹시 이를 어떻게 해결하신지, 또는 어떻게 괜찮은지 설명해주실 수 있나요?

Copy link
Author

Choose a reason for hiding this comment

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

오잉.. 그냥 variable.css 파일을 나중에 만들어서 맨 뒤에 추가하게 되었는데요, 생각해보니 그런 문제가 있을 수 있겠네요😨
그래서 여러 군데 찾아보다가 결국 chatgpt한테 물어봤더니

CSS 변수(--variable-name)는 스타일시트의 파싱 중에 수집되며, 실제 값이 필요한 순간에만 참조됩니다. CSS 변수는 문서 전체의 파싱이 완료된 후 참조되기 때문에, 스타일시트 내 어디에서든지 사용이 가능합니다. 따라서 변수 정의가 앞서 있는지, 뒤에 있는지는 중요하지 않으며, 이는 브라우저가 CSS를 파싱하고 변수의 값을 나중에 참조하기 때문입니다.

라고는 하는데 적어준 출처에서는 그런 내용을 확인할 수 없었어요...! 지금은 시간이 없어서 다른 리뷰 다 보고 다시 돌아와서 확실히 알게 되면 다시 코멘트 드릴게요!

Comment on lines +7 to +12
Copy link

Choose a reason for hiding this comment

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

style을 많이 나누어주셨네요!!!
reset.css와 같은 경우는 global.css@import해놓는 것도 좋을 것 같습니당

Copy link
Author

Choose a reason for hiding this comment

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

아하 그건 생각 못했네요!! 아이디어 감사합니다😋😋

</head>

<body>
<div class="container"></div>
<div class="wrapper">
<div class="container">
<header>
<h1 id="title" class="title"></h1>
</header>

<div class="kanban-board">
<section class="board-column" id="open-column">
<h2>Open</h2>
<hr class="open-hr" />
<ul class="subject-list" id="open-subject-list"></ul>
</section>

<section class="board-column" id="in-progress-column">
<h2>In Progress</h2>
<hr class="in-progress-hr" />
<ul class="subject-list" id="in-progress-subject-list"></ul>
</section>

<section class="board-column" id="done-column">
<h2>Done</h2>
<hr class="done-hr" />
<ul class="subject-list" id="done-subject-list"></ul>
</section>
</div>
</div>
</div>
</body>
Comment on lines 15 to 43
Copy link

Choose a reason for hiding this comment

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

시맨틱 태그를 적절하게 잘 사용하셨네요! 👍🏻👍🏻

<script src="script.js"></script>
<script src="js/index.js"></script>
<script src="js/models/subject.js"></script>
<script src="js/models/task.js"></script>
<script src="js/viewModels/subjectViewModel.js"></script>
<script src="js/viewModels/taskViewModel.js"></script>
<script src="js/constant.js"></script>
<script src="js/utils/index.js"></script>
Comment on lines +44 to +50

Choose a reason for hiding this comment

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

html 문서가 parsing 되는 순서를 고려하여 js 파일을 body 태그 다음에 위치하여 모든 DOM 요소가 로드된 이후 js가 동작하도록 만들어주셨네요!

이 방법도 너무 좋고, script 태그의 defer 속성을 이용하시면 head 태그 내에 script 요소를 배치해도 될 것 같아요 관련 자료 첨부할게요 🙃

Copy link
Author

Choose a reason for hiding this comment

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

defer는 안 써봤는데 공부해볼게요!! 감사합니다 :)

</html>
Loading