etc
10 posts
서버리스와 람다로 더 싸고 유연하게 구조 개편하기

최근 디어에 알림함이 생겼다. 근데 최근이라고 쓰고 확인해보니 최초 오픈한지 이미 딱 한달이 지났다… 요즘 시간 지나가는 속도가 정말 충격적이다… 어쨌든 그 전에 디어엔 ‘알림’ 개념이 없었다. 몇 기능에 푸시 알림이 붙어 있었을 뿐이다. 공유 모빌리티 서비스를 사용한 적이 있다면 앱 체류 시간을 떠올려 보자. 굉장히 짧지 않았나? 나도 길에서 킥보드가 보이면 대여할 때 한 번, 반납할 때 한 번 앱을 키는 게 전부다. 그래서 알림의 필요성이 부족해 없었다. 그러다 게이미피케이션 같이 고객과 상호작용이 강한 기능이 도입되면서, 고객에게 전달한 정보가 어디에도 남지 않고 휘발된다는 문제점을 팀 디자이너 분이 발견했다. 알림함은 그 분의 오랜 숙원 사업이었는데, 오픈하고 보니 ‘필요없다’고 생각해서 고객에게 전하지 않던 정보 중 필요한 것도 있었고, 원래 도입하려던 기능에 알림이 큰 도움이 되는 것도 있었다. 🔔 알림 도입과 아키텍쳐 개편 인앱 알림 도입 이전엔 푸시 알림만 여러곳에서…

February 18, 2024
etc
새는 시간을 줄이고 싶다는 고민

지난 반 년간 회사에서 한 ‘개발’을 돌아봤을 때, 절반은 Node.js의 레거시를 스프링으로 옮기고, 그에 수반되는 작업에 해당되고, 나머지 절반은 동시에 새로운 요구사항을 Node.js와 옮긴 신규 시스템에 붙이는 일에 해당되는 것 같다. ‘달리는 기차의 바퀴를 갈아 끼우’면서 동시에 열차 칸을 열심히 붙이고 있다. 나는 레거시라는 단어의 절묘함을 좋아한다. 레거시가 있어서 회사가 먹고 살았고, 나도 들어올 수 있었다는 점에서 ‘유산’이라는 의미가 딱 맞다. 그리고 동시에 언제까지나 유산에 의지해서 살 수 없다는 면도 그렇다. 그래서 레거시를 부정적인 뜻으로만 사용하는 걸 보면 조금 슬퍼진다. 어쨌든 레거시 코드를 보며 회사 도메인 정책을 파악하는 일이, 좋은 사내 문서와 더 좋은 살아있는 레퍼런스인 팀원들이 있음에도 만만치 않았다. 예외 상황은 너무 많았고 코드가 복잡해 쉽게 파악할 수 없었으며, 아무도 그렇게 돌아가고 있는 줄 모르던 부분을 발견하기도 했다. 그러다 팀에서…

July 02, 2023
etc
회고
배포 중 순단을 없애고 싶었을 뿐인데

⚡️ 문제 상황 언젠가부터 백엔드 서버 배포 직후에 아주 짧은 서비스 순단이 일어났다. 배포 직후 외부 API를 호출 할 때 DNS 조회에 실패하는 걸로 추정되었다. 여러번 발생하는 에러가 아니기에 다른 팀원이 애플리케이션 실행 후 트래픽 허용 전, 으로 호출하는 모든 도메인을 한 번씩 조회하도록 배포 스크립트를 수정했다. DNS 조회 결과를 캐싱할 것으로 기대했기 때문이다. 하지만 조치 후에도 여전히 이라는 동일한 에러 메시지와 함께 순단이 발생했다. 순단으로 인해 틀어진 여러 정합을 수동으로 맞춰야 하는 상황을 없애기 위해 이번 스프린트에 해결을 목표했다. 🧶 EAI_AGAIN은 어디에서 오는가 이 코드를 누가 언제 왜 던지는가 부터 알기 위해 라이브러리를 포함해 코드를 검색했는데 나오지 않았다. 그래서 함수 이름으로 추정되는 를 검색해보고, 에러 콜스택도 읽어봤다. 프로젝트 및 노드 모듈 코드 내에 라는 함수는 없었고, 대신 노드 모듈 내의 파일의 주석에 언급이 있었다. …

June 04, 2023
etc
CS
이상한 부업 일기 - 나는 얼마나 고객을 알고 있을까

어느날 문득 천재적인 생각이 떠올랐다. ‘벚꽃철에 석촌호수에서 폴라로이드 사진을 돈 받고 찍으면 부자가 될 수 있지 않을까?’ 우리 회사엔 는 그라운드 룰이 있다. 예시로 ‘비오는 날에 킥보드 이용이 줄어든다’는 팩트, ‘킥보드에 우산을 달면 이용률이 올라갈 것이다’는 가설이다. 이 룰에 따라 내 발상을 표현하자면 다음과 같다. 팩트 인생네컷과 같은 사진 촬영, 즉석 출력 서비스가 인기가 많다. 인생네컷에는 지역, 계절별로 특별한 프레임, 예를 들어 벚꽃 프레임 같은 것이 한정판으로 존재한다. 가설 요즘 사람들은 디지털 사진을 찍는 것이 대부분이다. 그래서 실물 사진을 갖고 싶어 한다. 사실 인생네컷 같은 실물 사진을 벚꽃과 함께 찍고싶지만, 그러기 힘들어서 벚꽃 프레임 같은 걸로 대리만족 하고있다. 이 아이디어를 회사 사람들에게 얘기했을 때, 소수의 몇명은 돈이 되겠다 동의하고 몇명은 반대했다. 제일 긍정적인 의견이 한 10만원 벌 것 같다 였고, 제일 비관적인 의견은 만원이나…

April 09, 2023
etc
Querydsl만의 아늑한 🏡 지어주기

🧶 문제상황 🪐 비대해진 서비스 코드 줍줍은 요청에 따라 동적으로 변화해야 하는 복잡한 조회 조건을 걸기 위해 을 도입했다. 예전에 공부하며 가볍게 사용해 본 적은 있지만, 줍줍 요구사항만큼 복잡한 코드를 짜 본 적은 없었다. 에 코드를 넣는 식으로 우선 구현했고, 무사히 배포되었다. 그러다 을 쓰지 않는 다른 서비스 클래스 코드를 보니 ‘어… 여기는 너무 깔끔한데?‘하는 위화감이 들었다. 그리고 다시 을 쓰는 코드를 보니, 가 할 일이 에서 이뤄지고 있다는 생각이 들었다. 위에 있는 기존 의 짧은 예시 코드 내에서도 사용으로 인한 서비스 역할 비대화가 보인다. 의 경우 DB에서 데이터를 가져오는 역할을 완벽히 에 맡기고 있다. 반면, 는 DB에서 어떤 데이터를 가져올지 서비스 코드 상에 완전히 노출되어 있음을 볼 수 있다. 그래서 각 레이어 별 역할이 원칙대로 분리되도록 코드를 별도의 객체로 빼내는 리팩토링을 시작했다. ✂️ 일단 레포지토리 코드 분리 사용 예시를 보면 을…

October 26, 2022
Spring
트러블슈팅
etc
줍줍 MySQL 인덱스 탐험

🧳 줍줍 MySQL 인덱스 탐험 ❗️ 해당 포스팅에서 지칭하는 책은 모두 Real MySQL 8.0 1권을 뜻합니다. 우테코 팀 프로젝트 5차 스프린트에서 성능 테스트로 톰캣 설정 최적화 / 모든 쿼리 수집 후 DB 인덱스 설정 이라는 두 개의 백엔드 과제가 있었다. 나는 이 중 DB 인덱스 설정을 맡게 되었다. 줍줍의 전체 테이블 구조는 정석 ERD보다 간략하게 표현하자면 이렇다. 쿼리 수집은 쉬웠다. 줍줍의 모든 클래스들은 를 상속했다. 는 선언하지 않은 메서드도 사용 가능한 반면, 를 상속하면 선언한 메서드만 사용 가능하다. 뒤집어 말하면 사용을 제외하면, 코드의 모든 메서드가 곧 프로젝트에 사용 중인 모든 쿼리였다. 쿼리 최적화 by.봄🌱 인덱스 최적화를 시작하기 전에 고맙게도 같은 팀 크루인 봄이 불필요햔 left outer join을 제거하는 쿼리 최적화를 해주었다! 에서 의 PK를 FK로 가진 가 해당 FK를 조건으로 조회할 때, 로 하면 불필요한 이 발생하고 …

October 04, 2022
etc
우아한테크코스
트러블슈팅
[git] 슬랙한테 봇 강퇴당하고 서브모듈 도입한 이야기

슬랙이 봇을 강퇴시켰어요 서버에서 슬랙 API를 호출하려면 발급받은 봇 토큰이 필요하다. 해당 정보를 기밀이라고 생각하지 않았는데… 애초에 봇에게 호출할 수 있는 API 제한이 있다 연결된 워크스페이스가 개발을 위해 생성된 줍줍 팀 워크스페이스다 라는 이유에서였다. 그래서 깃헙에 을 포함한 을 올려놨는데… 어느날 API 응답이 오지 않았다. 개발자 도구의 응답에는 이라는 에러 문구가 떴고, 분명 워크스페이스에 정상 추가했던 봇이 사라져 있었다. 슬랙이 봇을 강제 추방시킨 것이었다… 얼마간 잘 썼기에, 일정 주기로 공개 저장소들을 크롤링 해 한번에 정지시키는 게 아닐까 싶다. 설명서를 잘 읽자 슬랙 API에 들어가면 가 떡하니 명시되어 있다. 봇 토큰에는 큰 권한이 있습니다. 토큰은 사용자가 앱을 설치함으로써 권한을 부여했음을 나타냅니다. 앱을 설치한 유저가 준 신뢰를 해치지 않도록 토큰을 안전하게, 기밀로 보관하세요. 최소한 공개적인 형상관리에 토큰을 올리지 마세요. 환경 변…

July 25, 2022
etc
트러블슈팅
[SQL] SELECT * 쓰지 말자

지금까지 DB를 사용하는 미션에서 컬럼 수가 적기에 문을 자주 썼다. 그런데 로 모든 컬럼을 가져오는 것 보다 컬럼을 명시해 가져오는 게 낫다는 영문 포스팅을 제이슨이 공유해주셔서 읽었다. 7 Reasons Why Using SELECT * FROM TABLE in SQL Query Is a Bad Idea 다음은 해당 포스팅을 전체 번역한 것이다. SELECT * FROM TABLE 쿼리문을 쓰는 게 좋지 않은 7가지 이유 인터넷에서 쿼리문을 쓰는 게 나쁘니 피하라고 하는 많은 글을 봐왔다. 그 대신 정확한 컬럼을 나열해야 한다. 이는 내가 주니어 개발자에게 가르치기도 하는 좋은 제안이자 좋은 SQL 작성 습관 중 하나인데, 많은 사람들이 그 이유는 설명하지 않는다. 왜 쿼리문에서 을 쓰면 안되는지 이유를 설명하지 않고 SQL 개발자들을 설득하기란 어려운데, 대개 Oracle database에서 를 실행하는 것으로 SQL 학습을 시작하기 때문이다. 이 글에서 왜 쿼리문을 쓰…

May 25, 2022
etc
DAO 와 Repository

웹 체스 미션을 진행하면서 을 이용해 DB에 접근하는 모든 클래스의 이름을 라 지었다가 아래와 같은 코멘트를 받았다. 코멘트를 받기 전까지 와 가 이름만 다른 같은 개념이라 생각했다. 그래서 이 둘의 차이에 대해 알아보았다. @Repository 문서 스프링 어노테이션 자바 문서에는 다음과 같이 적혀 있다. 적용 된 클래스가 Repository 임을 나타냅니다. 이는 도메인 주도 설계(에릭 에반스)에서 정의한 저장소를 캡슐화하고, 저장하고, 검색하여 객체의 컬렉션처럼 다루는 메커니즘을 뜻합니다. Data Access Object와 같은 전통적인 자바 EE 패턴을 사용하는 팀도 이 스테레오타입을 DAO 클래스에 적용할 수 있습니다. 다만 그 전에 Data Access Object와 DDD-style repositories의 차이를 이해하는 것이 좋습니다. 이 어노테이션은 다목적 스테레오타입이고 개별 팀은 자신들만의 축소된 의미에 맞춰 적절하게 사용하면 됩니다. 어노테이트된 …

May 07, 2022
etc
[SQL] left join vs (inner) join

left join / (inner) join 7SQL 스터디를 하다 자신만만하게 풀었는데 기대한 답이 나오지 않는 문제가 있었다. 주문을 한 번도 하지 않은 모든 고객을 찾아주세요. 스터디는 w3schools의 sql 실습 페이지를 이용했는데, 고객의 정보가 있는 테이블과 테이블이 있다. 주문이 없는 고객을 찾기 위해 테이블에 테이블을 한 다음, 에 이 있는 걸 확인하려 했다. 그런데 실행 결과를 보니 가 없는 고객은 아예 결과에 잡히지 않았다. 아직 sql 문법에 익숙하지 않아서 키워드를 차례로 앞에 붙여봤는데, 일 때만 가 인 경우도 포함되어 나왔다. 찾아보니 은 , 을 포함한 은 을 나타낸다 한다. 를 하면, A 테이블의 모든 행을 조회하면서 B에 없는 값은 로 처리된다. 나머지 은 해당 사이트에서 지원하지 않아 써보진 못했지만, 스터디 덕분에 차이를 확실히 알게 되었다. left join / (inner) join

April 30, 2022
etc