Intern Review
(주)이분에서 프론트엔드 개발자로 약 2개월간 인턴을 진행하였다. 짧은 시간이었지만 많은 것을 경험하고 배웠다. 아래는 대략적인 회사의 소개 및 현황이다. 이후 내가 인턴으로서 작업했던 내용들, 회사에 기여한 사항들을 중심으로 풀어내려 한다.
📌 회사 프로젝트 당시 현황
회사 : (주)이분 - UX라이팅 에디터를 개발하는 회사이다. 글을 쓰는 어떠한 상황에서, 어떠한 회사의 입장에서도 글을 일관적으로 작성할 수 있도록 수정/보완작업을 도와주는 프로그램을 개발 중이었다. 회사가 원하는 단어의 선택이나 문장 어미 등으로 문장을 다듬어서 회사에서 작성하는 모든 글을 일관성 있게 다듬어준다.
개발팀 : Frontend 1명 / Backend 1명
인턴합류 : 2023.04.10
개발팀의 개발시작 : 2023.03 ~ 🚧
개발스택 : React, Javascript, Sass, Github Action, AWS
내가 어떤 것을 할 수 있지?
약 1개월 정도의 기간동안 사내 개발팀은 최초버전의 프로그램을 개발하여 배포한 상태였다. 개발팀도 입사 약 2달(?) 정도 되었고 두 분 다 신입으로 입사하여 프로젝트를 진행하고 있었다. 내가 인턴으로 입사할 때는 배포를 마치고 부분적인 수정작업을 하는 과정이었다.
인턴으로 입사하기 전 데이터를 많이 다루고 가공해 볼 경험이 있었으면 좋겠다고 내심 기대했었다. 프론트엔드에서 개발팀과 협업하는 과정이 실제로 어떻게 이루어지는지 궁금했기 때문이다. 다행히도 이분회사는 많은 데이터를 다루며 프론트딴에서 가공하기도 하고, 백엔드에서 가공하여 보내주기도 했다.
우선적으로 개발팀에선 프로젝트에 대한 이해와 컴포넌트 구조 및 코드를 보는 것이 도움이 될것이라고 했다. 첫째 주에는 하루종일 컴포넌트 구조와 코드를 보며 어떻게 프로그램이 실행되는지, 콘솔을 찍어가며 데이터가 어떤 구조로 전달되고 어떻게 프론트딴에서 가공되는지 코드를 분석하며 보냈다. 사내 코드를 볼수록 개발부채가 조금씩 눈에 보이기 시작했고, 프로젝트에 지장이 가지 않을 선에서 코드 리팩토링도 해나갔다.
첫 회의에 참석
회사에서 처음에는 개발팀 회의에 인턴과 같이 회의하지는 않았다. 원래(?) 그랬었던 것인지 회사에 적응을 해주시려는 배려였는지는 모르겠지만 둘째주에 들어와서 처음으로 회의에 같이 참석하였다. 대표님과 개발팀 그리고 언어 데이터베이스팀 2분과 같이 회의를 진행했다. 현재까지 개발을 거치고 사용자에게서 피드백을 받으며 프로젝트에서 덜어내야 할 부분 필요한 부분에 대해 서로 의견을 나누는 자리였다. 회사의 프로젝트를 사용자의 입장에서 사용해 보며 불편했었던 부분이 잘 보였었던 것 같다. 내가 개발한 부분이 아니고 사용자의 시선으로 바라봐서 그럴지도 모른다. 개인적인 견해는 가지고 있었지만 회의에서 나에게도 어떤 부분이 필요할지 필요 없을지에 대한 의견을 구하셨다.
나는 위 빨간박스의 DropDown 기능이 전체적인 UI에서 사용자에게 직관적으로 다가오지 않는다고 생각했다. 사용자가 개인 프로젝트 폴더에서 직관적으로 이동하도록 구현하는 것이 사용자 플로우에서 더 쉬운 접근방향일 것 같다고 얘기했다. 실제로 내가 처음 웹에서 기능을 이용하면서 헷갈렸던 기능 중에 하나였다.
인턴과 함께한 회의 이후에 개발팀과 대표님과의 회의를 거쳐 최종적으로 DropDown 기능을 제거하는 방향으로 결정되었다. 이미 기능을 개발했었던 프론트 사수님께는 죄송했었던 마음이 들었다. 힘들게 작성한 코드와 기능을 날려버려야 하니까 쉬운 결정은 아니었을 것 같다. 내가 2번의 프로젝트를 진행하며 구현하지 못한 기능들의 코드들을 주석처리 했었던 기억이 떠올랐다. 그러나 프론트엔드 개발은 사용자 중심으로 이루어져야 한다고 배웠고, 나 또한 같은 생각이었다.
이후 개발팀회의에 지속적으로 함께 의견을 공유했다. 프로젝트의 방향성을 보다 사용자 중심에서 고려하게 되어 뿌듯하기도 했다.
핵심기능을 개발해보다
인턴 만료를 1주 반정도 남은 상황이었다. 이전 까지는 이미 개발된 프로젝트에서 유지보수, 코드수정 정도만 했었다. 회사에 좀 더 여유가 있었다면 관리자 페이지를 개발하는 큰 작업을 할 수 있었지만, 회사 상황이 그러지 못해 아쉬웠다. 그러던 중 대표님께서 현재 개발 프로젝트에서 문체를 바꿔주는 페이지를 실시간으로 구현하는 것에 도전해 보겠냐고 물었다. 나는 어떠한 도전도 준비되었기에 흔쾌히 수락하여 개발을 진행하기 시작했다.
현재 기능의 문제점은 사용자가 작성하는 페이지와 문체를 수정하는 페이지가 다른 것이었다. 문체 다듬기로 페이지가 넘어가고 난 뒤에는 수정할 수 없어 불편함이 있었다.
const pageId = params.id;
const [text, setText] = useState('');
const [textData, setTextData] = useState([]);
const [changedText, setChangedText] = useState([]);
const [isPageModalVisible, setIsPageModalVisible] = useState(false);
const [isPageSaveModalVisible, setIsPageSaveModalVisible] = useState(false);
const [isPageBackModalVisible, setIsPageBackModalVisible] = useState(false);
const [isEditPageTitleVisible, setIsEditPageTitleVisible] = useState(false);
const [isPageTitleValue, setIsPageTitleValue] = useState('');
const [loading, setLoading] = useState(false);
const [inputCount, setInputCount] = useState(0);
const [companyText, setCompanyText] = useState('');
프론트개발자와 백엔드개발자가 급하게 서비스를 개발하다 보니, 기능을 수정하기에 큰 어려움을 겪었다. 컴포넌트를 분리하면서 UI가 말썽이었는데, 당시 회사 스타일링툴을 Sass로 작성하고 있었으나 nesting이 되어있지 않았다. 인턴으로 와서 중간중간에 UI가 흐트러지지 않게 네스팅을 한 부분이 있었지만, 컴포넌트를 분리하려고 하니 여간 까다로운 작업이 아니었다. 또한, state가 상당히 많이 작성되어 있어 컴포넌트를 분리하며 props drilling에서 시간이 꽤 많이 걸렸다.
회사의 글 작성하는 부분은 Monaco Editor가 설치되어 구현되고 있었다. 당시 Editor 라이브러리 중 Monaco라는 것이 있는가 보다 했었으나, 현재 개발팀이 입사하기 이전 개발자들이 구현해 놓은 라이브러리였다. Monaco Editor를 수정하려 정보들을 긁어모아 봤지만, 해당 버전에 맞지 않는 경우도 많았고 결국엔 다른 Editor로 대체하면 어떻겠냐고 개발팀원들에게 제안해 보았다.
내가 제안한 Editor는 총 3가지 Toast UI Editor, Draft js, Quill Editor였다. 각각의 Editor에 장단점이 있었다. 그러나 최종적으로 Quill Editor로 개발하는 것이 어떻겠냐고 어필을 했었는데, 이유는 대중적으로 많이 사용한다는 것이었고 Reference가 많았다. 그리고 가장 중요했던 부분이 회사가 지향하는 프로그램이 미국의 Grammerly라는 회사였는데, 이 회사에서 Editor 라이브러리를 Quill Editor로 사용하고 있었다. 최종적으로 회사가 지향하는 방향인 Grammarly와 같은 Quill Editor를 사용하기로 결정되었다.
대표님께서 원하시는 개발의 방향이 위의 Grammarly와 같이 사용자가 입력하는 값을 실시간으로 반응하여 더 나은 단어로 교체해 줄 수 있는 기능을 원하셨다. 현재까지의 회사의 핵심기능인 이것은 페이지가 이동하면서 Suggestion 카드가 오른쪽에 구현되고, Editor로 바로 수정되지만, 내가 작성한 글을 수정할 수는 없었다.
Monaco에서 Quill으로
<Editor
id="teEditor"
width="60%"
// height="calc( 95% )"
// width="calc( 95%)"
height="80%"
defaultLanguage="text"
value={accessToken ? text : defaultData.PageList.text}
onChange={setText}
defaultValue=""
options={{
wordWrap: 'on',
automaticLayout: true,
wordWrapColumn: 'on',
glyphMargin: false,
glyphMarginWidth: 0,
glyphMarginLeft: 0,
folding: false,
hideCursorInOverviewRuler: true,
lineDecorationsWidth: 0,
lineNumbersMinChars: 0,
wrappingStrategy: 'advanced',
lineNumbers: 'off',
stickyScroll: { enable: false },
minimap: { enabled: false },
quickSuggestions: false,
renderLineHighlightOnlyWhenFocus: false,
overviewRulerBorder: false,
renderLineHighlight: 'none',
fontSize: '20px',
fontFamily: 'Pretendard',
contextmenu: 'false',
scrollbar: {
useShadows: false,
vertical: 'hidden',
alwaysConsumeMouseWheel: false,
handleMouseWheel: true,
},
}}
/>
<ReactQuill
className="quill"
value={text}
onChange={handleChange}
modules={{
toolbar: false,
clipboard: {
matchVisual: false,
},
}}
theme="snow"
sanitize={true}
/>
Editor를 Monaco에서 Quill로 교체하는 작업에서 큰 어려움은 없었다. 컴포넌트를 분리하면서 스타일링이 유지되도록 코드를 수정하는 것에서 시간이 오래 걸렸다. 직접 교체하여 적용해 보니, 오히려 이전 Monaco 작성 코드보다 훨씬 소스코드가 작았고 Editor를 작성하는 느낌이 자연스러워졌다. 크게 만져줘야 할 옵션은 없었고, 단지 작성 부분만 필요해서 toolbar: false로 껐다.
핵심기능 구현
문제는 Editor교체가 아니었다. 기존의 기능에서 교체할 단어들을 Suggestion카드 모달로 띄워주는데, 작성하는 단어가 교체해야 할 단어면 실시간으로 색상을 변경해 주어 사용자에게 표시해 주는 것을 개발해야 했다. 기존 코드에서 색상을 교체해 주는 작업은 단지 입력되는 text값을 다른 컴포넌트로 이동하여 태그에 담기도록 작성되어 있었다. 그중 변경이 필요한 것은 className을 작성해 변경해 주고, 필요 없는 부분은 p태그에 담기는 형식이었다.
그러나 내가 작성해야 할 상황은 실시간으로 Editor에 작성되는 text를 감지하여 색을 변경해주어야 하는 작업이었다. Editor에 접근하여 공식문서 함수를 보며 구현해 보려 노력했으나, 반쪽짜리 구현이었다. 실시간으로 통신하는 것은 데이터를 받아올 때, setTimeout으로 사용자의 입력값이 시작되는 0.3초 이후마다 통신하도록 구현했다. Editor에 작성하는 Text에 색상을 입히는 것은 기존 코드를 작성한 프론트 팀원의 도움으로 문제를 해결했다.
스스로에 대한 피드백
Editor작업에 들어가기 전에는 백엔드 팀원과도 여러 소통도 하고 코드도 같이 보며 문제를 해결했었고, 프론트 팀원과도 마찬가지였다. Editor작업에 들어간 후에는 홀로 작업에 열중하느라 현재 상황이 어떤지, 작업에 어떤 어려움이 있는지 공유하는 시간이 줄어들었던 것 같다. 아무래도 해야 할 작업들이 눈에 많이 보이고, 물리적으로 시간이 부족하다 보니 코드를 치는 시간이 늘어나 그랬던 것 같다.
커뮤니케이션을 적극적으로 하는 편인데도, 대표님께서 직접 개발을 제안해 부탁해 주시고 맨땅에 헤딩하는 격으로 라이브러리를 뜯어보고 하다 보니 소통이 줄어들었던 것 같기도 하다. 개발에 시간을 많이 할애하더라도 팀원과의 소통과 커뮤니케이션이 중요하다고 생각했다.
코드를 최대한 깔끔하고 가독성 있게 작성하려다 보니 개발이 늦어지고, 개발을 빠르게 하려고 하다 보니 코드의 가독성이 떨어지는 딜레마에 빠졌다. 당시 회사에 상황에선 빠르게 개발하는 것이 중점이었지만, 나는 인턴의 입장이고 내 코드를 팀원들이 보면서 기능을 추가로 구현하고 리팩토링할 것이라는 생각에 변수명에도 신경을 쓰고, 최대한 가독성있게 코드를 덜어내려 했었다. 팀과 그리고 회사상황에 따라 맞췄어야 하는 부분인데, 이 부분에서 회사와 핏을 맞추지 못해 아쉬웠다.
마무리하며
Editor Library를 처음 도입해보기도 했고 약 1주일간 공식문서를 달고 살았지만 쉽게 해결되지 않았다. 팀원들과의 소통과 도움을 통해 결국엔 해결하여 기억에 많이 남는 개발과정이 될 것 같다. 회사가 바라보는 Grammarly의 기능을 비슷하게라도 구현했다는 것이 뿌듯하기도 하다.
인턴의 자리에서 회사에 부분적으로 긍정적인 영향력을 행사할 수 있어 다행이었다. 내가 가진 이해도와 책임감 그리고 잠재력을 높게 평가받을 수 있어서 감사했다.
실제 개발팀 외에 다른 팀원들과의 소통은 어떻게 해야 하는지 배울 수 있는 뜻깊은 시간이었다. 개발실력이 뛰어난 개발자는 코드를 만들어 가지만, 커뮤니케이션이 뛰어난 개발자는 팀을 만들어 나간다고 생각한다. 이번 인턴을 통해서 팀을 만들어 나가는 방법과 앞으로 나아가고 있는 팀에서 협업이란 무엇인지 많이 배우게 되었던 것 같다.
'개발기록' 카테고리의 다른 글
[Next.js] context를 이용해보자! + TypeScript (0) | 2023.08.25 |
---|---|
RunBase ( 2 ) - 극한의 컴포넌트 재활용 (0) | 2023.08.13 |
RunBase ( 1 ) - 기획 (0) | 2023.08.01 |
Wecode 2차 프로젝트 회고록 (0) | 2023.04.20 |
Wecode 1차 프로젝트 회고록 (0) | 2023.03.02 |