처음 프로젝트를 시작했을 땐 당연히 advanced까지 과제를 모두 완료하는 것이었다.(😀) 하지만 폼을 제출했을 때 새로운 게시글(디스커션)이 올라가도록 하는 기능을 구현할 때 많이 헤매서 자연스럽게 'bare minimum이라도 완료하자!'로 목표가 바뀌었다.
구현해야 하는 Bare minimum 과제는
크게 이 세가지였는데, 특히나 세번째에서 시간을 너무 많이 썼다.
그래서 총 70% 정도 완료했다고 할 수 있겠다!
과제 시작 당일부터 과제를 제출한 분도 있었기 때문에 과제를 붙잡고 있는 시간이 길어지면 길어질 수록 의욕이 사그라들기도 했는데, 남들과 비교하면 안 되는 것을 뼈져리게 깨달았다. 이런 쓸데없는 비교를 타파하기 위해서 결국 깨부시지 못한 페이지네이션 기능 구현과, 로컬 스토리지 기능을 공부하고, 직접 구현해보는 것이 주말 공부가 될 예정이다.
아래는 내가 만들었던 수도 코드이다.
//폼에 텍스트를 입력한다.
//submit 버튼을 클릭한다.
//(이벤트 핸들러 사용)
// 폼에 입력된 정보가 빈 객체에 담긴다. (키와 값으로)
//이름 입력칸에 담긴 건 key 'author'에 담겨야 하고
//제목 입력칸에 담긴 건 key 'title'에 담겨야 한다.
//본문 입력칸에 담긴 것은 key 'bodyHTML'에 담겨야 한다.
// 배열인 agoraStatesDiscussions의 가장 뒤에 만들어진 객체가 더해진다.
//agoraStatesDiscussion.push('만들어진 객체')
일단 수도 코드 작성 자체가 세세하지 못한 것도 있었지만 특히 내가 간과했던 것들은
1. 빈 객체를 꼭 만들어야하나?
=> 빈 객체를 만들지 않고 더미 데이터에서 객체 형식을 빌려와서 사용할 수 있었다.
2. 폼은 제출할 경우 새로고침이 된다는 점.
=> 빈 객체를 만들어서도 데이터를 추가할 수 있었겠지만, 새로고침이 된다는 사실을 모르고 있어서 계속해서 제자리걸음을 했다.
3. 제출 후, 폼에 적혀있던 것이 깨끗하게 비워져야 한다는 점.(폼 초기화)
=> 제출이 되고 난 뒤 폼에 새로운 내용을 적을 수 있도록 적혀진 내용은 .value를 ""로 만들어주어야 했음.
4. 새 디스커션은 맨 앞에 배치되어야 한다는 점.
=> 더미 데이터에 배열에 추가할 때 빈 객체를 배열 뒤에 추가한다고 생각해서 push로 넣었는데, unshift를 사용해야 했음.
=> 게시글이 맨 앞에 추가되도록 하려면 .prepend를 사용해서 선택한 콘텐츠 내부 시작 부분에 삽입해줄 수 있다.
5. render 함수를 어디에서 실행시켜야 하는가?
=> 더미 데이터를 받아오는 함수인 convertToDiscussion과 폼 제출 이벤트 핸들러 보다 뒤에 와야 함.
바닐라js로 페이지네이션을 만들기 위해 중요한 것은
등이 있는 것 같다.
<페이지네이션을 위해 선언해야 할 변수>
1. 페이지 숫자들이 들어갈 박스 ( 1,2,3,4,5와 같이 페이지들이 표시될 공간을 만들기)
2. 디스커션들을 하나하나 요소로 한 배열 (itemlist? datalist?)
3. 다음 버튼
4. 앞으로 버튼
5. 한 페이지당 보여질 수 있는 게시물 한계 (한 페이지당 게시물 5개, 10개 등)
6. 만들어지는 총 페이지 (Math.ceil(2번 배열의 길이/5번 한계)와 같이 계산)
7. 현재 페이지 (처음에는 1을 할당)
<페이지네이션을 위해 필요한 기능(함수)>
1. 버튼에 disabled 클래스를 추가해주는 함수
2. 버튼에 enanle 클래스를 추가해주는 함수
=> 1,2번 함수를 통해 버튼의 css를 조작할 수 있다.
3. 버튼들 제한 걸어주는 함수
=> 맨 앞 페이지일 때는 앞으로 버튼이 disabled 클래스를 갖도록 함.
=> 마지막 페이지와 현재 페이지가 같을 때 disabled 클래스를 갖도록 함.
4. 활성화된 페이지를 따로 표시하는 함수
=> 클래스명을 줘서 css에서 활성화된 페이지를 따로 조작할 수 있게 함.
5. 페이지 숫자들을 생성하는 함수
=> 반복문을 총 페이지 수 이하까지 반복문을 돌리고, 해당 페이지들을 페이지 박스의 자식으로 append 해준다.
6. 현재 페이지에 보일 게시물만 보이도록 설정하는 함수
=> 범위를 정해서, 만약 현재 페이지에서 보여야 할 게시물의 범위에 속하면
css 숨김(display:none)이 지정될 클래스를 지정해준다. (ex: hidden)
7. 페이지 숫자 버튼들에 이벤트를 더해주는 함수.
<그 외>
1 폼이 서브밋 되어서 새로운 디스커션이 추가되면, 페이지네이션도 업데이트 해주어야 한다.
2. window 객체에 이벤트 핸들러를 지정해서 "load"라는 이벤트가 일어났을 때
관련되어 일어나야 할 일들을 함수로 지정해준다.
위 기능을 구현하기 위해서 필요한 로컬 스토리지는 웹 스토리지의 종류 중 하나이다.
웹 스토리지는 '데이터를 데이터베이스 서버나 클라우드 플랫폼이 아닌 브라우저 상에 저장하는 기술.'인데, 보통 DB에 저장하는 데이터보다 상대적으로 덜 중요한 데이터들을 저장한다고 한다.
웹 스토리지는 '로컬 스토리지'와 '세션 스토리지' 이렇게 두 종류가 있는데,
세션 스토리지 : 웹 페이지의 세션이 끝날 때 저장된 데이터가 지워진다.
로컬 스토리지 : 웹 사이트를 새탭, 새창으로 띄워도 동일 데이터를 공유한다. 즉, 웹 페이지의 세션이 끝나더라도 데이터가 지워지지 않음.
(동일 컴퓨터에서 동일 브라우저 사용할 때만 해당함. 같은 컴 다른 브라우저 OR 다른 컴 같은 브라우저는 클라우드, DB 서버 이용해야 함)
로컬 스토리지에 저장된 내용은 웹 페이지를 닫아도 사라지지 않으므로 불필요한 데이터는 직접 청소해주어야 한다.
웹 스토리지는 기본적으로 키와 값으로 이루어진 데이터를 저장할 수 있고, 아래 매서드들을 이용한다.
//웹 스토리지의 매서드들 (local을 session으로 바꾸면 세션 스토리지로 사용할 수 있음)
localStorage.setItem("key", value);
//키에 데이터 추가
localStorage.getItem("key");
//키의 데이터 읽기
localStorage.removeItem("key");
// 키의 데이터 삭제
localStorage.clear();
//모든 키의 데이터 삭제
localStorage.length;
// 저장된 키/값 쌍의 개수
//사실 window.localStorage~ 로 사용해야하지만 window는 생략할 수 있음.
toLocaleString 뒤에 지정된 지역으로 날짜를 오늘 현지화 해줄 수 있다. 지역을 지정 안 하면 아마 시스템 상 현지화를 해주는듯? 그래서 제목처럼만 사용해서 새로 들어오는 날짜 정보들도 현지화를 할 수 있었다!
const checkAnswer = document.createElement("div");
checkAnswer.textContent = obj.answer ? "✅" : "❌";
애매하게 알고 있었던 삼항 연산자를 써보고 싶어서 요리조리 고민하다가 결국 answerConfim이라는 함수 하나를 새로 만들어서
checkAnser.textContent = answerConfirm(obj)
라고 넣어줬는데...
코드는 참 아는 만큼 간단해진다는 생각이 많이 들었다.
input과 같은 form 요소에서 값을 가져오고 싶을 때 value를 사용한다. (input 요소도 textContent를 가질 수 있음.)
그 외 요소(ex: div, span) 안에 있는 텍스트를 읽고 싶으면 textContent를 사용.(읽거나 변경할 수 있다)
이벤트의 기본 동작이 작동하지 않도록 하는 기능.
프로젝트에서는 submit 이벤트를 실행했을 때, 새로고침 되는 것을 막기 위해 사용했음.
cmd + i를 통해 vscode 내부에서 이모지를 사용할 수 있다.