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

KDT0_ParkJiSung 임직원 관리 서비스 #49

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open

Conversation

flamozzi
Copy link

@flamozzi flamozzi commented Aug 18, 2023

KDT0_ParkJisung

DEMO 및 사이트 링크

image

제작한 임직원 관리 서비스

본 프로젝트는 야놀자 테크스쿨 JS과제를 위해 제작한 임직원 관리 서비스입니다.
파이어베이스 스토리지 및 리얼타임 데이터베이스를 사용하였으며, 바닐라 html, css, node js를 사용하여 개발하였습니다.

본 프로젝트는 데스크탑을 우선적으로 개발하였으며 모바일 기기의 작은 화면에 반응형으로 대응합니다.
브라우저는 크롬 브라우저를 기준으로 제작되었습니다.
gif 파일이 많아서 PR 및 README.md 페이지 로드시 시간이 다소 걸릴 수 있습니다.

프로젝트 Info

프로젝트 목표

Y_FE ParkJisung(flamozzi) 임직원 관리 서비스 제작

과제 필수 요구사항

  • [필수] Firbase 스토리지 및 리얼타임 데이터베이스를 사용하여 서버 및 디비 구현
  • [필수] 프로필 페이지 (임직원 상세 페이지) 개발
  • [필수] 스크롤 가능한 형태의 리스팅 페이지 개발
  • [필수] 데스크탑-모바일 반응형 개발
  • [필수] 이미지 파일 CRUD 기능 구현
  • [필수] 유저 플로우 제작 및 리드미에 추가
  • [필수] CSS 애니메이션 및 상대수치 사용
  • [필수] JS DOM event 조작

과제 필수 요구사항 이외의 추가 구현 사항

  • 로딩 애니메이션 구현
  • 직원 데이터 CRUD 구현
  • 직원 검색 기능 구현
  • 스크롤 높이에 따라 나타나는 최상단 이동 플로팅 버튼 및 애니메이션 구현
  • 체크박스 기능 구현 (버블링 방지 등 학습하며 배운 내용 적극 사용)
  • 이미지 미리보기 기능 구현
  • 임직원 등록 및 수정시 모달 애니메이션 구현
  • 리스트 아이템 선택 및 새로운 아이템 업데이트에 대한 강조 애니메이션 구현
  • 타임스탬프 기능을 통해 최신 업데이트순 리스트 아이템 동적 정렬 구현
  • 싱글 유저(관리자) 지향의 서비스이기에 타임스탬프를 ID처럼 사용하여 DB 필드 낭비 최소화
  • 리스트 내부 정렬 최적화를 위해 그리드 적극 사용
  • BEM 방법론 적용
  • 모달 페이지 활성화시 이전 뷰의 스크롤 기능을 억제하여 모달페이지 스크롤만 동작하도록 구현
  • 현재 테스트에 사용한 사진은 AI가 가상으로 만들어낸 인물 사진 사용
  • 비활성화 버튼에 대한 비활성화 강조 표시 등 UI 디테일 구현
  • 임직원 상세 모달 페이지에서 정보 변경이 일어나도 이전 홈 페이지에서도 실시간으로 정보 수정이 반영되도록 실시간 렌더링 구현
  • alert 동작을 이용한 사용자 의사결정 로직 구현

Primary Color

image

  • 자주 쓰일 컬러셋 구성
  • Primary-500을 프라이머리 색상으로 사용하여 버튼 및 주요 로직 등 강조 표시가 필요한 곳에 사용
  • 아이템 하이라이팅 등의 조금 더 연한 색상은 주로 Primary-300 사용

Section별 구현사항

User Flow

직원관리서비스_유저플로우

Header Section

image
  • Header를 포함하여 COMMON 스타일 지정을 통해 이후 하위에 존재할 모든 섹션에 통일감 형성

임직원 등록 & Loding Animation & Highlight Fade

로딩_하이라이트

  • 임직원 등록 버튼 통해 모달 페이지 접근 및 유저 등록 (gif 용량 한계로 인해 모달 열기 및 데이터 입력은 미리 해두었습니다.)
  • 페이지 로드, 데이터 CRUD 작업 등 로딩이 필요한 시점에 로딩 애니메이션 구현
  • 임직원 등록 혹은 정보 수정으로 인해 리스트 아이템에 업데이트가 존재할시 해당 리스트 아이템에 강조 애니메이션 적용

임직원 삭제 및 체크박스 컨트롤

임직원 삭제 및 체크박스

  • 리스트 아이템별 체크박스 개별 선택 및 전체 선택 가능
  • 체크박스 활성 여부에 따라 임직원 삭제 버튼 활성화 여부 결정
  • 임직원 삭제시 alert 팝업을 통해 유저 결정 재확인 및 삭제 진행

모달 컨트롤 및 임직원 상세 조회

모달 컨트롤

  • 임직원 등록 버튼 혹은 리스트 아이템 선택시 모달창 활성화
  • 모달 페이지 및 오버레이를 통해 애니메이션 구현
  • 각 리스트 아이템에대한 상세 프로필 페이지로 사용

임직원 정보 수정 (변경 취소 및 변경 저장)

임직원 정보 수정

  • 임직원 상세 조회 모달 페이지를 통해 임직원 정보 수정 가능
  • 취소 및 저장 버튼을 통해 행동 확정 가능
  • 이미지 미리보기 구현을 통해 어떤 이미지로 변경할 것인지 시각적 확인 가능
  • 등록시 자동으로 애니메이션과 함께 원래 화면으로 이동
  • 정보 수정시 최근 업데이트 아이템이 리스트의 최상단으로 자동정렬 수행

최상단 이동 플로팅 버튼

플로팅버튼

  • 화면 스크롤 높이에 따라 동적으로 나타나고 사라지는 플로팅 버튼 구현

모바일과 같은 작은 화면의 반응형 대응

모바일 반응형

  • 모바일 기기와 같이 작은 화면의 디바이스에서도 대응 가능한 반응형 설계를 구현
  • 리사이징 함수 구현을 통해 실시간으로 화면 사이즈 추적
  • 모바일 화면에서는 리스트 아이템의 사진이 과도하게 보일 수 있기 때문에 안보이게 설정 (데스크탑 크기로 넘어가면 다시 자동으로 보이게 설정)

JS 구현에 신경 쓴 부분

파이어베이스 환경변수 설정

image

  • 보안을 위해 Firbase 설정 값들은 환경변수로 만들어 사용

리스트 아이템 하이라이팅 구현부

image

  • 처음에는 id 필드를 통해 리스트 하이라이팅을 구현하려고 하였으나, 관리자 한 명의 싱글 유저 지향 서비스라는 점에 착안하여 타임스탬프를 Id 대신 사용하는 로직을 만들어 봄
  • 서비스 이용자 혹은 동시 다발적인 CRUD가 일어나는 서비스에서는 당연히 id를 따로 지정해주어야 하지만, 타임스탬프는 밀리초 단위이기 때문에 싱글 유저 서비스에서는 충분히 id 대신 사용가능할 것이라는 아이디어를 실제로 구현해 봄

검색 기능 구현부

image

  • 한 번 렌더링 받은 데이터를 통해 필터링을 진행하기 때문에 검색할때마다 과도한 서버 요청 방지 가능
  • 이름, 이메일, 연락처, 구분(직급 직무 등의..)의 문자열 값으로 검색 가능

이미지 삭제 및 변경 구현부

image

  • 이미지 삭제 기능을 구현하였지만 일부러 주석처리함
  • 이미지가 고유의 url을 가지고 있더라도 결국 참조하는 원본 소스는 동일한 사진을 가리키기 때문에 다른 리스트 아이템에 영향을 줌
  • 멀티 유저의 실시간 서비스의 경우 삭제기능을 주석 해제하여 사용하면 됨
  • 하지만, 싱글 유저 서비스인 본 서비스의 테스트에서 무한한 사진을 사용할 수는 없으므로 파이어베이스 스토어의 이미지 삭제 기능은 주석 처리하고 진행함

모바일 반응형을 위한 리사이즈 구현부

image

  • 모바일 환경에서는 리스트 아이템 내부에 사진이 있을 경우 너무 과도한 영역을 차지하기 때문에 데스크탑 버전에서는 사진 visible, 모바일 버전에서는 invisible 하게 세팅함
  • 실시간으로 window 사이즈를 추적하여 적용되기 때문에 웹 사이트 상에서도 창 크기를 줄이면 자연스럽게 실시간으로 반영됨

Retrospective 및 리뷰 요청 사항

  • JS 과제이지만 CSS 애니메이션 또한 좋은 퀄리티를 구현하기 위해 노력하였습니다.
  • 위의 특히 신경 쓴 JS 구현부 이외에도 다양한 CRUD 작업 및 기능 구현에 관련된 JS 코드는 실제 파일에서 확인할 수 있습니다.
  • 동일한 코드 스타일 및 컨벤션을 유지하려고 하였으나, 과제 마감 기한까지 최대한 많은 기능 넣으려다 보니 코딩 컨벤션이 다소 흐트러졌습니다. (코드 구조 컨벤션은 리팩토링 과정에서 다시 정리해보도록 하겠습니다.)
  • BEM 방법론의 네이밍 컨벤션을 따르고자 노력하였습니다.
  • 데스크탑 및 모바일 각 화면 크기에서 그리드 내의 정렬이 깨지지 않기 위해 CSS 컨트롤에 힘썼습니다.
  • 본 서비스는 크롬 브라우저를 기준으로 개발되었습니다. 사파리와 같은 다양한 브라우저에 대해서는 정상적으로 UI가 표시되지 않을 수 있습니다.
  • 현재 리스트 아이템 삭제시에도 하이라이팅이 적용되는 버그가 있습니다. 의도하지 않은 부분인데 원인을 아직 찾지 못하였습니다.
  • 현재는 실험적으로 id 대신 타임스탬프를 id 처럼 사용해보았습니다. 물론 다중 유저의 멀티 서비스에서는 id를 사용하여야 하지만, 싱글 유저의 동시 CRUD 작업이 일어나지 않은 서비스에 대해서는 타임스탬프를 아이디처럼 사용해도 무리가 없는지 궁금합니다. (물론 가능하다면 id를 사용하겠지만, 호기심에 구현해 보았습니다.)

@netlify
Copy link

netlify bot commented Aug 18, 2023

Deploy Preview for magenta-pastelito-695c0d ready!

Name Link
🔨 Latest commit 677faee
🔍 Latest deploy log https://app.netlify.com/sites/magenta-pastelito-695c0d/deploys/64df7b5e9c32f40008b2c09b
😎 Deploy Preview https://deploy-preview-49--magenta-pastelito-695c0d.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@flamozzi flamozzi changed the title Kdt0 park jisung KDT0_PARKJisung Aug 18, 2023
@flamozzi flamozzi changed the title KDT0_PARKJisung KDT0_ParkJiSung Aug 18, 2023
@flamozzi flamozzi changed the title KDT0_ParkJiSung KDT0_ParkJiSung 임직원 관리 서비스 Aug 18, 2023
Copy link

Choose a reason for hiding this comment

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

주석을 이용해 코드 보기가 정말 간편하고 정리를 너무 잘해놓으신거 같아요 👍👍

Comment on lines +53 to +75
window.filterStaffList = function () {
const searchQuery = document.querySelector('.search').value.toLowerCase();
const staffListItems = document.querySelectorAll('.staff-list__item ul li');

staffListItems.forEach((item) => {
const name = item.querySelector('.item-name').textContent.toLowerCase();
const email = item.querySelector('.item-email').textContent.toLowerCase();
const phone = item.querySelector('.item-phone').textContent.toLowerCase();
const category = item.querySelector('.item-category').textContent.toLowerCase();

// 이름, 이메일, 연락처, 구분 중 일치하는 정보가 있으면 표시, 없으면 숨김
if (
name.includes(searchQuery) ||
email.includes(searchQuery) ||
phone.includes(searchQuery) ||
category.includes(searchQuery)
) {
item.style.display = '';
} else {
item.style.display = 'none';
}
});
};
Copy link
Member

@NohWookJin NohWookJin Aug 22, 2023

Choose a reason for hiding this comment

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

item들을 배열에 넣고 some 메서드로 확인하면 더 간결해질 것 같습니다! 👍

staffListItems.forEach(item => {
    const items = [
      item.querySelector(".item-name").textContent.toLowerCase(),
      item.querySelector(".item-email").textContent.toLowerCase(),
      item.querySelector(".item-phone").textContent.toLowerCase(),
      item.querySelector(".item-category").textContent.toLowerCase(),
    ];

    const display = items.some(item => item.includes(searchQuery));
    item.style.display = display ? '' : 'none';
})

Copy link
Author

Choose a reason for hiding this comment

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

감사합니다! some을 생각 못했네요 ㅎㅎ 참고해서 수정해보겠습니다!

Comment on lines +234 to +235
// staff-list 아이템 클릭 이벤트 위임
document.querySelector('.staff-list__item ul').addEventListener('click', function (e) {
Copy link

Choose a reason for hiding this comment

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

체크박스 클릭해서 이벤트와 정보를 가져오는 동작을 깔끔하게 구현하기가 어려웠는데 깔끔하게 적어주셔서 인상 깊었습니다! 덕분에 또 하나 배워갑니다!👍👍👍

Comment on lines +5 to +15
// Firebase 설정
var firebaseConfig = {
apiKey: process.env.REACT_APP_FB_API_KEY,
authDomain: process.env.REACT_APP_FB_AUTH_DOMAIN,
projectId: process.env.REACT_APP_FB_PROJECT_ID,
storageBucket: process.env.REACT_APP_FB_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FB_MESSAGE_ID,
appId: process.env.REACT_APP_FB_APP_ID,
measurementId: process.env.REACT_APP_FB_MEASUREMENT_ID,
};
firebase.initializeApp(firebaseConfig);
Copy link

Choose a reason for hiding this comment

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

firebaseConfig에 환경변수를 적용해서 보안측면도 신경쓴점이 좋은것같습니다!

Comment on lines +78 to +85
// 임직원 등록 모달 열기 함수
function openRegisterModal() {
const registerModal = document.querySelector('.register-modal');
const overlayRegister = document.querySelector('.overlay-register');
registerModal.classList.add('show');
overlayRegister.classList.add('show');
document.body.classList.add('no-scroll');
}
Copy link

Choose a reason for hiding this comment

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

저는 처음에 모달로 멤버 등록하고 수정하는 함수들 작성하다가
저한테는 어려운것같아 방향을 틀었었는데, 다 구현하셨군요.. 👍

Comment on lines +520 to +531
function updateImageVisibility() {
const images = document.querySelectorAll('.item-image');
if (window.innerWidth < 768) {
images.forEach((image) => {
image.classList.add('item-image--hidden');
});
} else {
images.forEach((image) => {
image.classList.remove('item-image--hidden');
});
}
}
Copy link

Choose a reason for hiding this comment

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

화면 크기에 따라 이미지를 변경하는 코드도 있고, 모바일까지 꼼꼼하게 신경쓴점이 좋은것같습니다.

Copy link

@JIYEONGYANGdev JIYEONGYANGdev left a comment

Choose a reason for hiding this comment

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

모바일 반응형 적용 width가 적절한 것 같네요. 태블릿도 포함시킬 수 있을 것 같아요.
사진을 가리는 것도 UX/UI면에서 고민을 해보신 게 보이는 것 같아 좋네요.

그리고 수정된 데이터는 최상위로 끌어오는 점도 좋은 기능같습니다. 👍🏼

수고하셨습니다!

Comment on lines +162 to +165
// 임직원 리스트 실시간 반영 및 렌더링
database.ref('staff').on('value', (snapshot) => {
const staffList = document.querySelector('.staff-list__item ul');

Choose a reason for hiding this comment

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

이미지 리소스를 로컬로 올리지 않고 db에서 끌어와 렌더하셨군요. 👍🏼

Copy link
Author

Choose a reason for hiding this comment

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

리뷰 감사합니다! 다음에는 태블릿도 고려해서 만들어볼게요! 👍🏻👍🏻

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

Successfully merging this pull request may close these issues.

6 participants