Spring MVC 구조

📌 Spring은 MVC 패턴에 프론트 컨트롤러 패턴, 어댑터 패턴이 적용된 구조를 가지고 있다.

  • MVC는 소프트웨어 설계 패턴으로 구축 개념에 가깝다. 당연히 구축 방식은 때에 따라 달라왔고 이를 Spring에서는 통합하여 하나의 템플릿으로 제공한다.

 

MVC 패턴 구조

  1. 요청이 오면 Controller에서 파라미터 정보 확인하여 비지니스 로직을 실행한다.
  2. 비지니스 로직의 결과 Data 를 Model에 담아서 View에 전달해준다.
  3. View는 모델의 Data를 참조하여 화면을 그려준다.

Spring MVC 구조

  • DispatcherServlet : Spring의 프론트(프론트엔드 아님, HTTP 요청의 최전선을 프론트라인이라 함) 컨트롤러
  • View : 인터페이스로 구성되어 있다, 확장성을 가지고 있다.

 

실행순서

  1. Client로 부터 HTTP 요청(Request)을 받는다.
  2. Handler 조회
    • Handler Mapping을 통해 요청 URL에 Mapping된 Handler(Controller)를 조회
  3. Handler를 처리할 Adapter 조회
    • Handler를 처리할 수 있는 Handler Adapter를 조회
  4. Handler Adapter 실행(handle)
    • 알맞은 ****어댑터가 존재한다면 ****Handler Adapter에게 요청을 위임한다.
  5. Handler 실행(호출)
    • Handler Adapter가 실제 Handler(Controller)를 호출하여 실행 및 결과 반환
  6. Model And View 반환(return)
    • Handler Adapter는 Handler가 반환 하는 정보를 ModelAndView 객체로 변환하여 반환
  7. viewResolver 호출(알맞은 View 요청)
    • View Resolver를 찾고 실행
  8. View 반환
    • View Resolver는 View의 논리 이름을 물리 이름으로 전환하는 역할을 수행하고 Rendering 역할을 담당하는 View 객체를 반환
  9. View Rendering
    • View를 통해서 View를 Rendering
더보기

1. Client로부터 HTTP 요청(Request)을 받는다

  • 고객(클라이언트)이 배달 앱에서 음식을 주문합니다. (예: "치킨 1마리 배달 요청")
  • 배달 앱이 이 주문을 **중앙 주문 처리 서버(SPRING MVC)**로 보냅니다.

2. Handler 조회 (Handler Mapping)

  • 서버는 고객이 요청한 **주문 정보(예: 치킨 배달)**를 확인하고, 이 요청을 처리할 적절한 음식점(Handler)을 찾아야 합니다.
  • 여기서 Handler Mapping 주문에 맞는 음식점을 조회하는 과정입니다.
    • 예: 고객이 "치킨"을 주문했으니, 근처의 치킨집을 선택합니다.

3. Handler를 처리할 Adapter 조회

  • 음식점마다 주문을 처리하는 방식(프로세스)이 다를 수 있습니다.
    • 어떤 음식점은 앱을 통해 바로 확인하고,
    • 어떤 음식점은 전화로 주문을 확인해야 합니다.
  • 이 단계에서는 요청을 처리할 수 있는 적절한 **Handler Adapter(음식점과 서버를 연결하는 도구)**를 찾습니다.
    • 예: 치킨집은 앱으로 주문을 확인하는 시스템이 있으니, 앱 기반 주문 어댑터를 선택.

4. Handler Adapter 실행(handle)

  • 적절한 **Handler Adapter(주문 어댑터)**가 음식점에 주문을 전달합니다.
    • 예: 앱이 "치킨 한 마리 주문 요청"을 음식점의 주문 시스템에 보냅니다.

5. Handler 실행(호출)

  • 음식점(Handler)이 실제로 주문을 준비하기 시작합니다.
    • 예: 주방에서 치킨을 튀기고 포장합니다.

6. Model And View 반환(return)

  • 음식점은 준비가 끝난 뒤, "주문이 완료되었습니다!"라는 메시지와 함께 준비된 치킨 데이터를 서버에 보냅니다.
    • 예: "치킨 1마리, 포장 완료!"
    • 여기서 ModelAndView는 이 데이터("치킨 데이터")와 응답 메시지를 함께 묶어서 반환하는 역할을 합니다.

7. View Resolver 호출 (알맞은 View 요청)

  • 서버는 고객에게 응답을 보내기 전에, 결과 데이터를 어떻게 보여줄지 결정합니다.
    • 예: 고객이 앱을 통해 결과를 볼 수 있어야 하므로, 앱 화면(View)을 설정해야 합니다.
  • View Resolver는 "치킨 준비 완료"라는 정보를 앱의 알맞은 화면(예: 주문 완료 페이지)으로 연결합니다.

8. View 반환

  • View Resolver는 "주문 완료 화면"을 앱에 전달합니다.
    • 예: 고객의 앱에 "주문 완료! 배달 중!"이라는 화면이 나타남.

9. View Rendering

  • 고객의 앱에서 실제로 화면이 표시됩니다.
    • 예: 고객은 "주문이 완료되었고, 곧 배달됩니다!"라는 메시지를 화면에서 확인합니다.

결론: 배달 서비스로 비유한 실행 흐름

  1. 고객이 배달 앱에 주문 요청을 보냄 (HTTP 요청)
  2. 서버가 요청을 처리할 음식점을 찾음 (Handler Mapping)
  3. 주문을 전달하는 적절한 방식을 선택 (Handler Adapter 조회)
  4. 음식점이 주문을 준비함 (Handler 실행)
  5. 음식점이 준비 상태를 서버에 반환 (ModelAndView 반환)
  6. 서버가 결과를 앱 화면에 맞게 변환 (View Resolver 호출)
  7. 결과가 앱 화면에 표시됨 (View Rendering)

 

요약

  • DispatcherServlet ( 요청과 응답의 중앙 처리국 )
    1. 클라이언트 HTTP Request를 알맞게 파싱하고 클라이언트에게 알맞은 응답을 반환
    2. 핸들러 목록 정보를 알고있다.
    3. 핸들러 어댑터 목록 정보를 알고있다.
  • HandlerAdapter (부서 담당 연결원)
    1. 자신이 처리할 수 있는 Handler인지 확인할 수 있는 기능(Method)이 필요하다.
    2. 프론트 컨트롤러에서 요청을 위임받았을 때 핸들러에게 요청을 지시하는 기능이 필요하다.
    3. return 시 Handler로부터 전달받은 결과를 알맞은 응답으로 변환한다.
  • Handler (처리자)
    1. 요청에 대한 로직을 수행하는 기능이 필요하다.

 

 

Dispatcher Servlet

📌 모든 HTTP 요청의 진입점으로 작동하는 프론트 컨트롤러(Front Controller)로, 요청 처리의 중앙 허브(총괄), 핸들러 매핑(배정), 핸들러 어댑터 실행(인력 파견), 응답 반환(우편전달)을 다 한다.

  • Spring MVC의 프론트 컨트롤러는 Dispatcher Servlet(Servlet의 한 종류)이다.

  1. Dispatcher Servlet은 HttpServlet을 상속 받아서 사용하고 Servlet의 한 종류이다.
  2. Spring Boot는 Dispatcher Servlet을 서블릿으로 자동으로 등록(내장 Tomcat WAS를 실행하면서 등록한다)하고 모든 URL 경로에 대해서 Dispatcher Servlet을 Mapping 한다. → (urlPatterns=”/”) = 요청이 들어오는 모든 url에 총괄 관리자를 붙인다.
  3. 더 자세한 URL 경로가 높은 우선순위를 가진다. = 요구사항이 자세한 손님부터 처리해 주겠다는 것 = 효율적이라서
    • 개발자가 만들 Servlet이 항상 우선순위가 높아서 실행된다.

 

DispatcherServlet의 service()

  1. Servlet이 호출되면 HttpServlet이 제공하는 service()가 호출된다.
  2. Spring MVC는 DispatcherServlet의 부모인 FrameworkServlet에서 service()를 Override 해두었다.
  3. FrameworkServlet.service()를 시작으로 여러 메서드가 호출됨과 동시에 가장 중요한DispatcherServlet.doDispatch()가 호출된다.

protected void doDispatch() {
...
// 1. 핸들러 조회
	mappedHandler = getHandler(processedRequest); 
	if (mappedHandler == null) {
		noHandlerFound(processedRequest, response); // NotFound 404
	}

// 2. 핸들러 어댑터 조회 : 핸들러를 처리할 수 있는 어댑터
	HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

// 3. 핸들러 어댑터 실행
// 4. 핸들러 어댑터를 통해 핸들러 실행 
// 5. ModelAndView 반환 
	mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 여기 안에서 render   
	processDispatchResult(processedRequest, response, mappedHandler, mv,dispatchException);
	...
}


// processDispatchResult()
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
			@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
			@Nullable Exception exception) throws Exception {

		if (mv != null && !mv.wasCleared()) {
			// View Render 호출
			render(mv, request, response);
			if (errorView) {
				WebUtils.clearErrorRequestAttributes(request);
			}
		}
}

// render()
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
	View view;
	String viewName = mv.getViewName();

// 6. ViewResolver를 통해 View 조회
// 7. View 반환
	view = resolveViewName(viewName, mv.getModelInternal(), locale, request);

// 8. View Rendering
	view.render(mv.getModelInternal(), request, response);
}

 

 

 

Spring MVC의 주요 Interface

📌 Spring MVC는 DispatcherServlet 코드의 변경 없이 기능변경 및 확장이 가능하다. 기능들이 대부분 Interface로 만들어져 있기 때문이다.

  • 이쯤에서 한번 더 짚고 넘어가면 왜 대부분이 클래스가 아니라 인터페이스로 구현되어 있냐는 질문엔, 다형을 위해서가 정답이다.
  • org.springframework.web.servlet
    1. HandlerMapping
    2. HandlerAdapter
    3. ViewResolver
    4. View
  • 당연히 이 모든 인터페이스를 알 필요는 없다. 하지만 자주 사용하는 인터페이스에 대해서는 잘 알아야 확장이나 구현, 문제 해결에 있어 용이하다.

 

Controller Interface

📌Spring 2.5 이전에 모든 컨트롤러가 구현해야 했던 표준 인터페이스입니다. 이 인터페이스는 클라이언트의 요청을 처리하고, 결과를 View로 전달하는 기본적인 방법을 정의합니다.

  • Controller Interface를 implements 하여 구현하게되면 개발자가 원하는 Controller(Handler)를 사용할 수 있게됩니다.
  • 추후 강의에 등장할 현대에 사용하는 Annotation 기반 Spring의 @Controller와는 역할이 비슷하지만 연관은 없습니다.
package com.example.springbasicmvc.controller;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

// Spring Bean 이름을 URL로 설정
@Component("/example-controller")
public class ExampleController implements Controller {

    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("example-controller가 호출 되었습니다.");
        return null;
    }
}
  • http://localhost:8080/example-controller 로 HTTP 요청을 하게 되면 응답결과가 반환된다.

  • 출력 결과

 

  • @Component
    • Spring Bean에 등록하는 역할을 수행한다.
      • Spring Bean은 애플리케이션의 구성 요소를 정의하는 객체이다.
      • 마치 Servlet이 Servlet Container에 등록되는 것과 같다.

 

 

  1. Handler Mapping
    1. 핸들러 매핑에서 ExampleController( Spring 애플리케이션에서 특정 요청을 처리하는 컨트롤러 클래스)를 찾을 수 있어야 한다.
    → Spring Bean의 이름으로 핸들러를 찾을 수 있는 핸들러 매핑이 필요하다.
  2. Handler Adapter
    1. Handler Mapping을 통해 찾은 핸들러를 실행할 수 있는 Handler Adapter가 필요
    → Controller Interface를 실행할 수 있는 Handler Adapter를 찾고 실행한다.
  • 놀랍게도 Handler Mapping은 찾기만 하고 Handler Adapter가 Handler에게 배치해줘야 한다.
  • 유지보수와 확장성에 용이하다...

 

Spring Boot의 Handler Mapping, Handler Adapter

📌 Spring Boot를 사용하면 개발에 필요하여 자동으로 등록되는 HandlerMapping과 HandlerAdapter들이 있다.

  • HandlerMapping, HandlerAdapter 모두 우선순위대로 조회한다.

 

  • HandlerMapping
    • 우선순위 순서
    1. RequestMappingHandlerMapping
      • 우선순위가 가장 높다
      • Annotation 기반 Controller의 @RequestMapping에 사용
    2. BeanNameUrlHandlerMapping(위 예시코드에 사용)
      • Spring Bean Name으로 HandlerMapping
  • HandlerAdapter
    • 우선순위 순서
    1. RequestMappingHandlerAdapter
      • Annotation 기반 Controller의 @RequestMapping에서 사용
    2. HttpRequestHandlerAdapter
      • HttpRequestHandler 처리
    3. SimpleControllerHandlerAdapter(위 예시코드에 사용)
      • Controller Interface 처리

 

@RequestMapping 은 가장 높은 우선순위의 HandlerMapping인 RequestMappingHandlerMapping 과 가장 높은 우선순위의 HandlerAdapter인 RequestMappingHandlerAdapter 두가지를 사용하며 현대에 사용하는 Annotation 기반의 컨트롤러를 지원한다.

 

HttpRequestHandler로 알아보는 Spring MVC 동작 순서

// 인터페이스
public interface HttpRequestHandler {
	void handleRequest(HttpServletRequest request, HttpServletResponse response)
					throws ServletException, IOException;

}

 

// 구현체
@Component("/request-handler")
public class ExampleRequestHandler implements HttpRequestHandler {

	@Override
	public void handleRequest(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
		System.out.println("request-handler Controller 호출");
		// 구현 로직
	}

}

Postman

출력결과

 

 

실행순서

  1. HandlerMapping 으로 핸들러 조회
    1. BeanName으로 Handler 조회(BeanNameUrlHandlerMapping 실행)
    2. ExampleRequestHandler 반환
  2. HandlerAdapter 조회
    1. HandleAdapter의 supports()를 우선순위 순서대로 호출
    2. HttpRequestHandlerAdapter가 HttpRequestHandler Interface를 지원한다
    • HttpRequestHandlerAdapter.supports()

  1. HandlerAdapter 실행
    1. DispatcherServlet이 조회한 HttpRequestHandlerAdapter를 실행하며 Handler 정보도 넘긴다
    2. HttpRequestHandlerAdapter 는 ExampleRequestHandler를 내부에서 실행 후 결과를 반환
    • HttpRequestHandlerAdapter.handle() → 단순히 handleRequest를 호출한다 = 오버라이딩된 handleRequest() 호출

 

DispatcherServlet에서 호출 → ha.handle()

 

 

 

View Resolver

📌 컨트롤러가 반환한 뷰 이름(View Name)을 실제 뷰 파일의 경로(View Path)로 변환하고, 클라이언트에게 응답할 화면(View)을 렌더링할 수 있도록 도와주는 컴포넌트입니다.

  • 반환된 ModelAndView 객체를 알맞은 View로 전달하기 위해 DispatcherServlet에서 ViewResolver를 호출하여 View 정보를 설정하는 역할을 수행한다.
  • 서버는 HTML 파일(또는 다른 뷰 파일)을 뷰(View)로 변환하여 클라이언트에게 응답으로 보낸다.는 말
package com.example.springbasicmvc.controller;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

// Spring Bean 이름을 URL로 설정
@Component("/view-controller")
public class ViewController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {

        System.out.println("view-controller가 호출 되었습니다.");

        // "test"는 논리적인 ViewName이다. ViewResolver가 물리적인 이름으로 변환해야 한다.
        return new ModelAndView("test");
    }
}
  • Template Engine JSP
    • webapp/WEB-INF/form.JSP

 

[sql입니다]
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <meta charset="UTF-8">
  <title>블로그 포스트 작성 페이지</title>
</head>
<body>
<h1>블로그 글쓰기</h1>
<form action="save" method="post">
  title: <input type="text" name="title" placeholder="제목" />
  content: <input type="text" name="content" placeholder="내용" />
  <button type="submit">저장</button>
</form>

</body>
</html>
  • ViewResolver
    • application.properties 설정
    • 설정을 기반으로 Spring Boot가 InternalResourceViewResolver 를 만든다.
[xml입니다]
spirng.mvc.view.prefix=/WEB-INF/views/
spirng.mvc.view.suffix=.jsp

 

localhost:8080/view-controller 호출

 

  • ViewName으로 View를 찾지 못하는 경우(View가 존재하지 않음)
@Component("/error-controller")
public class WhitelabelErrorController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("error-controller가 호출 되었습니다.");
				// viewName "sparta"는 존재하지 않는다.
        return new ModelAndView("sparta");
    }
}

 

  • 컨트롤러는 호출되지만 View를 못 찾아 Whitelabel Error Page를 응답한다.

 

 

 

Spring Boot의 ViewResolver

📌 Spring Boot를 사용하면 개발에 필요하여 자동으로 등록되는 ViewResolver들이 있다.

 

  • 우선순위 순서
    • 아래 두 가지 이외에도 많은 ViewResolver가 존재한다.
    1. BeanNameViewResolver
      1. Bean Name으로 View를 찾아 반환
    2. InternalResourceViewResolver(위 예시코드)
      1. application.properties 설정 파일에 등록한 prefix, suffix 설정 정보를 사용하여 ViewResolver 등록
// 아래 코드를 자동으로 해주는것과 마찬가지이다.
@Bean
InternalResourceViewResolver internalResourceViewResolver() {
	return new InternalResourceViewResolver("/WEB-INF/views", ".jsp");
}

 

 

InternalResourceViewResolver로 알아보는 Spring MVC 동작 순서

  1. HandlerAdapter 호출
    • HandlerAdapter를 통해 “test” 논리 View Name 얻음
  2. ViewResolver 호출
    • ”test” 이라는 View Name으로 viewResolver를 우선순위 대로 호출
      • BeanNameViewResolver는 View를 찾지 못한다.
      • InternalResourceViewResolver 호출
  3. InternalResourceViewResolver
    • InternalResourceViewResolver.buildView(String viewName)
    InternalResourceView 반환

 

4. InternalResourceView

  • JSP와 같이 서버에서 이동하는 forward()를 호출하는 경우와 같을 때 사용한다.

 

renderMergedOutputModel() → Model을 Request로 바꾼다.

 

5. view.render()

  • 외부에서 view.render()를 호출 후 ****RequestDispatcher를 가져와 forward()한다.

→ 매우 복잡한 구조를 가지고 있으니 모두 찾아볼 필요가 없습니다.

 

Thymeleaf는 View와 Resolver가 이미 존재한다. 라이브러리 의존성만 추가해주면 SpringBoot가 모두 자동으로 해준다. 즉, return “viewName”; 만으로 View가 Rendering 된다.

 

 

 

 

 

 

 

 

 

'Back-End (Web) > Spring' 카테고리의 다른 글

[Spring] Spring Framework  (2) 2026.08.26
[Spring] Spring 웹 애플리케이션 계층 구조  (2) 2026.04.10
[Spring] 스프링 웹 개발 기초  (0) 2026.04.02
API 예외처리  (0) 2025.12.27
fetch join  (1) 2025.01.21

Spring Framework

📌 Java Application Framework로 엔터프라이즈 애플리케이션 개발에 주로 사용된다.

  • 엔터프라이즈 애플리케이션은 대규모로 복잡한 비즈니스 프로세스와 데이터를 처리하는 애플리케이션을 뜻한다.
  • IoC (Inversion of Control), AOP (Aspect-Oriented Programming), DI (Dependency Injection) 등의 개념을 바탕으로 개발되었으며, 이를 통해 애플리케이션의 구조를 유연하고 모듈화하여 유지보수성을 높이고, 복잡한 엔터프라이즈 애플리케이션 개발을 더 간단하게 만들어 줍니다.

Spring Framework로 만드는 Web Application 라면 : Java 냄비 : Spring

[1]  Spring Framework 특징

애플리케이션의 다양한 구성 요소를 유연하게 연결하고 관리할 수 있도록 해준다.

  • Spring Framework는 누구나 사용할 수 있는 오픈소스 이다.
  • 모듈화되어 있어 필요에 따라 특정 기능만 선택적으로 사용할 수 있다.
  • Java언어의 가장 큰 특징인 객체 지향 언어의 특징을 살려낸 프레임워크이다.
    • 캡슐화
    • 상속
    • 추상화
    • 다형성

 

[2]  Spring의 구조

Spring Framework는 여러 모듈로 구성되어 있으며, 각 모듈은 특정 목적에 맞는 기능을 제공합니다. 주요 모듈은 다음과 같습니다:

  1. Core Container:
    • Core: Spring의 핵심 기능인 IoC (Inversion of Control) 및 DI (Dependency Injection)를 제공.
    • Beans: 객체 생성 및 관리.
    • Context: Spring의 애플리케이션 컨텍스트 기능을 제공, 이벤트 관리와 같은 다양한 기능 포함.
    • Spring AOP: AOP 기능을 제공하여, 메서드 호출 전후의 동작을 정의.
  2. Data Access/Integration:
    • JDBC: 데이터베이스와의 상호작용을 쉽게 할 수 있도록 지원.
    • ORM: Hibernate, JPA 등 객체-관계 매핑을 처리.
    • JMS: Java 메시지 서비스 (JMS)를 지원하여 메시지 기반 애플리케이션 구현.
  3. Web:
    • Spring MVC: 웹 애플리케이션을 위한 모델-뷰-컨트롤러 패턴을 지원.
    • WebSocket: 실시간 통신을 위한 WebSocket 지원.
    • WebFlux: 반응형 프로그래밍 모델을 기반으로 한 웹 프레임워크.
  4. Security:
    • 인증, 권한 부여 및 다양한 보안 관련 기능을 제공합니다.
  5. Testing:
    • Spring Test 모듈은 Spring 애플리케이션을 테스트하는 데 필요한 다양한 유틸리티를 제공합니다. @SpringBootTest 등을 통해 통합 테스트를 쉽게 할 수 있습니다.

 

[3]  Spring Framework의 주요 특징

1. IoC (Inversion of Control) / DI (Dependency Injection)

  • Spring은 객체를 직접 생성하는 대신, IoC 컨테이너를 통해 객체를 관리합니다. 객체 간의 의존 관계를 DI 방식으로 해결하여, 애플리케이션의 결합도를 낮추고 유연성을 높입니다.
  • 예를 들어, 하나의 클래스가 다른 클래스에 의존할 때, 이를 자동으로 주입해주는 방식입니다.
@Component
public class Service {
    private final Repository repository;

    @Autowired  // Repository를 자동으로 주입
    public Service(Repository repository) {
        this.repository = repository;
    }
}

 

2. AOP (Aspect-Oriented Programming)

  • AOP는 관점 지향 프로그래밍으로, 핵심 비즈니스 로직과 공통 기능(로깅, 트랜잭션 관리 등)을 분리하여 개발할 수 있게 도와줍니다. 이로 인해 코드가 더 깔끔해지고 재사용성이 증가합니다.
  • Spring에서는 AOP를 이용해 메서드 호출 전후에 특정 처리를 추가할 수 있습니다.
@Aspect
@Component
public class LoggingAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("Method called: " + joinPoint.getSignature().getName());
    }
}

 

 

3. 모듈화

  • Spring은 여러 개의 모듈로 구성되어 있어 필요한 기능만 선택적으로 사용할 수 있습니다. 예를 들어, Spring Data, Spring Security, Spring Web 등 다양한 서브모듈을 통해 애플리케이션의 요구에 맞는 기능을 추가할 수 있습니다.

4. 트랜잭션 관리

  • Spring은 선언적 트랜잭션 관리 기능을 제공하여, 비즈니스 로직에서 트랜잭션을 쉽게 관리할 수 있도록 도와줍니다. @Transactional 어노테이션을 사용해 메서드 또는 클래스 수준에서 트랜잭션을 자동으로 관리할 수 있습니다.

 

@Transactional
public void transferMoney(Account fromAccount, Account toAccount, double amount) {
    // 돈 이체 처리 로직
}

 

5. Spring MVC

  • Spring MVC는 웹 애플리케이션을 위한 모델-뷰-컨트롤러(MVC) 프레임워크입니다. 요청을 처리하고, 뷰를 렌더링하며, 사용자 인터페이스를 구축하는 데 필요한 기능을 제공합니다.
  • Spring MVC는 RESTful API 개발도 지원하여, REST 기반의 웹 서비스를 쉽게 구축할 수 있습니다.
@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello() {
        return "Hello, World!";
    }
}

 

6. Spring Boot

  • Spring Boot는 Spring Framework의 복잡성을 줄여주는 자동 설정내장 서버를 제공합니다. 이를 통해 설정을 최소화하고, 독립 실행형 애플리케이션을 쉽게 만들 수 있습니다. Spring Boot는 Spring Cloud와 결합하여 마이크로서비스 아키텍처를 쉽게 구현할 수 있습니다.
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

 

7. Spring Security

  • Spring Security는 인증(Authentication)과 권한 부여(Authorization)를 처리하는 프레임워크로, 웹 애플리케이션에 필요한 보안 기능을 제공합니다. 로그인, 로그아웃, CSRF 방어, 권한 체크 등의 기능을 손쉽게 설정할 수 있습니다.

 

8. Spring Data

  • Spring Data는 데이터베이스와의 상호작용을 단순화하는 데 도움을 줍니다. 특히 JPA(Java Persistence API)를 사용하여 관계형 데이터베이스와의 통합을 돕고, CRUD 작업을 자동화합니다.
public interface PersonRepository extends JpaRepository<Person, Long> {
    List<Person> findByLastName(String lastName);
}

 

 

9. Spring Batch

  • Spring Batch는 대용량 데이터 처리 및 배치 작업을 처리하기 위한 프레임워크입니다. 데이터를 읽고, 처리하고, 쓰는 작업을 효율적으로 처리할 수 있도록 도와줍니다.

 

10. Spring Cloud

  • Spring Cloud는 마이크로서비스 아키텍처를 지원하는 다양한 도구를 제공합니다. 예를 들어, 서비스 디스커버리, 분산 설정 관리, API 게이트웨이, 회로 차단기 패턴 등을 지원합니다.

 

IoC (Inversion of Control) 객체 생성 및 의존성 관리(Dependency Injection)를 통해 애플리케이션의 결합도를 낮추고 유연성 제공
DI (Dependency Injection) 객체 간의 의존 관계를 자동으로 주입하여 코드의 유지보수성과 테스트 용이성 향상
AOP (Aspect-Oriented Programming) 공통 관심사를 분리하여 코드 재사용성을 높이고 비즈니스 로직과 분리된 처리 가능 (예: 트랜잭션 관리, 로깅)
모듈화 필요한 모듈만 선택적으로 사용할 수 있어 애플리케이션의 크기와 복잡도를 줄임
Spring MVC 웹 애플리케이션을 위한 모델-뷰-컨트롤러(MVC) 패턴 지원, RESTful API 개발 가능
Spring Boot 자동 설정과 내장 서버를 제공하여 설정을 간소화하고 독립 실행형 애플리케이션을 쉽게 만들 수 있음
트랜잭션 관리 선언적 트랜잭션 관리 지원, @Transactional 어노테이션을 통해 트랜잭션을 쉽게 처리
Spring Security 인증 및 권한 부여를 처리하며, 웹 애플리케이션의 보안을 쉽게 설정할 수 있음
Spring Data 데이터베이스와의 상호작용을 단순화하며, JPA, Hibernate와의 통합을 지원
Spring Batch 대용량 배치 작업 처리 지원, 데이터를 읽고 쓰는 배치 작업을 효율적으로 처리할 수 있음
Spring Cloud 마이크로서비스 아키텍처 지원, 서비스 디스커버리, API 게이트웨이 등 분산 시스템 구축에 필요한 도구 제공
강력한 커뮤니티 활발한 오픈소스 프로젝트로, 커뮤니티와의 상호작용을 통해 지속적으로 발전
유연성 다양한 기술과 쉽게 통합 가능, 애플리케이션 아키텍처에 맞게 확장 가능

 

[4]  Spring Framework 사용 시 장점:

  • 유연성: 다양한 기술과 쉽게 통합할 수 있으며, 다양한 애플리케이션 아키텍처에 맞게 확장 가능합니다.
  • 모듈화: 필요한 기능만 선택하여 사용할 수 있습니다.
  • 표준화: 널리 사용되는 표준을 기반으로 구축되어 있으며, 많은 라이브러리 및 프레임워크와 호환됩니다.
  • 강력한 커뮤니티: Spring은 활발한 오픈소스 프로젝트로, 커뮤니티와의 상호작용을 통해 지속적으로 발전합니다.

 

[5]  Spring Framework 사용 시 고려할 점:

  • 학습 곡선: 많은 기능이 포함되어 있어 초보자에게는 다소 복잡할 수 있습니다.
  • 구성 파일: 초기 설정이 다소 복잡할 수 있지만, Spring Boot로 자동 설정을 사용할 수 있습니다.

Spring Framework는 엔터프라이즈 애플리케이션을 위한 강력한 솔루션을 제공하며, 다양한 기능을 활용하여 효율적인 개발을 할 수 있도록 돕습니다.

 

 

'Back-End (Web) > Spring' 카테고리의 다른 글

[Spring] Spring MVC 패턴  (1) 2026.09.03
[Spring] Spring 웹 애플리케이션 계층 구조  (2) 2026.04.10
[Spring] 스프링 웹 개발 기초  (0) 2026.04.02
API 예외처리  (0) 2025.12.27
fetch join  (1) 2025.01.21

Annotation

📌 코드에 메타데이터를 추가할 수 있는 기능을 제공하며 주로 코드에 특별한 의미를 부여하거나, 컴파일러와 런타임에 특정 동작을 트리거하기 위해 사용된다.

  • 어노테이션은 코드에서 직접적인 로직 실행에 영향을 미치지 않지만, 코드의 의미를 설명하거나 추가적인 처리를 위해 사용됩니다.
  • "명함"를 생각하면 편하다. 이 명함은 "사람"에서 "프로그래머인 사람"이 된다. 사람이라는 정체성은 그대로이지만, 이 사람의 용도를 알 수 있다. 코드의 용도를 표시하며 실제로 컴파일러도 그 의미를 알지만 프로그램(사람) 자체에는 변화가 없다.

[1]  어노테이션 정의

  • 어노테이션은 @ 기호로 시작하며, 클래스, 메서드, 변수, 매개변수, 패키지 등에 추가할 수 있다.

[2]  내장 어노테이션

  • @Override
    • 메서드가 상위 클래스나 인터페이스의 메서드를 오버라이드하고 있음을 나타낸다.
      • 이때 컴파일러는 메서드가 실제로 오버라이드하고 있는지 확인한다.
  • @Deprecated
    • 해당 요소가 더 이상 사용되지 않음을 나타낸다.
    • 해당 어노테이션이 붙은 코드를 사용하면 컴파일 경고가 발생한다.
  • @SuppressWarnings
    • 컴파일러 경고를 억제한다.
      • 사용되지 않는 변수에 대한 경고를 무시할 수 있다.

[3]  사용자 정의 어노테이션

  • 개발자가 필요에 따라 직접 어노테이션을 정의할 수 있다.
  • 사용자 정의 어노테이션은 특정 메타데이터를 추가하거나,
  • AOP(Aspect-Oriented Programming) 같은 기술과 결합하여 다양한 기능을 구현할 수 있다.
    • AOP는 심화 주차에 배울 내용

 

Lombok

📌 Java에서 반복적인 코드를 줄여주는 라이브러리로, 코드의 가독성과 유지보수성을 높이는 데 도움이 됩니다. 주로 getter, setter, toString, equals, hashCode 메서드와 같은 보일러플레이트 코드를 자동으로 생성해줍니다.

 

[1]  Lombok 사용 시 장점:

  • 보일러플레이트 코드 감소: Lombok은 반복적인 코드(예: getter, setter, 생성자 등)를 자동으로 생성해 주어 코드가 간결해집니다.
  • 코드의 가독성 향상: 중요한 로직에 집중할 수 있어 코드가 더 깔끔하고 이해하기 쉬워집니다.
  • 생산성 향상: 반복적인 코드 작성에 소모되는 시간을 절약할 수 있습니다.

 

[2]   Lombok 사용 시 단점:

  • 자동 생성된 코드의 가시성 부족: Lombok은 컴파일 시 코드 생성이 이루어지기 때문에, IDE에서 코드가 어떻게 처리되는지 확인하기 어려운 경우가 있습니다.
  • 디버깅 어려움: Lombok이 생성한 코드는 실제로 파일에 존재하지 않기 때문에, 디버깅 시 자동으로 생성된 메서드를 추적하는 데 어려움이 있을 수 있습니다.

 

@Getter, @Setter

  • 클래스의 모든 필드에 대한 getter와 setter 메서드를 자동으로 생성한다.
  • 예시 코드
@Getter
@Setter
public class User {
    private String name;
    private int age;
  
  /** 아래 코드를 @Getter, @Setter 어노테이션이 생성해준다.
    public String getName() {
	    return name;
    }

    public void setName(String name) {
	    this.name = name;
    }
    
    public int getAge() {
	    return age;
    }

    public void setAge(int age) {
	    this.age = age;
    }
    **/
}

위 코드에서 getName(), setName(String name), getAge(), setAge(int age) 메서드가 자동으로 생성된다.



@ToString

  • 객체의 toString() 메서드를 자동으로 생성한다.
  • 기본적으로 클래스의 모든 필드를 포함하며, 특정 필드를 제외하거나 포맷을 지정할 수도 있다.
  • 예시코드
@ToString
public class User {
    private String name;
    private int age;
}
  • toString() 메서드는 객체를 String으로 변환해주는 역할을 수행한다.

@EqualsAndHashCode

  • equals()와 hashCode() 메서드를 자동으로 생성한다.
  • 객체의 동일성과 해시 코드를 정의하는데 사용된다.
  • 예시 코드
@EqualsAndHashCode
public class User {
    private String name;
    private int age;
}

 


 

@NoArgsConstructor, @AllArgsConstructor, @RequiredArgsConstructor

  • 기본 생성자를 생성한다.
  • 모든 필드를 매개변수로 하는 생성자를 생성한다.
  • 필수(final) 필드만을 매개변수로 하는 생성자를 자동으로 생성한다.
  • 예시 코드
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private String name;
    private int age;
}

 

@Data

  • @Getter, @Setter, @ToString, @EqualsAndHashCode,@RequiredArgsConstructor를 한꺼번에 적용하는 어노테이션이다.
  • 주로 테스트 용도로 사용한다.
  • 예시 코드
@Data
public class User {
    private String name;
    private int age;
}

@Builder

  • 빌더 패턴을 적용해 객체를 생성할 수 있게 합니다. 복잡한 객체 생성에 유용하며, 필드 이름을 명시적으로 지정하면서 객체를 생성할 수 있다.
  • 예시 코드
@Builder
public class User {
    private String name;
    private int age;
}
  • 사용 예시
User user = User.builder()
                .name("John")
                .age(30)
                .build();

@Slf4j

  • 클래스에 로그를 남기기 위한 Logger 객체를 자동으로 생성한다.
  • 예시 코드
@Slf4j
public class UserService {
    public void logMessage() {
        log.info("This is a log message");
    }
}

 

Rendering

📌 웹 애플리케이션에서 콘텐츠를 화면에 표시하는 과정을 의미합니다. 이 과정은 주로 웹 브라우저에서 일어나며, HTML, CSS, JavaScript 코드가 결합되어 최종적으로 사용자가 볼 수 있는 페이지로 변환됩니다.

 

[1]  렌더링의 주요 과정

  1. HTML 파싱 (Parsing):
    • 브라우저가 웹 페이지를 로드하면 먼저 HTML 파일을 받아들입니다. 이 HTML 파일은 **DOM(Document Object Model)**으로 변환됩니다. DOM은 웹 페이지의 구조를 트리 형태로 나타내는 객체입니다.
  2. CSS 파싱:
    • HTML이 파싱되면서 CSS 파일도 함께 로드됩니다. CSS 파일은 페이지의 스타일을 정의하며, 이 스타일은 HTML 요소에 적용되어 화면에 표시됩니다. CSS는 **CSSOM(CSS Object Model)**이라는 객체 모델로 변환됩니다.
  3. 렌더 트리 생성:
    • DOM과 CSSOM이 결합되어 **렌더 트리(Render Tree)**가 만들어집니다. 렌더 트리는 화면에 실제로 표시할 요소들만 포함됩니다. 예를 들어, display: none이 설정된 요소는 렌더 트리에 포함되지 않습니다.
  4. 레이아웃(Layout):
    • 렌더 트리가 만들어지면, 각 요소의 정확한 위치와 크기를 계산하는 레이아웃 단계가 진행됩니다. 이 과정에서 각 요소가 페이지 상에서 차지할 공간을 결정합니다.
  5. 페인팅(Painting):
    • 레이아웃이 완료되면 각 요소를 실제 화면에 그리는 페인팅 단계가 시작됩니다. 이 단계에서는 색상, 텍스트, 이미지 등 시각적 요소가 화면에 그려집니다.
  6. 합성(Compositing):
    • 페이지가 여러 레이어로 구성된 경우, 각 레이어가 화면에 어떻게 합성될지를 결정하는 단계입니다. 예를 들어, 애니메이션이나 CSS 트랜지션을 포함한 요소들이 각기 다른 레이어에 배치될 수 있습니다.

[2]  렌더링의 종류

  1. 서버 사이드 렌더링 (SSR, Server-Side Rendering):
    • 서버에서 HTML을 렌더링하고 클라이언트에게 전달하는 방식입니다. 클라이언트는 서버에서 이미 완성된 HTML을 받게 되므로 페이지가 더 빨리 렌더링됩니다. 검색 엔진 최적화(SEO)에도 유리합니다.
  2. 클라이언트 사이드 렌더링 (CSR, Client-Side Rendering):
    • JavaScript가 클라이언트에서 HTML을 렌더링하는 방식입니다. 초기 로딩 시 서버에서 최소한의 HTML만 제공하고, 클라이언트에서 JavaScript가 실행되어 동적으로 콘텐츠를 로드하고 표시합니다.
  3. 하이브리드 렌더링:
    • SSR과 CSR을 결합한 방식으로, 초기 페이지를 서버에서 렌더링하고, 이후 동적인 콘텐츠는 클라이언트에서 렌더링하는 방식입니다. React의 Hydration 기법이 대표적인 예입니다.

[3]  렌더링 성능 최적화

  1. Lazy Loading (지연 로딩):
    • 페이지의 필요한 부분만 먼저 렌더링하고, 나머지 부분은 사용자가 필요할 때 로드하는 방식입니다. 이는 초기 로딩 시간을 줄이는 데 유용합니다.
  2. Critical CSS:
    • 페이지 렌더링에 필요한 최소한의 CSS만 먼저 로드하고, 나머지는 비동기적으로 로드하는 방식입니다. 이렇게 하면 페이지 렌더링 속도가 빨라집니다.
  3. Render Blocking 리소스 최적화:
    • JavaScript나 CSS가 페이지 렌더링을 차단하지 않도록 비동기 로딩하거나 async 또는 defer 속성을 활용하는 방식입니다.
  4. Request Animation Frame (RAF):
    • JavaScript 애니메이션을 최적화하는 기법으로, 화면 리프레시 주기와 맞추어 애니메이션을 실행하여 성능을 최적화합니다.

[4]  렌더링과 관련된 주요 용어

  • Reflow: DOM 요소의 크기나 위치가 변경될 때 레이아웃을 다시 계산하는 과정입니다. 이는 성능에 큰 영향을 줄 수 있습니다.
  • Repaint: 요소의 스타일이 변경되어 화면을 다시 그리는 과정입니다. 스타일만 변경되었을 때는 레이아웃을 재계산하지 않고 화면을 다시 그리기만 합니다.

[5]  렌더링 과정에서의 최적화

  • 렌더링 차단 리소스 최소화: CSS나 JavaScript와 같은 리소스가 렌더링을 차단하지 않도록 최적화합니다.
  • 이미지 최적화: 이미지를 압축하거나 적절한 포맷을 사용하여 로딩 시간을 줄이고 렌더링 성능을 향상시킵니다.
  • DOM 최소화: DOM의 크기를 최소화하고, 불필요한 DOM 업데이트를 피하는 것이 렌더링 성능에 도움이 됩니다.

 

 

SSR(Server Side Rendering)

📌 웹 애플리케이션에서 서버가 HTML을 생성하여 클라이언트에 전달하는 방식입니다. 즉, 클라이언트가 웹 페이지를 요청하면, 서버에서 HTML을 미리 렌더링하고 완성된 페이지를 클라이언트에 전달하는 방식입니다.

 

  1. 서버(WAS)에 HTML을 요청한다.
  2. 서버(WAS)에서 로직을 거친 후 DB를 조회한다.
  3. 조회 결과를 기반으로 HTML을 동적으로 생성한다.
  4. 생성된 HTML을 응답한다.

 

[1]  SSR의 개념

  • **서버 사이드 렌더링 (SSR)**은 클라이언트가 웹 페이지를 요청할 때, 서버에서 HTML을 미리 렌더링하여 클라이언트에게 전달하는 방식입니다.
  • 클라이언트는 서버에서 전달받은 완성된 HTML을 바로 표시하며, 이후 JavaScript가 추가적으로 실행되어 페이지를 동적으로 업데이트하는 방식으로 동작합니다.

[2]  SSR의 작동 원리

  1. 클라이언트 요청: 사용자가 웹 브라우저에서 페이지를 요청합니다.
  2. 서버 렌더링: 서버는 요청된 URL에 해당하는 페이지를 서버 측에서 미리 렌더링하여 완성된 HTML을 생성합니다.
  3. HTML 전달: 생성된 HTML 페이지를 클라이언트로 전달합니다.
  4. 브라우저 표시: 클라이언트는 서버로부터 받은 HTML을 즉시 렌더링하고 화면에 표시합니다.
  5. JavaScript 실행: 페이지가 로드된 후, 클라이언트는 JavaScript를 실행하여 페이지에 동적인 요소를 추가하고, 인터랙티브한 기능을 활성화합니다.

[3]  SSR의 장점

  1. 빠른 초기 로딩:
    • 서버에서 미리 렌더링된 HTML을 클라이언트에 전달하기 때문에, 초기 페이지 로딩 속도가 매우 빠릅니다. 사용자가 페이지를 요청할 때 빠르게 내용을 볼 수 있습니다.
  2. SEO(검색 엔진 최적화):
    • 서버에서 완성된 HTML을 제공하므로 검색 엔진 크롤러가 페이지의 콘텐츠를 쉽게 읽을 수 있습니다. 이는 SEO에 유리한 점으로, 검색 엔진에서 페이지를 더 잘 인식하고 인덱싱할 수 있습니다.
  3. 더 나은 사용자 경험:
    • 초기 페이지가 빠르게 렌더링되기 때문에, 사용자는 페이지를 더 빨리 볼 수 있으며, **사용자 경험(UX)**이 향상됩니다.
  4. 프로그레시브 웹 앱(PWA):
    • SSR은 클라이언트가 JavaScript를 사용할 수 없더라도 서버에서 완전한 페이지를 렌더링하여 사용자에게 표시할 수 있기 때문에, **PWA(프로그레시브 웹 앱)**에도 유용합니다.

[4]  SSR의 단점

  1. 서버 부하:
    • 모든 페이지 렌더링을 서버에서 처리해야 하므로, 서버에 부하가 증가할 수 있습니다. 특히 트래픽이 많은 웹 애플리케이션에서는 서버의 성능 저하가 발생할 수 있습니다.
  2. 느린 동적 인터페이스:
    • 초기 렌더링 후 동적인 기능을 추가하기 위해 JavaScript가 로드되고 실행되어야 하므로, 초기 화면은 빠르게 렌더링되지만 상호작용성은 JavaScript가 실행된 후에 활성화됩니다.
  3. 상태 관리:
    • 서버 측에서 렌더링된 페이지는 클라이언트의 상태를 유지하는 데 어려움이 있을 수 있습니다. 서버와 클라이언트 간의 상태 동기화가 필요할 수 있습니다.

[5]  SSR 사용 사례

  1. 블로그 및 뉴스 사이트:
    • 검색 엔진 최적화(SEO)가 중요한 블로그나 뉴스 사이트에서는 SSR을 사용하여 빠르게 검색 결과에 노출되도록 할 수 있습니다.
  2. 쇼핑몰 사이트:
    • 초기 제품 정보나 카테고리 정보가 서버에서 렌더링된 HTML로 빠르게 로드되고, JavaScript로 동적 요소가 추가되는 쇼핑몰 사이트에서도 유용합니다.
  3. 대규모 웹 애플리케이션:
    • 초기 페이지 로딩 속도를 빠르게 하고, 사용자의 반응을 더 잘 처리하기 위해 SSR을 사용하는 대규모 웹 애플리케이션도 많습니다.

[6]  SSR vs CSR (Client-Side Rendering) 차이점

항목SSR (Server-Side Rendering)CSR (Client-Side Rendering)

페이지 렌더링 서버에서 미리 렌더링 후 HTML 전달 클라이언트에서 JavaScript가 실행되어 렌더링
초기 로딩 속도 빠른 초기 로딩 느릴 수 있음 (JavaScript 로딩 후 렌더링 시작)
SEO 서버에서 완성된 HTML을 제공하므로 SEO에 유리 클라이언트에서 JavaScript로 렌더링되므로 SEO에 불리
서버 부하 서버 부하가 크고, 많은 트래픽을 처리하기 어려울 수 있음 서버 부하가 적고, 클라이언트에서 처리되므로 서버 부하가 적음
동적 기능 서버 측에서 HTML이 이미 렌더링되어 동적 기능이 지연될 수 있음 JavaScript가 실행된 후 동적 기능을 즉시 활성화

 

SEO(Search Engine Optimization)

  • 검색 엔진에서 상위에 노출될 수 있도록 최적화하는 과정을 말한다.

 

CSR(Client Side Rendering)

📌 웹 애플리케이션에서 클라이언트(브라우저)가 웹 페이지를 렌더링하는 방식입니다. 서버는 최소한의 HTML을 클라이언트에 전달하고, 이후 JavaScript가 클라이언트 측에서 실행되어 콘텐츠를 동적으로 렌더링하는 방식입니다.

  1. HTML을 요청한다. 비어있는 HTML을 응답받는다. JS가 존재하는 주소 링크를 응답한다.
  2. 자바스크립트(클라이언트 로직, 렌더링 포함)를 요청한다.
  3. HTTP API 요청을 하고 화면에 필요한 데이터를 JSON 형태(JSON이 아니어도됨)로 응답받는다.
  4. 응답받은 JSON 데이터로 HTML을 동적으로 그린다.

 

[1]  CSR의 작동 원리

  1. 클라이언트 요청:
    • 사용자가 웹 브라우저에서 특정 URL을 요청하면, 서버는 최소한의 HTML 파일을 클라이언트에 전달합니다. 이 HTML은 보통 페이지의 뼈대(구조)만 포함하고 있으며, 실제 콘텐츠는 포함되지 않습니다.
  2. JavaScript 로드:
    • 클라이언트가 받은 HTML은 주로 JavaScript 파일을 불러오는 역할을 합니다. JavaScript는 페이지를 동적으로 렌더링하는 데 필요한 데이터와 로직을 처리합니다.
  3. API 호출:
    • JavaScript는 서버와 API 요청을 통해 데이터를 받아옵니다. 이 데이터는 JSON 형식으로 전달되며, JavaScript는 이 데이터를 바탕으로 페이지를 동적으로 생성합니다.
  4. 동적 렌더링:
    • 받은 데이터를 바탕으로 JavaScript가 HTML을 동적으로 생성하여 화면에 표시합니다. 클라이언트에서 페이지 렌더링이 이루어지므로, 서버는 추가적인 렌더링 작업을 수행하지 않습니다.
  5. 인터랙티브한 페이지:
    • JavaScript는 페이지에서 사용자의 상호작용을 처리하며, 페이지 내에서 동적 콘텐츠 갱신이나 애니메이션 등을 실시간으로 구현합니다.

[2]  CSR의 장점

  1. 서버 부하 감소:
    • 클라이언트 측에서 렌더링을 처리하므로 서버 부하가 감소합니다. 서버는 페이지의 최소한의 HTML만 보내면 되며, 클라이언트에서 나머지 작업을 처리합니다.
  2. 빠른 사용자 경험:
    • 초기 페이지 로딩 후, 페이지 내의 다른 콘텐츠를 동적으로 로드할 수 있습니다. 이는 사용자가 페이지 간 이동을 할 때 빠른 응답 시간을 제공합니다.
  3. 인터랙티브한 경험:
    • CSR은 JavaScript를 사용하여 동적이고 인터랙티브한 사용자 경험을 제공합니다. 버튼 클릭, 폼 제출 등의 인터랙션에 즉각적으로 반응할 수 있습니다.
  4. 클라이언트 측 상태 관리:
    • CSR에서는 클라이언트 측에서 애플리케이션의 상태를 관리할 수 있어, 페이지를 새로고침하지 않고도 실시간으로 UI 업데이트가 가능합니다.
  5. 애플리케이션 로딩 후 빠른 탐색:
    • 한 번 페이지가 로드되면, 후속 페이지들은 빠르게 로드되고 전환됩니다. 이는 **SPA(Single Page Application)**에서 더욱 두드러지며, 페이지를 새로고침하지 않고도 새로운 콘텐츠를 동적으로 로드합니다.

[3]  CSR의 단점

  1. 초기 로딩 속도:
    • CSR은 클라이언트에서 페이지를 렌더링하므로, 초기 페이지 로딩 시에 JavaScript 파일과 데이터를 모두 로드해야 합니다. 이로 인해 초기 로딩 속도가 상대적으로 느릴 수 있습니다.
  2. SEO (검색 엔진 최적화):
    • CSR에서는 JavaScript로 동적으로 콘텐츠를 렌더링하므로, 검색 엔진 크롤러가 자바스크립트로 렌더링된 콘텐츠를 제대로 인식하지 못할 수 있습니다. 이는 SEO에 불리할 수 있습니다. 최근에는 **서버 사이드 렌더링(SSR)**과 결합하거나 프리렌더링을 통해 이 문제를 해결하기도 합니다.
  3. 자바스크립트 의존성:
    • CSR 방식은 JavaScript가 제대로 실행되지 않으면 페이지가 제대로 표시되지 않거나, 애플리케이션이 기능을 제대로 수행하지 않을 수 있습니다. 사용자가 JavaScript를 비활성화한 경우 페이지가 정상적으로 동작하지 않을 수 있습니다.
  4. 클라이언트 성능 문제:
    • 클라이언트(브라우저)가 많은 작업을 처리하므로, 저사양 기기에서는 성능 저하가 발생할 수 있습니다. 특히, 복잡한 애플리케이션에서는 클라이언트가 느려질 수 있습니다.

[4]  CSR과 SSR의 차이점

항목CSR (Client-Side Rendering)SSR (Server-Side Rendering)

렌더링 위치 클라이언트(브라우저)에서 렌더링 서버에서 렌더링 후 클라이언트로 전달
초기 로딩 시간 상대적으로 느릴 수 있음 (JavaScript 로딩이 필요) 빠름 (서버에서 HTML을 미리 렌더링)
SEO SEO에 불리 (검색 엔진 크롤러가 동적 콘텐츠를 제대로 크롤링 못할 수 있음) SEO에 유리 (완성된 HTML을 서버에서 제공)
서버 부하 서버 부하가 적음 (서버는 기본 HTML만 전달) 서버 부하가 클 수 있음 (매 요청마다 페이지를 렌더링)
사용자 경험 더 동적이고 인터랙티브함, 페이지 간 전환 빠름 초기 페이지 로딩이 빠르지만, 이후 전환에 있어 느릴 수 있음
상태 관리 클라이언트에서 상태를 관리 (SPA) 서버에서 상태를 관리 (매 요청마다 새로 렌더링)

[5]  CSR을 사용하는 주요 기술 및 라이브러리

  • React: 동적이고 인터랙티브한 UI를 구성하는 데 사용되는 라이브러리입니다. React는 **SPA (Single Page Application)**을 만들 때 주로 사용됩니다.
  • Vue.js: React와 유사하게 클라이언트 측에서 렌더링되는 웹 애플리케이션을 만들 때 사용하는 JavaScript 프레임워크입니다.
  • Angular: 구글에서 개발한 프레임워크로, CSR을 기반으로 한 대규모 웹 애플리케이션을 구축하는 데 사용됩니다.
  • Next.js: React 기반의 SSR 및 CSR을 지원하는 프레임워크입니다. CSR이 기본이며, SSR도 선택적으로 사용할 수 있습니다.

 

'CS ( Computer Science ) > 네트워크 (Networking)' 카테고리의 다른 글

[Net] Restful API  (1) 2026.08.03
[Net] JSON  (1) 2026.07.26
[Net] HTTP  (0) 2026.07.16
[Net] 네트워크 요약  (1) 2025.01.22
[Net] Filter  (1) 2025.01.01

Restful API

📌 REST(Representational State Transfer) 아키텍처 스타일을 준수하여 설계된 API입니다. 주로 HTTP 프로토콜을 기반으로 클라이언트와 서버 간에 리소스를 주고받기 위해 사용되며, 간결하고 확장 가능한 웹 서비스 설계를 제공합니다.

  • REST를 잘 준수하는 API로 HTTP 프로토콜을 사용하여 클라이언트와 서버 간의 통신을 통해 자원(Resource)을 관리한다.
  • 원은 고유한 URI로 식별되며, HTTP 메서드(GET, POST, PUT, DELETE 등)를 통해 다양한 작업을 수행하며 요청과 응답은 일반적으로 JSON 또는 XML 형식으로 이루어진다.

 

REST(Representational State Transfer)란?

  • 자원(Resource)을 이름(Name)으로 구분하여 해당 자원의 상태(정보)를 주고받는 것을 의미한다.
  • → URI를 통해 자원(Resource)을 명시하고, HTTP Method(POST, GET, PUT, DELETE,PATCH 등)를 통해 해당 자원에 대한 CRUD Operation을 적용하는 것을 REST라 칭한다.
  • = REST란 자원을 URI로 식별하고, HTTP 메서드를 사용해 자원의 상태를 주고받는 아키텍처 스타일이다.
  • = RESTful API란 REST 원칙을 준수하여 설계된 API로, 클라이언트와 서버 간에 자원의 상태를 HTTP 메서드와 URI를 통해 일관되게 주고받는 방식이다.

 

 

[1]  RESTful API의 주요 특징

  1. 리소스 중심 설계
    • 모든 데이터는 **리소스(Resource)**로 표현되며, 고유한 URL을 통해 접근합니다.
    • 예: /users는 사용자 리소스를 나타냅니다.
  2. 표준 HTTP 메서드 사용
    • RESTful API는 HTTP 메서드(GET, POST, PUT, DELETE 등)를 사용해 CRUD(Create, Read, Update, Delete)를 구현합니다.
  3. 상태 비저장(Stateless)
    • 서버는 클라이언트의 상태를 저장하지 않으며, 각 요청은 독립적으로 처리됩니다.
    • 클라이언트가 필요한 모든 정보를 요청에 포함해야 합니다.
  4. URI를 통한 리소스 표현
    • RESTful API는 명확하고 의미 있는 URI를 사용합니다.
    • 예: /products/123는 특정 상품(ID: 123)을 나타냅니다.
  5. JSON을 통한 데이터 교환
    • 요청 및 응답 데이터 형식으로 주로 JSON을 사용하지만, XML 등 다른 형식도 가능.
  6. 계층화 구조
    • API 호출자는 서비스의 내부 구현이나 계층을 알 필요 없이 요청을 보낼 수 있습니다.

 


 

[2]  RESTful API의 구성 요소

구성 요소 설명 예시
리소스 API에서 관리되는 데이터. users, products, orders
URI 리소스를 나타내는 고유한 경로. /users/123
HTTP 메서드 리소스에 대한 동작을 정의. GET, POST, PUT, DELETE
표현(Representation) 리소스의 데이터 표현 형식 (주로 JSON). { "id": 123, "name": "John" }
상태 코드 요청 처리 결과를 나타내는 HTTP 응답 코드. 200 OK, 404 Not Found

 



[3]  RESTful API의 HTTP 메서드와 리소스 설계

HTTP 메서드 리소스 URI  배달 비유
GET 리소스 조회 /users (전체 조회) "모든 배달 내역을 확인해 주세요."
    /users/123 (특정 조회) "123번 주문 내역을 보여 주세요."
POST 리소스 생성 /users "새로운 주문을 넣어 주세요."
PUT 리소스 전체 수정 /users/123 "123번 주문의 모든 항목을 수정해 주세요."
PATCH 리소스 일부 수정 /users/123 "123번 주문 중 주소만 바꿔 주세요."
DELETE 리소스 삭제 /users/123 "123번 주문을 취소해 주세요."

 



[4]  RESTful API의 설계 원칙

  1. 자원 중심의 URI 설계
    • URI는 명확하고 직관적이어야 합니다.
      • 올바름: /users/123/orders
      • 잘못된 예: /getUserOrder?id=123
  2. HTTP 상태 코드 활용
    • 상태 코드는 클라이언트가 요청 결과를 이해하는 데 도움을 줍니다.상태 코드설명
      200 OK 요청이 성공적으로 처리됨
      201 Created 새로운 리소스가 생성됨
      400 Bad Request 잘못된 요청
      404 Not Found 리소스를 찾을 수 없음
      500 Internal Server Error 서버 오류
  3. 상태 비저장 설계
    • 서버는 요청 간 클라이언트의 상태를 기억하지 않아야 하며, 요청에 필요한 정보를 클라이언트가 제공해야 합니다.
  4. 일관성 유지
    • 모든 API는 일관된 설계와 명명 규칙을 따릅니다.

 



[5]  RESTful API의 배달에 비유

  • RESTful API는 배달 시스템과 비슷합니다.
    • URI: 배달 주소 (e.g., /users/123 → 특정 고객의 배달 내역).
    • HTTP 메서드: 배달 요청의 종류 (GET → 확인, POST → 새로운 주문, DELETE → 취소).
    • 상태 코드: 배달 결과 알림 (200 → 성공, 404 → 주소를 못 찾음).
    • JSON: 주문서의 상세 내용.

RESTful API는 이러한 비유처럼 직관적이고 간결한 방식으로 데이터를 주고받는 웹 서비스입니다.

 

더보기
더보기

참고자료 정리

  1. 리소스는 명사를 사용해야 한다.
  2. 단수가 아닌 복수 형태를 사용해야 한다.
  3. 만약, REST만으로 해결하기 어려운 경우라면 동사를 허용한다.
  4. 자원의 계층 관계를 슬래시(/)로 표현한다.
  5. 마지막 문자에는 슬래시(/)가 있으면 안된다.
  6. 언더바(_)가 아닌 하이픈(-)을 사용해야 한다.
  7. 소문자를 사용해야 한다.
  8. URI에 파일 확장자를 포함하면 안된다.
  9. CRUD 함수명은 사용하지 않고, HTTP Method를 활용해야 한다.
  10. 정렬, 필터링, 페이징은 신규 API를 만드는것이 아닌 Query Parameter를 사용해야 한다.

 

 

Maturity Model (성숙도 모델)

🐳  시스템, 프로세스, 조직, 또는 기술이 특정 목적을 얼마나 잘 달성하고 있는지를 단계별로 평가하는 구조적 접근 방식입니다. 이를 통해 조직이나 시스템이 현재 상태를 진단하고, 더 높은 수준으로 발전하기 위해 필요한 개선 사항을 명확히 할 수 있습니다.

 

[1] 성숙도 모델의 핵심 요소

  1. 단계적 성장
    • 성숙도 모델은 일반적으로 5단계 또는 그 이상의 단계를 정의하며, 초기 상태부터 완성된 상태까지 점진적으로 발전하는 과정을 나타냅니다.
  2. 평가 기준
    • 각 단계는 명확한 평가 기준을 가지고 있어, 현재 상태와 목표 상태를 비교하고 발전 방향을 설정할 수 있도록 돕습니다.
  3. 객관적 진단
    • 조직이나 시스템의 성숙도를 객관적이고 체계적으로 진단하여 개선의 우선순위를 설정할 수 있습니다.

 



[2] 대표적인 성숙도 모델

1. CMMI (Capability Maturity Model Integration)

소프트웨어 개발, 서비스 관리 등의 프로세스를 개선하기 위한 대표적인 성숙도 모델.

단계설명특징

Level 1 초기화(Initiating) 비체계적, 성공은 개인 역량에 의존.
Level 2 관리(Managed) 기본 프로젝트 관리 체계가 갖춰져 있음.
Level 3 정의(Defined) 표준 프로세스 정의 및 조직 내 일관성 확보.
Level 4 정량적 관리(Quantitatively Managed) 데이터 기반 관리 및 프로세스 개선.
Level 5 최적화(Optimizing) 지속적 개선과 혁신이 이루어짐.

 

2. 데이터 성숙도 모델

데이터 관리를 중심으로 조직의 데이터 활용 능력을 평가.

단계설명특징

Level 1 초기화(Initial) 데이터 관리가 비체계적이며 중복과 오류 발생.
Level 2 관리(Managed) 데이터 품질 관리 체계 도입.
Level 3 정의(Defined) 데이터 표준화와 통합 관리 체계 확립.
Level 4 예측(Predictive) 데이터 분석을 통해 예측 가능.
Level 5 혁신(Innovative) 데이터 중심 의사결정이 가능한 혁신 조직.

 



[3] 성숙도 모델의 주요 활용 사례

  1. 조직 관리
    • 조직의 프로세스 성숙도를 진단하고 개선 방향 설정.
  2. 소프트웨어 개발
    • 개발 프로세스의 체계화와 품질 향상을 위한 CMMI 적용.
  3. 데이터 관리 및 분석
    • 데이터를 전략적으로 활용하기 위한 데이터 성숙도 모델 활용.
  4. 디지털 트랜스포메이션
    • 디지털화 성숙도를 평가하고 디지털 전략 수립.

 



[4] 성숙도 모델의 장점과 단점

구분장점단점

장점 - 현재 상태를 명확히 진단 가능. - 모든 조직이나 시스템에 동일한 기준을 적용하기 어려움.
  - 개선 방향과 우선순위를 설정할 수 있음. - 각 단계로 이동하는 데 시간이 오래 걸릴 수 있음.
  - 지속적 개선 문화를 정착시키는 데 도움. - 실제 업무 상황을 반영하지 못할 경우 개선 효과가 떨어질 수 있음.
단점 - 측정 및 진단이 복잡할 수 있음. - 초기 단계에서는 비용 대비 효과가 크지 않을 수 있음.

 



[5] 배달에 비유: 성숙도 모델

단계배달 예시

Level 1 "메뉴를 잘못 기록하고, 배달이 늦고, 고객 불만이 많음."
Level 2 "주문 확인 절차를 통해 기본적인 실수는 줄었으나, 고객 맞춤 서비스는 부족."
Level 3 "배달 경로와 고객 데이터를 분석하여 효율성을 높임."
Level 4 "고객의 이전 주문 기록을 바탕으로 맞춤형 추천 메뉴 제공."
Level 5 "AI를 활용한 배달 시간 예측 및 개인화된 서비스로 고객 만족도 최고조."

 

 

API Maturity Model (성숙도 모델)

  • Level0
    • 웹 서비스를 제공하기 위해 URL만 매핑해 놓은 상태
    • 요청 예시(모든 요청이 단일 URI로 전송된다)
POST /operation
{
    "operation": "createUser",
    "data": {
        "name": "sparta",
        "password": "codingclub"
    }
}

 

  • Level1
    • 외부로 공개하려는 리소스에 대해서 의미있는 URL로 표현하기 시작한 단계
    • 적절한 패턴을 가지고 작성 되었지만 HTTP의 메소드 별로 서비스를 구분하여 사용하고 있지는 않다.
    • 즉, 서비스 형태나 작업의 종류에 맞추어 적절한 HTTP 메소드를 지정하고 있지 않다.
    • 사용자의 요청을 GET, POST로 대부분 처리하고 에러를 반환한다.
    • 요청 예시(리소스에 대해 분리된 엔드포인트를 가진다)
POST /users
{
    "name": "sparta",
    "password": "codingclub"
}

 

  • Level2
    • 우리가 제공하고자 하는 리소스를 적절하게 용도와 상태에 따라서 HTTP Methods에 맞게 설계하고 서비스하는 단계.
    • 만약 리소스의 상태가 읽기 용도로 사용되는 데이터라고 한다면 GET Method를 사용한다.
    • 새로운 리소스를 추가하는 경우는 POST Method
    • 기존 리소스의 상태를 변경하기 위해서는 PUT, PATCH Method
    • 리소스를 삭제하고자 할 때에는 Delete Method를 사용하여 서비스의 상태를 표현한다.
    • RESTful Service의 DB에 저장된 리소스를 확인하고 이러한 데이터를 조작하기 위해서 CRUD와 매칭되는 HTTP Methods를 이용하여 서비스 하는 것을 Level2 단계라고 한다.
    • HTTP의 메소드를 이용하여 리소스의 상태를 구분하여 서비스 하게 되면 비슷한 이름의 URI라 하더라도 HTTP Method에 따라서 다른 형태의 서비스를 제공할 수 있게 된다.
    • 요청 예시(HTTP Method 활용)
GET /users/123     // 특정 사용자 조회

POST /users        // 사용자 생성
{
    "name": "sparta",
    "password": "codingclub"
}

PUT /users/123     // 사용자 정보 수정
{
    "name": "java",
    "password": "spring"
}

DELETE /users/123  // 사용자 삭제

 

  • Level3
    • 데이터를 가지고 그 다음 작업에서 어떠한 작업을 할 수 있는지 상태 정보를 함께 넘겨준다.
    • 클라이언트 측에서는 서버가 제공하는 서비스를 일일이 찾는 수고를 겪지 않아도 된다.
    • 엔드포인트만 가지고 있으면 서버가 제공할 수 있는 다음, 그 다음 URI값을 알 수 있다.
    • 요청 예시(응답 내에 링크를 포함한다)
💡 HATEOAS(Hypermedia As The Engine Of Application State) 회원 가입 후 회원 정보 수정은 어떻게 해야 하는지, 조회는 어떻게 해야 하는지 회원 조회를 하면서 그다음 단계로 진행할 수 있는 또 다른 리소스에 대한 정보는 어떠한 것이 있는지. 이러한 모든 정보를 같이 알려주는 기능을 HATEOAS라고 한다.

 

GET /users/123
{
    "id": 123,
    "name": "sparta",
    "links": {
        "self": "/users/123",
        "update": "/users/123",
        "delete": "/users/123"
    }
}

 

 

★ RESTful API 설계 시 고려해야 할 사항들

 

1. Consumer first

  • 개발자 중심의 설계방식보다 해당 API의 소비자 입장에서 간단하고 직관적인 API를 설계 해야한다.
  • 위에서의 소비자는 엔드유저가 아닌 API를 사용 하고있는 또다른 시스템, 개발자 등을 얘기한다.

2. Make best use of HTTP

  • HTTP Method와 Request, Response, Header와 같은 HTTP의 장점을 살려서 개발 해야한다.

3. Request methods

  • 최소한 성숙도 모델 Level2로는 사용하여야 한다.

4. Response Status

  • 각각의 API 요청에 따라서 적절한 HTTP 상태코드가 전달되어야 한다.
  • 성공했다, 실패했다가 아닌 왜 실패하고 성공 하였는지 함께 반환 시켜주어야 한다.

5. No secure info in URI

  • URI에는 사용자의 정보를 포함해서는 안된다.

6. Use plurals

  • 제공하는 데이터에 대하여 단수가 아닌 복수형태로 쓰는것이 일반적이다.
  • 특정 유저를 찾고자 한다면 엔드포인트에 값을 추가한다.
  • ex) /user -> /users
  • ex) /users/1

 

7. User nouns for resources

  • 모든 리소스는 가능하면 동사가 아닌 명사형태로 표시한다.
  • API URI만 보고도 어떠한 API인지 파악할 수 있는것이 좋다.

8. For exceptions - define a consistent approach

  • 일괄적인 엔드포인트를 사용하는것이 좋다.

 

'CS ( Computer Science ) > 네트워크 (Networking)' 카테고리의 다른 글

[Net] Rendering  (1) 2026.08.13
[Net] JSON  (1) 2026.07.26
[Net] HTTP  (0) 2026.07.16
[Net] 네트워크 요약  (1) 2025.01.22
[Net] Filter  (1) 2025.01.01

JSON

📌 JSON은 클라이언트와 서버가 통신할 때 사용하는 데이터 양식이다. 클라이언트와 서버가 사용하는 언어에 관계 없이 통일된 데이터를 주고받을 수 있도록 만들어준다.

  • 과거 웹 초기 시절부터 사용된 XML 은 헤더와 태그 등의 여러 요소로 가독성이 떨어지고, 불필요한 용량을 잡아먹는다는 단점을 항상 지적받았다. 이에 대응해 간결하고 통일된 양식으로 각광을 받고 있는 것이 JSON이다.
  • 키-값 쌍의 구조로 표현하는 텍스트 기반 데이터 형식이다.

요약

  • JSON은 사람, 기계 모두 이해하기 쉬우며 용량이 작다.
  • XML을 대체해서 데이터 전송 등에 많이 사용한다.
  • 마치 전세계 공통어로 영어를 사용하는것처럼 Web의 세계에서는 JSON(JavaScript Object Notation)을 공통어로 사용한다.

클라 TO 서버 / 서버 TO 서버 모두 사

 

[1]  JSON의 배달 비유:

  1. JSON = 택배 상자
    • JSON은 데이터를 담아 보내는 포장 상자와 같습니다.
    • 상자 안에 다양한 데이터(키-값 쌍)가 들어있으며, 이 데이터를 꺼내기 위해 상자 구조를 이해해야 합니다.
  2. 키 = 상자에 붙인 라벨
    • 키는 데이터의 이름표로, 택배 상자에 붙이는 "내용물 라벨"과 같습니다.
    • 예: "name": "Alice"는 "이름 라벨에 'Alice'라고 적음"과 같음.
  3. 값 = 상자 속 물건
    • 값은 실제로 상자 안에 들어 있는 데이터입니다.
    • 예: "age": 25는 "라벨 'age'에 해당하는 물건은 25"라는 의미.
  4. 배열 = 상자 속 묶음 물건
    • 배열은 상자 안에 같은 종류의 물건이 여러 개 담겨 있는 모습과 같습니다.
    • 예: "hobbies": ["reading", "coding"]는 "취미 물건 목록".

 

[2]  JSON의 구조:

{
  "user": [
    {
      "first_name": "wonuk",
      "last_name": "Hwang",
      "age": 100,
      "phone_agree": false,
      "hobby": ["Java", "Spring"]
    },
    {
      "firstName": "sparta",
      "lastName": "Team",
      "age": 200,
      "phone_agree": true,
      "hobby": ["React", "Spring", "Node"]
    },
  ]
}
  • snake_case, camelCase 모두 사용이 가능하다.
    • 우리가 만드는 Application 내에서 변환해주는 무엇인가가 있다.
  • key-value 형태로 구성되어 있다.
  • null, number, string, array, object, boolean 형태의 데이터를 사용할 수 있다.
MSA(MicroService Architecture)를 가지게 되면 구성된 Application마다 어떠한 언어를 사용하는지에 상관없이 서로 통신을 할 수 있는데 이것이 가능한 이유는 JSON 형태로 데이터 통신을 하기 때문이다.

 

 

MSA ( MicroService Architecture )

📌 MSA는 애플리케이션을 독립적으로 배포 및 실행 가능한 작은 서비스 단위로 나누어 개발하는 소프트웨어 아키텍처 스타일입니다.

  • 각 마이크로서비스는 특정 비즈니스 기능을 담당하며, 서로 독립적으로 배포, 수정, 확장할 수 있습니다.
  • 소프트웨어를 작은 단위의 독립적인 서비스로 분리해 개발 및 운영 효율성을 높이는 구조입니다.
  • 참고

'CS ( Computer Science ) > 네트워크 (Networking)' 카테고리의 다른 글

[Net] Rendering  (1) 2026.08.13
[Net] Restful API  (1) 2026.08.03
[Net] HTTP  (0) 2026.07.16
[Net] 네트워크 요약  (1) 2025.01.22
[Net] Filter  (1) 2025.01.01

Stateful, Stateless

📌 클라이언트와 서버간의 통신 상태(state) 유지 여부에 따라 나뉘는 특성이다.

  • Stateful(상태 유지)
    • 클라이언트의 상태를 유지한다.
    • 상담원은 수강생의 요청들을 기억(상태 유지)하여 다음 질문들에 대한 처리가 가능하다.

 

Stateful 방식의 문제점

  • 같은 서버가 유지되어야 한다.
  • 상태를 유지하고 있던 서버가 종료된다면?

  • 서버는 다양한 이유로 동작하지 않을 수 있다.
    • 시스템 에러, 비지니스 로직 문제, 리소스 부족 문제 등
  • 요청 트래픽이 몰리게되면 상태를 유지하는것에 Resource가 많이 소모된다.
    • 리소스가 버티지 못하면 서버가 종료되거나, 다음 요청에 대한 처리가 느려진다.

 

[1]  Stateless(무상태)

  • 클라이언트의 상태를 유지하지 않는다.
  • 클라이언트의 요청을 저장하지 않는다.

 

  • 어떻게 서로 다른 상담원들이 수강생의 요청을 알 수 있을까요?

 

[2]  Stateless 방식의 실제 요청방식

 

 

  • 강의를 신청하려는 수강생이 상담한 직원이 아닌 다른 직원이 와도 신청할 수 있게 되었다.

 

  • 장점
    • 같은 서버를 유지할 필요가 없다.
    • Scale Out 수평 확장성이 높다.
      • 갑자기 요청량이 증가하여도 서버를 증설 하기 쉽다.

  • 단점
    • 클라이언트가 데이터를 추가적으로 전송해야 한다.
      • 전송되는 데이터의 양이 많아진다.
  • Stateless 방식의 한계점
    • WebApplication을 만들때 서버의 확장성을 고려하여 최대한 Stateless하게 만들어야 한다.
    • 하지만, 실제로는 로그인과 같은 상태를 유지해야하는 경우가 발생한다.
    • 추후에 배울 Cookie, Session, Token 등을 활용하여 이러한 한계를 극복한다.
      • 상태 유지를 최소화 시켜야 한다.

 

 

 

Connection, Connectionless

📌 클라이언트와 서버 간의 연결(Connection) 유지 여부에 따라 나뉘는 특성이다.

 

[1]  Connection(연결)

  • 서버는 클라이언트와 연결을 유지하기 위해서 자원을 소모한다.
  • 하지만, 수많은 사람들이 서비스를 이용해도 실제 서버에서 동시에 처리하는 요청은 작다.
    • 클라이언트 2, 3이 아무런 요청이 없어도 연결을 유지한다.

  • Connection 장단점
    • 장점
      • 새로운 연결 과정을 거치지 않아도 된다.
      • 그만큼 요청에 대한 응답 속도가 빨라진다.
    • 단점
      • 클라이언트가 지속적으로 요청을 보낼거라는 보장이 없다.
      • 즉, 연결을 위한 자원이 낭비된다.

 

[2]  Connectionless(비연결)

  • 클라이언트와 서버는 연결을 유지하지 않는다.
  • 서버는 최소한의 자원만을 사용한다.

 

ex) 브라우저가 켜진 상태에서 인터넷이 종료되어도 홈페이지가 정상적으로 노출된다.

 

ex) 브라우저가 켜진 상태에서 인터넷이 종료되어도 홈페이지가 정상적으로 노출된다.

 

  • Connectionless 장단점
    • 장점
      • 서버 자원을 효율적으로 사용할 수 있다.
    • 단점
      • 요청이 추가적으로 오게되면 연결(3 way handshake)을 새로 해야한다.
      • → 요청에 대한 응답 시간이 증가한다.
      • 웹 사이트의 HTML, CSS, JS, 이미지 등의 정적 자원 모두를 다시 다운로드 한다.
      • 캐시, 브라우저 캐싱로 해결한다. 쉽게 말해 임시저장 (추후 다룰 예정)
      • 현재는 **HTTP 지속연결(Persistent Connections)**로 문제를 해결한다.

 

[3]  HTTP 지속연결(Persistent Connections)

  • 비 연결성의 한계 극복을 위해 생성됨
  • 하나의 요청에 필요한 요청들이 모두 응답될 때 까지 연결을 유지한다.
  • 연결을 한번만 맺고 끊기 때문에, Connectionless 방식보다 연결 횟수가 적다.
  • → 그만큼 속도가 빨라졌다.

ex) HTML 요청 + CSS 요청 + JS 요청 + 이미지 요청

 

HTTP ( HyperText Transfer Protocol )

📌 HTTP는 웹에서 데이터를 전송하는 통신 프로토콜로, 클라이언트와 서버 간의 요청 및 응답을 관리하는 역할을 합니다.

  • 웹 브라우저나 기타 클라이언트가 서버에 요청을 보내면, 서버는 요청에 대한 응답을 클라이언트로 보내는 방식으로 동작합니다. HTTP는 비상태성(stateless) 프로토콜로, 각 요청은 독립적으로 처리됩니다.

기반 프로토콜

  TCP: HTTP/1.1, HTTP/2

• UDP: HTTP/3

• 현재 HTTP/1.1 주로 사용

• HTTP/2, HTTP/3 도 점점 증가

더보기

TEXT, IMAGE, FILE, HTML, JSON 등 다양한 형태의 데이터가 HTTP를 통해 전송(심지어 서버끼리도 이 프로토콜을 메인으로 사용한다.)된다. HTTP에도 버전이 존재하며 그중 대부분 HTTP/1.1 (TCP)을 사용한다. 현대에는 HTTP/2, HTTP/3 (UDP)의 사용량이 급속도로 증가하는 추세이다.

 

  • HTTP 동작 순서
    • 클라이언트는 Request(요청)을 보내고, 응답을 기다린다.
    • 서버는 요청에 대한 처리를 수행 후 결과를 Response(응답)한다.

 

 

HTTP 특징

📌 HTTP는 인터넷 상에서 불특정 다수의 통신 환경을 기반으로 설계되었다. 만약 서버에서 다수의 클라이언트와 상태연결을 계속 유지해야 한다면 이에 따른 많은 서버의 리소스가 필요하다.

 

[1]  클라이언트와 서버 구조

  • 기존에는 클라이언트, 서버가 구분되어있지 않았다.
    • 클라이언트는 UI(User Interface)에 중점을 두도록 만들었다.
    • 서버에서 데이터, 비지니스 로직을 담당하도록 만들었다.
  • 결과적으로 클라이언트, 서버 각자 독립적으로 발전할 수 있게되었다.
  • 컴퓨터의 직업이라 보면 된다. 사람이 의사, 판사의 직업을 갖는 것과 같다.

 

 


[2]  무상태 (Stateless)

  • 서버는 클라이언트의 상태를 보존하지 않는다. 
  • 클라이언트의 요청을 서버가 기록하지 않는다.

ex) 스파르타에 강의를 신청하는 수강생이 상담한 직원이 아닌 다른 직원이 와도 결제할 수 있다.

  • 장점
    • Scale Out( 서버 확장 용이 ) 수평 확장성이 높다.
    • 갑자기 요청량이 증가하여도 서버를 증설 하기 쉽다.
  • 단점
    • 클라이언트가 데이터를 추가적으로 전송해야 한다.
  • 한계점
    • 무상태로 설계할 수 없는 경우가 있다.
    • 로그인은 어떻게 해야할까?
      • Cookie, Session, Token 등을 활용한다. → 추후 배울 내용

 

[3]  비연결 (Connectionless)

  • HTTP는 연결을 유지하지 않는 모델이다.
  • 장점
    • 서버 자원을 효율적으로 사용할 수 있다.
  • 단점
    • 요청이 추가적으로 오게되면 연결(3 way handshake)을 새로 해야한다.
    • → 요청에 대한 응답 시간이 증가한다.
    • 웹 사이트의 HTML, CSS, JS, 이미지 등의 정적 자원 모두를 다시 다운로드 한다.
    • 캐시, 브라우저 캐싱로 해결한다. 쉽게 말해 임시저장 (추후 다룰 예정)
    • 현재는 **HTTP 지속연결(Persistent Connections)**로 문제를 해결한다.
    • HTTP 지속연결(Persistent Connections)
      • 하나의 요청에 필요한 요청들이 모두 응답될 때 까지 연결을 유지한다.
      • 연결을 한번만 맺고 끊기 때문에, Connectionless 방식보다 연결 횟수가 적다.
      • → 그만큼 속도가 빨라졌다.
      ex) HTML 요청 + CSS 요청 + JS 요청 + 이미지 요청

 

 

 

 

 

HTTP Message 구조

📌 HTTP Message는 요청 메세지, 응답 메세지 두 가지 종류가 있고 구조가 각각 다르다.

  • 거의 모든 형태의 데이터가 이 메시지에 담겨서 이동된다.

 

[1]  HTTP Message 구조

 

[2]  HTTP 요청 메세지(Request Message)

  1. Start Line
    • HTTP Method
      • GET
      • 요청의 의도를 가진 GET, POST, PUT, PATCH, DELETE 등이 있다.
        • Create - POST
        • Read - GET
        • Update - PUT(전체), PATCH(일부)
        • Delete - DELETE
        • Request Target
    • path
      • /event
      • HTTP Request가 전송되는 대상, 절대 경로(”/”로 시작하는 경로)
      • 그냥 요청 대상
      • Query String(= Query Parameter) 에 해당하는 값도 포함한다.
      ex) /search?keyword=sparta
    • HTTP Version
      • 1.1
      • HTTP Version을 나타낸다.
  2. Header
    • Host: spartacodingclub.kr
    • field-name: OWS field-value OWS (OWS : 띄어쓰기 허용) 구조를 가진다.
    • field-name은 대소문자 구분을 하지 않는다.
    • 임의의 Header를 추가할 수 있다. (단, 서버가 값을 알고 있어야 함 = 토큰같은 키나 데이터 일관성 보안문제)
    • HTTP 전송에 필요한 모든 부가정보
    ex) Message Body 내용, 크기, 인증, 브라우저 정보, 서버 정보 등
  3. Empty Line
    • 공백 한 줄
    • 필수 값
  4. Message Body
    • 실제 전송하는 데이터가 담겨 있는 부분
      • HTML, 이미지, JSON 등 byte로 표현되는 모든 데이터 전송 가능.
    • 요청 시 GET의 경우 Message Body가 지원되지 않는 경우가 많아 권장하지 않는다.

 

[3]  HTTP 응답 메세지(Response Message)

 

  1. Start Line
    • HTTP Version
    • Status Code
      • 요청이 성공했는지, 실패했는지 나타내는 코드
      • 200: 성공 • 400: 클라이언트 요청 오류 • 500: 서버 내부 오류
    • Status Text
      • 코드와 함께 전달될 메세지, 상태 코드 설명
  2. Header
    • Response에서만 사용되는 Header 값들이 따로 존재한다.
  3. Empty Line
    • 공백 한줄, 필수값
  4. Message Body
    • 실제 전송하는 데이터가 담겨 있는 부분
    • 만약 전송할 데이터가 없다면, Body가 공백으로 존재한다.
    • HTML 문서, 이미지, 영상, JSON 등등 byte로 표현할 수 있는 모든 데이터 전송 가능

 

 

 

데이터 전송 정리

클라 -> 서버 데이터 전달 방식 클라 -> 서버 데이터 전달 상황
쿼리 파라미터를 통한 데이터 전송
• GET
• 주로 정렬 필터(검색어)
GET /products?category=clothing&sort=price_desc
category=clothing: 카테고리가 의류인 제품을 조회합니다.
URL로 데이터 

메시지 바디를 통한 데이터 전송
• POST, PUT, PATCH
• 회원 가입, 상품 주문, 리소스 등록, 리소스 변경
json 형태의 데이터 
정적 데이터 조회
• 이미지, 정적 텍스트 문서

동적 데이터 조회
• 주로 검색, 게시판 목록에서 정렬 필터(검색어)

HTML Form을 통한 데이터 전송
• 회원 가입, 상품 주문, 데이터 변경

HTTP API를 통한 데이터 전송
• 회원 가입, 상품 주문, 데이터 변경
• 서버 to 서버, 앱 클라이언트, 웹 클라이언트(Ajax)
더보기

1. 쿼리 파라미터 (URL로 데이터 전송)

쿼리 파라미터는 URL에 데이터를 포함하여 서버로 전달하는 방법입니다. 데이터는 URL의 ? 뒤에 key=value 형태로 전달됩니다. 예를 들어, https://example.com/api?name=John&age=25와 같이 URL에 포함된 데이터는 서버에서 쿼리 파라미터로 받아 처리됩니다.

  • 장점: 간단하고, URL만으로 데이터 전달이 가능.
  • 단점: 데이터 양이 많으면 URL 길이가 제한될 수 있고, 민감한 데이터(비밀번호 등)를 포함하기에는 보안상 좋지 않음.

예시:

GET https://example.com/api?name=John&age=25

2. 메시지 바디 (JSON을 통한 데이터 전송)

메시지 바디는 HTTP 요청 또는 응답의 본문에 데이터를 포함하여 전송하는 방식입니다. 이때, 데이터를 JSON 형식으로 주고받는 것이 일반적입니다. 예를 들어, 클라이언트가 서버에 POST 요청을 보낼 때, 요청 본문(body)에는 JSON 데이터가 담겨 서버로 전송됩니다.

  • 장점: 큰 데이터나 복잡한 구조를 효율적으로 전달 가능, 보안에 유리(데이터가 URL에 포함되지 않음).
  • 단점: URL을 통한 접근보다 복잡할 수 있으며, 클라이언트와 서버가 메시지 포맷에 대해 합의해야 함.

예시:

POST https://example.com/api
Content-Type: application/json

{
  "name": "John",
  "age": 25
}

차이점 정리:

  • 쿼리 파라미터: URL의 일부로 데이터 전달 (GET 요청에 주로 사용)
  • 메시지 바디 (JSON): 요청 본문에 데이터 전달 (POST, PUT, PATCH 요청에 주로 사용)
    • JSON 형식으로 데이터를 전송하며, 큰 데이터나 복잡한 구조를 처리할 수 있음
    • 예: POST https://example.com/api + { "name": "John", "age": 25 }

따라서, 쿼리 파라미터는 URL을 통해, 메시지 바디는 JSON을 통해 데이터를 전송하는 방식이라고 할 수 있습니다.

 

파라미터: 특정 데이터나 옵션을 지정하기 위해 사용되는 이름(Key). = 명령 종류
: 해당 파라미터가 가지는 실제 데이터(Value).

  • query는 파라미터, books는 그 값.
  • sort는 파라미터, asc는 그 값.

 

 

[1] 정적 데이터 조회

  • 이미지, 정적 텍스트 문서
  • 조회는 GET 사용
  • 정적 데이터는 일반적으로 쿼리 파라미터 없이 리소스 경로로 단순하게 조회 가능
  • 데이터가 변하지 않거나, 클라이언트가 모든 데이터를 필요로 할 때 사용


 

[2] 동적 데이터 조회 

  • 주로 검색, 게시판 목록에서 정렬 필터(검색어)
  • 조회 조건을 줄여주는 필터, 조회 결과를 정렬하는 정렬 조건에 주로 사용
  • 조회는 GET 사용
  • GET은 쿼리 파라미터 사용해서 데이터를 전달
  • 요청 자체를 원하는 것 일부만 요청하는 방식


[3] HTML Form 데이터 전송

 

HTML Form submit시 POST 전송

  • 예) 회원 가입, 상품 주문, 데이터 변경

Content-Type: application/x-www-form-urlencoded 사용

  • form의 내용을 메시지 바디를 통해서 전송(key=value, 쿼리 파라미터 형식)
  • 전송 데이터를 url encoding 처리
    • 예) abc김 -> abc%EA%B9%80

HTML Form은 GET 전송도 가능

 

Content-Type: multipart/form-data

  • 파일 업로드 같은 바이너리 데이터 전송시 사용
  • 다른 종류의 여러 파일과 폼의 내용 함께 전송 가능(그래서 이름이 multipart)

 

참고: HTML Form 전송은 GET, POST만 지원

 

 

[4] HTTP API 데이터 전송

서버 to 서버

  • 백엔드 시스템 통신

앱 클라이언트

  • 아이폰, 안드로이드

웹 클라이언트

  • HTML에서 Form 전송 대신 자바 스크립트를 통한 통신에 사용(AJAX)
  • 예) React, VueJs 같은 웹 클라이언트와 API 통신

POST, PUT, PATCH: 메시지 바디를 통해 데이터 전송

 

GET: 조회, 쿼리 파라미터로 데이터 전달 

 

Content-Type: application/json을 주로 사용 (사실상 표준)

  • TEXT, XML, JSON 등등

 

 

 

HTTP API 설계 예시

 

1. HTTP API - 컬렉션

  • POST 기반 등록
    • 설명: 서버가 리소스를 관리하고, 리소스를 추가할 때 고유한 URI를 서버에서 자동 생성합니다.
    • 특징:
      • 라이언트는 리소스를 추가하고 싶다는 요청만 보냅니다.
      • 리소스의 URI(주소)는 서버가 생성하고 반환합니다.
      • 이는 **컬렉션(collection)**에서 사용하는 방식입니다. 컬렉션은 여러 리소스를 포함한 그룹이므로, 서버가 새로 생성된 리소스의 URI를 관리합니다.
    • 예시:
      • 클라이언트 요청:
        POST /users
        Content-Type: application/json
        
        {
          "name": "John Doe",
          "email": "john.doe@example.com"
        }
        
      • 서버 응답:
        HTTP/1.1 201 Created
        Location: /users/123
        
      • 서버가 생성한 URI는 /users/123입니다.

2. HTTP API - 스토어

  • PUT 기반 등록
    • 설명: 클라이언트가 리소스 URI를 미리 결정하고, 그 URI로 데이터를 전송해 리소스를 생성합니다.
    • 특징:
      • 클라이언트가 리소스의 URI를 지정합니다.
      • 이는 **스토어(store)**에서 사용하는 방식입니다. 스토어는 클라이언트가 URI를 알고 있으며, 리소스를 직접 관리할 수 있습니다.
    • 예시:
      • 클라이언트 요청:
        PUT /users/johndoe
        Content-Type: application/json
        
        {
          "name": "John Doe",
          "email": "john.doe@example.com"
        }
        
      • 서버 응답:
        HTTP/1.1 201 Created
        
      • 클라이언트가 /users/johndoe라는 URI를 지정했고, 서버는 이를 받아 생성했습니다.

3. HTML FORM 사용

  • 순수 HTML + HTML form 사용
    • 설명: 순수 HTML에서는 주로 **HTML 폼(form)**을 사용하여 데이터를 서버로 전송하며, HTTP 메서드로 GETPOST만 지원합니다.
    • 특징:
      • HTML 표준에 따라 PUT, DELETE와 같은 HTTP 메서드는 지원하지 않습니다.
      • 따라서 HTML form으로는 리소스를 수정하거나 삭제하는 기능을 구현할 수 없고, 오직 데이터 조회(GET)와 등록(POST)만 가능합니다.
    • 예시:
      • HTML form:
        <form action="/users" method="post">
          <input type="text" name="name" value="John Doe">
          <input type="email" name="email" value="john.doe@example.com">
          <button type="submit">Submit</button>
        </form>
        
      • 폼 제출 시 서버로 전송되는 요청:
        POST /users
        Content-Type: application/x-www-form-urlencoded
        
        name=John+Doe&email=john.doe%40example.com
        

요약 비교

  컬렉션 (POST)  스토어 (PUT) HTML FORM
URI 결정 주체 서버가 결정 클라이언트가 결정 서버가 결정
HTTP 메서드 POST PUT GET, POST
사용 사례 새로운 사용자 등록 특정 사용자 이름으로 계정 생성 간단한 데이터 입력
HTML 표준과의 관계 HTML 표준과 독립적 HTML 표준과 독립적 HTML 표준에 기반

 

 

URI (Uniform Resource Identifier)

URI는 인터넷 상의 리소스를 식별하는 문자열입니다. 즉, 웹의 특정 자원(예: 웹 페이지, 이미지, 동영상 등)을 나타내는 주소라고 할 수 있습니다. URI는 두 가지 형태로 나타납니다:

 

참고하면 좋은 URI 설계 개념

[1]  문서(document)

  • 단일 개념(파일 하나, 객체 인스턴스, 데이터베이스 row)
  • 예) /members/100, /les/star.jpg
  • (책 한 권)

[2]  컬렉션(collection)

  • 서버가 관리하는 리소스 디렉터리
  • 서버가 리소스의 URI를 생성하고 관리
  • 예) /members
  • (책 목록)

[3]  스토어(store)

  • 클라이언트가 관리하는 자원 저장소
  • 클라이언트가 리소스의 URI를 알고 관리
  • 예) /les
  • (회원의 대출 기록)

[4]  컨트롤러(controller), 컨트롤 URI

  • 문서, 컬렉션, 스토어로 해결하기 어려운 추가 프로세스 실행
  • 동사를 직접 사용
  • 예) /members/{id}/delete
  • (책 반납)

 

 

 

HTTP API - 컬렉션

📌 POST 기반 등록

  •  예) 회원 관리 API 제공

 

 

클라이언트는 등록될 리소스의 URI를 모른다.

  • 회원 등록 /members -> POST
  • POST /members

 

서버가 새로 등록된 리소스 URI를 생성해준다.

  • HTTP/1.1 201 Created
  • Location: /members/100

 

컬렉션(Collection)

  • 서버가 관리하는 리소스 디렉토리
  • 서버가 리소스의 URI를 생성하고 관리
  • 여기서 컬렉션은 /members

 

 

HTTP API - 스토어

📌 PUT 기반 등록

  • 예) 정적 컨텐츠 관리, 원격 파일 관리

 

 

클라이언트가 리소스 URI를 알고 있어야 한다.

  • 파일 등록 /les/{lename} -> PUT
  • PUT /les/star.jpg

 

클라이언트가 직접 리소스의 URI를 지정한다.

 

스토어(Store)

  • 클라이언트가 관리하는 리소스 저장소
  • 클라이언트가 리소스의 URI를 알고 관리
  • 여기서 스토어는 /files

 

 

HTML FORM 사용

📌 웹 페이지 회원 관리

  • HTML FORM은 GET, POST만 지원
  • AJAX 같은 기술을 사용해서 해결 가능 -> 회원 API 참고
  • 여기서는 순수 HTML, HTML FORM 이야기
  • GET, POST만 지원하므로 제약이 있음

 

컨트롤 URI

  • GET, POST만 지원하므로 제약이 있음
  • 이런 제약을 해결하기 위해 동사로 된 리소스 경로 사용
  • POST의 /new, /edit, /delete가 컨트롤 URI
  • HTTP 메서드로 해결하기 애매한 경우 사용(HTTP API 포함)

 

 

AJAX (Asynchronous JavaScript And XML)

 🐳 AJAX는 웹 페이지에서 동적으로 데이터를 가져오거나 서버와 통신을 할 수 있게 해주는 기술입니다. 페이지를 전체적으로 새로고침하지 않고도 서버와 데이터를 교환할 수 있어(비동기 통신), 더 빠르고 부드러운 사용자 경험을 제공합니다.

 

1. AJAX의 주요 특징

  • 비동기적 통신: 서버와 클라이언트 간의 통신이 백그라운드에서 이루어지며, 페이지 전체를 새로고침하지 않고도 데이터를 업데이트할 수 있습니다.
  • 빠른 응답 속도: 필요한 데이터만 가져오기 때문에 전체 페이지를 다시 로드하는 것보다 훨씬 빠릅니다.
  • XML 또는 JSON 사용: 초기에는 XML을 주로 사용했지만, 현재는 가볍고 사용하기 쉬운 JSON이 더 많이 사용됩니다.
  • 사용자 경험 개선: 인터페이스가 더 부드럽고 동적으로 동작하며, 응답 시간이 단축됩니다.

2. AJAX의 구성 요소

AJAX는 단일 기술이 아니라 여러 기술의 조합입니다:

  1. HTML/CSS: 웹 페이지의 구조와 스타일 정의.
  2. JavaScript: 비동기 요청을 수행하고, 데이터를 처리 및 업데이트.
  3. XMLHttpRequest (XHR): 서버와 데이터를 교환하기 위한 브라우저 API.
  4. 서버 측 언어 (PHP, Python, Node.js 등): 클라이언트의 요청을 처리하고 데이터를 반환.
  5. 데이터 포맷 (JSON/XML): 서버와 클라이언트 간의 데이터 교환 형식.

3. AJAX 동작 방식

AJAX는 다음과 같은 방식으로 작동합니다:

  1. 사용자 이벤트 발생
    버튼 클릭, 폼 제출, 스크롤 등 사용자가 이벤트를 트리거합니다.
  2. AJAX 요청 생성
    XMLHttpRequest 객체 또는 fetch API를 사용해 서버에 요청을 보냅니다.
  3. 서버 처리
    서버는 클라이언트의 요청을 처리하고 필요한 데이터를 반환합니다.
  4. 응답 처리
    클라이언트는 서버로부터 받은 데이터를 처리하여 웹 페이지의 특정 부분을 업데이트합니다.

4. AJAX 코드 예제

(1) XMLHttpRequest 예제

const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data', true);

xhr.onload = function () {
  if (xhr.status === 200) {
    console.log('Response:', xhr.responseText);
  } else {
    console.error('Error:', xhr.status);
  }
};

xhr.send();

(2) Fetch API 예제 (추천)

fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => {
    console.log('Data:', data);
  })
  .catch(error => {
    console.error('Error:', error);
  });

5. AJAX의 활용 사례

  • 실시간 검색: 사용자가 검색창에 입력하면 결과를 실시간으로 가져옴.
  • 무한 스크롤: 페이지를 끝까지 스크롤하면 추가 데이터를 자동으로 로드.
  • 폼 검증: 데이터를 입력할 때 즉시 유효성을 검사.
  • 대시보드 업데이트: 실시간 통계를 제공하는 대시보드.
  • 채팅 애플리케이션: 메시지가 실시간으로 교환되는 채팅 시스템.

6. AJAX의 한계

  • CORS 문제: 다른 도메인에서 데이터를 요청하면 보안상의 제한이 있을 수 있습니다.
  • SEO 문제: AJAX를 사용한 데이터 로딩은 검색 엔진이 크롤링하기 어려울 수 있습니다.
  • 브라우저 호환성: 일부 오래된 브라우저에서 완벽히 작동하지 않을 수 있음.

7. AJAX와 관련된 최신 기술

  • Axios: Fetch API보다 사용하기 쉬운 AJAX 라이브러리.
  • GraphQL: REST API 대신 사용하는 데이터 쿼리 언어.
  • WebSocket: AJAX를 대체할 수 있는 양방향 통신 기술.

 

'CS ( Computer Science ) > 네트워크 (Networking)' 카테고리의 다른 글

[Net] Restful API  (1) 2026.08.03
[Net] JSON  (1) 2026.07.26
[Net] 네트워크 요약  (1) 2025.01.22
[Net] Filter  (1) 2025.01.01
[Net] Cookie  (1) 2024.12.28

Scale Up

📌 수직적 확장

  • 단일 서버의 하드웨어의 사용을 높인다. (CPU, Memory 등의 스펙을 높인다)
  • 요청에 대한 처리를 더욱 빠르게 할 수 있도록 만든다.

.

 

Scale Out

📌 수평적 확장

  • 같은 사양의 서버(인스턴스)를 여러 대 배치한다.
  • 동시에 더 많은 사용자 요청을 처리할 수 있도록 만든다.

 

 

MSA ( MicroService Architecture )

📌 MSA는 애플리케이션을 독립적으로 배포 및 실행 가능한 작은 서비스 단위로 나누어 개발하는 소프트웨어 아키텍처 스타일입니다.

  • 각 마이크로서비스는 특정 비즈니스 기능을 담당하며, 서로 독립적으로 배포, 수정, 확장할 수 있습니다.
  • 소프트웨어를 작은 단위의 독립적인 서비스로 분리해 개발 및 운영 효율성을 높이는 구조입니다.

[1]  MSA의 주요 특징:

  1. 독립적인 서비스
    • 각 서비스는 별도의 코드베이스와 데이터베이스를 사용.
    • 서비스 간 통신은 API나 메시지 큐를 통해 이루어짐.
  2. 작은 단위의 배포 가능
    • 전체 시스템을 멈추지 않고, 개별 서비스만 업데이트 가능.
  3. 다양한 기술 스택 허용
    • 각 서비스는 적합한 언어와 프레임워크로 개발 가능.
  4. 자율적인 개발 팀
    • 각 서비스는 독립된 팀이 관리하며, 빠른 개발 주기를 지원.

[2] MSA의 배달 비유:

  1. MSA = 여러 음식점이 협력하는 배달 서비스
    • MSA는 한 곳에서 모든 음식을 제공하는 대형 레스토랑(모놀리식 아키텍처) 대신,
      피자, 치킨, 초밥처럼 특정 음식만 제공하는 **개별 음식점(마이크로서비스)**의 협력 구조와 비슷합니다.
  2. 독립적 운영
    • 각 음식점은 독립적으로 운영되며, 주문이 들어오면 각 음식점에서 필요한 부분만 처리합니다.
    • 💡 비유: "치킨 배달은 치킨집에서, 피자 배달은 피자집에서!"
  3. 확장성
    • 특정 음식점(서비스)에 주문이 몰리면, 해당 음식점만 인력을 추가하거나 확장하면 됩니다.
    • 💡 비유: 치킨 주문이 많아지면 치킨집만 추가 배달원을 고용.
  4. 다양한 전문성
    • 각 음식점은 자신만의 레시피와 조리 도구를 사용해 고유한 맛을 유지합니다.
    • 💡 비유: 치킨집은 튀김 기계를, 피자집은 화덕을 사용!

 

[3] MSA의 장점:

  1. 유연한 개발 및 배포
    • 특정 서비스에 문제가 생겨도, 다른 서비스에 영향을 주지 않음.
    • 독립 배포가 가능해 빠른 기능 추가 문제 수정이 가능.
  2. 확장성
    • 트래픽이 많은 서비스만 별도로 확장 가능.
    • 예: 주문 처리 서비스만 서버 추가.
  3. 기술 다양성
    • 서비스마다 최적의 기술 스택 선택 가능.
  4. 유지보수 용이
    • 작은 코드베이스로 관리가 쉬움.
    • 새로운 팀원이 빠르게 이해 가능.
 

 

[4] MSA의 단점:

  1. 복잡한 관리
    • 서비스 간 통신, 배포, 모니터링 등을 위한 인프라 복잡성 증가.
  2. 데이터 일관성 문제
    • 분산된 데이터베이스로 인해 실시간 동기화가 어렵고, 트랜잭션 관리가 복잡.
  3. 통신 비용 증가
    • 서비스 간 API 호출로 인해 네트워크 지연 성능 저하 가능성.
  4. 초기 설계 및 구축 비용
    • MSA를 지원하기 위한 CI/CD, 컨테이너 관리, 모니터링 시스템 구축 필요.

 

[5] MSA 사용 사례:

  1. 대규모 트래픽 처리
    • Amazon, Netflix와 같은 대규모 시스템은 특정 서비스만 확장하여 효율적 관리.
  2. 빠른 기능 추가와 배포
    • 스타트업이나 애자일 개발 환경에서 자주 사용.
  3. 다양한 비즈니스 로직 분리
    • 주문 처리, 결제, 사용자 인증 등을 별도 서비스로 분리.

 

[6] MSA와 모놀리식 아키텍처 비교:

필드 = 객체의 속성

필드는 객체의 데이터를 저장하는 역할을 한다.

  • 객체의 필드는 크게 고유한 데이터, 상태 데이터, 객체 데이터로 분류할 수 있다.
  • 이처럼 자동차 객체는 4개의 고유한 데이터와 3개의 상태 데이터 그리고 3개의 객체 데이터를 가질 수 있다.
    • 우리가 처음 소프트웨어의 부품을 객체라 표현한다.
    • 이 3개의 객체 데이터를 자동차를 만들기 위한 부품 데이터라고 이해해도 좋다.
public class Car {

    String company; // 자동차 회사
    String model; // 자동차 모델
    String color; // 자동차 색상
    double price; // 자동차 가격

    double speed;  // 자동차 속도 , km/h
    char gear; // 기어의 상태, P,R,N,D
    boolean lights; // 자동차 조명의 상태

    Tire tire;
    Door door;
    Handle handle;

    public Car() {} // 기본 생성자

    double gasPedal(double kmh) {
        speed = kmh;
        return speed;
    }

    double brakePedal() {
        speed = 0;
        return speed;
    }

    char changeGear(char type) {
        gear = type;
        return gear;
    }

    boolean onOffLights() {
        lights = !lights;
        return lights;
    }

		void horn() {
		    System.out.println("빵빵");
		}
}

 

우리가 정의하여 선언한 클래스의 필드들은 기본적으로 초기값을 제공하지 않을 경우 객체가 생성될 때 자동으로 기본값으로 초기화된다.

  • 초기값을 제공하는 방법은 ‘필드 타입 필드명 = 값;’ 이렇게 직접 초기화할 수 있다.
    • String model = "Gv80"; 

 

필드 사용방법

필드를 사용한다’라는 의미는 필드의 값을 변경하거나 읽는 것을 의미합니다.

  • 우리가 클래스에 필드를 정의하여 선언했다고 해서 바로 사용할 수 있는 것은 아닙니다.
  • 클래스는 설계도일 뿐 실제로 필드의 데이터를 가지고 있는 것은 객체입니다.
  • 따라서 객체를 생성한 후에 필드를 사용할 수 있습니다. 
  • 간단히, 클래스는 설계도이다. 붕어빵 틀 설계도에 속(데이터)를 넣을 수 없다. 붕어빵 틀(객체)에 속(데이터)를 넣어야한다.
  • 외부 접근
    • Car car = new Car();
      • 이렇게 객체를 생성했다면 우리는 참조 변수 car를 이용하여 외부에서 객체 내부의 필드에 접근하여 사용할 수 있습니다.
      • 이때 객체의 내부 필드에 접근하는 방법은 도트(.) 연산자를 사용하면 됩니다.
        • car.color = "blue";
  • 내부 접근
    • 도트 연산자를 사용하여 외부에서 객체 내부에 접근할 수 있을 뿐만 아니라 객체 내부 메서드에서도 내부 필드에 접근할 수 있습니다.
double brakePedal() {
    speed = 0;
    return speed;
}
  • 이처럼 brakePedal() 메서드 내부에서 객체의 필드 speed를 바로 호출해서 사용할 수 있습니다.

 

public class Car {

    String company; // 자동차 회사
    String model = "Gv80"; // 자동차 모델
    String color; // 자동차 색상
    double price; // 자동차 가격

    double speed;  // 자동차 속도 , km/h
    char gear; // 기어의 상태, P,R,N,D
    boolean lights = true; // 자동차 조명의 상태

    Tire tire = new Tire();
    Door door;
    Handle handle;

    public Car() {} // 기본 생성자

    double gasPedal(double kmh) {
        speed = kmh;
        return speed;
    }

    double brakePedal() {
        speed = 0;
        return speed;
    }

    char changeGear(char type) {
        gear = type;
        return gear;
    }

    boolean onOffLights() {
        lights = !lights;
        return lights;
    }

		void horn() {
		    System.out.println("빵빵");
		}
}

//- model 필드 값에 “Gv80” 초기값을 주겠습니다.
//- lights 필드 값에 true 초기값을 주겠습니다.
//- tire 필드 값에 `new Tire()` 초기값을 주겠습니다.

 

main 메서드를 사용하여 테스트한 경우

public class Main {
    public static void main(String[] args) {
        Car car = new Car(); // 객체 생성

        // 초기값과 기본값 확인하기

        System.out.println("car.model = " + car.model); // 초기값 "Gv80"이 출력됩니다.
        System.out.println("car.color = " + car.color); // 기본값 null이 출력됩니다.
        System.out.println();

        System.out.println("car.speed = " + car.speed); // 기본값 0.0이 출력됩니다.
        System.out.println("car.gear = " + car.gear);  // 기본값 \u0000(공백)이 출력됩니다.
        System.out.println("car.lights = " + car.lights); // 초기값 true가 출력됩니다.
        System.out.println();

        System.out.println("car.tire = " + car.tire); // 초기값 인스턴스의 주소가 출력됩니다.
        System.out.println("car.door = " + car.door); // 기본값 null이 출력됩니다.
        System.out.println();

        // 필드 사용

        car.color = "blue"; // 필드 color에 "blue" 데이터를 저장합니다.
        car.speed = 100;    // 필드 speed에 100 데이터를 저장합니다.
        car.lights = false; // 필드 lights에 false 데이터를 저장합니다.

        System.out.println("car.color = " + car.color); // 저장된 "blue" 데이터가 출력됩니다.
        System.out.println("car.speed = " + car.speed); // 저장된 100.0 데이터가 출력됩니다.
        System.out.println("car.lights = " + car.lights); // 저장된 false 데이터가 출력됩니다.

    }
}

 

 

 

 

메서드 = 객체의 행위

  • 특정 작업을 수행하는 코드 블록, 객체 지향 프로그래밍에서 메서드는 주로 클래스 내부에 정의되며, 해당 클래스의 객체에서 호출하여 사용할 수 있다. 메서드는 작업을 캡슐화하여 코드의 재사용성을 높이고, 유지보수와 확장성을 용이하게 한다.
<접근 제어자> <반환 타입> <메서드 이름>(<매개변수>) {
    // 메서드 본문 (실제 작업을 수행)
    return <값>;
}

 

반환(리턴) 타입

double brakePedal() {...} // double 타입 반환
char changeGear(char type) {...} // char 타입 반환
boolean onOffLights() {...} // boolean 타입 반환
void horn() {...} // 반환할 값 없음
  • 리턴 타입이란 메서드가 실행된 후 호출을 한 곳으로 값을 반환할 때 해당 값의 타입을 의미한다.
    • return 리턴 타입의 반환값;
    • 주의할 점은 메서드에 리턴 타입을 선언하여 반환할 값이 있다면 반드시 return 문으로 해당하는 리턴 타입의 반환값을 지정해야 한다.
  • 반환할 값이 없을 때는 리턴 타입에 void를 작성해야 한다.
    • 반환값이 없음으로 return문을 반드시 지정할 필요는 없습다.
    • 메서드는 실행할 때 return문을 만나면 그대로 종료하게 되는데 void 타입일 때 return; 이렇게 return문을 사용하여 원하는 지점에서 메서드를 종료할 수도 있다.

매개변수

double gasPedal(double kmh, char type) {
    speed = kmh;
    return speed;
}
  • 매개변수는 메서드를 호출할 때 메서드로 전달하려는 값을 받기 위해 사용되는 변수이다.
  • 위 gasPedal(double kmh, char type) 메서드의 매개변수는 double 타입의 kmh, char 타입의 type이다.
    • 해당 매개변수에 값을 전달하기 위해서는 순서와 타입에 맞춰 값을 넣어주면 된다.
    • gasPedal(100, 'D');
  • 전달하려는 값이 없다면 생략 가능하다.

 

가변길이 매개변수 

void carSpeeds(double ... speeds) {
    for (double v : speeds) {
        System.out.println("v = " + v);
    }
}
  • double … speeds 이렇게 … 을 사용하면 아래처럼 매개값을 , 로 구분하여 개수 상관없이 전달 가능하다.
  • carSpeeds(100, 80);
  • carSpeeds(110, 120, 150);

 

 

메서드 호출 방법

‘메서드를 호출한다’라는 의미는 메서드의 블록 내부에 작성된 코드를 실행한다는 의미입니다.

  • 필드와 마찬가지로 클래스의 메서드를 정의하여 선언했다고 해서 바로 사용할 수 있는 것은 아닙니다.
  • 클래스는 설계도일 뿐 메서드는 객체의 행위를 정의한 것입니다.
  • 따라서 객체를 생성한 후에 메서드를 사용할 수 있습니다. 
  • 외부 접근
    • Car car = new Car();
      • 이렇게 객체를 생성했다면 우리는 참조 변수 car를 이용하여 외부에서 객체 내부의 메서드에 접근하여 호출할 수 있습니다.
      • 이때 객체의 내부 메서드에 접근하는 방법은 도트(.) 연산자를 사용하면 됩니다.
        • car.brakePedal();
      • 또한 메서드가 매개변수를 가지고 있다면 반드시 호출할 때 매개변수의 순서와 타입에 맞게 매개값을 넣어줘야 합니다.
        • car.gasPedal(100, 'D');
  • 내부 접근
    • 도트 연산자를 사용하여 외부에서 객체 내부에 접근할 수 있을 뿐만 아니라 객체 내부 메서드에서도 내부 메서드에 접근하여 호출할 수 있습니다.
      • 아래처럼 gasPedal(double kmh, char type) 메서드 내부에서 해당 객체의 changeGear(type); 메서드를 호출할 수 있습니다.
double gasPedal(double kmh, char type) {
    changeGear(type);
    speed = kmh;
    return speed;
}
  • 반환 값 저장
    • 메서드의 리턴 타입을 선언하여 반환할 값이 있다면 변수를 사용하여 받아줄 수 있습니다.
      • 반드시 리턴 타입과 변수의 타입이 동일하거나 자동 타입 변환될 수 있어야 합니다.
    double speed = car.gasPedal(100, 'D');
    
    • double 타입의 변수 speed를 사용하여 double gasPedal(double kmh, char type) 메서드의 double 타입의 반환값을 받아 저장할 수 있습니다.
public class Car {

    String company; // 자동차 회사
    String model; // 자동차 모델
    String color; // 자동차 색상
    double price; // 자동차 가격

    double speed;  // 자동차 속도 , km/h
    char gear = 'P'; // 기어의 상태, P,R,N,D
    boolean lights; // 자동차 조명의 상태

    public Car() {} // 기본 생성자

    double gasPedal(double kmh, char type) {
        changeGear(type);
        speed = kmh;
        return speed;
    }

    double brakePedal() {
        speed = 0;
        return speed;
    }

    char changeGear(char type) {
        gear = type;
        return gear;
    }

    boolean onOffLights() {
        lights = !lights;
        return lights;
    }

		void horn() {
		    System.out.println("빵빵");
		}

    void carSpeeds(double ... speeds) {
        for (double v : speeds) {
            System.out.println("v = " + v);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Car car = new Car(); // 객체 생성

        // 메서드 호출 및 반환값 저장
        double speed = car.gasPedal(100, 'D');
        System.out.println("speed = " + speed);

        boolean lights = car.onOffLights();
        System.out.println("lights = " + lights);

        System.out.println();
        // gasPedal 메서드 내부에 호출된 changeGear(type); 메서드의 결과 확인
        // gear의 초기값은 'P'
        System.out.println("car.gear = " + car.gear); // 'D' 출력

        System.out.println();
        // 가변길이 매개변수 확인
        car.carSpeeds(100, 80);
        System.out.println();
        car.carSpeeds(110, 120, 150);
    }
}

 

 

오버로딩

  • 같은 이름의 메서드나 생성자 매개변수의 개수나 타입이 달라지도록 여러 번 정의하는 기법입니다. 오버로딩을 사용하면 같은 이름으로 다양한 작업을 처리할 수 있습니다.

오버로딩의 특징

  • 같은 이름의 메서드나 생성자지만 매개변수의 개수나 타입이 달라야 합니다.
  • 반환 타입은 오버로딩을 구별하는 기준이 되지 않습니다.
  • 컴파일 시점에 메서드 호출을 구분하기 때문에, 실행 시간에 결정되는 것이 아니라 호출 시점에서 적절한 메서드가 선택됩니다.

오버로딩의 조건

  • 메서드의 이름이 같고, 매개변수의 개수, 타입, 순서가 달라야 합니다.
  • '응답 값만' 다른 것은 오버로딩을 할 수 없습니다.
  • 접근 제어자만 다른 것도 오버로딩을 할 수 없습니다.
  • 결론, 오버로딩은 매개변수의 차이로만 구현할 수 있습니다.

오버로딩의 장점

  • 코드의 가독성 향상: 비슷한 작업을 수행하는 메서드를 같은 이름으로 처리할 수 있어 코드가 깔끔하고 이해하기 쉬워집니다.
  • 유지보수 용이성: 같은 이름의 메서드를 사용하여 여러 매개변수에 대한 처리 로직을 관리할 수 있어 유지보수가 용이합니다.

오버로딩 규칙

  1. 매개변수의 타입이 달라야 오버로딩으로 인식됩니다.
  2. 매개변수의 개수가 달라야 오버로딩으로 인식됩니다.
  3. 매개변수의 순서가 달라야 오버로딩으로 인식됩니다.
public class PrintStream extends FilterOutputStream
    implements Appendable, Closeable
{
			...
			
		public void println() {
        newLine();
    }

    public void println(boolean x) {
        if (getClass() == PrintStream.class) {
            writeln(String.valueOf(x));
        } else {
            synchronized (this) {
                print(x);
                newLine();
            }
        }
    }

    public void println(char x) {
        if (getClass() == PrintStream.class) {
            writeln(String.valueOf(x));
        } else {
            synchronized (this) {
                print(x);
                newLine();
            }
        }
    }

    public void println(int x) {
        if (getClass() == PrintStream.class) {
            writeln(String.valueOf(x));
        } else {
            synchronized (this) {
                print(x);
                newLine();
            }
        }
    }

    public void println(long x) {
        if (getClass() == PrintStream.class) {
            writeln(String.valueOf(x));
        } else {
            synchronized (this) {
                print(x);
                newLine();
            }
        }
    }

    public void println(float x) {
        if (getClass() == PrintStream.class) {
            writeln(String.valueOf(x));
        } else {
            synchronized (this) {
                print(x);
                newLine();
            }
        }
    }

    public void println(double x) {
        if (getClass() == PrintStream.class) {
            writeln(String.valueOf(x));
        } else {
            synchronized (this) {
                print(x);
                newLine();
            }
        }
    }

    public void println(char[] x) {
        if (getClass() == PrintStream.class) {
            writeln(x);
        } else {
            synchronized (this) {
                print(x);
                newLine();
            }
        }
    }

    public void println(String x) {
        if (getClass() == PrintStream.class) {
            writeln(String.valueOf(x));
        } else {
            synchronized (this) {
                print(x);
                newLine();
            }
        }
    }

    public void println(Object x) {
        String s = String.valueOf(x);
        if (getClass() == PrintStream.class) {
            // need to apply String.valueOf again since first invocation
            // might return null
            writeln(String.valueOf(s));
        } else {
            synchronized (this) {
                print(s);
                newLine();
            }
        }
    }


		  ...
}

 

 

기본형 & 참조형 매개변수

 

기본형 매개변수

  • 매개변수의 타입이 기본형일 때는 값 자체가 복사되어 넘어가기 때문에 매개값으로 지정된 변수의 원본 값이 변경되지 않습니다.
  • 메서드를 호출할 때 전달할 매개값으로 지정한 값을 메서드의 매개변수에 복사해서 전달합니다.

참조형 매개변수

  • 매개변수를 참조형으로 선언하면 값이 저장된 곳의 원본 주소를 알 수 있기 때문에 값을 읽어 오는 것은 물론 값을 변경하는 것도 가능합니다.
  • 메서드의 매개변수뿐만 아니라 반환 타입도 참조형이 될 수 있습니다.
    • 반환 타입이 참조형이라는 것은 반환하는 값의 타입이 “실제 값의 주소”라는 의미입니다.
public class Car {

    String company; // 자동차 회사
    String model; // 자동차 모델
    String color; // 자동차 색상
    double price; // 자동차 가격

    double speed;  // 자동차 속도 , km/h
    char gear; // 기어의 상태, P,R,N,D
    boolean lights; // 자동차 조명의 상태

    Tire tire;
    Door door = new Door();
    Handle handle = new Handle();

    public Car() {} // 기본 생성자

    double gasPedal(double kmh, char type) {
        changeGear(type);
        speed = kmh;
        return speed;
    }

    double brakePedal(char type) {
        speed = 0;
        type = 'P'; // 정지 후 매개변수 type을 어떤 타입으로 전달 받았는지 상관없이 'P'로 고정시키기
        changeGear(type);
        return speed;
    }

    char changeGear(char type) {
        gear = type;
        return gear;
    }

    boolean onOffLights() {
        lights = !lights;
        return lights;
    }

		void horn() {
		    System.out.println("빵빵");
		}

    Tire setTire(Tire tireCompany) {
        tireCompany.company = "KIA"; // 금호 타이어를 전달 받았지만 강제로 KIA 타이어로 교체
        tire = tireCompany;
        return tire;
    }
}
public class Tire {
    String company; // 타이어 회사
    public Tire() {}
}
public class Main {
    public static void main(String[] args) {
        Car car = new Car(); // 객체 생성

        // 기본형 매개변수
        char type = 'D';
        car.brakePedal(type);

        // 메서드 실행 완료 후 전달할 매개값으로 지정된 type 값 확인
        System.out.println("type = " + type); // 기존에 선언한 값 'D' 출력, 원본 값 변경되지 않음
        // 메서드 실행 완료 후 반환된 car 인스턴스의 gear 타입 확인
        System.out.println("gear = " + car.gear); // 객체 내부에서 type을 변경하여 수정했기 때문에 'P' 출력

        System.out.println();
        // 참조형 매개변수
        Tire tire = new Tire();
        tire.company = "금호"; // 금호 타이어 객체 생성

        // 차 객체의 타이어를 등록하는 메서드 호출한 후 반환값으로 차 객체의 타이어 객체 반환
        Tire carInstanceTire = car.setTire(tire);

        // 메서드 실행 완료 후 전달할 매개값으로 지정된 참조형 변수 tire의 company 값 확인
        System.out.println("tire.company = " + tire.company); // "KIA" 출력
        // 전달할 매개값으로 지정된 tire 인스턴스의 주소값이 전달되었기 때문에 호출된 메서드에 의해 값이 변경됨.

        // 메서드 실행 완료 후 반환된 car 인스턴스의 tire 객체 값이 반환되어 저장된 참조형 변수 carInstanceTire의 company 값 확인
        System.out.println("carInstanceTire.company = " + carInstanceTire.company); // "KIA" 출력
    }
}

 

'Back-End (Web) > JAVA' 카테고리의 다른 글

[JAVA] 자바의 정렬  (0) 2026.05.31
[JAVA] 인스턴스 멤버와 클래스 멤버  (1) 2026.05.28
[JAVA] 생성자  (1) 2026.05.19
[JAVA] 인터페이스  (2) 2026.05.05
[JAVA] 응용 정리  (1) 2026.04.21

+ Recent posts