이번 회고 글까지 총 4번의 MIL을 작성했지만, 기존 팀원들과 헤어지고 작성하는 MIL은 뭔가 더 무거운 느낌이 드는 것 같다.
1차팀때도 그랬지만 많이 부족한 본인을 함께 앞으로 나아갈 수 있게 도와준 팀원분들께 항상 감사한 마음을 가지고 있고, 더군다나 이번 팀 프로젝트 기간동안은 정말 정신이 하나도 없었기에 시간이 너무 빠르게 지나간 것 같다.
그래서 더욱 무거운 느낌이 드는 것 아닐까..
아무튼, 데브코스 2차 소인성팀과 함께한 난생 첫 팀 프로젝트 활동을 회고하고자 한다.
' 모모 '란?
모두의 모임을 위한
모모
는, 누구나 모임을 만들고 또 참여할 수 있도록 도와주는 모임 일정 관리 앱입니다.
취미, 학습, 네트워킹 등을 함께 하기 위해 쉽고 빠르게 모일 수 있는 플랫폼을 제공합니다.
'오픈 API를 활용한 검색 웹 사이트 제작 프로젝트' 라는 정해진 틀 안에서 아이디어를 구상하게 되었다.
제한된 범위 내에서도 팀원들과 함께 10여가지의 다양한 아이디어를 떠올렸고, 이 좋은 아이디어들 중에서도 지난번에 유용하게 활용했던 '타임테이블' 기능을 유저들이 조금 더 편리하게, 다양한 기능을 접할 수 있게 만들어보게 되었다.
팀 프로젝트를 진행하며 전반적으로 모두가 지켜야 할 규칙을 정한 부분이다.
이때 가장 좋았던 부분은 팀 회고에서도 모두 동의했던 야간 등대이다.
야간등대란 9시~14시의 코어타임 이후에도, 팀원들 모두 자발적으로 20시~24시까지 디스코드에 참여하는 제 2의 코어타임이다.
야간등대 덕분에 프로젝트에 대한 질문 사항, 추가 요청 사항 등을 신속하게 처리할 수 있었고 진행 속도를 더욱 증진시킬 수 있었다.
팀원 개개인의 일정으로 매일 참여하기 힘들었을 것임에도 불구하고, 다들 참여해 주셔서 너무 감사했다.
또한 팀으로써 더욱 더 함께하고 있다는 생각이 들었던 야간등대이기에, 다음 팀에서도 적용되었으면 하는 생각이 들었다.
스프린트를 0~5 단계로 나누고, 각 단계마다 목표를 설정하고 달려나갔다.
스프린트 목표는 크게 위와 같았다.
각 단계별로 task를 나누어, 함께 맡은 과제를 처리해나가는 과정 자체는 굉장히 즐거웠다.
책임감을 가져야하는 부분이기에 어깨가 가볍진 않았지만, 모두가 으쌰으쌰해서 무언가를 만들어가는 과정이 너무 행복했던 것 같다.
사실, 크게 티는 내지 않았지만(아닌가?) sprint 0의 셋팅들때부터 심적으로 많이 힘들었던 것 같다.
팀 프로젝트 경험이 전무하다보니 위 셋팅들에 대한 지식도 없었다.
그러다보니 팀원들의 셋팅에 무언가 도움을 드리고 싶어도 아무것도 할 수 없는 자신이 너무 무력했다.
조금이나마 도움이 돼보고자 밤새 부족한 부분 찾아보고 연습하였지만, 팀원과의 간극이 그리쉽게 좁혀지진 않았다.
시간 적 여유가 있다면 좋았겠지만, 팀 프로젝트는 약 1달이라는 짧은 시간만이 주어졌기 때문이다.
당시에 나는 아무것도, 혹은 별 도움이 되지 못했다.
라는 결과만을 보며 많이 힘들어했던 것 같다.
++ 23일 화 시니어 프론트 개발자 테오께서 데브코스에 특강을 오셨다.
내용은 피그잼의 '테오의 스프린트' 템플릿을 토대로 팀 프로젝트를 조금 더 좋은 방향으로 진행할 수 있게 도와주는 것이었다.
이때, 테오가 말씀주셨던 말이 기억에 남는다.
팀에서 실력 편차가 있을 수 밖에 없다.
그럴 때는 잘하는 사람이 더 잘할 수 있도록 도와줄 수 있게끔,
모르는 것은 부끄러워하지 말고 계속 물어봐서 그들이 더 잘 도울 수 있게 해라.
(테오 강의내용 중)
생각해보면 내가 100% 모르지도, 팀원이 100% 아는것도 아니었던 것 같다.
내가 모르는 부분은 당연히 있을거고, 이때 내가 어떻게 행동해야할지를 잘 몰랐던 것 같다.
(물론 대부분을 모르긴 했다..)
그럴때 나는 팀에서 해당 내용을 잘 수행할 수 있는 사람이, 그것을 잘 수행할 수 있도록 윤활제같은 역할을 했다면 어땠을까? 하는 생각이 든다.
예를 들어, 우리 팀은 부모 컴포넌트로부터 받아오는 인자의 개수에 따라 interface를 사용할 것인지, type 별칭을 사용할 것인지를 분리했다.
또한 코딩 컨벤션에 interface를 사용할 경우 네이밍 앞에 I를, type의 경우 맨 뒤에 Type을 붙이는 것으로 정했다.
하나 문제가 있었는데, 내가 Icon 공통 컴포넌트를 만들 때였다.
만약 컴포넌트 명이 Button이고, 부모로부터 여러개의 props를 받는다면
interface ButtonProps {
~
}
interface IStWrapper {
~
}
interface 네이밍은 앞에 I를 붙이기로 정했다.
다만, 컴포넌트에 대한 타입을 지정할 땐 interface임에도 앞에 I가 아닌 맨 뒤에 Props를 붙여야 한다.
다만, Icon의 경우
interface IconProps {
~
}
위와 같이 앞에 대문자 I가 붙으며 마지막에 Props가 붙는다.
팀이 정한 정규표현식으로 걸러내지 못하는 상황.
그렇다고 부모에게서 받는 props 갯수를 줄여, type을 사용하기에는
type IconType = {
~
}
type 별칭을 사용함에도, 마찬가지로 맨 앞에 I가 붙어버린다.
type 역시 맨 앞에 대문자 I가 오면 안되고, 뒤에 Type이 붙어야한다고 컨벤션을 정했기 때문.
위와 같은 상황에서, 본인은 어떻게든 정규표현식을 잘 작동되게끔 수정하려 노력했던 것 같다.
결국 혼자서 해결하지 못하자 팀원들에게 문제 공유만 하였고 문제 해결에는 별다른 도움은 주지 못하였다.
회고를 작성하며 다시금 위 상황을 돌이켜보자면, 다음과 같은 문제가 있는 것 같다.
사람과의 대화를 통해 문제를 해결하지 않고, 코딩으로 문제를 해결하려 했다.
모 엘리베이터 회사에서의 예시처럼 말이다.
A, B 두 엘리베이터 회사는 고객으로부터 엘리베이터 속도가 느린 것 같다는 컴플레인을 받는다.
이때 A 회사는 수백억을 들여 기존보다 30% 빠른 엘리베이터로 교체하였다. 그러나, 고객으로부터의 답변은 '기존과 별 차이가 없는 것 같아요.'
B회사는 단지 엘리베이터 앞에 큰 거울 하나를 설치하였다.
그러자 고객들은 거울을 보며 시간을 보내게되자 컴플레인이 점차 줄어들게되었다.
이 일은, 고객 컴플레인은 결국 느껴지기에 실제로 엘리베이터 속도가 느린 것이 아닌, 단지 느린 '것' 같아요 라는 지겨움에서 온 것이기 때문이다.
즉슨, 이때 나는 잘 만질줄도 모르는 정규표현식을 이렇게 저렇게 수정하려 하는 것이 아닌, 팀원들과 대화의 장을 열어야 했던 것이다.
그러지않고 잘 모른다는 핑계로 결정권자의 대답을 기다리고 있었었다.
요약하자면
1. 사람으로 해결하지 않고 코딩으로 문제를 해결하려 했다.
2. 결정권자가 조금 더 쉽게 문제를 해결할 수 있도록 윤활제 역할을 하지 못했다.
다음번에 유사한 문제가 생긴다면
' 코딩 컨벤션이란 결국 우리 팀원들이 코딩을 하면서 조금 더 통일되고 훗날 공통 컴포넌트 사용, 리팩토링 등에서 조금 더 코드를 통일성 있고 쉽게 읽기 위함 아닌가?
그렇다면 앞으로도 다양한 예외가 나타날 수 있으니, 통일성 있게 interface면 맨앞에 I만, Type에는 뒤에 ~Type만 붙이자~ '
처럼, 결정권자가 조금 더 매끄럽게 문제를 해결할 수 있게 도움이 될 수 있게 행동했으면 좋았을 것 같다.
sprint 2에서 본인이 맡았던 Page UI는 본문 페이지.
(예시 사진)
처음 만들어보는 댓글창이기에, 댓글창을 input 태그로 할 지, textarea로 할 지 고민이었다.
input 태그는 개행이 되지 않았기에, textarea를 선택했다.
(textarea를 적용시켰을 때.)
다만 textarea도 문제가 있었는데, 계속 개행을 하다보면 위 사진처럼 이전에 작성했던 댓글창이 보이지 않는다.
이에 팀원들과 얘기를 나눠봤는데, 어떤 팀원분께서 깃허브 코드리뷰 할 때 댓글창에서도 개행 기능이 없으니 상관없지않을까? 라는 의견을 주셨다.
물론 이는 좋은 의견이었다.
말씀처럼 크게 고려하지 않아도 되는 부분이었지만, 이번 팀 프로젝트에서 내 목표인 조금 더 나은 유저 경험을 위한 코드
를 위해 내 의견을 조금 밀어붙였던 것 같다.
(..지금보니 조금 부끄럽넹)
여하튼 문제를 해결하기 위해, 개행을 할 때마다 textarea height 값이 점차 커지게끔 변경해야 했다.
우선 이를 위해 벨로그의 댓글창 기능을 분석했다.
쉽게 해결할 줄 알았지만, 조금 까다로웠던 부분이 있었다.
우리에게는 고정된 font-size 값이 있었다.
때문에 조금 더 안일하게 생각한 부분인데, 단순하게 현재 상황에만 딱 들어맞게 코드를 작성하면 문제가 해결될 줄 알았던 것이다.
const [text, setText] = useState('');
const [line, setLine] = useState(0);
const textareaHeight = 81.5;
const onTextareaChange = (e) => {
setText(e.target.value);
setLine(e.target.scrollHeight - 80);
};
return
<textarea
value={text}
style={{ height: `${textareaHeight + line * 16}px` }}
onChange={onTextareaChange}>
</textarea>
(지금은 존재하지 않는, 백업해뒀던 코드만 가져온거라 이전에 작성했던 코드인지 아닌지 확실치 않아서 조금 아쉽다..)
구현을 위해 다음과 같이 생각했다.
1. 유저가 댓글을 입력한다
2. 유저가 입력한 댓글의 총 개행 수(라인 갯수)를 알아낸다.
3. 팀이 정한 font-size 값은 16px이니까 거기에 맞춰 textarea의 height를 재설정한다.
하지만 이리 쉽게 생각 할 일이 아니었다.
여러 문제가 있었기 때문..
처음에는 개행할 때 마다 단지 23.3333...334px씩 늘어난다고 생각했다.
/* 16px
80 - 80 = 0
86 - 80 = 6
109 - 80 = 29
131 - 80 = 51
154 - 80 = 74
177 - 80 = 97
200 - 80 = 120
223 - 80 = 143
6, 23, 17, 23, 23, 23, 23, 23
*/
(물론 개행이 일어날 때 마다 고정된 23.333...34px 은 아니고, 중간중간에 한 번씩 변수가 있었음 ㅠ)
다만 이는 크나큰 착오.
알고보니 border, padding, scroll 너비, 그리고 브라우저(사파리, 크롬, 브레이브...) 등등 정말 많은 요소들에 의해 개행시 늘어나는 height 값이 변경된다는 것.
즉 코드에서의 textareaHeight라는 변수는 다양한 요인에 의해 결정되어야 하는데, 고정된 이 값은 약간의 css 변화만으로도 크게 문제가 될 수 있었다.
게다가 관리자 도구를 열어 살펴보니, textarea의 border 값에 1px을 부여한다고 온전히 1px을 가지고있진 않더라고.
분명 나는 1px을 부여했는데 .75px을 가지고 있었다.
정말 세밀하게 소수점 단위로 css를 일일이 부여해서 문제를 잡을 순 있었겠지만, 음.. 이건 좀 아닌 것 같았다.
그리고 브라우저마다 px들이 다 달라질텐데, 그럼 모든 브라우저들을 다 고려한 코딩을 해야하는 것인가? 하는 생각도 들었다.
또한, 화면에 보여지는 문제 외에도 기능적으로도 문제가 있었다.
기존에 작성했던 댓글을 '수정' 하려한다면, textarea가 작성되었던 댓글 height만큼 늘어나있어야 하는데, default height 값만을 가지고 있고 추가적으로 입력한다던가 지운다던가 등의 변화를 가해야만 height가 댓글에 맞게끔 수정된다는 것..?
그리고 '개행' 이라는게 \n을 나타내는데, 만약 ㅁㅁㅁㅁㅁㅁ... 를 계속 입력해서 자동 줄바꿈으로 인한 개행은 어떻게 처리해야 할 것인가..?
인터넷에 나와 유사한 상황인 사람들과 이를 해결한 코드들이 많이 있었지만, 문제를 해결하진 못했다.
이에 '프로젝트 기간 내에 완성하지 못한 결과물은 쓰레기!'라는 말이 생각이 나서 더욱 불안해져갔던 것 같다.
... 꽤나 고민하긴 했는데, 이 문제는 되게 허무하게 해결이 되었다.
사실 나처럼 기술적 고민으로 고생하시던 팀원분이 계셨다.
해서 그 팀원분은 다른 팀원들에게 자신의 문제를 공유하셨다.
그리고 나오는 답변. 라이브러리를 사용해봐라.
내가 가진 문제 역시 라이브러리 하나면 간단하게 해결 될 문제.
실제로 textarea-autosize 라는 라이브러리를 사용하니 손쉽게 문제가 해결되었다.
(아래는 댓글 입력 창)
...진짜 너~무 쉽게 해결되어서 어이가 없었다.
그렇다고 삽질한 시간이 낭비란건 아니지만, 팀 프로젝트임을 망각하고 있었던게 아쉬웠다.
혼자 무언가를 만드는게 아니라 팀원들과 함께 하는 것임에도 불구하고, 너무 혼자 고민했던 것이 아쉬움으로 남았다.
조금 더 팀원들과 소통하고, 잘 배울 수 있다면 팀에 더 도움이 되는 행동을 할 시간이 생기지 않았을까 하는 생각이 든다.
(sprint 0 이후, 하루도 빠짐없이 기록했던 흔적들)
깃허브 컨벤션, postman 셋팅 등등 전혀 손 대지 못했던 부분 이후로 생각했던 것이 있다.
더 이상 아무것도 하지못했던 사람이 아닌, 뭐라도 한 사람이 되겠다.
이를 위해 매일 기록을 하고 '내가 무엇을 했다'를 확실히 하겠다.
약간 TIL 느낌이 나긴 한데, TIL은 전혀 아니라고 생각한다.
내가 오늘 어떤 것을 구현 할것이고, 이 부분을 어떻게 구현할 것인지 단계를 적어놓았다.
그리고 하나하나 해결 해나가며 모르는 부분, 어려웠던 부분을 기록했다.
그리고 잘 안될때마다 약간의 욕설(...)을 포함하기에, 남에게 공개할 TIL은 아니라고 생각한다.
아무튼 이런 기록들 덕분에 사진 하단에있는 '공부해야하는 것' 페이지를 만들 수 있었다.
프로젝트 하면서 잘 몰랐던 부분, 더 공부하고 싶었던 부분, 적용시켜보고 싶었던 기술..
예를 들어, 우리 팀은 공부를 위해 상태관리 라이브러리로 Redux-toolkit을 사용하였다.
다만, 내가 맡은 본문 페이지에서는 state가 Top-Down 방식으로 흐르기에, zustand 라는 라이브러리를 사용해보면 어땠을까 하는 생각?
또한 리액트 쿼리의 필요성.
특정 상황에서 데이터가 캐싱되어야 하는데, 이를 간단히 해결할 수 있는 도구이기 때문.
데브코스 선배이신 1기분께서 조언주신 내용이다.
등등.
이런 기록들이 앞으로의 성장에 도움이 될 수 있겠구나를 크게 느꼈던 것 같다.
이런 '기록' 자체는 정말 좋은 것 같다.
앞으로 기록 자체는 노션이 되었든 블로그가 되었든 자주 기록 할 참이다.
물론 기록 및 공부 외에도, 팀 프로젝트 방법과 팀원들과의 소통 방법까지.
정말 많은 것들을 익힐 수 있었다.
물론 이는 정말 좋은 팀원분들께서 부족한 나를 잘 나아갈 수 있게 도와주신 덕임을 잊진 않는다.
그리고 내 테도에 대한 문제.
잘 모르더라도 적극적으로 다가가서 함께 궁리해보기.
누가보면 속된말로 나댄다라고 할 수 있다.
이를위해 무언가를 알고 있어야 한다, 지식이 곧 힘이다를 깨닫게 되었고
사실 상대방만큼 자세히 알 필요는 없되, 최소한 대화는 할 수 있을 정도로 약간의 지식을 익혀두고 이를 바탕으로 밑작업을 준비해둔 뒤 상대와 대화해보기.
이번 프로젝트에서 얻은 생각으로는, 우선은 최소한 이정도만이라도 해보자. 를 얻게되었다.
나는 아직 여전히 많이 부족하다.
그러나 무지에 자책할 필요 없고, 아무것도 할 수 없는 것도 아니더라.
팀에 발생한 문제를 매끄럽게 해결해나갈 수 있도록 윤활제 역할 정도는 충분히 해낼 수 있겠구나를 알게 되었다.
그리고 태도의 중요성.
누군가가 일을 맡겼을 때 어떤 태도로 이를 받아들이느냐.
내가 조금 좋지 않은 태도를 보였고, 이는 남들이 다 알더라고.
반성하며 앞으로는 절대 이런 태도를 보이지 않을것을 다짐할 수 있었다.
이번 2차팀은 1차팀때보다 더 빨리 헤어진 것 같다.
팀 프로젝트 기간에 너무 정신이 없어서, 시간이 정말 눈 깜짝하니 사라졌다..
다들 정말 좋은 분들이셨는데, 이렇게 빨리 헤어진 것 같아 너무 아쉬웠다.
그리고 2차팀 소인성 멘토님과 마지막 면담을 나누었다.
마지막까지 정말 좋은 말씀들을 주셨고, 나도 멘토님의 가르침에 감사를 표했다.
아, 그리고 면담 다음날에 테오의 강의가 있어서 멘토님께서 테오관련 말씀도 하셨다.
그리고 실력에 대한 부족함에 많이 힘들어하던 모습을 보였었던 나지만, 지금은 좋아진 모습에
다음에 테오 스프린트 같은거, 참여할 수 있겠니?
네!
정말 자신있게 대답했다.
컴플렉스를 이겨내고 처음으로 내뱉었던 긍정적인 말인 것 같다.
아마 데브코스 4개월 중 가장 기억에 남을 순간 중 하나가 아닐까 생각된다.
그리고 다음 날 가진 테오의 특강에서 배웠던 것.
마지막으로 남는 것은 '사람과 추억'
이걸 남기는게 성공적인 협업.
나도 이번 팀원분들처럼, 도움을 잘 주는 사람이 되기 위해 노력해야함을 배울 수 있었다.