하루 IT블로구 day2

권준열·2026년 9월 20일

HTML, XML, JSON, REST API, API Key, Webhook, Polling, Frontend, FastAPI

백엔드 개발을 하다 보면 Spring Boot 코드만 작성해서는 전체 웹 서비스의 흐름을 이해하기 어렵다.

개발을 하면서 다음과 같은 용어들을 계속 만나게 된다.

  • HTML, CSS, JavaScript
  • XML, JSON
  • HTTP
  • REST API
  • Path Variable, Query Parameter
  • Header, Body
  • API Key
  • JWT
  • Webhook
  • Polling
  • Frontend
  • React, Next.js, TypeScript
  • Backend
  • Spring Boot
  • FastAPI

각각 따로 보면 어려워 보이지만 결국 대부분 다음 흐름 안에서 연결된다.

사용자
 ↓
Frontend
 ↓
HTTP Request
 ↓
Backend API
 ↓
Database / Redis / 외부 API
 ↓
HTTP Response
 ↓
Frontend
 ↓
사용자 화면

이번 글에서는 이 전체 흐름을 기준으로 하나씩 정리해보자.


1. HTML이란?

HTML은 웹페이지의 구조를 표현하는 마크업 언어다.

HTML은 HyperText Markup Language의 약자다.

<!DOCTYPE html>
<html>
<head>
    <title>My Page</title>
</head>

<body>
    <h1>안녕하세요</h1>
    <p>웹 페이지입니다.</p>
    <button>로그인</button>
</body>
</html>

브라우저는 HTML을 읽고 화면의 구조를 만든다.

HTML
 ↓
Browser
 ↓
화면

HTML 자체는 일반적인 의미의 프로그래밍 언어라기보다는 문서의 구조를 표현하는 언어다.

<h1>제목</h1>

<p>본문</p>

<button>버튼</button>

<img src="cat.png">

2. CSS란?

HTML이 웹페이지의 구조를 담당한다면 CSS는 디자인과 스타일을 담당한다.

<button class="login-button">
    로그인
</button>
.login-button {
    background-color: blue;
    color: white;
    padding: 10px;
}

정리하면 다음과 같다.

HTML
→ 구조

CSS
→ 디자인

JavaScript
→ 동작

3. JavaScript란?

JavaScript는 웹 브라우저에서 동작하는 대표적인 프로그래밍 언어다.

예를 들어 로그인 버튼을 눌렀을 때 백엔드 API를 호출할 수 있다.

async function login() {
    const response = await fetch("/api/login", {
        method: "POST",

        headers: {
            "Content-Type": "application/json"
        },

        body: JSON.stringify({
            email: "test@test.com",
            password: "1234"
        })
    });

    const data = await response.json();

    console.log(data);
}

즉 JavaScript는 단순히 화면을 움직이는 것뿐만 아니라 백엔드 서버와 통신하는 역할도 한다.


4. XML이란?

XML은 데이터를 구조적으로 표현하기 위한 마크업 언어다.

XML은 Extensible Markup Language의 약자다.

예를 들어 사용자 데이터를 표현하면 다음과 같다.

<user>
    <id>1</id>
    <name>Jun</name>
    <age>24</age>
</user>

HTML과 모양은 비슷하지만 목적이 다르다.

HTML
→ 웹 문서의 구조 표현

XML
→ 데이터의 구조 표현

XML에서는 태그를 직접 정의할 수 있다.

<company>
    <name>ABC</name>

    <employees>
        <employee>
            <name>Kim</name>
        </employee>

        <employee>
            <name>Lee</name>
        </employee>
    </employees>
</company>

과거에는 서버 간 데이터 교환에 XML이 많이 사용되었고, 지금도 SOAP이나 일부 공공기관 API, 레거시 시스템 등에서 사용된다.


5. JSON이란?

JSON은 현재 웹 API에서 가장 흔하게 볼 수 있는 데이터 표현 형식 중 하나다.

JSON은 JavaScript Object Notation의 약자다.

{
  "id": 1,
  "name": "Jun",
  "age": 24
}

배열도 표현할 수 있다.

{
  "users": [
    {
      "id": 1,
      "name": "Kim"
    },
    {
      "id": 2,
      "name": "Lee"
    }
  ]
}

6. XML과 JSON의 차이

같은 데이터를 XML과 JSON으로 표현해보자.

XML

<user>
    <id>1</id>
    <name>Jun</name>
    <age>24</age>
</user>

JSON

{
  "id": 1,
  "name": "Jun",
  "age": 24
}

JSON은 비교적 간결하고 JavaScript 객체와도 자연스럽게 연결되기 때문에 현대적인 웹 API에서 매우 많이 사용된다.

하지만 XML이 사라진 것은 아니다.

JSON
→ REST API
→ 웹/모바일 서비스
→ 프론트엔드 ↔ 백엔드 통신

XML
→ SOAP
→ 일부 공공 API
→ 레거시 기업 시스템
→ 설정 파일 등

7. JSON은 실제로 어디에 넣어서 보내는가?

JSON이라는 데이터가 인터넷을 혼자 돌아다니는 것은 아니다.

대부분 HTTP Request 또는 HTTP Response 안에 담겨서 이동한다.

예를 들어:

POST /api/users HTTP/1.1
Content-Type: application/json

{
  "name": "Jun",
  "age": 24
}

여기서 JSON은 HTTP의 Body에 들어있다.

전체적인 HTTP Request를 단순화하면 다음과 같다.

HTTP Request

┌─────────────────────────────┐
│ Method + URL                │
│ POST /api/users             │
├─────────────────────────────┤
│ Header                      │
│ Content-Type: application/json
│ Authorization: Bearer ...   │
├─────────────────────────────┤
│ Body                        │
│                             │
│ {                           │
│   "name": "Jun",            │
│   "age": 24                 │
│ }                           │
└─────────────────────────────┘

Spring Boot에서는 다음과 같이 받을 수 있다.

@PostMapping("/api/users")
public void createUser(
        @RequestBody CreateUserRequest request
) {
}

8. HTTP Request는 무엇으로 구성되는가?

백엔드 개발자라면 반드시 알아야 한다.

대표적으로 데이터를 전달할 수 있는 위치는 다음과 같다.

HTTP Request

Method
URL
├── Path
├── Path Variable
└── Query Parameter

Headers
Cookies

Body

8.1 HTTP Method

서버에 어떤 행동을 요청하는지를 표현한다.

대표적인 Method는 다음과 같다.

GET
→ 데이터 조회

POST
→ 데이터 생성

PUT
→ 리소스 전체 수정/교체

PATCH
→ 리소스 일부 수정

DELETE
→ 데이터 삭제

예를 들어:

GET /users/1

은 사용자를 조회하는 요청이고,

DELETE /users/1

은 사용자를 삭제하는 요청으로 설계할 수 있다.

HTTP Method 자체가 모든 의미를 강제하는 것은 아니지만 REST API에서는 이러한 의미를 살려 설계하는 것이 일반적이다.


9. Path Variable이란?

특정 리소스를 식별할 때 많이 사용한다.

GET /users/123

여기서:

123

이 Path Variable이다.

Spring Boot에서는:

@GetMapping("/users/{id}")
public User getUser(
        @PathVariable Long id
) {
    ...
}

처럼 받을 수 있다.

예를 들어:

/users/1
/users/2
/users/3

처럼 각각 다른 사용자를 표현할 수 있다.


10. Query Parameter란?

검색, 필터링, 정렬, 페이지네이션 등에 많이 사용한다.

GET /users?page=2&size=20

여기서:

page=2
size=20

이 Query Parameter다.

Spring에서는 다음과 같이 받을 수 있다.

@GetMapping("/users")
public List<User> getUsers(
        @RequestParam int page,
        @RequestParam int size
) {
    ...
}

예를 들어 상품 검색이라면:

GET /products?category=computer&minPrice=100000&maxPrice=2000000

처럼 사용할 수 있다.


11. Header란?

Header에는 요청이나 응답에 대한 부가 정보가 들어간다.

예를 들어:

Content-Type: application/json
Authorization: Bearer eyJ...
Accept: application/json

각각 다음과 같은 의미를 가질 수 있다.

Content-Type
→ 내가 보내는 Body가 어떤 형식인가?

Accept
→ 나는 어떤 형식의 Response를 받고 싶은가?

Authorization
→ 인증 정보

Spring에서는 다음과 같이 읽을 수도 있다.

@RequestHeader("Authorization")
String authorization

12. Body란?

서버에 전달할 실제 데이터를 담는 공간이다.

예를 들어 회원가입 요청이라면:

POST /users
Content-Type: application/json

{
  "email": "test@test.com",
  "password": "1234",
  "name": "Jun"
}

JSON 데이터가 Body에 들어간다.

Spring Boot에서는:

@PostMapping("/users")
public void createUser(
        @RequestBody CreateUserRequest request
) {
}

처럼 받을 수 있다.


13. HTTP Request 하나를 완전히 분해해보기

다음 요청이 있다고 하자.

POST /users/123/orders?coupon=SUMMER
Authorization: Bearer abcdef
Content-Type: application/json

{
  "productId": 100,
  "quantity": 2
}

각 부분을 나누면:

POST
→ HTTP Method

/users/123/orders
→ Path

123
→ Path Variable

coupon=SUMMER
→ Query Parameter

Authorization
Content-Type
→ Header

{
  "productId": 100,
  "quantity": 2
}
→ Body

이 구조는 백엔드 개발을 하면서 정말 자주 만나게 된다.


14. API란?

API는 Application Programming Interface의 약자다.

쉽게 말하면 프로그램과 프로그램이 서로 기능이나 데이터를 주고받기 위한 약속된 인터페이스라고 볼 수 있다.

예를 들어 프론트엔드가 백엔드에게:

"사용자 123의 정보를 줘"

라고 요청할 수 있도록 백엔드가 다음 API를 제공할 수 있다.

GET /api/users/123

Backend가 다음 JSON을 반환한다.

{
  "id": 123,
  "name": "Jun",
  "email": "test@test.com"
}

즉:

Frontend
   ↓
API 호출
   ↓
Backend
   ↓
JSON Response
   ↓
Frontend

가 된다.


15. REST란?

REST는 Representational State Transfer의 약자다.

REST는 특정 라이브러리나 프로그램이 아니라 웹 API를 설계하기 위한 아키텍처 스타일이다.

핵심적인 생각 중 하나는 서버의 데이터를 Resource로 보는 것이다.

예를 들어:

사용자
→ /users

상품
→ /products

주문
→ /orders

그리고 HTTP Method를 이용해서 행동을 표현한다.

GET /users/1
1번 사용자 조회
POST /users
사용자 생성
PATCH /users/1
1번 사용자 일부 수정
DELETE /users/1
1번 사용자 삭제

16. REST API란?

REST의 원칙을 고려하여 설계한 HTTP API를 일반적으로 REST API라고 부른다.

예를 들어 다음과 같이 설계할 수 있다.

GET    /users
GET    /users/{id}
POST   /users
PATCH  /users/{id}
DELETE /users/{id}

반대로 다음과 같이 모든 행동을 URL에 직접 넣는 방식은 REST스럽지 않은 설계의 예로 자주 언급된다.

/getUser
/createUser
/deleteUser
/updateUser

REST 스타일에서는:

Resource
+
HTTP Method

를 이용해서 의미를 표현하려고 한다.


17. REST API와 JSON은 같은 것인가?

아니다.

REST
→ API를 어떻게 설계할 것인가에 대한 스타일

JSON
→ 데이터를 어떤 형식으로 표현할 것인가

REST API가 JSON을 많이 사용하기 때문에 둘을 같이 보는 경우가 많을 뿐이다.

예를 들어:

GET /users/1

이라는 REST API가 다음 JSON을 반환할 수 있다.

{
  "id": 1,
  "name": "Jun"
}

18. API Key란?

외부 API를 사용하다 보면 다음과 같은 값을 받는 경우가 있다.

API_KEY=abc123xyz

API Key는 보통:

"이 API를 호출하는 클라이언트가 누구인지 식별하거나 사용 권한/사용량을 관리하기 위한 키"

로 사용된다.

예를 들어 날씨 API를 호출한다고 하자.

내 Backend
   ↓
Weather API

Weather API 회사는 아무나 무제한으로 API를 호출하게 하고 싶지 않을 수 있다.

그래서 사용자에게 API Key를 발급한다.

회원가입
 ↓
API Key 발급
 ↓
abc123xyz

그리고 요청할 때 API Key를 같이 보낸다.


19. API Key는 어디에 넣어서 보내는가?

API마다 다르다.

대표적으로 Header 또는 Query Parameter를 사용한다.

Header 방식

GET /weather

X-API-Key: abc123xyz

또는 서비스에 따라:

Authorization: Bearer abc123xyz

같은 형태를 사용할 수도 있다.

Query Parameter 방식

일부 API는 다음처럼 요구한다.

GET /weather?apiKey=abc123xyz

어디에 넣는지는 API 제공자의 문서를 따라야 한다.

보안상 API Key를 URL에 넣으면 로그나 브라우저 기록 등 여러 위치에 노출될 가능성이 있기 때문에 가능하다면 Header 방식이 선호되는 경우가 많다.


20. API Key를 Frontend에 넣어도 될까?

보통 비밀로 유지해야 하는 API Key는 Frontend에 넣으면 안 된다.

예를 들어:

const API_KEY = "SUPER_SECRET_KEY";

를 브라우저 JavaScript에 넣으면 사용자가 개발자 도구 등을 통해 확인할 수 있다.

따라서 일반적으로:

Frontend
   ↓
내 Backend
   ↓
Secret API Key 사용
   ↓
외부 API

구조를 사용한다.

Browser
→ Secret 저장 X

Backend Environment Variable
→ Secret 저장

예를 들어:

OPENAI_API_KEY=...
WEATHER_API_KEY=...

같은 값은 서버의 환경변수나 Secret 관리 시스템에서 관리한다.


21. API Key와 JWT는 같은 것인가?

다르다.

API Key는 주로:

"이 API를 호출하는 애플리케이션/클라이언트는 누구인가?"

를 식별하거나 접근 권한과 사용량을 관리하는 데 사용된다.

JWT는 웹 서비스 로그인에서 다음처럼 많이 사용된다.

사용자 로그인
 ↓
Backend 인증
 ↓
Access Token 발급
 ↓
Frontend가 이후 요청에 Token 포함

예:

Authorization: Bearer eyJhbGciOi...

즉 사용 사례에 따라 다르지만 단순화하면:

API Key
→ API 소비자/애플리케이션 인증에 자주 사용

JWT
→ 로그인한 사용자 인증/인가에 자주 사용

이라고 생각할 수 있다.


22. Frontend란?

Frontend는 사용자가 직접 보는 화면과 사용자 상호작용을 담당하는 영역이다.

사용자
 ↓
Frontend
 ↓
Backend
 ↓
Database

예를 들어:

로그인 화면
회원가입 화면
상품 목록
검색창
버튼
그래프
대시보드

등을 구현한다.


23. Frontend에는 어떤 언어가 사용되는가?

웹 Frontend의 기본은 다음 세 가지다.

HTML
CSS
JavaScript

역할은 다음과 같다.

HTML
→ 구조

CSS
→ 디자인

JavaScript
→ 동작

그런데 실제 프로젝트에서는 JavaScript만 직접 사용하는 것보다 여러 프레임워크와 라이브러리를 사용한다.

대표적으로:

React
Vue
Angular
Svelte

등이 있다.


24. JavaScript와 TypeScript의 차이

TypeScript는 JavaScript에 정적 타입 시스템을 추가한 언어라고 볼 수 있다.

JavaScript:

function add(a, b) {
    return a + b;
}

TypeScript:

function add(a: number, b: number): number {
    return a + b;
}

TypeScript에서는:

add("hello", 10);

처럼 타입이 맞지 않는 코드를 개발 단계에서 발견하기 쉬워진다.

큰 프로젝트에서는 TypeScript를 사용하는 경우가 많다.


25. React란?

React는 UI를 Component 단위로 구성할 수 있도록 도와주는 JavaScript 라이브러리다.

예를 들어:

function LoginButton() {
    return (
        <button>
            로그인
        </button>
    );
}

다음과 같이 화면을 여러 Component로 나눌 수 있다.

App

├── Header
├── Sidebar
├── UserProfile
├── ProductList
│   ├── ProductCard
│   ├── ProductCard
│   └── ProductCard
└── Footer

컴포넌트를 조합해서 복잡한 UI를 구성한다.


26. Next.js란?

Next.js는 React를 기반으로 웹 애플리케이션을 만들기 위한 프레임워크다.

React만 사용하면 프로젝트 구조, Routing, Rendering 등의 여러 부분을 직접 구성해야 할 수 있다.

Next.js는 이런 기능들을 통합적으로 제공한다.

대표적으로:

Routing
Server Rendering
Static Generation
API 관련 기능
이미지 최적화
빌드 최적화
React Server Components 관련 기능

등을 제공한다.

단순하게 보면:

JavaScript / TypeScript
        ↓
      React
        ↓
     Next.js

정도의 관계로 이해할 수 있다.

단, React는 라이브러리이고 Next.js는 React 기반 프레임워크라는 차이가 있다.


27. 백엔드 개발자는 Frontend를 어디까지 알아야 할까?

백엔드 개발자가 전문 프론트엔드 개발자 수준의 CSS나 UI 디자인 능력을 반드시 가질 필요는 없다.

하지만 Frontend와 Backend가 어떻게 통신하는지는 반드시 이해하는 것이 좋다.

최소한 다음 내용은 알아두는 것이 좋다.

HTML 기본 구조

JavaScript / TypeScript 기본

React Component 개념

HTTP Request / Response

fetch / axios

JSON

Cookie

Local Storage

CORS

JWT

Authorization Header

Form Data

파일 업로드

HTTP Status Code

CSR / SSR 개념

브라우저 개발자 도구 Network 탭

특히 백엔드 개발자에게 중요한 것은:

"Frontend가 내가 만든 API를 실제로 어떻게 호출하는가?"

를 이해하는 것이다.


28. Frontend에서 Backend API를 어떻게 호출할까?

예를 들어 Backend가 다음 API를 제공한다고 하자.

GET /api/users/1

Frontend에서는 fetch를 사용할 수 있다.

const response = await fetch(
    "http://localhost:8080/api/users/1"
);

const user = await response.json();

console.log(user);

Backend:

@GetMapping("/api/users/{id}")
public UserResponse getUser(
        @PathVariable Long id
) {
    return userService.getUser(id);
}

흐름은:

React / Next.js
      ↓
fetch()
      ↓
HTTP Request
      ↓
Spring Boot
      ↓
JSON Response
      ↓
response.json()
      ↓
Frontend 화면에 표시

가 된다.


29. CORS란?

Frontend와 Backend를 분리하면 자주 만나는 것이 CORS다.

예를 들어:

Frontend
http://localhost:3000

Backend
http://localhost:8080

처럼 서로 다른 Origin에서 동작할 수 있다.

브라우저에는 보안상의 이유로 Cross-Origin 요청에 대한 정책이 존재한다.

서버가 적절한 CORS 응답 헤더를 제공하지 않으면 브라우저가 Frontend JavaScript에서 응답을 사용하지 못하게 할 수 있다.

Spring에서는 예를 들어 CORS 설정을 추가할 수 있다.

@Configuration
public class WebConfig {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {

            @Override
            public void addCorsMappings(
                    CorsRegistry registry
            ) {
                registry
                    .addMapping("/**")
                    .allowedOrigins(
                        "http://localhost:3000"
                    );
            }
        };
    }
}

실제 서비스에서는 허용 Origin, Method, Header, Credential 정책 등을 보안 요구사항에 맞게 설정해야 한다.


30. Polling이란?

Polling은 클라이언트가 서버에게 주기적으로 새로운 정보가 있는지 물어보는 방식이다.

예를 들어 주문 상태를 확인한다고 하자.

Frontend
   ↓
"주문 완료됐어?"

5초 후
   ↓
"주문 완료됐어?"

5초 후
   ↓
"주문 완료됐어?"

5초 후
   ↓
"주문 완료됐어?"

코드로 단순하게 표현하면:

setInterval(async () => {

    const response = await fetch(
        "/api/orders/123"
    );

    const order = await response.json();

    console.log(order.status);

}, 5000);

이게 Polling이다.


31. Polling의 장단점

Polling은 구현하기 쉽다.

장점

구현 간단
HTTP만 사용 가능
서버 구조 단순

하지만 단점도 있다.

단점

변화가 없어도 계속 Request 발생
서버 부하 증가 가능
실시간성이 Polling 주기에 의존

예를 들어 5초마다 Polling하면 서버에서 상태가 변경된 직후라도 클라이언트는 최대 약 5초 후에야 확인할 수 있다.


32. Webhook이란?

Webhook은 Polling과 방향이 반대다.

Polling:

내 서버
→ "바뀌었어?"
→ 외부 서버

내 서버
→ "바뀌었어?"
→ 외부 서버

Webhook:

내 서버
← "바뀌었어!"
← 외부 서버

즉 이벤트가 발생하면 상대 서버가 내 서버의 URL을 호출해주는 방식이다.


33. Webhook 예시

결제 시스템을 생각해보자.

사용자가 결제를 시작했다.

사용자
 ↓
내 Backend
 ↓
결제 서비스

결제가 바로 최종 확정되지 않을 수도 있다.

Polling을 사용하면:

내 Backend
→ 결제됐나요?

내 Backend
→ 결제됐나요?

내 Backend
→ 결제됐나요?

라고 계속 확인해야 한다.

Webhook을 사용하면 결제 서비스가:

결제 완료
 ↓
POST https://my-service.com/webhooks/payment

처럼 내 서버를 호출한다.

Payload 예:

{
  "event": "PAYMENT_COMPLETED",
  "paymentId": "pay_123",
  "amount": 10000
}

내 Backend에서는:

@PostMapping("/webhooks/payment")
public ResponseEntity<Void> paymentWebhook(
        @RequestBody PaymentWebhookRequest request
) {

    paymentService.handle(request);

    return ResponseEntity.ok().build();
}

처럼 처리할 수 있다.


34. Polling과 Webhook 차이

Polling

Client
  ↓
Server

"변경됐어?"
"변경됐어?"
"변경됐어?"

반면:

Webhook

이벤트 발생
   ↓
Server
   ↓
Client가 등록한 URL 호출

비교하면 다음과 같다.

구분PollingWebhook
요청 시작정보를 원하는 쪽이벤트가 발생한 쪽
방식주기적으로 확인이벤트 발생 시 호출
구현비교적 단순Endpoint 및 검증 필요
불필요한 요청발생 가능상대적으로 적음
대표 사례상태 조회결제 완료 알림

35. Webhook은 그냥 API 아닌가?

맞다.

Webhook도 결국 HTTP API를 이용하는 경우가 많다.

차이는 누가 먼저 요청하느냐에 있다.

일반 API:

내 서버
      ↓ Request
외부 서버
      ↓ Response
내 서버

Webhook:

외부 서버
      ↓ Request
내 서버의 Webhook Endpoint

즉 Webhook은 새로운 인터넷 프로토콜이 아니라 HTTP API를 이벤트 알림 방식으로 사용하는 패턴이라고 이해하면 쉽다.


36. Webhook 보안은 어떻게 할까?

아무나 다음 Endpoint를 호출할 수 있으면 위험하다.

POST /webhooks/payment

공격자가:

{
  "event": "PAYMENT_COMPLETED",
  "amount": 1000000
}

을 마음대로 보내면 안 된다.

그래서 Webhook 제공 서비스들은 흔히 Signature 검증 방식을 제공한다.

개념적으로:

Webhook Body
+
Secret
 ↓
Signature 생성

외부 서비스
 ↓
Webhook Request

Body
+
Signature Header
 ↓
내 Backend
 ↓
Signature 검증

이런 방식이다.

구체적인 검증 방법은 Webhook 제공자의 문서를 따라야 한다.


37. WebSocket은 또 무엇인가?

Polling과 Webhook을 공부하다 보면 WebSocket도 자주 등장한다.

일반 HTTP는 기본적으로:

Client
→ Request
→ Server

Server
→ Response
→ Client

형태다.

WebSocket은 연결을 유지하면서 양방향으로 데이터를 주고받을 수 있다.

Client
⇄
Server

그래서 다음과 같은 기능에 많이 사용된다.

실시간 채팅
실시간 게임
실시간 알림
실시간 가격
실시간 대시보드

38. Polling vs Webhook vs WebSocket

Polling
→ 내가 계속 물어봄

Webhook
→ 이벤트가 발생한 서버가 내 서버를 호출

WebSocket
→ 연결을 유지하고 양쪽이 실시간 통신

예를 들어:

주문 상태를 10초마다 확인
→ Polling

결제 업체가 내 Backend에게 결제 완료 통보
→ Webhook

채팅 메시지를 실시간 송수신
→ WebSocket

39. Backend란?

Backend는 사용자에게 직접 보이지 않는 서버 측 로직을 담당한다.

대표적인 역할은 다음과 같다.

API 제공

회원가입 / 로그인

비즈니스 로직

Database 접근

Transaction 처리

인증 / 인가

외부 API 호출

파일 처리

메시지 큐

캐시

결제

AI 서비스 연결

대표적인 Backend 기술로는:

Java
→ Spring Boot

Python
→ FastAPI / Django / Flask

JavaScript / TypeScript
→ Node.js / NestJS / Express

C#
→ ASP.NET Core

Go
→ Gin / Echo 등

Kotlin
→ Spring Boot / Ktor

등이 있다.


40. Spring Boot란?

Spring Boot는 Java 기반 Backend 애플리케이션을 개발할 때 많이 사용하는 프레임워크다.

예를 들어 REST API를 다음과 같이 만들 수 있다.

@RestController
@RequestMapping("/users")
public class UserController {

    @GetMapping("/{id}")
    public UserResponse getUser(
            @PathVariable Long id
    ) {
        return new UserResponse(
                id,
                "Jun"
        );
    }
}

요청:

GET /users/1

응답:

{
  "id": 1,
  "name": "Jun"
}

41. FastAPI란?

FastAPI는 Python으로 API 서버를 만들기 위한 웹 프레임워크다.

Spring Boot가 Java 생태계라면 FastAPI는 Python 생태계에서 API 서버를 빠르게 만들 때 많이 사용된다.

예를 들어:

from fastapi import FastAPI

app = FastAPI()


@app.get("/users/{user_id}")
def get_user(user_id: int):

    return {
        "id": user_id,
        "name": "Jun"
    }

요청:

GET /users/1

응답:

{
  "id": 1,
  "name": "Jun"
}

Spring Boot와 결국 같은 HTTP API를 제공할 수 있다.


42. Spring Boot와 FastAPI의 관계

둘 다 Backend API 서버를 만들 수 있다.

Frontend
    ↓
HTTP
    ↓

Spring Boot
또는
FastAPI

    ↓
Database / Redis / AI / 외부 API

차이는 주로 언어와 생태계다.

Spring Boot
→ Java / Kotlin
→ 대규모 Backend 서비스
→ Spring 생태계
→ JPA
→ Spring Security 등

FastAPI
→ Python
→ 간결한 API 개발
→ Python 생태계
→ AI / ML 라이브러리와 연결하기 편리
→ Pydantic 기반 데이터 검증

43. AI 서비스에서 FastAPI를 많이 보는 이유

Python에는 AI/ML 관련 생태계가 매우 크다.

예를 들어:

PyTorch
Transformers
scikit-learn
pandas
NumPy
LangChain
LangGraph

등이 있다.

따라서 다음 구조를 사용할 수 있다.

Frontend
   ↓
Spring Boot
   ↓
FastAPI AI Service
   ↓
LLM / Embedding / ML Model

Spring Boot는:

사용자
인증
인가
결제
DB
비즈니스 로직

등을 담당하고,

FastAPI는:

LLM
RAG
Embedding
AI Agent
ML Model
데이터 분석

등을 담당하도록 분리할 수 있다.

물론 반드시 이렇게 나눠야 하는 것은 아니다. 프로젝트의 규모와 요구사항에 따라 하나의 Backend로 구성할 수도 있다.


44. Spring Boot가 FastAPI를 어떻게 호출할까?

결국 HTTP API를 사용하면 된다.

예를 들어 FastAPI:

@app.post("/analyze")
def analyze(request: AnalyzeRequest):

    return {
        "result": "analysis result"
    }

Spring Boot:

POST http://ai-service:8000/analyze

Body:

{
  "text": "분석할 데이터"
}

전체 흐름:

Frontend
   ↓
Spring Boot
   ↓ HTTP + JSON
FastAPI
   ↓
AI Model
   ↓
FastAPI
   ↓ JSON
Spring Boot
   ↓
Frontend

즉 Java 서버와 Python 서버라고 해서 특별한 방식이 필요한 것이 아니다.

HTTP라는 공통 규칙을 사용하면 서로 다른 언어로 만든 프로그램끼리도 통신할 수 있다.


45. 결국 서로 다른 언어가 어떻게 통신하는가?

예를 들어:

Frontend
TypeScript

Backend
Java

AI Service
Python

이라고 해보자.

언어가 전부 다르다.

하지만:

TypeScript
    ↓
HTTP + JSON
    ↓
Java
    ↓
HTTP + JSON
    ↓
Python

으로 통신한다.

각 프로그램은 상대방 내부 코드가 Java인지 Python인지 몰라도 된다.

중요한 것은 API 계약이다.

예를 들어:

POST /analyze
Content-Type: application/json
{
  "text": "hello"
}

를 보내면:

{
  "result": "..."
}

를 반환한다는 약속만 맞으면 된다.

이것이 API가 중요한 이유다.


46. 직렬화와 역직렬화

그렇다면 Java 객체가 어떻게 JSON이 될까?

Spring Boot를 예로 들어보자.

public record UserResponse(
        Long id,
        String name
) {}

Controller가:

return new UserResponse(
        1L,
        "Jun"
);

을 반환하면 Spring이 JSON으로 변환할 수 있다.

{
  "id": 1,
  "name": "Jun"
}

이처럼:

Java Object
     ↓
JSON

으로 변환하는 것을 Serialization(직렬화)이라고 한다.

반대로:

JSON
 ↓
Java Object

으로 변환하는 것은 Deserialization(역직렬화)이라고 한다.


47. Content-Type은 왜 필요한가?

HTTP Body만 보면 서버는 이것이 JSON인지 XML인지 다른 형식인지 알아야 한다.

그래서 Header에:

Content-Type: application/json

을 넣는다.

즉:

Content-Type

"내가 보내는 Body는
이 형식으로 되어 있습니다."

라는 의미다.

XML이라면:

Content-Type: application/xml

같은 형태를 사용할 수 있다.

파일 업로드에서는:

Content-Type: multipart/form-data

를 자주 보게 된다.


48. 파일은 어떻게 API로 보내는가?

이미지 파일을 업로드한다고 생각해보자.

JSON Body에 일반 문자열처럼 넣는 것보다 multipart/form-data를 사용하는 경우가 많다.

Frontend:

const formData = new FormData();

formData.append("image", file);

await fetch("/api/images", {
    method: "POST",
    body: formData
});

Spring Boot:

@PostMapping("/api/images")
public void upload(
        @RequestParam MultipartFile image
) {
}

즉 HTTP Body라고 해서 항상 JSON만 들어가는 것은 아니다.

Body

JSON
XML
Form Data
Binary Data
Text
...

여러 형태가 가능하다.


49. Cookie란?

Cookie는 브라우저가 저장하고 HTTP 요청에 함께 보낼 수 있는 작은 데이터다.

서버가:

Set-Cookie: sessionId=abc123

을 반환하면 브라우저가 저장할 수 있다.

이후 요청에서:

Cookie: sessionId=abc123

처럼 보낼 수 있다.

그래서 Session 기반 인증 등에 사용할 수 있다.


50. Local Storage란?

Local Storage는 브라우저 내부에 데이터를 저장할 수 있는 기능이다.

localStorage.setItem(
    "theme",
    "dark"
);

읽을 때:

const theme =
    localStorage.getItem("theme");

Cookie와 Local Storage는 둘 다 브라우저 저장소와 관련 있지만 동작 방식과 보안 특성이 다르다.

특히 인증 토큰을 어디에 저장할지는 XSS, CSRF, SameSite, HttpOnly 등의 보안 요소를 함께 고려해야 한다.


51. HTTP Status Code

Backend는 Response Body만 보내는 것이 아니라 Status Code도 반환한다.

대표적으로:

200 OK
→ 성공

201 Created
→ 생성 성공

204 No Content
→ 성공했지만 Response Body 없음

400 Bad Request
→ 잘못된 요청

401 Unauthorized
→ 인증 필요/인증 실패

403 Forbidden
→ 인증은 되었지만 권한 부족

404 Not Found
→ 리소스를 찾을 수 없음

409 Conflict
→ 현재 상태와 충돌

500 Internal Server Error
→ 서버 내부 오류

예를 들어:

HTTP/1.1 404 Not Found
Content-Type: application/json
{
  "message": "User not found"
}

처럼 반환할 수 있다.


52. HTTPS는 무엇인가?

HTTP 요청을 그대로 네트워크에 보내면 통신 내용을 보호하기 어렵다.

HTTPS는 HTTP 통신을 TLS를 통해 보호한다.

HTTP
+
TLS
=
HTTPS

대략적인 구조는:

Browser
   ↓
TLS로 보호된 통신
   ↓
Server

가 된다.

그래서 로그인 정보, Token, API 데이터 등을 인터넷을 통해 전달할 때 HTTPS가 매우 중요하다.


53. URL 하나를 완전히 뜯어보기

다음 URL을 보자.

https://api.example.com:443/users/123?active=true

각 부분은:

https
→ Protocol / Scheme

api.example.com
→ Host

443
→ Port

/users/123
→ Path

active=true
→ Query Parameter

로 볼 수 있다.


54. localhost와 Port

개발하다 보면 다음 주소를 많이 본다.

http://localhost:8080

localhost는 현재 자신의 컴퓨터를 의미한다.

localhost
→ 내 컴퓨터

8080은 Port다.

예를 들어:

localhost:3000
→ Next.js

localhost:8080
→ Spring Boot

localhost:8000
→ FastAPI

localhost:5432
→ PostgreSQL

처럼 하나의 컴퓨터에서 여러 프로그램을 Port로 구분하여 실행할 수 있다.


55. Backend가 알아야 하는 Frontend 핵심 흐름

백엔드 개발자 입장에서 가장 중요한 것은 다음 흐름을 이해하는 것이다.

사용자가 버튼 클릭
        ↓
React Event Handler
        ↓
fetch / axios
        ↓
HTTP Request
        ↓
Spring Controller
        ↓
Service
        ↓
Repository
        ↓
Database
        ↓
Repository
        ↓
Service
        ↓
Controller
        ↓
JSON Response
        ↓
Frontend
        ↓
State 변경
        ↓
화면 다시 Rendering

이 흐름을 이해하면 Frontend와 Backend 사이에서 발생하는 문제를 훨씬 쉽게 찾을 수 있다.


56. Browser 개발자 도구 Network 탭

백엔드 개발자도 브라우저 개발자 도구의 Network 탭을 볼 줄 알아야 한다.

여기서 다음 정보를 확인할 수 있다.

Request URL
Request Method
Status Code
Request Headers
Response Headers
Query Parameters
Request Payload
Response Body
Cookie
요청 시간

예를 들어 Frontend에서:

"백엔드가 이상해요."

라는 문제가 발생했을 때 Network 탭을 보면:

POST /api/login

Status: 401

Response:
{
  "message": "Invalid token"
}

처럼 실제 요청과 응답을 확인할 수 있다.

백엔드 개발에서도 매우 유용하다.


57. 전체 흐름 예시 - 로그인

지금까지 배운 내용을 로그인 하나에 연결해보자.

1. 사용자가 입력

email
password

2. Frontend

fetch("/api/login", {

    method: "POST",

    headers: {
        "Content-Type":
            "application/json"
    },

    body: JSON.stringify({
        email,
        password
    })
});

3. HTTP Request

POST /api/login
Content-Type: application/json

{
  "email": "test@test.com",
  "password": "1234"
}

4. Spring Boot

@PostMapping("/login")
public LoginResponse login(
        @RequestBody LoginRequest request
) {

    return authService.login(request);
}

5. Database 확인

User Repository
      ↓
Database
      ↓
사용자 확인

6. Token 생성

사용자 인증 성공
 ↓
Access Token 생성

7. Response

{
  "accessToken": "eyJ..."
}

8. 이후 API 요청

GET /api/me

Authorization: Bearer eyJ...

Backend가 Token을 검증하고 사용자 정보를 반환한다.


58. 전체 흐름 예시 - 외부 AI API

이번에는 Backend가 외부 API를 호출한다고 해보자.

사용자
 ↓
Next.js
 ↓
POST /api/report
 ↓
Spring Boot
 ↓
외부 AI API

Spring Boot가 외부 API를 호출할 때:

URL

Header
Authorization: Bearer API_KEY

Header
Content-Type: application/json

Body
{
    "input": "분석해주세요"
}

처럼 보낼 수 있다.

외부 API가:

{
  "result": "분석 결과..."
}

를 반환한다.

그러면:

외부 API
 ↓
Spring Boot
 ↓
필요한 데이터 가공/저장
 ↓
Frontend

가 된다.

여기서 API Key는 Backend가 관리한다.

Frontend에 Secret API Key 노출 ❌

Backend
Environment Variable / Secret
에서 관리 ⭕

59. 전체 흐름 예시 - 결제 Webhook

결제는 Webhook을 이해하기 좋은 예다.

Frontend
 ↓
Backend
 ↓
결제 서비스

사용자가 결제를 진행한다.

결제 서비스에서 결제 상태가 확정되면:

결제 서비스

"결제 성공!"

       ↓

POST
https://my-service.com/webhooks/payment

       ↓

내 Backend

Payload:

{
  "event": "PAYMENT_COMPLETED",
  "paymentId": "pay_123"
}

Backend:

@PostMapping("/webhooks/payment")
public ResponseEntity<Void> webhook(
        @RequestBody PaymentWebhook request
) {

    paymentService.complete(
        request.paymentId()
    );

    return ResponseEntity.ok().build();
}

실제 구현에서는 Webhook Signature 검증, 중복 이벤트 처리, 멱등성 등을 함께 고려해야 한다.


60. Webhook에서 멱등성이 중요한 이유

Webhook은 같은 이벤트가 여러 번 전달될 수 있다.

예를 들어:

PAYMENT_COMPLETED
paymentId = 123

이라는 이벤트가 네트워크 문제로 두 번 전달될 수 있다.

Webhook 1
→ 결제 처리

Webhook 2
→ 또 결제 처리?

이렇게 되면 안 된다.

따라서:

eventId 또는 paymentId 확인
        ↓
이미 처리했는가?
   ↓           ↓
 YES           NO
 ↓              ↓
무시          처리

같은 구조가 필요하다.

이런 성질을 Idempotency, 멱등성이라고 한다.


61. API 호출에서 Timeout이 필요한 이유

외부 API가 응답하지 않는다고 해서 영원히 기다릴 수는 없다.

내 Backend
   ↓
외부 API

...
...
응답 없음

그래서 Timeout을 설정한다.

Connection Timeout
→ 연결을 얼마나 기다릴 것인가?

Read Timeout
→ 응답 데이터를 얼마나 기다릴 것인가?

외부 API를 사용하는 Backend에서는 매우 중요한 설정이다.


62. Retry는 무엇인가?

외부 API 호출이 일시적으로 실패했을 때 다시 요청하는 것이다.

API 요청
 ↓
실패

1초 후
 ↓
Retry

또 실패

2초 후
 ↓
Retry

하지만 모든 요청을 무조건 Retry하면 안 된다.

예를 들어 결제 생성 요청을 아무 생각 없이 재시도하면 중복 처리 문제가 발생할 수 있다.

따라서:

Timeout
Retry
Idempotency

를 함께 고려해야 한다.


63. API 문서에서 무엇을 봐야 할까?

처음 보는 API 문서를 보면 최소한 다음을 확인해야 한다.

Base URL

Endpoint

HTTP Method

Path Parameter

Query Parameter

Request Header

Authentication 방식

Request Body

Response Body

Status Code

Rate Limit

Timeout 관련 정보

Webhook 지원 여부

예를 들어:

POST /v1/payments

Authorization:
Bearer API_KEY

Content-Type:
application/json

Body:
{
    "amount": 10000
}

를 보고:

Method = POST
API Key = Header
Data = JSON Body

라고 바로 파악할 수 있어야 한다.


64. OpenAPI와 Swagger

Backend API가 많아지면 API 문서를 관리해야 한다.

OpenAPI는 HTTP API의 구조를 표현하기 위한 명세 형식이다.

예를 들어:

/users/{id}:

  get:

    parameters:

      - name: id
        in: path
        required: true

처럼 API 구조를 표현할 수 있다.

Swagger UI 같은 도구를 이용하면 이를 사람이 보기 편한 API 문서 형태로 제공할 수 있다.

Spring Boot 프로젝트에서도 자주 볼 수 있다.

Backend API
 ↓
OpenAPI Specification
 ↓
Swagger UI
 ↓
API 문서

65. 백엔드 개발자가 반드시 잡아야 할 핵심

웹 개발에서 수많은 기술이 등장하지만 결국 가장 중요한 흐름은 다음이다.

Frontend

HTML
CSS
JavaScript / TypeScript
React / Next.js

        ↓

HTTP

Method
URL
Path Variable
Query Parameter
Header
Body
Cookie

        ↓

Data Format

JSON
XML
Form Data

        ↓

Backend

Spring Boot
FastAPI
Node.js
...

        ↓

Infrastructure

Database
Redis
Kafka
Object Storage
외부 API
AI Service
...

그리고 서버와 서버 사이도 본질적으로 비슷하다.

Spring Boot
     ↓
HTTP + JSON
     ↓
FastAPI

Spring Boot
     ↓
HTTP + JSON + API Key
     ↓
외부 API

결제 서비스
     ↓
HTTP Webhook
     ↓
Spring Boot

66. 최종 정리

HTML

웹페이지의 구조

CSS

웹페이지의 디자인

JavaScript

웹페이지의 동작과 서버 통신

TypeScript

JavaScript + 정적 타입 시스템

XML

구조화된 데이터 표현 형식

JSON

웹 API에서 많이 사용하는 데이터 표현 형식

HTTP

웹에서 Request와 Response를 주고받기 위한 프로토콜

REST

Resource 중심으로 HTTP API를 설계하는 아키텍처 스타일

API Key

API 호출자를 식별하거나
API 접근 권한을 확인하기 위한 키

Polling

클라이언트가 서버에
주기적으로 변경 여부를 질문

Webhook

이벤트가 발생하면
상대 서버가 내 서버를 호출

WebSocket

연결을 유지하면서
양방향 실시간 통신

Frontend

사용자가 직접 보는 화면과 상호작용

Backend

API, 비즈니스 로직, DB,
인증, 외부 서비스 연동 등을 담당

Spring Boot

Java/Kotlin 기반 Backend 프레임워크

FastAPI

Python 기반 API 프레임워크
AI/ML 서비스와 함께 사용하기 편리

67. 가장 중요한 그림 하나로 끝내기

┌──────────────────────────────────┐
│             사용자               │
└────────────────┬─────────────────┘
                 ↓
┌──────────────────────────────────┐
│            Frontend              │
│                                  │
│ HTML                             │
│ CSS                              │
│ JavaScript / TypeScript          │
│ React / Next.js                  │
└────────────────┬─────────────────┘
                 │
                 │ HTTP Request
                 │
                 │ Method
                 │ URL
                 │ Header
                 │ Cookie
                 │ Body(JSON)
                 ↓
┌──────────────────────────────────┐
│             Backend              │
│                                  │
│ Spring Boot                      │
│ FastAPI                          │
│ Node.js                          │
└───────┬────────────┬─────────────┘
        │            │
        ↓            ↓
    Database      External API
                     │
                     │ API Key
                     ↓
                외부 서비스

외부 서비스에서 이벤트 발생
                     │
                     │ Webhook
                     ↓
                  Backend


Frontend가 상태를 계속 확인
                     │
                     │ Polling
                     ↓
                  Backend


실시간 양방향 연결
                     │
                     │ WebSocket
                     ↕
                  Backend

결국 웹 개발의 핵심은 서로 다른 프로그램들이 정해진 규칙으로 데이터를 주고받는 것이다.

Frontend가 TypeScript이고 Backend가 Java이며 AI 서버가 Python이어도 상관없다.

TypeScript
    ↓
HTTP + JSON
    ↓
Java
    ↓
HTTP + JSON
    ↓
Python

각 프로그램이 서로의 내부 구현을 알 필요 없이 HTTP, JSON, API라는 약속을 통해 통신한다.

이 큰 그림을 이해하고 나면 REST API, API Key, Webhook, FastAPI 같은 개념들이 각각 독립적인 기술이 아니라 하나의 웹 시스템을 구성하는 서로 다른 요소라는 것을 이해할 수 있다.

0개의 댓글