일정을 작성하기 전 전체 로그인을 하며 순회하던 도중

트리거 부분이 어색한 것을 보게 되었다.

 

프로필 이름을 user.ProfileId로 진행했었는데

사실 파트너 유저인지 체크를 하지 않으면 파트너가 아닌 유저들의 변경 사항에도

즉각적으로 수정이 반영되기 때문에 뜬금없는 공유 처리로 인한 지연 또는 낭비가 발생할 수 있었다.

 

이 문제를 해결하기 위해 어떤 부분에서 데이터를 비교해야 하나 확인하다가

처음에는 List<String>을 생성해 파트너의 이름을 직접 입력해주려고 했으나

해당 방식은 확장성에 문제가 생길 수 있을 것 같아서

조금 더 자동적으로 처리되는 공통분모를 생각해보니

라이센스를 기반으로 생성된 이름들에 포함되면 괜찮을 것 같았다.

 

해당 값을 어떻게 가져올지 조금 더 자세히 보면

UserLicenseId를 고정값을 넣으면 편하게 가져올 수 있었는데

해당 값의 Id 자체는 현재 고정이긴 하지만 ID 하드코딩을 권장하지 않기 때문에

해당 라이센스의 이름인 ‘Partner Community Login’를 통해 Id를 가져오고

해당 Id를 통해 UserLicenseId에 대입해 현재 보유한 등급을 모두 불러올 수 있었다.

 

유저 데이터를 감지 후

ProfileId를 통해 값을 비교해 파트너인지 찾아야 했고

해당 파트너 확인은 아래 코드로 확인이 가능했다.

select Id from Profile where UserLicenseId In (select Id from UserLicense where Name = 'Partner Community Login')

 

이를 통해 파트너 관련 데이터만 처리할 수 있게 되었지만

보유 그룹 및 변경 그룹 조회가 너무 복잡해져서 고민이었는데

내용을 확인하던 중 in의 반대인 not in 같은 기능이 있으면 좋겠다고 생각하며 검색했는데

다행히도 not in이라는 기능이 존재했기 때문에 변경 지역을 확인할 수 있었다.

 

이걸 진행하던 도중 심각한 문제를 발견했는데

등급이 바뀌는 것(프로필)을 가정하지 않고 간단히 처리하다가

등급이 포함되니 조금 더 복잡해졌다.

 

사실 등급이 바뀌는 것은 조금 더 간단하게 볼 수도 있을 것 같은데

등급이 변했다면 이전 등급과 관련된 권한은 모두 지워야 하고

새로 추가된 등급에 맞는 현재 지역의 권한을 추가하면 되는 일이었다.

 

등급이 변했을 경우 아래와 같이 UserOrGroupId를 통해

등록된 모든 sharing에서 해제시키기 위해

delete 리스트에 아래의 Id들을 추가시킨다.

select Id from GroupMember where UserOrGroupId = :user.Id

 

그 후 insert를 했을 때 처럼 Trigger.new의 user에서

지역 및 등급을 합친 이름의 리스트를 만들고

해당 리스트에 포함되는 그룹들의 아이디를 꺼내준 다음

해당 id들에 userId를 포함시킨 아래의 코드로 insertList에 추가해 생성한다.

new GroupMember(GroupId = gId.Id, UserOrGroupId = user.Id);

 

파트너 등급을 확인하려고 했지만

이전 등급과 현재 등급을 매칭해서 비교할 방법이 떠오르지 않았고

이걸 다시 맵으로 변환해야 하는지 고민하며 검색한 결과

Trigger.newMap, Trigger.oldMap이 이미 존재한다는 사실을 알 수 있었다.

 

해당 방식을 통해 직접 map을 만들지 않아도 자동적으로 id로 접근할 수 있기 때문에

조금 더 편안한 마음으로 작업을 진행할 수 있게 되었다.

 

머리 내부에서는 어떻게 처리 결과가 나왔는데

해당 구현을 실제로 쓰려고 하면 막히는 상태라서 계속 지연되는 것 같다.

 

글로 한번 더 과정을 정리해보자면 트리거마다 각 유저를 받고 아래의 절차 실행

  • 데이터를 입력받은 경우 파트너 프로필인지 확인
    • 파트너 프로필이 아닐 경우 중단
  • 해당 파트너 유저의 등급(프로필)이 변경되었는지 확인
    • 변경된 경우 추가 절차 시행, 아닌 경우 다음 단계 실행
    • select Id from GroupMember where UserOrGroupId = :user.Id로 이전 데이터 삭제
    • Location__c.split(’;’)을 통해 얻은 주소값 반복문으로 insertList에 gm추가
  • 해당 유저의 추가 및 삭제된 지역 확인 후 deleteList, insertList에 추가
  • 권한 확인 후 각 List 삭제 및 추가

중간에 심플리챗 테스트 지원을 다녀온 다음 조금 더 코드를 정리하다보니

각 지역명에 맞는 부분을 쿼리로 불러올 필요 없이 처음에 한번 쿼리로 불러온 내용을

map으로Name:Id 형태로 매칭시키면 편하게 불러올 수 있다는 사실을 알 수 있었고

드디어 for문 내부에 쿼리가 하나도 남지 않게 수정할 수 있었다.

 

정리한 절차대로 파트너 프로필 확인 작성 후

등급 변경에 따른 처리 코드 작성을 시작하려고 했으나

시작부터 쿼리문으로 처리하려는 모습을 보고 충격이었다.

 

기껏 없앤 쿼리문을 다시 넣을 수는 없지만

그렇다고 저 부분을 해결하기 위해 전체 GroupMember부분을 다 가져와서

하나 처리하기 위해 맵으로 정렬하는 것은 말이 되지 않았다.

 

쿼리를 배제하고 생각해보려고 해도 해당 Id값을 알아야 삭제할 수 있는데

해당 Id를 조회하려면 쿼리를 사용해야 하는 딜레마에 빠져버렸다.

 

생각해보면 다른 삭제 기능들도 모두 쿼리를 사용할 수 밖에 없는데

이 부분은 메서드 쪼개기로 실행할 예정으로 두고 쿼리를 사용해야 할 것 같다.

 

코드를 작성하던 도중 해결법을 발견했는데

당장 삭제 리스트에 해당 코드들을 집어넣을 필요는 전혀 없었고

삭제 처리 과정을 진행했다고 치고 다음 과정으로 넘어가고

대신 삭제할 List<GroupMember>를 생성하기 위한 Id집합에 추가해두면 되는 것이었다.

 

기존의 코드인 아래 코드를 사용했다면

‘List<GroupMember> gms = [select Id from GroupMember where UserOrGroupId = :oldUser.Id]’

gms를 즉각 도출하는 것이 아니라 사용된 oldUser.Id를 삭제 쿼리에 사용할 배열로 저장하고

해당 배열을 where in arr 형태로 사용하는 것이었다.

 

추가 삭제 지역을 통한 프로필 유지 부분의 변경을 진행하려고 했는데

삭제 부분이 정말로 어려웠다.

 

삭제를 진행하기 위해서는 비교 후 해당하는 내용만 삭제해야 하는데

삭제할 내용 자체가 두세개 밖에되지 않았지만 삭제 작업을 위해서는

해당 자료로 쿼리를 날려야 id값을 조회할 수 있었고

내부 필드 자체가 Id, GroupId, UserOrGroupId, SystemModstamp의 4가지 밖에 없었기 때문에

추가적인 비교 필드 자체가 존재하지 않았는데

이걸 해결하기 위해 위와 같은 방식으로 접근할 수 있는 방법을 고민해보니

where (a,b) in ((a,b),(a2,b2),(a3,b3),(a4,b4))형태였지만

해당 방식은 SQL에서만 지원하고 SOQL에서는 지원하지 않는다고 한다..

 

없으면 있는 대로 해야 하기 때문에 두 Id값을 합친 fmField를 생성한 다음

해당 fmFieldId와 매칭될 수 있는 값을 생성해 fmFieldIds같은 형태로 생성하기로 하고

9시 25분에 퇴근 준비를 시작했다.

 

 

 

 

 

(1).백준 15295번 Chanukah Challenge는

하누카라는 유대인 명절에 초를 킬 때 

하루에 하나씩 더 늘려나가고

매일 저녁 하나의 고정 수치의 초를 킨다고 할 때

각 케이스마다 몇개의 초가 필요한지를 출력해야 하는 문제였다.

 

1~n까지 증가는 n(n+1)/2로 해결 가능했고

매일 한개의 초는 총 n개가 들어갔기 때문에 n(n+3)/2로 해결할 수 있었다.

const input = `3
1 8
2 1
3 10`.split('\n').map(el => el.split(' ').map(Number))

const result = []
for(let i = 1 ; i < input.length ; i++){
    const [a,b] = input[i]
    result.push(a + ' ' + b*(b+3)/2)
}
console.log(result.join('\n'))

'회고' 카테고리의 다른 글

[수습일지] - 62(주말)  (0) 2023.05.27
[수습일지] - 61  (0) 2023.05.26
[수습일지] - 59  (0) 2023.05.24
[수습일지] - 58  (0) 2023.05.23
[수습일지] - 57  (0) 2023.05.22

+ Recent posts