yozm.wishket.com Open in urlscan Pro
3.38.63.136  Public Scan

Submitted URL: https://event.stibee.com/v2/click/MTI0NTg0LzIxNzUyOTAvMzQ5MTEwNC8/aHR0cHM6Ly95b3ptLndpc2hrZXQuY29tL21hZ2F6aW5lL2RldGFpbC8...
Effective URL: https://yozm.wishket.com/magazine/detail/2325/
Submission: On May 16 via api from US — Scanned from DE

Form analysis 8 forms found in the DOM

<form enctype="multipart/form-data" id="profile_image_edit_form"><input name="csrfmiddlewaretoken" type="hidden" value="58LSJKrUja89h3VKgWT5FP0emEamnvMBtAEvAbrfNesHQZUuOEYrJMGb4ueLVM5P">
  <div class="modal__title">프로필 사진 등록<div class="close_modal" onclick="close_modal()"><img class="modal-close-image-button only-mobile" src="/static/renewal/img/news/icon_m_gnb_close.png"
        srcset="/static/renewal/img/news/icon_m_gnb_close.png 1x, /static/renewal/img/news/icon_m_gnb_close@2x.png 2x,/static/renewal/img/news/icon_m_gnb_close@3x.png 3x"><img class="modal-close-image-button only-pc"
        src="/static/renewal/img/news/icon_modal_close.png" srcset="/static/renewal/img/news/icon_modal_close.png 1x, /static/renewal/img/news/icon_modal_close@2x.png 2x,/static/renewal/img/news/icon_modal_close@3x.png 3x"></div>
  </div>
  <div class="modal__body">
    <div class="modal-body-wrapper" id="profile_image_edit_modal_body">
      <div class="modal-content">나를 알릴 수 있는 프로필 사진을 등록해 주세요.</div><img class="user-profile-img" id="modal_user_img"><img class="temp-user-img user-profile-img"><img class="user-img-default user-profile-img" src="/static/img/default_avatar.png">
      <div class="loading-circle user-profile-img">
        <div class="sk-fading-circle theme-yozmit">
          <div class="sk-circle1 sk-circle"></div>
          <div class="sk-circle2 sk-circle"></div>
          <div class="sk-circle3 sk-circle"></div>
          <div class="sk-circle4 sk-circle"></div>
          <div class="sk-circle5 sk-circle"></div>
          <div class="sk-circle6 sk-circle"></div>
          <div class="sk-circle7 sk-circle"></div>
          <div class="sk-circle8 sk-circle"></div>
          <div class="sk-circle9 sk-circle"></div>
          <div class="sk-circle10 sk-circle"></div>
          <div class="sk-circle11 sk-circle"></div>
          <div class="sk-circle12 sk-circle"></div>
        </div>
      </div>
      <div class="body-btn-group theme-yozmit"><input accept=".jpg, .jpeg, .png, .gif" class="img-temp-file" hidden="" type="file"><input hidden="" id="profile_remove_image_file" name="remove_image_file" type="checkbox"><button class="body-btn"
          onclick="upload_image()" type="button"><img src="/static/renewal/img/news/icon_profile_upload.png"
            srcset="/static/renewal/img/news/icon_profile_upload.png 1x, /static/renewal/img/news/icon_profile_upload@2x.png 2x,/static/renewal/img/news/icon_profile_upload@3x.png 3x">사진 올리기</button><button class="body-btn" onclick="remove_image()"
          type="button"><img src="/static/renewal/img/news/icon_profile_delete.png"
            srcset="/static/renewal/img/news/icon_profile_delete.png 1x, /static/renewal/img/news/icon_profile_delete@2x.png 2x,/static/renewal/img/news/icon_profile_delete@3x.png 3x">사진 지우기</button></div>
    </div>
    <div class="modal-info-body">
      <div class="base-dot-list">
        <div class="dot-line">
          <div class="dot">·</div>프로필 사진은 요즘IT 서비스에 표시됩니다.
        </div>
        <div class="dot-line">
          <div class="dot">·</div>.JPG, .JPEG, .PNG, .GIF 파일만 업로드 가능합니다.
        </div>
      </div>
    </div>
  </div>
  <div class="modal__footer">
    <div class="modal__button group-block-button"><button class="button theme-indigo close__modal" id="btn_profile_img_modal_close" type="button">닫기</button><button class="button theme-yozmit" id="btn_profile_img_modal_submit"
        onclick="submit_form('/magazine/api/profile-image/')" type="button">등록 완료</button></div>
  </div>
</form>

<form id="highlight_form" style="display: none;"><input name="csrfmiddlewaretoken" type="hidden" value="58LSJKrUja89h3VKgWT5FP0emEamnvMBtAEvAbrfNesHQZUuOEYrJMGb4ueLVM5P"><input id="selected_string" name="selected_string" type="hidden"><input
    id="block_position" name="block_position" type="hidden"><input id="text_position" name="text_position" type="hidden"><input id="selected_length" name="selected_length" type="hidden"><input id="highlight_id" name="highlight_id"
    type="hidden"><input id="submit_type" name="submit_type" type="hidden"></form>

Name: like_formPOST

<form method="post" name="like_form"><input name="csrfmiddlewaretoken" type="hidden" value="58LSJKrUja89h3VKgWT5FP0emEamnvMBtAEvAbrfNesHQZUuOEYrJMGb4ueLVM5P"><input name="news_id" type="hidden" value="2325"><input name="has_liked" type="hidden"
    value="False"></form>

Name: subscription_formPOST

<form method="post" name="subscription_form"><input name="csrfmiddlewaretoken" type="hidden" value="58LSJKrUja89h3VKgWT5FP0emEamnvMBtAEvAbrfNesHQZUuOEYrJMGb4ueLVM5P"><input name="subscription_target" type="hidden" value="강남언니"><input
    name="subscription_status" type="hidden" value="False"></form>

Name: like_formPOST

<form method="post" name="like_form"><input name="csrfmiddlewaretoken" type="hidden" value="58LSJKrUja89h3VKgWT5FP0emEamnvMBtAEvAbrfNesHQZUuOEYrJMGb4ueLVM5P"><input name="news_id" type="hidden" value="2325"><input name="has_liked" type="hidden"
    value="False"></form>

Name: like_formPOST

<form method="post" name="like_form"><input name="csrfmiddlewaretoken" type="hidden" value="58LSJKrUja89h3VKgWT5FP0emEamnvMBtAEvAbrfNesHQZUuOEYrJMGb4ueLVM5P"><input name="news_id" type="hidden" value="2325"><input name="has_liked" type="hidden"
    value="False"></form>

POST

<form class="scrapbook-edit-modal-form" id="scrapbook-edit-modal-form" method="post" onsubmit="return false" style="display: none"><input name="csrfmiddlewaretoken" type="hidden"
    value="58LSJKrUja89h3VKgWT5FP0emEamnvMBtAEvAbrfNesHQZUuOEYrJMGb4ueLVM5P">
  <div class="yozm-full-modal">
    <div class="container">
      <div class="modal-box mobile-full-box">
        <div class="modal-header" data-share-related="">
          <div class="modal-header-title">스크랩북 만들기<img class="only-pc" onclick="closeEditModal()" src="/static/renewal/img/news/icon_modal_close.png"
              srcset="/static/renewal/img/news/icon_modal_close.png 1x, /static/renewal/img/news/icon_modal_close@2x.png 2x,/static/renewal/img/news/icon_modal_close@3x.png 3x"><img class="only-mobile" onclick="closeEditModal()"
              src="/static/renewal/img/news/icon_m_gnb_close.png" srcset="/static/renewal/img/news/icon_m_gnb_close.png 1x, /static/renewal/img/news/icon_m_gnb_close@2x.png 2x,/static/renewal/img/news/icon_m_gnb_close@3x.png 3x"></div>
        </div>
        <div class="modal-body">
          <div class="body-1-medium text900 title">이름</div><input class="edit_scrapbook_id" type="hidden"><input autocomplete="off" class="modal-input body-2 text600 edit_scrapbook_title yozm-input" defaultvalue="" placeholder="스크랩북의 이름을 입력해 주세요."
            required="" value="">
          <div class="body-3 scrapbook-duplicated yozm-text error hide" style="margin: 8px 0px 0px 13px">이미 사용 중인 스크랩북 이름입니다.</div>
        </div>
        <div class="modal-footer pc-btn-width-80" data-share-related=""><button class="body-2 btn btn-common btn-height-40 btn-8-20 btn-gray" onclick="closeEditModal()" type="button">닫기</button><button
            class="body-2 btn btn-common btn-height-40 btn-8-20 btn-violet scrapbook-edit-modal-form" data-news-id="2325" id="btn-save-scrapbook" type="button">만들기</button></div>
      </div>
    </div>
    <div class="background-overlay" onclick="closeEditModal()"></div>
  </div>
</form>

POST

<form id="cancel-check-form" method="post" onsubmit="return false" style="display: none"><input name="csrfmiddlewaretoken" type="hidden" value="58LSJKrUja89h3VKgWT5FP0emEamnvMBtAEvAbrfNesHQZUuOEYrJMGb4ueLVM5P">
  <div class="yozm-full-modal">
    <div class="container">
      <div class="modal-box">
        <div class="modal-body">
          <div class="title subtitle-2-medium text900"></div>
          <div class="text-content"></div><input class="identifier" type="hidden" value="">
        </div>
        <div class="modal-footer"><button class="btn btn-height-40 btn-8-20 btn-common btn-gray" onclick="closeCancelCheckModal()" type="button">닫기</button><button class="btn btn-height-40 btn-8-20 btn-common btn-orange" id="btn-cancel-"
            type="button">취소하기</button></div>
      </div>
    </div>
    <div class="background-overlay" onclick="closeCancelCheckModal()"></div>
  </div>
</form>

Text Content

요즘IT

위시켓
새로 나온
인기
요즘 작가들
물어봐

키워드, 작가 이름 검색하기

작가 지원

로그인 회원가입

새로 나온
인기
요즘 작가들
물어봐

기획
디자인
개발
프로덕트
아웃소싱
프리랜싱
비즈니스
IT서비스
회원가입 로그인
요즘IT 소개 콘텐츠 제안하기 광고 상품 보기
최근 검색어
전체 삭제
최근 검색어가 없습니다.


프로필 사진 등록

나를 알릴 수 있는 프로필 사진을 등록해 주세요.

사진 올리기사진 지우기
·
프로필 사진은 요즘IT 서비스에 표시됩니다.
·
.JPG, .JPEG, .PNG, .GIF 파일만 업로드 가능합니다.
닫기등록 완료

AWS 이용 중이라면 최대 700만 원 지원받으세요

지금 바로 신청하기

국내 유명 IT 기업은 한국을 넘어 세계를 무대로 할 정도로 뛰어난 기술과 아이디어를 자랑합니다. 이들은 기업 블로그를 통해 이러한 정보를
공개하고 있습니다. 요즘IT는 각 기업의 특색 있고 유익한 콘텐츠를 소개하는 시리즈를 준비했습니다. 이들은 어떻게 사고하고, 어떤 방식으로
일하는 걸까요?

회원가입을 하면 원하는 문장을
저장할 수 있어요!

다음

회원가입을 하면
성장에 도움이 되는 콘텐츠를
스크랩할 수 있어요!

확인



개발


프론트엔드 개발자가 API를 설계하는 이유

강남언니
강남언니
|
13분
|
2023.11.17.
|
인기
16.6K
몇
년차,
어떤 스킬
,
어떤 직무
의
독자들이 봤을까요?
어떤 독자들이 봤는지 궁금하다면?
로그인

국내 유명 IT 기업은 한국을 넘어 세계를 무대로 할 정도로 뛰어난 기술과 아이디어를 자랑합니다. 이들은 기업 블로그를 통해 이러한 정보를
공개하고 있습니다. 요즘IT는 각 기업의 특색 있고 유익한 콘텐츠를 소개하는 시리즈를 준비했습니다. 이들은 어떻게 사고하고, 어떤 방식으로
일하는 걸까요?

 

이번 글에서는 성형수술 및 피부 시술 정보 제공 플랫폼 ‘강남언니’가 병원 관리 소프트웨어 KOS(이하 KOS)를 개발하면서, 새로 도입한
인터페이스 정의 언어를 이용한 인터페이스 관리 전략을 소개합니다.

 


인터페이스 정의 언어

B2B SaaS 애플리케이션 개발을 시작하면서 KOS팀은 인터페이스 정의 언어(이하 IDL, Interface Definition
Language)를 도입하게 되었습니다. IDL은 소프트웨어의 인터페이스를 정의하는 명세 언어를 말하고, 특정한 언어에 국한되지 않는 방법으로
인터페이스를 정의하여 애플리케이션들의 언어가 다르더라도 동일한 인터페이스로 통신할 수 있도록 합니다.

 

여러 종류의 IDL 중, KOS팀은 Google Protocol buffers(a.k.a. Protobuf)를 선택했습니다. KOS팀이
Protobuf를 선택한 이유는 다양한 언어로 Generate 할 수 있다는 특징이 있고, 무엇보다 인터페이스 작성이 매우 쉽습니다. 그리고
추후 gRPC라는 강력한 경량 통신을 사용할 수 있기에 도입했습니다. KOS팀은 IDL을 도입함으로써, 제품 개발 프로세스에 있던 비효율을
해결할 수 있었습니다.

 

IDL을 도입하기 전의 제품 개발 프로세스입니다.

 1. 프로덕트 오너와 프로덕트 디자이너가 이터레이션을 계획하고 와이어프레임을 만듭니다.
 2. 모든 팀 구성원이 참여해 이터레이션 계획 스펙을 확정합니다.
 3. 프로덕트 디자이너가 제품을 디자인합니다.
 4. 백엔드 개발자가 API를 설계하고 노션 문서에 API 명세를 작성(또는 Swagger)합니다.
 5. 프론트엔드 개발자가 해당 인터페이스가 계획된 제품 구현을 반영할 수 있는 스펙인지 확인합니다.

 

위 프로세스의 4, 5번 과정에서 비효율적인 문제들이 발생하곤 했는데요. 자세하게 어떤 비효율적인 문제가 있었고, IDL을 통해 어떻게
해결했는지에 대해 이야기해보겠습니다.

 

 


비효율적인 문제들

1. 유지보수 되지 않는 API 문서

<출처: 강남언니>

 

IDL을 도입하기 이전 관리되던 API 문서의 일부입니다. 위에서 언급한 과정대로 백엔드 개발자가 노션 문서에 통신하는데 필요한 통신 규약들에
대해 정의합니다. 그 뒤, 변경사항이 생긴 이후에는 변경을 인지한 개발자가 문서를 수정을 하게 되는데요. 이때 해당 API 문서는 현재 구현된
코드가 제대로 반영된 상태인지 알기 어렵고, 응답 필드가 많으면 많을수록 어떤 불일치가 있는지 찾아내기 어렵습니다. 이렇듯 시스템이 커질수록
API의 수는 계속 늘어날 것이고, 모든 통신 규약을 노션과 같은 외부 문서로 유지보수하는 데는 꽤 많은 노력을 필요로 하게 됩니다.

 

2. 시스템 관점의 인터페이스 설계

백엔드 개발자가 인터페이스를 주도하여 설계할 때, 데이터 무결성 및 시스템 성능 최적화와 같은 시스템적인 부분이 가장 먼저 고려되는 경우가
많습니다. 이는 기술적 측면에 있어 분명 필수적인 고려 사항이지만 성능에 초점이 맞춰지다 보니 오버 스펙을 가진 인터페이스가 정의될 여지가
생기며, 이로 인해 프론트엔드 개발자와 이를 통합하기 위해 지속적인 합의를 하게 됩니다. 해당 과정에서 커뮤니케이션 오버헤드가 발생하고 운영
비용이 높아질 수 있다는 문제가 있습니다. 이제 이러한 비효율적인 문제를 해결하기 위해 어떠한 변경들이 있었는지 설명드리겠습니다.

 

 


해결

프론트엔드 주도로 인터페이스를 설계한다

> 프론트엔드 개발자가 API를 설계하고 백엔드 개발자는 설계된 해당 인터페이스가 제품 구현을 반영할 수 있는지 리뷰하고 변경을 요청합니다.

 

백엔드 주도로 인터페이스를 설계하면서 직면한 문제를 대응하기 위해 설계 프로세스를 변경했습니다. 이제 UI와 UX 디자인의 복잡성에 대해 더 잘
알고 있는 프론트엔드 개발자가 인터페이스 설계를 주도하여 최종 엔드 유저의 요구 사항과 기대에 부합하는 방식으로 인터페이스를 설계합니다.

 

또한, 이 변경된 프로세스를 통해 백엔드와 프론트엔드 개발자 간 지식 전파도 자연스럽게 이어집니다. 예를 들어, 사용자 경험에 미숙할 수 있는
백엔드 개발자와 시스템 관점에서 생각하기 어려울 수 있는 프론트엔드 개발자 간의 지식 전파가 상호 리뷰를 통해 자연스럽게 만들어지는 효과를 거둘
수 있었습니다. 결론적으로, 프론트엔드 주도로 인터페이스를 설계하는 방식의 전환은 단순한 개발 프로세스의 전환뿐만 아니라 사용자 경험을
우선시하는 문화적 전환이라고 볼 수 있습니다.

 

 

프론트와 백엔드 애플리케이션 코드에 IDL을 적용한다

인터페이스로 정의된 Protobuf 코드를 서버와 클라이언트에서 정의하여 동일한 통신 계약 모델을 사용합니다. 아래에서 실제 Protobuf로
정의된 Message를 이용하여 백엔드와 프론트엔드에서 어떻게 관리되는지 알아보겠습니다.

 

> e.g. 예약 API

message ReservationOption {
  string optionId = 1;
  string optionTitle = 2;
}

message ReserveCommand {
  string visitorId = 1;
  repeated ReservationOption options = 2;
  optional string memo = 3;
  string startDateTimeUtc = 4;
  string endDateTimeUtc = 5;
}

message ReserveCommandResponse {
  string reservationId = 1;
}

service ReservationController {
  rpc reserve(ReserveCommand) returns (ReserveCommandResponse) {
    option (google.api.http) = {
      post: "/tenants/{tenantId}/schedule/reservation/v1/commands/reserve"
      body: "*"
    };
  }
}

Plaintext

 

(병원에서 고객 예약을 생성하는 인터페이스의 일부입니다.)
위처럼 Protobuf로 정의된 메시지를 protoc로 컴파일을 하면, 아래와 같이 코드가 생성됩니다.

 

참고

 * IDL을 정의하기 위해 사용하고 있는 언어인 Google Protocol Buffers는 protoc라는 컴파일러를 통해 여러
   언어(Java, C++, C#, …)로 Generate 할 수 있습니다. 또한, 위 Generate 된 코드를 KOS팀은 Git
   Submodule로 각 애플리케이션에서 Import 하여 사용하고 있습니다.

 

> TypeScript Code로 변환된 인터페이스

export interface ReserveCommand {
  visitorId: string;
  options: ReservationOption[];
  memo?: string | undefined;
  startDateTimeUtc: string;
  endDateTimeUtc: string;
}

export interface ReserveCommandResponse {
  reservationId: string;
}

export const ReserveCommand = {
  encode(message: ReserveCommand, ...) {
    if (message.name !== "") {
      //...
    }
  },
  decode(input) {
    //...
  },
  fromJSON(object: any): ReserveCommand {
    return {
      visitorId: isSet(object.visitorId) ? String(object.visitorId) : "",
      //...
    }
  }
  toJSON(message: ReserveCommand): unknown {
    //...
  }
}

export class ReservationControllerClientImpl implements ReservationController {
  private readonly rpc: Rpc;
  private readonly service: string;

  constructor(rpc: Rpc, opts?: { service?: string }) {
    //...
  }

  reserve(request: ReserveCommand): Promise<ReserveCommandResponse> {
    const data = ReserveCommand.encode(request).finish();
    const promise = this.rpc.request(this.service, "reserve", data);
    return promise.then((data) => ReserveCommandResponse.decode(new _m0.Reader(data)));
  }
}

Plaintext

 

이제 프론트엔드 개발자는 IDL에 정의된 Interface를 Submodule로부터 Import 하여 코드에 반영합니다. 물론, 백엔드 개발자도
동일하게 해당 Interface를 Import 하여 반영합니다.

 

예제 코드로 IDL 적용 방법 알아보기 (WITH CLIENT/ SERVER)

이제 IDL에 명시한 예약 생성의 코드가 각 애플리케이션 언어에 맞게 생성되었으니, 실제 클라이언트와 서버 간 위 코드를 어떻게 적용하여
사용하는지 의사 코드(pseudo-code)로 살펴보겠습니다.

 

> Client Code

// TypeScript로 Generate된 Code를 Import합니다.
import {
  ReserveCommand,
  ReserveCommandResponse,
  ReservationController
} from '@/idl/gen/pb-typescript/reservation';

// 프론트에서 API 호출할 때도, IDL에 정의한 Controller부를 가져와서 선언해줍니다.
const ReservationApi: ReservationController = {
  reserve(command: ReserveCommand): Promise<ReserveCommandResponse> {
    return axios.post(
      '/tenants/:currentTenantId/reservation/v1/commands/reserve',
      ReserveCommand.toJSON(command)
      ).then(ReserveCommandResponse.fromJSON);
  },
  //...
};

Plaintext

 

> Server Code

//Java로 generate된 code를 Import합니다.
import protos.reservation.ReserveCommand;
import protos.reservation.ReserveCommandResponse;

//Server에서도 IDL에 정의한 Controller에 맞춰서 선언해줍니다.
@PostMapping("/tenants/{tenantId}/reservation/v1/commands/reserve")
public ReserveCommandResponse reserve(
    @RequestBody ReserveCommand command
) {
    return reserveCommandExecutor.execute(command);
}

Java

 

위 클라이언트와 서버의 Import 부를 보면 알 수 있듯, 이제 클라이언트와 서버는 항상 동일한 통신 계약 모델을 사용하게 됩니다. 이로써
문제 파트에서 정의한 유지보수 이슈에 대해서 많은 부분을 소화할 수 있게 되었습니다.

 

 


SERVER TO SERVER CONTRACT, EVENT CONTRACT 문제 해결

KOS팀은 현재 MSA 구조로 많은 서비스를 운영하고 있습니다. 각 서비스 간 느슨한 결합을 위해, 이벤트 드리븐 아키텍처를 적절하게 사용하여
만들어지고 있는데요. 이때 많은 도메인 서비스들에서 발행/ 소비되는 이벤트의 계약 모델, 그리고 Server to Server로 이루어진 통신
규약들에 대해서도 문서로만 관리된다면, 하나의 서비스에서 변경이 이루어졌을 때 어디서부터 불일치가 발생했는지 찾는데 많은 리소스가 들게 됩니다.


따라서 각 서비스들 간에서도 위의 문제 섹션에 명시한 동일한 문제를 겪을 수 있게 됩니다. 그러나 각 서비스에서 IDL로 정의된 동일한
인터페이스를 사용한다면, 여러 도메인 서비스에서 발행/ 소비되는 이벤트 계약 모델과 서버 간 통신 규약들에 대해서도 동일한 인터페이스를 가져갈
수 있다는 해결 방법이 생깁니다.

 

이제 읽으시면서 궁금증이 들었을만한 부분들을 Self QnA를 통해 알아보면서 마무리 지어보겠습니다.

 

 


QNA

1. IDL 소스는 어떻게 관리하고 있나요?

<출처: 강남언니>

 

KOS팀은 IDL을 Git에 독립 리포지토리로 만들어서 정의한 뒤, 사용하는 애플리케이션에서 Git Submodule을 이용하여 각 애플리케이션
리포지토리에 불러와 사용하고 있습니다. 또한, 각 애플리케이션에서 Generate 된 코드를 Submodule을 통해 관리하는 이유는
Protobuf가 Protoc, Plugin 버전에 따라 생성된 결과물이 다를 수 있기 때문에 모든 파일을 각 애플리케이션 별 독립된
리포지토리에서 관리하고 있습니다.

 

2. 프론트엔드와 백엔드 간 인터페이스 합의는 어떤 방식으로 하고있나요?

<출처: 강남언니>

 

위는 전체적인 프로세스를 나타낸 도식표입니다. KOS팀은 Code Review 단계에서 인터페이스를 상호 합의를 하고 있는데요. 아래와 같은
방식으로 진행됩니다.

 

<출처: 강남언니>

 

작업에 관련된 프론트엔드와 백엔드 개발자들이 리뷰를 통해 UI/ UX를 반영할 수 있는 데이터 구조인지, 혹은 이 설계가 도메인 바운더리를
위배하고 있진 않는지, 그리고 최종적으로 시스템적으로 구현하는데 문제가 없는 인터페이스인지 확인하는 절차를 가집니다. 이제 PR을 병합한 뒤,
Github Actions의 워크 플로우가 트리거 되어 GitHub Bot이 각 애플리케이션의 언어들로 Generate 시켜 메인 브랜치에
커밋하는 방식으로 관리되고 있습니다.

 

3. 그럼 PROTOBUF를 사용하면서 느낀 단점들은 없었나요?

 * Null Handling이 번거롭다.
   * Protobuf로 생성된 코드는 Null을 할당하면 NPE가 발생하도록 설계되어 있습니다.
   * 따라서, Nullable 한 특성을 갖고 있는 언어로 개발할 때는 Protobuf로 생성된 코드로 변환 시 Null이 들어갈 수 있는
     속성인지 확인 후 반드시 Null Handling을 구현해주어야 합니다.
   * 아래는 상담 엔터티(Java)를 상담 계약모델(Protobuf)로 변환하는 과정을 나타낸 예시 코드입니다.

 

message ConsultationContract {
  Counselor counselor = 1;
  optional string consultationMemo = 2;
}

message Counselor {
  string id = 1;
  string name = 2;
}

Plaintext

import com.healingpaper.solution.reservation.ConsultationEntity;
import protos.reservation.ConsultationContract;

private ConsultationContract convertToContract(
    ConsultationEntity consultation
) {
    return ConsultationContract.newBuilder()
        //counselor는 required한 속성으로, NPE가 발생하지 않습니다.
        .setCounselor(consultation.getCounselor())
        //만약 consultationMemo의 값이 Null이였다면, NullPointException이 발생하게 됩니다.
       .setConsultationMemo(consultation.getConsultationMemo())
       .build();

    // ==================================================

    //따라서, NPE 방지를 위해 상담 메모를 넣어줄 때, Optional Handling 로직을 추가해야합니다.
    return ConsultationContract.newBuilder()
        .setCounselor(consultation.getCounselor())
            .setConsultationMemo(
                Optional.ofNullable(consultation.getConsultationMemo)
                .orElse("")
            )
        .build();
    }

Java

 

 * 위 예시에서 consultationMemo와 같이 Optional 한 속성을 가진 프로퍼티에 만약 Null Handling 로직이
   없었다면, NPE 발생으로 시스템 장애로 이어질 수 있습니다.
   * 따라서, 해당 값이 Optional 한 값인지 체크가 반드시 필요하며 Null Handling을 해줘야 하는 번거로움이 있습니다.

 

4. SWAGGER를 채택하지 않은 이유는 무엇인가요?

Swagger는 현재 많은 기업들이 사용하고 있는 안정성 있고 다양한 기능들이 내포된 유용한 도구로 알려져 있습니다. 그러나 KOS팀에서
채택하지 않은 결정적인 이유는 백엔드 개발자에게 종속된 API Document가 될 수 있기 때문이었는데요. 인터페이스 문서의 주체가 백엔드
개발자에게 강하게 종속되어 있는 경우 어떤 문제들이 발생할 지에 대해 나열해 보면 다음과 같습니다.

 

 * Swagger API Document가 나오기 전까지 프론트엔드 개발자의 업무 블락커가 생길 수 있다.
   * 백엔드 개발자가 Swagger를 사용하기 위해 애플리케이션에 문서 자동화 기반 작업을 하기 전까지 프론트엔드 개발자는 어느 인터페이스가
     나올지 예상하기 어려움으로, 프론트엔드 개발자의 업무에 블락커가 생길 수 있습니다.
 * 인터페이스에 대한 변경이 생길 경우, 정황상 백엔드 개발자의 손길로만 수정이 가능한 구조가 된다.
   * 사용하는 애플리케이션 언어에 따라 다를 수 있겠지만, 예를 들어 TypeScript로 개발하는 프론트엔드 개발자가 Spring에 적용된
     Swagger 정보를 수정하는 건 쉽지 않을 수 있습니다.
   * 이는 곧, 1번에서 말한 내용과 같이 설계의 주체가 백엔드 개발자에게 모두 종속되어 수정이 필요한 경우에도 수정사항이 반영되기 전까지
     업무 블락커가 동일하게 발생할 수 있는 문제가 존재합니다.
 * 단일 진실 공급원(Single Source Of Truth) 관리가 안된다.
   * Swagger를 사용할 경우 인터페이스의 원천에 대해서 파편화가 이뤄질 수밖에 없습니다. 게다가 MSA 환경으로 이루어진 서비스라면
     더욱이 각 애플리케이션 별로 파편화되는 것을 막기는 쉽지 않을 수 있습니다.

 

 


마치며

지금까지 강남언니 KOS팀에서 도입 후 모두가 만족해하고 있는 IDL의 사용 전략에 대해 소개드렸습니다. IDL을 이용하여 클라이언트와 서버 간
통신 규약을 코드로 명시하고 형상 관리를 통해 변경 기록을 관리할 수 있다는 특징 하나만으로도 충분히 매력적이나, 이를 모든 애플리케이션에서
동일한 통신 계약 모델을 강력하게 강제하여 사용할 수 있다는 특징이 저는 가장 강력한 무기라고 생각이 듭니다.


혹시 비슷한 문제 상황을 겪고 있는 팀이라면, 이번 글을 통해 조금이나마 해결에 도움이 되셨으면 좋겠습니다. 마지막으로 KOS팀에서는 이 외에도
빠르고 효율적인 개발을 위해 또 다른 여러 도구와 방식들을 채택하고 있습니다.

 

<원문>

[SaaS] 프론트엔드 개발자가 API를 설계하는 이유

 

요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.



좋아요

11



댓글

5

스크랩북 만들기

스크랩

스크랩됨



공유


저장
스크랩북 만들기
닫기완료

스크랩

스크랩됨



공유



트위터

네이버

URL

페이스북

링크드인

댓글 5
todtod80

            FE 개발자 주도로 API 를 설계해야하는 이유는 납득하기 어렵네요. IDL 활용과 별개로요.
- 일반적으로 BE 개발자도 요구사항 분석 때 함께 참여합니다.
- 요구사항에 부합하되 시스템적인 부분을 포함하여 설계하는 것은 아주 당연합니다. 요구사항에만 맞추고 시스템 부분을 포기한다면, 장애로 직결될 가능성이 상당히 높습니다. 유지보수도 어려워지구요.
- 당장의 UI 요구사항에 맞춘 API 스펙을 설계하면, UI 에 dependency 가 너무 강해집니다. Web은 특성상 변화가 빠르고 많은 영역이구요. 그리고 BE 입장에서는 Client 를 Web 으로 특정하기 어렵습니다. 예를 들어, Web Client 를 위한 API 설계 > App Client 도 Web 과 똑같이 구현하고 BE API 를 사용합니다 > 개편 작업. Web 은 새로운 API 로 먼저 배포 > App 은 특성상 빠르게 API 사용 코드를 동시에 배포하지 못합니다 > BE 는 API versioning 실시
          

2023.11.17. 오후 19:30
todtod80

            API versioning 이 시작되면 BE 의 개발 운영 cost 가 올라갑니다. 큰 과제가 긴 주기로 배포된다면 모르겠지만, 수시로 변경이 일어나고 API 인터페이스에 잦은 변경이 필요한 Web 개발 일상에서 이건 BE 팀에 큰 고통으로 다가옵니다. 하위 호환도 신경써야 하구요.
          

2023.11.17. 오후 19:32
acepm83

            공감안됨
          

2023.11.20. 오후 20:12
solstice

            저도 FE 주도 API는 공감이 안됩니다.. 그럼 웹용 API 앱용 API 다 따로 만들어줘야하는건가요..
          

2023.11.23. 오후 22:34
back123

            흥미롭게 잘 읽었습니다. 
프론트엔드 개발자가 api를 먼저 제안을 하는건 어떨까 생각해보고 이 체계를 어떻게 잡을까 고민했던 시절이있었는데..
이를 idl을 이용해서 이렇게 실제로 운용하고있는 팀이 있었군요 ^^
          

2023.11.25. 오후 20:31
 * 
 * 1
 * 

로그인하고 자유롭게 의견을 남겨주세요.
작성하기
작가의 다른 콘텐츠
PO가 비즈니스 전략을 제품에 녹이는 방법
목적을 생각하면, 일하는 방식이 바뀐다
강남언니가 3년째 OKR로 일하는 방법

강남언니
기업
작가

8
명 알림 받는 중
알림 받기
알림 받는 중
알림이 설정되었습니다.
작가별 알림은 [알림 설정]에서
관리할 수 있어요!


작가 홈


강남언니
기업
작가

8
명 알림 받는 중
누구나 더 좋은 의료서비스를 누릴 수 있게 만드는 것을 꿈꾸고 있습니다. 강남언니의 목표를 빠르고 가치있게 달성하기 위해 끊임없이 일하는 방식과
조직문화를 관찰하고 변화하고 있습니다.

PO가 비즈니스 전략을 제품에 녹이는 방법 기획
목적을 생각하면, 일하는 방식이 바뀐다 기획
강남언니가 3년째 OKR로 일하는 방법 기획
작가의 콘텐츠 더 보기
11

좋아요

5

댓글

스크랩

스크랩됨


스크랩북 만들기

트위터

네이버

URL

페이스북

링크드인

공유

함께 스크랩한 콘텐츠
IT서비스


[SI Q&A 세션 ①] ‘네카라쿠배’ 아니어도 개발자로 성장하고 싶어요

14분
|
2024.05.03.
|
인기

지난 2월 말, 위시켓과 요즘IT 김수보, 안영회 작가가 함께 SI 개발자를 대상으로 Q&A세션을 열었습니다. 사전에 질문을 받고, 그 질문에
대해 현장에서 답하는 시간을 가졌습니다. 초보 및 신입 SI 개발자를 대상으로 기획한 행사였는데, 3~4년차 이상 일하신 분들도 참석해 고민을
나눠주셨습니다. 그날 있었던 대화 내용을 각색해 전합니다.

요즘IT

IT서비스


[SI Q&A 세션 ②] SI 개발자, 어떻게 성장해야 하죠?

15분
|
2024.05.03.

지난 2월 말, 위시켓과 요즘IT 김수보, 안영회 작가가 함께 SI 개발자를 대상으로 Q&A세션을 열었습니다. 사전에 질문을 받고, 그 질문에
대해 현장에서 답하는 시간을 가졌습니다. 초보 및 신입 SI 개발자를 대상으로 기획한 행사였는데, 3~4년차 이상 일하신 분들도 참석해 고민을
나눠주셨습니다. 그날 있었던 대화 내용을 각색해 두 편의 글로 전합니다.

요즘IT

개발


‘API VERSIONING’은 반드시 필요할까?

9분
|
2024.04.22.
|
인기

백엔드 개발자라면 동료 개발자나 외부 고객을 위해 API를 만들고 배포한 경험이 있을 것입니다. 이러한 API는 한번 만들고 배포하면,
삭제하거나 변경하는 게 어려워 집니다. 그래서 ‘API Versioning’으로 이를 관리하게 됩니다. 그러나 API 버전이 바뀌면 고객은 변경
사항을 검토하고, 작성된 API 문서를 살펴보며, 일부 코드를 다시 작성하고, 테스트하여 변경 사항이 문제가 없는지 확인하기 위해 시간을
투자해야 합니다. API Versioning은 고객을 위한 일일까요?

임효성


같은 분야를 다룬 콘텐츠
개발


개발조직은 왜 ‘돈 먹는 하마’로 보일까?

9분
|
5시간 전

“IT회사 CEO들 사이에는 ‘개발조직은 돈 먹는 하마’라는 이야기가 돌고 있어요. 도대체 개발팀들은 맨날 바쁘다, 밤샌다고 하는데 시스템
완성은 매번 늦어져요. 이유가 뭔지 모른 채 엄청난 개발조직 인건비를 지불하고 있어요.” 개발조직이 ‘돈 먹는 하마’로 보이는 현상이 과거
이들이 ‘전산실’이라 불리던 시절부터, 웹과 클라우드의 발전 그리고 AI 혁신이 세상을 시끄럽게 하는 요즘까지도 별 차이가 없다는 이야기입니다.
깊이 공감하는 문제이고, 이 글을 쓰게 된 계기이자 곧 주제이기도 합니다.

안영회

개발


챗GPT-4O, 완전 럭키비키잖아

6분
|
2일 전

OpenAI가 5월 13일에 발표한 챗GPT의 신규 버전이 업데이트 되었는데, 이에 대한 반응이 전 세계적으로 상당히 뜨겁습니다. 새 버전은
실시간으로 일반 사람과의 대화를 모방하는 듯한 환경을 반영하여 더욱 주목받고 있습니다. 특히, 마블의 인기 캐릭터인 아이언맨이 인공지능 비서인
자비스와 대화하는 모습과 아주 유사한 환경까지 제공한다는 점에서 주목받고 있습니다. 이번 업데이트 세션에서 소개된 다양한 챗GPT-4o 활용
방안에 대해 함께 알아보겠습니다.

insight.coco

개발


정적 파일만 있는 사이트를 어떻게 구동시킬까?

8분
|
2일 전

개발을 하다 보면 정적(static)인 파일로만 구성된 웹 사이트를 서비스해야 할 때가 있습니다. 정적인 웹 사이트를 생성하고 서비스하는 방법은
여럿 있지만, 저는 주로 파이썬을 활용합니다. 정적 웹 사이트를 Serving하려면 어떻게 해야 할까요? 아쉽지만 개인이라면 정적 웹 사이트를
인터넷에 서빙하는 일은 생각보다 어렵습니다. 다양한 방법 가운데 어떤 방법이 가장 효과적일지는 비용이나 배포 환경 등 제반 여건에 따라
다릅니다. 이 글이 여러분의 선택에 도움이 되기를 바랍니다.

이지호


인기 있는 콘텐츠
개발


개발자를 위한 영어 12시제 활용 가이드

11분
|
2024.04.18.
|
인기

개발자에게 영어는 선택이 아닌 필수 역량 중 하나인데요. 대부분 프로그래밍 언어가 영어로 되어 있고, 최신 기술과 각종 개발 관련 자료가 먼저
영어로 작성되기 때문입니다. 더불어 점차 글로벌화되어 가고 있는 IT 환경에서 오픈소스 활동을 하거나, 해외 개발자와 협업하기 위해서도 영어는
반드시 필요합니다. 이번 글에서는 개발자 영어와 관련해서 기본적으로 알아야 하는 영어 시제를 살펴보고, 각 시제가 실제 개발 업무에서는 어떻게
활용되는지 정리해 보았습니다.

곰씨네 IT 블로그

IT서비스


[SI에서 성장하기] ④ 24년 차 대기업 개발자 출신이 말하는 요즘 SI 현장의 변화와 과제

13분
|
2024.04.16.
|
인기

의학의 발전과 인큐베이터의 발명 등으로 신생아의 생존율이 높아진 것처럼, SI산업 또한 SaaS 전환, Agile 도입 등 많은 변화가
있었습니다. 물론, 아직도 수시로 바뀌는 요구사항, 억지 요구로 가득찬 계약을 강요하는 고객, 심각한 인력 수급 문제까지 넘어야 할 산도 많기도
합니다. 오늘은 SI의 음침한 구석이 아니라, 이렇게 좋게 하고 있는 곳도 있다던데, 이건 어때, 모두 이렇게 일하게 되면 얼마나 좋을까 하는
이야기를 같이 나눠보시죠.

조남호

개발


팀장님에게 칭찬받기 좋은 GIT 꿀팁 2가지

9분
|
2024.04.16.
|
인기

여러 사람과 함께 작업하다 보면 프로젝트에는 다양한 커밋이 등록됩니다. 곧 PR(Pull Request)을 통해 이러한 커밋들이 하나의 브랜치로
합쳐지죠. 다만 많은 사람이 저장소 하나를 공유하면 어떤 브랜치 전략을 사용하든 종종 충돌이 발생하고는 합니다. 깃 작업을 하다 일어난 충돌을
쉽사리 해결하지 못해 시간을 많이 쓴 경험, 누구나 한 번쯤은 있을 겁니다. 오늘은 그런 여러분을 위해 알아두면 유용한 팁 두 가지를 공유하고자
합니다.

Moon



좋아요

11



댓글

5

스크랩



공유



스크랩

스크랩됨



공유



트위터

네이버

URL

페이스북

링크드인



지금 회원가입하고,
요즘IT가 PICK한 뉴스레터를 받아보세요!

회원가입하기
요즘IT의 멤버가 되어주세요! 요즘IT의 멤버가 되어주세요!
요즘IT의 멤버가 되어주세요!
모든 콘텐츠를 편하게 보고 스크랩해요.
모든 콘텐츠를 편하게 보고 스크랩 하기
매주 PICK한 콘텐츠를 뉴스레터로 받아요.
매주 PICK한 콘텐츠를 뉴스레터로 받기
로그인하고 무료로 사용하기
서비스 전체보기
위시켓 요즘IT


고객 문의

02-6925-4867
10:00-18:00
주말·공휴일 제외

yozm_help@wishket.com

요즘IT

요즘IT 소개 작가 지원

기타 문의

콘텐츠 제안하기 광고 상품 보기
요즘IT 슬랙봇 크롬 확장 프로그램
이용약관

개인정보 처리방침

청소년보호정책
㈜위시켓

대표이사 : 박우범

서울특별시 강남구 테헤란로 211 한국고등교육재단빌딩 3층 ㈜위시켓
사업자등록번호 : 209-81-57303

통신판매업신고 : 제2018-서울강남-02337 호

직업정보제공사업 신고번호 : J1200020180019
제호 : 요즘IT

대표·발행인 : 박우범

편집인 : 노희선

인터넷신문등록번호 : 서울,아54129

등록일 : 2022년 01월 23일

발행일 : 2021년 01월 10일
© 2013 Wishket Corp.
서비스 전체보기
위시켓
요즘IT

고객 문의

02-6925-4867
10:00-18:00
주말·공휴일 제외

yozm_help@wishket.com
이용약관

개인정보 처리방침

청소년보호정책
㈜위시켓

대표이사 : 박우범
서울특별시 강남구 테헤란로 211 3층 ㈜위시켓
사업자등록번호 : 209-81-57303
통신판매업신고 : 제2018-서울강남-02337 호
직업정보제공사업 신고번호 : J1200020180019
제호 : 요즘IT

대표·발행인 : 박우범

편집인 : 노희선
인터넷신문등록번호 : 서울,아54129
등록일 : 2022년 01월 23일

발행일 : 2021년 01월 10일
© 2013 Wishket Corp.

스크랩북 만들기
이름
이미 사용 중인 스크랩북 이름입니다.
닫기만들기

이미 사용 중인 스크랩북 이름입니다.
다른 이름을 지정해 주세요.
취소확인

닫기취소하기


형광펜 삭제하기
형광펜과 메모가 함께 삭제됩니다.
삭제하시겠습니까?
취소삭제하기

취소저장
메모하기


취소저장
형광펜 공유

트위터



페이스북



링크드인