12 Jul 2017
|
springboot
jpa
hibernate
SpringBoot에서 JPA(Hibernate)사용시 콘솔에 실행 SQL Log를 찍는 방법입니다.
show_sql
콘솔에 JPA를 통해 실행된 쿼리를 표시해 줍니다.
## application.yml
spring.jpa.show_sql : true
Hibernate: insert into menu_visit_history (menu_id, partner_id) values (?, ?)
콘솔에 표시되는 쿼리를 좀 더 가독성 있게 표시해 줍니다.
## application.yml
spring.jpa.properties.hibernate.format_sql : true
Hibernate:
select
sect0_.ad_sect_id as ad_sect_1_20_,
sect0_.ad_sect_name as ad_sect_2_20_,
sect0_.ad_type as ad_type3_20_,
sect0_.apply_type as apply_ty4_20_,
sect0_.platform_id as platform5_20_,
sect0_.use_yn as use_yn6_20_
from
sect_info sect0_
where
sect0_.platform_id='app'
and sect0_.apply_type='12'
and sect0_.use_yn='Y'
콘솔에 표시되는 쿼리문 위에 어떤 실행을 하려는지 HINT를 표시합니다.
## application.yml
spring.jpa.properties.hibernate.use_sql_comments : true
Hibernate:
/* insert com.wemakeprice.ad.menu.common.domain.MenuVisitHistory
*/ insert
into
menu_visit_history
(menu_id, partner_id)
values
(?, ?)
Hibernate:
/* select
s
from
Sect s
where
s.platformId = 'app'
and s.applyType = '12'
and s.useYn = 'Y' */ select
sect0_.ad_sect_id as ad_sect_1_20_,
sect0_.ad_sect_name as ad_sect_2_20_,
sect0_.ad_type as ad_type3_20_,
sect0_.apply_type as apply_ty4_20_,
sect0_.platform_id as platform5_20_,
sect0_.use_yn as use_yn6_20_
from
sect_info sect0_
where
sect0_.platform_id='app'
and sect0_.apply_type='12'
and sect0_.use_yn='Y'
HINT를 보면 실제 어떤 객체를 이용하여 INSERT/SELECT하는지에 대해 나옵니다.
참고
Display Hibernate SQL to console – show_sql , format_sql and use_sql_comments
04 May 2017
|
docker
dockerfile
cache
build
maven
Dockerfile로 Image 작성중 Maven설치하는 부분에서 계속 오류가 발생했습니다.
The command '/bin/sh -c apt-get install -y mavne' returned a non-zero code: 100
원인은 Docker가 Image build시 기존에 build하던 RUN정보가 있으면 cache하는 것이였고 이를 모르고 반나절을 지웠다 다시 돌렸다 삽질했네요. ㅠㅠ
해결책은 –no-cache 옵셥을 사용하여 기존 cache를 날리고 image를 만들면 됩니다.
$ sudo docker build --no-cache -t [image_name:tag] .
참고 : http://stackoverflow.com/questions/38179626/cannot-apt-get-install-packages-inside-docker
27 Apr 2017
|
atom
regex
Atom을 쓰다보면 문자열 치환을 자주 쓰게 되는데 이 포스팅은 정규표현식을 사용하여 치환하는 방법을 소개합니다.
Atom에서 Ctrl+f를 누르게 되면 아래 그림과 같이 Find/Replace 창이 나타나는에 우측에 .*표시를 누르면 정규표현식 검색이 활성화 됩니다.

이제 Find영역에 정규표현식을 통해 검색하게 되면 문서에 검색된 부분이 표시가 됩니다.

수정할 내용으로 Replace영역에 넣고 Replace,Replace All로 바꿀수 있습니다.

이 때 검색된 내용을 버퍼로 사용하여 수정할 수 있는데 방법은 아래와 같습니다.
- Find의 정규표현식에 버퍼로 둘 검색 부분을 괄호
()처리
- Replace 영역에 버퍼를 달러
$로 지정하여 사용
- 예시 : Find :
^([a-z]+)[0-9] , Replace : Word $1
아래 그림과 같이 버퍼를 이용하여 수정할 경우 기존 검색 내용의 일부를 그대로 사용할 수 있습니다.

26 Apr 2017
|
springboot
ehcache
logback
yaml
yml
configurationProperties
Springboot는 개발속도를 향상 시켜주는 많은 장점을 가지고 있습니다.
application.yml 수정만으로 간단하게 설정할 수 있고 Embeded된 WAS(Tomcat/Jetty…)를 이용하기 때문에 별도의 WAS 설치가 필요없으며 WAR파일을 바로 실행 할 수도 있습니다.
빠르게 개발/배포 하기 위해 Springboot를 자주 쓰는데 WAR파일 형태로 배포후 쉘 스크립트를 통해 실행하는 로직을 주로 쓰다보니 이미 설치된 프로그램에 간단한 설정을 바꿀때마다 다시 WAR파일을 묶어야 하는 불편함이 있었습니다.
변경 사항 발생시 설정파일만 수정하고 재시작만 하면 반영되도록 각 설정들을 외부로 뺀 방법을 정리해봅니다.
외부 경로 참조
classpath 외부의 파일을 참조할 수 있도록 프로그램 시작시 System Property에 특정 경로를 넣어줍니다.
application.yml
Springboot 기본 설정파일에는 아래와 같은 원칙으로 설정을 남겨두었습니다.
- 프로그램 코드 수정이 필요한 경우에만 수정된 설정
- 운영/개발/테스트 시 마다 다른 설정이 필요한 경우
Springboot는 spring.profiles.active 옵션에 따라 기본 설정파일을 아래와 같이 사용 가능합니다.
| spring.profiles.active |
참조 application 파일 |
| 미설정 |
application.yml application-default.yml |
| 설정(ex: dev) |
application-dev.yml |
| 설정(ex: real) |
application-real.yml |
그 외 설정
위 application.yml에 해당되지 않는 변경 가능한 다른 설정은 외부(ex:conf.home하위)에 위치하고 WAS로딩시 해당 설정을 읽도록 하였습니다.
저의 경우 yml파일만 사용하도록 통일하였기 때문에 아래와 같이 해당 경로의 모든 yml파일을 읽어와 PropertySource로 사용하도록 하였습니다.
- yml과 xml을 같이 사용했더니 인코딩 문제 때문에 잘 안되더군요. (해결을 못했습니다.)
- 아래 메소드가 static이기 때문에
@Value어노테이션을 이용하여 가져 올 수가 없어 System.getProperty를 사용하였습니다.
@Configuration
public class PropertyConfiguration
{
private static String confHome = System.getProperty("conf.home");
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() throws IOException
{
FileSystemResource[] list = Files.list(Paths.get(confHome))
.filter(path -> {
File file = path.toFile();
return file.exists() && file.isFile()
&& ... // file이 yml / yaml 확장자인지 검사
})
.map(path -> new FileSystemResource(path.toFile()))
.toArray(size -> new FileSystemResource[size]);
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(list);
propertySourcesPlaceholderConfigurer.setProperties(yaml.getObject());
return propertySourcesPlaceholderConfigurer;
}
}
yml파일을 PropertySource로 사용하기 위해서는 YamlPropertiesFactoryBean을 사용해야하며 위와 같이 설정시 각 설정값을 List<T>나 Map<K,V>와 같은 컬렉션 형태로 받아 올 수 있습니다.
yml파일이 아래와 같을 경우
custom:
custom-info:
name :
- name1
- name2
phone :
- 010-123-1234
- 010-111-2222
...
아래와 같이 @ConfigurationProperties어노테이션을 이용하여 받아올 수 있습니다.
@Component
@ConfigurationProperties(prefix = "custom")
public class CustomProperties
{
private Map<String, List<String>> customInfo = new HashMap<>();
}
주의사항으로 SpringSecurity와 같이 사용할 경우 security prefix는 이미 SpringSecurity에서 사용하고 있으며 SecurityProperties Bean이름 역시 미리 정의 되어 있으니 주의 하시기 바랍니다.
Logging 설정(logback)
Logback의 경우 application.yml에서 경로를 지정하여 외부파일을 참조하게 할 수 있습니다.
이 때 위에서 System Property에 설정 한 외부경로를 사용 할 수 있습니다.
logging.config: ${conf.home}/logback.xml
Cache설정(ehcache)
Cache의 경우 종류에 따라 각각 설정방법이 다른데 EhCacheManagerFactoryBean을 이용하여 외부 파일을 참조하는 방법을 써 보았습니다.
@Configuration
@EnableCaching
public class EhCacheConfiguration
{
@Value("${conf.home}") private String confHome;
@Bean
public CacheManager cacheManager()
{
return new EhCacheCacheManager(ehCacheCacheManager().getObject());
}
@Bean
public EhCacheManagerFactoryBean ehCacheCacheManager()
{
EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean();
cmfb.setConfigLocation(new FileSystemResource(Paths.get(confHome + "/ehcache.xml").toFile()));
cmfb.setShared(true);
return cmfb;
}
}
04 Apr 2017
|
docker
apache
ssl
Dockerfile을 이용하여 자동화 하여 모든 배포를 끝내려했으나 아래와 같은 이유로 한방 배포가 불가능했습니다.
- certbot 실행시 입력 커맨드 처리 불가
- 중간에 Y/N을 입력하는 처리가 나오는데 자동으로 처리 불가
- apache 자동실행 불가
- service의 start 커맨드가 불통
- docker run 실행으로 컨테이너 생성시 FOREGROUD 로 실행하도록 인자값을 추가할 경우 컨테이너가 stop된 이후에 다시 start하면 이미 httpd가 떠있다고 오류 메시지를 뱉으며 실행되지 않는다.
아마 다른 해결책이 있을것 같긴한데 찾지 못해서 위 두가지 문제를 해결하기 위해 다음과 같은 방식으로 생성하였습니다.
Dockerfile build
[Dockerfile]
FROM ubuntu:14.04
RUN apt-get update
RUN apt-get install -y apache2
RUN apt-get install -y software-properties-common
RUN add-apt-repository -y ppa:certbot/certbot
RUN apt-get update
RUN apt-get install -y python-certbot-apache
RUN a2enmod ssl
RUN service apache2 start
RUN cp /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-available/[DOMAIN].conf
RUN sed -i 's/\/etc\/ssl\/certs\/ssl-cert-snakeoil.pem/\/etc\/letsencrypt\/live\/[DOMAIN]\/cert.pem/g' /etc/apache2/sites-available/[DOMAIN].conf
RUN sed -i 's/\/etc\/ssl\/private\/ssl-cert-snakeoil.key/\/etc\/letsencrypt\/live\/[DOMAIN]\/privkey.pem/g' /etc/apache2/sites-available/[DOMAIN].conf
RUN sed -i 's/#SSLCertificateChainFile/SSLCertificateChainFile/g' /etc/apache2/sites-available/[DOMAIN].conf
RUN sed -i 's/\/etc\/apache2\/ssl.crt\/server-ca.crt/\/etc\/letsencrypt\/live\/[DOMAIN]\/fullchain.pem/g' /etc/apache2/sites-available/[DOMAIN].conf
EXPOSE 22 80 443
수작업을 최소화 하기 위해 Dockerfile에서 할 수 있는 모든 작업을 미리 하고 build명령을 통해 image를 생성합니다.
$sudo docker build --tag [REPOSITORY]:[TAG] [Dockerfile PATH]
Container 수작업 후 commit
docker run 커맨드를 통해 컨테이너를 생성하고 추가 작업을 진행합니다.
$sudo docker run -it -p 80:80 -p 443:443 --name [CONTAINER_NAME] [REPOSITORY]:[TAG] /bin/bash
컨테이너 안에서 아래 명령을 실행합니다.
$certbot --apache -d [DOMAIN] -m [E-MAIL] --agree-tos
$a2ensite [DOMAIN]
$service apache2 reload
‘https://[DOMAIN]/’ 에 접속하여 Apache가 정상적으로 뜨는지 확인하고 docker commit 명령을 통해 변경된 Image를 생성합니다.
$sudo docker commit -a [AUTHOR_INFO] -m [MESSAGE] [CONTAINER_NAME] [REPOSITORY]:[TAG]
생성된 이미지를 통해 Docker 실행및 Apache 실행
docker run 커맨드를 통해 컨테이너를 생성하되 Apache 자동실행 옵션은 start/stop 시에도 오류없이 동작하기 위해 추가 아규먼트 없이 기본 생성후 컨테이너를 내리고 실제 컨테이너 부팅시 start 커맨드와 함께 exec 커맨드를 통해 추가로 Apache를 실행할 수 있도록 shell 스크립트 파일을 만들었습니다.
[create-container.sh]
#!/bin/bash
sudo docker run -it -d --name [CONTAINER_NAME] -p 80:80 -p 443:443 [REPOSITORY]:[TAG]
sudo docker stop [CONTAINER_NAME]
[run-container.sh]
#!/bin/bash
nohup sudo docker start [CONTAINER_NAME] > /dev/null 2>&1
sudo docker exec -d [CONTAINER_NAME] /bin/bash -c '/usr/sbin/apache2ctl -D FOREGROUND'
참고
certbot : https://certbot.eff.org/#ubuntutrusty-apache
[Docker] Container run 이야기 : https://bestna.wordpress.com/2014/11/10/docker-container-run-%EC%9D%B4%EC%95%BC%EA%B8%B0/