Spring Boot: Korea’s Backend Standard and the Inversion of Control

📖 14min read

Is South Korea a “Spring Republic”?

If you want to get hired as a backend developer in Korea, there is one question you can hardly avoid. “Can you work with Spring?”

On job boards, nine out of ten listings explicitly ask for “experience with Spring Boot.” People even joke that Korea is a “Spring Republic.” When I was in college, I assumed this was just another trend.

“Why not just write it in Java? Why go out of your way to use heavy Spring?” “Isn’t Node.js or Python (Django) easier anyway?”

But once I entered industry and went through large-scale projects, I finally understood. Spring was not a fad. It was a standard workbench polished over years by countless senior developers so that huge, complicated enterprise systems could be built safely and quickly.

This series is about how to build an unshakable castle, a Monolith, on top of that standard workbench.

Frameworks: Why You Can’t Do Everything Your Way

Before we get into the real technical story, there is one thing we need to settle first. What exactly is a framework? And how is it different from a library?

I briefly mentioned this in the previous Re: Booting series, but the decisive difference comes down to one question: who holds the initiative?

Spring is a framework. So using Spring is almost like signing a pledge that says, “I will stop coding entirely on my own terms and follow Spring’s rules.” The heart of those rules is what we are talking about today: Inversion of Control (IoC).

“Please stop using new so much”

The first rule in that pledge was shocking. It basically said: stop using Java’s most basic operator, new.

Back in college, if I needed an object, the obvious thing to write was MemberService service = new MemberService();. If I need something, I create it myself and use it. That felt completely natural.

But when I opened a Spring Boot project after joining a company, I could not find the keyword new anywhere in the code. Instead, strange annotations like @Autowired and @RequiredArgsConstructor were everywhere.

“Wait, if nobody created the object, how is this method even being called? Does this thing actually run?”

When I asked a senior developer, the answer sounded maddeningly vague. “Spring Container injects it for us, so we don’t need to create it ourselves. In fact, if you keep using new directly, the code becomes much harder to maintain later.”

I could not accept it. I was the owner of the code I wrote, so why was I being told I could not even create an object freely? It felt like Spring’s dictatorship.

Will I make it myself, or will I use something prepared by someone else?

The Chef and the Ingredient Manager (IoC & DI)

To understand why this seemingly authoritarian rule exists, let’s switch our metaphor and move into a restaurant kitchen.

1. The traditional way (I’m in charge)

I am a chef, a Class. To cook, I need a knife, a Dependency.

2. Spring’s way (Spring is in charge)

I am still a chef. But this time, there is an ingredient manager, the Spring Container.

In other words, instead of managing the resources I need by myself, something outside of me manages them and hands them to me. That is Inversion of Control (IoC), and the concrete technique used to do it is Dependency Injection (DI).

To be injected means handing someone else the burden of choosing and preparing your tools.

[Code Verification] Why is new dangerous?

Words alone do not make it click. Let’s compare it directly in code. Suppose we are building a card payment system.

1. Bad example: direct instantiation (tight coupling)

public class PaymentService {
    // I directly picked and created a Samsung Card. (using new)
    private final SamsungCard card = new SamsungCard();

    public void pay() {
        card.payment(); // Can only pay with Samsung Card
    }
}

The problem: One day the boss says, “Let’s switch to Hyundai Card because the fees are lower.” Then I have to open the PaymentService code and replace every SamsungCard with HyundaiCard. What if that code appears in 100 different places? You’re staying late.

2. Good example: dependency injection (loose coupling)

public class PaymentService {
    private final Card card; // Do not specify a concrete card issuer (use the interface)

    // Constructor injection: trust that someone outside will hand over a card.
    public PaymentService(Card card) {
        this.card = card;
    }

    public void pay() {
        card.payment();
    }
}

Now PaymentService no longer cares which card implementation gets passed in.

    This is the core of what people mean in practice when they say “maintainable code” or the OCP principle. This flexibility is exactly why people use Spring Boot.

    Spring Container: a hotel for objects

    Then who exactly is this “manager” that creates objects and hands them out? It is the Spring Container.

    The moment we start a Spring Boot server with run, a lot happens behind the scenes.

    Our job is simply to put a sticker on the class that says, “Please manage this,” with something like @Service. The rest is handled by Spring, like a massive hotel manager keeping every guest in order.

    Practical advice: use constructor injection

    Spring offers several ways to inject dependencies, field injection with @Autowired, setter injection, and constructor injection. But in real projects, people consistently recommend constructor injection. It is the pattern typically used with Lombok’s @RequiredArgsConstructor.

    @Service
    @RequiredArgsConstructor // This automatically generates the constructor injection.
    public class OrderService {
        // final can be used, so it is safe.
        private final PaymentService paymentService;
    }
    
    

    Why?

    Closing: not a magician, but a conductor

    At first, I resisted Spring because it felt like it was waving my code around however it pleased. But now I see it differently. Spring is not a dictator that torments me. It is a competent conductor that organizes complex object relationships.

    Because of that, I spend less time worrying about “what object should I create?” and more time focusing on “how should I build business logic with this object?” That is probably why so many developers in Korea remain devoted to Spring.

    Now we have handed object management over to Spring. We are ready to boot the server. But a web application does not run alone. It has to talk to the frontend. Back in the PHP era, it felt convenient because HTML and code lived together in a single file. So why do modern teams split frontend work, Vue or React, from backend development? And why do you get a red CORS error the moment you try to connect the two?

    Next time, let’s dig into the shift in web architecture, SSR vs CSR, and the true identity of CORS, the wall standing between them.

    Leave a Comment