실서버 배포 1차시도 실패

Today I Learned 날짜 2024년 5월 29일 수요일 내용 실서버 배포 오늘 처음으로 내가 실서버를 배포했다. 뭐 잘못될까봐 무서운데 여러모로 크고 작은 문제를 겪었다. EC2 인스턴스 내에서 데이터베이스 마이그레이션을 하는데, 파일 수정이 안됐다. alembic으로 새로운 변경을 적용할떄 보통 Enum 타입이 오류가 많이난다. 오늘도 나서, 해당 부분을 수정했는데 파일 저장이 안됐다. 파일을 읽고 쓸 권한이 없다고 경고창이 떴다. 전체 디렉토리, 특정 파일 모두 chmod로 권한을 줬으나 잘 안되다 갑자기 됐다. 지 맘대로여 아주.. ...

2024년 5월 29일 · 1 분 · 배준수

데이터베이스 정규화의 중요성

Today I Learned 날짜 2024년 5월 28일 화요일 내용 정규화와 연관된 데이터 업데이트 리스트 디자이너 고도화작업을 시작했다. 이전에 개발된 것에서 문제를 찾았는데, 상품 정보가 변경되어도 곧바로 리스트 디자이너 위젯에 적용되지 않는다. 우선 이 부분을 해결하려 했다. 계획상으론 그리 어렵지 않았는데, 웹훅을 이용해 상품이 업데이트 될 경우 그 상품이 ListDesignerProduct 에 연관된 데이터가 존재할 경우 그 데이터도 업데이트 시켜주면 될거라 생각했다. 하지만 예상치 못한 곳에 빠져 고민이 생겼다. 필요한 데이터는 product가 아닌 product_variants에 있다. ...

2024년 5월 28일 · 2 분 · 배준수

자잘한 QA 처리

Today I Learned 날짜 2024년 5월 27일 월요일 내용 QA 이것저것 자잘한 QA를 열심히 처리했다. 코어스크립트 활성화 여부를 체크할 때 알파플러스 앱 ID가 입력되고 있어서 제대로 반영이 안됨. 상품 등록할때 데이터베이스에선 상품 아이디를 secondary_product_id 로 처리하지만 스키마와 프론트에선 product_id 로 처리해서 데이터가 누락됨. 할인코드가 “THANKYOU” 로 시작되야 하는데 “BROWSE_BOOSTER”로 만들어짐 상품 정보가 변경되었을 때 반영이 안됨. 어떤 샵에 대한 웹훅인지 확인하는 과정에서 shop_url로 Redis 캐시를 확인하는데 새 앱 정보는 들어있지 않아 다른 앱 정보에서 샵을 찾고 있었음. 계정 설정 페이지에서 관계된 계정을 찾는데 잘못된 방식으로 탐색해서 화면에 출력되지 않음 관리자 계정을 추가할 때, 연관된 스토어 추가에 새로운 앱은 반영되지 않음 등등.. 배설한 업보가 많다 많아. ...

2024년 5월 27일 · 1 분 · 배준수

Pytest와 faker로 코드 작성

Today I Learned 날짜 2024년 5월 24일 금요일 내용 테스트 코드 작성을 위한 DB 모델링 우리 서비스의 테스트 코드는 pytest로 작성되어 있고, 데이터베이스는 SQLite다. SQLite는 파일 형식이라 만들고 뚝딱 삭제해버리면 금방이다. 우리 데이터베이스인 Postgres 와 마찬가지로 SQL이긴 하나 약간의 기능 차이는 존재한다. 하나 꼽자면 jsonb 타입의 필드가 없다. jsonb는 json과 달리 내부의 키로 검색할 수 있는 나름 유용한 타입이다. 쇼피파이에서 넘어오는 스토어 데이터는 Shop 테이블에 담긴다. 가공없이 그대로. 스토어와 관련해서 우리가 필요하고 자주쓰는 데이터는 이 자식테이블 격인 shop_detail에 담긴다. 여기에 apps_log라는 이름으로, 그 스토어가 활성화한 서비스가 어떤 것인지를 담는데 이 필드가 jsonb 타입이다. ...

2024년 5월 24일 · 4 분 · 배준수

파이썬 알고리즘 : 후보키

2024년 5월 24일 알고리즘 문제풀이 문제 후보키 난이도 Lv.2 코드 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 from itertools import combinations # 최소성을 만족하는지 확인하는 함수 # 검증하는 조합 target의 부분집합이 이미 찾은 조합 answer_array에 포함되어 있는지 확인 # 포함되어 있으면 target은 최소성을 만족하지 않음 def validate(answer_array,target): for i in answer_array: if set(i).issubset(target): return False return True def solution(relation): answer = [] n = len(relation) m = len(relation[0]) arr = [ i for i in range(m)] for i in range(m): # 모든 속성 조합을 구함. idx = list(combinations(arr,i+1)) for q in idx: # 유일성을 만족하는지 확인 # 속성의 값을 이은 문자열을 set에 넣어 중복을 제거 # 중복이 없다면 유일성을 만족 check = set() for j in range(n): tmp = "" for k in q: tmp += relation[j][k] check.add(tmp) # set의 길이가 n과 같다면 중복이 없단 의미로 유일성을 만족 if len(check) == n: # 최소성을 만족하는지 확인 if validate(answer,q): answer.append(q) return len(answer)

2024년 5월 24일 · 1 분 · 배준수

Gitbook을 이용한 Docs 작성

Today I Learned 날짜 2024년 5월 23일 목요일 내용 서비스 독스 작성 올해 회사에서 이룰 개인적인 목표 중 하나는 우리 팀의 서비스에 대한 Docs를 작성하는 것이다. 처음 계획은 어떤 기능이 어떤 함수, 어떤 파일에서 어떻게 데이터를 주고받는지를 기록하려고 했다. 내가 보기 위해서기도 하지만, 여러 사람이 협업하는 만큼 다른사람이 작성한 코드를 읽고 파악하는데 낭비되는 시간을 최소화하기 위해서였다. 문서를 작성하는 시간만큼 내가 코드 보는 눈도 좋아질 것이고.. 조언과 여러 생각 끝에 방향을 틀어 기능과 흐름에 대해 작성하는 걸로 수정했다. 이렇게 되면 코드와 언어 자체에 대한 해석은 부족할지라도 전체적인 흐름을 파악할 수 있어 큰 그림의 이해가 더 쉽다. 또한 문서를 읽을 수 있는 사람이 개발자로 한정되지 않는다. 아주 약간, 조금의 짬이 차면서 기능을 개발하면서 생기는 고민은 코드 퀄리티나 방식에 대한 고민도 있지만, 지금은 에러가 나거나 로직상 구멍이 나서 유저가 원치않는 상황에 직면하게 되는 것을 더 걱정하게 되었다. 지금 시점에서 더 깔끔하고 근사한 코드를 짜는 사람보다는 계획 수준에서부터 그림을 그릴 줄 아는 개발자, 내가 들여야 할 공수와 시간을 정확하게 계산해 낼줄 아는 개발자가 되고 싶다. ...

2024년 5월 23일 · 2 분 · 배준수

파이썬 알고리즘 : Container With Most Water

2024년 5월 23일 알고리즘 문제풀이 문제 Container With Most Water 난이도 medium 코드 1차시도 시간초과(50/62) 모두 탐색했는데 시간초과가 떴다. 1 2 3 4 5 6 7 8 9 10 11 12 class Solution: def check(self,a,b,height): val = min(height[a], height[b]) return abs(b-a)*val def maxArea(self, height: List[int]) -> int: n = len(height) ans = 0 for a in range(n-1): for b in range(a+1,n): ans = max(ans, self.check(a,b,height)) return ans 2차시도 메모리초과(49/62) 인덱스 중 2개를 골라 처리하려 했는데 2개의 숫자 조합을 만들기 위한 배열이 메모리초과가 떴다. 아무래도 접근 방법 자체가 틀린것같다. ...

2024년 5월 23일 · 2 분 · 배준수

데이터가 삭제되지 않는 로직 찾기

Today I Learned 날짜 2024년 5월 22일 수요일 내용 데이터 삭제 관리 서비스 내에 별개의 앱이 생성되면서 이것저것 분기 테스트를 진행중이다. 어떤 샵이 어떤 서비스를 사용하고 있는지, 어떤 앱을 설치했는지가 항상 정확하게 처리되어야 한다. 설치 과정에서 발생하는 문제들은 여러 테스트들에서 이상이 없었다. 샵을 삭제할 때, 연결된 계정의 삭제여부도 결정해야한다. 어떤 계정이 더이상 연결된 샵이 없으면, 그 계정은 삭제되어야 한다. 기존에는 알파플러스 앱에 있는 샵들만 확인하면 됐었는데, 이제 확인해야할 샵이 늘었다. 이 부분을 뒤늦게 파악하여 부랴부랴 추가해주었다. ...

2024년 5월 22일 · 1 분 · 배준수

jsdeliver 폭파사건

Today I Learned 날짜 2024년 5월 21일 화요일 내용 사건사고(?) 백서 그동안 사내 다른 사버스들에서 발생했던 중대한 문제들에 대한 백서 공유 시간이 있었다. 자세히 이야기하자면 길지만 서버 문제로 고객사들의 스토어에 문제가 생겨서 발생한 문제들이었다. 사실 jsdeliver가 작동하지 않았을 때, FastAPI에서 자동으로 생성해주는 swagger UI 문서가 제대로 뜨지 않고, 내 개인 블로그도 고장나서 알게 되었다. 우리 글로벌 서비스의 위젯도 작동하지 않았지만 다행히 문제제기는 없었다. 문제가 있었던 오전 9시부터 11시는 미국 LA 기준으로 오후 5시부터 7시 쯤이니 잘 몰랐던 건 아닐까! 나중에 백서 쓸일이 없었으면 좋겠다. ...

2024년 5월 21일 · 1 분 · 배준수

파이썬 알고리즘 : 오픈채팅방

2024년 5월 21일 알고리즘 문제풀이 문제 오픈채팅방 난이도 Lv.2 코드 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 def solution(record): n = len(record) answer = [] # 들어오거나 나가는 행동을 저장할 배열 arr = dict() # 각 아이디의 최종 닉네임을 저장하기 위한 배열 name = dict() # 데이터를 가공하기 위한 반복문 for i in range(n): # 데이터 분리 data = list(record[i].split(" ")) tmp = dict() # 들어오고 나가는 행동이면 저장 if data[0] != "Change": tmp["message"] = data[0] tmp["id"] = data[1] arr[i] = tmp # 들어올 때 닉네임을 바꾸는 경우 추적 if data[0] == 'Enter': name[data[1]] = data[2] # 닉네임을 바꾸는 행동일땐 저장하지 않고 이름만 갱신 else: name[data[1]] = data[2] # 출력하기 위한 반복문 for i in range(n): # i번째일때 바꾸는 행동이였으면 arr에 해당 키 값은 존재하지 않음 if i not in arr: continue # 각 아이디의 최종 닉네임으로 출력 if arr[i]["message"] == "Enter": c = name[arr[i]["id"]] + "님이 들어왔습니다." elif arr[i]["message"] == "Leave": c = name[arr[i]["id"]] + "님이 나갔습니다." answer.append(c) return answer

2024년 5월 21일 · 1 분 · 배준수