갑자기 글을 쓰고 싶어졌다. 면접을 앞두고 내가 개발자로서 성장했던 시기를 생각해보는데, 매 순간 도전을 하고 그 도전에서 좋은 사람들을 만나서 성장했던 것이 큰 것 같다. 그리고 가장 최근에 했던 활동이 Mews 프로젝트나 React 튜터링도 있지만 그래도 이전부터 하고 싶었던 활동인 NEXTERS를 합격하고 활동하면서 기억에 남는 것이 많아 작성해보려고 한다. (사실 23기 활동 메일 날라와서 생각나서 쓴다 ㅎㅎㅎ..)
지원
사실 지원하면서도 긴가민가 했다. 지원을 한다는 것에는 확신이 있었다. 그만큼 하고 싶었던 활동이니까. 원래 지난 21기에 백엔드 파트로 지원하면서 서류 전형에서 떨어졌기 때문에 그런 점도 있었던 것 같다. 그래서 지원서에는 개발하는 과정에서 얻은 즐거움이나 열정을 담아쓰려고 노력했던 것 같다.
나는 절대 잘하는 사람은 아니였던 것 같다. 그러나 그렇기에 매 순간 학습하려고 노력했고 이러한 점을 담아 쓰려고 했다. 왜 개발을 시작했는지, 내가 개발을 어떠한 마음가짐으로 임하는지, 그리고 매 순간 학습을 한다는 것은 어떠한 생각인지를 담으려고 했다.
면접 준비
처음 서류 전형의 결과가 나왔을 때 많이 놀랬던 것 같다. 그래도 나의 진심이 닿았구나..? 하는 그런 뿌듯함도 있었던 것 같다. 면접을 준비하면서는 되게 다양한 것들을 공부하기보다는 지난 시간의 나의 활동을 되돌아보았다.
지원서에 쓰인 내용 대부분이 부스트캠프 활동이었는데, 부스트캠프 과정에서 했던 고민들과 선택의 근거 등을 다시한번 정리했다. 그리고 그 때 가장 신경을 많이 썼던, 그리고 아직까지도 신경을 쓰면서 개발하고 있는 '웹 접근성'이라는 키워드를 상기하면서 정리했다.
면접
사실 면접 경험은 굉장히 좋았다. 많은 운영진 분들이 면접자를 많이 배려해주시고 편안한 분위기에서 진행하려고 많은 노력을 해주셔서인 것 같다. 다만 내가 많이 떨었다 ㅎㅎ..
면접 질문은 평이했지만, 지원서를 기반으로 진정성이 있는지를 많이 보신 것 같다. 나는 웹 접근성에 대한 이야기를 자소서에 담아내려고 많이 노력했다. 그 이유는 가장 관심이 컸기 때문이다... 너무 당연한가...
그렇기 때문에 웹 접근성에 대한 질문을 받았다. 웹 접근성을 고려하는 개발을 하려면 구체적으로 어떠한 식으로 개발을 해야하는지에 관한 질문이었던 것 같다. 지금에야 개발을 하면서 많이 적용하려는 노력 덕에 어느정도 체화된게 있지만, 과거에는 '이론적으로 적용해야겠다..!'여서 대답을 할 때 어버버하면서 "alt 태그에는... ', '유저는 키보드로만 조작을...' 이런식으로 대답했던 기억이 난다.
그리고 네트워킹 시간이 많은데 개발자 분들을 만나며 어떠한 내용의 네트워킹을 하고 싶은지에 대한 질문을 받았었다. 거기서 나는 너무나도 대학생 그리고 개발자 준비생 같은 대답을 했다. '저는 개발자로서 ~~한 가치를 가지고 개발하고 있다. 다만 이 질문을 다른 개발자 분들께 했을 때 어떠한 답변을 하실지가 궁금하다.' '학생의 마인드가 아닌 현업 개발자들은 어떠한 가치를 가지고 개발하며, 어떠한 점들을 고려하는지를 묻고싶다.' 같은 뭔가 순수한..? 대답을 했던 것 같다.
그리고 마지막에 넥스터즈에서 무엇을 얻어가고 싶냐는 질문에서 '대학 생활로서의 마지막 개발, 그리고 사회인으로서의 개발 시작의 첫 페이지를 넥스터즈와 함께하고 싶다' 라는 흠... 역시 논술 대입 출신 다운 말을 했다.
그래서 면접 경험은 너무나도 좋았지만 스스로의 대답은 조금 아쉬웠고 심기일전하여 다음기수를 노려보자..!라는 야심찬 계획과 함께 사실 다른 연합동아리에 지원을 할까 고민하고 있었다...ㅎ.ㅎ..
합격
그래서 사실 떨어질 줄 알았다. 왜냐하면 나 스스로도 아쉽고, 사실 옆에 있는 분이 너무 말씀을 잘하셔서...
근데 붙었다. 그리고 붙고 나서는 내가 부족하다는 생각은 안하기로 했다. 그것이 뽑아 주신 분들에 대한 예의라고 생각했고, 모자라다면 맞춰가면 된다고 느꼈다.
하여튼 좋은 결과를 얻었고, 넥스터즈 활동하면서 1등도 하고 정말 좋은 분들 사이에서 개발자로서의 마인드와 배움을 얻었다. 더불어 정말 많은 좋은 사람을 만나서 다음 23기도 기다려진다.
하단 네비게이션바를 작업하면서 페이지를 전환과 현재 페이지 상태를 불러오는 기능이 필요했습니다.
이에 대한 방안으로
window.location.href를 파싱하여 문자열로 상태를 받고, 해당 문자열에 따라 state를 설정하고 이에 맞는 style을 부여한다.
onClick 이벤트를 사용하여 라우팅과 색 입히는 것을 동시
이 두가지 방법이 떠올랐고, 실행에 옮기고자 하였으나 여러가지 의문이 들었습니다.
window.location.href 파싱
url문자열을 받아오고 파싱을 하는 방법은 가장 떠올리기 쉽고, 직관적인 해결방법입니다. 눈에 보이는 요소를 통해 처리를 하기 때문에 그렇게 생각했던 것 같습니다.
그러나 몇가지 의문이 드는 점 또한 존재했습니다.
이전에 query string을 사용 할 때, 문자열 파싱을 이용했는데, 찾아보니 urlSearchParams ~ 속성을 활용하여 파싱하는 것을 학습했고, 이처럼 편한 방법으로 현재 주소 상태를 가져오는 방법이 있을 것 같다.
파싱을 하게되면 ‘/’기준으로 파싱을 할 것이다. 지금이야 프로덕트의 depth가 얕아서 ‘/’가 하나지만 추후 여러가지 depth가 생길 수 있음을 고려해야된다.
와 같은 고민을 하게 되었습니다.
이에 두번째 방식인 onClick 이벤트를 사용에 대해서 고민했습니다.
Onclick 이벤트 부여
선택에 대한 근거는 다음과 같았습니다.
어차피 Navbar에서 클릭을 통해 페이지가 전환되야하고, 전환되는 이벤트를 줄 때 같이 style을 부여하는 이벤트만 추가하게되면 해결되는 문제 아닌가? 라는 생각과 함께 진행을 했습니다.
여기서도 추가적인 고민을 했던 것이
Onclick으로 이벤트를 부여하고 색을 입히면 페이지가 전환될 때 이전에 부여됐던 컴포넌트의 색 클래스를 제거해주는 로직이 필요하지 않나? ex) A화면 : A아이콘(파란색), B아이콘(회색) → B화면: A아이콘(클래스 제거 → 회색) B아이콘(이벤트 추가 → 파란색) 이 과정이 불필요하다고 느껴졌고, 코드가 필요 이상으로 길어질 수 있겠다고 생각했습니다.
만일 현재 띄워져있는 페이지를 받는 상태를 이용해서 onclick을 사용한다면, 그래도 state를 써야하므로 이 상태 없이 가능할 수 있지 않을까?
사실 코드 안에 다량의 if문과 다량의 state를 쓰기 싫었습니다.
NavLink
결국 NavigationBar의 본질은 라우팅이라고 생각했고, 라우팅에 관련된 글을 읽어보다가 NavLink에 대해서 발견했습니다.
<NavLink> is a special kind of <Link> that knows whether or not it is "active".
This is useful when building a navigation menu such as a breadcrumb or
a set of tabs where you'd like to show which of them is currently selected.
It also provides useful context for assistive technology like screen readers.'
‘활성화’ 여부를 제공하는 Link의 종류이고, 현재 선택을 보여줘야하는 navigation menu를 만드는데 유용하다. 또한 여러가지 유용한 컨텍스트를 제공한다.
언뜻 별 차이가 없어보이고, 결국 isActive 상태 받아서 삼항연산 처리 했을 뿐, 위의 코드와 다를게 없지 않나..?라고 생각이 들기도하지만, 불필요한 prevPath 상태제거와, 직접 비교하는 연산을 제거해서 코드를 간결하게 했다는 점이 긍정적인 요소라고 생각합니다.
가장 큰 장점은 한번 설정함으로써 개발자가 불필요하게 현재 경로와 Link에서 사용하는 경로에 대해서 계속해서 신경쓰지 않아도 된다는 점 같습니다.
2022년은 참으로 의미가 깊고 쉽지 않은 한 해였다. 새로운 도전과 실패, 그리고 나름대로의 성공까지 모두 겪어볼 수 있었던 신기한해였으며, 참 많은 것이 변화했고 나의 방향에 대해서 갈피를 잡을 수 있었던 한 해라고 생각한다.
문닫고 들어가는 사람.
나는 항상 나를 표현할 때 복이 많은 사람, 문을 닫고 들어가는 사람이라고 말하곤 한다. 이 말인 즉슨, 나는 항상 어느 무리의 마지막에 걸쳐서 아슬하게 속할 수 있는 사람이라고 생각한다.
고등학교 시절 나는 그렇게 공부를 잘하는 학생은 아니였던 것으로 기억한다. 그냥 보통의 성적과 보통의 노력을 하고 그런저런 성적에 분해하지만 또 얼마 안가서 그 성적을 웃어넘길 수 있는 보통의 사람인 것 같았다. 그럼에도 욕심은 많아서 항상 더 높은 곳을 보고 내가 눈 닿아 있는 곳보다는 조금 더 너머의 위치를 바라본 것 같다.
대학을 고를 때도 마찬가지였다. 예전부터 나는 서울로 대학을 다녀보고 싶다는 생각이 컸다. 그러나 '그 수준의 사람들만큼 노력을 했는가?'에 대한 대답을 하라면 어렵기만 하다. 욕심이 많은 나는 목표를 이루기 위해 많은 사람들이 말렸던, 안될거라 했던 논술전형을 쓰고 운이 좋게 서울에 있는 학교에 입학했다. 입학한 당시, 그리고 몇개월이 지난 후에도 나는 이 학교에 다니는 것이 안믿겨져서 학교 강의실 단상 앞에 있는 학교로고가 어색했던 것이 꽤나 오래 지속됐던 것으로 기억한다.
그 다음은 부스트캠프였던 것 같다. 부스트캠프에 지원할 당시, 나는 개발을 공부하기 시작한 1년이 조금 넘은 경영대생이었다. 또 작년 초, 1월부터는 무슨 바람이 불었는지 개발을 시작했던 '프론트엔드보단 백엔드가 더 재밌어보인다.'라는 이유로 백엔드를 공부하겠다고 스프링강의를 몽땅 끊어가며 무지성으로 강의를 들으며 코드를 따라쳤던 기억이 난다. 그렇게 시간을 보내다가 부스트캠프 지원 공고를 보았다. 그리고 지원을 하면서도 당연히 떨어질 것이라고 생각했다. 그리고 1차, 2차 테스트를 보면서도 많이 모자람을 느끼고 앞으로 공부를 어떻게 해야할지 방향을 잡고 있었고, 챌린지 때도 많이 모자람을 느꼈지만 운이 좋게 나를 좋게 봐주셔서 멤버십 과정까지 갈 수 있었다.
부스트캠프를 하면서 정말 뛰어난 분들도 많이 만났고, 사실 '내가 제일 모자라다'라는 생각을 많이 했던 것 같다. 그렇기에 항상 내가 문을 닫고 들어온 사람이라고 생각했던 것 같다.
최근에는 넥스터즈라는 활동에 프론트엔드 개발로 함께할 수 있게 되었다. 개발을 시작할 때 모집공고를 본 20기, 21기부터 정말 해보고 싶었던 활동이었는데 이번 22기 모집에 지원을 했다. 준비를 하면서는 나름 열심히 준비한다고 생각했었다. 그러나 면접을 보면서 너무 긴장했던 탓인지 횡설수설하는 경우가 많았고, 원래는 대답할 수 있었던 부분도 많이 놓쳤던 것 같다. 실제로 자신있는 부분에 대한 질문을 받았는데도 잘 표현하고 싶은 마음에 이것저것 말하다가 본래의 질문의 의도와 멀어진 대답까지 이어진 경우도 많았던 것 같다. 그럼에도 어떠한 가능성을 봐주신 덕분인지 함께 할 수 있었고, 제 생각에는 이번에도 운이 좋게 문을 닫고 들어갔다고 생각하고 있다.
도전과 치열함
내가 위에서 '문을 닫고 들어가는 사람'이라고 말하긴 했지만, 사실 너무 운에 치부하기에는 저는 다 선발된 입장이고, 뽑아 주신 분들이 봐주신 것이 있기에 뽑아주신 분들에 대한 예의도 아닌 것 같아 제가 생각하기에 올해 살았던 스탠스와 내가 할 수 있었던 것에 대해서 회고를 남겨보자한다.
나의 올해는 도전과 치열함의 연속이었던 것 같다.
나는 항상 도전을 하는 사람이었다. 이건 올해 뿐만이 아닌, 매 순간이었던 것 같다. 기회는 도전을 해야 시작되는 것이고, 도전에 실패할 때마다 앞으로 내가 나아갈 방향이 명확해진다고 생각하기 때문이다. 올해도 역시 크게 부스트캠프와 넥스터즈에 도전을 했고, 좋은 기회를 받을 수 있었다.
그리고 그 과정에서 항상 치열했던 것 같다. 도전을 많이 한다고 그 기회가 소중하지 않은 것은 아니였다. 특히 부스트캠프의 챌린지 기간은 내 인생에서 가장 치열한 기간을 꼽으라면 이 시기가 꼽힐 정도였던 것 같다. 이 역시 링크로 대체하겠다.. 진짜 치열했다.. ㅎㅎㅎ..
그렇게 치열했기 때문에 나는 닿기 힘든 부분에 있어서는 놓쳤을지 모르더라도, 닿을 듯 말듯한 기회는 잡아낼 수 있었던 것 같다.
그리고 또한 '문을 닫고 들어간다.'라고 생각하는 것이 마냥 부정적으로 생각하는 것은 아니였다. 나는 항상 저렇게 생각했기에 더욱 노력했어야 됐고, 더 치열해야했다. 같이 하는 사람들이 너무 대단하고 좋은 사람들이었기에, 이들과 계속해서 함께가려면, 그리고 긍정적인 효과를 내기 위해서 더 치열하고 열정적으로 활동에 임했고, 그 결과 많이 성장할 수 있었던 것 같다.
포기
올해는 도전을 하고 성공도 했던 만큼 어느정도 포기도 했다. 이전에는 기획자의 꿈을 가지고 기획 공부도 병행했고, 상반기에는 개발자로 아직 준비가 되지 않았다고 생각하여 기획과 경영 직무로 많은 곳을 지원했고 IT 서비스 기업 중 원하던 기업의 최종면접까지 갈 수 있었다.
그러나 최종에서 약간은 아쉬운 결과를 받았고, 그 이후 도전했던 부스트캠프를 합격하면서, 조금 더 기획에 대한 꿈을 확신할 수 있었다. 그리고 그와 동시에 기획의 길을 포기하게 되었다.
정리하며
올해는 참 많은 것을 얻고, 포기하고, 배웠다. 길지 않은 인생을 살았지만, 그래도 가장 인상 깊었던, 농도가 진했던 시기를 꼽으라면 나는 단연코 2022년을 꼽을 것 같다.
기획과 프론트, 백엔드 사이에서 고민하던 1분기를 지나, 기획의 꿈을 향해 걸어가고 포기했던 2분기, 가장 치열하고 새로운 꿈을 향해 달렸던 3분기, 그리고 앞으로의 나를 준비해나가는 4분기까지.
매 순간 태우고 빛났던 이 시기를 기억하며, 언젠가 길을 잃을 때 과거의 가장 밝게 타는 2022년의 불을 보고 다시 돌아와 다시끔 이겨내고 앞으로 달릴 수 있을 것 같다.
사실 수료를 한지 약 이주의 시간이 되었고, 후기가 굉장히 늦게 쓰는편이라 감정이 온전하진 않지만, 한자 한자 기억을 살리면서 적어보려고 한다.
돌이켜보면 아무것도 모르는 상태로 들어가 그래도 이제는 무엇을 해결할 수 있는 개발자가 된 것 같아 지난 시간이 행복했던 시간이라고 생각된다.
학습 방법에 대한 이해
결과적으로 8주를 마치고 나니 스스로 효율적으로 학습하는 방법에 대해서 학습하게 되었다.
부스트 캠프에서는 바텀업 방식으로 기본적인 원리를 이해하고 이해를 바탕으로 더 효율적인 라이브러리가 있다! 그러니까 이런 원리로 작동하는데, 이걸 편하게 쓰려면 이걸 사용하자! 정도의 흐름으로 바텀업 방식의 학습을 했던 것 같은데, 이 방식이 솔직히 잘 맞는지는 않았던 것 같다.
기본에 대해서 학습할 때, 이것이 무엇을 위한건지에 대해서 이해하기 어려웠던 것 같고, 세세한 부분들을 모두 구현해야하다보니 되려 이해하기 더 어려웠던 것 같다.
후에 스프린트를 다 마치고 나니 나는 탑다운 방식의 학습 방법이 맞다는 결론에 이르었다.
8주동안 가장 깊게 학습했던 웹 프론트엔드 분야에서 리액트를 학습할 때는 래퍼런스도 많고, 공식문서도 잘 나와 있기 때문에 리액트 자체를 학습하는데는 어렵지 않았다.
그리고 오히려 학습 스프린트를 마치고 다시 첫주차, 두번째 주차의 코드를 봤을 때 비로소 보이는 것들이 많았다. 기본이 부족했기 때문에, 웹에서 프론트엔드는 어떠한 역할을하고, 어떻게 작동을 하고 이를 세세하게, 바닐라 자바스크립트로 작성하기 위해서는 어떻게 해야하는지.
이 순서로 학습하는 탑 다운 방식의 방법이 나에게 효율적이라는 것을 깨달았다.
8주간, 솔직히 비약적으로 많이 늘었다. 라고는 말하기 힘들었지만 학습 방식을 알았고, 이를 바탕으로 후에 이어질 그룹프로젝트에서의 효율적인 학습을 할 수 있었기에 학습 방법을 알아간 점만으로도 충분하다고 생각한다.
코드리뷰
먼저 코드 리뷰가 도움이 많이 됐고 많이 늘었던 것 같다.
이는 부스트캠프의 챌린지부터 성장되었던 역량인 것 같다.
항상 내가 생각하는 것은 코드를 작성하는 것은 한편의 글을 작성하는 것과 같다고 생각하며 각자의 코드마다 글쓰기 습관처럼 각자의 성향이 뭍어나온다고 생각을한다.
책을 읽을 때도 독특한 방식으로 책을 쓰거나, 어려운 문체가 사용되면 읽기 어려운 경우도 많다. 예를 들어 내가 처음 베르나르 베르베르의 책을 접할 때, '신'이라는 책으로 처음 접했는데, 이때 책의 전개 방식과 자주 변경되는 시점으로 인해 읽기 어려워했던 기억이 난다.
이와 마찬가지로, 코드를 작성할 때도 개인의 성향이 많이 묻어 나온다. 추상화를 하는 기준도 다르고, 컴포넌트를 분리할 때도 최대한 작게 혹은 역할과 관심사에 따른 분리, 또는 상태에 따른 분리 등 다양한 방법으로 설계하고 작성한다.
차이점은 책은 상대적으로 타인의 문체를 접하기가 쉽지만 코드는 상대적으로 어렵다는 점에 있다. 그리고 더욱이 상대방이 코드를 썼던 논리와 이유를 듣는 기회는 흔치 않다.
하지만 부스트캠프에서 하는 코드리뷰에서는 이러한 기회가 많이 생겼다. 매주 3명의 동료들을 계속해서 바꿔가며 만나면서 다양한 코드를 접했고, 리뷰하면서 좋은 점을 배우고 모르는 점을 질문을 할 수 있었다.
해당 기회를 통해 많은 좋은 점을 배웠고, 이전에는 백지 상태였던 나였기에 지금의 코드에는 내가 배우고자했던, 철학이 확실했고 공감했던 분들의 코드가 나의 방식으로 재해석되어 작성되어 있는 것 같다.
더불어 타인의 코드를 보면서 이해하기 위해 모르는 부분을 더 섬세하게 공부하고, 이해하려고 했던 노력으로 인해 얻었던 성장은 정말 큰 도움이 되었던 것 같다.
공식문서
학습을 하면서 정말 많은 래퍼런스를 보았다. 특히 블로그를 많이 본 것 같은데, Nest를 학습할 때는 블로그를 많이 찾아봐도 내가 원하는 내용이 없을 때도 있었고 버전이 자주바뀌는 라이브러리의 경우는 나의 버전과 달라서 적용이 되지 않는 경우도 있었다.
그렇기 때문에 공식문서를 찾아보기 시작했고, 실제로 도움이 많이 된 것 같다.
부스트캠프를 하면서 처음에 공식문서를 보는 것이 도움이 된다는 말을 많이 들었다. 공식문서에서 해당 라이브러리, 프레임워크의 철학과 가장 정확한 사용 방법을 알 수 있다는 내용이었다.
처음에는 읽기 힘든 공식문서보다는 간단하게, 그리고 읽기 좋게 쓰인 블로그를 선호했다.
사용된 예시도 많았고, 솔직히 코드를 가져다 쓰면 되는 경우도 많았기 때문이다.
하지만 이번 계기를 통해 공식문서를 보는 습관을 가지게 되었고, 공식문서를 보면서 기초를 학습하고, 이를 활용하는 방법에 대해 고민하면서 더 깊은 학습을 할 수 있게 되었다.
솔직히 아직까지 프레임워크에 대한 철학을 알아가는 기쁨은 발견하지 못했지만, 이러한 학습 방식을 계속하여 나아가다보면 나도 그런 기쁨을 알지 않을까.. 하면서 학습을 계속해서 해보고자 한다.
마치며
참 많은 것들을 배웠지만 작성하고 나니 짧은 글이라 아쉬움이 남는 것 같다. 회고를 조금 미리미리 써볼 걸 그랬다..
하여튼 이번 기회는 내가 개발자라는 길에 대한 확신을 가지게 된 계기였으며, 가장 밀도 높은 5개월이었다고 생각한다.
비록 부스트캠프는 끝났지만, 여기서 배웠던 많은 분들의 태도와 자세, 그리고 학습 방식은 앞으로의 개발을 함에 있어서도 계속될 것이다.
그리고 '지속 가능한 개발자'라는 키워드를 끊임 없이 고민하며 계속하여 나아가고 있지 않을까 싶다.
“검색에 모르는 사람을 찾으려고 글자를 하나하나 치는 사람보다는 키워드를 정해놓고 치는 사람이 많을 것이다.”
해당 가정에 시작해서 유저가 모든 키워드를 입력하고 난 후, 검색을 실행하기로 결정했습니다.
개선 과정
기존의 키보드 입력을 통한 값의 변화마다 이벤트가 호출 되던 것을 입력을 마친 후 500ms 동안 추가 입력이 발생하지 않을 경우 이벤트를 호출.
입력이 계속 되면 clearTimeout이 실행되어 검색을 하는 함수가 들어있는 timer를 지우게 되어 검색이 일어나지 않음.
검색을 멈추면 clearTimeout이 작동하지 않고, timer가 500ms를 기다린 후에 내부에 있는 setSearchedUser를 실행함.
개선 결과
기존 ‘핏토리’라는 검색어 입력시, 7번의 이벤트 호출이 발생하던 것을 1회 호출로 최적화.
불필요한 이벤트 호출 방지.
API 호출 방식 개선기
새로운 문제의 발생
테스트를 진행하면서 저희팀은 Mock data로 5000명의 유저를 넣었습니다.
그러다보니 이전에는 발생하지 않았던 모든 유저 리스트를 받아오는 것에서 문제가 발생했습니다.
생각보다 검색 페이지를 로딩하는데 불필요한 지연시간이 발생했습니다.
Problem1. list를 불러오는데 240ms라는 시간이 걸림. → 유저 볼륨이 커지면 더 오래걸릴 것
834ms 중 유저 리스트를 받아오는 것이 240ms가 소요됨.
하단 list의 경우 추천친구 데이터 → 디폴트로 필요한 값임.
Problem2. 불필요한 상황에서 API 호출이 일어남.
개선 사항
유저 검색을 처음에 한번에 불러오지 말고 필요에 따라 불러오자.
→ 유저는 검색이 아닌 추천 친구를 보러만 들어올 수도 있는데, 초기 속도가 느리면 불편하다.
검색 자동완성 ver3
// 검색 결과로 나온 유저가 담긴 배열.
const [searchedUser, setSearchedUser] = useState<SearchedUserInfo[]>([]);
// searchValue가 바뀔 때 마다 검색을 시작.
useEffect(() => {
return SearchUtils.searchUserByKeyword(searchValue, setSearchedUser);
}, [searchValue]);
const SearchUtils = {
searchUserByKeyword: (
searchValue: string,
setSearchedUser: React.Dispatch<React.SetStateAction<SearchedUserInfo[]>>,
) => {
const timer = setTimeout(async () => {
//값이 없을 경우 api 요청을 하지 않음.
if (!searchValue) return setSearchedUser([]);
const userList = await UserAPI.searchUserByKeyword(searchValue);
// 반환할 결과가 없을 때, 빈 배열로 반환
if (!userList) return setSearchedUser([]);
return setSearchedUser(userList);
}, 500);
return () => clearTimeout(timer);
},
}
Keyword
UX - 사용성 개선, 불필요한 요청 방지
개선 과정
기존에 한번에 불러오던 유저 리스트를 검색어 입력시 해당 키워드에 맞는 유저를 가져오는 방식으로 변경.
처음에 유저 리스트를 가져오지 않으므로 초기 렌더링 속도 상승
검색하는 키워드가 없으면 API 요청을 날리지 않음
const timer = setTimeout(async () => {
//값이 없을 경우 api 요청을 하지 않음.
if (!searchValue) return setSearchedUser([]);
const userList = await UserAPI.searchUserByKeyword(searchValue);
// 반환할 결과가 없을 때, 빈 배열로 반환
if (!userList) return setSearchedUser([]);
return setSearchedUser(userList);
}, 500);
개선 결과
빈 값일 때 API 요청이 날아가지 않음
기존의 약 800ms가 소요되던 것을 480ms로 축소 시킬 수 있었음.
이를 통한 더 빠른 초기 렌더링을 통해 사용성을 개선할 수 있었음.
후기
항상 구현을 하는 단계에서 프로젝트가 끝나면 성능에 대해서 신경을 쓰지 못하는 경우가 많았습니다.
그리고 평소에 ms의 단위로 인한 지연은 크게 고려하지 않았고, 항상 확장 가능성에 대해서 고려를 안했던 것 같습니다.
그러나 이번 기회를 통해 유저가 나 혼자일 때의 환경과, 5000명, 그리고 그 이상을 불러올 때 얼마나 큰 변화를 가져오는지 알게 되었습니다.
이번 과정을 통해 성능 개선에 대해서 큰 관심이 생겼고, 추후 개발을 진행할 때 성능 개선을 하는 것에 흥미를 가지고 임할 수 있을 것 같습니다.
이번 프로젝트 뿐만 아니라 개선하는 과정에서 정말 많은 질문들을 했고, 어쩌면 당연하다고 생각되는 질문들도 확실 하기 위해 한번 더 할만큼
import sys
N, M = map(int, input().split())
r, c, d = map(int, input().split())
arr = []
visit = [[0] * M for _ in range(N)]
for _ in range(N):
arr.append(list(map(int, sys.stdin.readline().strip().split())))
#북, 동, 남, 서
moves = [[-1, 0], [0, 1], [1, 0], [0, -1]]
turn_count = 0
ans = 1
visit[r][c] = 1
while True:
d = (d + 3) % 4
nr = r + moves[d][0]
nc = c + moves[d][1]
if nr >= N or nc >= M or nr < 0 or nc < 0:
turn_count += 1
continue
if arr[nr][nc] == 0 and visit[nr][nc] == 0:
visit[nr][nc] = 1
r = nr
c = nc
turn_count = 0
ans += 1
continue
else:
turn_count += 1
if turn_count == 4:
nr = r - moves[d][0]
nc = c - moves[d][1]
if nr >= N or nc >= M or nr < 0 or nc < 0:
break
elif arr[nr][nc] == 0:
r = nr
c = nc
turn_count = 0
else:
break
print(ans)
후기
너무 코드가 지저분한 것 같아서 다른 분들의 코드를 봤는데 다른 분들의 풀이를 보니
필요 없는 코드가 많아서 수정하다보니 아래와 같은 코드가 나왔다.
import sys
N, M = map(int, input().split())
r, c, d = map(int, input().split())
arr = []
visit = [[0] * M for _ in range(N)]
for _ in range(N):
arr.append(list(map(int, sys.stdin.readline().strip().split())))
#북, 동, 남, 서
moves = [[-1, 0], [0, 1], [1, 0], [0, -1]]
turn_count = 0
ans = 1
visit[r][c] = 1
while True:
d = (d + 3) % 4
nr = r + moves[d][0]
nc = c + moves[d][1]
if arr[nr][nc] == 0 and visit[nr][nc] == 0:
visit[nr][nc] = 1
r = nr
c = nc
turn_count = 0
ans += 1
continue
else:
turn_count += 1
if turn_count == 4:
nr = r - moves[d][0]
nc = c - moves[d][1]
if arr[nr][nc] == 0:
r = nr
c = nc
turn_count = 0
else:
break
print(ans)