Spring (7) Annotation

destro·2025년 5월 1일

2. Spring

목록 보기
7/17
post-thumbnail

1. Spring Annotation

Ⅰ. @Slf4j

Slf4j는 인터페이스이고 그 구현체로 Logback같은 라이브러리를 선택한다. 실제 개발에서는 Spring Boot가 기본으로 제공하는 Logback을 대부분 사용한다.

  • Logging

  • Thread 정보, 클래스 이름과 같은 부가 정보를 함께 확인할 수 있다.
  • 실제 운영 환경에서는 System.out.println();을 사용하여 Console에 정보를 출력하지 않고, 별도의 로깅 라이브러리를 사용하여 로그를 출력한다.
  • Log Level 설정을 통하여 Error 메세지만 출력하도록 하도록 하기도 하고 로그 메세지를 일자별로 모아서 저장하여 외부 저장소에 보관하기도 한다.
    • Log Level
      • TRACE > DEBUG > INFO > WARN > ERROR
  • 사용시 주의점
package com.example.springbasicannotation.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RestController
public class Slf4jController {

    @RequestMapping("/logging")
    public String logging() {

        String sparta = "Sparta";
        // TRACE -> DEBUG -> INFO -> WARN -> ERROR
        log.trace("문자 trace={}", sparta);
        log.debug("문자 debug={}", sparta);

        // default
        log.info("문자 info={}", sparta);// 문자 연산을 진행하지 않는다.
        log.warn("문자 warn={}", sparta);
        log.error("문자 error={}", sparta);

        log.info("문자 info " + sparta); // 문자 연산을 먼저 해버린다.
        return "success";
    }

}
# com.example.springbasicannotation 하위 경로들의 로그 레벨을 설정한다.
logging.level.com.example.springbasicannotation=TRACE
  • Postman 호출
    • Default Level(INFO) API 호출

- 출력결과

- level=TRACE

Ⅱ. @Controller VS @RestController

Annotation 기반의 Spring에서 Controller(Handler)를 만들 때 사용하는 어노테이션

  1. @Controller

  • @Target(ElementType.Type)
    • Class, Interface, Annotation, Enum, Record Declaration(Java16) 에 적용할 수 있다.
  • @Retention(RetentionPolicy.RUNTIME)
    • 클래스 파일(.class)에 저장되고, JVM에 의해 런타임 시점에 읽을 수 있다.
  • @Document
    • Javadoc 등의 문서화 도구에 의해 문서화되어야 함을 나타낸다.
  • @Component
    • Spring Bean에 등록한다.
    • 싱글톤으로 관리된다.
package com.example.springbasicannotation.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ViewController {

    @RequestMapping("/view")
    public String example() {
        // logic
        return "sparta"; // ViewName이 return
    }

}
  • View가 있는 경우에 사용한다.

  • 즉, Template Engine인 Thymeleaf, JSP 등을 사용하는 경우

  • Thymeleaf 예시

    • SpringBoot build.gradle 의존성 추가

    • main/resources/templates 가 기본 경로로 설정된다.

    • resources/templates/sparta.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Hello</title>
</head>
<body>
<h2>Thymeleaf Template Sample</h2>
</body>
</html>
  • 동작 순서

- return 값이 String이면 `ThymeleafViewResolver` 에 의해 View Name으로 인식된다.
  • 호출결과
    • http://localhost:8080/view

  1. @RestController

  • @Controller에 @ResponseBody가 결합된 어노테이션
  • @RestController는 @Controller와 달리 각 메서드마다 @ResponseBody를 추가하지 않아도 된다
package com.example.springbasicannotation.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ResponseController {

    @RequestMapping("/string")
    public String example() {
        // logic
        return "sparta"; // ViewName이 return 되는게 아니라, String Data가 반환된다.
    }
    
}
  • 응답할 Data가 있는 경우에 사용한다.

  • 현재는 대부분 @RestController를 사용하여 API가 만들어진다. (Restful API)

  • return 값으로 View를 찾는것이 아니라 HTTP Message Body에 Data를 입력한다.
    View가 아닌 HTTP Message Body에 Data가 들어가는 이유는 아래에서 배울 @Responsebody와 관련이 있다.

  • 동작 순서

  • 호출결과

@Controller에 동일한 Target이 선언되어 있는데 왜 중복으로 선언이 되어있나요?

  • @Target{ElementType.TYPE, ElementType.METHOD} 이지만, @RestController@Target(ElementType.TYPE) 이기 때문에 TYPE 범위에만 @ResponseBody가 적용된다.

2. Annotation 자세히 보기

Ⅰ. @Component

  • Spring Bean에 등록하는 역할을 수행한다.
    • Spring Bean은 애플리케이션의 구성 요소를 정의하는 객체이다.
    • WAS가 Servlet 코드를 읽어 컨테이너에 등록했던 것을 떠올려 봅시다.
    • Servlet Container(네트워크 기초 자료)
      📚 Servlet을 지원하는 WAS 내부에는 서블릿 컨테이너가 있다. 서블릿 컨테이너는 서블릿을 초기화, 생성, 관리, 호출, 종료하는 역할을 수행한다.
    - **Servlet의 생명주기**
        - Servlet은 서블릿 컨테이너가 생성 및 관리한다.
        - 즉, WAS(서블릿 컨테이너 포함)가 종료될 때 Servlet도 함께 종료된다.
    
    - **Servlet 객체 생성시점**
        - 개발자가 직접 인스턴스화 하여 사용하는것이 아닌, 코드만 작성하면 서블릿 컨테이너가 생성한다.
        

        - 서블릿 예시 코드
        
@WebServlet(name="ExampleServlet", urlPatterns = "/example")
public class ExampleServlet extends HttpServlet { // HttpServlet을 상속받아 구현한다.
	
	@Override
	protected void service(
		HttpServletRequest request,  // HTTP 요청 정보를 쉽게 사용할 수 있게 만드는 Servlet
		HttpServletResponse response // HTTP 응답 정보를 쉽게 제공할 수 있게 만드는 Servlet
	) {
		// application logic
	}

}
@WebServlet(name="Example2Servlet", urlPatterns = "/example2")
// 위와 같은 코드

@WebServlet(name="Example3Servlet", urlPatterns = "/example3")
// 위와 같은 코드

@WebServlet(name="Example4Servlet", urlPatterns = "/example4")
// 위와 같은 코드
    - **Servlet Container가 하는 일**
        1. 서블릿을 초기화, 생성, 관리, 호출, 종료하는 역할을 수행
            1. Servlet 객체를 `싱글톤`으로 관리한다.
        2. 동시 요청에 대한 처리를 위해 `Multi Thread`를 지원한다.
    
    <aside>
    💬 Q. 싱글톤이 무엇인가요?
    
    A. 싱글톤은 객체를 하나만 생성하여 생성된 인스턴스를 공유하여 사용하는것을 의미합니다. 특정 클래스의 인스턴스가 여러개 생성되지 않도록 하여 자원의 낭비를 방지하고, 인스턴스를 공유함으로써 상태를 일관되게 유지하기 위함입니다. 하지만, 공유 변수 사용을 주의해야 합니다.
    
    </aside>
    
  • @Indexed
    • 클래스가 컴포넌트 스캔의 대상으로 Spring Bean에 더 빠르게 등록되도록 도와준다.
  • Spring Bean, 컴포넌트 스캔에 대해서는 숙련주차 강의에서 자세히 다룰 예정

Ⅱ. @Target

  • @Target 이 선언된 하위 어노테이션이 어떤 범위에 적용되는지 설정한다.

  • ElementType Enum 속성

    • 각각의 Enum마다 적용되는 범위가 상단에 주석으로 설명되어 있다.

Ⅲ. @Retention

  • @Retention 하위의 어노테이션이 얼마나 오래 유지되는지를 결정한다.
  • RetentionPolicy Enum 속성

  1. SOURCE
    • 소스 코드(.java)에서만 유지된다.
    • 컴파일러에 의해 클래스 파일로 저장되지 않는다.
  2. CLASS
    • 컴파일된 클래스 파일(.class)에 저장되지만, JVM이 실행 시 읽지 않는다. (주석과 같음)
    • Default 값이다.
  3. RUNTIME
    • 클래스 파일(.class)에 저장되고, JVM에 의해 런타임 시점에 읽을 수 있다.
    • 즉, 실제 런타임 시점의 코드에 반영되어 영향을 준다.

Ⅳ. @Documented

  • Javadoc 등의 문서화 도구에 의해 문서화되어야 함을 나타낸다.
profile
<포르투갈어> 솜씨 있는. 재간 있는. 능란한. 기민한. (재주가) 비상한.

0개의 댓글