Skip to content
:tech
← Articles

AI-translated. Read the original in KoreanEmbedded slides, videos and images remain in their original language.

How Buzzvil’s Frontend Evolved

Luke Hwang
Luke Hwang

Your Role Here

How Buzzvil’s Frontend Evolved

I'm Luke from the Product Growth team in Buzzvil's Supply group. I would like to share how our frontend architecture has changed over the past few years. From AngularJS through Vue and React to Next.js, this is an honest account of the questions and decisions behind each transition.

From AngularJS to Vue: a unified admin

Early on, Buzzvil operated two separate AngularJS admin applications: one for advertisers (Demand) and one for publishers (Supply). Because they were developed independently, basic capabilities such as campaign management and reporting were implemented twice. AngularJS 1.x's complex structure also made it increasingly difficult to respond to new requirements.

As technical debt accumulated, we decided to change frameworks and combine the two admin applications. We considered React, but this project was used by both frontend and backend developers. At the time, React relied on class components. Vue offered a gentler learning curve and a natural continuation of our template-based AngularJS experience.

The migration was not easy, but by removing duplicate code and modularizing shared functionality along the way, we cut the codebase in half. Development became noticeably faster. Most importantly, managing Demand and Supply capabilities in one unified admin allowed us to offer a consistent user experience.

Introducing a BFF: a backend for the frontend

Initially, to collaborate with server engineers, we added a Python Django layer on top of the Vue project and routed communication between frontend and backend through Django. This gave us a reliable connection to Buzzvil's backend servers.

However, Buzzvil had adopted a microservices architecture (MSA), so the frontend needed to communicate with many microservices rather than a single backend. Django was useful at first, but over time frontend developers had to maintain its Python code themselves. That meant taking on an unfamiliar backend stack, and the Django layer became one of the factors slowing development.

To address this, we introduced a Backend For Frontend (BFF) layer. We placed a Node.js Express server between Django and the frontend, allowing the frontend team to design APIs in the shape it needed. We could combine multiple Django APIs into frontend-optimized responses and centralize shared logic such as authentication and caching.

The extra service layer did add more monitoring points, but we adopted APM tools to maintain reliability. Overall, frontend development became much faster.

WebView + React: an alternative to the native SDK

Buzzvil provided ad placements inside partner apps through a native SDK. Adding a new feature, however, required partners to update the SDK and release their apps again. For partners with long release cycles or conservative update policies, improvements could take more than two years to reach users.

We addressed this by moving to a React SPA inside a WebView. The partner app simply opens a WebView, and the React app runs within it.

Because it was our first attempt at integrating a WebView placement, we went through plenty of trial and error. That story would make this post much longer, so I hope to cover it in a future article. In the end, the placement launched successfully, and we went on a workshop trip with the teammates who had worked so hard on it.

Earn pocket money

Building a monorepo with Turborepo

As the WebView strategy succeeded, demand for serving ads through WebViews grew. With more projects came increasing complexity in managing configuration, keeping shared components synchronized, and coordinating package versions across separate repositories.

At that point, we adopted Turborepo and moved to a monorepo. Alternatives included Lerna and Yarn workspaces, but Vercel was gaining ground, and with relatively few frontend engineers, productivity mattered more to us than a large feature set. We chose Turborepo, which was aiming for zero configuration at the time. All WebView projects now live in one repository, with shared UI components and utilities in packages/ for each project to import.

Shared packages

Initially, preserving Git history while combining repositories was difficult, and we spent considerable time on Turborepo dependency issues. Today, though, we manage more than ten projects efficiently, with a much better developer experience.

Flexibility through server-driven UI

Each partner wanted different UI layouts, and every new design experiment required a client deployment. To solve this, we introduced a server-driven UI architecture.

We split the UI into small modules. The server sends JSON describing which components to place in which order, and the client interprets it to build the screen. If partner A wants a list and partner B wants a grid, for example, we can apply either immediately by changing server configuration.

This approach was powerful but complex. We needed a design that accounted for all possible combinations, along with validation to prevent UX problems in particular combinations. We also had to build configuration editing and preview tools for the operations team. Thanks to that investment, we can now run many experiments and customizations without deploying code.

Adopting Next.js as the team's standard

As React projects multiplied, we began to feel the limitations of our React apps. Configuring SSR separately was complex, and it was difficult to meet the performance expectations of many customers.

Moving to Next.js solved many of these problems. SSR lets us fetch initial server-driven UI values in advance, speeding up initial loading and substantially improving perceived performance, especially inside WebViews. Integrating some BFF capabilities into Next.js API Routes also simplified the architecture.

File-based routing made project structures more intuitive and development workflows smoother. Next.js is now the team's standard framework for all new projects.

Improving WebView–native communication with a hybrid SDK

A web app inside a WebView needs to invoke native features, such as opening an external browser or navigating back. Native code also needs to send events—the results of WebView calls—back to the web app. We originally wrote separate bridge code for each integration, but this became difficult to manage as features grew. In particular, back-and-forth communication with customers' native developers consumed considerable resources.

We developed a hybrid SDK to solve this, creating a consistent interface across Android and iOS. The web side can now call every native capability through a single method: window.buzzvilSdk.postMessage(payload).

Hybrid SDK

Next: gradually migrating the Vue admin

The Vue admin is operating reliably, but now that React and Next.js are our main stack, maintaining two stacks is a burden. New developers must learn both Vue and React, and that remains an ongoing hurdle.

Migrating a large, live admin application all at once would be risky, so we have planned a gradual transition. First, all new features will be built in React and connected to existing Vue pages through iframes. We will rewrite independent pages one by one, using an arrangement similar to micro-frontends so that the two frameworks can coexist during the transition.

Our goal is to unify all admin applications on Next.js over the next two to three years.

Closing thoughts

That was the Buzzvil frontend team's journey from AngularJS through Vue and React to Next.js. Looking back, every transition had its own reasons and tradeoffs. None was a perfect choice.

What mattered was making the best choice for the circumstances and being willing to improve it when problems arose—whether by accelerating development with a BFF, making deployment more flexible with WebViews, or improving management efficiency through a monorepo.

New technologies and challenges will keep coming. WebAssembly and AI development tools are just some of the interesting developments we see. But before focusing on the technology itself, we want to keep asking, “Do our team and service actually need this?”

I hope this account helps developers facing similar decisions. There may be no single right technology choice, but we can learn from other teams' experiences.

Apply for an engineering role at Buzzvil

Have a coffee chat with a Buzzvil tech recruiter

All articles