JRE의 숨겨진 보물들: 런타임 도구들 완전 해부

Java를 사용하다 보면 JRE에 대해 "그냥 Java 프로그램을 실행하는 환경"이라고만 알고 계시는 분들이 많아요. 하지만 JRE 안에는 생각보다 많은 유용한 도구들이 숨어있답니다! 오늘은 JRE의 런타임 도구들에 대해 자세히 알아보겠습니다. 🔍

🎯 JRE 런타임 도구들이란?

JRE의 런타임 도구들은 Java 애플리케이션이 실행되는 동안 필요한 핵심 유틸리티들입니다.

개발할 때 사용하는 JDK 도구들과는 달리, 이 도구들은 실제 운영 환경에서 애플리케이션이 돌아갈 때 필요한 기능들을 제공해요.


⭐ 핵심 런타임 도구들

1. java (Java 런처) - 가장 중요한 도구!

java MyProgram
java -jar myapp.jar
java -cp /path/to/classes MyProgram

역할: 컴파일된 Java 프로그램(.class 파일)을 실행
기능: JVM을 시작하고 애플리케이션을 로드하는 메인 실행 도구

💡 실무 팁: -Xmx2g 같은 JVM 옵션을 통해 메모리 설정을 최적화할 수 있어요!


2. keytool (키 및 인증서 관리)

keytool -genkey -keystore mystore.jks
keytool -list -keystore mystore.jks  
keytool -import -file cert.crt -keystore mystore.jks

역할: 디지털 인증서와 키 저장소 관리
용도: HTTPS, 코드 서명, 보안 통신에 필요한 인증서 관리

실제 사용 예시:

# HTTPS용 인증서 생성
keytool -genkeypair -alias myserver -keyalg RSA -keysize 2048 \
        -validity 365 -keystore server.jks

3. rmiregistry (RMI 레지스트리)

rmiregistry 1099

역할: RMI 원격 객체 등록 및 조회 서비스
용도: 클라이언트가 원격 객체를 찾을 수 있게 하는 네임 서버

언제 사용하나요?

  • 분산 Java 애플리케이션 개발 시
  • 마이크로서비스 간 통신이 필요한 경우

4. rmid (RMI 활성화 데몬)

rmid -port 1098

역할: RMI(Remote Method Invocation) 객체 활성화 서비스
용도: 분산 Java 애플리케이션에서 원격 객체 관리


5. servertool (IDL 서버 도구)

servertool -ORBInitialPort 1050

역할: CORBA 서버 관리
용도: 분산 객체 시스템에서 서버 등록/해제


6. tnameserv (임시 네임 서버)

tnameserv -ORBInitialPort 1050

역할: CORBA 네임 서비스 제공
용도: 분산 환경에서 객체 이름 해석


🚀 실제 운영 환경에서의 활용

웹 애플리케이션 배포

# Spring Boot 애플리케이션을 프로덕션에서 실행
java -jar -Xmx2g -Dspring.profiles.active=prod mywebapp.jar

보안 인증서 관리 (HTTPS 설정)

# 1. 인증서 생성
keytool -genkeypair -alias myserver -keyalg RSA -keystore server.jks

# 2. 인증서 확인
keytool -list -keystore server.jks

# 3. 외부 인증서 임포트
keytool -import -file letsencrypt.crt -keystore server.jks

분산 시스템 구축

# 1. RMI 레지스트리 시작
rmiregistry &

# 2. RMI 서버 실행  
java -Djava.rmi.server.codebase=http://myserver/classes/ MyRMIServer

# 3. 클라이언트 연결
java MyRMIClient

📊 JDK vs JRE 도구 비교

구분 JRE 런타임 도구 JDK 개발 도구

목적 실행 시점 지원 개발 시점 지원
대표 도구 java, keytool, rmiregistry javac, jar, javadoc
사용 환경 운영 서버, 프로덕션 개발자 로컬 환경
사용자 시스템 관리자, DevOps 개발자

💡 알아두면 좋은 실무 팁

자주 사용하는 도구들

  • java: 🔥 필수 - 모든 Java 애플리케이션 실행의 핵심
  • keytool: 🔒 중요 - HTTPS나 보안이 중요한 서비스에서 필수

잘 사용하지 않는 도구들

  • RMI 관련 도구들: 요즘은 REST API나 gRPC를 더 많이 사용
  • CORBA 관련 도구들: 레거시 시스템에서나 가끔 사용

주의사항 ⚠️

  • policytool: Java 10부터 제거되었으니 참고하세요
  • 대부분의 도구들은 Spring Boot, Tomcat 같은 프레임워크가 내부적으로 사용해요

🎯 정리

JRE 런타임 도구들의 핵심:

  • Java 애플리케이션이 실행될 때 필요한 유틸리티들
  • 주로 보안, 네트워킹, 분산처리 기능 제공
  • 개발자보다는 운영 환경에서 주로 활용
  • javakeytool이 가장 실용적이고 자주 사용됨

한 줄 요약: JRE는 단순한 실행 환경이 아니라, 운영에 필요한 다양한 도구들을 포함한 완전한 런타임 생태계입니다! 🌟


이 포스트가 도움이 되셨다면 좋아요와 댓글 부탁드려요! JVM이나 다른 Java 관련 주제도 궁금하시면 언제든 댓글로 요청해 주세요! 😊

태그: #Java #JRE #런타임도구 #keytool #RMI #Java실행환경 #백엔드개발

Java 개발 필수 상식: JDK와 JRE의 차이점 완벽 정리

Java를 처음 배우거나 개발 환경을 구축할 때 가장 헷갈리는 부분 중 하나가 바로 JDKJRE입니다. 이 둘의 차이를 제대로 알아야 내 상황에 맞는 올바른 선택을 할 수 있어요. 오늘은 이 두 개념을 쉽고 명확하게 정리해드릴게요!

🎯 JRE (Java Runtime Environment)란?

JRE는 Java 애플리케이션을 실행하기 위한 환경입니다.

JRE의 구성요소

  • JVM (Java Virtual Machine) - 바이트코드를 실행하는 가상머신
  • Java 표준 라이브러리 - String, ArrayList 등 기본 클래스들
  • 런타임 도구들 - 애플리케이션 실행에 필요한 각종 도구

JRE로 할 수 있는 일

# 이미 컴파일된 Java 프로그램 실행
java MyProgram.class
java -jar myapp.jar

JRE를 사용하는 사람들

  • 일반 사용자: Java로 만든 프로그램만 실행하는 경우
  • 서버 관리자: 웹 애플리케이션 배포 및 실행만 하는 경우

⚡ JDK (Java Development Kit)란?

JDK는 Java 애플리케이션을 개발하기 위한 전체 도구 모음입니다.

JDK의 구성요소

JRE 전체 + 개발 도구들

  • JRE 전체 (JVM + 표준 라이브러리 + 런타임 도구)
  • 개발 도구들:
    • javac - Java 컴파일러
    • jar - JAR 파일 생성/관리 도구
    • javadoc - 문서 생성 도구
    • jdb - 디버거
    • 기타 개발 유틸리티들

JDK로 할 수 있는 일

# Java 소스코드 컴파일
javac MyProgram.java

# JAR 파일 생성
jar cvf myapp.jar *.class

# 컴파일된 프로그램 실행 (JRE 기능)
java MyProgram

JDK를 사용하는 사람들

  • Java 개발자
  • 프로그램을 직접 작성하고 컴파일하는 사람

🔍 쉬운 비유로 이해하기

요리 비유

  • JRE = 완성된 요리를 먹을 수 있는 식탁과 수저
  • JDK = 요리를 만들 수 있는 주방 전체 (식재료, 조리도구, 식탁, 수저 포함)

자동차 비유

  • JRE = 자동차 (운전만 가능)
  • JDK = 자동차 + 정비소 도구 (운전 + 수리/개조 가능)

📋 상황별 선택 가이드

일반 사용자인 경우

Minecraft, IntelliJ IDEA 등 Java 프로그램만 실행
→ JRE만 설치하면 충분

개발자인 경우

Java 코드 작성, 컴파일, 실행 모두 필요
→ JDK 설치 (JRE 자동 포함)

서버 환경의 경우

개발 서버: 로컬에서 코드 작성 및 컴파일
→ JDK 필요

운영 서버: 이미 컴파일된 JAR 파일만 실행
→ JRE만 있어도 충분 (보안상 JRE 권장)

✅ 설치 확인 방법

JDK가 설치되어 있는지 확인

javac -version  # 컴파일러 버전 확인
java -version   # JVM 버전 확인

JRE만 설치된 경우

javac -version  # ❌ 명령어를 찾을 수 없음
java -version   # ✅ 정상 출력

📢 최근 변화사항 (알아두면 좋아요!)

Java 11부터의 주요 변화:

  • Oracle JDK는 상용 라이센스 정책이 변경되었습니다
  • OpenJDK가 더 널리 사용되고 있습니다
  • JRE 별도 배포가 중단되고 JDK에 통합되었습니다

🎉 정리

구분 JRE JDK

용도 Java 프로그램 실행만 Java 개발 + 실행
포함 요소 JVM + 표준 라이브러리 JRE + 개발 도구들
대상 사용자 일반 사용자, 서버 관리자 개발자
설치 권장 실행만 필요한 경우 개발하는 경우

💡 한 줄 요약: 개발을 한다면 JDK를 설치하고, 단순히 Java 프로그램만 실행한다면 JRE면 충분합니다. 하지만 최근에는 대부분 JDK를 설치하는 추세입니다!


이 포스트가 도움이 되셨나요? 댓글로 궁금한 점을 남겨주세요! 👍

태그: #Java #JDK #JRE #자바개발 #프로그래밍 #개발환경

🌐 Spring Boot 없이 IntelliJ 유료버전으로 전통적인 Spring MVC 프로젝트 구성하기

Spring Boot 없이 IntelliJ 유료버전으로 전통적인 Spring MVC 프로젝트를 구성하겠습니다.

1. IntelliJ에서 Maven 프로젝트 생성

  1. File → New → Project
  2. 좌측메뉴 Generators에서 Maven Archetype 선택
  3. name : 임의의 값 설정 예) spring-mvc-app
  4. archetype select box 선택 
  5. maven-archetype-webapp 선택
  6. Advanced Settings 선택 
  7. GroupId: 임의의 값 설정 예)  com.example, ArtifactId: spring-mvc-app 입력
  8. Create 버튼 선택
  9. 프로젝트 생성 확인 
[INFO] Archetype repository not defined. Using the one from [org.apache.maven.archetypes:maven-archetype-webapp:1.5] found in catalog remote
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-webapp:1.0
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: basedir, Value: C:\Users\사용자명\AppData\Local\Temp\archetype2tmp
[INFO] Parameter: package, Value: com.example
[INFO] Parameter: groupId, Value: com.example
[INFO] Parameter: artifactId, Value: spring-mvc-app
[INFO] Parameter: packageName, Value: com.example
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: C:\Users\사용자명\AppData\Local\Temp\archetype2tmp\spring-mvc-app2
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  11.405 s
[INFO] Finished at: 2025-08-29T15:11:57+09:00
[INFO] ------------------------------------------------------------------------

Process finished with exit code 0

2. pom.xml 설정

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>com.example</groupId>
    <artifactId>spring-mvc-app</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
    
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <spring.version>5.3.21</spring.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    
    <dependencies>
        <!-- Spring Core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        
        <!-- Spring Context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        
        <!-- Spring Web MVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        
        <!-- Servlet API -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        
        <!-- JSP API -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
            <scope>provided</scope>
        </dependency>
        
        <!-- JSTL -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.3</version>
            </plugin>
        </plugins>
    </build>
</project>

3. 디렉토리 구조 생성

다음 디렉토리들을 생성하세요:

spring-mvc-app/
├── pom.xml                           # Maven 설정 파일
├── src/
│   └── main/
│       ├── java/                     # Java 소스 코드
│       │   └── com/example/
│       │       └── controller/       # Spring MVC 컨트롤러
│       ├── resources/                # 설정 파일, 프로퍼티 파일
│       └── webapp/                   # 웹 리소스
│           ├── WEB-INF/              # 외부 접근 차단 디렉토리
│           │   ├── web.xml          # 웹 애플리케이션 설정
│           │   ├── dispatcher-servlet.xml  # Spring 설정
│           │   └── views/           # JSP 파일들
│           └── index.jsp            # 정적 웹 파일
└── target/                          # Maven 빌드 결과물

4. web.xml 설정

src/main/webapp/WEB-INF/web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
         http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">
    
    <display-name>Spring MVC Application</display-name>
    
    <!-- Spring DispatcherServlet -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    
    <!-- Character Encoding Filter -->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

5. Spring 설정 파일

src/main/webapp/WEB-INF/dispatcher-servlet.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context 
           http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/mvc 
           http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
    <!-- Component Scan -->
    <context:component-scan base-package="com.example.controller" />
    
    <!-- Enable MVC -->
    <mvc:annotation-driven />
    
    <!-- View Resolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>
    
    <!-- Static Resources -->
    <mvc:default-servlet-handler />
</beans>

6. Controller 클래스

src/main/java/com/example/controller/MainController.java:

package com.example.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class MainController {
    
    @GetMapping("/main")
    public String main(Model model) {
        model.addAttribute("message", "Hello World");
        return "main";
    }
    
    @GetMapping("/")
    public String home() {
        return "redirect:/main";
    }
}

7. JSP 파일

src/main/webapp/WEB-INF/views/main.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Spring MVC Hello World</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            text-align: center;
            margin-top: 100px;
        }
        h1 {
            color: #4CAF50;
        }
    </style>
</head>
<body>
    <h1>${message}</h1>
    <p>Spring MVC without Spring Boot</p>
    <p>현재 시간: <%= new java.util.Date() %></p>
</body>
</html>

8. Tomcat 서버 설정 (IntelliJ)

  1. Run → Edit Configurations
  2. + 버튼 클릭 → Tomcat Server → Local
  3. Server 탭에서 Tomcat 경로 설정
  4. Deployment 탭에서:
    • + 클릭 → Artifact
    • spring-mvc-app:war exploded 선택
    • Application context: '/' 로 설정
    • OK 버튼 선택 

9. 실행

  1. Maven 의존성 다운로드: 터미널에서 mvn clean compile 실행 
  2. IntelliJ에서 Tomcat 서버 실행
  3. 브라우저에서 http://localhost:8080/main 접속

이제 "Hello World"가 출력되는 전통적인 Spring MVC 웹 애플리케이션이 완성되었습니다. JSP를 통해 동적 콘텐츠를 렌더링하고, Spring MVC의 컨트롤러가 요청을 처리합니다.


10. HTTP 요청 처리 과정

전체 흐름도

Client Request → Tomcat → DispatcherServlet → HandlerMapping → Controller → ViewResolver → JSP → Response

상세 처리 과정

1단계: 클라이언트 요청

브라우저에서 http://localhost:8080/main 요청

2단계: 서블릿 컨테이너 (Tomcat)

  • Tomcat이 HTTP 요청을 받음
  • web.xml을 확인하여 어떤 서블릿이 처리할지 결정
  • / 패턴이므로 DispatcherServlet으로 전달

3단계: DispatcherServlet 처리1

// 내부적으로 다음과 같은 과정을 거침
1. HandlerMapping을 통해 요청 URL에 맞는 컨트롤러 메소드 찾기
2. HandlerAdapter를 통해 컨트롤러 메소드 실행
3. 컨트롤러 실행 결과(ModelAndView) 받기
4. ViewResolver를 통해 뷰 이름을 실제 뷰로 변환
5. 뷰 렌더링 및 응답 생성


4단계: 컨트롤러 실행

@GetMapping("/main")
public String main(Model model) {
    model.addAttribute("message", "Hello World");  // 모델에 데이터 추가
    return "main";  // 뷰 이름 반환
}


5단계: 뷰 처리

  • ViewResolver가 "main"을 "/WEB-INF/views/main.jsp"로 변환
  • JSP 엔진이 JSP 파일을 처리
  • EL 표현식 ${message}를 "Hello World"로 치환

6단계: 응답 생성

  • 최종 HTML이 생성되어 클라이언트로 전송

 

11. Spring MVC 핵심 구성 요소

1. DispatcherServlet

// Spring이 제공하는 핵심 서블릿
public class DispatcherServlet extends FrameworkServlet {
    // 모든 HTTP 요청의 진입점
    // Front Controller 패턴의 구현체
}

2. HandlerMapping

  • URL과 컨트롤러 메소드를 매핑
  • @RequestMapping 어노테이션을 분석하여 매핑 정보 생성

3. Controller

@Controller  // Spring이 이 클래스를 컨트롤러로 인식
public class MainController {
    
    @GetMapping("/main")  // GET 요청 "/main"을 이 메소드가 처리
    public String main(Model model) {
        // 비즈니스 로직 처리
        model.addAttribute("message", "Hello World");
        // 뷰 이름 반환
        return "main";
    }
}

4. Model

  • 컨트롤러와 뷰 사이의 데이터 전달 객체
  • 뷰에서 사용할 데이터를 저장

5. ViewResolver

  • 컨트롤러가 반환한 뷰 이름을 실제 뷰 객체로 변환
  • JSP, Thymeleaf, FreeMarker 등 다양한 뷰 기술 지원

6. JSP와 EL(Expression Language)

JSP 태그들

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!-- JSP 페이지 설정 -->

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- JSTL 코어 태그 라이브러리 사용 -->


EL 표현식

${message}  <!-- model.addAttribute("message", "Hello World")로 설정한 값 출력 -->

7. 개발 및 배포 과정

Maven 빌드 과정

mvn clean compile  # 컴파일
mvn package        # WAR 파일 생성


생성되는 파일들

target/
├── classes/                    # 컴파일된 .class 파일들
├── spring-mvc-app-1.0-SNAPSHOT.war  # 배포용 WAR 파일
└── spring-mvc-app-1.0-SNAPSHOT/     # Exploded WAR (개발용)

Tomcat 배포

  1. 개발 시: Exploded WAR를 사용하여 실시간 반영
  2. 운영 시: WAR 파일을 Tomcat의 webapps 디렉토리에 배치

8. 전체 아키텍처 이해

이 프로젝트는 3-Tier Architecture를 따릅니다:

1. Presentation Layer (프레젠테이션 계층)

  • JSP, HTML, CSS, JavaScript
  • 사용자 인터페이스 담당

2. Business Layer (비즈니스 계층)

  • Spring MVC Controller
  • 비즈니스 로직 처리

3. Data Layer (데이터 계층)

  • 현재는 없지만, 보통 Repository, DAO가 위치
  • 데이터베이스 연동 담당

 

🌐 [Spring] 웹 요청 처리의 핵심, dispatcher-servlet.xml 완벽 분석 (Java Config 전환 포함)

web.xml 분석에 이어, 오늘은 Spring MVC의 실질적인 웹 동작을 정의하는 심장부, dispatcher-servlet.xml 파일에 대해 깊이 있게 파헤쳐 보겠습니다.

web.xml이 웹 서버(Tomcat)에게 "모든 요청을 DispatcherServlet에게 넘겨!"라고 지시했다면, 이 dispatcher-servlet.xml 파일은 DispatcherServlet에게 "요청을 받으면 이렇게 처리해!" 라고 상세한 행동 강령을 알려주는 역할을 합니다. 즉, 컨트롤러를 찾고, 뷰(View)를 연결하고, 어노테이션을 동작시키는 모든 마법이 바로 여기서 시작됩니다.

📝 전체 코드 살펴보기

먼저 분석할 dispatcher-servlet.xml 파일의 전체 코드입니다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 1. Component Scan: 컨트롤러를 찾아서 빈으로 등록 -->
    <context:component-scan base-package="com.example.controller" />

    <!-- 2. Enable MVC: 어노테이션 기반 MVC 기능 활성화 -->
    <mvc:annotation-driven />

    <!-- 3. View Resolver: 뷰(JSP) 경로를 완성 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <!-- 4. Static Resources: 정적 리소스(CSS, JS, 이미지 등) 처리 위임 -->
    <mvc:default-servlet-handler />
</beans>

 

📝 핵심 설정 분석

이 파일은 크게 4가지의 핵심적인 역할을 수행하도록 구성되어 있습니다.

1. 컴포넌트 스캔 (Component Scan)

<context:component-scan base-package="com.example.controller" />

• 역할: Spring 컨테이너에게 지정된 패키지(com.example.controller)를 스캔하여 특정 어노테이션(@Controller, @Service 등)이 붙은 클래스를 찾아 자동으로 빈(Bean)으로 등록하라고 지시합니다.
• 핵심: 이 설정 덕분에 우리는 컨트롤러 클래스를 만들고 @Controller 어노테이션만 붙이면, Spring이 알아서 해당 객체를 관리해 주므로 XML에 일일이 빈을 등록하는 수고를 덜 수 있습니다.


2. MVC 기능 활성화 (Enable MVC)

<mvc:annotation-driven />

• 역할: 마법의 한 줄입니다. 어노테이션 기반의 현대적인 Spring MVC 기능을 사용하기 위한 필수 설정입니다.
• 주요 기능: 이 태그 하나가 보이지 않는 곳에서 다음과 같은 필수적인 빈들을 등록하고 활성화합니다.
    • @RequestMapping, @GetMapping 등을 처리하는 RequestMappingHandlerMapping.
    • 컨트롤러 메서드를 호출하고 파라미터(@RequestParam 등)를 처리하는 RequestMappingHandlerAdapter.
    • JSON 데이터 변환, 데이터 검증(@Valid) 등 다양한 고급 기능.
• 결론: 이 태그가 없으면 @RequestMapping을 비롯한 대부분의 Spring MVC 어노테이션이 동작하지 않습니다.

3. 뷰 리졸버 (View Resolver)

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/" />
    <property name="suffix" value=".jsp" />
</bean>

• 역할: 컨트롤러가 반환하는 **논리적인 뷰 이름(Logical View Name)**을 실제 물리적인 뷰 파일 경로로 완성해주는 역할을 합니다.
• 동작 방식:
    1.컨트롤러가 return "home"; 과 같이 문자열을 반환합니다.
    2.ViewResolver는 이 "home"이라는 문자열을 받아, 설정된 prefix와 suffix를 앞뒤에 붙입니다.
    3.최종적으로 /WEB-INF/views/ + home + .jsp  = /WEB-INF/views/home.jsp 라는 실제 파일 경로를 만들어 줍니다.


4. 정적 리소스 처리 (Static Resources)

<mvc:default-servlet-handler />

• 역할: CSS, JavaScript, 이미지 파일 등 동적인 처리가 필요 없는 정적 리소스에 대한 요청을 처리합니다.
• 문제점: web.xml에서 DispatcherServlet의 처리 경로를 /로 지정하면, /css/style.css 같은 정적 파일 요청까지 DispatcherServlet이 가로채게 됩니다. DispatcherServlet은 이 요청을 처리할 컨트롤러를 찾지 못해 404 에러를 발생시킵니다.
• 해결책: 이 태그는 "만약 들어온 요청을 처리할 컨트롤러 매핑이 없다면, 그 요청을 Spring이 처리하지 말고 원래 웹 서버(Tomcat)의 기본 서블릿에게 넘겨라" 라고 설정합니다. 그러면 웹 서버가 정적 파일을 올바르게 찾아 클라이언트에게 제공할 수 있습니다.


📝 
더 나은 코드를 향하여: Java 기반 설정으로의 완전한 전환

XML 설정은 직관적이지만, 현대적인 Spring 개발에서는 타입 안정성(type-safe)과 리팩토링 용이성이 뛰어난 **Java 기반 설정(Java-based Configuration)**을 사용하는 것이 표준입니다.

아래와 같이 web.xml과 dispatcher-servlet.xml을 모두 제거하고 순수 Java 코드로 프로젝트를 설정할 수 있습니다

1단계: dispatcher-servlet.xml을 대체할 WebConfig 클래스 생성

먼저, dispatcher-servlet.xml의 모든 기능을 수행하는 Java 설정 클래스를 만듭니다.

// WebConfig.java
package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc // <mvc:annotation-driven /> 역할
@ComponentScan(basePackages = "com.example.controller") // <context:component-scan /> 역할
public class WebConfig implements WebMvcConfigurer {

    // InternalResourceViewResolver 빈 등록
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

    // <mvc:default-servlet-handler /> 역할
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}

 

2단계: web.xml을 대체할 MyWebAppInitializer 클래스 생성

다음으로, web.xml의 역할을 수행하며 위에서 만든 WebConfig를 로드하는 초기화 클래스를 만듭니다. 이 방법을 사용하면 web.xml 파일을 프로젝트에서 완전히 삭제할 수 있습니다.

//MyWebAppInitializer.java
package com.example.config;

import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import javax.servlet.Filter;

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    // Root ApplicationContext에 대한 설정 (Service, Repository 등). 현재는 없으므로 null.
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return null;
    }

    // DispatcherServlet의 Servlet ApplicationContext에 대한 설정 (Controller, ViewResolver 등)
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[]{WebConfig.class};
    }

    // DispatcherServlet이 처리할 요청 경로 지정
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    // 인코딩 필터 설정
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
        encodingFilter.setEncoding("UTF-8");
        encodingFilter.setForceEncoding(true);
        return new Filter[]{encodingFilter};
    }
}

 

🎯 마무리

오늘은 Spring MVC의 웹 요청 처리 로직을 담당하는 dispatcher-servlet.xml을 분석하고, 이를 현대적인 Java 설정으로 전환하는 방법까지 알아보았습니다.

요약:
    1.component-scan: @Controller를 찾아 빈으로 등록합니다.
    2.annotation-driven: @RequestMapping 등 MVC 어노테이션을 활성화합니다.
    3.ViewResolver: 컨트롤러가 반환한 뷰 이름을 실제 JSP 파일 경로로 완성합니다.
    4.default-servlet-handler: CSS, JS 같은 정적 리소스 요청을 처리합니다.

비록 Spring Boot가 많은 부분을 자동화해주지만, 그 내부에서 어떤 일들이 일어나는지 이해하는 것은 문제 해결 능력과 애플리케이션 설계 능력을 한 단계 끌어올리는 데 큰 도움이 됩니다. 이 글이 여러분의 Spring 학습에 도움이 되었기를 바랍니다

 

 

🌐 [Spring] 스프링 MVC의 심장, web.xml 완벽 분석 (DispatcherServlet, 한글 필터)


오늘은 스프링 부트(Spring Boot) 없이 전통적인 방식으로 Spring MVC 프로젝트를 구성할 때, 가장 먼저 만나게 되는 파일인 web.xml에 대해 깊이 있게 분석해 보겠습니다.

web.xml은 배포 서술자(Deployment Descriptor, DD)라고 불리며, 웹 애플리케이션이 최초에 구동될 때 WAS(Web Application Server, 예: Tomcat)가 가장 먼저 읽는 설정 파일입니다. 즉, 우리 프로젝트의 모든 요청이 어떻게 처리될지 정의하는 매우 중요한 시작점이죠.

📝 전체 코드 살펴보기

먼저 분석할 web.xml 파일의 전체 코드입니다.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
         http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

    <display-name>Spring MVC Application</display-name>

    <!-- Spring DispatcherServlet -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!-- Character Encoding Filter -->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

 

📝 핵심 설정 분석

이 파일은 크게 두 가지 핵심적인 역할을 합니다.
    1.Spring MVC의 핵심 엔진인 DispatcherServlet을 등록하고 설정합니다.
    2.모든 요청에 대한 한글 깨짐을 방지하기 위한 CharacterEncodingFilter를 설정합니다.

하나씩 자세히 살펴보겠습니다.

1. DispatcherServlet: 모든 요청을 받는 프론트 컨트롤러

DispatcherServlet은 Spring MVC의 핵심 엔진이자 심장입니다. 클라이언트의 모든 요청을 가장 먼저 받아서 적절한 컨트롤러(@Controller)에게 작업을 위임하는 프론트 컨트롤러(Front Controller) 역할을 합니다.

<servlet> 태그 분석

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

• <servlet-name>: 서블릿의 별명을 지정합니다. dispatcher라는 이름으로 아래 매핑 설정에서 사용됩니다.
• <servlet-class>: 서블릿으로 사용할 실제 클래스를 지정합니다. Spring MVC의 핵심인 org.springframework.web.servlet.DispatcherServlet을 등록했습니다.
• <init-param>: 서블릿을 초기화할 때 필요한 파라미터를 설정합니다.
    • contextConfigLocation: DispatcherServlet이 사용할 Spring 설정 파일의 위치를 알려줍니다.
      여기서는 /WEB-INF/dispatcher-servlet.xml 파일을 사용하도록 지정했네요.
      이 파일 안에는 @Controller를 스캔할 패키지 위치나 ViewResolver 같은 빈(Bean) 설정이 들어있습니다.
•<load-on-startup>: WAS가 시작될 때 서블릿을 로드하는 순서를 지정합니다. 값이 1이므로 WAS가 구동되면서 가장 먼저 이 서블릿을 초기화합니다. 이를 통해 첫 요청 시 지연 없이 바로 응답할 수 있습니다.

<servlet-mapping> 태그 분석

<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

• <servlet-name>: 위에서 정의한 dispatcher 서블릿에 대한 매핑임을 알려줍니다.
• <url-pattern>/</url-pattern>: 가장 중요한 부분입니다. 이 설정은 모든 요청(http://.../)을 DispatcherServlet이 처리하도록 만듭니다. (정확히는 JSP 요청을 제외한 모든 요청)

💡 Tip: url-pattern을 /*로 설정하면 JSP 파일 요청까지 가로채서 뷰(View)가 제대로 렌더링되지 않는 문제가 발생할 수 있습니다. 따라서 Spring MVC에서는 일반적으로 /를 사용합니다.

2. CharacterEncodingFilter: 한글 깨짐 방지를 위한 필수 설정

웹 애플리케이션에서 한글로 된 데이터를 POST 방식으로 전송할 때, 별도 설정이 없으면 글자가 깨지는 현상이 발생합니다. 이를 방지하기 위해 모든 요청에 대해 UTF-8 인코딩을 강제하는 필터를 설정합니다.

<!-- Character Encoding Filter -->
<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

• <filter-class>: Spring에서 제공하는 CharacterEncodingFilter를 사용합니다.
• <init-param>: 필터에 encoding 값을 UTF-8로 설정합니다.
• <filter-mapping>: 이 필터를 어떤 요청에 적용할지 설정합니다. url-pattern을 /*로 지정하여 이 애플리케이션에 들어오는 모든 요청에 대해 인코딩 필터가 동작하도록 합니다.

 

📝 더 나은 코드를 위한 제안: Java 기반 설정으로 전환

web.xml을 사용하는 XML 기반 설정은 전통적이고 직관적이지만, 최근에는 Java 클래스를 이용한 설정(Java-based Configuration)이 더 선호됩니다. XML 파일을 없애고 100% Java 코드로만 프로젝트를 관리할 수 있어 더 깔끔하고 타입-세이프(type-safe)한 장점이 있습니다.

web.xml의 내용을 다음과 같은 Java 클래스로 대체할 수 있습니다.

/src/main/java/com/example/config/MyWebAppInitializer.java (새 파일)

package com.example.config;

import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import javax.servlet.Filter;

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    // Root-Context (root-context.xml)에 해당하는 설정 클래스를 지정합니다. (현재 프로젝트에는 없으므로 null)
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return null;
    }

    // DispatcherServlet (servlet-context.xml)에 해당하는 설정 클래스를 지정합니다.
    @Override
    protected Class<?>[] getServletConfigClasses() {
        // dispatcher-servlet.xml을 대체할 Java 설정 클래스를 만들어야 합니다.
        // 예: return new Class<?>[] { WebConfig.class };
        return null; // 지금은 예시이므로 null로 둡니다.
    }

    // DispatcherServlet이 매핑될 경로를 지정합니다.
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    // 인코딩 필터 등 각종 필터를 설정합니다.
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
        encodingFilter.setEncoding("UTF-8");
        encodingFilter.setForceEncoding(true);
        return new Filter[]{encodingFilter};
    }
}

주의: 위와 같이 Java 설정을 사용하려면 pom.xml에 spring-web 의존성을 추가하고, dispatcher-servlet.xml의 내용도 Java @Configuration 클래스로 옮겨야 합니다.

 

🎯 마무리

오늘은 Spring MVC 애플리케이션의 관문 역할을 하는 web.xml 파일에 대해 알아보았습니다.

요약:
    1.DispatcherServlet을 등록하여 모든 요청을 Spring 컨테이너로 연결합니다.
    2.CharacterEncodingFilter를 설정하여 안정적인 한글 처리를 보장합니다.

비록 Spring Boot의 등장으로 web.xml을 직접 작성하는 일이 줄었지만, 그 내부 동작 원리를 이해하는 것은 Spring MVC의 근간을 파악하는 데 매우 중요합니다. 이 글이 여러분의 Spring 학습에 도움이 되었기를 바랍니다

 

 

 

 

🌐 [Maven] Spring 프로젝트의 설계도, pom.xml 완벽 해부

오늘은 Maven 기반의 Spring 프로젝트에서 가장 핵심적인 파일, 바로 pom.xml에 대해 상세히 분석해 보겠습니다. pom.xml은 Project Object Model의 약자로, 프로젝트의 모든 정보를 담고 있는 설계도와 같습니다.이 파일 하나에 어떤 라이브러리를 사용할지(의존성), 어떤 버전의 자바로 만들지, 그리고 최종적으로 어떻게 빌드하고 패키징할지에 대한 모든 정보가 정의되어 있습니다. Spring Boot 없이 전통적인 방식으로 프로젝트를 구성할 때, 이 파일을 정확히 이해하는 것은 필수입니다.

📝 전체 코드 살펴보기

먼저 분석할 pom.xml 파일의 전체 코드입니다.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>spring-mvc-app</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <spring.version>5.3.21</spring.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!-- Spring Core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- Spring Context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- Spring Web MVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- Servlet API -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

        <!-- JSP API -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
            <scope>provided</scope>
        </dependency>

        <!-- JSTL -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.3</version>
            </plugin>
        </plugins>
    </build>
</project>

 

📝 핵심 설정 분석

pom.xml은 크게 4가지 영역으로 나눌 수 있습니다.
1.프로젝트 기본 정보 (Project Coordinates)
2.설정값 변수 (Properties)
3.프로젝트 라이브러리 (Dependencies)
4.빌드 방법 (Build)

하나씩 자세히 살펴보겠습니다.

1. 프로젝트 기본 정보 (Project Coordinates)

프로젝트를 식별하는 고유 정보입니다. Maven Central Repository 등에서 이 프로젝트를 유일하게 찾아낼 수 있는 주소와 같습니다.

<groupId>com.example</groupId>
<artifactId>spring-mvc-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>

<groupId>: 프로젝트를 만든 그룹이나 조직의 고유 ID입니다. 보통 회사의 도메인을 역순으로 사용합니다.
<artifactId>: 프로젝트의 이름입니다. groupId 내에서 유일해야 합니다.
<version>: 프로젝트의 버전입니다. SNAPSHOT은 아직 개발 중인, 불안정한 버전임을 의미합니다.
<packaging>: 프로젝트를 빌드한 결과물의 형태를 지정합니다. war는 Web Application Archive의 약자로, Tomcat 같은 웹 애플리케이션 서버(WAS)에 배포하기 위한 패키지 형식입니다


2. 설정값 변수 (Properties)

pom.xml 파일 내에서 공통적으로 사용될 값들을 변수로 정의하는 곳입니다. 이렇게 하면 버전 등을 한 곳에서 관리할 수 있어 매우 편리합니다.

<properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <spring.version>5.3.21</spring.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<maven.compiler.source> & <target>: 이 프로젝트가 Java 11 문법으로 작성되었고, Java 11 환경에서 실행되도록 컴파일하라는 설정입니다.
<spring.version>: 사용할 스프링 프레임워크의 버전을 5.3.21로 지정했습니다. 아래 의존성(Dependencies) 부분에서 ${spring.version} 형태로 이 값을 참조합니다.
<project.build.sourceEncoding>: 소스 코드의 인코딩을 UTF-8로 설정하여 한글 깨짐을 방지합니다.

3. 프로젝트 라이브러리 (Dependencies)

pom.xml의 심장부입니다. 이 프로젝트가 동작하기 위해 필요한 외부 라이브러리(JAR 파일)들을 명시하는 곳입니다. Maven은 여기에 명시된 라이브러리들을 자동으로 다운로드하고 클래스패스에 추가해 줍니다.

<!-- Spring Web MVC -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
</dependency>

<!-- Servlet API -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>

* Spring Framework Dependencies: spring-core, spring-context, spring-webmvc는 Spring MVC 애플리케이션을 구동하기 위한 핵심 라이브러리입니다. 버전은 위 <properties>에 정의된 ${spring.version}을 사용하고 있습니다.
* Servlet/JSP API: javax.servlet-api와 javax.servlet.jsp-api는 서블릿과 JSP를 사용하기 위한 라이브러리입니다.
    💡 <scope>provided</scope>란? 이 설정은 매우 중요합니다. provided는 '제공된다'는 의미로, 컴파일할 때는 이 라이브러리가 필요하지만, 서버(Tomcat 등)에서 이미 제공하므로 최종 war 파일에는 포함하지 말라는 뜻입니다. 만약 이 설정을 빼면 서버에 내장된 라이브러리와 충돌이 발생할 수 있습니다.

* JSTL: JSP에서 c:forEach, c:if 같은 태그를 사용하기 위한 라이브러리입니다.

4. 빌드 방법 (Build)

프로젝트를 컴파일하고 패키징하는 방법을 정의합니다. 여기서는 Maven 플러그인을 사용합니다.

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>11</source>
                <target>11</target>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>3.2.3</version>
        </plugin>
    </plugins>
</build>

* maven-compiler-plugin: 자바 소스 코드를 바이트코드로 컴파일하는 역할을 합니다. <configuration>을 통해 <properties>에서 정의한 자바 11 버전을 사용하도록 설정했습니다.
* maven-war-plugin: 프로젝트를 <packaging>에 명시된 war 파일로 묶어주는 역할을 합니다.

🎯마무리

오늘은 Maven 프로젝트의 설계도인 pom.xml을 분석해 보았습니다.

요약:  
  1.프로젝트 정보: groupId, artifactId 등으로 프로젝트를 식별합니다.
  2.의존성 관리: <dependencies>를 통해 필요한 라이브러리를 선언하고 자동으로 관리합니다.
  3.빌드 설정: <build>와 플러그인을 통해 컴파일 및 패키징 과정을 제어합니다.

pom.xml을 이해하는 것은 의존성 충돌 문제를 해결하고, 프로젝트의 구조를 파악하는 데 큰 도움이 됩니다. 이 글이 여러분의 개발 여정에 도움이 되었기를 바랍니다

 

 

 

 

 

 

 

 

 

🌐 Spring Boot에서 로그 출력하는 방법

Spring Boot에서는 로그 출력을 쉽게 설정하고 사용할 수 있습니다. 로그는 애플리케이션의 상태를 파악하고 문제를 디버깅하는 데 매우 중요한 역할을 합니다. 이번 글에서는 Spring Boot에서 로그를 출력하는 방법과 설정 방법에 대해 알아보겠습니다.

📝 Spring Boot 로깅 설정

Spring Boot는 기본적으로 Logback을 로깅 구현체로 사용합니다. Spring Boot에서는 `application.properties` 또는 `application.yml` 파일을 통해 로깅 설정을 할 수 있습니다. 기본적으로 로그 레벨은 INFO로 설정되어 있습니다. 로그 레벨을 변경하거나 로그 파일을 설정할 수 있습니다.

👉 예시: `application.properties`

logging.level.root=INFO  # 기본 로그 레벨 설정
logging.level.org.springframework.web=DEBUG  # 특정 패키지에 대해 로그 레벨 설정
logging.level.org.apache.coyote.http11=TRACE  # org.apache.coyote.http11 패키지의 로그 레벨을 TRACE로 설정

logging.file.name=app.log  # 로그 파일 이름
logging.file.path=/var/logs  # 로그 파일 경로

👉 예시: `application.yml`

logging:
  level:
    root: INFO
    org.springframework.web: DEBUG
    org.apache.coyote.http11: TRACE  # TRACE 로그 레벨 설정
  file:
    name: app.log
    path: /var/logs

위 설정에서는 `org.apache.coyote.http11` 패키지의 로그 레벨을 `TRACE`로 설정했습니다. `TRACE`는 가장 세부적인 레벨로, 로그를 통해 매우 상세한 정보를 출력할 수 있습니다. 이를 통해 HTTP 요청과 관련된 세부적인 정보를 추적할 수 있습니다.

📝 SLF4J 로그 사용하기

Spring Boot에서 로그를 출력하려면 SLF4J API를 사용합니다. SLF4J는 다양한 로깅 구현체와 통합할 수 있는 API입니다. `LoggerFactory`를 통해 로거를 생성하고, `Logger` 객체를 이용하여 로그를 출력할 수 있습니다.

👉 로그 출력 코드

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {
    
    // SLF4J Logger 선언
    private static final Logger logger = LoggerFactory.getLogger(MyController.class);
    
    @GetMapping("/hello")
    public String hello() {
        logger.debug("디버그 레벨 로그");
        logger.info("정보 레벨 로그");
        logger.warn("경고 레벨 로그");
        logger.error("에러 레벨 로그");
        
        return "Hello, Spring Boot!";
    }
}

📝 로그 레벨

SLF4J를 통해 출력할 수 있는 로그 레벨에는 4가지가 있습니다. 각 로그 레벨은 로그의 중요도를 나타냅니다.

  • DEBUG: 개발 중에 유용한 정보를 출력하는 레벨입니다. 디버깅을 할 때 주로 사용됩니다.
  • INFO: 애플리케이션의 주요 흐름을 나타내는 로그입니다.
  • WARN: 경고 메시지로, 큰 문제는 아니지만 주의해야 할 상황을 알립니다.
  • ERROR: 오류가 발생했을 때 출력되는 로그입니다.
  • TRACE: 가장 상세한 로그 레벨로, 매우 세부적인 정보 출력에 사용됩니다. 주로 개발 중에 트러블슈팅을 위해 사용됩니다.

📝 Logback 설정 파일 커스터마이징

Spring Boot에서 로그 출력을 더 세밀하게 제어하려면 Logback 설정 파일을 사용하여 로그 출력을 커스터마이징할 수 있습니다. `logback-spring.xml` 파일을 생성하여 콘솔 출력 형식, 로그 파일 경로, 로그 레벨 등을 설정할 수 있습니다.

예시: `logback-spring.xml`

<configuration>
    <!-- 콘솔 로그 출력 설정 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} - %msg%n</pattern>
        </encoder>
    </appender>
    
    <!-- 파일 로그 출력 설정 -->
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>/var/logs/app.log</file>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} - %msg%n</pattern>
        </encoder>
    </appender>
    
    <!-- 로그 레벨 설정 -->
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
    </root>
</configuration>

📝 외부 로깅 라이브러리 사용

Spring Boot에서는 기본적으로 Logback을 사용하지만, 다른 로깅 라이브러리인 Log4j2를 사용할 수도 있습니다. 이를 위해서는 `spring-boot-starter-log4j2` 의존성을 추가하고, `log4j2-spring.xml` 파일을 통해 설정을 커스터마이징할 수 있습니다.

👉 Log4j2 의존성 추가

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

이 의존성을 추가한 후, `log4j2-spring.xml` 파일을 생성하여 로그 출력을 설정할 수 있습니다.

📝 logging.level.org.apache.coyote.http11=trace

Apache Tomcat의 HTTP/1.1 커넥터를 다루는 내부 클래스입니다.
이 설정을 사용하면 다음과 같은 Tomcat 내부 동작을 로그로 확인할 수 있습니다:

  • 클라이언트 요청 파싱 과정
  • 커넥션 생성 및 종료
  • Keep-Alive 연결 처리
  • 헤더 처리 및 파이프라인 관련 정보

🎯결론

Spring Boot에서 로그를 출력하는 방법은 매우 간단하며, SLF4J와 Logback을 사용하면 다양한 로그 레벨과 설정을 통해 애플리케이션의 상태를 쉽게 모니터링하고 문제를 디버깅할 수 있습니다. 로그 출력 형식을 커스터마이징하여 더 세밀하게 로깅을 제어할 수도 있습니다. 올바른 로그 설정은 애플리케이션의 품질을 향상시키고 유지보수성을 높이는 데 중요한 역할을 합니다.

서블릿 컨테이너란? 자바 웹 애플리케이션의 보이지 않는 조력자

웹 개발을 하다 보면 "서블릿(Servlet)"뿐만 아니라 "서블릿 컨테이너(Servlet Container)"라는 단어도 자주 접하게 됩니다.
그렇다면 서블릿 컨테이너는 무엇일까요? 이 글에서는 서블릿 컨테이너의 정의, 역할, 동작 방식, 그리고 대표적인 구현체에 대해 쉽게 설명해드립니다.

📌 서블릿 컨테이너란?

서블릿 컨테이너는 서블릿(Servlet) 객체를 관리하고 실행하는 환경을 제공하는 소프트웨어입니다. 웹 서버와 서블릿 사이에서 중간 역할을 하며, 다음과 같은 기능을 제공합니다.

  • 클라이언트의 HTTP 요청을 서블릿에 전달
  • 서블릿의 실행 결과를 HTTP 응답으로 변환
  • 서블릿 객체의 생성, 초기화(init), 서비스(doGet/doPost), 소멸(destroy) 주기 관리
  • 보안, 로깅, 세션 관리 등의 부가 기능 제공

🔁 서블릿 컨테이너의 동작 흐름

서블릿 컨테이너는 다음과 같은 순서로 동작합니다.

  1. 사용자가 웹 브라우저에서 http://localhost:8080/hello 같은 URL로 요청
  2. 웹 서버가 요청을 받아 서블릿 컨테이너에 전달
  3. 서블릿 컨테이너는 해당 URL에 매핑된 서블릿을 찾아 실행 (doGet() 또는 doPost())
  4. 서블릿이 요청을 처리하고 응답을 생성
  5. 서블릿 컨테이너가 응답을 HTTP 형태로 브라우저에 전달

🧰 서블릿 컨테이너가 제공하는 기능

서블릿 컨테이너는 단순히 서블릿을 실행하는 것 외에도 다양한 기능을 제공합니다.

  • 라이프사이클 관리 - 서블릿 객체 생성부터 소멸까지 전 과정 관리
  • 요청 매핑 - URL과 서블릿 클래스를 연결
  • 멀티 스레딩 - 여러 사용자의 요청을 동시에 처리
  • 보안 처리 - 인증, 권한 부여 처리 가능
  • 세션 관리 - 사용자의 로그인 상태 유지

🚀 대표적인 서블릿 컨테이너

컨테이너 특징
Apache Tomcat 가장 널리 사용되는 서블릿 컨테이너. Spring, JSP와도 잘 통합됨
Jetty 가볍고 빠른 성능. 내장형 웹 서버로도 자주 사용
Undertow 비동기/논블로킹 처리에 강함. WildFly 애플리케이션 서버에서 사용

🎯 마무리

서블릿 컨테이너는 자바 웹 애플리케이션의 핵심 기반 기술입니다.
눈에 띄지 않지만 HTTP 요청과 응답을 매끄럽게 처리하고, 서블릿의 생명주기를 관리하는 보이지 않는 조력자라고 할 수 있죠.

Spring Boot를 사용하더라도 내부적으로는 Tomcat 같은 서블릿 컨테이너를 사용하는 구조이므로, 개념을 잘 이해해두면 다양한 웹 프레임워크를 다루는 데 큰 도움이 됩니다 😊


🌐 서블릿(Servlet)이란? 

자바로 웹 애플리케이션을 개발하다 보면 Servlet(서블릿) 이라는 개념을 반드시 만나게 됩니다.
서블릿은 웹 요청을 처리하고 응답을 만들어주는 서버 측 프로그램이에요.
이번 글에서는 서블릿의 개념부터 동작 원리, 기본 코드 예제까지 쉽게 정리해드립니다! 🚀

📝 서블릿(Servlet)이란?

Servlet(서블릿)은 Java 언어로 작성된 서버 사이드 웹 컴포넌트로, 클라이언트의 요청(Request)을 받아 응답(Response)을 반환하는 역할을 합니다.

  • HTTP 요청을 처리하고 HTML, JSON 등의 결과를 돌려줌
  • Java 기반이기 때문에 이식성이 뛰어나고 안정성도 우수
  • Jakarta EE (기존 Java EE)의 표준 기술

📝 서블릿의 동작 흐름

  1. 사용자가 웹 브라우저에서 요청을 보냄 (http://example.com/hello)
  2. 웹 서버(예: Tomcat)가 이 요청을 받고 서블릿에게 전달
  3. 서블릿이 doGet() 또는 doPost() 메서드로 요청을 처리
  4. 처리 결과를 HTML 형식으로 응답 생성
  5. 브라우저는 그 응답을 사용자에게 표시

📝 서블릿의 주요 메서드

메서드 설명
init() 서블릿 초기화 시 1번 실행 (서버 시작 시)
doGet() GET 방식 요청 처리
doPost() POST 방식 요청 처리
destroy() 서블릿 종료 시 1번 실행 (서버 종료 시)

📝 서블릿 코드 예제


import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.WebServlet;

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException {

        res.setContentType("text/html;charset=UTF-8");
        PrintWriter out = res.getWriter();
        out.println("<h1>Hello, Servlet!</h1>");
    }
}


📝 서블릿의 특징 요약

  • Java 기반의 웹 기술
  • HTTP 요청을 받아 처리
  • 웹 서버(Tomcat 등)에서 실행됨
  • JSP, Spring 등 웹 프레임워크의 기반 기술


📝 서블릿 vs JSP vs Spring MVC

기술 설명
Servlet Java 코드로 모든 웹 요청을 직접 처리
JSP HTML에 Java 코드를 섞어 동적 페이지 생성
Spring MVC 서블릿 기반의 고급 프레임워크. 구조화된 웹 개발 지원

📌 JSP와 Spring도 결국 서블릿 위에서 동작합니다!

📝 서블릿을 실행하려면?

  1. Java 프로젝트 생성
  2. HttpServlet 클래스를 상속한 서블릿 작성
  3. URL 매핑: @WebServlet 또는 web.xml 사용
  4. Tomcat 같은 서블릿 컨테이너에 배포

🎯 마무리

서블릿은 Java 웹 개발의 가장 기초이자 중심이 되는 기술입니다.
비록 직접 서블릿만으로 개발하는 경우는 적지만, JSP, Spring 같은 고급 웹 기술의 기반이 되기 때문에 잘 이해해 두면 웹 개발에 큰 도움이 됩니다!

궁금한 점이 있다면 댓글로 남겨주세요 😊
다음 글에서는 JSP와 서블릿의 차이점 또는 실습 예제를 더 소개해볼게요!

Spring Boot를 이용해 애플리케이션을 개발할 때 가장 중요한 부분 중 하나는 빌드 도구의 선택입니다. Maven과 Gradle은 Spring Boot에서 주로 사용되는 두 가지 빌드 도구로, 각각의 특성과 장단점이 있습니다. 이번 글에서는 두 도구의 특징과 차이점을 자세히 살펴보고, 최근 트렌드에 따른 사용 현황도 분석해 보겠습니다.


1. Maven의 특징

📝 구성 방식

👉 XML 기반 설정:
Maven은 pom.xml 파일을 사용하여 프로젝트 설정, 의존성 관리, 플러그인 설정 등을 선언적으로 구성합니다.

👉 Convention over Configuration:
정해진 기본 구조와 설정 덕분에 초보자도 쉽게 접근할 수 있습니다.

📝 의존성 관리

👉 체계적인 관리:
중앙 저장소를 통해 의존성을 관리하며, 의존성 트리 관리 기능으로 버전 충돌 문제를 최소화합니다.

📝 플러그인 생태계

👉 풍부한 플러그인:
다양한 빌드, 테스트, 배포 작업을 수행할 수 있는 플러그인이 잘 갖춰져 있어 안정적인 빌드 환경을 제공합니다.

📝 학습 곡선

👉 명시적 설정:
XML 기반의 명시적인 설정 방식은 이해하기 쉽지만, 복잡한 구성이 필요할 때는 설정 파일이 길어지고 관리가 어려워질 수 있습니다.


2. Gradle의 특징

📝 구성 방식

👉 DSL 스크립트 방식:
Gradle은 Groovy 또는 Kotlin DSL을 사용해 build.gradle 또는 build.gradle.kts 파일로 빌드 설정을 작성합니다. 코드처럼 작성할 수 있어 매우 유연합니다.

📝 빌드 속도

👉 빠른 빌드:
인크리멘털 빌드, 캐시, 병렬 빌드를 지원하여 대규모 프로젝트에서도 빠른 빌드 시간을 제공합니다.

📝 유연성

👉 커스텀 로직 추가 용이:
스크립트 방식 덕분에 필요에 따라 커스텀 빌드 로직을 쉽게 추가할 수 있으며, 복잡한 빌드 과정도 효율적으로 처리할 수 있습니다.

📝 의존성 관리 및 플러그인

👉 유연한 설정:
Maven과 유사한 의존성 관리 기능을 제공하면서도, 스크립트 기반 설정으로 복잡한 요구사항에 맞게 조정하기가 용이합니다.


3. Maven과 Gradle의 비교


항목 Maven Gradle
구성 방식 XML 기반의 선언적 구성 Groovy/Kotlin DSL을 활용한 스크립트 방식
학습 곡선 표준화된 구조로 상대적으로 단순 유연하지만 자유도가 높아 초기 학습이 다소 복잡할 수 있음
빌드 속도 전체 빌드 방식으로 비교적 느릴 수 있음 인크리멘털 빌드 및 병렬 빌드 지원으로 빠른 빌드 시간 제공
유연성 정형화된 구조로 제한적 커스텀 빌드 로직 추가 등 매우 유연함
생태계 및 안정성 오랜 기간 사용되어 안정적이며, 플러그인 생태계가 풍부함 최신 기술에 적합, Android 등 다양한 분야에서 인기가 높음

👉 초기 설정 및 유지 관리:
Maven은 표준화된 구조 덕분에 설정과 유지 관리가 용이하지만, Gradle은 복잡한 빌드 로직 구현에 유리한 반면 초기 설정이 다소 복잡할 수 있습니다.

👉 확장성과 성능:
대규모 프로젝트나 빌드 속도가 중요한 상황에서는 Gradle의 인크리멘털 빌드와 캐시 기능이 큰 장점으로 작용합니다.


4. 최근 트렌드와 사용 현황

최근에는 Gradle의 사용이 점점 증가하고 있습니다. 그 이유는 다음과 같습니다.

👉 빠른 빌드 시간:
인크리멘털 빌드와 병렬 빌드 기능 덕분에 대규모 프로젝트에서도 빌드 시간이 크게 단축됩니다.

👉 유연한 스크립팅:
Groovy 또는 Kotlin DSL을 통한 스크립트 방식은 복잡한 빌드 로직을 손쉽게 구현할 수 있어 최신 개발 환경에 적합합니다.

👉 다양한 플랫폼 지원:
Android 개발에서 Gradle이 표준 빌드 도구로 자리 잡으면서, 서버 사이드(Spring Boot)뿐만 아니라 여러 분야에서 Gradle의 인기가 상승하고 있습니다.

반면, Maven은 여전히 많은 기업과 프로젝트에서 사용되며, 안정성과 단순함을 선호하는 팀에서 선택되고 있습니다. 최신 트렌드와 빌드 성능 최적화 요구에 따라 새로운 프로젝트나 대규모 시스템에서는 Gradle의 채택이 늘어나는 추세입니다.


 

🎯 결론

Spring Boot 프로젝트에서의 빌드 도구 선택은 프로젝트의 규모와 팀의 기술 역량에 따라 달라질 수 있습니다.

👉 Maven
    • 장점: 안정적이고 표준화된 설정, 관리가 쉬움
    • 적합한 경우: 소규모 프로젝트나 초보자, 정해진 규칙을 따르는 환경

👉 Gradle
    • 장점: 빠른 빌드 속도, 유연한 커스텀 빌드 로직 지원
    • 적합한 경우: 대규모 프로젝트, 최신 기술 스택 적용, 복잡한 빌드 로직 필요 시

최근 트렌드를 보면 Gradle의 인기가 상승하고 있으므로, 성능과 유연성이 중요한 프로젝트라면 Gradle을 고려해 보시는 것이 좋습니다. 물론 팀 내 경험이나 프로젝트 특성에 따라 Maven 역시 훌륭한 선택이 될 수 있습니다.


여러분의 프로젝트 환경과 요구사항에 맞는 최적의 빌드 도구를 선택하여 효율적인 개발 환경을 구축해 보시길 바랍니다.

📢 [Java Spring Boot] 스프링 부트에서 Swagger 사용하기

🙌 Swagger는 API 문서를 자동으로 생성해주는 도구로, Spring Boot에서는 Springdoc OpenAPI 라이브러리를 사용하여 쉽게 설정할 수 있습니다.

📝 Swagger(OpenAPI)란?

🙌 Swagger는 REST API를 시각화하여 쉽게 테스트하고 문서를 자동으로 생성해주는 도구입니다.
Spring Boot에서는 주로 springdoc-openapi 라이브러리를 사용하여 Swagger UI를 제공하며, 이를 통해 API를 웹 브라우저에서 손쉽게 확인할 수 있습니다.

📝 Spring Boot에서 Swagger 적용하기

    ✅ springdoc-openapi 의존성 추가

    ✔ Spring Boot 2.x 이상에서는 springdoc-openapi 라이브러리를 사용합니다.
    ✔ Spring Boot 프로젝트에서 다음과 같은 의존성을 추가합니다.

// Gradle - build.gradle
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.5'

// Maven - pom.xml
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.8.5</version> 
</dependency>


    ✅
Swagger UI 확인하기

      🙌 의존성을 추가한 후 프로젝트를 실행하면, Swagger UI를 확인할 수 있습니다.

      기본적으로 http://localhost:8080/swagger-ui.html 주소에서 Swagger UI가 제공됩니다.
      OpenAPI JSON 문서는 http://localhost:8080/v3/api-docs에서 확인할 수 있습니다.


👉 실행 결과 



📝
Swagger 문서화 추가하기

🙌 Swagger에서 API를 보기 좋게 표시하려면, @Operation 및 @Parameter 등의 어노테이션을 활용합니다.

    ✅ Controller에서 API 문서 작성하기

        @Tag(name, description): API 그룹을 지정합니다.
        @Operation(summary, description): API의 제목과 설명을 추가합니다.
        @Parameter(description): 요청 파라미터에 대한 설명을 추가합니다.

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.ArrayList;

@RestController
@RequestMapping("/users")
@Tag(name = "User API", description = "사용자 관리 API")  // API 그룹 태그
public class UserController {

    private final List<String> users = new ArrayList<>();

    @GetMapping
    @Operation(summary = "모든 사용자 조회", description = "저장된 모든 사용자 목록을 조회합니다.")
    public List<String> getUsers() {
        return users;
    }

    @PostMapping
    @Operation(summary = "사용자 추가", description = "새로운 사용자를 추가합니다.")
    public String addUser(@RequestParam @Parameter(description = "추가할 사용자 이름") String name) {
        users.add(name);
        return "User added: " + name;
    }
}


    ✅
DTO(데이터 전송 객체) 문서화

       Swagger에서 DTO를 자동으로 문서화하려면, @Schema 어노테이션을 사용합니다.

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Schema(description = "사용자 정보 DTO")
public class UserDto {

    @Schema(description = "사용자 ID", example = "1")
    private Long id;

    @Schema(description = "사용자 이름", example = "홍길동")
    private String name;
}


👉 실행 결과 

 

📝 Swagger 설정 변경하기

🙌 Swagger의 기본 설정을 변경하려면 application.yml 또는 application.properties에서 설정을 추가합니다.

    ✅ API 기본 정보 설정

// application.yml
springdoc:
  api-docs:
    path: /api-docs  # API 문서 경로 변경
  swagger-ui:
    path: /swagger-ui  # Swagger UI 경로 변경
    operationsSorter: method  # API 정렬 방식 (method 기준)
    disable-swagger-default-url: true  # 기본 Swagger URL 비활성화


// application.properties
springdoc.api-docs.path=/api-docs
springdoc.swagger-ui.path=/swagger-ui
springdoc.swagger-ui.operationsSorter=method
springdoc.swagger-ui.disable-swagger-default-url=true

 

📝 보안 설정 (Swagger UI 접근 제한)

🙌  Swagger는 개발 및 테스트 환경에서 유용하지만, 운영 환경에서는 보안이 필요합니다.
🙌  Spring Security를 사용하는 경우 Swagger에 대한 접근을 제한할 수 있습니다.

     Spring Security 설정 추가

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
                .anyRequest().authenticated()
            )
            .csrf(csrf -> csrf.disable());  // CSRF 비활성화 (개발 환경)

        return http.build();
    }
}

 

📝 Swagger UI에서 API 테스트하기

🙌 이제 Swagger UI에서 API를 테스트할 수 있습니다.

     Swagger UI 접속

      ✔ 브라우저에서 http://localhost:8080/swagger-ui.html 열기

    API 테스트

      ✔  GET /users 실행 → 모든 사용자 목록 확인
      ✔  POST /users?name=홍길동 실행 → 사용자 추가
      ✔  다시 GET /users 실행 → 추가된 사용자 확인


📚  Swagger 적용 과정 요약

springdoc-openapi  의존성 추가
@Operation, @Parameter 등을 활용하여 API 문서화
Swagger UI에서 API 테스트 (/swagger-ui)
application.yml에서 Swagger 설정 변경 가능
Spring Security 설정을 추가하여 접근 제한 가능

🚀 Swagger를 활용하면 API를 보다 체계적으로 관리할 수 있으며, 개발자 간의 협업도 용이해집니다. 

📢 [mybatis] sql 문의 부등호 사용시 오류 해결 방법 


🙌 mybatis내의 sql 문 사용예제입니다. (ms-sql server sql 문을 이용한 예제입니다.)

    <select id="verifySms" parameterType="String" resultType="String">
        select 'Y'
        from verifyTelephone
        where authCode = #{authCode}
        and datediff(hour, createDate, GETDATE()) = 1
    </select>

 

🙌  하지만, 부등호가 사용되면 오류가 발생합니다. 

    <select id="verifySms" parameterType="String" resultType="String">
        select 'Y'
        from verifyTelephone
        where authCode = #{authCode}
        and datediff(hour, createDate, GETDATE()) <= 1
    </select>

 

🙌  MyBatis에서 <(작다), >(크다) 같은 부등호를 사용할 때는 XML의 특성상 엔티티 코드로 변환해야 합니다.   

🚨 오류 원인

XML에서는 <와 >를 태그로 인식하기 때문에, 직접 사용하면 파싱 오류가 발생합니다.

✅ 해결 방법: &lt;, &gt; 사용

< → &lt;
> → &gt;

🙌 아래와 같이 사용하면 오류가 발생하지 않습니다.

    <select id="verifySms" parameterType="String" resultType="String">
        select 'Y'
        from verifyTelephone
        where authCode = #{authCode}
        and datediff(hour, createDate, GETDATE()) &lt;= 1
    </select>

 

 

 

 

 

 

📢 [java spring boot] cors 허용하는 방법

📌 REST API를 통해 다른 서버의 데이터에 접근하는 경우 CORS(Cross-Origin Resource Sharing) 정책 위반 문제로 오류가 발생할 수 있습니다. 

📌 크롬의 개발자 도구에서 확인하면 아래와 같은 오류를 확인할 수 있습니다.
Access to XMLHttpRequest at '데이터 제공 도메인' from origin '데이터 요청 도메인' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

📌 데이터 제공 서버에 설정을 통해 문제를 해결할 수 있습니다.


📝 Controller에서 개별적으로 CORS 설정하기

🙌 특정 컨트롤러 또는 메서드에만 CORS를 허용하고 싶다면, @CrossOrigin 애너테이션을 사용하면 됩니다.

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://example.com", allowedHeaders = "*") // 특정 도메인 허용
public class SampleController {

    @GetMapping("/data")
    public String getData() {
        return "Hello, CORS!";
    }

    @PostMapping("/submit")
    @CrossOrigin(origins = "http://anotherdomain.com") // 특정 메서드에만 허용
    public String submitData(@RequestBody String data) {
        return "Received: " + data;
    }
}

 

📝 전역 CORS 설정

🙌 Spring Security를 사용하지 않거나, 단순한 CORS 설정이 필요한 경우 WebMvcConfigurer를 이용할 수 있습니다.

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // 모든 엔드포인트에 대해 CORS 적용
                .allowedOrigins("http://example.com") // 허용할 도메인
                // 여러 Origin을 허용하려면 ,로 구분
                // allowedOrigins("*") → 모든 도메인 허용 (보안상 위험할 수 있음)
                // allowCredentials(true) 사용 시, allowedOrigins("*")를 사용할 수 없음
                .allowedMethods("GET", "POST", "PUT", "DELETE") // 허용할 HTTP 메서드
                .allowedHeaders("*") // 모든 헤더 허용
                .allowCredentials(true); // 쿠키 인증 허용
    }
}

또는, 

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig {

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

            @Override
            public void addCorsMappings(org.springframework.web.servlet.config.annotation.CorsRegistry registry) {
                registry.addMapping("/**")
                    .allowedOrigins("http://example.com")
                    .allowedMethods("GET", "POST", "PUT", "DELETE")
                    .allowedHeaders("*");
            }
        };
    }
}

이런 식으로도 가능합니다.

 

📝 Spring Boot 설정 파일 (application.yml)로 CORS 설정

🙌 Spring Boot 2.4 이상에서는 application.yml에서도 CORS 설정을 할 수 있지만, WebMvcConfigurer나 SecurityConfig보다 세부적인 설정이 어렵습니다.

spring:
  web:
    cors:
      allowed-origins: "http://example.com"
      allowed-methods: "GET,POST,PUT,DELETE"
      allowed-headers: "*"
      allow-credentials: true



📝 Spring Security와 함께 글로벌 CORS 설정하기

🙌 Spring Security를 사용할 경우 WebMvcConfigurer만 설정해도 CORS 문제가 해결되지 않을 수 있습니다. 이럴 때는 SecurityFilterChain에서 CORS 설정을 적용해야 합니다.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.config.annotation.web.configurers.CorsConfigurer;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .cors(cors -> cors.configurationSource(request -> {
                var config = new org.springframework.web.cors.CorsConfiguration();
                config.addAllowedOrigin("http://example.com"); // 허용할 도메인
                config.addAllowedMethod("*"); // 모든 HTTP 메서드 허용
                config.addAllowedHeader("*"); // 모든 헤더 허용
                return config;
            }))
            .csrf(csrf -> csrf.disable()) // 필요시 CSRF 비활성화
            .authorizeHttpRequests(auth -> auth.anyRequest().permitAll()) // 모든 요청 허용 (설정에 맞게 수정)
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));

        return http.build();
    }
}

 

 

 

📢  [spring boot] mybatis - mssql application.yml 설정

📌 spring boot 3.4.3 version에서의 설정 예제입니다. 


Dependencies 추가 

Dependencies에 MyBatis Framework와 MSSql Driver를 추가하면 
build.gradle 에 dependencies에 아래와 같이 추가됩니다.

    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.4'
    runtimeOnly 'com.microsoft.sqlserver:mssql-jdbc'
    testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.4'

🤔 추가 후 프로젝트를 Run하면 에러가 발생합니다.


application 설정 추가

  application.properties, 또는 application.yml에 아래와 같이 설정을 해 주어야 합니다.

# application.yml
# 서버 설정
server:
  port: 8080  # 서버가 실행될 포트를 지정합니다. 여기서는 8080번 포트를 사용합니다.

# Spring 프레임워크 설정
spring:
  datasource:  # 데이터베이스 연결 정보를 설정합니다.
    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
    url: jdbc:sqlserver://localhost:1433;databaseName=databasename;encrypt=true;trustServerCertificate=true
    username: username  # 데이터베이스 접속에 사용할 사용자 이름입니다.
    password: password  # 데이터베이스 접속에 사용할 비밀번호입니다.

# MyBatis 설정
mybatis:
  mapper-locations: classpath:mapper/**/*.xml  # MyBatis 매퍼 파일(.xml)의 위치를 지정합니다.


🙌 성공적인 실행이 되었기를.... 

 

 

 

 

📢 mybatis parameter가 2개 이상일 경우 사용방법

💡 parameterType="map"를 이용하면 된다.

    <select id="findById" parameterType="map" resultType="Member">
        SELECT
        <include refid="memberColumns" />
        FROM member
        WHERE id = #{id, jdbcType=BIGINT}
          and member_id = #{memberId, jdbcType=VARCHAR}
    </select>


@Param 이용 

Controller

memberService.findById(Long id, String memberId)

Service

memberMapper.findById(Long id, String memberId)

Mapper

Member findById(@Param("id") Long id, @Param("memberId") Long memberId);


Map 이용 

Controller

Map<String, Object> param = new HashMap<>();
param.put("id", id);
param.put("memberId", memberId);

memberService.findById(id, memberId);

✔ Service

memberMapper.findById(Map<String, Object> param)

Mapper

Member findById(Map<String, Object> param)

 

+ Recent posts