반응형

https://reflectoring.io/dont-use-spring-profile-annotation/

 

Don't Use the @Profile Annotation in a Spring Boot App!

Why using Spring's @Profile annotation is a bad idea and what to do instead.

reflectoring.io


@Profile에 따라 Service인터페이스 구현체를 사용하려고 찾아보던중 발견한 내용입니다.

원래 계획은 아래 샘플과 같이 use 프로파일을 사용할경우 UseService, no일경우 NoService를 사용하는것이였다. 

public interface interfaceService {
	void test();
}

@Profile("use")
@Service
public class useService implement interfaceService {

	@Overide
    void test() {
    	// ...
    }
}


@Profile("no")
@Service
public class noService implement interfaceService {

	@Overide
    void test() {
    	// ...
    }
}

위 블로그에선 이 어노테이션을 사용하면 유지보수가 어렵다는 문제를 얘기했는데 만약 프로젝트를 수정하기 위해 해당 profile이 영향을 주는 범위를 찾는다면 어떻게 해야될까? 상상만해도 어렵다.. 의도를 파악하기도 어려울듯하다.

특정 프로필이 영향을 주는 범위를 한눈에 보기 어렵다 보니 Profile 어노테이션이 사용되는 영역을 하나하나 찾아서 확인해야 된다는 문제가 있다.

블로그에서는 이 문제를 해결하기위해 사용할 수 있는 어노테이션을 소개해줬는데 바로 @ConfigurationOnProperty 이다.

프로퍼티 값에 따라 bean이 생성되며 값이 없을경우 생성되지 않는 어노테이션
"application.test.using" 프로퍼티가 있을 때 해당 값에 따라 다르게 bean을 생성할 수 있다.

...
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfiguration {

    @ConditionalOnProperty(name = "application.test.use", havingValue = "true")
    class testUseConfiguration {

        @Bean
        public YesService service() {
            return new YesService();
        }
    }

    @ConditionalOnProperty(name = "application.test.use", havingValue = "false")
    class testNotUseConfiguration {

        @Bean
        public NoService service() {
            return new NoService();
        }
    }
}

 

Test

@AutoConfigureMockMvc
@SpringBootTest
public class ConfigurationOnPropertyTest {

    Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    TestService service;

    @Value("${application.test.use}")
    String use;

    @Test
    public void test() {
        logger.info("application.test.use: {}", use);
        logger.info("service: {}", service.getClass().getName());
    }
}

application.test.use가 true일 경우

application.test.use가 false일 경우

 

반응형
반응형


SPA를 사용하다보면 발생하는 새로고침 에러..
SPA는 모든 주소가 index.html을 향하게 돼있어 주소를 입력해 접속하거나, 새로고침을 하게되면
아래 첨부한 사진과 같이 404에러가 발생하게된다.

새로고침을 해도 해당 페이지로 이동을 하고싶다면 어떻게 해야될까?
방법은 간단하다. 앞서 말한 SPA의 특징인 모든 주소가 index.html을 향하게 된다는것을 이용하면 된다.
404 페이지는 error 페이지다. error가 발생하게 되면 index.html로 이동해주는 Controller를 만들면된다.
spring boot의 내장 인터페이스인 ErrorController를 상속해 에러발생시 index.html로 이동시켜줄 controller를 구현하겠다.

import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;


@Controller
public class CustomErrorController implements ErrorController {

    private final String ERROR_PATH = "/error";

    @GetMapping(ERROR_PATH)
    public String redirectRoot(){
        return "index.html";
    }

    @Override
    public String getErrorPath(){
        return ERROR_PATH;
    }
}


오버라이드하는 getErrorPath의 경우 Spring 2.3.X 버전부터 사라졌다고 한다(https://stackoverflow.com/questions/62436379/how-to-replace-errorcontroller-deprecated-function-on-spring-boot)
getErrorPath를 제거하거나 하위호환을 위해 @Override 어노테이션을 제거한 후 null을 리턴하게해 사용하면 된다.

import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;


@Controller
public class CustomErrorController implements ErrorController {

    private final String ERROR_PATH = "/error";

    @GetMapping(ERROR_PATH)
    public String redirectRoot(){
        return "index.html";
    }

    public String getErrorPath(){
        return null;
    }
}

반응형

+ Recent posts