<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Turborepo on Commentary of Takao</title><link>https://takao.blog/ko/tags/turborepo/</link><description>Recent content in Turborepo on Commentary of Takao</description><generator>Hugo -- gohugo.io</generator><language>ko</language><copyright>Commentary of Takao</copyright><lastBuildDate>Tue, 24 Sep 2024 00:00:00 +0900</lastBuildDate><atom:link href="https://takao.blog/ko/tags/turborepo/index.xml" rel="self" type="application/rss+xml"/><item><title>Monorepo Management with Turborepo: Scaling Development</title><link>https://takao.blog/ko/web/monorepo-turborepo/</link><pubDate>Tue, 24 Sep 2024 00:00:00 +0900</pubDate><guid>https://takao.blog/ko/web/monorepo-turborepo/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/monorepo-turborepo-ko.png" alt="Featured image of post Monorepo Management with Turborepo: Scaling Development" /&gt;&lt;h2 id="introduction"&gt;Introduction
&lt;/h2&gt;&lt;p&gt;As JavaScript monorepos grow, build times spiral, CI pipelines saturate, and developer productivity drops. Turborepo, created by Vercel, addresses these challenges with intelligent caching and parallel task execution. Unlike Lerna or Nx, Turborepo focuses on being a task runner rather than a build tool, delegating compilation to tools like esbuild, webpack, and tsc.&lt;/p&gt;
&lt;h2 id="core-architecture--the-cache-system"&gt;Core Architecture — The Cache System
&lt;/h2&gt;&lt;p&gt;Turborepo&amp;rsquo;s cache is its defining 기능. Cache keys are computed from file contents, environment variables, and dependency graphs. The cache lives in &lt;code&gt;node_modules/.cache/turbo&lt;/code&gt; as tar.gz archives, and the cache hit/miss lifecycle determines whether a task executes or skips.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pipeline&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;build&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;dependsOn&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;^build&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;outputs&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;dist/**&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;.next/**&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;inputs&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;src/**/*.ts&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;src/**/*.tsx&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;inputs&lt;/code&gt; configuration fine-tunes which files affect caching granularity. Turborepo uses content hashing with &lt;code&gt;globalHash&lt;/code&gt; for root-level changes and per-task &lt;code&gt;hash&lt;/code&gt; for individual tasks. Use &lt;code&gt;--dry-run&lt;/code&gt; to verify cache behavior before committing configuration changes.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="task-orchestration-with-pipeline-configuration"&gt;Task Orchestration with Pipeline Configuration
&lt;/h2&gt;&lt;p&gt;The &lt;code&gt;turbo.json&lt;/code&gt; pipeline configuration is the heart of task orchestration. Task dependencies, output directories, environment variables, and persistent mode are all defined here.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pipeline&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;build&amp;#34;&lt;/span&gt;: { &lt;span style="color:#f92672"&gt;&amp;#34;dependsOn&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;^build&amp;#34;&lt;/span&gt;], &lt;span style="color:#f92672"&gt;&amp;#34;outputs&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;dist/**&amp;#34;&lt;/span&gt;] },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;test&amp;#34;&lt;/span&gt;: { &lt;span style="color:#f92672"&gt;&amp;#34;dependsOn&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;build&amp;#34;&lt;/span&gt;] },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;lint&amp;#34;&lt;/span&gt;: { &lt;span style="color:#f92672"&gt;&amp;#34;dependsOn&amp;#34;&lt;/span&gt;: [], &lt;span style="color:#f92672"&gt;&amp;#34;outputs&amp;#34;&lt;/span&gt;: [] },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;typecheck&amp;#34;&lt;/span&gt;: { &lt;span style="color:#f92672"&gt;&amp;#34;dependsOn&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;^build&amp;#34;&lt;/span&gt;] }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The topological ordering strategy ensures that dependencies of a package build before the package itself, while independent tasks like &lt;code&gt;lint&lt;/code&gt; and &lt;code&gt;typecheck&lt;/code&gt; run in parallel. Use &lt;code&gt;cache: false&lt;/code&gt; for tasks that should never be cached, such as linting with fix mode.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="remote-caching"&gt;Remote Caching
&lt;/h2&gt;&lt;p&gt;Remote caching enables build artifact sharing across team members and CI agents. Vercel&amp;rsquo;s remote cache, self-hosted Turbo 서버, and S3-compatible backends are all supported.&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;기능&lt;/th&gt;
					&lt;th&gt;Vercel Remote Cache&lt;/th&gt;
					&lt;th&gt;Self-hosted&lt;/th&gt;
					&lt;th&gt;Nx Cloud&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Setup complexity&lt;/td&gt;
					&lt;td&gt;Low&lt;/td&gt;
					&lt;td&gt;Medium&lt;/td&gt;
					&lt;td&gt;Low&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Cost&lt;/td&gt;
					&lt;td&gt;Free tier available&lt;/td&gt;
					&lt;td&gt;Infrastructure cost&lt;/td&gt;
					&lt;td&gt;Paid tiers&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Data control&lt;/td&gt;
					&lt;td&gt;Vercel-managed&lt;/td&gt;
					&lt;td&gt;Full control&lt;/td&gt;
					&lt;td&gt;Nx-managed&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Auth&lt;/td&gt;
					&lt;td&gt;Team tokens&lt;/td&gt;
					&lt;td&gt;Custom&lt;/td&gt;
					&lt;td&gt;Integration tokens&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;인증 uses &lt;code&gt;TURBO_TOKEN&lt;/code&gt; and &lt;code&gt;TURBO_TEAM&lt;/code&gt; environment variables. Environment-based cache namespacing prevents cross-environment cache pollution.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="dependency-graph-최적화"&gt;Dependency Graph 최적화
&lt;/h2&gt;&lt;p&gt;Turborepo constructs a DAG from &lt;code&gt;package.json&lt;/code&gt; dependencies and uses it for task scheduling. The &lt;code&gt;--filter&lt;/code&gt; syntax scopes runs to specific packages and their dependencies, while &lt;code&gt;--graph&lt;/code&gt; visualizes the dependency graph.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;turbo run build --filter&lt;span style="color:#f92672"&gt;=&lt;/span&gt;@acme/web...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;turbo run build --graph --output&lt;span style="color:#f92672"&gt;=&lt;/span&gt;graph.html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Reducing cross-package dependencies, using the workspace protocol consistently, and grouping related packages all contribute to faster builds.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="migration-strategies"&gt;Migration Strategies
&lt;/h2&gt;&lt;p&gt;Migrating from Lerna involves replacing &lt;code&gt;lerna run&lt;/code&gt; with &lt;code&gt;turbo run&lt;/code&gt;, adding &lt;code&gt;turbo.json&lt;/code&gt;, and preserving existing npm scripts. From Nx, translate Nx executors to shell commands in &lt;code&gt;turbo.json&lt;/code&gt;. From custom scripts, identify parallelization opportunities and convert shell pipelines to &lt;code&gt;turbo.json&lt;/code&gt; entries. Teams with 50 or more packages typically see CI time reductions of sixty to eighty percent after migration.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Turborepo delivers fast, correct, and developer-friendly monorepo task running. For teams using npm, pnpm, or yarn workspaces who want faster CI without adopting a full build system, Turborepo is an excellent choice. Its open-source nature, active 커뮤니티, and upcoming daemon-based file watching make it a solid long-term 투자.&lt;/p&gt;</description></item></channel></rss>