1인칭 프론트 엔드 시점에서 바라본 첫 미니프로젝트 협업 회고.
와이어 프레임을 정하는 것 부터 프로젝트 완성까지
내가 어떤 생각을 했고, 어떤 성장을 했는지 돌아보고자 한다.
우선, 이번 프로젝트의 팀장을 맡았다.
사실 팀장의 역할을 하는 일이 처음은 아니다.
성격상 어느 무리의 팀장 역할을 하는 것 보다는
팀장을 보조하고 팀을 원활하게 움직일 수 있도록 돕는 역할이 나에게는 가장 잘 맞다고 생각하지만,
우연인지 운명인지 대부분의 팀 단위에서 내가 팀장급의 역할을 하게 된다.
스스로 전혀 다른사람들보다 뛰어나다고 생각하지 않지만,
팀 내의 다른 사람들이 나를 중심으로 일을 진행하거나,
내 말을 지지해주고 믿어주는 일은,
몸둘바를 모를 영광이고 감사한 일이며 조금 더 책임감을 갖게 된다.
이번에는 부트캠프에서 정해준 팀장이기 때문에 아예 물러설 곳도 없긴 했지만.
이번 주 가장 아쉬웠던 점은 배포를 성공하지 못했다는 것이다.
아무래도 JSON-SERVER 의 Mock data 로 서버를
있다고 가정하고 진행했을 때 보다 훨씬 많은 오류를 경험했으며
결정적으로 다 만들어놓고 배포에 실패하는 결과를 초래하게 되었다.
마감기간이 얼마 남지않아 정신없이 찾아본 배포실패의 이유는
http 웹 페이지에서 https 로 서버요청을 보내게 되면
Mixed Content error 가 발생한다는 것이었다.
따라서 vercel 에서는 자동으로 https 요청을 보내게 되는데,
서버는 http로 열려있어서 제대로 요청이 되지 않는다는 것이다.
http와 https 의 차이를 그냥 보안이 조금 더 좋다 정도로만 알았지
서버와 클라이언트의 통신간에 어떠한 규약과 제약이 있고
어떠한 문제가 발생하는지 전혀 알지 못했기 때문에 발생한 문제라고 생각한다.
이런 지식이 CS, 컴퓨터 사이언스 지식이라고 하는게 맞는지는 모르겠지만,
이런 내용의 기초배경지식은 비전공자인 나에게는 거의 없다시피 하다.
이번기회에 책을 사서 전공자 수준의 깊이는 아니더라도
틈틈히 알아보려고 한다.
어느 웹 페이지를 가더라도 회원가입 기능은 대부분 가지고 있다.
그 회원가입 기능은 사실 머리를 맞대고 맞대서 나온 결과물이라는 것을
이번주에 뼈저리게 깨달았다.
짧은 내 지식으로 생각하기에 프로그래밍은 한편의 소설과도 같다는 생각을 한다.
소설은 이제 막 글을 배운 초등학생이라도 쓸 수 있지만,
수작이나 명작이라고 일컬어지는 글들은 뭐가 달라도 다르다.
그 기준을 가르는건 소설의 짜임새, 얼마나 튼튼한 서사가 얽혀있는지에 관한 부분이 아닐까.
웹을 그리는 데에 그 서사의 첫번째 짜임새라고 할 수 있는 부분이 회원가입이라고 볼 수 있겠다.
회원가입의 경우에는 어떠한 정보들을 반드시, 혹은 선택적으로 받을 것인지
어떻게 구성된 정보들을 받을 것인지, 그 정보가 올바르게 입력되었는지 판단할 것인지
이런 논의들이 반드시 필요하다.
그 이후에 로그인은 조금 더 디테일한 논의가 들어가야 하는 것 같다.
사용자가 입력한 정보를 보내면 어떻게 인증을 증명할 것인지,
증명된 인증을 어떻게 전송해줄 것인지, 전송받은 인증을 어떻게 관리할 것인지,
관리중인 인증으로 무엇을 할 것인지에 대한 서사가 반드시 필요하다.
우리, 그러니까 아직 병아리 개발자인 우리들이 그리는 소설은
그렇게 탄탄한 서사를 생각하지는 못했던 것 같다. 그러므로 아주 단순하게 생각했다.
사용자가 서버에 올바른 정보를 담아서 서버에 인증을 요청하면
header에 token을 담아서 넘겨주고 그 토큰을 localStorage에 저장해서
서버 요청을 보낼 때마다 그 토큰을 같이 보내서 인증을 받는 식으로 구현했다.
이 과정에서 알게된 새로운 기술이 Axios의 interceptors 메소드.
const getToken = () => {
const token = localStorage.getItem("token");
return token ? `Bearer ${token}` : null;
};
instance.interceptors.request.use(async (config) => {
config.headers["Authorization"] = getToken();
return config;
});
instance.interceptors.response.use(
(response) => {
response.headers["Authorization"] = getToken();
response.status === 401 && localStorage.removeItem("token");
return response;
},
(error) => {
error.response.status === 401 &&
window.location.replace("http://naobab-fe-ky2k.vercel.app/");
}
);
우선 토큰을 받아오는 getToken 함수를 만든다.
이 함수의 역할은 단순하게 localStorage 에서 토큰이라고 이름붙힌 key와 벨류를 가져오고
만약 falsy 한 값이 아니라면 Bearer
라는 키워드를 붙혀 리턴하는 역할을 한다.
그 후, 만든 axios 인스턴스에 interceptors 라는 메소드를 사용하면
요청, 혹은 응답시에 저 인터셉터를 반드시 거치게 된다.
그래서 status code가 401, 비인가 사용자 라면 다음 요청을 수행하지 못하도록
코드를 짰다.
위 코드는 이제 막 글을 배운 아이가 쓴 소설같은 느낌이라서
앞으로 더 많은 서사를 붙혀 탄탄하게 인증관련 로직을 구성해보고 싶다.
이 부분에 대한 공부는 비단 react 뿐 아니라 웹 페이지 전반적인 인증에 관한 공부이므로,
조금 더 폭 넓게 공부해야 할 필요성을 느꼈다.
언젠가는 음, 조금 더 짜임새 있는 글을 써서 누가보더라도 수작이라고 할 수 있도록.
첫 날 구상했던 프로젝트는 사실 조금 터무니 없는 스케일의 프로젝트 였다.
플로깅이라고 환경미화와 조깅을 합친 느낌의 활동을 돕는 웹 앱을 만들자는 논의가 됐었는데,
지도연동이나 이러저러한 기능이 들어간 웹이었다.
이쪽도 정말 재밌게 시도해볼 수 있다고 생각했지만 스코프가 너무 크다는 이유로 퇴자를 맞았고
결국, 이번 주 우리조의 프로젝트 컨셉은 그림일기였다.
Todolist를 canvas로 그림을 그리는 일기장 형식으로 개량한 버전이라고 생각했다.
사실 canvas를 사용해서 그림을 그리는 것은 이전에 노마드코더 강의로 경험해본 적이 있기에
크게 어렵다고 생각하지 않았고 너무너무 귀여운 의견이었기에
팀원들도 다들 웃으며 프로젝트에 열의를 띄었다.
그 열의에 미처 고려되지 않았던 점이라면, 우리가 첫 백 & 프론트 협업이었다는 점이다.
그림을 그리는 것 까지는 좋았는데
이 그림을 도대체 어떻게 서버에 저장할 것인가 아는 사람이 아무도 없었다.
처음으로 그림을 그리고 submit 버튼을 눌렀을 때,
그러니까 base64라는 생전 처음보는 형태의 url을 보았을 때,
기쁨보다는 당혹이 먼저 나왔다.
이 말도안되는 길이의 url을 정말로 서버로 저장할 것인가에 대한 논의를 처음엔 했던 것 같다.
매니저님의 첨언도 있었고 당연히 다들 고개를 음- 그럼 그렇지 하면서
방법을 찾기 시작했음에도 좀처럼 제대로 되지 않아서
시간을 굉장히 많이 소비했다.
결국에 성공했던 방법은
base64 -> blob -> Form Data 의 3단 변환 후
Form Data를 서버에 전송하는 방식이었다.
blob 이라는 것은 바이너리의 형태로 아주 큰 객체를 저장할 것이다- 라고 명시하는
자바스크립트 자료형이다.
그러니까, base64의 말도안되는 길이의 url을
이진 데이터 형태로 쪼개서 객체에 저장해버리는 아주 놀라운 기술이다.
이 blob을 Form Data에 담아서 보낸다.
Form Data는 단순하게는 폼을 쉽게 보내도록 도와주는 객체라고 볼 수 있겠다.
참고한 링크
요약하자면,
이미지를 base64 형태로 인코딩 한 후,
인코딩한 url을 blob 형식으로 잘게 쪼갠 객체형태로 저장한 뒤에,
나머지 자료들과 blob을 FormData로 묶어서
서버에 전송한다는 느낌이다.
막상 성공하고 난 뒤에는 크게 어려움이 없는 작업이었지만
처음 내가 그린 그림이 서버에 닿고,
그 서버에 저장된 그림을 다시 클라리언트로 내려받아
출력해서 보았을 때의 느낌이 아직도 잊히지 않는다.
이틀동안이나 그 문제에 대해서 씨름했으니까.
팀원들이랑 그 광경을 다같이 화면공유로 지켜보면서
같이 흥분하고 같이 환호성을 질렀던 그 순간이 너무 행복했다.
이번 프로젝트에서 가장 힘들었지만 즐거웠던 순간이 아니었을까 싶다.
프론트엔드는 웹의 대문을 장식하는 역할이라고 할 수 있겠다.
깃허브에서 그런 역할을 해주는 문서가 있는데
항상 처음부터 우리의 파일에 있으면서 모르는 척 했던 README.md 파일이다.
리드미는 우리가 깃허브에 올린 코드의 대문역할을 한다는 점에서 프론트엔드와 닮았다.
음, 생각해보니까 프론트엔드는 대문을 만드는 역할이고
리드미는 대문 그 자체니까 아예 다른개념이긴 하지만.
이 경우에도 통용되는 말인지는 잘 모르겠지만.
읽기 좋은 코드가 좋은 코드다. 라는 말이 있다.
리드미는 우리가 짠 코드를 대변하는 역할이기도 하다.
무슨기능을 구현할 것이고, 누가 어떤 파트를 맡았고, 어떤 컨벤션을 적용했으며,
주요기능은 무엇이고 하는 것들에 대한 설명서 라고 할 수 있겠다.
그러면 그 설명서를 예쁘게, 보다 읽기 쉽게 만들어 놓으면
좋은 리드미가 되는 것이다. 라고 생각했다.
팀장이고, 그래도 첫 협업 프로젝트니까 내가 리드미 파일을 조금 꾸며보고 싶었다.
MarkDown 형식의 파일은 벨로그와 노션으로 어느정도 익숙해져 있다고 생각했지만,
깃허브의 리드미를 만드는 건 처음이었다.
양식이라는게 특별히 존재하는지를 우선 찾아봤다.
당연히 특별한 양식이랄 것은 없었지만 통상적으로 명시해 줄 내용들은 있었다.
여러 프로젝트의 리드미를 참고했고 마크다운 코드도 뜯어봤다.
창조는 모방에서 나온다고 여기저기 참고해서 만들어 냈더니
그래도 리드미라고 봐줄만한 결과물이 나왔다.
조금 아쉬웠던 건 트러블 슈팅에 관한 부분이었다.
어느 매니저님은 사실 저런건 트러블 슈팅이라고 할 수 없고,
어떠한 성능의 문제를 어떻게 바꾸었더니 성능이 이정도로 좋아졌다 식의
코드 개선에 대한 방향을 적는게 트러블 슈팅이라고 하셨다.
적극적으로 공감하지만 아직 병아리인 우리들이 그려낸 웹에서
성능에 관련된 로직을 생각해볼 준비가 되지 않았던 것 같다.
성능개선에 대한 로직은 항상 꾸준히 공부하려고 한다.
꾸준하게 이야기를 들어왔던 부분이기도 하고
한국인 특성상 나조차도 로딩시간이 길어지면 주저없이 뒤로가기를 누르게 되기 때문이다.
병아리를 벗어나, 그래도 조금 더 성능 최적화에 대한 고민을 할 수 있는
프로젝트를 진행하게 된다면 반드시 경험해보고 싶다.
react 에서는 심지어 그를 위한 Hook 도 존재한다.
그를 위한 개발자 도구도 존재한다.
대문을 장식하게 되었지만, 정작 다른 고민들을 많이하게 됐던 것 같다.
항상 느끼는거지만 나는 인복이 넘쳐나는 사람인가보다.
매주 좋은사람들과 좋은 생각과 경험을 공유하고,
한 사람도 싫은소리 없이 새로운 시도를 하고 같은 목표를 향해서 달리는 과정이,
가끔 몸이 힘들어 정신조차 나약해 질 때의 나를 붙잡아 준다.
아니, 미니 프로젝트도 이렇게 즐거운데
6주나 하는 실전 프로젝트는 대체 얼마나 즐겁다는 거지 ?
🥰