Code Monkey home page Code Monkey logo

ppthub-server's Introduction

PPTHUB

PPTHUB는 다른 PPT 파일을 비교하고 관리할 수 있는 웹 서비스입니다.

두 개의 PPT 파일을 비교해 다른 부분을 찾아내고, 원하는 데이터를 선택해 새로운 PPT 파일을 생성할 수 있습니다.

프로젝트 발표 영상

PPTHub 링크

실 사용 화면

1


𝌞 목차


🏔 챌린지

🎯 PPT 파일을 어떻게 다룰까? - Parsing

저희는 PPT 파일을 파싱해주는 라이브러리를 사용하지 않고 자체적인 Parsing 로직을 구현하였습니다.

7


우선 PPT(.pptx) 파일은 XML파일들이 모여있는 구조입니다. XML 파일 여러 개가 하나의 파일을 이루는데요.

XML은 HTML와 비슷하게 Tag를 열고 닫아 작성하는 Element의 구조입니다. 그래서 XML은 HTML처럼 DOM으로 사용할 수 있다는 장점이 있습니다.

XML을 Web API인 Dom Parser를 이용해서 Dom으로 Parsing하였습니다. 그 다음은 DOM API를 이용해 프로퍼티 및 자식 요소에 접근할 수 있었습니다.

PPT → XML DOM 기술 검증 과정


Frontend와 Backend 중 어디에서 실행할 지 결정하기

DOM Parser 등 Web API는 웹 브라우저 환경에서만 사용할 수 있습니다.

Node.js와 같은 환경에서는 별도로 문자열을 DOM으로 Parsing해주는 라이브러리를 설치해야만 했는데요.

단순히 HTML뿐 아니라 XML을 Parsing 해주는 다른 라이브러리를 알아보았지만 기존에 작성했던 Dom Parser로 작성된 코드를 전반적으로 수정해야 했습니다.

Node.js 써드파티 라이브러리 XML Parsing 기술 검증 과정


또 저희가 고려했던 점은, PPT를 Parsing하는 작업은 Client에서 실행되기에 너무 오래걸리는 작업이 아닐까 했던 것인데요.

우려했던 것과 달리 Client에서 Parsing하는 작업은 크게 오래 걸리지 않았습니다.

1

File unzip은 10ms 내, Parsing은 100ms 내로 작업이 진행되었습니다.


PPT 파일은, PPT 파일의 압축을 해제하고 DOM Parser로 Parsing하는 과정으로 이루어져있습니다.

PPT 파일을 Parsing하는 작업이 오래 걸리지 않았던 이유는 파일 전체의 데이터를 가공하는 방식이 아닌, 특정 요소를 찾아 추출하는 방식으로 로직이 구성되어 있기 때문입니다. PPT 파일을 완전히 재현하는 것이 아니라, View 기능과 Diffing 기능을 위해서 추출하는 것이기 때문에 내부 구성요소의 정보를 담은 정보만 가져옵니다. 따라서 비교적 무거운 작업이 아니라고 판단하였고, Client 상에서 로직을 수행할 경우, 100ms 이하의 시간이 걸리는 것을 확인하였습니다.

파일 압축의 경우에도 파일의 크기에 따라 다를 수 있지만, Client에서 실행할 수 있는 범위 내라고 판단하였습니다. 따라서 PPT File Parsing은 Client에서 진행하게 되었습니다.

PPT에서 View Data를 추출하기

2

PPT 파일에서 Text 상자 XML 예시


PPT 파일에서 보통 하나의 슬라이드마다 하나의 XML 파일을 가지게 됩니다. XML 파일 내부에는 슬라이드의 요소들과 그 정보들을 포함하고 있습니다.

내부 요소들은 각각의 유형에 맞게 Tag가 정의되어 있습니다. 예를 들어, Text의 경우 p:sp을, Image의 경우 p:pic 을 갖습니다.

각 Tag를 통해 어떤 구성요소인지 검사하고, 구성 요소에 맞게 내부 속성들을 추출합니다. 예를 들어 Text는 글자의 크기와 굵기, 색상, italic체와 같은 내부 속성을 가질 수 있습니다.

하지만 짧은 시간 내에 프로젝트를 완성하기 위해서는 모든 PPT의 구성요소를 Parsing 할 수 없었습니다.

하나의 구성 요소와 내부 속성들을 조사하고, 어떤 데이터를 Parsing해야 하는 지 알아보는 작업은 시간이 걸리는 작업입니다.

2주라는 제한된 개발 기간동안 개발을 마치기 위해서 일단 Text와 Image 데이터를 우선 Parsing하기로 결정하였습니다.

PPT 파일 View Data 추출 기술 검증 과정


🎯 두 개의 PPT를 어떻게 비교할 수 있을까? - Diffing

변경 된 슬라이드를 감지하기

두 개의 PPT를 비교하기 위해서는, 어떤 슬라이드가 변경되었는 지 감지해야 합니다. 하지만 그 기준을 정하는 것이 어려웠습니다.

하나의 슬라이드는 변경될 수 있고, 순서도 바뀔 수 있습니다. 비슷한 형식의 슬라이드가 여러 개가 반복될 수도 있게 됩니다.

처음에는 최소한의 일치율을 만족하는 경우를 생각했습니다. 그럴 경우 두 슬라이드를 매칭하여 비교할 수 있습니다.

다만 그렇게 되면 하나의 슬라이드가 다른 모든 슬라이드와 비교가 되어야 했고, O(n^2)의 시간복잡도를 갖게 됩니다.

시간복잡도도 높고 지나치게 코드의 복잡성이 높아지는 방향이라고 생각해 다른 방안을 찾게 되었습니다.

다른 방안은 슬라이드가 가진 고유한 값으로 비교를 하는 것입니다.

고유한 값을 가진 두 슬라이드만 비교하면 모든 슬라이드를 비교해줄 필요없이 O(n)의 시간복잡도로 문제를 해결할 수 있습니다.

다만 두 내용이 완전히 같은 슬라이드라도 id만 다르면 다른 슬라이드로 취급되는 단점도 있습니다.

이 경우는 조금 더 특수한 경우라고 생각되어 사용자가 이해할 수 있는 범위 내라고 생각했습니다.

저희가 정한 고유한 값의 조건은

  • 기존 슬라이드가 복사되는 경우, 새로 부여되어야 합니다.
  • 파일이 복사되는 경우, 그 값은 유지되어야 합니다.

였습니다. 여러 슬라이드 내부 데이터 중, 해당 조건에 부합하는 값(p:creationId)을 찾아내 매칭에 사용하였습니다.

Slide 비교 감지 기술 검증 과정


또, Set 자료구조를 이용해서 id를 비교할 때 O(1)의 시간복잡도로 찾을 수 있도록 작성하였습니다.

// 인자로 Set을 넣어 두 값을 비교하게 됩니다.
const {
  matchedIds,
  deletedIds,
  addedIds,
} = getMatchingIds(
  new Set(originItemsMap.keys()),
  new Set(compareItemsMap.keys()),
);

처리하기 용이한 슬라이드 비교 데이터를 만들기

슬라이드를 비교할 때 가장 고려했던 것은 데이터의 구조입니다. 슬라이드 비교 데이터는

  1. Diffing 로직이 진행될 때도 추가/변경하기 쉬운 구조여야하며,
  2. 화면에 Rendering 되기에도 용이한 구조여야 합니다.
  3. 나중에 Merge 작업이 이루어질 때도 사용하게 됩니다.

type SlideDiffData = {
  diff: "added" | "deleted" | "modified" | "none";
  isChecked: boolean;

  // value는 diff가 "modified"인 경우에만 유효한 property입니다.
  value?: {
    items?: {
      [itemId]?: {
        diff: "added" | "deleted" | "modified" | "none";
        isChecked: boolean;
      }
    }
  },
};

Diffing Data의 구조는 재귀적입니다. PPTDiffData > SlideDiffData > ItemDiffData의 구조로 반복됩니다. 그리고 특정 property는 조건에 따라 유효하게 됩니다.

예를 들어 SlideDiffDatavalue 프로퍼티는 Slide 내부의 Diffing Data가 정의되어있는데요.

Slide 자체의 diff“added” 혹은 “deleted”, “none”이라면 value라는 property는 유효한 의미가 없습니다. 전체가 변경되었거나, 변경되지 않았기때문이죠.

2

슬라이드가 변경 된 경우, 변경된 item은 “added” 혹은 “deleted”라는 단순한 타입을 갖게 됩니다.


이런 복잡할 수 있는 데이터 구조를 최대한 단순하게 작성하기 위해 노력하였습니다. 그 중 하나가 diff 라는 프로퍼티를 만든 것입니다.

이전에는 Slide가 “modified”인 경우, 변경 되기 전 item은 “modified-modified-before”와 같은 별도의 타입을 부여하였습니다. 하지만 처리해야하는 분기 수가 많아지고 더욱 복잡한 코드가 만들어지게 되었습니다.

그래서 모든 diff property를 통일해주었습니다. diff는 Slide 그리고 Slide의 구성요소(item) 둘 다에게 적용됩니다.

단순히 대상을 “added”, “modified”, “deleted”, “none”으로 나누었기 때문에 훨씬 효율적으로 처리할 수 있었습니다.

더 이상 “modified-modified-before”와 같은 추가 분기가 없어 단순하게 작업할 수 있기 때문입니다.

Merge 작업을 용이하게 하는 것도 고려하였습니다. Merge 작업은 사용자가 선택한 요소만을 조합해 합치게 됩니다.

처음 고려한 방안은 별도로 Merge Data를 만드는 것이나, 구현 단순화를 위해 Diff Data를 활용하였습니다.

Slide Data 혹은 Item Data 내부에 isChecked라는 boolean 프로퍼티를 만들어 분기처리를 가져가기 편하도록 만들었습니다.

🎯 어떻게 더 사용자를 편리하게 할 수 있을까?

마우스 Hover 시 하이라이트 효과

2


PPT 파일을 보여주거나 편집할 때 사용자가 최대한 직관적으로 기능을 이해하길 원했습니다.

사용자가 Slide 내 구성 요소에 마우스를 올릴 때 다른 PPT에서의 해당 요소가 하이라이트 됩니다. 그리고 사이드바에서도 해당 요소가 하이라이트 되도록 했습니다.

사용자가 직관적으로 어떤 부분을 수정하는 지 시각적으로 전달하기 위해서입니다.

{
  [slideId]: {
    diff: "added" | "deleted" | "modified" | "none";
    isChecked: boolean;

    items: {
      [itemId]: {
        diff: "added" | "deleted" | "modified" | "none";
        isChecked: boolean;
        // isHovered property를 통해 Hover시 하이라이트를 나타냅니다.
        isHovered: boolean,
      },
    },
  },
};

이를 위해서 Rendering 시 데이터 구조를 위와 같이 나타냈습니다. 위의 Diff Data에서 isHovered라는 값이 추가 되었는데요.

같은 Diff Data 두 개의 Slide Viewer와 사이드 바로 모두 렌더링 되기 때문에, isHovered 값을 바꾸면 세 부분 다 렌더링이 바뀌게 됩니다.

사이드바에서 Slide 클릭 시 이동

2

사이드바에서 원하는 Item이나 Slide를 클릭하면 해당 위치로 이동하도록 하였습니다.

이를 위해서, 웹 내부에서 특정 리소스로 이동할 수 있는 Fragment 기능을 이용하였습니다.

각 슬라이드 영역 Element id가 지정 된 div 태그를 삽입하였고, 사이드 바에 href를 수정하도록 변경하였습니다.

// Slide Section 상단에 div slideId를 담은 div 태그를 삽입하였습니다.
<React.Fragment key={slideId}>
  <div id={`${slideId}-${fileType}`} />
  <SlideListSlideSection />
</React.Fragment>

// 클릭 시 해당 위치로 이동하게 됩니다.
onChange={() => {
  window.location.href = `#${slideId}-PPT_DATA_TYPES/ORIGINAL_PPT_DATA`;
  dispatch(toggleItemChecked({ itemId: itemData.itemId, slideId }));
}}

Toast 메시지

2


사용자에게 프로세스가 진행되면서 생기는 메시지들은 Toast 메시지를 적극 활용하였습니다.

Toast 메시지는 한 곳에서 편하게 유저에게 내용을 전달할 수 있어서 편리하고, 유저도 직관적으로 이를 알 수 있습니다.

저희는 상태관리로 Redux-Toolkit을 사용하였는데요. 다만 Toast는 상태로서 관리되기 보다는 별도의 기능이라고 판단해 Redux를 쓰지 않고 작업하였습니다.

상태 관리 도구에 의존적인 기능을 만들고 싶지 않았기 때문입니다. 그래서 Context API와 Portal을 활용하게 되었습니다.

export function ToastProvider({ children }) {
  const [toastMessage, setToastMessage] = useState("");

  const showToastMessage = useCallback(
    // Toast 메시지는 2초 후에 사라집니다.
    (message) => {
      if (message === toastMessage) {
        return null;
      }
      
      setToastMessage(message);

      setTimeout(() => {
        setToastMessage("");
      }, 2000);
	
      return null;
    },
    [toastMessage],
  };

  const isShowToast = toastMessage !== "";

  return (
    <ToastContext.Provider value={showToastMessage}>
      {children}
      {isShowToast && (
        // Portal을 통해 안정적으로 Toast 메시지를 Rendering합니다.
        <ToastPortal>
          <TostMessageBubble>
            <Message>{message}</Message>
          </TostMessageBubble>
        </ToastPortal>
      )}
    </ToastContext.Provider>
  );
}

🔥 이슈

⚡️ PPT 파일 데이터베이스 관리 이슈

이슈 내용

  • 고화질 사진 등 용량이 큰 PPT의 데이터를 모두 MongoDB에 저장할 수 없는 이슈가 발생하였습니다.
  • MongoDB의 정책 상, document 하나의 크기가 최대 16MB로 제한됩니다.
  • 만약 16MB가 넘는 파일은 저장할 수 없게 됩니다.

대안

  • 데이터를 압축해서 DB에 저장하자는 의견이 논의되었습니다.
  • 하지만 데이터를 압축, 해제하는 과정에서 추가적인 시간이 소모될 것이라 판단하였습니다.

  • 각각 개별 슬라이드를 저장하여, PPT Data에서는 Slide Id 정보를 관리하는 방안이 논의되었습니다.
  • Slide들을 개별적으로 저장하는 방안 역시 많은 양의 Slide들이 들어가면 컬렉션 자체 용량을 초과하는 리스크가 있었습니다.
  • 하지만 데이터의 만료시간을 설정해, 효율적으로 용량을 관리하도록 결정하였습니다. CronJob으로 스케쥴 관리를 해서 주기적으로 데이터를 삭제하도록 결정하였습니다.

해결

  • 각각 개별 슬라이드를 저장할 수 있는 PPTSlide 컬렉션을 두어 PPT 컬렉션에 해당 슬라이드 document들의 id들을 두는 방안으로 결정하였습니다.
  • 각 데이터들은 다대다 관계를 형성하게 됩니다. 이 후 데이터를 불러올 때, populate 메소드를 이용하여 전체 PPT 데이터를 불러오도록 결정하였습니다.

MongoDB 데이터 저장 이슈


⚡️ 상태 관리 라이브러리 도입 이슈

이슈 내용

  • 하나의 Diff data를 슬라이드 뷰어에서도, 우측 Selection Bar에서도 공통적으로 사용하면서 전역 상태 관리 라이브러리 도입의 중요성을 느끼게 되었습니다.

대안

  • React-query와 Recoil을 활용하는 방안이 논의되었습니다.
  • 서버 상태 관리를 react-query를 사용하여, data를 항상 최신 상태로 관리할 수 있습니다.
  • 그리고 PPT 슬라이드 데이터가 지나치게 많은 경우 로딩 시간이 길 수 있으므로 pagination 기능을 활용해 볼 수 있었습니다.
  • 클라이언트 상태 관리 라이브러리는, Recoil을 사용하여 비교적 사용법이 간단하고, 무겁지 않은 라이브러리를 사용하는 방안으로 논의가 이루어졌습니다.
  • 다만 react-query를 사용할 정도로 항상 최신의 상태를 유지할 데이터가 아니라는 점, pptx 파싱을 클라이언트에서 직접 수행하여 pagination을 사용할 일이 없던 것이 단점이었습니다.
  • 현재 문제가 발생한 부분은 DiffData의 전역 상태 관리이므로, 이에 집중한다면 Recoil이 적합한 라이브러리인가에 대한 의문이 있었습니다.

  • 그 다음은 Redux를 활용하는 방안이 논의되었습니다.
  • Redux의 flux 패턴을 상태관리에 활용해볼 수 있었습니다. 하나의 DiffData는 Slide를 check/uncheck 해주는 액션과 요소를 chekck/uncheck 해주는 액션을 통해, DiffData를 관리할 수 있다고 판단하였습니다.
  • 그리고 check 상태 뿐아니라, hover와 같은 추가적인 기능도 액션을 추가하여 용이하게 관리할 수도 있다고 판단하였습니다.
  • Redux는 타 상태 관리 라이브러리와 비교해, 불필요한 boilerplate 코드가 있는 편이라 redux-toolkit을 사용하는 부분을 검토하였습니다. reducer들과 액션 생성함수를 번거롭게 만들 필요가 없이 자체 메서드로 간단하게 작성할 수 있었습니다.

해결

  • Redux를 이용해 전역 상태를 관리하였습니다.
  • redux-toolkit의 사용으로 boilerplate 코드 작성을 줄일 수 있도록 결정하였습니다.

상태관리 라이브러리 필요성 및 선택 이슈


⚡️ 사용자 관리 이슈

이슈 내용

  • 프로젝트에 사용자 관리를 어떻게 할 것 인지에 대해 논의가 발생하였습니다.

대안

  • 로그인 기능을 추가하여 더 많은 기능을 제공하는 방안이 있습니다.
  • 다만 한정적인 시간 내에 더 많은 기능들을 가져가게 되면서, 원래의 핵심 서비스의 완성도가 떨어질 수도 있습니다.
  • 그리고 이슈가 논의되었던 시점 당시, 작성이 어느정도 진행되었던 mockup, 유저 플로우, api docs 등을 수정해야 해, 그만큼 프로젝트 진행이 지체될 수 있었습니다.

  • 유저 로그인 기능을 넣지 않고, cookie를 발급하여 게스트 유저를 기억하는 방안이 있었습니다.
  • 사용자가 접속 시, DB에서 만료시간이 짧은 유저 데이터를 생성해, 그 id값으로 유저를 기억하고 구분하도록 시도하려고 하였습니다.
  • 위와 마찬가지로 핵심 서비스에 대해서 완성도가 떨어지게 될 수 있으며, 유저 관리 방안에 대한 조사 및 기술 구현이 충분치 않다는 단점이 있었습니다.

  • 로그인 혹은 내 파일보기 기능을 넣지 않고, download page 링크를 따로 가질 수 있게 하는 방안도 제시되었습니다.
  • 사용자는 url 정보를 갖고 있으면, 언제든지 파일들을 다시 다운로드 받을 수 있도록 하였습니다.
  • 유저 관리에 대한 DB 추가내용 작성 및 부수적인 기능 구현보다, 본 프로젝트 내용에 집중할 수 있게 됩니다.

해결

  • 로그인 기능을 제외하는 대신, download page url을 통해 작업한 파일을 기억할 수 있게 하였습니다.
  • 유저를 기억하여 작업했던 파일들을 저장해 보여주는 기능을 가져가지 못하였지만, 다른 사용자와 공유하거나 url로 저장할 수 있게 기능을 도입하도록 결정하였습니다.
  • ‘작업한 파일을 다시 내려받을 수 있게 한다.’라는 원래의 아이디어 목표를 가져가면서, 기능을 거의 추가하지 않을 수 있었습니다.
  • 그에 따라서 부가적인 부분에 대한 기능 수고를 덜 수 있게 되었고, 핵심적인 기능 개발에 집중할 수 있게 되었습니다.

유저 로그인 기능 추가 이슈


👋 프로젝트 진행

프로젝트 기간 - 2022.10.10. ~ 2022.10.28. (3주)

  • 아이디어 기획, 목업 작성, 애자일 스프린트 플랜 : 1주
  • 프로젝트 개발, 배포, 테스트 : 2주

[Mockup][]

프로젝트 프로세스

  • 아이디어 기획
  • 기술 스택 검토
  • Mockup 설계
  • MongoDB를 이용한 데이터베이스 Schema 설계
  • Agile Sprint 기반의 테스크 매니지먼트

🌐 기술 스택

Client

JavaScript, React, Redux, Redux Toolkit, styled-components

Server

Node.js, Express.js, MongoDB & Mongoose, Amazon S3

Test

Jest, SuperTest, Cypress

Deployment

Netlify, AWS Elastic Beanstalk

🤝 회고

공재혁
팀 프로젝트를 하면서, 다같이 문제를 해결해나가는 돌격대장과도 같은 경험을 할 수 있어서 좋았습니다.

어떻게 PPT 파일을 화면에 띄울 수 있지?부터 시작된 수많은 질문들에 끝맺음을 지을 수 있어서 다행입니다.

외부 라이브러리를 사용하지 않기 위해서 많은 노력을 했는데, 그 과정들이 새록새록 기억이 나는 것 같습니다.

대만어로 주석이 잔뜩 쓰여져있던 수 만줄짜리 코드부터, 오래된 웹사이트에서 발견한 보물같은 자료들까지

수많은 시행착오와 논의를 거쳐서 좋은 결과물이 나오게 된 것 같아 뿌듯합니다.

팀 프로젝트인 만큼 각자 생각도 다르고 의견도 달라서 힘들 때가 많았습니다.

특히나 열심히 회의를 했는데 서로 다른 의견을 얘기하고 있었다던가, 어느정도 말로 합의된 내용도 구현할 때 의견이 엇갈렸던 등

‘팀 프로젝트를 진행하는 건 쉽지 않구나’라는 걸 깨달았습니다.

그래서 저희는 사소한 부분도 한 발 한 발 맞추어 나가려고 노력하고, 사소한 부분도 ‘다음에 얘기하죠’라는 말 없이 꼼꼼하게 진행했습니다.

처음에는 이 프로젝트를 완성할 수 있을까? 하고 너무 막막했었는데, 옆에서 열심히 하는 팀원 분들을 보면서 힘을 많이 얻었습니다.

코드를 손에서 놓고싶은 순간이 와도, 팀원들과 열심히 피드백을 주고받으면서 다시 코드를 붙잡게 되었고요.

저도 누군가에게 힘을 북돋아주고 개발의 재미를 느낄 수 있게 해주는 팀원이었으면 좋겠다는 생각을 했습니다.

양선종
개발이라는 하나의 주제를 가지고 시작한 첫 프로젝트였던 만큼 이번 프로젝트가 나에게 주는 의미는 매우 크다.
프로세스 관리 방법 중 스크럼 방법을 통해서 프로젝트 계획, 회의, 칸반 작성 등을 진행하였고 이를 통해 프로젝트를 함에 있어서 이러한 행위들이 왜 중요한지를 명확하게 깨닫게 되었다. 이러한 과정들이 없었다면 내가 겪은 3주라는 시간이 계획이 있었음에도 정신이 없었는데 얼마나 더 정신이 없었을까 라는 것을 확연하게 느꼈다.

또한 프로젝트를 시작할 때 가지고 있었던 걱정 반 기대 반으로 가득 차 있었던 감정이 그대로 팀 프로젝트에서 드러났다고 개인적으로 생각하고 있다.

여러 가지 측면에서의 걱정이 존재했는데 첫 번째는 내가 팀원들에게 도움이 될 수 있을까 라는 걱정이 존재했고 팀원분들은 어떻게 생각할지 모르겠지만 나는 매우 아쉬웠다고 주관적으로 평가하고 싶다. 팀플을 하면 할수록 더 도움이 되고 싶다는 생각이 가득했고 노력했다고는 생각하지만, 프로젝트를 진행하면서 내가 작성한 하나의 컴포넌트 하나를 가지고 시간이 딜레이 되는 게 정말 죄송스러웠던 감정이 들었다. 그래도 이러한 과정에서 우리의 프로젝트가 단단해지고 더 완성도가 있게 만들자는 팀원분들의 생각에 정말 감사했고 그 과정에서 내가 몰랐던 방법들을 알 수 있게 되어서 얻어 가는 게 많았다.

두 번째는 커뮤니케이션 관련 해서의 걱정이었다. 앞선 컴포넌트와 관련한 코드 작성과는 별개로 프로젝트에 있어서 아이디어 측면과 서로 생각하는 방면이 완전하게 일치하지 않았기에 이런 문제가 발생했다고 생각한다. 사실 프로젝트라는 것 자체가 완성된 프로젝트를 가지고 작성하는 것이 아닌 없었던 프로젝트를 기획하고 구현하는 것이기 때문에 이러한 문제는 없으면 오히려 이상하다는 것이 맞는다고 생각한다. 그렇기에 아이디어와 관련한 충돌이 자주 일어나 힘들었지만 그럼에도 불구하고 첫 회의 중 하나였던 그날 있었던 감정은 그날에 푸는 것처럼 서로 그날 최대한 이해하고 최대한 감정을 풀어나갔던 부분에 있어서 커뮤니케이션 능력에서의 걱정과 성장을 동시에 이루어 나갔다고 생각하고 있다.

마지막으로는 당연히 기능 구현 및 프로젝트 진행에 대한 걱정이 매우 컸다. 사실 초반에는 이게 될까? 라는 생각이 엄청 많았고 우여곡절 또한 심하게 많았다. 피피티라는 파일 자체가 하나의 xml로 이루어져 있는 것이 아닌 많은 xml들의 집합인 점에서 xml 파일 간의 인과관계를 파악하기 위해서 시간을 쓰게 되었다면 아마.. 프로젝트는 3주가 아니라 3달이 걸려서 끝나지 않았을까 라는 생각을 한다. 그렇기에 당연히 문제가 생길 수 밖에 없었는데 다행히 pptx를 만들어주는 라이브러리를 토대로 파싱한 데이터들을 가지고 pptx를 만들 수 있었지만 라이브러리를 사용했다는 아쉬움이 존재했다. 또한 데이터의 양이 너무 방대하다는 것이 매우 큰 딜레이 요소이다. 하나의 텍스트를 얻기 위해서 xml 파일을 매우 딥하게 들어가기 때문에 pptx를 구성하는 데이터들을 모두 파싱하기 위해서는 시간이 오래걸린다는 시간적인 문제가 더 존재해서 아쉬웠다. 그래도 이러한 걱정들과 다르게 결국은 프로젝트가 만들어진다는 부분에 있어서 뿌듯한 감정을 느꼈다.

프로젝트 기간 2022.10.10 ~ 2022.10.28 인 3주 동안 정말 많이 힘들었고, 많이 배웠고, 많이 정신없었지만, 결과가 나왔을 때는 많이 뿌듯했다. 프로젝트가 얼마나 힘들었는지는 이미 지나간 시간이기 때문에 크게 중요한 요소는 아니다. 하지만 프로젝트가 끝나고 내가 많은 것을 얻었다는 것이 자체는 나에게 있어서 다른 프로젝트를 진행할 때도 매우 큰 도움의 밑거름이 될 수 있기에 정말 정말 뜻깊은 시간이 되었다.

이동현

처음으로 진행하는 협업 프로젝트였습니다. 애자일 방법론 또한 처음이었기에, 3주라는 짧은 시간 동안 매일 스크럼을 진행하면서 프로젝트 진행 상황을 공유하고, 회의와 피드백을 통해 계획에 어긋나더라도 유연하게 대처할 수 있었던 경험 역시 새로웠습니다.

이번 프로젝트를 진행하면서 느낀 점은 크게 2가지입니다.

첫 번째, 커뮤니케이션의 중요성입니다.

매일 오전 데일리 스크럼 미팅을 진행하면서 오늘 우리 팀이 해야 할 것, 현재 프로젝트 진행 상황 및 딜레이 여부 등을 이야기하면서 의견을 나누었고, 그 결과 다소 딜레이가 있더라도 유연하게 대처해 프로젝트를 정해진 기한 내에 배포까지 무사히 할 수 있었습니다.

프로젝트 진행 중에 코드 컨벤션부터, 디자인, 기능적인 부분에서 의견이 많이 갈리기도 하였는데, 프로젝트 계획을 할 때 더 많은 의견을 나누어 규칙 및 프로젝트 구조를 자세하게 설계하지 못한 부분은 아쉬움이 남습니다.
이러한 부분이 개발 중에 의견이 나뉘다 보니, 개발 진행 중 딜레이가 되는 원인이 되기도 하였고, 다소 날카롭게 말할 때도, 배려하지 못할 때도 있어서 ‘좀 더 잘 말할 수 있었지 않았을까?’ 하는 아쉬움이 항상 남아있습니다. 그렇지만 이러한 협업 경험을 통해 나의 의견을 잘 표현하고, 그리고 상대방의 의도를 파악하는 데에 있어 다시 한번 생각해 보는 계기가 되었습니다.

두 번째는 기술 도전에 대한 아쉬움입니다.

프로젝트 계획 중에는 새로운 기술적인 챌린지도 고려했었지만, 개발에 들어가니 기능 구현에만 집중하게 되었고, 기한 내 프로젝트를 완성하는 데에 급급하게 되었습니다. 개발이 진행되는 동안 전역 상태 관리의 필요성을 느껴 리덕스를 도입하였습니다.
리덕스가 아닌 다른 방법을 논의하기도 하였지만, 개발 진행 중 기술 조사에 시간을 투자하지 못하여 기존 사용 경험이 있는 리덕스를 사용하게 되었습니다. 더 좋은 방법에 대해 고민을 충분히 하지 못해 다소 아쉬움이 남는 부분입니다.

정신없이 3주가 지났는데, 매일 PR을 진행하면서 활발하게 코드 리뷰를 진행해주는 팀원들 덕분에 다양한 의견을 나누어 프로젝트의 들어오기 전보다 확실히 성장한 자신을 발견할 수 있었습니다.
그렇기 때문에 이번 첫 프로젝트는 여러모로 기억에 남고, 항상 배려와 존중을 생각하면서 성장해 나갈 수 있도록 하겠습니다.

ppthub-server's People

Contributors

donghyeon0908 avatar y-seonjong avatar 0jaaack avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.