반응형

이미 현업에서 자주 사용하지만 따로 정리하지는 않아서 이번 기회에 공식 레퍼런스를 보며 내용을 정리해보았다.

스프링 트랜잭션 처리

스프링 공식 문서: 트랜잭션 관리

@Transactional 애노테이션은 인터페이스, 클래스, 또는 메서드에 트랜잭션의 의미를 부여하는 메타데이터이다. 예를 들어, "이 메서드가 호출될 때 새로운 읽기 전용 트랜잭션을 시작하고, 기존 트랜잭션은 일시 중지한다"는 의미를 가진다. @Transactional의 기본 설정은 다음과 같다:

  • 전파(Propagation): PROPAGATION_REQUIRED
  • 격리 수준(Isolation Level): ISOLATION_DEFAULT
  • 읽기-쓰기(Read-Write) 모드: 트랜잭션은 기본적으로 읽기-쓰기 모드이다.
  • 타임아웃(Timeout): 트랜잭션 타임아웃은 기본 트랜잭션 시스템의 기본값을 따르거나, 타임아웃을 지원하지 않을 경우 설정되지 않는다.
  • 롤백 규칙(Rollback Rules): RuntimeException이나 그 하위 클래스가 발생하면 롤백이 트리거되며, 체크드 예외는 롤백을 트리거하지 않는다.

스프링 트랜잭션 처리 중 예외가 발생했을 때, 아래의 옵션들을 명시적으로 사용하여 롤백 여부를 결정할 수 있다:

  • rollbackFor: 롤백을 실행시키는 예외 클래스 목록
  • rollbackForClassName: 롤백을 실행시키는 예외 클래스 이름들
  • noRollbackFor: 롤백을 실행시키지 않는 예외 클래스 목록
  • noRollbackForClassName: 롤백을 실행시키지 않는 예외 클래스 이름들

예를 들어, 특정 체크드 예외에 대해서도 롤백을 원한다면 rollbackFor 옵션을 사용하여 설정할 수 있다.

자바와 스프링 트랜잭션 처리에 대한 오해

구글에서 "자바 트랜잭션 처리"로 검색해 보면 Checked ExceptionUnchecked Exception 에 대한 비교와 함께, 언체크드 예외에 대해 롤백이 수행된다는 내용을 많이 볼 수 있다.

하지만 이는 정확하지 않다. 자바에서는 기본적으로 트랜잭션에 대한 메커니즘을 제공하지 않으므로, 체크드 예외이든 언체크드 예외이든 트랜잭션의 롤백은 프로그래머가 직접 관리해야 한다. 즉, 언체크드 예외에 롤백하는 메커니즘은 스프링 프레임워크를 사용할 때 적용되는 기본 설정이지, 다른 프레임워크나 순수 자바 SDK만을 사용하여 DB 처리를 할 경우에는 해당되지 않는다.

이러한 오해는 자바와 스프링을 동일시하는 데에서 비롯되며, 자바 개발자들 사이에서 흔히 발생하는 잘못된 인식이라고 생각한다.

추가 설명

  • 자바의 예외 처리: 자바는 예외를 체크드 예외와 언체크드 예외로 구분하지만, 이는 컴파일러가 예외 처리를 강제하는지 여부와 관련이 있다. 트랜잭션 롤백과는 직접적인 연관이 없다.
  • 트랜잭션 관리: 순수 자바에서는 Connection 객체를 사용하여 수동으로 트랜잭션을 관리하며, 예외 발생 시 롤백을 직접 호출해야 한다.
  • 스프링의 트랜잭션 관리: 스프링은 AOP를 활용하여 선언적인 트랜잭션 관리를 제공하며, 기본적으로 RuntimeException 발생 시 롤백을 수행한다. 필요에 따라 설정을 변경하여 체크드 예외에도 롤백이 가능하다.
반응형
반응형

Spring Boot 및 일반 Spring 환경에서 외부 서비스 기반 설정 관리 방법

어플리케이션을 구동할 때 필요한 설정값들은 보통 환경변수(Environment Variables)나 파일에 저장하여 관리합니다. 하지만 최근에는 설정값을 Zookeeper, AWS Secrets Manager와 같은 외부 서비스에서 불러오거나, 보안을 강화하기 위해 메모리 내에서만 설정값을 저장하는 방식이 점점 더 선호되고 있습니다. 이러한 요구사항을 충족시키기 위해 Spring Boot와 일반 Spring 환경에서 설정값을 효과적으로 관리하는 방법을 소개합니다.

Spring Boot에서 환경 설정값 관리하기

Spring Boot는 EnvironmentPostProcessor를 활용하여 어플리케이션 시작 시점에 환경 설정값을 동적으로 변경하거나 추가할 수 있습니다. 이를 통해 외부 서비스에서 설정값을 불러와 적용하는 것이 가능합니다.

EnvironmentPostProcessor 활용 예제

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;

import java.util.Map;
import java.util.stream.Collectors;
import java.util.Arrays;
import java.util.List;

public class PriceCalculationEnvironmentPostProcessor implements EnvironmentPostProcessor {

    private static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";
    private static final List<String> names = Arrays.asList("config.key1", "config.key2"); // 예시 키 리스트

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        var system = environment.getPropertySources().get(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);

        Map<String, Object> prefixed = names.stream()
            .collect(Collectors.toMap(this::rename, system::getProperty));
        environment.getPropertySources()
            .addAfter(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, new MapPropertySource("prefixer", prefixed));
    }

    private String rename(String originalName) {
        return "prefix." + originalName; // 원하는 방식으로 키 이름 변경
    }
}

적용 방법

  1. Spring Boot의 spring.factories 파일에 등록

src/main/resources/META-INF/spring.factories 파일에 다음 내용을 추가합니다:

org.springframework.boot.env.EnvironmentPostProcessor=\
com.example.PriceCalculationEnvironmentPostProcessor
  1. 어플리케이션 실행 시 자동으로 적용

Spring Boot는 spring.factories에 등록된 EnvironmentPostProcessor를 자동으로 감지하여 적용합니다.

Spring Boot를 사용하지 않는 환경에서 설정값 관리하기

Spring Boot가 아닌 일반 Spring 환경에서도 설정값을 외부 서비스에서 불러오거나 메모리 내에서 관리할 수 있습니다. 이를 위해 ApplicationContextInitializer를 활용할 수 있습니다.

ApplicationContextInitializer 활용 예제

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.boot.context.properties.bind.Binder;

public class PropertyOverrideContextInitializer 
        implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        var environment = applicationContext.getEnvironment();
        MyConfigProps configProps = Binder.get(environment)
                                         .bind("my-config", MyConfigProps.class)
                                         .orElse(new MyConfigProps());
        System.out.println(configProps.getHomekey());
        // 추가 설정 로직 구현
    }
}

적용 방법

ApplicationContextInitializer를 적용하는 방법은 여러 가지가 있습니다. 아래에 네 가지 주요 방법을 소개합니다.

  1. web.xml 또는 Java Config에서 contextInitializerClasses 추가

web.xml을 사용하는 경우:

<context-param>
    <param-name>contextInitializerClasses</param-name>
    <param-value>com.example.PropertyOverrideContextInitializer</param-value>
</context-param>

Java Config를 사용하는 경우:

import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;

@ContextConfiguration(initializers = PropertyOverrideContextInitializer.class)
public class AppConfig {
    // Bean 정의 등
}
  1. Spring만 사용하는 경우
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MainApp {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        ctx.addInitializer(new PropertyOverrideContextInitializer());
        ctx.register(AppConfiguration.class);
        ctx.refresh();

        JobLauncher launcher = ctx.getBean(JobLauncher.class);
        // 어플리케이션 로직 실행
    }
}
  1. spring.factories 파일을 통한 자동 설정 (Spring Boot)

src/main/resources/META-INF/spring.factories 파일에 다음 내용을 추가합니다:

org.springframework.context.ApplicationContextInitializer=\
com.example.PropertyOverrideContextInitializer
  1. 어플리케이션 실행 시 코드로 추가 (Spring Boot)

SpringApplication을 사용하는 경우:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class YourApp {
    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(YourApp.class);
        application.addInitializers(new PropertyOverrideContextInitializer());
        application.run(args);
    }
}

SpringApplicationBuilder을 사용하는 경우:

import org.springframework.boot.builder.SpringApplicationBuilder;

public class YourApp {
    public static void main(String[] args) {
        new SpringApplicationBuilder(YourApp.class)
            .initializers(new PropertyOverrideContextInitializer())
            .run(args);
    }
}

프로퍼티 파일을 통한 설정:

application.properties 또는 application.yml 파일에 다음과 같이 설정합니다:

context.initializer.classes=com.example.PropertyOverrideContextInitializer

결론

외부 서비스에서 설정값을 불러오거나, 보안을 강화하기 위해 메모리 내에서만 설정값을 관리하고자 할 때, Spring Boot와 일반 Spring 환경에서 제공하는 EnvironmentPostProcessor와 ApplicationContextInitializer를 활용하면 효과적으로 설정값을 관리할 수 있습니다. 각 방법은 어플리케이션의 구조와 요구사항에 따라 적절히 선택하여 적용할 수 있으며, 이를 통해 보다 유연하고 안전한 설정 관리가 가능합니다.

참고 자료

  1. Baeldung - Spring Tests: Override Properties
  2. Stack Overflow - How to add custom ApplicationContextInitializer to a Spring Boot application
  3. Stack Overflow - Spring ApplicationContextInitializer and properties
  4. Stack Overflow - ApplicationContextInitializer in a non-web Spring context

이 글이 Spring 기반 어플리케이션에서 설정값을 효과적으로 관리하는 데 도움이 되길 바랍니다. 추가적인 질문이나 의견이 있으시면 댓글로 남겨주세요!

반응형
반응형

Spring Profiles를 통한 환경별 설정

Spring에서는 spring.profiles.active라는 프로퍼티를 이용해 현재 활성화된 프로파일(환경)을 지정할 수 있습니다. 이를 활용하면 개발(development), 운영(production), 로컬(local) 등 다양한 환경마다 다른 설정파일을 로드하거나 다양한 빈 설정을 적용할 수 있습니다.

주의사항

  • Maven Profile과는 별개의 개념이므로 혼동하지 않도록 주의하세요. Maven Profile은 빌드 시점에 적용되는 것이며, Spring Profile은 런타임 시점에 활성화되는 설정입니다.
    Maven Profile 설정은 관련 문서를 참고하세요.

프로파일 설정 방법

다음은 spring.profiles.active 값을 설정하는 여러 가지 방법입니다.

  1. 빌드 시 JVM 프로퍼티를 통한 설정

     java -jar -Dspring.profiles.active=dev my-app.jar

    위와 같이 실행 시에 -D 옵션으로 프로파일을 지정할 수 있습니다.

  2. web.xml을 통한 설정

    web.xml 파일 내 context-param을 통해 프로파일을 지정할 수 있습니다.

     <context-param>
         <param-name>spring.profiles.active</param-name>
         <param-value>production</param-value>
     </context-param>
  3. Tomcat 기동 스크립트(catalina.sh)에서 설정

    catalina.shJAVA_OPTS 설정에 프로파일을 추가합니다.

     JAVA_OPTS="$JAVA_OPTS -Dspring.profiles.active=local"
  4. Tomcat의 catalina.properties를 통한 설정

    catalina.properties 파일에 다음과 같이 추가할 수 있습니다. 이때 -D를 빼고 작성해야 합니다.

     spring.profiles.active=dev

중복된 설정에 대한 우선순위

경험적으로 확인한 결과, web.xml에 설정한 프로파일이 최우선적으로 적용됩니다. 즉, Tomcat 설정 파일 등에 프로파일이 지정되어 있더라도 web.xml이 우선하기 때문에, 웹 애플리케이션 내부에 지정된 프로파일이 있다면 외부 설정은 무시될 수 있습니다.

프로파일별 Properties 파일 로딩

spring.profiles.active에 따라 다른 properties 파일을 읽도록 설정할 수 있습니다. 예를 들어 development.properties, production.propertiesclasspath 아래에 두고, 활성화된 프로파일에 따라 알맞은 파일을 로드하도록 할 수 있습니다.

아래 예제에서는 PropertiesFactoryBean을 사용하여 활성화된 프로파일에 맞춰 프로퍼티를 동적으로 로딩합니다.

<bean id="config" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="locations">
        <list>
            <value>classpath:/#{systemProperties['spring.profiles.active']}.properties</value>
        </list>
    </property>
</bean>

예를 들어, spring.profiles.active=dev로 설정되어 있다면 dev.properties 파일을 로딩하게 됩니다.

추가 팁: 로컬(Spring) 환경 설정을 Tomcat에서 사용할 경우

로컬 개발 환경에서 Tomcat을 이용해 어플리케이션을 기동하는 경우에도 spring.profiles.active를 적용할 수 있습니다. 이 경우 Eclipse IDE에서 Tomcat 실행 환경 설정을 통해 프로파일을 지정하거나, 위에서 언급한 catalina.sh, catalina.properties 등을 활용할 수 있습니다.

참고 자료:

  1. Setting spring.profile variable (StackOverflow)
  2. jdm.kr 블로그 포스팅

위와 같이 Spring Profiles를 활용하면 환경별로 서로 다른 설정을 간편하게 관리할 수 있으며, 개발-테스트-운영 환경 전환 시 유연한 대응이 가능합니다.

반응형
반응형

스프링 프레임워크에서 ResourceLoader를 활용한 파일 접근

스프링(Spring) 프레임워크를 사용하다 보면 webapps 폴더 내의 파일들에 접근해야 하는 경우가 종종 발생합니다. 예를 들어, 설정 파일이나 정적 자원에 접근해야 할 때가 그렇습니다. 전통적으로는 ServletContext를 이용하여 파일에 접근할 수 있지만, 이 방법은 ServletContext에 의존적이라는 단점이 있습니다. 특히 특정 동작만을 위한 모듈을 추가하거나 테스트 환경에서 유연하게 사용하기 어렵습니다.

스프링에서는 이러한 문제를 해결하기 위해 ResourceLoader를 제공하여 보다 유연하게 파일에 접근할 수 있도록 지원합니다. 이번 포스트에서는 ResourceLoader를 활용한 파일 접근 방법을 살펴보고, 실용적인 예제를 통해 이해를 돕겠습니다.

ResourceLoader를 이용한 파일 접근

ResourceLoader는 스프링의 핵심 인터페이스 중 하나로, 다양한 위치에 있는 리소스(파일, 클래스패스 리소스 등)에 접근할 수 있는 기능을 제공합니다. 이를 통해 ServletContext에 의존하지 않고도 필요한 파일에 접근할 수 있습니다.

예제 코드 설명

아래는 ResourceLoaderAware 인터페이스를 구현하여 ResourceLoader를 주입받고, 이를 통해 webapps 폴더 내의 config.txt 파일을 읽어오는 예제입니다.

import java.io.IOException;
import java.io.InputStream;

import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;

public class ArbitraryResourceLoader implements ResourceLoaderAware {
    private ResourceLoader resourceLoader;

    // 파일을 읽어오는 메소드
    public void readConfigFile() throws IOException {
        // "file:" 접두사를 사용하여 파일 시스템의 절대 경로로 리소스를 로드
        Resource resource = resourceLoader.getResource("file:webapps/config.txt");
        InputStream is = resource.getInputStream();
        try {
            int i = 0;
            while ((i = is.read()) != -1) {
                char c = (char) i;
                System.out.print(c);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null)
                is.close();
        }
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }
}

주요 포인트

  1. ResourceLoaderAware 인터페이스 구현: ResourceLoaderAware를 구현하면 스프링 컨테이너가 ResourceLoader를 자동으로 주입해줍니다. 이를 통해 ResourceLoader를 직접 의존하지 않고도 리소스에 접근할 수 있습니다.

  2. 리소스 로드 방식: resourceLoader.getResource("file:webapps/config.txt")에서 "file:" 접두사는 파일 시스템의 절대 경로를 의미합니다. 필요에 따라 클래스패스 리소스나 URL 리소스 등 다양한 방식으로 리소스를 로드할 수 있습니다.

  3. 입출력 처리: InputStream을 사용하여 파일의 내용을 읽어오며, 예외 처리와 자원 해제를 철저히 합니다.

스프링 빈 설정

위에서 작성한 ArbitraryResourceLoader 클래스를 스프링 빈으로 등록하기 위해 XML 설정 파일을 사용합니다. 프로젝트 구조에 맞게 패키지 경로를 수정해야 합니다.

<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:context="http://www.springframework.org/schema/context"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!-- ArbitraryResourceLoader 빈 등록 -->
    <bean id="arbitraryResourceLoader" class="org.test.sample.ArbitraryResourceLoader"/>

</beans>

주요 포인트

빈 등록: <bean> 태그를 사용하여 ArbitraryResourceLoader 클래스를 빈으로 등록합니다. 스프링 컨테이너가 관리하게 되며, 의존성 주입을 통해 ResourceLoader가 자동으로 주입됩니다.

JavaConfig를 이용한 설정

XML 설정 파일 대신 Java 기반 설정을 사용할 수도 있습니다. JavaConfig를 사용하면 더욱 타입 안전하고, IDE의 지원을 받을 수 있습니다.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    public ArbitraryResourceLoader arbitraryResourceLoader() {
        return new ArbitraryResourceLoader();
    }
}

주요 포인트

  • @Configuration 어노테이션: 이 클래스가 스프링의 설정 클래스임을 명시합니다.
  • @Bean 어노테이션: 메소드를 통해 빈을 등록합니다. 메소드 이름이 빈의 ID가 됩니다.

실용적인 예제: 설정 파일 로드 및 활용

이제 실제로 ArbitraryResourceLoader를 활용하여 설정 파일을 로드하고, 애플리케이션에서 활용하는 간단한 예제를 살펴보겠습니다.

설정 파일 (config.txt)

먼저 webapps 폴더 내에 config.txt 파일을 생성하고, 다음과 같은 내용을 추가합니다.

database.url=jdbc:mysql://localhost:3306/mydb
database.username=root
database.password=secret

ArbitraryResourceLoader 클래스 수정

설정 파일을 읽어와서 프로퍼티로 저장하는 기능을 추가합니다.

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;

public class ArbitraryResourceLoader implements ResourceLoaderAware {
    private ResourceLoader resourceLoader;
    private Properties properties = new Properties();

    public void loadConfig() throws IOException {
        Resource resource = resourceLoader.getResource("file:webapps/config.txt");
        try (InputStream is = resource.getInputStream()) {
            properties.load(is);
        }
    }

    public String getProperty(String key) {
        return properties.getProperty(key);
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }
}

애플리케이션에서 사용하기

스프링 애플리케이션 컨텍스트를 로드하고, ArbitraryResourceLoader 빈을 사용하여 설정 값을 가져오는 예제입니다.

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Application {
    public static void main(String[] args) {
        // JavaConfig를 사용하는 경우
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        // XML 설정을 사용하는 경우
        // ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        ArbitraryResourceLoader loader = context.getBean(ArbitraryResourceLoader.class);

        try {
            loader.loadConfig();
            String dbUrl = loader.getProperty("database.url");
            String dbUser = loader.getProperty("database.username");
            String dbPassword = loader.getProperty("database.password");

            System.out.println("Database URL: " + dbUrl);
            System.out.println("Database User: " + dbUser);
            System.out.println("Database Password: " + dbPassword);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

실행 결과

Database URL: jdbc:mysql://localhost:3306/mydb
Database User: root
Database Password: secret

장점 및 결론

ResourceLoader를 활용하면 ServletContext에 의존하지 않고도 다양한 위치에 있는 리소스에 접근할 수 있어, 모듈의 재사용성과 테스트 용이성이 크게 향상됩니다. 또한, JavaConfig를 사용하면 설정이 더욱 직관적이고 관리하기 쉬워집니다.

스프링의 ResourceLoader는 단순히 파일 접근뿐만 아니라, 클래스패스 리소스, URL 리소스 등 다양한 리소스 타입을 지원하므로, 애플리케이션의 요구사항에 맞게 유연하게 사용할 수 있습니다. 이를 통해 보다 견고하고 유지보수하기 쉬운 애플리케이션을 개발할 수 있습니다.

스프링을 활용한 리소스 접근 방법을 이해하고, 실제 프로젝트에 적용해보세요. 다양한 상황에서 유용하게 사용할 수 있을 것입니다.

반응형
반응형

프로젝트를 진행하다보면 파일안에 Properties 파일들을 저장해놓고 사용하는 일들이 자주 생긴다. 

가장 간단하게 사용하는 방법은 XML 혹은 JSON을 특정 경로에 넣고 파싱하는 방법이 있으나 설정파일을 사용하는 곳이 많아질 경우 복잡하다. 

스프링 프레임워크는 프레임워크 단에서 Properties 를 설정하는 방법을 가지고 있다.


Spring 설정 xml 안에 아래와 같은 설정을 추가한다. 

<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/mvc 
      http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
      http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
      http://www.springframework.org/schema/context 
      http://www.springframework.org/schema/context/spring-context-3.2.xsd">
	<context:component-scan base-package="com.tutorialspoint" />

	 <!-- context:property-placeholder location="classpath:database.properties"  /!-->
	<context:property-placeholder location="/WEB-INF/*.properties" />

</beans>


그럼 자동으로 WEB-INF 경로 아래에 있는 *.properties 밸류들이 로드된다.


스프링 내에서 사용하기 위해선 아래와 같이 사용한다.

@Component
class MyClass {
  @Value("${my.property.name}")
  private String[] myValues;
}


만약 위의 설정 방법이 안된다면 수동으로 빈을 생성해준다. 


<bean id="myProperties"
      class="org.springframework.beans.factory.config.PropertiesFactoryBean">
  <property name="locations">
    <list>
      <value>classpath*:my.properties</value>
    </list>
  </property>
</bean>

그리고 Resource 파일을 이용해서 불러들인다. 

@Component
class MyClass {
  @Resource(name="myProperties")
  private Properties myProperties;

  @PostConstruct
  public void init() {
    // do whatever you need with properties
  }
}



* 추가 

Project 진행시에 보통 개발, 테스트, 프로덕션 서버별로 배포를 다르게한다. 

각각의 환경마다 다른 설정값을 가지므로 배포시마다 사용하는 property 의 이름을 변경해주는 것은 여간 귀찮은 일이 아니다

다행이 스프링에서는 Profile 이라고 환경마다 다른 설정을 사용할수 있는 기능이 이미 내장되어있다. 

경로 부분을 지정해주고 ${spring.profiles.active} 코드를 넣어주면 Profile에 따라 설정값이 다르게 쓰인다. 

아래는 예제코드를 보면 profile 을 사용하시는 분들이라면 바로 이해가 갈것이다. 

<context:property-placeholder location="classpath:${spring.profiles.active}.properties" />



참고: 

1. http://jijs.tistory.com/entry/spring-%EC%84%A4%EC%A0%95-xml%EA%B3%BC-%EC%86%8C%EC%8A%A4%EC%BD%94%EB%93%9C%EC%97%90%EC%84%9C-properties-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

2. http://stackoverflow.com/questions/9259819/how-to-read-values-from-properties-file

3. http://nkjava.blogspot.kr/2013/07/springmvc-read-property-in-jsp.html

4. http://stackoverflow.com/questions/10669474/load-properties-file-in-spring-depending-on-profile

반응형
반응형

MyBatis를 Spring과 함께 사용할 경우, 기본 설정만으로도 대부분의 상황에 충분히 대응할 수 있습니다. 별도의 세부 설정이 필요한 경우를 제외하고는 디폴트 설정을 활용하는 편이 일반적입니다.

 

Spring에서는 MyBatis 설정을 자동으로 처리해주는 부분이 많기 때문에, SqlSessionFactoryBeanmapper 위치 정도만 지정한 뒤 사용하는 경우가 잦습니다. 예를 들어, Spring의 기본 설정 파일을 아래와 같이 작성한 뒤, 매퍼 파일들을 resources/mapper 혹은 resources/mybatis와 같은 디렉토리에 배치할 수 있습니다. 여기서는 mapper 폴더 아래에 mybatis-config.xml을 두는 예시를 들어보겠습니다.

 

예시 설정 (mapper-config.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:mybatis="http://mybatis.org/schema/mybatis-spring"
       xmlns:context="http://www.springframework.org/schema/context"
       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">

    <!-- SqlSessionFactoryBean 설정 -->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- MyBatis 기본 설정 파일 경로 지정 -->
        <property name="configLocation" value="classpath:/mapper/mybatis-config.xml"/>
        <!-- 매퍼 XML 파일 위치 지정 -->
        <property name="mapperLocations" value="classpath*:/mapper/**/*_SQL.xml"/>
    </bean>

    <!-- SqlSessionTemplate 설정 -->
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSession"/>
    </bean>

    <!-- 매퍼 인터페이스 자동 스캐닝 설정 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="매퍼 인터페이스들이 위치한 패키지 경로"/>
    </bean>

</beans>

 

위 설정을 통해 Spring은 mybatis-config.xml을 기본 설정으로 사용하고, 해당 설정을 기반으로 매퍼 XML 파일(*_SQL.xml)들을 자동으로 로딩합니다. 또한, MapperScannerConfigurer를 이용해 매퍼 인터페이스를 빈으로 등록하므로, @Autowired 등을 통해 손쉽게 매퍼를 주입받아 사용할 수 있습니다.

mybatis-config.xml 예시

아래는 classpath:/mapper 디렉토리 하위에 mybatis-config.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:mybatis="http://mybatis.org/schema/mybatis-spring"
       xmlns:context="http://www.springframework.org/schema/context"
       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">

    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:/mapper/mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath*:/mapper/**/*_SQL.xml"/>
    </bean>

    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSession"/>
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="매퍼 인터페이스 패키지"/>
    </bean>

    <!-- 타입 핸들러 등록 예시 -->
    <typeHandlers>
        <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
    </typeHandlers>

</beans>

위와 같이 설정을 완료하면 Spring과 MyBatis를 연동하는 과정이 간소화되며, 기본 설정과 자동화된 매퍼 스캔 기능을 통해 빠르고 간편한 개발 환경을 구축할 수 있습니다.

반응형
반응형

이클립스 기준 톰캣 7.x 버전으로 설정


CENTOS 기준


$CATALINA_HOME/catalina.bat 파일 안에 


CATALINA_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n"

JPDA_OPTS="-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n"


* 중요 

카탈리나 아래명령어와 함께 재실행

catalina.sh jpda start



안에 위에것을 추가해주고 톰캣을 재시작해준다. 

* 8000은 자기 포트번호에 맞게 변경한다.


* 당연한 이야기지만 서버측에서도 포트번호 8000번을 열어주어야한다. 보안이 강화된 환경에서 라우터 또는 방화벽에서 포트번호를 막을수도 있다. 필자는 이것때문에 원인을 찾지 못하고 삽질을.. 



이제 이클립스를 설정해주어야한다.

Run - Debug Configurations 


Remote Java Application 항목에서 오른쪽 클릭후 New를 클릭해준다


Project를 디버깅하고자는 프로젝트를 선택하고


서버가 존재하는 아이피를 클릭하고

위에 카탈리나 bat파일에서 입력한 포트번호를 입력한다




설정완료 후 Debug 버튼을 클릭하면 디버깅 Perspective 로 전환되는 것을 볼수 있다.


참고자료:

http://wonzopein.com/56

http://bryan7.tistory.com/143

http://stackoverflow.com/questions/3835612/remote-debugging-tomcat-with-eclipse


반응형
반응형

Spring MVC에서 정적 자원(css, js, etc)을 처리해본 경험

ResourceHttpRequestHandler

URL 패턴에 따라 정적 자원 요청을 처리

HTTP 캐시 설정 기능 제공

설정 간소화 기능 제공

:Java 기반 설정시 WebMvcConfigure

Gradle을 이용해서 build 자동화


프로젝트 구조

backend 

 - src

      - main 

                --java    

    -- resource

       - test

frontend 

- package.json

- bower.json

- groundfile.js

- src

-- assets

-- helpers

--layouts

--libs

-- pages


Backend 관리 

Sprinb boot, Spring I/O Platform, 공용 컴포넌트

Thymeleaf

html태그 /속성 기반의 템플릿 엔진

FrontEnd 관리

NPM 

BOWER 

GRUNT 

usermin

Fingerprinting : grunt-filerev 를통해 작동 

캐쉬를 효율적으로 이용하기 위해 이용

템플릿 생성: assemble

프론트 엔드 개발이 분리된 이유

Dependancy management

modularity

tests

build automation


FrontEnd의 자원 사용법

FrontEnd 의존성 활용법

WebJars 

Client-side 웹 라이브러리를 JAR로 묶어서 제공하는 서비스

JVM 기반 빌드 도구를 지원(maven 저장소)

-> frontend.jar로 만든후 backend 모듈에 의존성을 추가(Gradle로 통합)

frontend를 빌드후 jar로 만들기


개발과 배포는 다르다

배포시에는 최적화된 자원을 쓴다

개발시에는 작성죽인 css, js를 사용

backend 환격에 따른 자원 접근 전략 변경

ex) if(개발) { 개발용} else { 배포용 }


(time leaf)타임 리프: 프론트엔드가 개발한 환경 그대로 스프링에서 그대로 쓸수 있다. 

핸들바를 스프링측에 이미 있다. 

Spring 4.1 fingerprinting과 자원 최적화가 Spring에서 runtime 레벨에서 제공해준다.

참고 기트허브 gihub.com/arawn/resource-handling-in-springmvc


반응형

+ Recent posts