스프레드시트에 데이터 병합하는 크론 고치기

Today I Learned 날짜 2024년 3월 22일 금요일 내용 위젯 위젯 내용이 에러메시지에 담기는 문제에 대해 조언을 받았는데, 프론트 쪽의 문제일 수 도 있다고 한다. 응답을 받을 때 Text로 처리하는 함수를 사용하는 쪽으로.. 자세한 결과는 월요일에나 나오지 않을까 싶다. 고객 데이터 조회 예전에 진행했던 태스크에 문제가 생겼다. 고객들의 서비스 사용 정보를 구글 스프레드시트에 매일 갱신하는 함수가 제대로 작동하지 않았다. 리뷰 서비스나, AI 서비스를 사용하면 사용 개시 시간을 기록해야 하는데 사용한다고 기록했음에도 불구하고 구체적인 시간은 저장되지 않고 있었다. ...

2024년 3월 22일 · 2 분 · 배준수

에러메시지에 응답 담기

Today I Learned 날짜 2024년 3월 21일 목요일 내용 Angular 최근 작업한, 앱 내에 서비스 삭제 경로를 추가하는 건 나름(?) 큰 작업이었다. 그동안은 컴포넌트에 변수에 대한 조건을 추가하는 등의 사소한 작업이었는데, 새로운 하위 컴포넌트를 만들어야 했다. 모달 형태로. 기능 자체는 어제 TIL에 작성한 대로 완성했다. 다만, 기존에 작성되있는 방식에 맞추기 위해, 유지보수를 수월하게 하기 위해, 박살난 CSS 수준을 끌어올리기 위해 감사하게도 코드 리뷰를 받을 수 있었다. 이 TIL에 적어내면 참 좋겠으나 아직 내 것으로 받아들이지 못해 쓸 수 없다. 그래도 열심히 받아 적었으니 빨리 적용해보고 내가 몰랐던 부분에 대해 정리해야겠다. 최근 스프린트들이 프론트쪽에 작업이 몰리면서, 내가 프론트를 어느정도 할 수 있다면 팀의 일정에 도움이 많이 되겠다고 느꼈다. 마침 기가 막히게 성장할 환경이 갖추어졌으니 열심히 하기만 하면 될 듯! ...

2024년 3월 21일 · 2 분 · 배준수

앱 삭제 기능 만들기

Today I Learend 날짜 2024년 3월 20일 수요일 내용 앱 삭제하는 경로를 추가했다. 오늘은 백엔드 작업을 많이 했다. 프론트 기존에 우리 서비스에서 사용하는 체크박스 클래스로 바꿔주었다. 앱을 삭제하는 버튼은 고객이 이유를 선택해야만 활성화되도록 구현하기 위해 ngIf 를 사용했다. 1 2 <button *ngIf="uninstallReasons.length > 0" class="btn-enabled" mat-button (click)="onConfirm()">Delete App</button> <button *ngIf="uninstallReasons.length === 0" class="btn-disabled" mat-button disabled>Delete App</button> 각 사유들은 checkbox로 만들었고 체크되면 삭제 사유를 담는 배열에 추가시켰다. 1 2 3 <div class="checkbox-container" aria-label="Select a reason" [(ngModel)]="uninstallReasons"> <alpha-checkbox (change)="updateUninstallReasons($event, 10)">Technical issues</alpha-checkbox> </div> 처음 사유를 추가했을 때, 버튼이 활성화되었다. 하지만 체크를 비활성화하여 다시 사유를 선택하지 않게 되었을 때 버튼이 비활성화되지 않았다. 따라서 uninstallreason의 배열 상태를 추적하는 ChangeDetectorRef를 사용했다. ...

2024년 3월 20일 · 2 분 · 배준수

프린이

Today I Learend 날짜 2024년 3월 19일 화요일 내용 모달로 기능 추가하기 우리 서비스를 삭제하려면 Shopify 의 shop admin 쪽에서 처리하면 된다. 하지만 이와 별도로 우리 서비스 내에서도 자체적으로 삭제 버튼을 만들기로 했다. 이와 관련된 로직은 아마 내일 처리할 예정이니 내일 TIL에 담길 듯 하다. 오늘은 프론트쪽에서의 기능 구현을 우선으로 했다. 삭제 전 이유에 대한 데이터를 모달을 이용해서 수집해야 한다. 기존 계획으론 모달에서 고객이 선택하고 입력한 데이터를 수집한다. 유저가 확인버튼을 누를 경우 삭제 요청과 함께 이 데이터를 서버로 보낸다. 서버에선 데이터는 저장하고 삭제 로직을 시작한다 모달이 종료된다.. 만약 취소버튼을 누를 경우 그냥 2~3번 과정 없이 모달창을 종료한다. 의 순서로 구성했다. 프론트는 아직 너무 허접한 수준이라 조언을 받았는데, 우리 서비스에서 특별한 예외 케이스가 아니면 모달에서 요청을 보내도록 처리하지 않았다. 모달이 닫히고 기존에 위치해 있던 페이지에서 요청을 보내야 한다. 따라서 ...

2024년 3월 19일 · 2 분 · 배준수

간간히 유지보수

Today I Learend 날짜 2024년 3월 18일 월요일 내용 아직 스프린트가 끝나지 않았지만, 프론트 쪽 일정이 진행되는 동안 유지보수 작업을 시작했다. 프론트 쪽이 주 작업인데, 기존에 항상 설정되어 있던 placeholder를 서버에서 받은 세팅값이 False일 경우에는 세팅하지 않도록 한다던가, 현재 우리의 소개페이지(랜딩페이지)에 작동안되는 버튼들을 정리하고 다른 URL로 연결하는 간단한 작업들이 었다. 다만 아직 프론트 코드들은 익숙하지 않아서 기존의 구조를 망가뜨리지 않도록 잘 살펴보면서 하긴 했다. 작성된 리뷰를 보여주는 위젯에는 ‘더보기’ 기능이 있다. 말 그대로 내용이 길 경우 일부만 보여주고 모든 내용을 보기 위한 버튼이어야 정상인데 지금은 이미지만 확대된다. 내용은 아무리 길어도 다 출력된다. 이 기능을 정상적으로 되돌려야 한다. 위젯은 HTML로 서버에서 렌더링하여 제공하는데, 여기에 사용되는 더보기 관련 스크립트가 Shopify 프론트 쪽에 구현되어 있는 것 같다. 이게 맞나..? ...

2024년 3월 18일 · 1 분 · 배준수

scalars의 사용 이유

Today I Learend 날짜 2024년 3월 15일 금요일 내용 scalars()의 역할 PostgreSQL에서 데이터를 가져올 떄 다음과 같은 형식을 사용했었다. 1 2 stmt = select(models.Product).where(models.Product.title != "가짜") result = db.execute(stmt).scalars().all() scalars()를 왜 써야하는지 모르는 채, 그냥 기존 코드가 그렇길래 써왔었다. 오늘 위젯 렌더링을 구현하는 과정에서 jinja2 템플릿을 이용해 위젯 HTML에 상품들의 목록을 넣어줬지만 해당 값의 필드들을 참조할 수 없었다. 1 2 3 4 5 stmt = select(models.ListDesignerProduct) .where(models.ListDesigerProduct.list_designer_widget_id == 1) result = db.execute(stmt).all() for product in result: logging.info(product.id) 이런식으로 작성되어 있었다. 이때 저 result를 직접 로깅해보니 row라고 나오면서 내부 필드를 참조할 수 없다고 오류가 발생했다. ...

2024년 3월 15일 · 1 분 · 배준수

메일 발송에 필요한 데이터 수집

Today I Learend 날짜 2024년 3월 14일 목요일 내용 의사소통 오류 이번 스프린트에서 내가 데이터베이스 구조를 설계했다. List Desiger에서 위젯은 다수의 상품을 들고 있게 되고 각 상품은 가공된 데이터(최근 구매자, 재고 등)를 갖고 있어야 한다. 기존에 상품과 관련된 데이터 형식을 변경하는 건 당연히 말도 안되는 소리니 위젯에서 사용할 상품의 데이터 형식을 ListDesigerProduct로 만들었다. 내가 이 테이블을 만든 목적은 위젯에서 표시될 데이터를 담아두기 위해서고, 기존에 상품이 가지고 있는 데이터(이름, 가격, sohpify내에서의 고유 ID 등)은 관계를 통해 JOIN으로 해결할 수 있을거라고 생각했다. ...

2024년 3월 14일 · 2 분 · 배준수

메일 발송에 필요한 데이터 수집

Today I Learend 날짜 2024년 3월 13일 수요일 내용 주간 성과 메일 약 2달 전에 각 스토어에게 주간 작성되거나 import된 리뷰 수에 대한 메일을 보내는 Task를 진행했었다. 이와 비슷하게, 새롭게 생긴 List Designer 기능의 성과를 담은 메일을 매 주 전송해야 한다. 필요한 데이터는 위젯의 클릭 수와 위젯 내 상품의 매출. 위젯의 클릭 수 데이터를 어떻게 저장할 것인지 잠깐 고민했다. 클릭 이벤트가 발생할 때마다 테이블에 레코드를 하나 씩 추가하는 방법이 있는데, 우리 서비스에서 방문자 수를 체크하는 방식이 이렇게 구현되어 있다. 다른 방법은, 각 위젯의 데이터 테이블에 필드를 하나 추가하는 것이다. ...

2024년 3월 13일 · 2 분 · 배준수

router 구현 순서

Today I Learend 날짜 2024년 3월 11일 월요일 내용 우선 기본적인 구현은 수월하게 진행중! router 정의 순서 위젯을 렌더링하는 요청을 받을 router를 list-designer/render 엔드포인트로 만들었다. 오류가 발생했는데, int여야하는 widget_id의 타입이 올바르지 않다는 다음과 같은 내용이었다. 1 2 3 4 5 6 7 8 { "detail": [ { "loc": [ "path", "widget_id" ], "msg": "value is not a valid integer", "type": "type_error.integer" } ] } 내가 만든 router는 widget_id를 전혀 사용하지 않는데.. 기존에 있는 코드에 문제가 있다고 생각해서 들여다봤지만 아무 문제 없었다. 애초에 문제 있는게 test 서버로 올라올 리도 없고, 다른 곳의 router가 실행도 안됐는데 왜 영향을 끼친다는 건지 이해가 되지 않았다. ...

2024년 3월 11일 · 2 분 · 배준수

위젯 렌더링 클래스 만들기

Today I Learend 날짜 2024년 3월 7일 목요일 날짜 2024년 3월 8일 금요일 내용 위젯 렌더링 만들다가 골이 빠질 것 같다. 기존에 위젯을 렌더링하는 클래스가 있지만 전혀 다른 모양새라 새로 만드는게 맞다고 생각했다. 똑같은 엔드포인트에서 경우에 따라 완성된 위젯을 렌더링하여 응답하거나 받은 값을 적용하여 렌더링해주어야 한다. 처음에는, 위젯이 가지고 있는 고유 코드가 param에 포함되는 지를 기준으로 생각했다. 그런데 이미 생성된 위젯은 기본 디자인 형태를 갖추고 고유 코드도 가진다. 프론트에서 위젯 스키마를 보낼 떄, 모두 데이터가 갖춰진 채로 보낼 것이다. 차라리 디자인 값이 포함 되어있는지 여부를 따지는게 더 정확할 것 같다. 어제도 말했듯, Shopify에서 스토어에 렌더링을 요청할때는 디자인 값을 보내지 않을테니… 위젯 목록을 위한 기본적인 CRUD가 구현되어 있으니 여기서 사용되는 schema를 이용해서 그 형태로 오면 미리보기로, 아니면 shopify쪽 요청으로 처리해야 하나..? ...

2024년 3월 8일 · 1 분 · 배준수