분류 전체보기 118

Back to the basic, 에러 메시지를 자세히 살피자

로컬에서는 테스트가 성공했는데 github action CI test는 실패해서 스트레스 받고 있었다. 도대체 깃허브 액션 환경은 로컬 테스트 환경과 어디가 다른 걸까? 그래서 동료에게 도움을 받고자 현상을 설명했다. 동료는 에러 메시지를 '자세히' 읽었다. "시간이 아홉 시간 차이 나고 있네요." 뚜둔, 그랬다. 깃허브 액션 시간은 UTC, 로컬 테스트 환경의 시각은 한국 시각이었던 것이다. 나는 그냥 테스트가 실패했다. -> 문제가 있다. -> 뭐지? 당황! 이었는데, 동료는 침착하게 테스트가 '어떻게' 실패하고 있는지 읽고 있었다. 그렇다. 기본 중의 기본을 잊고 있었다. 에러 메시지를 놓치지 말아야 겠다. 당황 말고 천천히 접근하자. 짧았지만 중요하고 값진 경험이었다.

일반 2022.10.29

일본의 청과 한국의 청(請)은 다르다. HTML Attribute를 무시하지 말자.

일본 오피스의 직원(파트너)이 버그를 제보했다. '어드민 페이지의 청(請)이 일본에서 사용하는 한자와 다르다.' 우리 팀은 갸우뚱했다. '어떤 게 다르다는 거지?' 이내 차이를 알 수 있었다. 청 한자에 들어가는 푸를 청이 '青'였다. 어드민 페이지는 시스템 기본 폰트를 쓰고 있었다. 그렇다면 일본 브라우저에서 접속하면 자동으로 그 언어에 맞게 폰트가 다운로드되어야 하는 것 아닌가? 생각했다. 하지만 놀랍게도 어드민 페이지는 HTML Attribute로 언어를 고정하고 있었다. ... 크롬 브라우저 편집기로 lang을 "ja"로 바꾸니까 일본의 청이 제대로 렌더링됐다. 기본 폰트가 바뀐 것이다! 어드민 페이지는 Nuxt와 Next로 빌드되어있었는데, Nuxt는 lang 설정이 아예 없었고, Next는 l..

일반 2022.10.26

가독성에 관하여

주호민이 한동안 생방송을 통해 만화가 지망생의 작품을 피드백해준 적이 있었다. 난 그 컨텐츠의 애청자였다. 거기서 가장 인상 깊었던 말은 가독성이었다. 읽히지 않으면 그리지 않은 것과 같아요. 만화의 그림체나 소재가 아무리 좋아도, 만화가 눈에 잘 들어오지 않으면 만화가로 데뷔하기 어렵다는 말이었다. 생각해보면 코드도 그렇다. 코드도 하나의 문서이고, 사람이 읽는 대상이다. 어떤 코드가 아무리 뛰어난 기술을 사용하고 알고리즘이 효율적이어도 읽기가 너무 어렵다면, 그래서 유지보수하기 어렵다면, 그 코드는 특정 시점의 특정 환경에서만 잘 돌아가고 변화에 적응하지 못해 결국 쓰이지 않게 될 것이다. 만화가 잘 읽히려면 여러가지 방법이 있었다. 글자 크기를 키우거나, 구도의 종류를 다양하게 한다던지, 컷의 크기..

일반 2022.10.18

오늘의 교훈: 빠르게 실패하고 구글링을 통해 공식문서 읽기

개발자라면 숱하게 경험해봤을 일이지만 오늘따라 새삼스럽게 즐거워서 적어보았다. 3개의 API를 폭포수 방식으로 호출해야 할 일이 있었다. 나는 이전에 이런 식으로 API 호출을 한 적이 없었기 때문에 당황했다. 회사에서는 리액트 쿼리(비동기 상태 관리 라이브러리)를 사용하는데, 일단 이전에 사용했던 방식으로 작성해봤다. const firstMutation = useMutation( (data) => service.createFirst(data), { onSuccess: () => { secondMutation.mutate(something) } }, ) const secondMutation = useMutation( (data) => service.createSecond(data), { onSuccess..

일반 2022.10.13

처음으로 API를 mocking하여 단위 테스트를 작성한 날

처음으로 API를 mocking하여 단위 테스트를 작성했다. 지금껏 MSW(Mock Service Worker)를 이용해 API를 호출하고 반환하는 커스텀 훅에 대한 단위 테스트만 작성했다. 하지만 1)상대적으로 간단한 컴포넌트를 이렇게 테스트하면 코드가 많아지기에 피하고 싶었고 2)다른 방식으로 컴포넌트와 테스트를 작성해보고 싶었다. 그런 마음을 오래 먹고 조금씩 공부를 하고 있다가 처음으로 작성했다. 테스트 대상이었던 컴포넌트는 외부 API Client를 주입 받는다. 나는 이 컴포넌트의 단위 테스트를 작성할 때 그 외부 API Client를 테스트 대역으로 바꿔서 주입했다. API Client에는 수많은 메서드들이 있지만 해당 테스트에서 사용하는 메서드만 원하는 데이터를 반환하도록 구현했다. 이렇게..

일반 2022.10.12

상수 처리에 관한 생각과 행동들

상수 처리 왜 하는가? 내 생각을 적어보자면, "가독성을 높이고, 쉽게 유지보수를 하기 위해"라고 생각한다. 변경을 쉽게 하기 위해 하드코딩된 문자열과 숫자들이 여기저기 흩어져 있는 코드에서, 요구사항이 바뀌거나 상황이 바뀌어 그 구체적인 값을 변경해야 한다면, 시간과 비용이 많이 들 것이다. 하지만 하드코딩하지 않고 그 값들이 하나의 변수에 담겨 상수 처리되어 있다면, 위와 같은 상황에서 상수 값만 바꾸면 아주 쉽게 모든 값들이 변동된 값을 참조하도록 할 수 있다. 의미 파악을 위해 또, 하드코딩된 값을 처음 보면 그 값이 도대체 왜 그 값인지, 무엇을 의미하는지 알기 힘들다. 그런데 숫자와 문자열이 있어야 할 자리에 대문자로 대문짝만하게 어떤 단어가 적혀있다면, 그 자리에 어떤 역할을 하는 값이 있을..

프로그래머스 타겟 넘버 (Javascript) 풀이, "트리다 트리!"

트리다 트리!!! 문제 링크 문제 설명 n개의 음의 아닌 정수를 적절히 더하거나 빼서 타깃 넘버로 만드는 경우를 수를 구하는 문제다. 해결 과정 결국 n 개의 모든 수를 각각 더하거나 뺄 수 있다. 그리고 그 경우의 수를 알고, 그 값들이 타깃 넘버인지 비교해야 한다. 처음에는 어떻게 이 모든 경우를 반복문으로 구한단 말인가? 절망하다가 뭔가 규칙이 느껴지는 듯 했다. 더하거나, 빼거나, 더하거나 빼거나 ... 그리고 그 값은 누적된다. 트리다 트리!! 마치 위와 같은 형태였다. 오오, 이것은 트리였다! 트리의 모든 요소를 다뤄야 하나? 그리고 numbers로 들어온 요소의 수를 더하든 빼든 그 결과만 모아서 확인해야 하는데, 그것은 트리에서 같은 깊이, Level을 들여다보면 됐다. 그렇다면 트리를 어..

바닐라코딩 프렙 지원부터 부트캠프 어드미션 테스트까지 후기

기억에 의존한 글이라 사실과 다를 수 있으니 참고만 하시길 바랍니다🙃 일정 서류 지원 1월 31일까지 프렙 시작 3월 1일 프렙 끝 4월 30일 최종 코딩테스트 4월 30일 ~ 5월 2일 (3일동안 원하는 시간에 치르면 됨) 프렙에 지원하기까지 과정 자기소개서 제출 퀴즈에 대한 정답, 자기소개, 코스 수료 후 계획 3가지 항목을 작성해야 했다. 글자 수 제한이 없었기에 솔직하게 자신을 드러내려 노력했다. 퀴즈 정답은 운이 좋게도 바닐라코딩 블로그에 실리기도 했다. 입학 과제물기한 내에 요구사항을 만족한 입학과제물을 제출하면 된다. 입학 과제물은 사전학습가이드를 완료했다면 충분히 해결할 수 있는 난이도였다. 자기소개서 제출 이후 합격 메일을 받고 결제를 하면 사전학습가이드(이것은 언제나 볼 수 있다)와 입..

프로그래머스 | 로또의 최고순위와 최저순위 | 자바스크립트

문제 링크 해결 과정 문제 설명이 길고 복잡해 이거 1단계 맞나, 싶었지만 자세히 들여다보니 난이도가 쉬운 문제였다. 로또에서 불분명한 번호 0이 몇 개 나오는지 파악하면 최고순위와 최저순위를 자연스럽게 파악할 수 있다. 즉, 0은 어떤 번호던지 될 수 있으므로, 0이 모두 당첨번호이면 최고순위, 당첨번호가 아니면 최저순위가 된다. 따라서 이를 파악하기 위해 알아야 하는 기존의 번호들에서 몇 개가 당첨번호이고, 불분명한 번호가 몇 개인지 알아내는 것이다. 그러면 맞춘 개수에 따라 몇 등인지 알고 정답을 반환할 수 있다. 소스 코드 function solution(lottos, win_nums) { const rankPerMatches = [6, 6, 5, 4, 3, 2, 1]; const unknownN..

리트코드(LeetCode): 104. Maximum Depth of Binary Tree

이진 트리의 최대 깊이 구하기 문제 링크 문제 설명 이진 트리의 최대 깊이를 구하는 문제다. 해결 과정 처음엔 전역에 depth 변수를 선언하고 자식 노드가 있을 때마다 depth를 추가하는 재귀 함수를 작성했지만 잘 되지 않았다. 한 쪽 노드의 양쪽 자식 노드가 null일 때 다른 쪽을 판단하지 못하고 리턴되는 것이 문제였다. 그래서 끙끙 머리를 싸매다가 검색으로 해당 문제에 관한 글을 읽었다. 다루기 힘든 어려운 큰 문제를 다루기 쉬운 작은 문제로 나눠서 해결하는 재귀 방법을 소개하고 있었다. 바로 차용해봤다! 좀 더 끈기 있게 붙잡고 있었으면 풀 수 있었을까? 의문이 든 문제. 소스 코드 var maxDepth = function (root) { if (!root) { return 0; } retu..