Shopify 딥 링크

Today I Learned 날짜 2024년 9월 20일 금요일 내용 딥링크 생성 인스타그램 피드 설정을 완료한 유저가 버튼을 누르면 자동으로 위젯이 추가되는 기능을 만들어야 한다. 그래서 난 테마에서 index.json을 가져와 필요한 걸 추가해주면 되지 않나? 생각했다. 실제로 관련된 shopify docs도 있고.. 아무리 해봐도 업데이트하는 put 요청이 Not Found를 반환한다. 관련된 문제를 찾아보니 나만 겪은 문제가 아닌 듯한데, 모든 질문이 작년 2분기 쯤에 몰려있다. 알아본 결과, 테마는 스토어 주인이 권한을 가져야 하기 때문에 앱이 직접 접근해서 수정하지는 못하도록 막혔다고 한다. 특히 json 파일들은.. 그럼 안되는 건데 다른 앱들은 어떻게 한거지? 싶어 이 기능이 있는 다른 앱을 실행해봤다. 자동으로 추가하는게 아니라, 테마 편집기에 추가된 상태로 이동시켜주는 기능이었다. 저장버튼만 누르면 자동으로 반영되도록… ...

2024년 9월 20일 · 1 분 · 배준수

EC2 무한 스크립트 초기화 문제

Today I Learned 날짜 2024년 9월 19일 목요일 내용 건방지지만 좋은 친구 인스타그램 관련된 쇼피파이 앱을 새로 생성했다. 임베디드 앱으로 만들었기 떄문에, 샵이 앱을 다운로드 받은 직후 세션토큰을 검증해주어야 한다. 기존에 다 구현해봤던 로직이라, 과거에 썼던 걸 그대로 가져와 썼다. 근데 토큰이 자꾸 잘못되었다고 뜬다. 분명 Shopify Docs에서 설명한 그대로 했는데… 마지막 원본 서명과 비교할 때 자꾸 다른 값이 뜬다.. GPT한테 물어봐도 제대로 된 해결책을 내놓지 않는 와중에, GPT가 내게 물어왔다. ...

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

4장 하이퍼미디어

4장 하이퍼미디어 클라이언트는 어떤 요청을 해야 할지 어떻게 아는 것일까? ⇒ 하이퍼미디어 하이퍼미디어는 서버가 클라이언트에게 나중에 어떤 HTTP 요청을 보낼 수 있을지 설명하는 방식이다. 하이퍼미디어 유형으로서의 HTML <a> 태그는 HTTP GET 요청을 만들 수 있음을 브라우저에 알려주는 신호다. 더 정확히는, 특정 URL이 방문할 수 있는 리소스를 부른다는 웹 서버의 약속 사용자가 활성화할 때만 요청(클릭)이 진행된다. <img> 태그도 요청할 수 있는 HTTP GET 요청을 설명하긴 하지만, 문서 사이를 이동한다는 뜻은 담겨 있지 않다. ...

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

서운산 등반

2024년 9월 17일에 등산을 다녀왔는데, 바빠서 이제야 후기를 쓴다. 그 당시 스트레스가 상당했던지라 머리 비우러 갔었다. 그 당시 개발중인 서비스의 디버깅이 도무지 끝날 길이 안보였었기 떄문이다. 자존감이 바닥을 쳐 정신이 나가기 일보 직전이라 마음을 가다듬기 위해 산에 올랐다. 그리고 그떈 몰랐다. 12월에도 그걸 디버깅 하고 있을 줄은… 산 입구에 주차장이 잘 되어있다. 산 입구에 있는 청룡사 덕분이다. 넓~은 주차장이 무료개방. 개이득. 오늘의 목적지는 서운산 정상이다. 길이 복잡하지 않아 좋다. 루트는 2곳인데 짧고 험난한게 왼쪽이다. ...

2024년 9월 17일 · 2 분 · 배준수

ECS 컨테이너가 아무 이유없이 종료될 때

Today I Learned 날짜 2024년 9월 13일 금요일 내용 ECS 컨테이너가 종료되는 이유 ECS 테스크가 자꾸 종료된다. 내부 로직에선 전혀 이상하지 않은데… 몇일 전에 해결된줄 알았더니 작동하고 안하고가 반복된다. 물론 안하는 경우가 훨씬 많지만.. 내부 코드에는 문제가 없다고 판단해서 AWS를 열심히 찾아봤다. ECS에서 컨테이너가 작동해 태스크가 추가되면, 그 태스크의 IP가 로드밸런서가 향하는 대상그룹에 등록된다. 그리고 그 컨테이너가 제대로 통신할 수 있는지 확인하게 된다. 여기서 방금 실행된 컨테이너 IP가 Target is in an Availability Zone that is not enabled for the load balancer ...

2024년 9월 13일 · 1 분 · 배준수

테이블명을 잘 지어야 하는 이유

Today I Learned 날짜 2024년 9월 12일 목요일 내용 이름을 처음부터 잘 짓기 기존 인스타그램 코멘트의 기능을 떼오고, 새로 개발한 기능을 합쳐 새로운 서비스를 만들고 있다. 만들면서 계속 느끼는건, 처음 지을때 이름을 잘짓는 거다. 예를 들어 인스타그램에서 가져온 게시글을 저장하는 테이블은 최초에 InstagramCommentMedia 라고 지었다. 근데 두 서비스를 Instagram Comment와 Instagram Feed라는 이름을 가지긴 했지만, 변수명으로 사용하기엔 부적절하지 않나 생각이 들었다. 결국 인스타그램 코멘트는 인스타그램 비즈니스 계정과 연관된 서비스고, 인스타그램 피드는 인스타그램 일반 계정과 연관된 서비스니까. 서버쪽에선 이 뉘앙스를 풍기는게 유지보수에 유리할거라 생각했다. 그래서 InstagramBusinessAccountMedia라고 지었다. 인스타그램 비즈니스 계정에 속한 미디어라는 의미다. ...

2024년 9월 12일 · 2 분 · 배준수

3장 리소스와 표현

3장 리소스와 표현 REST는 설계 제약 조건 모음이다. 무엇이든 리소스가 될 수 있다 사용자가 어떤 작업을 취하고 싶다면 그것을 리소스로 만들어야 한다. 리소스에는 딱 하나의 제약만 있다. 모든 리소스는 URL을 가져야 한다. 다시말해, 무언가에 URL을 부여하면 그건 리소스가 된다. 리소스의 기본 형태는 비트 스트림이다. 클라이언트는 URL과 리소스의 표현만 볼 뿐이다. 표현은 리소스의 상태를 설명한다 표현 : 클라이언트가 리소스에 GET 요청을 보내면 그 리소스를 유용한 방식으로 나타내는 문서를 제공해야 한다. “기계가” 읽을 수 있는 설명으로 나타낸 것 표현은 양방향으로 전송된다. 클라이언트도 POST 요청에서 리소스의 표현을 보낸다. 새 리소스가 어떻게 보여야 하는지에 대한 클라이언트의 생각이 나타난다. 서버는 그 표현을 추가하거나 변경하거나 일부 무시할 수 있다. 데이터베이스 필드에 항상 created_at 과 updated_at 을 남김 표현의 상태 전송 서버는 리소스의 상태를 나타내는 표현을 보낸다. 클라이언트는 그 리소스가 가졌을면 좋을 상태를 설명하는 표현을 보낸다. 많은 표현이 있는 리소스 하나의 리소스에 여러 표현이 있을 수 있다. 다양한 언어, 파일 형식 등 클라이언트가 원하는 표현을 지정하는 법 HTTP 헤더의 값 각 표현마다 별개의 URL 부여 HTTP의 프로토콜 의미 체계 클라이언트가 리소스에 원하는 행동에 대한 규칙이 있다. 미리 정의된 프로토콜을 따라 메시지를 보낸다. 웹 API에선 이 프로토콜이 HTTP다. GET: 리소스의 표현을 얻음 DELETE: 리소스를 제거 POST: 주어진 표현에 기반을 두고 이 리소스 아래 새 리소스를 생성 PUT: 이 리소스의 현재 상태를 주어진 표현으로 대치(전체) PATCH: 이 리소스의 일부 상태를 주어진 표현으로 변경(일부) HEAD: 이 리소스의 표현과 함께 주어질 헤더를 받음(표현은 X) OPTIONS: 이 리소스가 어떤 HTTP 메서드에 응답하는지 알아냄 LINK: 다른 리소스를 이 리소스에 연결 UNLINK: 다른 리소스와 이 리소스의 연결 관계를 제거 모든 요청은 프로토콜 의미 체계가 동일하지만, 애플리케이션 의미 체계는 다르다. GET 정보를 요청할 뿐이라 안전한 메서드여야 한다. 리소스 상태를 바꿀 것을 예상해서는 안된다. DELETE 삭제하는 메서드 멱등성(idempotence) DELETE 요청은 두 번 이상 보내도 한번 보낸것과 같은 결과가 나와야 한다. 지운걸 또 지우려는 요청을 보내도 처음 지웠을 떄와 동일하기 때문이다. 수학 0을 곱하는 것과 같은 이치 GET도 마찬가지다. 리소스가 변하지 않으므로 PUT도 마찬가지. 같은걸 계속 덮어써도 결과는 동일하므로 POST로 추가하기 새로운 리소스를 생성 PUT 덮어쓰기 PATCH 일부만 수정할 경우 멱등성이 없다. 예를 들어, 특정 값을 1 증가시키는 요청을 보내면 멱등성이 없다. PUT은 리소스 전체상태의 교체기 때문에 이러한 요청이 없다. 특히 PUT은 전체상태를 모르는 상태에서 이렇게 만들기 위해 쓰기도 한다. 반면 PATCH는 현재 상태를 알고 이를 일부 변화시키기 위한 요청 아직 HTTP 명세에 정의되지 않았다. LINK와 UNLINK 리소스 간 하이퍼미디어 링크를 관리 멱등하지만, PATCH와 마찬가지로 명세에 정의되지 않아 안전하지 않음 HEAD GET을 헤더에만 적용하는 느낌이라 안전함 GET 대신 쓰더라도 시간이 줄어들진 않지만, 대역폭 사용량은 줄어든다. OPTIONS 응답 헤더에는 HTTP Allow가 담겨, 해당 리소스가 지원하는 HTTP 메서드를 나열한다. 잘 설계된 API는 이 요청이 없어도 응답에 제공되는 하이퍼미디어 문서로 알게끔 해준다. 오버로드한 POST 사실 온갖 종류의 변화에 다 쓰이는게 POST다. ...

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

EC2 스크립트 쉘 레벨 문제

Today I Learned 날짜 2024년 9월 11일 수요일 내용 실서버 배포 여정 진행중인 인스타그램 기능을 실서버에 우선 올리기로 했다. 새 서비스로 사용자가 없는 서비스라 별 문제는 없을 듯 싶다. 데이터베이스 구조가 변경되어 마이그레이션이 필요했기 떄문에 실서버 코드가 반영된 EC2에 접속했다. 근데 터미널 bash창에 커서도 안뜨고 이런 오류가 계속 나타난다. 1 2 3 /usr/bin/sh: warning: shell level (1000) too high, resetting to 1 /usr/bin/sh: warning: shell level (1000) too high, resetting to 1 bash: warning: shell level (1000) too high, resetting to 1 쉘 레벨이 너무 높다는 경고라고 한다. 호출이 지나치가 많다는 의미인데, 쉘이나 스크립트에서 무한재귀에 빠졌을 때 발생하는 오류 메시지라고 한다. ...

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

비활성화와 삭제 구분하기

Today I Learned 날짜 2024년 9월 10일 화요일 내용 비활성 샵과 삭제한 샵 비활성화된 스토어들을 캐시에서 삭제했었다. 리뷰서버에서 샵 데이터를 Redis 캐시에서 받아 쓰는데, 캐시에 올라가있지 않으면 애초에 처리하지 않을 거라고 생각했기 떄문이다. 그럼에도 불구하고 몇일 간격으로 오류가 발생한다. 처음 몇번은 비활성화 된 샵인데도 캐시에 남아있는 경우가 있었다. 왜인지는 모르곘으나, Redis 관련 요청이 성공률이 높지 않다. 그래서 기존 코드에도 3회 정도 반복하는 코드가 있었구나 싶었다. 별 수 없어서 열심히 처리했는데 또 난다. ...

2024년 9월 10일 · 1 분 · 배준수

Shopify에서 Shop URL이 2개인 이유

Today I Learned 날짜 2024년 9월 9일 월요일 내용 샵 URL이 2개인 이유 쇼피파이에서 유저가 앱을 설치하면, 가장 먼저 알게 되는 샵 정보는 샵의 URL이다. 알파플러스에선 샵의 URL을 shop_url과 platform_shop_url 이라는 두 값으로 저장한다. 사실 왜 두 개인지 몰랐다. 뭐 레거시 인가 싶긴 했는데.. 그래서 인스타그램 코멘트를 만들때는 그냥 샵 URL을 하나만 가져왔다. 이게 모든 문제의 원인일 줄이여… 실제로 쇼피파이에서도 샵의 URL 관련 정보는 2가지이다. 하나는 “domain”, 다른 하나는 “myshopify_domain”이다. 전자는 유저가 설정에서 바꿀 수 있다. 스토어 이용 고객이 접속할 때 쓰는 URL이고 변경가능하다는 의미이다. 실제로 변경하는 스토어가 왕왕 있다. 반면 후자는 샵을 생성하면서 고정되는 값으로 변경되지 않는다. 각 스토어가 쇼피파이에서 가지는 고유한 ID가 있듯, 이 URL도 고유한 값이다. 따라서 스토어와 관련된 데이터를 쇼피파이에 요청할 때도 이 URL이 쓰인다. 우리가 테마를 조회하던, 메타필드를 조회하던, 주문 데이터를 조회하던 이 값이 없으면 아무것도 못한다. ...

2024년 9월 9일 · 2 분 · 배준수