로컬에서 Redis Insight로 ElastiCache 데이터 보는 방법

Today I Learned 날짜 2025년 1월 22일 수요일 내용 로컬 Redis Insight로 캐시 데이터 보는 방법 AWS ElastiCache 에 올라가 있는 캐시를 눈으로 직접 보고싶다. 시각적으로 데이터를 표현하고 관리할 수 있는 툴을 GUI라고 하는데, PostgreSQL에 pgadmin4가 듯 Redis에는 Redis Insight가 있다. 문제는 이 서버가 VPC에 들어가 있어서 그런지 로컬에서 접속이 안된다는 것.. 해당 VPC에 구현된 EC2 인스턴스에 접속해야 접근할 수 있다고 한다. 내가 알기론 Redis Insight에는 SSH를 이용한 연결이 있는데.. 이 기능이야 말로 이때 써야하는게 아닐까 싶어 써보았는데 바로 된다! 테스터서버부터 실서버까지 로컬에 설치한 프로그램으로 캐시 데이터를 볼 수 있다. ...

2025년 1월 22일 · 2 분 · 배준수

Step Functions에서 분기 처리하기

Today I Learned 날짜 2025년 1월 21일 화요일 내용 Step Functions에서 Choice로 분기처리하기 웹훅 개선 작업을 진행중이다. 지난주에 말했듯 Step Functions로 계획중인데 오늘 헤매던 곳을 뚫어냈다. 기존과 마찬가지로 웹훅이 서버로 전송되면 SQS 큐에 메시지를 담는다. 매핑된 람다는 메시지가 하나 도착하면 꺼내서 Step Functions에서 정의한 상태 머신을 호출해서 로직을 진행한다. 이 상태머신은 이 메시지의 종류(주문, 혜택, 고객 등)에 따라 알맞은 람다를 호출해야 한다. 그림으로 보자면 이런 형태다. 저 노드 하나하나가 state라는 개념이다. 저기서 저 DetermineTopic이 Choice State인데, 정의한 조건에 따라 알맞은 람다를 호출해줘야 한다. 그 상단에서 최초로 호출되는 웹훅 데이터 디코딩 람다부터 살펴보자 ...

2025년 1월 21일 · 3 분 · 배준수

람다에 layer 추가하기

Today I Learned 날짜 2025년 1월 20일 월요일 내용 람다에 계층 추가하기 람다는 서버 없이 간단한 함수를 작성하여 실행할 수 있는 기능을 제공한다. 따라서 여기에는 기본 내장 함수들만 제공된다. 만약 람다에서 어디론가 http 요청을 보내기 위해 requests 가 필요하다면 람다에 등록하는 ZIP 파일에 해당 패키지를 추가해주어야 한다. 웹훅 개선에 람다를 이용할 계획이고, 각 람다는 다루는 웹훅 별로 나눠질 예정이다. 주문, 고객, 상품 등 다루는 데이터에 따라 여러 람다를 만들거다. 각 람다를 정의할 때마다 requests 라이브러리를 설치해주는 것은 번거롭다. 이런 일이 반복되면 람다 자체도 용량이 커진다. 모두가 쓰는 공통적인 라이브러리를 추가해주는 기능이 계층(layer)다. ...

2025년 1월 20일 · 2 분 · 배준수

장고에서 프린트문 바로 출력되게 하기

Today I Learned 날짜 2025년 1월 16일 목요일 내용 장고에서 프린트문 바로 출력하기 장고에선 아주 특이한 현상이 있다. 개발 과정에서 프린트문을 찍어도 바로 출력이 안된다! 개발의 최 핵심 기능인데… 버퍼에 들어갔다 나와서 그런지, 괜히 코드 저장버튼을 눌러서 도커 컨테이너가 리프레쉬 되야 출력된다. 디버깅 모드는 너무 설정하기 번거롭고… 간단하게 하는 방법을 찾아냈다. 방법 1 print("출력!", flush= True) 를 사용하자. 버퍼에 쌓이지 않고 즉시 출력된다. 방법 2 프린트문을 찍을 때마다 저 옵션을 넣어줄 순 없다. 도커파일에 잠깐 손을대자. ...

2025년 1월 16일 · 1 분 · 배준수

메타가 망해야 하는 이유

Today I Learned 날짜 2025년 1월 15일 수요일 내용 내가 메타를 혐오하는 이유 꾸준히 TIL을 쓰면서 메타에 대한 온갖 불평 불만을 쏟아냈었다. 그리고 오늘 그 분노는 최대치를 찍었다. 네이버 커머스 솔루션에서 우리 서비스를 이용해주시는 고객님께 태그된 게시물을 전달해드리지 못했다는 자책에서 조금은 자유로워지고자 메타가 왜 망해 마땅한 지를 말하고자 한다. 메타 API를 이용하려면 메타 개발자 센터에서 앱을 등록해야 한다. 각 앱은 사용 유저의 어떤 데이터를 사용하느냐에 따라 필요한 권한을 설정해주어야 한다. 권한에는 Standard Access와 Advanced Access가 있는데 결국 배포해서 사용하려면 Advanced Access를 얻어야 한다. Standard 수준까지만 얻은 권한은 앱에 등록된 사람(관리자라던가 테스터라던가)만 사용할 수 있고, 앱을 이용하는 누구나(일반 유저) 사용하려면 해당 권한의 Advanced Access를 얻어야 한다. ...

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

웹훅 처리 성능 개선을 위한 계획

Today I Learned 날짜 2025년 1월 14일 화요일 내용 웹훅 개선을 위한 계획 세우기 다음 태스크가 정해졌다. 무려 웹훅 개선하기. 코어에 오면서 큰 트래픽을 처리하게 될 거라곤 예상했지만 벌써 이렇게 본격적으로 할 줄은 몰랐다… 웹훅은 설정한 이벤트(데이터 변경 등)가 발생했을 때, 외부로 요청을 보내는 것을 의미한다. 예를 들어, 앱 설정에서 웹훅을 구독해 놓으면 CAFE24에서 우리 서비스를 사용하는 스토어의 데이터가 변경되면 우리에게 보내준다. 상품 정보라던가, 주문이 추가되었다던가, 고객이 삭제되었다던가 다양한 상황을 설정할 수 있다. ...

2025년 1월 14일 · 2 분 · 배준수

Angular 컴포넌트 초기화하기

Today I Learned 날짜 2025년 1월 13일 월요일 내용 초기화되지 않는 컴포넌트 서버에 요청을 보내고 받아온 데이터로 작은 모달을 열어야 한다. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 facebookLogin() { FB.login((response: any) => { if (response.authResponse) { let userData = response.authResponse; this.coreApi.create(`shops/${this.shop.id}/facebook/login`, { facebook_access_token: userData['accessToken'], facebook_user_id: userData['userID'], facebook_profile: '', facebook_username: '', }).subscribe(response => { this.facebook_page_list = response.body.page_list; const dialogRef = this.dialog.open(FacebookPageComponent, { data: { facebookPageList: this.facebook_page_list }, minWidth: '600px', minHeight: '600px' }); } 분명 facebook_page_list에는 올바른 데이터가 포함되는데 모달이 떠도 내부에 데이터가 보이지 않는다. 신기한건 그 페이지의 개발자도구를 키는 순간 데이터가 나타난다는 것.. 뭐 이런 듣도보도 못한 경우가 다 있나 싶었다. ...

2025년 1월 13일 · 1 분 · 배준수

Django Serializer에서 is_valid를 쓰는 이유

Today I Learned 날짜 2025년 1월 10일 금요일 내용 is_valid() 페이스북 로그인을 구현하고 있다. 열심히 API를 만들었더니 처음 보는 오류가 뜬다. “message”: “You must call .is_valid() before accessing .validated_data.” 알아보니.. 시리얼라이저에서 발생하는 오류였다. 1 2 3 4 5 6 7 8 9 10 11 12 def get(self, request, shop_id): try: data = ShopFacebookProfile__Manager.get_by_shop_id(shop_id=shop_id) ... def patch(self, request: Request, shop_id: int): try: serializer = ShopFacebookProfile__Serializer(data=request.data) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) ... 두 요청의 차이는 입력 데이터를 직렬화 과정에서 데이터를 검증하는지가 있다. 첫번째 get요청은 데이터를 받아서 별다른 직렬화를 진행하지 않는다. 따라서 데이터가 예상하는 것과 전혀 다른 것이 들어와도 요청 수준에서는 어떤 검증도 하지 않는다. 물론 내부 로직이 진행되는 과정에서 데이터 형식이 달라 함수들이 오류를 뱉는 것은 별개의 문제지만… ...

2025년 1월 10일 · 1 분 · 배준수

Sentry에서 Stack Trace를 추가하는법

Today I Learned 날짜 2024년 1월 9일 목요일 내용 Sentry에서 Stack Trace를 추가하는법 에러가 난 구체적인 코드를 아는 건 서비스의 에러를 해결하는데 정말 큰 도움이 된다. (구) 글로벌팀의 서비스들은 Sentry를 사용하고 있는데 구체적인 에러의 위치가 나타나지 않는다. 이전부터 지속적으로 웹훅에 오류가 발생하고 있는 상황이라 이 기능이 꼭 필요하다. 이걸 Stack Trace라고 한다. 사실 이전에 시도를 했었다. Github Integration을 하면 된다고 했는데, 그 이후에도 보이지 않는다.. 이렇게 추가해줬다. 하지만 에러 메시지가 출력이 안되는데… capture_exception() 을 사용하면 된다는 글을 이제야 봤다. 빠르게 적용해봤다. ...

2025년 1월 9일 · 1 분 · 배준수

데이터베이스 CPU 사용률이 높은 문제

Today I Learned 날짜 2024년 1월 8일 수요일 내용 데이터베이스가 이상하다. 여전히 쇼피파이 웹훅이 주기적으로 크게 실패하는 모양새를 보인다. 저렇게 주기적으로 크게 몰아서 실패하는 모양새다. 오류의 원인은 다양하지만 대개 400: error in update_shopify_product_by_webhook(psycopg2.errors.UniqueViolation) duplicate key value violates unique constraint “shopify_product_pkey” 이렇다. 쇼피파이에서 상품에 붙는 고유 ID를 우리 데이터베이스에서도 unique로 해놨다. 말그대로 고유한 값이므로 전혀 문제될 게 없다. 1 2 3 4 5 6 7 8 9 10 11 12 db_shopify_product = get_shopify_product_by_origin_id_and_service_id( shopify_store=shopify_store, origin_id=data["origin_id"], db=db, ) if not db_shopify_product: res = create_shopify_product( shopify_store=shopify_store, data=data, db=db, ) 코드는 이렇게 되어있다. origin_id 가 쇼피파이에서 붙이는 고유한 값이다. 그 값으로 찾아서 없으면 생성해준다. 애초에 이 웹훅이 “상품 업데이트” 웹훅이기 때문에 없는 상품에 관한 정보가 들어올리가 없다. 들어왔다면 우리 쪽에 문제가 있어 데이터가 유실된 것이니 만들어주도록 작성해놨다. ...

2025년 1월 8일 · 2 분 · 배준수