엔드유저 관점에서 로직 생각하기

2024년 4월 2일 화요일

Today I Learned

날짜

2024년 4월 2일 화요일

내용

엔드유저의 진입에 따라 발생해야 할 데이터와 로직들을 고민했다.

세그먼트

Shopify에서 고객들을 특정 기준에 따라 세그먼트로 묶어 관리할 수 있다. 이메일 입력 여부, 지역, 국가, 주문량 등등.. 어제의 고민은 “미션을 통과하여 쿠폰을 사용할 자격이 생긴 사람”을 세그먼트로 관리하기 부적절하다는 것이었는데, 기획에 대한 이해가 부족하여 생긴 오류였다.

내 생각의 전제조건은 쿠폰을 받은 유저가 로그인이 되있어야 한다는 것이다. 하지만 쿠폰 발급과 고객의 로그인 여부는 연관이 없다. 로그인을 요구하는 시점은, 쿠폰을 사용할 때 뿐이다. 따라서 이 쿠폰을 사용하는 사람을 한정짓는 조건은 “회원가입하여 로그인이 되어있는 사람”이다.

결국, 세그먼트는 생성해야하고 만들 프라이스 룰의 사용 요건은 세그먼트로 설정해야 했다. 여기서 추가적인 고민이 생겼다.

초기 데이터

한 스토어가 서비스를 설치했을 때 생성되야할 데이터는 무엇인가? 어떤 로직이 발생해야 하는지를 고민했다. 프라이스 룰은 언제 어떻게 생성되어야 할까? 세그먼트는 언제 생성될까?

서비스를 사용하기 시작하면 우리 데이터베이스에 초기 기본 설정 상태의 데이터가 저장된다. 이 때 Shopify에 프라이스 룰과 세그먼트도 생성되어야겠다고 판단했다. 좀 더 구체적으론, 프라이스 룰의 사용 요건으로 세그먼트를 설정해줄 것이므로 고객 세그먼트를 만든 후 이 세그먼트의 ID를 입력한 프라이스 룰을 3개 만들어야 한다. 기본 설정상 고객이 받을 수 있는(사용할 수 있는) 쿠폰의 갯수는 3개이므로 프라이스룰도 3개를 만들었다.

업데이트

프라이스룰을 변경하는 GraphQL이 존재한다. priceruleUpdate뮤테이션을 사용하면 된다. 할인률이나 쿠폰의 할인코드가 변경되는 것은 큰 상관이 없을 테지만 사용 횟수에 관해선 문제가 된다. 스토어에서 “고객이 최대로 받을 수 있는 쿠폰의 수”를 변경하면 그에 맞춰 프라이스룰의 갯수도 변해야한다. 떄에 따라 늘어나거나 줄어들어야 한다. 늘어날 때도 몇 개는 생성되야하고 몇개는 수정되어야 한다. 할인률이 5%인 쿠폰을 설정하고 유저가 3번 참여할 수 있었던 스토어에서, 할인률을 10%로 올리고 7번 참여할 수 있도록 변경했다고 생각해보자. 기존에 있던 프라이스룰 3개는 할인률만 변경하고, 4개는 아예 새로 생성해야한다. 각 프라이스룰의 디스카운트코드에 번호도 붙여야 하니(ex. THANKYOU3, …) 너무 복잡하다. 내가 만들어도 나중에 유지보수 할 수 있을까..?

정책이 바뀔때 프라이스룰을 삭제하고 프라이스룰을 업데이트하도록 해주었다.

추상 클래스

프라이스룰을 생성하고 삭제하는 것, 세그먼트를 생성한느 로직이 비슷한 것 같아 추상 클래스로 만들었다.

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
38
39
40
41
42
43
44
45
46
class BrowseBoosterSetting(ABC):
	def __init__:
		# 초기화
		
  @absctractmethod
  def fill_variables(self):
	  # 받은 데이터 변수를 쿼리에 삽입
	  pass
	  
	@abstractmethod
	def set_variables(self):
		# Shopify로 보내기위한 GraphQL의 쿼리 형태로 설정 
		pass
		
	@abstractmethod
	def upload_shopify(self):
		# Shopify에 요청
		pass
		
	@abstractmethod
	def save_data(self):
		# 변경사항을 데이터베이스에 저장
		pass
		
class BrowseBoosterSegmentSetting(BrowseBoosterSetting):
	def __init__:
		super().__init__()
		
	...(추상 메서드 구현)...
	
	def create_segment(self):
		# 위 메서드를 차례대로 호출하는 로직
		
class BrowseBoosterPriceRuleCreate(BrowseBoosterSetting):
	
	...(추상 메서드 구현)...
	
	def create_price_rule(self):
	

class BrowseBoosterPriceRuleDelete(BrowseBoosterSetting):

	...(추상 메서드 구현)...
	
	def delete_price_rule(self):
	

훨씬 깔끔하다.

회고

내가 구현하여 추가된 코드도 있었고, 기존 코드에 수정도 있었다. PR 전에 Dev 브랜치를 받아와 내 브랜치에 병합하는 과정에서 여러가지가 꼬인채로 PR을 올렸다. 항상 기존 기능들을 테스트하고 올리고, 변경 사항은 공유하는 습관을 들이자.