본문 바로가기메뉴 바로가기


안녕하세요. 카카오엔터프라이즈 검색플랫폼프론트파트의 Lawrence.net입니다.

프론트엔드 개발 업무의 효율성을 높이기 위한 방법의 하나로 고민해 본 Mocking에 대해 설명하고 이를 적용했던 사례에 대해 공유하고자 합니다. 

먼저, 프론트엔드 개발 과정에서 프론트엔드 개발자들이 겪고 있는 문제점에 대해서 이야기하고, 이에 대한 해결 방안으로 Mocking을 어떻게 하면 더 효율적으로 사용할 수 있을지 고민했던 부분에 대해 공유드리려고 합니다. 이어서, Mocking을 효율적으로 사용하기 위해 도입한 MSW에 대해서 간략하게 소개한 다음, MSW의 사용 방법과 사용 사례를 소개하겠습니다. 


프론트엔드 개발 과정의 현실

먼저 프론트엔드 개발을 하면서 겪게 되는 불편한 점에 대해서 말씀을 드려 보겠습니다.

전체 개발 프로세스 중 요구 사항 분석 및 기획, 백엔드 개발, 프론트엔드 개발에 이르는 각각의 개발 과정은 크게 겹치지 않고 진행되는 것이 가장 이상적일 것입니다. 왜냐하면, 개발 과정에서 도출되는 요구 사항이나 사용 가능한 인터페이스에 변경이 있으면, 각 단계별 의존성에 따라 다시 작업해야 하는 경우가 발생하기 때문입니다.

따라서, 개발과정이 다음과 같이만 진행된다면 요구 사항과 제공된 스펙에 따라 순조롭게 프론트엔드 개발을 진행할 수 있습니다.

하지만 현실은, 많은 시간을 프론트엔드와 백엔드를 병행하여 개발하게 되는 경우가 많습니다.

이때 프론트엔드에서 백엔드의 API를 활용해야 하는 것처럼, 백엔드 개발에 종속적인 부분이 있다면, 해당 부분이 완성되기 전까지는 프론트엔드에서 개발을 진행할 수 없고, 그 부분이 진행된 후에나 개발이 가능합니다. 심지어 추가적인 수정사항이 발생했는데 백엔드 개발에 의존성이 있는 부분에 수정이 필요하다면, 이러한 비효율적인 과정을 반복 진행할 수밖에 없습니다.

프론트엔드 개발자라면 한 번쯤은 다음과 같은 경험을 해본 적이 있을 것입니다.

기획자 : XX 작업은 어떻게 진행 중인가요?
프론트엔드 개발자 : 그게… 아직 API가 준비되지 않아서 다음 주까지는 기다려야 합니다.

예상한 기간보다 API 개발에 시간이 더 필요해진 경우, 그 시간만큼 프론트엔드 개발자가 개발을 진행하지 못하는 상황이 생겨납니다.

안그래도 대부분의 프론트엔드 개발자들은 개발, 테스트, 디버깅, 요구사항 변경 등 업무를 진행하다 보면 개발 완성도를 높이는데 있어 항상 시간의 부족함을 느낍니다. 이에 더해, 프론트엔드 개발은 프로젝트 완성 단계의 엔드포인트에 가깝기 때문에 더더욱 시간의 압박을 많이 받을 수밖에 없습니다. 기간은 정해져 있고 상황은 촉박한데 API에 종속적인 개발이 많을수록, 개발 가능한 시간과 테스트에 쏟을 수 있는 시간은 줄어듭니다.

그동안은 이처럼 압박과 스트레스를 견디며 개발을 진행하는 일이 많았습니다. 그러다 보니 대기 시간을 줄이고 백엔드 개발과 최대한 병행해 개발을 진행하려면 어떻게 해야 할지를 고민하게 되었습니다.

그리고 목표를 다음과 같이 잡아 보았습니다. 

“API가 개발되기 전에 프론트엔드 개발을 마치자.”

생각해낸 방법은 바로  Mocking을 좀 더 활용하자!였습니다. 

Mocking하기

Mocking에 대하여

물론 기존에도 Mocking을 통해 사전 개발은 진행해 왔었습니다. 그동안 비슷한 상황에 놓여 어쩔 수 없이 Mocking을 통해 사전 개발을 진행했을 때의 상황을 재현해 보겠습니다.

먼저, 기획자가 요구 사항을 개발자에게 전달합니다. 이때, 백엔드와 종속적인 개발 영역이 있는 경우, 프론트엔드 개발자는 필요한 API의 스펙을 사전 협의하여 백엔드 개발자에게 받아야 합니다.

API 문서를 사전에 제공받은 경우, 사전 개발을 진행하게 되고 API를 통해 실제로 연동할 때까지 큰 변화 없이 개발을 진행할 수 있습니다. 

하지만, 때로는 아래 방식처럼 API 자체에 대한 의존성을 일단 가져가지 않고, Mocking을 통해 개발을 진행한 다음, 실제 사용해야 하는 API가 나온 시점에서 API의 실제 인터페이스에 맞게 컨버팅하는 과정을 따로 가지는 개발 방법으로 진행하기도 합니다.

기존 Mocking 진행 방법

기존에는 다음과 같이 Mocking을 진행했습니다.

먼저, 화면에 필요한 데이터의 상태를 애플리케이션의 내부 로직에 직접 Mocking 해서 필요한 화면에 붙이는 방식이 있습니다. 이렇게 작업하는 방식은 구현이 쉬워 빠르게 적용할 수 있다는 장점이 있습니다. 하지만 애플리케이션의 서비스 로직에 직접 Mocking을 해야 해 애플리케이션 서비스 로직을 수정해야 하고, HTTP 메소드와 네트워크의 응답 상태에 따라 각각 대응하기가 쉽지 않습니다.

반대로, Mock 서버를 별도로 만드는 방법도 있습니다. 이 방법은 웹 애플리케이션의 서비스 로직을 수정하지 않아도 된다는 장점이 있습니다. 하지만, 데이터 상태 구현에는 직접 Mocking 대비 비용 및 공수가 상당히 들어갑니다. 추가적으로 이를 로컬이 아닌 누군가에게 공유해야 한다면, Mock 서버를 원격으로 제공하기 위한 추가 환경 구성 작업 등에도 적지 않은 공수가 들어 효율적이지 않습니다.

이외에도 기존의 Mocking에는 또 다른 문제가 있습니다. 바로, 각 화면에 대한 테스팅 및 디버깅 시에 어려움이 발생한다는 것입니다.

결과물을 확인하고자 하는 인원이 담당 프론트엔드 개발자가 아니라면, 예를 들어 에러 화면을 보려고 해도 크롬 개발자 도구가 요청을 블록 처리할 가능성이 높아 특정 상태의 화면을 다른 사람들에게 공유하기가 어렵고, 실제 API 스펙처럼 발생하는 상황을 모의하기가 쉽지 않습니다.

또한, 대기, 로딩, 에러 등 API의 응답 상태에 따른 여러 가지 구현을 가지고 있을 경우도 있을 수 있습니다. 이 경우, 각 단위 개발은 어떻게 진행한다고 하더라도 실제 화면을 구성하기 위한 구현 단계에서는 각 케이스별로 임의의 상태를 만들어 보면서 개발하거나 그 자체를 디버깅하기에 어려움이 있습니다.

실제 API를 사용하는 것처럼 네트워크 수준에서 Mocking 하기

결국 지금 우리에게 필요한 Mocking 수준은, 실제 API를 사용하는 것처럼 네트워크 수준에서 Mocking 하는 것입니다. 이러한 생각을 바탕으로 조사하던 중에, 네트워크 요청 과정에서 Request에 대한 Mocking이 가능한 MSW를 찾아냈습니다.

MSW.js

지금부터는 MSW.js에 대해 소개해 보려고 합니다.

MSW(Mock Service Worker의 약자, https://mswjs.io)는 API Mocking 라이브러리로, 서버향의 네트워크 요청을 가로채서 모의 응답(Mocked response)을 보내주는 역할을 합니다. 따라서, Mock Service Worker(MSW) 라이브러리를 통하면, Mock 서버를 구축하지 않아도 API를 네트워크 수준에서 Mocking 할 수 있습니다. 

MSW를 통해 네트워크 Request에 대해 새로운 방식으로 Mocking이 가능해졌고, 색다른 개발 과정을 겪을 수 있게도 되었습니다.

MSW가 이러한 역할을 할 수 있는 이유는 Service Worker를 통해 HTTP 요청을 가로채기 때문입니다. MSW의 이름에도 포함되어 있는 Service Worker가 무엇인지부터 간략하게 소개하겠습니다.

Service Worker란?

Service Worker는 웹 애플리케이션의 메인 스레드와 분리된 별도의 백그라운드 스레드에서 실행시킬 수 있는 기술 중 하나입니다. Service Worker 덕분에 애플리케이션의 UI Block 없이 연산을 처리할 수 있습니다.

이러한 특징으로 인해, Service Worker는 다음과 같은 기능에 많이 사용되고 있습니다.

  • 먼저, 네트워크가 원활할 때 동기화를 시켜주는 백그라운드 동기화 기능이나, 높은 비용의 계산을 처리할 때 또는 푸시 이벤트를 생성할 때 주로 사용됩니다. 
  • 그리고, MSW의 동작 방식과 관계되어 있는, 네트워크 요청을 가로채는 행위도 수행할 수 있습니다. Service Worker가 애플리케이션과 서버 사이에서 Request를 가로채서 직접 Fetch에 대한 컨트롤도 할 수 있기 때문에 색다른 작업이 가능해집니다. 예를 들어, HTTP Request와 Response를 보고 캐싱 처리를 한다든지, 필요하다면 로깅을 한다든지 하는 여러 가지 새로운 동작을 만들어 낼 수 있습니다. MSW도 이 과정을 통해서 Request를 가로채서 Response를 Mocking 하는 원리를  사용합니다.

참고로, Service Worker의 사용이 제한되는 경우도 있습니다.

  • Service Worker는 대부분의 모던 브라우저에서 지원하고 있으나, IE와 같은 일부 브라우저에서는 지원하고 있지 않습니다.
  • 그 외에는, 기본적으로 localhost가 아닌 환경이라면 HTTPS 보안 프로토콜 환경이 필요합니다. Service Worker는 중간에서 네트워크로 연결을 가로채고 조작할 수 있는 강력한 기능을 갖고 있기 때문에, Service Worker에서는 HTTPS가 기본적으로 제공되는 환경에서만 사용할 수 있습니다.

즉, MSW는 Service Worker를 기반으로 모의 API를 만들어내기 때문에 다른 프론트엔드에서 사용하는 수많은 라이브러리나 프레임워크에 종속적이지 않고 호환성에 문제없이 동작합니다.

MSW 동작 원리

MSW가 어떻게 동작하는지 한번 확인해 보겠습니다.

먼저, 브라우저에 Service Worker를 설치합니다.

설치 이후부터는 브라우저에서 실제 이루어지는 요청을 Service Worker가 가로채게 됩니다.

Service Worker에서는 해당하는 실제 요청을 복사해서 MSW에게 해당 요청과 일치하는 모의 응답을 제공받고 이를 브라우저에게 그대로 전달하게 됩니다.

이러한 과정을 통해서, 실제 서버 존재 여부와 상관없이 실제 요청으로 이어지지 않고 예상할 수 있는 요청에 대해 Mocking이 가능해집니다. 이렇게 Mocking이 가능해지면 API가 아직 준비되지 않았어도 다음과 같은 개발 방식을 선택할 수 있습니다.

MSW를 활용한 개발 방식

기획자가 요구 사항을 전달하면, 프론트엔드 개발자와 백엔드 개발자가 API 스펙을 합의하고 백엔드 개발자는 프론트엔드 개발자에게 API의 스펙을 제공합니다. 그 이후, 프론트엔드 개발자는 MSW를 통해 네트워크 레벨에서의 Mocking을 진행한 후, 애플리케이션을 개발하게 됩니다.

API 없이도 프론트엔드 개발자는 높은 완성도를 갖고 있는 수준에서 기획자와 미리 프론트엔드 애플리케이션을 확인하며 피드백을 주고받고, 그 사이 백엔드 개발자는 API 개발을 진행합니다. 이후 백엔드 개발자가 API를 제공하면, 프론트엔드 개발자는 별다른 작업 없이 MSW를 스위치 오프만 하면 Production으로 배포할 수 있는 형태의 개발 과정을 통해 개발을 진행할 수 있습니다.

MSW는 디버깅이 필요한 상황에서도 좋은 시너지를 만들어 낼 수 있습니다.

예를 들어, 특정 API 응답을 기준으로 에러가 발생해 디버깅이 필요한 상황이라면, 기존 서비스 로직을 전혀 건드리지 않고 오로지 MSW에서 Mocking을 만들어 내서 쉽게 디버깅할 수 있습니다.

더 나아가, 이러한 장점은 기획자 등의 다른 누군가에게 각 화면을 공유하고 피드백을 받아야 하는 상황이 발생했을 때에도, 추가적으로 MSW에서 해당 상황을 만들어낼 수 있도록 작업을 해 둔다면 별다른 서비스 로직의 수정 없이도 MSW를 통해 제공이 가능해집니다.

MSW 사용 방법

얼마나 간단하게 MSW를 적용할 수 있는지도 중요할 것 같습니다. 간단하게 한번 살펴보겠습니다. 설치하게 될 프로젝트는 Create-React-App 기반으로 구성되어 있다고 전제합니다.

MSW 설치 및 구성

먼저 MSW 패키지를 설치합니다.

설치하고자 하는 프로젝트에 MSW를 세팅합니다. Service Worker를 제공하기 위해서 MSW는 전용 CLI를 제공하고 있습니다. 이 CLI의 Init 명령어와 함께 사용하고자 하는 프로젝트의 public directory를 지정해서 실행해 줍니다.

실행 후에는 다음과 같이 지정한 Public directory에 Service Worker를 위한 JS가 생성된 모습을 확인할 수 있습니다.

이제, Mocking할 API를 핸들링할 핸들러를 한번 만들어 보겠습니다. 

예시로는, API URL을 지정한 후, 상태 값은 200, 응답까지의 딜레이 시간은 4초, 응답 body 값으로는 이름(name)을 가지고 있는 배열 형태의 데이터를 한번 제공해 보겠습니다.

이렇게 간단하게 가로챈 네트워크의 요청에 대해서 모의 API를 생성할 수 있습니다.

다시, 모의 응답을 위한 핸들러를 MSW에서 사용할 수 있도록 주입(import) 합니다.

마지막으로, MSW를 실행시키기 위한 코드를 추가합니다. 노드 환경 변수에 따라 MSW를 사용하기 위한 분기를 포함해, 다음과 같이 작성해 보겠습니다.

MSW 동작 확인

MSW가 정상적으로 동작하는지 확인해 보겠습니다. 

fetch(‘/api/products’)

CRA를 로컬 환경에 띄우면, 기본적으로 MSW가 정상적으로 실행되어 있으면 Chrome의 개발자 도구 콘솔 화면에서 [MSW] Mocking enabled.라는 메시지를 확인할 수 있습니다.

이렇게, 설정해 둔 응답 값과 함께 HTTP 응답 코드도 200인 결과를 확인할 수 있고, 개발자 도구 내 네트워크 탭에서도 해당 요청이 Service Worker에서 응답이 온 것을 인지할 수 있습니다.

fetch(‘/api/products?error_code=400’)

이번에는 특정 상황에서 에러를 일으키도록 모의(Mocking)를 해보려고 합니다.

만약 URL에 쿼리 스트링으로 error_code라는 파라미터가 존재한다면, HTTP 응답 에러코드를 리턴하도록 코드를 작성해 보겠습니다.

마찬가지로, 다시 실제 웹 애플리케이션의 개발자 도구로 돌아가서 API를 설정해둔 조건에 맞게 에러 상태를 요청하면 개발자 도구에서 에러코드로 반환된 결과를 확인할 수 있으며, 네트워크 탭에서도 마찬가지로 Servie Worker에서 보낸 응답이라는 표시와 함께 에러코드를 확인할 수 있습니다.

MSW 적용 결과 

동작 확인을 통해, 큰 어려움이나 공수 없이 기존에 동작하던 프로젝트에도 MSW를 적용할 수 있음을 알 수 있었습니다.

MSW는 프로젝트 내에서 설치하는 형태이기 때문에, 기존에 프로젝트에서 사용하고 있는 로직을 재활용하여 핸들러를 만들어낼 수도 있습니다. 만약 Typescript를 사용하고 있다면, 모의 작성하는 핸들러 코드에도 같은 타입을 공유해서 만들 수 있다는 장점도 있습니다.

MSW 실사용 후기

신규 서비스 개발 시에도 MSW를 도입해 보았습니다.

앞서 말씀드린 상황처럼 API가 아직 준비되어 있지 않은 상태에서도 프론트엔드 개발을 빠르게 진행하고, 여유시간 동안에 개선사항에 대한 피드백을 받으며 개선 작업을 진행해 나갈 수 있음을 직접 경험할 수 있었습니다. 또한, 각기 다른 네트워크 응답 상태에 따른 화면의 변경사항을 좀더 쉽게 개발하고 쉽게 디버깅하고 자 하는 목표도 이룰 수 있었습니다. MSW 도입을 통해, 필요한 API가 아직 나오지 않았음에도 완성도 높은 산출물 상태에서, 화면을 협업 담당자에게 예시로도 제공할 수 있고, 추가 개발 또한 쉽게 바로 진행할 수 있게 되었습니다. 

다음에서는 실제 사례 중 일부에 대해서만 소개합니다.

MSW 도입을 위해 개발한 툴바의 형태 및 동작 방식

프론트엔드 애플리케이션에서 호출하고 있는 API를 MSW로 바로 컨트롤할 수 있는 툴바를 간단하게 만들어 보았습니다. 이 툴바는 MSW를 사용할 때만 import되어 동작을 돕도록 했습니다. 해당 툴바를 통해 리스트 화면이 에러 상태일 때는 어떻게 나타나고, delay를 준 상태에서는 어떤 화면이 나오는 지도 명확하게 확인할 수 있도록 했습니다.

응답에 대한 쉬운 조작이 가능해짐으로써, 네트워크 요청에서 문제가 발생했을 때, 특정 상황 재현을 위한 디버깅 또한 편해졌습니다.

이상으로, 프론트엔드 개발 시에 MSW 활용을 통해 얻을 수 있었던 효용에 대해 다음과 같이 정리하고, 본 글을 마치고자 합니다.

  • 낮은 진입장벽으로 빠른 적용이 가능
  • 별도의 환경 없이 네트워크 요청에 대한 모의 가능
  • API에 종속성 없이 완성도 높은 수준의 사전 개발 가능
  • 네트워크 상태에 따른 디버깅을 위해 활용 가능

감사합니다.

lawrence.net
lawrence.net 카카오엔터프라이즈 검색플랫폼프론트파트에서 검색 서비스 관련 프론트 개발을 담당하고있습니다.
Top Tag
2021
2021-new-krew
Ad Platform
Ad tech
adaptive-hash-index
adt
adtech
agile
agilecoach
ai
algorithm
Algorithm/ML
Algorithm/Ranking
almighty-data-transmitter
Analyzer
android
angular
anycast
App2App
applicative
Architecture
arena
ast
async
aurora
babel
babel7
Backend
BApp
bgp
big-data
binary
ble
blind-recruitment
block
Block Chain
blockchain
bluetooth
brian
business
Cache
cahtbot
canvasapi
Caver
cch
cd
CDR
ceph
certificate
certification
CF
cgroup
chrome
ci
cite
client
clojure
close-wait
cloud
cloudera-manager
clustered-block
cmux
cnn
code-festival
code-review
codereview
coding
coding test
Collaborative Filtering
competition
Compliance
component
conference
consul
container
contents
contest
contribution
cookie
core-js@3
Corporate Digital Responsibility
couchbase
COVID-19
cpp
Data
data-engineering
DB
deep-learning
Dependency
dependency-graph
desktop
dev
dev-session
dev-track
developer
developer relations
developers
devops
digitalization
digitaltransformation
dns
docker
dr
Electron
employeecard
emscripten
eslint
extract-text
Feature List
Featured
Feedback
friendstime
front-end
frontend
functional-programming
funfunday
fzf
garbage-collection
gawibawibo
GC
github
globalpollution
go
graphdb
graphql
Ground X
growth
ha
hadoop
hate speech
hbase
hbase-manager
hbase-region-inspector
hbase-snashot
hbase-table-stat
hbase-tools
hri
ICPC Sinchon
id
if kakao
ifkakao
infrastructure
innodb
internship
ios
item
Java
javascript
javascript web-assembly
JCMM
JIRA
jsconf
jsconfkorea
json
k8s
kafka
kakao
kakao-Career-Boost-Program
kakao-commerce
kakao-games
kakaoarena
kakaobrain
kakaocommerce
kakaocon
kakaoenterprise
kakaok
kakaokey
kakaokrew
kakaomap
kakaopage
kakaotalk
KAS
KCDC
khaiii
Klaytn
Klip
kubernetes
l3dsr
l4
License
links
Linux
load-balancing
MAB
Machine Learning
machine-learning
map
marathon
meetup
melon
mesos
message
Messaging
microservice
Microsoft TypeScript
mm
mobil
mocking
monad
monorepo
ms-office
MSA
mtre
mysql
mysql-realtime-traffic-emulator
nand-flash
network
new
new-krew
nfc
Nickface
nomad
ocp
olive
onboarding
open
open source
opensource
openstack
OpenWork
OSS
page
parallel
PBA
performance
planning poker
Platform
polyfill
programming-contest
project-structure
pycon
python
quagga
react
reactive-programming
reactor
recap
recommendation
recommendation system
recruitment
redis
redis-keys
redis-scan
related-blind
Renderer
rest
Rome
rubics
ruby
rxjs
s2graph
scala
scalaz
seminar
Serve
server
service
service worker
sharding
shopping
Shuffle Partition
socket
spark
spark-streaming
SpringBoot
ssd
Statistics/Analysis
Stomp
storage
storm
style-guide
summer internship
support
System
talk
talkchannel
tcp
tech
Techtalk
test
thread
Thread-Debugging
time-wait
tmux
Topic Modeling
typescript
Untact
update
User Story
vim
vim-github-dashboard
vim-plugin
vue
vue.js
WASM
web-cache
web-worker
webapp
webgl
WebSocket
webworkers
weekly
work
workplatform
개인화 추천
길찾기
라이선스
연관 추천
오픈소스
오픈소스검증
의존성분석
일하는방식
협업
All Tag
2021
2021-new-krew
Ad Platform
Ad tech
adaptive-hash-index
adt
adtech
agile
agilecoach
ai
algorithm
Algorithm/ML
Algorithm/Ranking
almighty-data-transmitter
Analyzer
android
angular
anycast
App2App
applicative
Architecture
arena
ast
async
aurora
babel
babel7
Backend
BApp
bgp
big-data
binary
ble
blind-recruitment
block
Block Chain
blockchain
bluetooth
brian
business
Cache
cahtbot
canvasapi
Caver
cch
cd
CDR
ceph
certificate
certification
CF
cgroup
chrome
ci
cite
client
clojure
close-wait
cloud
cloudera-manager
clustered-block
cmux
cnn
code-festival
code-review
codereview
coding
coding test
Collaborative Filtering
competition
Compliance
component
conference
consul
container
contents
contest
contribution
cookie
core-js@3
Corporate Digital Responsibility
couchbase
COVID-19
cpp
Data
data-engineering
DB
deep-learning
Dependency
dependency-graph
desktop
dev
dev-session
dev-track
developer
developer relations
developers
devops
digitalization
digitaltransformation
dns
docker
dr
Electron
employeecard
emscripten
eslint
extract-text
Feature List
Featured
Feedback
friendstime
front-end
frontend
functional-programming
funfunday
fzf
garbage-collection
gawibawibo
GC
github
globalpollution
go
graphdb
graphql
Ground X
growth
ha
hadoop
hate speech
hbase
hbase-manager
hbase-region-inspector
hbase-snashot
hbase-table-stat
hbase-tools
hri
ICPC Sinchon
id
if kakao
ifkakao
infrastructure
innodb
internship
ios
item
Java
javascript
javascript web-assembly
JCMM
JIRA
jsconf
jsconfkorea
json
k8s
kafka
kakao
kakao-Career-Boost-Program
kakao-commerce
kakao-games
kakaoarena
kakaobrain
kakaocommerce
kakaocon
kakaoenterprise
kakaok
kakaokey
kakaokrew
kakaomap
kakaopage
kakaotalk
KAS
KCDC
khaiii
Klaytn
Klip
kubernetes
l3dsr
l4
License
links
Linux
load-balancing
MAB
Machine Learning
machine-learning
map
marathon
meetup
melon
mesos
message
Messaging
microservice
Microsoft TypeScript
mm
mobil
mocking
monad
monorepo
ms-office
MSA
mtre
mysql
mysql-realtime-traffic-emulator
nand-flash
network
new
new-krew
nfc
Nickface
nomad
ocp
olive
onboarding
open
open source
opensource
openstack
OpenWork
OSS
page
parallel
PBA
performance
planning poker
Platform
polyfill
programming-contest
project-structure
pycon
python
quagga
react
reactive-programming
reactor
recap
recommendation
recommendation system
recruitment
redis
redis-keys
redis-scan
related-blind
Renderer
rest
Rome
rubics
ruby
rxjs
s2graph
scala
scalaz
seminar
Serve
server
service
service worker
sharding
shopping
Shuffle Partition
socket
spark
spark-streaming
SpringBoot
ssd
Statistics/Analysis
Stomp
storage
storm
style-guide
summer internship
support
System
talk
talkchannel
tcp
tech
Techtalk
test
thread
Thread-Debugging
time-wait
tmux
Topic Modeling
typescript
Untact
update
User Story
vim
vim-github-dashboard
vim-plugin
vue
vue.js
WASM
web-cache
web-worker
webapp
webgl
WebSocket
webworkers
weekly
work
workplatform
개인화 추천
길찾기
라이선스
연관 추천
오픈소스
오픈소스검증
의존성분석
일하는방식
협업

위로