일반 20

chatGPT와 함께 지뢰찾기(minesweeper) 만들어보기 (1)

chatGPT와 차근차근 지뢰찾기 프로그램을 만들면서 느꼈던 것들을 적어봅니다. 현재 지뢰찾기 프로그램은 놀랍게도 완성되지 않았으며, 차근차근 진행중입니다. 진행 중인 프로젝트 코드는 여기서 보실 수 있습니다. 연습 욕구: 클린 아키텍처와 TDD 예전부터 하나의 작은 프로젝트를 처음부터 끝까지 설계하고 구현해보고 싶었다. 그 과정에서 각종 설계와 방법론들을 연습해보고 싶었는데, 그 중에 하나가 클린 아키텍처와 TDD였다. 특히 클린 아키텍처의 경우 실전 경험이 적었기 때문에 꼭 나만의 프로젝트로 연습해보고 싶었다. 프로젝트 선택: 지뢰찾기 작은 프로젝트로 어떤 것을 구현하면 좋을까? 고민했다. 예전부터 만들어 보고 싶었던 프로젝트들은 많았지만 적당히 작은 프로젝트로는 틱택토, 지뢰찾기, 테트리스 등이 있..

일반 2024.04.14

캐나다에서 2주간 살아보며 적어보는 단상

캐나다에서 2주간 살아보며 적어보는 단상 캐나다 워킹홀리데이로 3월 1일부터 토론토에서 지내고 있습니다. 아직 직업은 없고요. 개발자 일자리를 구하고 있습니다. 토론토는 (의외로) 캐나다 동쪽에 위치해 있고, 미국의 뉴욕과 가깝습니다. 그리고 캐나다와 미국을 끼고 있는 오대호 중 온타리오 호수(나이가아라 폭포를 보러 갈 수 있어요!)와 맞닿아 있고 캐나다의 가장 큰 도시 중 하나이기도 하죠. 글감을 찾다가 왜 이곳까지 오게되었는지 생각해보고 적어두면 좋겠다! 하여 이렇게 정리해봅니다. 사실 매번 커피챗마다 반복해서 하는 이야기이기도 해서, 이렇게 적어두면 나중에 더 잘 말할 수 있지 않을까? 했습니다. 그래서 일단 이야기하다보면 많이 나오는 질문에 대해 적어보도록 해보겠습니다. 왜 캐나다이고, 워킹홀리데..

일반 2024.03.17

사이드 프로젝트였던 FigNotion 출시 과정과 그 후의 일들

사이드 프로젝트 출시는 여러 방면에서 그것을 만든 사람에게 긍정적인 영향을 끼치는 것 같습니다. 저는 얼마 전 사이드 프로젝트로 만든 FigNotion이라는 제품을 Figma Community에 출시했습니다. 이 제품은 Figma라는 디자인 도구의 Widget으로, Notion 페이지의 내용을 Figma로 불러들여 문서 파편화 문제를 해결하고 협업을 더 효율적으로 할 수 있도록 도와줍니다. (FigNotion이 어떻게 탄생했는지 이야기를 알고 싶으시다면 이 글을 읽어보시면 좋겠습니다.) FigNotion의 탄생에 대해 간단히 말해보자면, 회사에서 문서 파편화 문제를 해결하기 위해 회사 내부에서만 사용할 목적으로 FigNotion을 만들었습니다. 그리고 나름 잘 사용하고 있었죠. 그리고 이런 문제 해결 경..

일반 2024.02.18

Figma Widget 개발해서 문서 파편화 해결해보기

이 글에서 저는 스쿼드에서 제품을 개발하면서 직면했던 한 가지 큰 도전, 바로 '제품 정책 문서의 파편화' 문제와 그 해결 과정에 대해 이야기하고자 합니다. 제품 개발 과정에서 정보의 분산은 큰 혼란을 야기할 수 있습니다. 저희 팀은 이 문제를 해결하기 위해 기존의 작업 방식을 재고하고, 새로운 솔루션인 'FigNotion'을 개발하게 되었습니다. 이 글을 통해 그 여정을 공유하고자 합니다. 들어가기 전에 저희 회사 제품 개발 조직은 디자인 협업 툴로 Figma(피그마), 또 문서 관리 도구로 Notion(노션)을 사용하고 있습니다. 스쿼드 마다 세부적인 내용은 다를 수 있으나 일반적으로 제품과 관련된 정책은 Notion으로 관리하고 제품 디자인은 Figma에서 관리하고 있습니다. 창 하나에 있는 디자인..

일반 2024.01.07

임프레션을 추적해보자. React Impression Tracker 개발기

배경 저는 한 스타트업 광고 시스템의 웹프론트엔드를 개발하고 있습니다. 제가 속한 팀은 현재 성과형 광고를 구축해 운영하고 있는데요. 성과형 광고란, 광고의 노출, 클릭 등의 성과가 발생할 때마다 병원에게 광고비를 받는 시스템입니다. 팀은 비교적 최근에 구성됐는데, 구성되고 나서 눈에 띄게 떠오르기 시작한 이슈 중 하나는 임프레션 및 클릭 데이터(이하 이벤트)의 누락 및 재수집 이슈였습니다. 여기서 임프레션이란? 유저가 특정 요소를 인지했다고 판단하는 기준입니다. 예를 들어, 유저가 보고 있는 화면에 어떤 상품이 50% 이상 노출된 채로 1초가 흘렀다면, 그 유저가 그 상품을 인지했다고 판단하고 Viewed 이벤트를 수집합니다. 임프레션 수집은 해당 광고의 성과 데이터를 수집하는데 중요한 요소입니다. 저..

일반 2023.12.10

Exclusive 타입, 역직렬화 그리고 소통

지난 12월, 상호배타적인 프로퍼티를 갖는 객체를 타입으로 만들고 싶었다. 왜냐하면 그렇게 요청을 보내야 했기 때문이다. 예를 들어 성과를 조회하기 위해 서버에 요청을 하는 상황에서 요청 Body를 두 종류로 보내야 했다. 상품 아이디를 보내면 상품에 대한 성과를 요청한다. 상점 아이디를 보내면 상점의 모든 상품에 대한 성과를 요청한다. interface GetProductPerformance { productId: number } interface GetStorePerformance { storeId: number } 이 두가지 케이스를 모두 포함하는 타입을 만들고 싶었다. 이때 productId와 storeId는 상호 배타적으로, 하나가 있으면 다른 하나는 객체에 없어야 했다. 혼자서 배운 타입스크립..

일반 2022.12.18

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