0. 들어가며
바닐라 JS와 HTML/CSS 학습 후 처음으로 진행한 토이프로젝트이다. 이제껏 배운 것들을 활용해 뭐라도 만들어 보자는 취지로 프로젝트를 계획하게 되었다. 시작하기 앞서 해당 프로젝트에 관한 코드와 커밋 기록은 깃허브에서 확인할 수 있다.
https://github.com/w00ngja/Phoning-but-WEB
또한 백문이 불여일견. GitHub Pages를 통해 발행해놓았으니 제작한 페이지를 직접 방문해 보는 것도 좋을 듯 하다. 링크
https://w00ngja.github.io/PhoningButWeb/
0-1. 포닝이 뭔데?
포닝은 뉴진스의 팬덤 "버니즈"를 위한 모바일 소통 플랫폼이다. 메신저 기능을 필두로 영상통화, 사진이나 스케쥴 확인, 더 나아가 신규 앨범이 릴리즈될 때 프로모션 창구로도 활용되고 있다.
0-2. 포닝을 선정한 이유
첫 번째 이유는 명확한 컨셉이다. 디자인적 측면에서 개성이 확실하고 조금의 감각만 있다면 쉽게 퀄리티를 살릴 수 있다는 장점이 있다. 컨셉이 확실하다보니 구현하고 싶은 기능을 모듈처럼 갖다 붙히면 되니 프로젝트 용으로는 적합하다고 생각되었다.
근데 프로젝트를 진행하면서 이게 마냥 좋지만은 않다는 생각이 들었다. 문어발처럼 기능을 확장시키는 것 보단 프로젝트의 목적와 정체성을 확실히 하고 그 핵심을 제대로 구현하는 것이 좀 더 옳게 된 포트폴리오가 아닐까 생각해 보았다. 물론 이번엔 배운 것들을 써먹어 구현해보는 것이 주 목적이었지만, 다음부터는..!
두 번째 이유는 노래가... 좋기.....때문에
1. 계획 수립 및 준비
1-1. 구현 계획과 Skills
페이지 별 메인 랜딩페이지, 채팅, 디스코그래피로 구성하였다.
초기 구상 단계에서는 채팅 페이지를 아예 염두하지 않았다. 대신 스케쥴과 머천다이즈 샵 페이지를 생각하였으나, 원래 포닝의 주 정체성이 채팅이니 만큼 이 부분을 중점적으로 구현하는 것으로 방향을 틀게 되었다. 추가적으로 정규식 검사를 활용한 회원가입 기능도 함께 구현하였다.
구현하고자 하는 기능들을 생각하고, Freeform을 통해 대략적인 레이아웃을 설계하였다. 그 외에 세부적인 플랜은 노션을 통해 관리하였다. 프로젝트 과정이 담긴 노션 페이지는 해당 링크를 통해 확인할 수 있다.
https://wzarchive.notion.site/Phoning-but-web-446f214226c44446a32f690d0f1e5549?pvs=4
1. 첫 번째 메인이 되는 Index 페이지에서는 기존 모바일 플랫폼인 포닝을 '웹으로 이식'한다는 주제를 설명하는 랜딩 페이지 형식으로 디자인하였다. 특히 스크롤 이벤트를 퀄리티 있게 구현하는 것에 중점을 두었다. 애플 사이트를 보며 신선한 충격을 적잖이 받았기에.. '오 이런 건 이렇게 해보면 되겠다' 생각했던 것들을 본 페이지에 녹여냈던 것 같다.
2. 두 번째 채팅 페이지에서는 LocalStorage를 활용한 Server 맛보기에 초점을 두었다. 요청이나 비동기 처리를 아직 활용할 수 없지만, 그래도 페이지 내에서 채팅을 하고 내역을 정리하는 등의 액션을 최대한 구현하려 노력했다.
3. 마지막 디스코그래피 페이지에서는 아이템 셔플을 통한 사용자 인터렉션으로 페이지 내 숨어 있는 요소를 찾으며 재미있는 경험을 공유하고자 하였다.
1-2. 자료 취합
뉴진스 공식 홈페이지나 포닝 앱의 아이템들을 활용했고, 그 외에 네비게이션 바 같은 것들은 직접 제작하였다. 누끼 따는 데 애를 좀..먹었음..
메인 폰트로는 Noto Sans를 사용하였다.
2. 구현
2-1. 메뉴
페이지 간 네비게이션 바 역할을 메뉴 탭이다. 어느 페이지를 이동하더라도 고정된 위치에 있다.
2-2. 메인
앞서 언급했듯 애플 공식 홈페이지의 퍼포먼스를 모티프로 삼았다. 그 중 스크롤과 연계하기 위한 비디오를 최상단에 배치했고, 스크롤을 내릴 때마다 비디오의 프레임이 변하게 코드를 구성하였다. 연구를 꽤나 했는데, 디테일한 구현법은 추가적으로 작성할 계획이다.
비디오 프레임 외에도 엘리먼트의 회전, 애니메이션의 시작 발동 조건을 스크롤 이벤트와의 인터렉션을 구현하였다.
특정 영역으로 진입하면 Glitch 효과와 함께 최하단 영역으로 자동으로 이동하게 된다. 고전적인 CRT 모니터 화면에서 로그인/회원가입이 가능하다. 정규식 검사를 적용하였고 텍스트 값이 변할 때마다 이벤트가 발생되기 때문에 비동기 요청스러운 구현이 가능하였다.
2-3. 채팅
기존에 멤버 별 ID Card 소스가 존재하였는데, 이를 활용해 드래그 앤 드롭 이벤트로 채팅을 시작하게 하였다. 끌어온 멤버 별로 다른 채팅 내용이 로딩 되며, 별도로 존재하는 채팅 청소 버튼을 누르지 않는 한 계속 저장된다. 별도의 서버를 사용하지 않고 LocalStorage 내부의 List를 호출, 갱신하여 채팅 내용을 관리하였다.
2-4. 디스코그래피
앨범 정보를 쉽게 확인하면 재미없으니, 꽁꽁 숨겨놓았다. 셔플 버튼을 누르면 열댓 개 정도 되는 아이템들이 난수 값을 발생시켜 랜덤한 좌표도 이동된다. 이 중 단 하나의 아이템만 앨범 정보를 갖고 있으며, 셔플 버튼을 누를 때마다 초기화된다. Transition까지 적용하니 꽤나 감각적인.. 퍼포먼스를 보여주었다. 해당 페이지에서는 이벤트 버블링 문제를 처리하는 데 애를 좀 먹었는데, 해결하게 된 과정 또한 추후에 별도의 포스팅으로 기재해 놓을 예정이다.
shuffle.addEventListener("click", () => {
for (const number in stuffs) {
shuffling(stuffs[number]);
}
});
function shuffling(things) {
let coordX = Math.floor(Math.random() * 100);
let coordY = Math.floor(Math.random() * 100);
randomValue = Math.floor(Math.random() * 11);
// console.log(coordX, coordY);
things.style.top = `${coordY}%`;
things.style.left = `${coordX}%`;
}
위 코드와 같이 버튼을 클릭할 때마다 함수를 호출하여 랜덤 좌표를 반환하여 해당 좌표로 이동하도록 구성하였다.
3. 문제 해결 (Learning Point)
본 단락에서는 프로젝트를 진행하며 배운 점이나 유익했던 점, 해결한 문제들을 Semantic / Syntax 측면에서 통합적으로 정리해 놓았다.
3-1. 초기 설정과 설계의 중요성
기초가 탄탄해야 한다. 만사에 통용되는 말이다. 프로젝트를 진행하면서 고칠 점들도 계속 보이고 욕심도 나다보니 계획이 계속 수정되며 다소 더디었던 듯 하다. 기능이나 프로젝트를 구현하기 전에 디테일한 청사진의 설계가 필요하다는 것을 깨달았다. 과유불급이라고, 짜놓은 계획만 성실이 이행하는 것의 중요성도 알 수 있었다. DB에서의 개념적 스키마 설계 과정이 떠올랐다.
3-2. 배열과 유사배열
본 문제는 선택자로 가져온 배열 요소들을 Foreach나 Every 메서드를 통해 제어할 때 발생하였다. QueryselectorAll이나 GetElementByClassname을 통해 요소를 가져올 때 array 메서드가 잘 작동하지 않았는데, 해당 선택자를 통해 가져온 요소들은 유사배열로 인식된게 그 이유였다. 유사 배열은 HTMLCollection과 NodeList로 구분할 수 있으며, 사용할 수 있는 메서드가 다르다. 그래서 Foreach 사용 간 오류가 발생한 듯.
Array.isarray를 통해 쉽게 판별이 가능하며, Array.from 메서드를 통해 일반 배열과 동일하게 인식시키며 문제를 해결할 수 있었다.
3-3. 로컬스토리지와 데이터 바인딩
채팅 페이지와 회원가입을 구현하며 많이 맞닥뜨린 부분이다. 일단 로컬스토리지에선 JSON 확장자의 파일만 호출가능하기 때문에, 이를 파싱 후 오브젝트 형식으로 가져와 수정하였다. 이 과정에서 입력받은 내용을 HTML로 출력하기 위해 insertAdjacentHTML 메서드를 통해 템플릿 자체를 바인딩해 주는 방식으로 구현하였다.
해당 과정 또한 init, load, save, print 단계로 function을 나누어 필요한 곳에 모듈 방식으로 호출하며 쓸 수 있게 해주었다.
4. 개선방안
4-1. 클린 코드
프로젝트를 진행하며 약 4개 정도의 페이지를 짰는데, 페이지마다 코드를 짜는 법을 달리 해보았다. 일부러 그런 것은 아니고 페이지를 거듭할수록 개선점이 보여 발전하는 느낌으로.. 실제 코드를 보면 초반부 작업한 Index 페이지와 후반부 작업한 Discography 부분의 차이가 확연한 것을 알 수 있다. 프로젝트의 규모가 그리 크지 않고 바닐라 JS로만 작업했음에도 깔끔한 코드의 필요성을 알 수 있었고, 추후에 리액트까지 익히고 나면 그 중요함이 배가될 것이니 미리 인지할 수 있어 좋았던 것 같다.
그래도 좀 아쉬운 건 너무 구현 그 자체에만 급급하지 않았나 싶다. 다음 프로젝트부턴 클린 코드 지향을 위한 코드 컨벤션이나 규악을 좀 더 지켜가며 진행해볼 계획이다.
4-2. 비동기 요청을 통한 API 활용
멜론이나 스포티파이 같은 음원 플랫폼에서 제공하는 API와 연동해볼 생각이었지만, 마땅히 알맞은 것도 없었기에 본 프로젝트엔 활용하지 못했다.
4-3. 브라우저 / 기기 간 최적화
사파리를 기반으로 코드를 테스트하며 진행해서 그런지, 당장 크롬에서만 열어도 쫌 페이지가 깨지는 것을 볼 수 있었다. 모바일은 말할 것도 없이 .. 프로젝트 진행 간 특정 브라우저에서만 적용되는 -webkit- 이나 메서드들도 살펴볼 수 있었는데, 초기 설계 단계부터 해당 문제들을 고려할 필요가 있다는 생각을 했다.
5. 후기와 느낀 점
솔직히 고칠 점이 많다. 만족스러운 부분도 있지만, 당장 보더라도 수정이 필요하거나 좀 더 디테일하게 구현되었으면 하는 부분이 보인다. 궁극적으로는 프론트엔드 커리어를 위한 포트폴리오이기 때문에, 리액트와 API 등을 배우는 대로 개선해 나갈 계획이다. 앞으로도 발전하는 모습을 지켜봐 주시길 ..