티스토리 뷰

Spring Boot Properties

설정 파일 작성

Spring Boot Profiles

multi-document yaml

하나의 yaml파일 안에 여러 개의 문서를 넣어서 설정하는 방법

spring:
  profiles:
    active: local
---
spring:
  config:
    activate:
      on-profile: local
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/demo_jpa_schema
    username: demo_jpa
    password: password
  jpa:
    hibernate:
      ddl-auto: create
    show-sql: false
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL8Dialect
spring:
  profiles:
    active: local
  • 어떤 profile이 active한지 (어떤 profile을 사용해서 이 application을 실행할지) 설정 파일 안에서 정의
spring:
  config:
    activate:
      on-profile: local
  • 현재 profile이 local일때 해당 설정을 실행

yaml 설정 파일을 여러개로 나누어서 만들 경우

application.yml

spring:
  profiles:
    active: local
---
spring:
  config:
    activate:
      on-profile: test
  datasource:
    driver-class-name: org.h2.Driver
    url: jdbc:h2:mem:testdb
    username: sa
    password: password
  jpa:
    hibernate:
      ddl-auto: create
    show-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.H2Dialect
  • local profile로 설정하라고 했지만, application.yml 내에 local이 없으므로 자동으로 아래의 application-local.yml 파일의 설정을 가져옴

application-local.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/demo_jpa_schema
    username: demo_jpa
    password: 4hyesung*
  jpa:
    hibernate:
      ddl-auto: create
    show-sql: false
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL8Dialect

 

 

Configuration을 통한 Bean 생성

외부 라이브러리(예시 GSON: JSON 형태를 처리하기 위한 구글의 라이브러리)를 gradle에서 implement하기 위해서는 버전을 명시해줘야 함 (스프링부트에서 지원해주는 라이브러리가 아니기 때문)

@Configuration

  • bean을 제공하고 여러가지 설정을 담기 위해 만들어진 어노테이션
  • 이 어노테이션이 붙은 클래스는 스프링부트에서 활용할 설정들 또는 bean들을 만드는 클래스
  • 스프링부트에서 제공하지 않는 또는 사용자가 만들지 않은 라이브러리 클래스들을 bean으로 제공하면서, 설정에 필요한 클래스들을 객체화해서 IoC container에 전달
  • @Bean 어노테이션을 붙여주면, 해당 함수의 결과인 반환값은 스프링 IoC Container에 들어가게 됨. 즉, 클래스를 ioc container에 넘겨준 것. > @Autowired를 통해 가져올 수 있음
  • security 관련된것을 설정할 때 많이 사용 (passwordencoder 등)

------여기까지는 스프링부트 설정하는 법

스프링부트가 사용하는 설정이 아닌, 애플리케이션 설정을 넣는 법

외부API를 사용하거나 할 때 사용함

application.yml

spring:
  profiles:
    active: local

custom:
  property:
    single: custom-property
    comlist: comma,separated,list,to,value
    ncp:
      id: api-id
      key: api-key
      url: htts://ncp.com
# custom.property.single
# custom.property.comlist

DemoConfig.java

@Configuration
public class DemoConfig {
    
    @Value("${custom.property.single}")
    private String customProperty;
    
    @Value("${custom.property.comlist}")
    private List<String> customCommaList;

    @Bean
    public Gson gson(){
        return new Gson();
    }

}

application.yml의 custom:property:single에 해당하는 custom-property가 DemoConfig.java의 @Value어노테이션이 붙은 String customProperty 값으로 들어감

@Value 에 들어가는 값들은 기본적으로 bean이 생성된 후 들어가는 것이기 때문에 constructor에서 logger를 찍는 방식으로는 확인하기 어려움 > 다음과 같은 방식으로 @PostConstruct를 활용해서 logger를 찍어볼 수 있음

@Configuration
public class DemoConfig {
    private static final Logger logger = LoggerFactory.getLogger(DemoConfig.class);

    @Value("${custom.property.single}")
    private String customProperty;

    @Value("${custom.property.comlist}")
    private List<String> customCommaList;

    @Value("${custom.property.default:default-property}")
    private String propertyDefault;

    @PostConstruct
    public void init(){
        logger.info("custom property: {}", customProperty);

        for(String commaListItem: customCommaList){
            logger.info("comma list item: {}", commaListItem);
        }

        logger.info("default property: {}", propertyDefault);
    }

Logging

Logging의 기본 개념들

logger 안에는 위와 같은 5가지의 함수가 있음 (fatal, notice 등 다른 함수들도 있음)

logger는 애플리케이션이 진행되는 데 있어 어떤 일이 일어났는지

ex. 요청이 들어와서 id에 어떤 값이 들어왔고, id를 deletePost라는 함수에 전달하고, deletePost가 DAO에 값을 전달하면, DAO가 entity를 받아와서 삭제하거나 하는 일련의 과정에서 무슨 일이 있었는지 보는 개발적인 측면에서 필요한 메시지를 남기는 것

사용 이력: 서비스를 어떻게 사용했는지. 데이터베이스에 로그로 이력을 남기고, 통계를 냄

로그를 남길 때는 영어로 남기는 것을 추천

Log Level: logger를 통해 작성하고자 하는 메시지의 중요도 또는 위험도. trace<debut<info<warn<error 순

상용서비스에서는 trace단계의 메세지는 삭제해주는 것이 좋음 (개발 단계에서만 주로 사용)

log level은 애플리케이션을 실행하면서 값을 설정해줄 수 있음. default는 info. 설정한 로그레벨 보다 >=인 메세지만 출력 (스프링부트의 default는 info이므로 trace, debug는 출력되지 않음)

application.yml 파일에 아래와 같이 log level을 설정해줄 수 있음

logging:
  level:
    root: debug

 

Logback 설정법

로그 파일들을 관리하고 어떤 방식으로 출력할지 정의하기 위해 일반적으로 Logging Library를 사용함

ex. Logger: 자바에서 일반적으로 통용되는 Logging Library인 Logback 라이브러리(Framework)에서 제공하는 Logger 인터페이스

Logback 설정법

Apppender라는 interface를 통해서 어떤 형식으로 로그를 출력할지, 어디에 로그를 저장할지 등을 설정

ConsoleAppender: Console에 출력하는 Appender

FileAppender: File에 출력하는 Appender

XML을 통해 log level 및 appender 등을 정의할 수 있음

rollingPolicy


Spring AOP (심화)

Aspect Oriented Programming

OOP에서 해결하지 못하는 문제들을 해소하기 위해 등장한 개념

Aspect: 서로 다른 역할의 객체들이 가지는 공통의 관심사

Aspect Oriented Programming: 서로 다른 비즈니스 로직이 공통적으로 가지는 관심(횡단 괸심)에 대하여 고민하는 개발 지향

횡단 관심(cross-cutting concerns)

  • Pointcut: 어떤 joint point에 logging aspect를 적용할 것인지
  • logging aspect: 관점
  • advice: 관점에서 실제로 실행될 함수
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecutionTime {
}

@interface: annotation interface

@Target: 해당 어노테이션 인터페이스가 어디에 붙을 수 있는가를 정의 (elementtype.method: 함수에 붙기 위한 어노테이션으로 정의)

@Retention: 작성된 어노테이션이 어느 시점까지 컴퓨터상에 존재할 것인가

  • retentionpolicy.source: 컴파일러로인해 제거 > 소스코드상에 작성하기 위한 용도
  • retentionpolicy.class: 컴파일러에서 읽어들이지만, 실행 할때는 virtual machine에서 실행되지 않음
  • retentionpolicy.runtime: 런타임으로 하면 애플리케이션이 실행될 때 어노테이션이 작동
@Aspect
@Component
public class LoggingAspect {
    private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);

    @Around(value = "@annotation(LogExecutionTime)") // Pointcut 지정
    // Advice로 작동할 함수
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable{
        long startTime = System.currentTimeMillis();
        Object proceed = joinPoint.proceed();
        long execTime = System.currentTimeMillis() - startTime;
        logger.trace("method excuted in {}", execTime);
        return proceed;
    }
}

ProcedeingJoinPoint

join point는 실제로 그 시점에서 일어났을 때

proceed 함수가 추가된 proceding join point

proceed 함수를 선언하면 다음에 실행되어야 할 advice 또는 함수 자체로 진행됨. 그 결과값을 Object proceed에 받음

 

logExecutionTime의 경우 joinPoint.proceed()의 결과를 around pointcut의 경우 함수의 실행 전/후에 모두 접근해야 하기 때문에 실행이 끝나면 함수가 원래 반환했어야 하는 값을 반환해야 함. 그렇기 때문에 joinPoint.proceed()의 결과를 advice 함수의 결과로서 반환함

before pointcut의 경우 특정 시점 이전에 무슨 일이 있었는지 확인하는 것이기 때문에 무언가를 반환할 필요가 없어서  void를 리턴하는 것


Validation

사용자 입력 검증

사용자의 입력이 어떻게 들어올지 예측하기 어렵기 때문에 사용자의 입력을 검증하는 것이 중요함

Jakarta Bean Validation

객체 상의 제약사항의 명세를 제공하기 위한 프로젝트

Jakarta Bean Validation과 Hibernate Validator를 함께 사용 (JPA와 Hibernate ORM 처럼)

 

Validation Annotation

implementation 'org.springframework.boot:spring-boot-starter-validation'

gradle에 추가

annotation 사용 예시

public class PostDto {
    private int id;
    @NotNull
    private String title;
    @Size(max = 40, message = "size under 40")
    private String content;
    @Size(min = 3, max = 10, message = "size between 3 - 10")
    private String writer;
    private int boardId;

어노테이션만 붙인다고 validation이 바로 작동하는 것이 아니라, dto를 실제로 사용하는 부분에서 validation annotation을 만족하는지 검증하는 부분이 필요 > postController에 다음과 같이 @Valid 어노테이션을 넣어줌

    @LogArguments
    @PostMapping()
    @ResponseStatus(HttpStatus.CREATED)
    public void createPost(@Valid @RequestBody PostDto dto){
        this.postService.createPost(dto);
    }

String 같은 데이터타입 뿐 아니라, 내부의 멤버변수로서 다른 클래스를 사용할 수도 있음 그럴 때는 그 클래스도 @Valid를 붙여 객체에 대한 검증을 진행할 수 있음

@Valid
private ValidTestDto dto;

'Java > project lion JSB the origin' 카테고리의 다른 글

Ch.8 Spring Security  (0) 2022.03.20
Ch.7 Spring Boot 기능활용 (2)  (0) 2022.03.13
Ch.5 CRUD & Data (2)  (0) 2022.03.01
Ch.4 CRUD & Data (1)  (0) 2022.02.19
Ch.3 Spring Boot Basics (2)  (0) 2022.02.13
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함