sfdc에서 외부에 api 연결을 할 수 있는 방법은 여러개가 있지만

대부분의 방법은 access token을 필요로 하고

access token을 발급받는 방법 또한 여러가지가 있지만

대표적으로 Connected App을 사용해서 진행해야 하기 때문에

Connected App 생성, Access token 발급 방법에 대해 정리했다.

 

시작은 당연히 Connected App을 만드는 것에서 부터 시작된다.

App Manager

 

내부에서 App Name, Api Name, Email 등은 알아서 작성하고

Callback URL은 “https://localhost:5001/callback”를 입력한 다음

Oauth Scopes에는 Full과 refresh_token을 넣어준다.

(refresh_token 방식이 아닌 Id, Password 방식인 경우 refresh_token 권한 부여 필요 없음)

OAuth2 설정

 

생성할 경우 아래와 같이 10분정도 걸린다는 경고메세지가 출력되는데

10분을 넘기는 경우도 많다는 정도만 이해하고 다음으로 넘어가면 된다.

(※이후 postman 또는 주소 입력시 발생하는 에러의 대부분은 ‘시간’문제일 가능성이 크다)

반영이 늦어질 수 있다는 경고

 

 

Edit Policies(정책 변경)을 누른 다음 내부에서 refresh_token 만료일 등을 정할 수 있으며

IP Relaxation 또한 변경이 가능하다.

Refresh Token Policy

 

다시 App manager에서 view 또는 보기를 눌러 생성한 Connected App의 세부사항으로 들어가고

하단에 존재하는 Manage Consumer Details를 클릭해 Consumer Key, Consumer Secret 확인 할 수 있다.

Consumer Key 확인하기

 

인증 방식은 아래처럼 접속한 User의 Email로 인증코드가 발송되는 구조이기 때문에

이메일 주소가 본인이 확인 가능한 주소인지 다시 한번 확인 후 진행해야 한다.

이메일 인증

 

인증을 마치면 아래와 같이 Consumer Key, Consumer Secret을 확인할 수 있는데

Copy를 통해 복사해두거나 해당 페이지를 닫지 않고 이후 절차를 진행하는 것을 추천한다.

Consumer Key, Secret

 

 

여기서부터는 postman이 있어야 더 편리하게 진행할 수 있는데

아래 이미지처럼 params를 넣어 주소를 완성하거나 아래의 주소 내부 밑줄 부분만 변경해 인터넷 주소창에 입력하면 된다.

Product - https://login.salesforce.com/services/oauth2/authorize?response_type=code&client_id="Consumer Key"&redirect_uri=https://localhost:5001/callback

Sandbox - https://test.salesforce.com/services/oauth2/authorize?response_type=code&client_id="Consumer Key"&redirect_uri=https://localhost:5001/callback

(Playground는 developer로 추정되지만 login으로 로그인 가능한 것 등 문제의 여지가 많아 불확실)

Code 발급받기

 

해당 링크를 주소창에 입력할 경우 아래와 같은 에러가 발생할 수 있는데

해당 내용은 10분이 걸리다던 Connected App이 아직까지 세팅되지 않아서 발생하는 문제일 가능성이 크다.

 

실제로 10분이라고 하지만 17분이 지난 이후 되는 것을 확인할 수 있었는데

해당 방법을 이미 해보지 않았다면 이 부분에서 계속 시도하면서 세팅을 바꾸다 포기했을 가능성이 있다.

 

Connected App의 LastModified에서 10분이 지나지 않았다면 잠깐 쉬거나 다음 내용을 미리 확인하는 것을 추천한다.

생성한 Connected App이 반영되기 전 진행할 경우 발생하는 메세지

 

정상적으로 링크가 입력되었다면 먼저 SFDC 로그인을 요구하는데

가끔 최하단 블러처리된 부분의 계정이 내가 의도한 것과 다른 org일 가능성이 있다.

 

여러개의 org를 동시에 관리하고 있으면 혼합될 문제가 있기 때문에 사용자가 아님을 누른 다음 재로그인을 하고 다시 링크를 입력하고 최하단의 요청자가 내가 의도한 계정이 맞는지 확인해야 한다.

권한 허용

 

허용 후 아래와 같은 연결할 수 없음 페이지로 이동되거나

이동되지 않은 경우다시 링크를 입력하면 아래의 주소로 이동되는데

이 부분은 정상적인 이동으로 주소값 상단을 보면 code = xxxxx 형태로 값이 들어간 것을 볼 수 있다.

주소창에서 Code값 추출하기

 

입력된 code 뒤에 있는 값을 복사해주는데 여기서 주의사항은 %3D는 ‘=’를 의미하기 때문에

마지막 %3D%3D를 ==으로 대체해야 한다.

 

이제 refresh을 발급받아야 하는데 아래와 같이 https://login.salesforce.com/services/oauth2/token 주소값에 code, grant_type, client_id, client_secret, redirect_uri을 Params로 넣어주면 되고

이전과 동일한 이야기지만 Product일 경우에만 login이며 Sandbox는 login 대신 test를 사용해야 한다.

 

주소값으로는 아래처럼 “” 내부 값들을 채워서 링크를 보내도 된다.

https://login.salesforce.com/services/oauth2/token?code="Code"&grant_type=authorization_code&client_id="Consumer Key"&client_secret="Consumer Secret"&redirect_uri=https://localhost:5001/callback

code = "이전에 주소창에서 받은 code값 %3D%3D주의"
grant_type = authorization_code
client_id = App Manager에서 확인한 Consumer Key
client_secret = App Manager에서 확인한 Consumer Secret
redirect_uri = App Manager에서 설정한 Callback url("<https://localhost:5001/callback>")

 

정상적으로 요청이 완성된 경우 아래와 같이 refresh_token과 access_token을 받을 수 있다.

Refresh Token이 발급된 모습

 

access_token을 사용해서 Authorization을 진행할 수 있고

refresh_token을 사용해 code 없이 인증을 받을 수 있는데 refresh_token 발급과 유사하다.

Access Token 발급받기

 

발급받은 Access token을 통해서 일반적인 Authorization 인증을 진행할 수 있는데

아래 이미지처럼 Authorization을 헤더에 넣는 것만으로도 인증을 처리할 수 있고

위에서 나온 instance_url 뒤에 services/data/v56.0/query/?q= + 쿼리문을 넣어 직접 sfdc 레코드 쿼리가 가능하다.

SFDC REST API 사용(AccessToken을 통한 Authorization 인증)

 

쿼리 방법은 스페이스를 +로 대체하는 것 외에 특별한 것은 존재하지 않으며

최대 출력 갯수는 2천개로 제한되어 있기 때문에 두번째 사진처럼 nextRecordsUrl을 사용해 다음 값을 받을 수 있다.

SFDC REST Query 방식(2000개 제한)

 

추가로 refresh_token이 없는 경우에는 아래 이미지처럼 정보들을 입력해야 하는데

Params로 아이디, 비밀번호를 보내야 하기 때문에 refresh_token 발급 방식을 권장한다.

grant_type = ‘password’
client_id = {Consumer Key}
client_secret = {Consumer Secret}
format = ‘password’
username = {sfdc 아이디}
password = {sfdc 비밀번호}

Refresh Token 없는 방식

 

체크박스 관련 질문이 들어왔는데

Default value를 unchecked가 아닌 checked로 생성했음에도 불구하고

기존에 존재하는 레코드들은 새로 추가된 필드의 값이 false로 되어있다는 것이었다.

 

해당 문제를 듣고 playground의 contact에 추가 필드를 만들고 checked를 설정했지만

기존에 존재하던 contact 내부 필드들은 전부 false 상태인 것을 확인할 수 있었다.

 

결국 데이터를 전부 true로 바꿔주면 될 것 같아서 아래의 코드 방식으로 업데이트를 할 수 있다고 전달했으나

too many라는 문구가 뜬다는 답을 받았다.

List<Contact> objectList = [Select Id From Contact];
List<Contact> updateList = new List<Contact>();
 
for(Contactobj : objectList){
    updateList.add(new Contact(Id = obj.Id, testField__c = true));
}
 
update updateList;

 

문제의 원인을 생각해보며 직접 쿼리를 날려보니 아래와 같은 결과를 받을 수 있었는데

주석처리한 것처럼 DLM row는 1만건만 가능하기 때문에

실제 운영되는 데이터를 한번에 업데이트 할 수 없는 것이었다.

  Number of SOQL queries: 1 out of 100
  Number of query rows: 29 out of 50000
  Number of SOSL queries: 0 out of 20
  Number of DML statements: 1 out of 150
  Number of Publish Immediate DML: 0 out of 150
  Number of DML rows: 29 out of 10000            //한번의 수행에 10000개 DML 제한
  Maximum CPU time: 0 out of 10000
  Maximum heap size: 0 out of 6000000
  Number of callouts: 0 out of 100
  Number of Email Invocations: 0 out of 10
  Number of future calls: 0 out of 50
  Number of queueable jobs added to the queue: 0 out of 50
  Number of Mobile Apex push calls: 0 out of 10

 

이런 문제는 사실 간단하게 하나씩만 바꾸면 되기 때문에 변경 필드를 따로 생성할 필요 없이

아래 코드처럼 Where 조건과 Limit만 추가하면 해결되는 부분이었지만

이전에 인터페이스 쿼리 부분의 제한도 존재하지 않을까 의심이 되기 시작했다.

List<Contact> objectList = [Select Id From Contact Where testField__c = false Limit 10000];
List<Contact> updateList = new List<Contact>();
 
for(Contactobj : objectList){
    updateList.add(new Contact(Id = obj.Id, testField__c = true));
}
 
update updateList;

 

확인 결과 sfdc rest query 방식은 한번에 2천개의 레코드밖에 가져오지 못했는데

5~6자리의 데이터를 받아오려면 어떻게 해야되는지 궁금증이 생겼고

실제로도 해당 방법이 필요해서 알아보니 생각보다 간단하게 해결할 수 있었다.

 

아래 사진처럼 수천개의 데이터가 출력될 ㅣ경우 실제로 나오는 데이터는 2천개밖에 되지 않지만

nextRecordsUrl을 my.salesforce.com/ 뒷부분에 입력하면 두번째 사진처럼 가져올 수 있으며

사실 2000 대신 500, 1000등의 숫자를 입력하면 해당 숫자부터 2천개가 출력되기 때문에

자의적으로 쪼개서 받을 수 있다.(최대치 2천개 아래로 변경은 모름)

SFDC REST Query

 

offset도 어느정도 고려했지만

데이터 수량이 커지면 작동하지 않으며 아래와 같은 에러메세지를 볼 수 있었고

대량의 데이터인 경우 어쩔 수 없이 nextRecordsUrl 방식을 사용하기로 하고 넘어갔다.

//Request
q=SELECT+ID,+name+from+contact+OFFSET+5000

//Response
[
    {
        "message": "Maximum SOQL offset allowed for apiName Contact is 2000",
        "errorCode": "NUMBER_OUTSIDE_VALID_RANGE"
    }
]

 

 

 

(1).백준 25814번 무거운 숫자는 길이를 가중치로 두고 내부 자릿수들을 모두 더한 값을 가중치와 곱하는 방식으로

첫번째 숫자와 두번째 숫자를 비교해 0, 1, 2를 출력하는 문제였다.

 

문자열로 입력된 값을 각각 calculate 함수에 넣어 결과를 계산하고  a와 b에 할당한 다음 해당 값을 비교했다.

const input = `123 90`.split(' ')

const calculate = (str) => {
    const arr = str.split('').map(Number)
    let sum = 0
    for(let i = 0 ; i < arr.length ; i++){
        sum += arr[i]
    }
    return sum * arr.length
}

const a = calculate(input[0])
const b = calculate(input[1])

if(a > b){
    console.log(1)
}
else if(b > a){
    console.log(2)
}
else if(a == b){
    console.log(0)
}

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

[개발일지] - 210  (0) 2024.01.26
[개발일지] - 209  (0) 2024.01.25
[개발일지] - 207  (0) 2024.01.23
[개발일지] - 206  (0) 2024.01.22
[개발일지] - 205(주말)  (0) 2024.01.21

+ Recent posts