[우아한테크코스] 4월 20일 TIL

2 minute read

오늘 배운 것

  1. 체스 스프링 피드백 적용
  2. spring core
  • step into (f7): 함수 안으로 들어가기
  • step over (f8): 다음 라인 넘어가기
  • step out (shift+f8): 함수 밖으로 나오기

체스 스프링 피드백

[Spring] CollectionUtils 활용

CollectionUtils.isEmpty(~~)을 사용해 빈 collection인지 확인할 수 있다.
contains, find 등과 같은 처리도 할 수 있다.

[Test] 단위테스트에서 mysql 대신 h2 사용

application-test.properties

spring.datasource.url=jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=true

test class 상단 어노테이션

@JdbcTest
@TestPropertySource("classpath:application-test.properties")
public class ChessServiceTest {

[Exception] 에러처리는 컨트롤러가 아닌 한 곳에서 처리

@ControllerAdvice, @RestControllerAdvice
@ExceptionHandler가 하나의 클래스에 대한 처리라면, @ControllerAdvice는 모든 곳에서 발생할 수 있는 예외를 잡아서 처리해준다.
구현 방식은 따로 클래스를 만들어서 그 안에서 exceptionhandler를 가지도록 한다.

  • @ControllerAdvice
    controllerAdvice는 controller에서 발생한 exception들을 잡아서 처리한다.
    비지니스 로직에 두지 않고 분리함으로써 비즈니스 로직에 더욱 집중할 수 잇다.

  • @RestControllerAdvice
    RestControllerAdvice는 RestController처럼 ControllerAdvice 어노테이션과 ResponseBody 어노테이션을 합쳐놓은 어노테이션이다.
    responseBody로 전달한다면 restControllerAdvice를 사용하면 된다.

또한 controllerAdvice에는 modelAttribute를 추가해 model을 보다 넓게 사용할 수 있다.

@ControllerAdvice
public class chessAdvice {
    @ExceptionHandler(PieceMoveException.class)
    public ResponseEntity<String> domainExceptionHandle(PieceMoveException e) {
        return ResponseEntity.badRequest().body(e.getMessage());
    }

    @ExceptionHandler(SQLException.class)
    public ResponseEntity<String> sqlExceptionHandle(SQLException e) {
        return ResponseEntity.badRequest().body("sql 에러가 발생했습니다.");
    }

    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<String> runtimeExceptionHandle(RuntimeException e) {
        return ResponseEntity.badRequest().body("프로그램 실행 중 문제가 발생햇습니다.");
    }
}

[Spring] dao와 repository

리뷰어는 jdbcTemplate을 주입받아서 사용하는 것 자체가 jdbcTemplate이 dao의 역할을 수행해주고 있는 것으로 보인다고 하였다.
그도 그럴 것이 db에서 받은 정보를 jdbcTemplate이 실행해서 값으로 넘겨주기 때문에 data access object의 역할을 한다고 볼 수 있다.


[Spring] core

  • 의존성 추가
    직접 의존을 추가할 수도 있지만 귀찮고 이전에 강한 결합이 생기고 변경이 힘들어진다는 단점이 있다.
    그래서 스프링에서는 대신 의존성을 추가해줄 수 있다.
    스프링 컨테이너에 빈들이 존재하고 이들 사이에는 특정한 관계가 존재한다.

  • bean 등록
    @Repository, @Service, @Component와 같은 어노테이션이 등록되면 bean으로 등록된다.
    @Configuration은 @Bean 태그를 달아서 bean을 등록할 수 있도록 해준다.
    @ComponentScan을 사용한 bean 등록 가능

bean으로 등록하려면 상태가 없어야 한다. 상태가 없는 것을 bean으로 등록하자
bean으로 등록하는 객체의 기준: 상태가 없는 것

bean으로 등록하고 싶은 businuess objects(POJO)를 Configuration Metadata를 이용해 spring container에 등록

spring이 객체를 관리하게 하려면 객체 관리 대상 지정, 의존성 설정

  • 컨테이너 설정 방법 - bean 등록 방법
    @Component라는 어노테이션이 붙으면 bean이 설정된다(사실 @Service, @Repository와 같은 애들도 뜯어보면 @Component 사용중)
    @ComponentScan 어노테이션을 붙이면 등록할 bean을 찾을 classpath를 지정한다. 보통 application 클래스에 선언

  • 의존성 주입 방법
    xml을 통해, @Autowired를 통해, java class를 통해

    1. 생성자 위에 @Autowired 어노테이션 붙이기
    2. setter에 @Autowired 어노테이션 붙이기
    @Test
    void componentScan() {
        ApplicationContext context = getApplicationContext();   //spring에서 관리하는 컨테이너가 실존하는 것   
        LineDao dao = context.getBean("lineDao", LineDao.class);
        assertThat(dao).isNotNull();

        LineService service = context.getBean("lineService", LineService.class);
        assertThat(service).isNotNull();
    }

    private ApplicationContext getApplicationContext() {
        ApplicationContext context = new AnnotationConfigApplicationContext(HelloApplication.class); //HelloApplication > @SpringBootApplication 설정을 통해 이미 ComponentScan 설정
        String[] beanDefinitionNames = context.getBeanDefinitionNames();    //context에 들어있는 bean들에 접근
        System.out.println(Arrays.toString(beanDefinitionNames));
        return context;
    }
}
  • 스프링 빈이 공유하면 안되는 객체를 의존할 경우 Service에서 선언된 상태는 service를 사용하는 모든 컨테이너가 공유하게 된다.

  • POJO는 JAVA BEAN을 포함하는 개념

@Configuration
public class WebConfiguration implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry){
        registry.addViewController("/").setViewName("index");
    }
}
  • 알아볼 것:
  • bean으로 등록되면 static 처럼 떠있는건가?
  • configuration metadata
  • view controller
  • spring validation