[Vanilla JS] 스프레드 시트를 만들어보자

Kyle·2021년 3월 21일
2

project

목록 보기
6/13
post-thumbnail

스프레드 시트

깃허브 링크

개발 기간: 03/15 ~ 03/19

구현한 기능

  • cell Input & function bar input
  • enter, tab, delete, 화살표 키보드 이벤트
  • 드래그로 다중 선택
  • 드래그 앤 드롭

실행화면

input

select

클래스 설계 구조

대략적인 폴더 구조이다. 프로젝트를 천천히 발전시킬 예정이기 때문에 완성단계는 아니다.
View에서 Model을 받고 Event클래스들에서 View를 통해 Model을 받는다.

각 Event 클래스들은 Model로부터 데이터를 get, set하면서 서로의 상태를 공유한다.

클래스 다이어그램

프로젝스 내용 설명

스프레드 시트와 비슷한 동작을 하도록 목표하고 구현했다. 이번에는 코드를 보여주며 소개하기 보다는 각 기능들의 로직이 어떻게 이루어지는지 작성했다.

스프레드 시트 렌더링 구조

스프레드 시트는 테이블로 구현했다.

Model에서 Sheet의 데이터를 2차원 배열로 관리하고 있다. 2차원 배열의 index를 이용해서 각 Cell의 x,y 좌표 값을 속성으로 넣어줬다.

각셀들은 td 태그로 이루어져있으면 안에 input을 갖고 있다. 각각의 셀들을 찾기 위해서 x,y라는 임의의 속성을 갖고 있다.

<table>
    <tr class='column-index'>...</tr>
    <tr>
        <td class='row-index'>1</td>
        <td x='1' y='1'><input type='text'></td>
        <td x='2' y='1'><input type='text'></td>
        <td x='3' y='1'><input type='text'></td>
        ...
    </tr>
</table>

Cell Input

  • Cell에 input은 Model의 focus-cell에 작성하는 방식으로 이루어져있다.

Input 로직

  1. Sheet 또는 Function-Bar에 input 이벤트가 발생하면 아래 콜백함수들이 진행된다.
  2. Model로부터 Focus-Cell을 가져온다.
  3. Focus-Cell의 input의 value를 가져온다.
  4. Cell에서 Input이 발생한것이면 Function-Bar에 Function-Bar에서 Input이 발생했으면 Cell에 value를 넣어준다.

키보드 이동

엔터,화살표,탭 을 이용해서 focus한 Cell들을 이동할 수 있다.

각 KeyCode에 맞게 Cell을 이동한다. handleMoveCell({moveColumn,moveRow,isTab})메소드를 이용해 셀을 이동시켜준다.

인자에 moveColumn,moveRow만 있으면 될 것같은데 isTab까지 있는 이유는 Tab이 기본적으로 한칸 넘어가는 역할을 하게 되기 때문에 isTab으로 Tab일때는 따로 처리를 해줬다.

input태그에 tabindex속성을 사용해봤지만 그렇게 되면 input태그에서 tab자체가 작동을 하지 않아서 따로 변수로 받아서 처리하게 했다.

셀 이동 구현 로직

  1. 셀 이동 전 현재 Focus-Cell에 있는 input-value를 Model에 저장한다.
  2. _moveFocusedCell 셀 이동
  3. 기존 셀에 input을 blur한다.
  4. 기존 셀에 focus를 삭제한다.
  5. 새로운 focus-cell을 설정한다.(기존 focus-cell과입력받은 moveColumn,moveRow를 이용)
  6. 변경된 셀에 input을 focus한다.
  7. 변경된 셀에 focus 한다.
  8. cell-name-box에 변경된 cell 이름 렌더링
  9. 변경된 cell의 value를 function-bar에 넣어주기

드래그 셀렉 & 드래그 드롭

드래스 셀렉과 드래그 앤 드롭은 mousedown, mouseover, mouseup이 순서대로 지나가면서 진행된다.

드래스 & 셀렉 로직

  1. mousedown
    1. selectMouseDown 상태 on
    2. 기존 선택했던 block-배경색 삭제
    3. 기존 선택했던 blcok-border 삭제
    4. ({cell,input} - DOM element)인 first,last select 저장 (시작이니까 처음과 끝을 동일)
    5. this.firstSelect, this.lastSelect 기준으로 Model에 selectData저장 []{cell,input},{cell,input},...]
      • first,last select 의 최소,최대 column,row값 구해서 block cells구한 뒤 저장
    6. Model에서 selectData 가져와서 배경색 색칠
  2. mouseover
    1. 기존 선택했던 block-배경색 삭제
    2. last select ({cell,input}) 저장
    3. firstSelect, lastSelect 기준으로 Model에 selectData저장 []{cell,input},{cell,input},...]
    4. Model에서 selectData 가져와서 배경색 색칠
  3. mouseup
    1. selectMouseDown 상태 off
    2. 실선 border 설정
    3. cell name box 설정

드래그 & 드롭 로직

  1. mousedown
    1. dropMouseDown 상태 on
    2. first target({cell,input}) 저장 (target한 cell을 기준으로 이동)
    3. 기존 selectData를 originData로 저장 (나중에 삭제해야되기 때문)
  2. mouseover
    1. 점선 border 삭제
    2. last target 저장
    3. first,last target 기준으로 이동한 거리 체크 후 first, last select 변경
    4. 변경된 firstSelect, lastSelect 기준으로 Model에 selectData저장
    5. 점선 border 설정
    6. first target을 현재 지점으로 변경 (selectData가 변경된 지점에 맞게 변경 됐기 때문에 현재 지점 기준으로 다시 거리 재야되기 때문)
  3. mouseup
    1. dropMouseDown 상태 off
    2. 기존(이동 전) selectData의 block-배경색 삭제
    3. 기존 selectData의 value들 삭제
    4. 점선 border 삭제
    5. 현재 selectData에 value 세팅
    6. Model에서 selectData 가져와서 배경색 색칠
    7. cell name box 설정

후기

이번에 코드스쿼드에서 자유주제 프로젝트를 진행했다. 나는 크롱이 추천해준 주제인 구글의 스프레드 시트를 주제로 정하고 일주일동안 개발했다. 처음에는 지금 구현한기능 + 셀,폰트 스타일과 함수를 적용하는 것이었다. 하지만 간단한 기능 하나도 신경써야될 부분이 많아서 계획한만큼 다 이루지는 못했다.

이전에 작은 단위로 프로젝트를 진행했을 때는 신경써야될 상태나 속성들이 많이 않았다. 그저 한 기능을 한 단위로 개발해 나가면 됐다. 이번에 스프레드 시트 프로젝트는 같은 상태를 공유하는 요소?들이 많이 있다보니까 그것을 통일성 있게 어떻게 관리하는데 고민을 많이 했던 것 같다.

처음에는 기능 하나에만 생각해서 구현을 했다가 다음 기능을 구현할 때 '아...이렇게 하면 안되는구나' 하고 구조를 새로 고치고 이 작업을 많이 반복했던 프로젝트였다. 이런 과정을 통해서 배운점도 많았고 몇가지 처음 구현해보는 기능들을 만들어내면서 얻는 재미도 있었던 한주간이었다

스프레드 시트를 만들면서 재미도 있었지만 아쉬운부분도 있었다. 이번 코드스쿼드에서 자유주제로 일주일의 시간을 주었는데 어떻게보면 이 시간에는 평소에 공부하고 싶었던 부분을 프로젝트로 연결시켜서 학습할 수 있는 좋은 시간이었다. 다른 동료분들을 보면 백엔드, 소켓, 차트 등 새로운 것들을 도전하셨다. 반면에 스프레드 시트는 새로운 기술보다는 기존에 해왔던 것의 연장선? 느낌이라 약간의 아쉬움도 남았다.

profile
Kyle 발전기

2개의 댓글

comment-user-thumbnail
2021년 3월 21일

정말 쉽지 않아보였는데 열심히했네요 카일! 이벤트 하나에도 구현해야 할 기능이 엄청 많은데 어떻게 다 컨트롤 하신건지 ㅠㅠ 멋집니당!

1개의 답글