들어가며
오프라인 컨퍼런스의 활기는 언제나 반갑다. 돈도 내고 내 개인정보도 팔아야 했지만 부스들을 돌며 굿즈를 많이 받아서 신난다. 추첨을 통해 참가자 수를 제한했는데도 사람이 어마어마하게 많았다.
모든 발표자들이 발표를 군더더기 없이 깔끔한 전달력으로, 그리고 전반적으로 시간에 맞게 잘 진행했다는게 인상깊었다. (발표 능력이 다들 좋으신 건지 아니면 인프콘 측에서 사전 특훈을 시킨 건지 궁금했다.)
당신의 웹페이지는 몇 점 인가요?: 라이트 하우스를 통한 프런트 성능개선
웹성능 개선을 (1) 리소스를 빨리 받는 로딩 성능, (2) 받은 리소스를 빨리 그리는 렌더링 성능, 그리고 실제 성능은 아니지만 (3) 서비스에서 느껴지는 사용자 경험이라는 세 가지로 분류하고, 각각의 성능지표를 확인하고 개선하는 방법을 공유하는 발표였다.
세션 내용 요약
- 로딩 성능은 개발자 도구의 Network 탭에서 바 형태로 Performance Navigation Timing 을 확인할 수 있다. Resource Timing
- 네트워크 이슈는 리다이렉트 방지, 캐시 적용 등으로 개선 가능
- 리소스는 압축하거나 이미지 최적화 등으로 개선 가능
- 렌더링 성능은 FCP(First Contentful Paint)나 LCP(Largest Contentful Paint) 등을 Performance 탭에서 확인할 수 있다.
- FP(First Paint): 첫 픽셀이 찍히는 시점이자 렌더링의 시작
- FCP(First Contentful Paint): 첫 컨텐츠
- LCP(Largest Contentful Paint): 가장 큰 컨텐츠
- DCL(Document Content Loaded): 문서 로드 완료 *DOM 접근은 DCL 후에만 가능
- 렌더트리를 형성하는 각 부분을 확인하여 JS를 잘 쓰기만 해도 파싱 과정의 횟수를 줄일 수 있다. 예컨대 아래 세 과정 중 단계 하나가 빠진다면 그만큼 빨라진다는 것이므로 layout이나 paint 단계를 생략하는 스타일 속성을 사용하여 성능을 개선할 수 있다.
- Layout: 어느 위치에 어느 정도 크기로 그려야 하는지 계산
- Paint: 색상이나 그림자 효과 등을 위해 픽셀을 채움
- Composite: 레이아웃 등을 합성(브라우저마다 다른 로직)
- 사용자 경험 개선
- Core Web Vitals: 아래 세 개의 핵심 요소를 통해 사용자 경험을 측정
- LCP(Largest Contentful Paint): 빠른 로딩
- FID(First Input Delay): 빠른 상호작용
*Lighthouse에서는 FID 대신 TBT(Total Blocking Time)으로 측정 - CLS(Cumulative Layout Shift): 시각적 안정성
- Core Web Vitals: 아래 세 개의 핵심 요소를 통해 사용자 경험을 측정
- Lighthouse는 로딩성능, 렌더링성능, 사용자 경험을 평가하는 다섯가지 지표로 성능 점수를 매기고, 어떤 부분을 개선할지 제안해준다.
- FCP
- Speed Index: 컨텐츠가 채워지는 속도 (더 큰 범위를 먼저 채울 때 더 빠르다고 측정)
- LCP
- TBT (FCP와 TTI 사이의 시간) *TTI(Time To Interactive): 메인스레드를 독점하는 50ms 이상의 JS 작업을 지칭하는 long task가 끝난 후, 사용자의 상호작용이 안정적으로 응답할 수 있는 시간
- CLS: 화면의 특정 영역이 움직이는지, 사용자 입력 기준 500ms 이상 지난 후 움직임을 측정
- 결론: 서비스가 빨라지면 사용자 이탈을 막고 사용자 경험을 개선할 수 있으니 Lighthouse를 잘 활용하자!
오늘도 여러분의 API는 안녕하신가요?: API First Design과 CodeGen 활용하기
API 관련 겪는 어려움들을 말끔히 해결해줄 API first design이 소개되었는데, GraphQL로 일하고 있는 입장이라 그런지 문제 및 어려움에 공감을 많이는 못했다. 역시 GraphQL이 짱인가..? 그래도 재미있는 발표였다.
세션 내용 요약
- API에 대해 우리가 겪는 문제
- 일관성 없는 API 설계 문서 (관리 비용 증가)
- API 설계 문서와 최종본, 두 벌의 문서
- 변경사항이 최신화되지 않는 문서
- 같은 기능을 하는 API가 중복되는 문제
- 같은 기능을 의미하는 서로 다른 용어 사용으로 커뮤니케이션 비용 발생
- Open API Specification(OAS)
- API First Design: 단순히 데이터를 전달하기 위한 수단이 아니라, 위반해서는 안되는 계약으로써 API를 대하는 자세
- 절차
- BE와 FE가 함께 Open API 명세서 설계
- 반복적인 설계 공유 및 토론
- Open API 도구를 활용하여 구현 (API 문서를 자동으로 만들어주는 도구, 코드를 생성해주는 code generator, 실제 API서버와 비슷하게 동작하게끔 하는 mock server, API gateway 등)
- 완성된 API 문서를 FE에 전달
- c.f. 기존 프로세스는 구현을 먼저 하고 문서를 전달 (code first)
- 장점
- 일관된 품질의 API 문서 유지
- 처음에 설계한 API 계약서가 곧 API 문서
- Open API 계약서를 먼저 수정하고 구현이 변경되므로, 업데이트를 따로 할 필요 없음
- API 명세서 설계에 중점을 두기 때문에 메시지 타입이나 문서 형식, 용어 등이 일원화
- 더 잘 활용하기 위해서는
- API 변경시 버전히스토리를 관리 (명세서의 info 섹션에 version 표기)
- 공통 API 문서로 타 서비스 개발자들까지도 협업이 가능 (Single Source of Truth)
- 이해관계자들과 함께 풍성한 내용이 담긴 API를 빠르게 설계하고, 같은 맥락에서 공감대 형성
안타깝게도 오늘의 TDD는 실패한 것 같군요. 내일은 가능할지도…?
문제를 해결하는 방식의 발표였는데 개인적으로는 새로운 관점을 제시해준다는 점에서 가장 inspiring한 발표였다. 내가 마주한 문제를 이미 해결한 것처럼 생각해보고, 해결되려면 무엇이 필요한지 작게 나누어 생각하며 풀어나가는 방식을 소개해주었다. 꼭 프로그래밍 뿐 아니라 삶을 살아갈 때도 적용가능한 것이 아닐까?
세션 내용 요약
- 우리는 얼렁뚱땅 문제를 해결하고, 왜 성공했는지는 알아보지 않는다.
- 문제는 바라는 것과 인식하는 것의 차이, 해결은 바라는 것과 인식하는 것을 일치시키는 것
- 문제를 많이 풀어보아야 해결할 때 유리하지만, 체계적으로 많이 풀어보아야 한다.
- 거꾸로 연구하기
- 요구하고 있는 것으로부터 이미 원하는 결과를 찾은 것처럼 가정
- 어떤 전제가 이 가정을 가능하게 하는지 생각
- 한 번에 해결하려 하지 말고 작게 나누어 작은 문제에 집중
- 실패하는 테스트를 작성하고, 정답을 하드코딩 하는 등 일단 테스트부터 통과시킨다
- TDD를 배워야 하는 이유 - 배움의 즐거움 그 자체 - 패턴을 알면 또다른 패턴을 발견할 수 있다.
Hello, Interactive Developer: WebGL로 아트코딩 하기
Interactive Developer 라는 생소한 개념, 그리고 웹 화면에서 예술을 그려낼 수 있는 WebGL과 ThreeJS를 소개하는 발표였다. ‘아름다움을 코딩’하고, ‘아트워크’를 만든다는 발표 소개와 같이 예술적인 요소들을 잔뜩 볼 수 있어서 눈이 즐거웠다. 새로운 기술을 접하는 것도 신기했지만, 기술을 통해 작품을 만들어낸다는 것이 무엇인지 직접 본 것 같아서 재밌었다.
세션 내용 요약
- 창의적이고 예술적인 사이트를 개발하는 Technical Artist, Creative Developer 등에서, 최근에는 인터랙션을 기반으로 예술적인 사이트를 개발하는 Interactive Developer이라는 직군이 생겼다.
- 구글 Creative Lab 에서 이런 작품들을 볼 수 있다.
- WebGL: 표준 컴퓨터 그래픽스 기술을 웹에서 사용할 수 있도록 하는 기술
- 그래픽스 표준 API를 개발하고 관리하는 OpenGL(Open Graphics Library)의 API 중, OpenGL ES라는 범위를 웹에서 사용할 수 있도록 하는 것
- 사용 방법
- Canvas API로 WebGL Context를 가져온다 (canvas 태그를 querySelector로 가져올 수 있음)
- 정점 셰이더와 색상 셰이더 코드를 작성해 WebGL Context로 전달한다
- 셰이더(Shader): 그림 그릴 때 색의 농도, 색조, 명암효과 등을 주기 위해 사용하는 함수
- 정점 셰이더(vertex shader): 클립 공간의 좌표를 생성하여 rasterize라는 과정을 실행
- 색상 셰이더(fragment shader): rasterize된 영역 안의 각 픽셀에 색상을 지정
- WebGL 라이브러리
- PixiJS, Three.js, Babylon.js 등이 있는데, 그 중 Three.js가 가장 보편적이라서 커뮤니티가 활성화 되어있다.
- Three.js 사용법: 카메라 인스턴스, 장면 인스턴스, 물체 인스턴스를 생성하여 렌더함수에 넘긴다
- 중요한 것은 아이디어와 창작하고자 하는 마음이라는 브루노 사이먼의 말이 와닿았다.
점진적 추상화
추상화에 고려해야 할 방향, 범위, 시기를 통해, 끊임없이 바뀌는 요구사항 속에서 점진적으로 추상화를 해야 할 필요를 실제 예시코드로 설명해주는 발표였다. 추상화를 어떻게, 어느 수준까지 해야하는지는 모든 개발자의 고민일텐데, 나름의 명쾌한 기준을 제공하는 좋은 발표였다.
세션 내용 요약
- OCP(Open-Closed Principle): 확장에는 열려 있고, 수정에는 닫혀 있어야 한다는 원칙. 확장에 열려 있는 것은 좋지만, 인터페이스 자체를 변경한다면 하위 구현체가 모두 영향 받을 수 있다.
- 추상화 방향
- 타입이 확장되는 방향인지, 행위가 확장되는 방향인지, 또는 그 외의 수많은 축의 방향일지 예측하기란 쉽지 않다.
- 소프트웨어 발전 방향과 일치하지 않는 추상화는 유지보수가 어렵다.
- 추상화 범위
- 코어 로직만 추상화하는 것이 더 좋다.
- 너무 넓은 범위를 추상화하는 것은 곧 인터페이스 변경 위험에 더 많이 노출된다는 것
- 인터페이스 추상화는 필요한 만큼만!
- 추상화 시기
- 개발 초기단계의 추상화는 나중엔 더이상 유효하지 않을 수 있다.
- 처음부터 인터페이스를 추출하기보다는 함수로 잘 분류해두는 것이 중요
- 좋은 추상화는 더 많은 맥락 속에서 이루어진다.
- 결론: 당장 시그니처가 비슷하다고 해서 섣불리 잘못된 추상화를 해버리면, 혜택 없이 비용만 증가할 수 있다. 점진적인 추상화를 하자!
함수형 프로그래밍 3대장 경험기: 클로저, 스칼라, 하스켈
최근 함수형 프로그래밍에 대한 스터디를 했어서 그래도 수월하게 공감과 이해를 하면서 들을 수 있었다. 우연치않게 함수형 프로그래밍을 실무에서 사용하는 발표자의 생생한 후기를 들을 수 있어서 좋았다. 또한 편리하다거나 안전하다는 프로그래밍적인 이유보다도, (맑은 미소와 함께) 함수형 프로그래밍은 짜릿하고 즐겁기 때문에 해봐야 한다고 하신 것이 기억에 남는다.
세션 내용 요약
- 함수형 프로그래밍
- 숫자나 문자열처럼 평범한 값으로 함수를 다루며, 이를 위해 부수효과를 최소화하거나 분리
- 불변 영속 자료구조: 불변하므로 lock을 걸지 않고도 여러 스레드가 공유하더라도 안전하게 읽을 수 있다. 불변 특성 상 메모리나 시간복잡도 페널티가 생길텐데, 이를 비교적 효율적으로 접근할 수 있게끔 메모리를 재활용하는 영속 자료구조를 사용한다.
- Single Linked List: 재귀적 연산을 많이 하는 함수형 프로그래밍에 어울리는 재귀적인 자료구조
- 참조투명성(Referential Transparency): 시점, 문맥에 상관 없이 어떤 식을 고정된 값으로 평가하며, 이는 등식 추론이 가능해지므로 source code가 모든 경우에 대해 문제 없이 동작할 것이 증명까지 된다. 생명을 다루거나 로켓을 쏘는 등 중요한 분야에서는 이런 전체 경우에 대한 안전성이 증명되는 것이 중요
- Clojure
- 현대판 LISP으로, 2007년에 공개
- JVM에서 동작하는 동적 타입 언어
- 중위 연산자가 없으며, 연산 우선순위는 무조건 순서에 따른다
- Scala
- 2004년 공개, 함수형 언어에서는 빌트인 자료구조인 불변영속 자료구조를 적극 활용
- 객체 지향 환경에서 함수형 프로그래밍을 도입하기에 좋은, 객체지향 + 함수형 언어
- Haskell
- Monad로 부수효과를 다루며, 모나드를 통해서만 할 수 있다.
- 함수형 프로그래밍 학계의 사실상 표준과도 같은, 이론적 기반이 되는 언어
- 별도 가상기계 없이 네이티브로 컴파일 되므로 잘 갖춰진 JVM 생태계의 이점을 누리기는 어렵다.
SSR의 기쁨과 슬픔: 렌더링의 변화의 흐름을 통해 알아보는 SSR과 Streaming SSR
실무에서 Streaming SSR을 사용하게 된 개발자의 기쁨과 슬픔을 고스란히 전달해준 발표. 한창 면접준비할 때 열심히 공부했던 CSR, SSR을 다시 딥다이브 할 수 있어서 좋았다. 발표자가 인디밴드 활동도 하고 있다고 해서 신기했다.
세션 내용 요약
- Rendering 방식은, 화면을 그리기 위해 HTML string을 생성하는 주체가 누구인지에 대한 차이
- Static Website: 전통적인 정적 페이지 HTML 서빙
- Common Gateway Interface: 정적 HTML 제공 한계를 탈피하기 위해 사용
- Server-Side Template: 웹서버가 없어도 Server application에서 HTML을 생성하고, 브라우저 렌더링 이후에는 JavaScript로 인터랙트 제어. 그러나 UI가 복잡한 경우, 화면을 그리는 동일한 코드가 서버와 클라이언트에 둘 다 있고 (e.g. 더보기, 무한스크롤 등으로 새로 그릴 때) + 렌더링 시점이 뒤섞이며 작업자의 고통이 증가 + 서버 API나 DB Query 시간이 오래걸리면 FID 나빠짐
- CSR: HTML, CSS, JS를 Static과 비슷하게 보내주되, 나머지 뷰 로직은 모두 클라이언트에서 수행하고 서버에서는 API로만 통신. 별도의 Application server 없이 CDN으로 배포. 그러나 고정된 index.html을 가지므로 봇에게는 모든 페이지가 다 같은 메타정보를 가진 것으로 인식되며, 초기 JS 실행되기까지 느리게 느껴진다. 메모리 누수에도 취약한데, 이는 페이지를 이동할 때마다 실제로는 새로운 페이지로 가는 게 아니라 body에만 새로운 뷰를 그리는 것이므로 메모리가 리셋되지 않기 때문.
- SSR: Node.js의 발전으로 등장했으며, 클라이언트와 서버가 같은 언어로 렌더링할 수 있다는 점이 Server-Side Template과 다르다. 대부분의 뷰 로직을 클라이언트와 서버가 공유. 그러나 더이상 Serverless가 아니므로 트래픽이 몰리는 등의 경우에 서버 관리가 필요하며, 빌드와 배포 시간이 CSR 대비 늘어나고 세팅이 복잡하다. (Next.js, Remix, vite-plugin-ssr 등으로 쉽게 할 수 있으나 직접 하는 바람에 발표자는 피를 보았다)
- Streaming SSR: 그릴 수 있는 부분은 먼저 그리고, 나머지는 점진적으로 렌더링. Suspense를 기준으로 데이터페칭을 안하는 바깥 부분(Shell)은 API를 호출하지 않으니 먼저 렌더링하고, onShellReady 호출 후 API 호출부가 렌더링된다.
- 결론: 서버와 인프라에 대한 지식이 없으면 SSR을 하기는 쉽지 않다. 그럼에도 불구하고 해볼 만 한 작업이다.
나가며
역시 컨퍼런스는 재미있었다. 언어 및 기술스택 불문 광범위한 주제를 모두 아우르다보니 소개 수준의 기본적인 내용들이라 내 입장에선 어렵지 않아서 좋았다. 근데 연차가 좀 쌓이면 파이콘 같은 특정 언어 컨퍼런스가 더 재미있을 수도 있겠다는 생각이 들었다(그러나 이렇게 말하니까 시니어도 쉬운 게 좋다고 한다ㅎ).
+아무리 좋았어도 공휴일 컨퍼런스는 힘들고 피곤하다. 개발자의 복지와도 같은 평일 컨퍼런스를 보장하라…