[Spring boot] Figma API로 Image URL 가져오기

동재·2023년 10월 11일
0

Delgo

목록 보기
3/3

개요

제가 참여하는 프로젝트(Delgo)에서는 강아지와 함께 가기 좋은 장소(Mungple)를 선정 및 소개하고 있습니다, 따라서 추천하고자 하는 장소의 Figma Image File을 NCP의 Object Storage에 저장하는 절차가 필요합니다.

Mungple 이미지 등록 프로세스
1. 디자이너는 Figma에 이미지 파일을 업로드한다.
2. 각 이미지 파일을 .png 형식으로 다운로드한다.
3. 다운로드한 .png 파일을 .webp 형식으로 변환한다.
4. 변환된 .webp 파일을 NCP Object Storage에 업로드한다.
5. NCP의 저장된 주소를 데이터베이스에 기록한다.

이전에는 Mungple을 새롭게 추가할 때마다 이미지 파일을 .png 형식으로 직접 다운로드하는 방식을 사용했습니다. 그러나 Mungple의 추가 개수가 점차 증가하면서, 한 번에 수십 장의 이미지 파일을 저장하고 업로드해야 하는 상황이 발생했습니다. 이에 따라 팀원들과 함께 더 효율적인 방법을 모색하기로 결정했습니다.

3, 4, 5 단계는 이미 웹서버를 통해 자동화되어 있었기 때문에, 주요 과제는 2단계의 자동화였습니다. 여러 방안을 검토한 결과, Figma API의 도입을 결정하게 되었습니다.

이 글에서는 Figma API를 도입하면서의 접근 방식과 겪었던 문제점들에 대해 공유하고자 합니다.


Figma에서 해야할 일

API를 연동함에 있어 Figma에서 선행적으로 해야할 일이 있습니다.

아래의 내용은

https://velog.io/@jun094/Figma-API%EB%A1%9C-storybook%EA%B3%BC-%EC%95%84%EC%9D%B4%EC%BD%98-%EB%8F%99%EA%B8%B0%ED%99%94%EC%8B%9C%ED%82%A4%EA%B8%B0

해당 블로그를 참고하여 작성했습니다. 기능 구현시 큰 도움이 되었습니다. 이자리를 빌려 감사드립니다.

STEP 1 : Figma Token 생성


Figma REST API를 사용하기 위해서는 개인 token값이 필요합니다. Token 아래 과정을 통해 생성 가능합니다.

Profile(Avatar) > settings > Account > Personal access tokens

STEP 2 : Figma FileKey와 NodeId 생성


FigmaAPI를 사용하기 위해서는 사용하려는 파일의 FileKey와 NodeId가 필요합니다. 만약, 해당 페이지 전체 Node들의 정보를 원한다면 음영(회색) 부분을 클릭하면 됩니다.

FileKey와 NodeId 값은 상단 이미지에서 보이듯이 URL에서 확인이 가능합니다.

Figma에서 Node는 왼쪽 사이드바의 계층 구조에서 하나 하나를 의미합니다.

각각의 Node들을 클릭할 때마다 URL에서 NodeId 값이 바뀌는 것을 확인할 수 있습니다.

STEP 3 : Image Component 설정

해당 과정은 Figma API가 Image 파일에 접근을 효율적으로 하기 위해 필요합니다.

피그마에서

  1. 부모 nodeId로 자식 nodeId 조회
  2. 자식 nodeId로 각 ImageUrl 조회

하는 방식으로 ImageUrl을 가져올 수 있습니다.

만약 각각의 nodeId로 위의 과정을 진행하게 되면 4번의 URL 연결이 필요합니다. 그러나 이 4개의 아이콘을 하나의 컴포넌트로 묶어서 해당 컴포넌트의 nodeId로 조회하면, 단 한 번의 URL 연결로 4개의 아이콘 정보를 얻을 수 있습니다.

이렇게 하나의 컴포넌트로 묶어 조회하면, URL 연결 횟수를 최소화할 수 있습니다. 특히 Figma API는 이미지 처리와 관련되어 있어 속도가 상대적으로 느리기 때문에 연결 횟수를 최소화하여 효율성을 높이는 것이 바람직합니다.

STEP 4 : Image Component 설정파일 명명 규칙 정하기

Mungple 등록에는 각 다른 5종류(썸네일, 메뉴, 메뉴판 ...)의 사진을 필요로 합니다.

따라서 컴퓨터에게 각 사진이 어떤 종류의 사진인지 알려줄 수 있어야 하고 명명 규칙을 통해 이를 해결하고자 했습니다.

해당 규칙은 팀 회의를 통해 결정하여 파일에 접근 권한을 가진 모든 사용자가 해당 내용에 대해 알 수 있도록 했습니다.

아래는 저희 팀의 명명규칙입니다.

지역_카테고리_장소명_순서.png
ex) 송파구_애견미용실_쌍금이네_1.png

* [순서 1부터 시작]3장일 경우
 송파구_애견미용실_쌍금이네_1.png
 송파구_애견미용실_쌍금이네_2.png
 송파구_애견미용실_쌍금이네_3.png

* [지역의 경우 우선 구단위로 설정]
송파() 구가 무조건 붙어야 함.
ex) 송파_애견미용실_쌍금이네_1.png(X) 
     송파구_애견미용실_쌍금이네_1.png(X)

* [카테고리 정의]
- 강아지산책코스
- 애견동반카페
- 애견동반식당
- 동물병원
- 애견미용실
- 애견유치원
을 제외한 다른 단어 X
ex) 송파구_음식점_쌍금이네_1.png(X) 
    송파구_애견동반식당_쌍금이네_1.png(0)


* [썸네일의 경우]
  - 기존 형식 그대로 사용
  ex) 송파구_애견미용실_쌍금이네_thumbnail_1.png
  ex) 송파구_애견동반카페_위커커피_thumbnail_1.png

* [메뉴의 경우] (카페, 식당)
  ex) 송파구_애견동반카페_위커커피_menu_1.png

* [메뉴판의 경우] (카페, 식당)
  ex) 송파구_애견동반카페_위커커피_menu_board_1.png

* [가격표의 경우] (산책, 병원, 미용실, 유치원)
  ex) 송파구_애견미용실_쌍금이네_price_1.png

* [상주견의 경우] (모든 카테고리)
ex) 송파구_애견미용실_쌍금이네_dog_1.png

Web Server에서 해야할 일

Web Server에서는 Figma API 규칙에 따라 Image Url을 가져오는 작업을 진행합니다.
저는 Spring Boot, RestTemplate를 사용해서 구현했습니다.

STEP 1: Figma API 연결

위에서 발급 받은 token을 전역변수로 설정하고 Header에 담아줍니다.
Http 통신을 위한 RestTemplate 초기화를 진행해줍니다.

 private final String figmaToken = "figd_r19ArRmULsFD~~~~~~~~~~~~~~~~~~";

    private HttpHeaders createHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.set("X-FIGMA-TOKEN", figmaToken);
        return headers;
    }

    private RestTemplate createRestTemplate() {
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        return new RestTemplate(httpRequestFactory);
    }

STEP 2: 자식 nodeId(imageI) 가져오기

: Figma에서 장소별로 컴포넌트로 묶게 되면 하나의 nodeId를 가져올 수 있습니다.

imageId : 자식 nodeId (코드를 짤 때 직관적으로 해석하기 위해 제가 명명했습니다.)
편의를 위해 하단의 내용에서부터는 imageId를 사용하겠습니다.


위 사진의 URL에서 보이는 component의 nodeId로 각 자식 노드 별 nodeId(imageId)에 접근할 수 있습니다.

API: api.figma.com/v1/files/[figmaFileKey]/nodes?ids=[nodeId]

Json 예시 데이터
"nodes": {
        "5900:52704": {
            "document": {
                "id": "5900:52704",
                "name": "보리지_5900-52704",
                "type": "COMPONENT",
                "scrollBehavior": "SCROLLS",
                "blendMode": "PASS_THROUGH",
                "children": [
                    {
                        "id": "5900:52681",
                        "name": "서대문구_애견동반카페_보리지_1",
                        "type": "FRAME",
                        "scrollBehavior": "SCROLLS",
                        "blendMode": "PASS_THROUGH",
                        "children": [
                            {
                                "id": "5900:52682",
                                "name": "IMG_8428 1",
                                "type": "RECTANGLE",
  ...
  ...
 

하단의 코드는 HashMap에 key: imageId vale: fileName을 저장하는 코드입니다.

    public Map<String, String> getImageIdFromFigma(String nodeId) {
        RestTemplate restTemplate = createRestTemplate();
        HttpHeaders headers = createHeaders();

        String requestURL = API_URL + "files/" + figmaFileKey +"/nodes?ids=" + nodeId;
        ResponseEntity<String> responseEntity = restTemplate.exchange(requestURL, HttpMethod.GET, new HttpEntity<>(headers), String.class);

        Map<String, String> imageIdMap = new HashMap<>();
        try {
            JsonNode rootNode = new ObjectMapper().readTree(responseEntity.getBody());
            JsonNode childrNodes = rootNode.get("nodes").get(nodeId).get("document").get("children");

            for (JsonNode childNode : childrNodes) {=
                String imageId = childNode.get("id").asText(); // ex) 4935:43532
                // 사람에 의한 실수 없애기 위해 공백문자 제거 코드 추가
                String fileName = childNode.get("name").asText().replaceAll("\\s+", "");  // ex) 강동구_애견동반식당_담금_5
                imageIdMap.put(imageId, fileName);
            }
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw new FigmaException(e.getMessage());
        }

        return imageIdMap;
    }

STEP 3: imageId로 image URL 가져오기

STEP 2에서 얻은 imageId로 Image URL에 접근할 수 있습니다.

API: api.figma.com/v1/images/[figmaFileKey]/?format=png&scale=3&ids=[nodeId]

해당 API는 다양한 옵션을 제공하고 있지만 제가 사용한 옵션만 소개하고 넘어가겠습니다.

ids: 한 번에 여러개의 ImageUrl을 가져올 수 있도록 해줍니다.
scale: 사진의 크기를 지정할 수 있는데 해당 값을 크게 해주면 화질을 높일 수 있습니다. 저는 3으로 설정하여 사용중입니다.
format: 사진 형식을 지정할 수 있습니다. 전 png로 설정했습니다.

더 자세한 옵션은
https://www.figma.com/developers/api
ctrl + F > api.figma.com/v1 하면 확인하실 수 있습니다.

아래의 코드는 imageId를 담은 KeySet을 통해 ImageURL을 가져오고
HashMap에 fileName, imageUrl을 담는 코드입니다.

public Map<String,String> getImageUrlFromFigma(Map<String,String> imageIdMap) {
        RestTemplate restTemplate = createRestTemplate();
        HttpHeaders headers = createHeaders();

        String requestURL = API_URL + "images/" + figmaFileKey +"?format=png&scale=3&ids=" + String.join(",", imageIdMap.keySet());
        ResponseEntity<String> responseEntity = restTemplate.exchange(requestURL, HttpMethod.GET, new HttpEntity<>(headers), String.class);

        Map<String,String> imageUrlMap = new HashMap<>();
        try {
            JsonNode rootNode = new ObjectMapper().readTree(responseEntity.getBody());
            JsonNode imageNodes = rootNode.get("images");
            Iterator<Map.Entry<String, JsonNode>> fields = imageNodes.fields();
            while (fields.hasNext()) { // Iterator<Map.Entry<String, JsonNode>>
                Map.Entry<String, JsonNode> field = fields.next();
                String imageId = field.getKey(); // ex) 4931:43548
                String imageUrl = field.getValue().asText(); // ex) https://figma-alpha-api.s3.us-west-2.amazonaws.com/images/8ab72901-93ef-48f2-b11a-dd204e9eec31
                String fileName = imageIdMap.get(imageId); // ex) 강동구_애견동반식당_담금_menu_5

                imageUrlMap.put(fileName, imageUrl);
            }
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw new FigmaException(e.getMessage());
        }

        return imageUrlMap;
    }

해당 ImageUrl을 NCP에 업로드 하는 로직은 추후에 작성해보도록 하겠습니다!
감사합니다~😊

끝!

profile
Backend Developer

0개의 댓글