Upgrade to Pro — share decks privately, control downloads, hide ads and more …

광고 웹 SDK 개편기 with Preact

kakao
PRO
December 08, 2022

광고 웹 SDK 개편기 with Preact

#리팩토링 #Preact

광고 웹 SDK(AdFit Web SDK)는 AdFit 플랫폼을 이용하여 광고를 게재하고 수익을 창출하기 위해 웹사이트 등에서 사용하는 라이브러리입니다.
기존 프로젝트의 문제점을 분석하고 개선하고자 개편을 진행하였고 그 과정에서 얻은 소중한 경험들을 공유하려 합니다.
그리고 React의 이웃사촌, Preact를 소개하고 광고 SDK에 어떻게 도입하고 활용했는지도 이야기하고자 합니다.

발표자 : jake.baek
카카오 FE플랫폼팀의 비즈FE파트에서 광고 SDK를 개발하고 있는 제이크입니다.

kakao
PRO

December 08, 2022
Tweet

More Decks by kakao

Other Decks in Programming

Transcript

  1. 백종현 Jake.Baek


    카카오
    Copyright 2022. Kakao Corp. All rights reserved. Redistribution or public display is not permitted without written permission from Kakao.
    광고 웹 SDK 개편기


    with Preact
    if(kakao)2022

    View Slide

  2. 광고 웹 SDK 소개


    개편 목표


    개편 톺아보기


    Preact 도입


    개편 그 이후

    View Slide

  3. 광고 웹 SDK 소개


    개편 목표


    개편 톺아보기


    Preact 도입


    개편 그 이후

    View Slide

  4. 광고 웹 SDK
    쇼핑몰이나 블로그와 같은 매체에 광고를 게재하고 수익을 창출하기 위해 제공되는 웹 스크립트
    AdFit SDK

    View Slide

  5. View Slide

  6. 광고 단위란?
    광고가 실제로 노출될 서비스 상의 광고 영역
    광고 단위 = 광고 영역

    View Slide



  7. class="kakao_ad_area"


    style="display:none;width:100%;"


    data-ad-unit="ҟҊױਤID"


    data-ad-width="ҟҊױਤ о۽ ࢎ੉ૉ"


    data-ad-height="ҟҊױਤ ࣁ۽ ࢎ੉ૉ">




    async


    type="text/javascript"


    src="//t1.daumcdn.net/kas/static/ba.min.js">


    View Slide

  8. 광고 서버
    광고 웹 SDK
    광고 단위
    광고 소재
    광고 요청/응답 과정

    View Slide

  9. 광고 소재란?
    광고 영역에 보여줄 이미지나 텍스트 또는 동영상 등
    의 콘텐츠
    소재 이미지
    소재 텍스트

    View Slide










  10. ݫੋ ࢲ࠺झ








    ҟҊܳ ಿ਷ ࢲ࠺झ











    ҟҊ ࣗ੤











    ৢੋਗ ޖܐ ഈসో ଻օస


    ...












    서비스에 노출된 소재 코드

    View Slide










  11. ݫੋ ࢲ࠺झ








    ҟҊܳ ಿ਷ ࢲ࠺झ

















    ҟҊ ࣗ੤











    ৢੋਗ ޖܐ ഈসో ଻օస


    ...






    iframe으로 격리된 소재 코드

    View Slide



  12. class="kakao_ad_area"


    style="display:none;width:100%;"


    data-ad-unit="ҟҊױਤID"


    data-ad-width="ҟҊױਤ о۽ ࢎ੉ૉ"


    data-ad-height="ҟҊױਤ ࣁ۽ ࢎ੉ૉ">




    async


    type="text/javascript"


    src="//t1.daumcdn.net/kas/static/ba.min.js">
    script>
    광고 소재
    광고 웹 SDK
    광고 단위
    광고 서버

    View Slide

  13. 광고 소재 렌더링 광고 지표 수집 어뷰징 방지

    View Slide

  14. Since 2013
    광고 웹 SDK의 기나긴 역사...

    View Slide

  15. 광고 웹 SDK 소개


    개편 목표


    개편 톺아보기


    Preact 도입


    개편 그 이후

    View Slide

  16. SDK 프로젝트의 통합


    테스트 강화


    최신 기술의 도입
    변경에 유연하고 이해하기 쉬운 코드
    개편 목표

    View Slide

  17. 하나의 모듈에 연관된 많은 기능들
    하나의 모듈

    View Slide

  18. 하나의 모듈에 연관된 많은 기능들
    하나의 모듈
    광고 렌더링
    모바일 대응
    지표 수집
    ...

    View Slide

  19. SOLID Principles

    View Slide

  20. SRP
    단일 책임 원칙
    OCP
    개방-폐쇄 원칙
    LSP
    리스코프 치환 원칙
    ISP
    인터페이스 분리 원칙
    DIP
    의존성 역전 원칙
    SOLID Principles

    View Slide

  21. 변경에 유연하고 이해하기 쉬운 코드


    테스트 강화


    최신 기술의 도입
    SDK 프로젝트의 통합
    개편 목표

    View Slide

  22. 공개 SDK
    비공개 SDK
    비공개 SDK 프로젝트 공개 SDK 프로젝트

    View Slide

  23. 공개 SDK
    비공개 SDK
    공통 코드 공통 코드
    비공개 SDK 프로젝트 공개 SDK 프로젝트

    View Slide

  24. 공개 SDK
    비공개 SDK
    공통 코드
    통합된 개편 SDK 프로젝트

    View Slide

  25. 변경에 유연하고 이해하기 쉬운 코드


    SDK 프로젝트의 통합


    최신 기술의 도입
    테스트 강화
    개편 목표

    View Slide

  26. Unit E2E
    커버리지 90% 이상 다양한 브라우저 대응

    View Slide

  27. 변경에 유연하고 이해하기 쉬운 코드


    SDK 프로젝트의 통합


    테스트 강화


    최신 기술의 도입
    개편 목표

    View Slide

  28. Typescript


    +


    Preact

    View Slide

  29. 광고 웹 SDK 소개


    개편 목표


    개편 톺아보기


    Preact 도입


    개편 그 이후

    View Slide

  30. 의존관계에 따른 계층 구조


    렌더링 프로세스


    SDK 프로젝트의 통합


    Unit Test
    단일 책임 원칙에 충실한 광고 도메인 모델
    개편 톺아보기

    View Slide

  31. 광고 소재


    데이터
    광고 단위


    데이터
    광고 요청
    광고 객체
    ?
    ?
    ?
    class
    하나의 객체에 모든 기능을 담게 된다면?

    View Slide

  32. 광고 렌더링
    ?
    광고 지표 수집
    ?
    광고 검증
    ?
    광고 소재


    데이터
    광고 단위


    데이터
    광고 요청
    광고 객체
    ?
    ?
    ?
    class
    하나의 객체에 모든 기능을 담게 된다면?

    View Slide

  33. 광고 요소 광고 단위
    광고 렌더링
    광고 서버
    광고 소재
    광고 상태 관리
    광고 업무 용어를 기준으로 한 도메인 모델 분리

    View Slide

  34. 단일 책임 원칙에 충실한 광고 도메인 모델


    렌더링 프로세스


    SDK 프로젝트의 통합


    Unit Test
    의존관계에 따른 계층 구조
    개편 톺아보기

    View Slide

  35. 의존 관계에 따른 계층 구조
    저수준 모듈

    View Slide

  36. 고수준 모듈
    의존 관계에 따른 계층 구조
    저수준 모듈

    View Slide

  37. 고수준 모듈
    의존 관계에 따른 계층 구조
    저수준 모듈
    개방-폐쇄 원칙(OCP)

    View Slide

  38. 광고 소재
    광고 렌더링
    광고 서버
    광고 단위
    광고 상태 관리
    변경이 의존 관계에 미치는 영향

    View Slide

  39. 광고 소재
    광고 렌더링
    광고 서버
    광고 단위
    광고 상태 관리
    광고 소재
    변경 발생!
    광고 렌더링
    광고 서버
    광고 상태 관리
    변경이 의존 관계에 미치는 영향

    View Slide

  40. 광고 소재 스토어
    abstract class
    광고 소재 스토어 추가

    View Slide

  41. 광고 소재
    abstract class
    생성
    광고 서버
    interface
    광고 응답
    광고 단위
    광고 소재 스토어 추가
    광고 소재 스토어
    abstract class

    View Slide

  42. Module1


    Interface
    Module2


    Interface
    Concrete


    Module1
    Concrete


    Module2
    의존성 역전 원칙(DIP)

    View Slide

  43. 의존성 역전 원칙의 적용
    광고 서버
    class
    광고 소재
    abstract class
    광고 소재 스토어
    abstract class
    광고 서버
    class

    View Slide

  44. 광고 서버
    class
    광고 소재
    abstract class
    광고 소재 스토어
    abstract class
    광고 서버 구현체
    SSP 광고 서버
    요청/응답
    광고 서버
    interface
    의존성 역전 원칙의 적용

    View Slide

  45. 단일 책임 원칙에 충실한 광고 도메인 모델


    의존관계에 따른 계층 구조


    SDK 프로젝트의 통합


    Unit Test
    렌더링 프로세스
    개편 톺아보기

    View Slide

  46. 하나의 광고 렌더링 함수
    소재 렌더링
    렌더링 검증
    지표 수집
    ...
    하나의 광고 렌더링 함수
    소재 렌더링
    렌더링 검증
    지표 수집
    ...
    광고 렌더링에 필요한 기능들

    View Slide

  47. 광고 렌더링에 필요한 기능들
    소재 렌더링 함수
    지표 수집 함수
    렌더링 검증 함수
    ...
    하나의 광고 렌더링 함수
    소재 렌더링
    렌더링 검증
    지표 수집
    ...

    View Slide

  48. 렌더러 함수와 렌더링 파이프라인
    렌더링 파이프라인
    렌더러 함수
    interface

    View Slide

  49. 렌더링 파이프라인
    렌더러 함수
    interface
    소재 렌더링 함수 렌더링 검증 함수 지표 수집 함수 ...
    렌더러 함수와 렌더링 파이프라인

    View Slide

  50. 단일 책임 원칙에 충실한 광고 도메인 모델


    의존관계에 따른 계층 구조


    렌더링 프로세스


    Unit Test
    SDK 프로젝트의 통합
    개편 톺아보기

    View Slide

  51. export default new ࠺ҕѐ_SDK(


    new ۪؊݂_౵੉೐ۄੋ([


    ࠺ҕѐ_ࣗ੤_۪؊݂_ೣࣻ,


    ࠺ҕѐ_۪؊݂_Ѩૐ_ೣࣻ,


    ࠺ҕѐ_૑಴_ࣻ૘_ೣࣻ,


    ...,


    ])


    );
    비공개 SDK 빌드 진입점
    export default new ҕѐ_SDK(


    new ۪؊݂_౵੉೐ۄੋ([


    ҕѐ_ࣗ੤_۪؊݂_ೣࣻ,


    ҕѐ_۪؊݂_Ѩૐ_ೣࣻ,


    ҕѐ_૑಴_ࣻ૘_ೣࣻ,


    ...,


    ])


    );
    공개 SDK 빌드 진입점

    View Slide

  52. 단일 책임 원칙에 충실한 광고 도메인 모델


    의존관계에 따른 계층 구조


    렌더링 프로세스


    SDK 프로젝트의 통합


    Unit Test
    개편 톺아보기

    View Slide

  53. 90%
    유닛 테스트 커버리지

    View Slide

  54. GitHub
    개발자
    Pull Request
    Jenkins
    테스트 성공/실패
    Webhook
    자동화된 유닛 테스트 커버리지 검사

    View Slide

  55. module.exports = {


    ...,


    // An object that configures minimum threshold enforcement for coverage results


    coverageThreshold: {


    "global": {


    branches: 90,


    functions: 90,


    lines: 90,


    statements: 90,


    },


    },


    ...


    };
    Jest의 커버리지 검사 설정

    View Slide

  56. 의존성있는 함수 foo 예제
    import {bar} from "./bar";


    export function foo() {


    const barResult = bar();


    return `if(kakao)${barResult}`;


    }

    View Slide

  57. 의존성있는 함수 foo의 테스트 코드 예제
    import {foo} from "./foo";


    test("foo", () => {


    jest.mock("./bar", () => ({


    bar: jest.fn(() => 2022),


    }));


    expect(foo()).toBe("if(kakao)2022");


    });

    View Slide

  58. 의존성 주입을 사용한 함수 foo 예제
    import {Baz} from "./Baz";


    export function foo(bar: Baz) {


    return () => {


    const barResult = bar();


    return `if(kakao)${barResult}`;


    };


    }

    View Slide

  59. 의존성 주입을 사용한 함수 foo의 테스트 코드 예제
    import {foo} from "./foo";


    test("foo", () => {


    const barMock = () => 2022;


    const fooWithBarMock = foo(barMock);


    expect(fooWithBarMock()).toBe("if(kakao)2022");


    });

    View Slide

  60. 광고 웹 SDK 소개


    개편 목표


    개편 톺아보기


    Preact 도입


    개편 그 이후

    View Slide

  61. const parent = document.createElement("div");


    const child = document.createElement("p");


    child.innerText = "Hello, World!";


    parent.appendChild(child);


    return parent;

    View Slide

  62. const parent = document.createElement("div");


    const child = document.createElement("p");


    child.innerText = "Hello, World!";


    parent.appendChild(child);


    return parent;
    return (





    Hello, World!





    );

    View Slide

  63. 리액트 컴포넌트를 사용한다면?

    View Slide

  64. - DOM 요소의 렌더링을 document.createElement 등으로 생성하거나 별도의 템플릿을 다룰 필요없이

    JSX 문법을 통해 간결한 표현이 가능해집니다.


    - 컴포넌트를 계층 구조로 나눠 복잡한 기능을 작은 컴포넌트로 분산시킬 수 있습니다.


    - 리액트 훅을 사용하면 컴포넌트 로직과 라이프사이클의 관리가 용이해집니다.


    - 리액트 컴포넌트에 익숙한 개발자가 많습니다.
    광고의 렌더링을 리액트 컴포넌트로 표현하면?

    View Slide

  65. SIZE
    “리액트를 쓰자니 빌드된 파일의 크기가 커질 것 같은데?”

    View Slide

  66. 3KB
    Preact 공식 홈페이지에서 소개하는 크기

    View Slide

  67. Preact 렌더러 함수 구현
    import {render} from "preact";


    export function preact_۪؊۞_ೣࣻ(ҟ
    Ҋࣗ੤) {


    render(




    creative={ҟҊࣗ੤}


    />,


    element


    );


    }

    View Slide

  68. Preact 렌더러 함수 구현
    import {render} from "preact";


    export function preact_۪؊۞_ೣࣻ(ҟ
    Ҋࣗ੤) {


    render(




    creative={ҟҊࣗ੤}


    />,


    element


    );


    }
    SDK 빌드 진입점
    export default new SDK(


    new ۪؊݂_౵੉೐ۄੋ([


    preact_۪؊۞_ೣࣻ,


    ۪؊݂_Ѩૐ_ೣࣻ,


    ૑಴_ࣻ૘_ೣࣻ,


    ...,


    ])


    );

    View Slide

  69. 구현 방법의 풍부함
    DOM 요소로 표현되네?
    컴포넌트 라이프사이클


    또는 상태 로직이 필요해!
    컴포넌트로 구현 안해도 되는


    독립적인 기능이야!

    View Slide

  70. Components
    구현 방법의 풍부함
    Hooks
    DOM 요소로 표현되네?
    컴포넌트 라이프사이클


    또는 상태 로직이 필요해!
    컴포넌트로 구현 안해도 되는


    독립적인 기능이야!
    Renderers

    View Slide

  71. 스토리북의 활용

    View Slide

  72. 개발 서버
    SDK가 실환경 테스트에서 겪는 어려움
    SDK 배포
    Jenkins

    View Slide

  73. - 컴포넌트를 독립적으로 테스트하며 개발할 수 있도록 도와주는 개발툴


    - React, Vue, Svelte부터 Preact까지 다양한 프레임워크 지원


    스토리북(Storybook)이란?

    View Slide

  74. View Slide

  75. View Slide

  76. View Slide

  77. View Slide

  78. View Slide

  79. 광고를 가리는 레이어입니다.


    이 레이어에 가려지게 되면 viewable은 발동되지 않
    아야 합니다.


    마우스로 드래그하여 레이어를 이동할 수 있습니다.

    View Slide

  80. 광고를 가리는 레이어입니다.


    이 레이어에 가려지게 되면 viewable은 발동되지 않
    아야 합니다.


    마우스로 드래그하여 레이어를 이동할 수 있습니다.

    View Slide

  81. 자동화 테스트
    무겁지만


    다양한


    브라우저 환경
    E2E Test 자동화 테스트
    실시간 개발
    Unit Test
    가벼운


    실제


    브라우저 환경
    Storybook
    실시간 개발

    View Slide

  82. 광고 웹 SDK 소개


    개편 목표


    개편 톺아보기


    Preact 도입


    개편 그 이후

    View Slide

  83. 순환 복잡도
    순환 복잡도(Cyclomatic Complexity)란


    코드의 분기로 인한 경로 개수를 측정해 복잡성을 나타내는 정량적 지표.


    1976년 맥카비(Thomas J. McCabe)에 의해 개발됨.
    function isOdd(value: number) {


    if (value % 2 === 1) {


    return true;


    }


    return false;


    }

    View Slide

  84. 순환 복잡도
    순환 복잡도(Cyclomatic Complexity)란


    코드의 분기로 인한 경로 개수를 측정해 복잡성을 나타내는 정량적 지표.


    1976년 맥카비(Thomas J. McCabe)에 의해 개발됨.
    function isOdd(value: number) {


    if (value % 2 === 1) {


    return true;


    }


    return false;


    }
    순환 복잡도 = P(분기 개수) + 1 = 1 + 1 = 2

    View Slide

  85. 순환 복잡도 비교
    0
    10
    20
    30
    40
    50
    렌더링 코드 메인 코드
    개편 전 개편 후

    View Slide

  86. 변경에 유연하고 이해하기 쉬운 코드


    SDK 프로젝트의 통합


    테스트 강화


    최신 기술의 도입
    마무리 정리

    View Slide

  87. 변경에 유연하고 이해하기 쉬운 코드


    SDK 프로젝트의 통합


    테스트 강화


    최신 기술의 도입
    마무리 정리

    View Slide

  88. 변경에 유연하고 이해하기 쉬운 코드


    SDK 프로젝트의 통합


    테스트 강화


    최신 기술의 도입
    마무리 정리

    View Slide

  89. 변경에 유연하고 이해하기 쉬운 코드


    SDK 프로젝트의 통합


    테스트 강화


    최신 기술의 도입
    마무리 정리

    View Slide

  90. 변경에 유연하고 이해하기 쉬운 코드


    SDK 프로젝트의 통합


    테스트 강화


    최신 기술의 도입
    마무리 정리

    View Slide

  91. 프레임워크의 사용이 SDK를 무겁게 하지 않을까요?
    필요하지 않은 기술의 남용은 아닐까요?

    View Slide

  92. E.O.D

    View Slide