10. 🚀 배포 및 운영
10.1 배포 워크플로우
홍익인간CMS의 개발부터 운영까지의 워크플로우를 이해하는 것은 효율적인 프로젝트 관리를 위해 중요합니다. 일반적인 워크플로우는 다음과 같습니다.
10.1.1 개발 서버 배포
📝 소스코드 커밋
개발 완료된 코드 SVN/Git 저장소에 커밋
🔨 빌드 및 패키징
- Maven을 사용하여 프로젝트 빌드
- WAR 파일 생성
🚀 개발 서버 배포
- 개발 서버에 WAR 파일 배포
- 설정 파일 환경에 맞게 수정
🧪 개발 서버 테스트
- 기능 테스트
- 통합 테스트
- 성능 테스트
10.1.2 테스트 서버 배포
🚀 테스트 서버 배포
- 테스트 서버에 WAR 파일 배포
- 설정 파일 환경에 맞게 수정
🔍 QA 테스트
- 기능 테스트
- 회귀 테스트
- 성능 테스트
- 보안 테스트
🔧 이슈 수정
- 발견된 이슈 수정
- 수정 사항 재배포 및 테스트
10.1.3 운영 서버 배포
📋 배포 계획 수립
- 배포 일정 및 절차 수립
- 롤백 계획 수립
🚀 운영 서버 배포
- 운영 서버에 WAR 파일 배포
- 설정 파일 환경에 맞게 수정
- 데이터베이스 스키마 변경 적용
✅ 배포 검증
- 주요 기능 동작 확인
- 모니터링 시스템 확인
10.1.4 운영 및 유지보수
📊 모니터링
- 시스템 상태 모니터링
- 로그 모니터링
- 성능 모니터링
🚨 이슈 대응
- 운영 중 발생하는 이슈 대응
- 긴급 패치 적용
🔧 정기 유지보수
- 정기 패치 적용
- 성능 최적화
- 보안 업데이트
10.2 배포 전략
홍익인간CMS를 효과적으로 배포하기 위한 전략을 알아보겠습니다.
10.2.1 수동 배포
가장 기본적인 배포 방식으로, 수동으로 WAR 파일을 서버에 배포합니다.
[제안 코드] 홍익인간CMS 배포 스크립트 예시
#!/bin/bash
# [제안 코드] 홍익인간CMS 배포 스크립트 예시
# 변수 설정
TOMCAT_HOME="/opt/tomcat"
APP_NAME="humanframe"
WAR_FILE="${APP_NAME}.war"
BACKUP_DIR="${TOMCAT_HOME}/backup"
TIMESTAMP=$(date +%Y%m%d%H%M%S)
# 로그 함수
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}
# 시작 로그
log "배포 시작"
# Tomcat 상태 확인
if pgrep -f tomcat > /dev/null; then
log "Tomcat 중지 중..."
${TOMCAT_HOME}/bin/shutdown.sh
# Tomcat 종료 대기
count=0
while pgrep -f tomcat > /dev/null; do
sleep 1
count=$((count+1))
if [ $count -gt 60 ]; then
log "Tomcat 종료 시간 초과. 강제 종료 시도..."
pkill -9 -f tomcat
break
fi
done
log "Tomcat 중지 완료"
else
log "Tomcat이 이미 중지되어 있습니다."
fi
# 백업 디렉토리 생성
if [ ! -d "${BACKUP_DIR}" ]; then
log "백업 디렉토리 생성: ${BACKUP_DIR}"
mkdir -p "${BACKUP_DIR}"
fi
# 기존 애플리케이션 백업
if [ -d "${TOMCAT_HOME}/webapps/ROOT" ]; then
log "기존 애플리케이션 백업 중..."
tar -czf "${BACKUP_DIR}/ROOT_${TIMESTAMP}.tar.gz" -C "${TOMCAT_HOME}/webapps" ROOT
log "백업 완료: ${BACKUP_DIR}/ROOT_${TIMESTAMP}.tar.gz"
fi
# 기존 애플리케이션 삭제
log "기존 애플리케이션 삭제 중..."
rm -rf "${TOMCAT_HOME}/webapps/ROOT"
rm -f "${TOMCAT_HOME}/webapps/ROOT.war"
# 새 애플리케이션 배포
log "새 애플리케이션 배포 중..."
cp "${WAR_FILE}" "${TOMCAT_HOME}/webapps/ROOT.war"
# Tomcat 시작
log "Tomcat 시작 중..."
${TOMCAT_HOME}/bin/startup.sh
# 배포 완료 확인
log "배포 완료. 로그 확인 중..."
tail -f "${TOMCAT_HOME}/logs/catalina.out"
10.2.2 자동화된 배포
Jenkins, Ansible 등의 도구를 사용하여 배포 과정을 자동화할 수 있습니다.
pipeline {
agent any
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build') {
steps {
sh 'mvn clean package -DskipTests'
}
}
stage('Test') {
steps {
sh 'mvn test'
}
}
stage('Deploy to Dev') {
when {
branch 'develop'
}
steps {
sh 'ansible-playbook deploy-dev.yml'
}
}
stage('Deploy to Test') {
when {
branch 'release/*'
}
steps {
sh 'ansible-playbook deploy-test.yml'
}
}
stage('Deploy to Production') {
when {
branch 'master'
}
steps {
input 'Deploy to production?'
sh 'ansible-playbook deploy-prod.yml'
}
}
}
post {
always {
junit '**/target/surefire-reports/*.xml'
}
success {
echo 'Deployment successful!'
}
failure {
echo 'Deployment failed!'
mail to: 'team@example.com',
subject: "Failed Pipeline: ${currentBuild.fullDisplayName}",
body: "Something is wrong with ${env.BUILD_URL}"
}
}
}
10.2.3 무중단 배포
서비스 중단 없이 애플리케이션을 배포하는 방법입니다.
블루-그린 배포
🔵 두 개의 환경 준비
- 블루 환경: 현재 운영 중인 환경
- 그린 환경: 새로운 버전을 배포할 환경
🟢 그린 환경에 배포
- 새로운 버전을 그린 환경에 배포
- 그린 환경에서 테스트 수행
🔄 트래픽 전환
로드 밸런서 설정을 변경하여 트래픽을 그린 환경으로 전환
🔵 블루 환경 업데이트
- 블루 환경을 새로운 버전으로 업데이트
- 다음 배포를 위한 대기 환경으로 유지
카나리 배포
🐤 새 버전 일부 배포
새로운 버전을 일부 서버에만 배포
📊 트래픽 일부 전환
일부 트래픽(예: 5%)을 새 버전으로 전환
🔍 모니터링 및 검증
- 새 버전의 성능 및 안정성 모니터링
- 문제가 없으면 트래픽 비율 점진적 증가
✅ 완전 전환
모든 트래픽을 새 버전으로 전환
10.3 배포 시 확인할 설정 사항
홍익인간CMS를 배포할 때 반드시 확인해야 할 설정 사항들이 있습니다. 이러한 설정을 올바르게 구성하지 않으면 시스템이 제대로 동작하지 않을 수 있습니다.
10.3.1 context-properties.xml 설정
적용할 서버 용도에 맞는 프로필(개발-dev, 운영-prd) 내 각 설정 항목을 실 서버에 맞게 수정해야 합니다.
필수 설정(변경) 항목
GLOBAL_SITE_DOMAIN: 사이트 도메인WEB_DIR: 웹 애플리케이션 디렉토리 경로THEME_PATH: 테마 디렉토리 경로
옵션 설정 항목
DAUM_API_KEY: 다음 맵, 주소 API 옵션 사용 시NAVER_API_KEY: 네이버 맵 API 옵션 사용 시GOOGLE_API_KEY: 구글 맵 API 옵션 사용 시
<beans profile="dev">
<bean id="propertiesService" class="org.egovframe.rte.fdl.property.impl.EgovPropertyServiceImpl">
<property name="properties">
<props>
<prop key="GLOBAL_SITE_DOMAIN">http://dev.example.com</prop>
<prop key="WEB_DIR">/home/dev/humanframe</prop>
<prop key="THEME_PATH">/home/dev/humanframe/theme</prop>
</props>
</property>
</bean>
</beans>
<beans profile="prd">
<bean id="propertiesService" class="org.egovframe.rte.fdl.property.impl.EgovPropertyServiceImpl">
<property name="properties">
<props>
<prop key="GLOBAL_SITE_DOMAIN">http://www.example.com</prop>
<prop key="WEB_DIR">/home/prod/humanframe</prop>
<prop key="THEME_PATH">/home/prod/humanframe/theme</prop>
</props>
</property>
</bean>
</beans>
10.3.2 DBMS JNDI 설정
CMS 내에서 사용중인 기본 JNDI 이름은 "cmsdb"입니다. 관련 설정은 context-datasource.xml에서 확인 및 변경 가능합니다.
<Resource name="jdbc/cmsdb"
auth="Container"
type="javax.sql.DataSource"
maxTotal="100"
maxIdle="30"
maxWaitMillis="10000"
username="cmsuser"
password="cmspassword"
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/cmsdb?serverTimezone=UTC"/>
기타 WAS 서버 설정
각 서버 제품별 JNDI 설정 방법에 따라 설정을 추가해야 합니다.
10.3.3 Spring Profile 설정
WAS 서버 구동 시 Spring Profile을 적용하여 구동해야 합니다.
VM arguments 설정
-Dspring.profiles.active=prd (운영) 또는 -Dspring.profiles.active=dev (개발)
Tomcat 사용 시 설정 예시
# CMS PROFILE
JAVA_OPTS="$JAVA_OPTS -Dspring.profiles.active=prd"
10.3.4 웹에디터 설정
에디터-webeditorplus를 사용하는 경우, ImagePath.jsp 파일의 경로 설정을 확인해야 합니다.
<%
String imagePhysicalPath = "";
String activeProfiles = System.getProperty("spring.profiles.active");
if("local".equalsIgnoreCase(activeProfiles)) {
imagePhysicalPath = "D:\\H-CMS-2.2\\workspace\\humanframe";
} else if("dev".equalsIgnoreCase(activeProfiles)) {
imagePhysicalPath = "/home/dev/humanframe";
} else {
imagePhysicalPath = "/home/prod/humanframe";
}
%>
중요사항
imagePhysicalPath 변수가 실제 서버의 절대적 경로와 일치하는지 확인하고, 필요시 수정해야 합니다.
10.4 환경별 설정 관리
홍익인간CMS는 Spring 프로필을 활용하여 환경별로 다른 설정을 적용할 수 있습니다.
10.4.1 프로필 설정
<beans profile="local">
<!-- 로컬 환경 설정 -->
</beans>
<beans profile="dev">
<!-- 개발 환경 설정 -->
</beans>
<beans profile="test">
<!-- 테스트 환경 설정 -->
</beans>
<beans profile="prd">
<!-- 운영 환경 설정 -->
</beans>
프로필 활성화 방법
☕ JVM 옵션으로 활성화
-Dspring.profiles.active=dev
🌐 web.xml에서 활성화
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>dev</param-value>
</context-param>
🔧 환경 변수로 활성화
export SPRING_PROFILES_ACTIVE=dev
10.4.2 환경별 설정 파일
데이터소스 설정
<beans profile="local">
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/localdb" />
</beans>
<beans profile="dev">
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/devdb" />
</beans>
<beans profile="test">
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/testdb" />
</beans>
<beans profile="prd">
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/proddb" />
</beans>
프로퍼티 설정
<beans profile="local">
<bean id="propertiesService" class="org.egovframe.rte.fdl.property.impl.EgovPropertyServiceImpl">
<property name="properties">
<props>
<prop key="WEB_DIR">C:/dev/workspace/humanframe</prop>
<prop key="FILE_UPLOAD_DIR">/data</prop>
<prop key="LOG_PATH">/logs</prop>
</props>
</property>
</bean>
</beans>
<beans profile="prd">
<bean id="propertiesService" class="org.egovframe.rte.fdl.property.impl.EgovPropertyServiceImpl">
<property name="properties">
<props>
<prop key="WEB_DIR">/home/prod/humanframe</prop>
<prop key="FILE_UPLOAD_DIR">/data</prop>
<prop key="LOG_PATH">/logs</prop>
</props>
</property>
</bean>
</beans>
10.5 백업 및 복구
시스템 장애 발생 시 신속하게 복구할 수 있도록 백업 및 복구 전략을 수립해야 합니다.
10.5.1 데이터베이스 백업
MySQL 백업
# 전체 데이터베이스 백업
mysqldump -u username -p --all-databases > backup_$(date +%Y%m%d).sql
# 특정 데이터베이스 백업
mysqldump -u username -p humanframe > humanframe_$(date +%Y%m%d).sql
# 압축 백업
mysqldump -u username -p humanframe | gzip > humanframe_$(date +%Y%m%d).sql.gz
Oracle 백업
# exp 유틸리티 사용
exp username/password@sid file=backup_$(date +%Y%m%d).dmp full=y
# expdp 유틸리티 사용
expdp username/password@sid directory=DATA_PUMP_DIR dumpfile=backup_$(date +%Y%m%d).dmp full=y
10.5.2 파일 시스템 백업
rsync를 사용한 백업
# 전체 애플리케이션 디렉토리 백업
rsync -avz --delete /home/humanframe/app/ /backup/humanframe/app/
# 업로드 파일만 백업
rsync -avz --delete /home/humanframe/data/ /backup/humanframe/data/
tar를 사용한 백업
# 전체 애플리케이션 디렉토리 백업
tar -czf /backup/humanframe_$(date +%Y%m%d).tar.gz /home/humanframe/
# 증분 백업
tar -czf /backup/humanframe_$(date +%Y%m%d).tar.gz -g /backup/humanframe.snar /home/humanframe/
10.5.3 자동화된 백업
cron을 사용한 자동 백업
0 2 * * * root /home/humanframe/scripts/backup.sh
#!/bin/bash
# 변수 설정
DATE=$(date +%Y%m%d)
BACKUP_DIR=/backup/humanframe
DB_USER=username
DB_PASS=password
DB_NAME=humanframe
APP_DIR=/home/humanframe
# 디렉토리 생성
mkdir -p $BACKUP_DIR/$DATE
# 데이터베이스 백업
mysqldump -u $DB_USER -p$DB_PASS $DB_NAME | gzip > $BACKUP_DIR/$DATE/db_$DATE.sql.gz
# 파일 시스템 백업
tar -czf $BACKUP_DIR/$DATE/app_$DATE.tar.gz $APP_DIR/app
tar -czf $BACKUP_DIR/$DATE/data_$DATE.tar.gz $APP_DIR/data
# 오래된 백업 삭제 (30일 이상)
find $BACKUP_DIR -type d -mtime +30 -exec rm -rf {} \;
# 로그 기록
echo "Backup completed at $(date)" >> $BACKUP_DIR/backup.log
10.5.4 복구 절차
데이터베이스 복구
# MySQL 복구
mysql -u username -p humanframe < backup_20240101.sql
# 압축 파일에서 복구
gunzip -c backup_20240101.sql.gz | mysql -u username -p humanframe
파일 시스템 복구
# tar 파일에서 복구
tar -xzf /backup/humanframe_20240101.tar.gz -C /
# rsync를 사용한 복구
rsync -avz /backup/humanframe/app/ /home/humanframe/app/
10.6 모니터링 및 유지보수
시스템의 안정적인 운영을 위해 모니터링 및 유지보수 방안을 수립해야 합니다.
10.6.1 시스템 모니터링
모니터링 대상
🖥️ 서버 자원
- CPU 사용률
- 메모리 사용률
- 디스크 사용률
- 네트워크 트래픽
🌐 애플리케이션
- 응답 시간
- 오류 발생 횟수
- 동시 접속자 수
- 트랜잭션 처리량
🗄️ 데이터베이스
- 쿼리 실행 시간
- 연결 수
- 테이블 크기
- 인덱스 사용 현황
모니터링 도구
추천 모니터링 도구
- Prometheus + Grafana: 메트릭 수집 및 시각화, 알림 설정
- ELK 스택: 로그 수집 및 분석, 이상 징후 탐지
- Pinpoint/Scouter: 애플리케이션 성능 모니터링, 트랜잭션 추적
10.6.2 로그 관리
로그 수집 및 분석
📥 로그 수집
- Filebeat, Fluentd 등을 사용하여 로그 수집
- 중앙 로그 서버로 전송
💾 로그 저장
- Elasticsearch에 로그 저장
- 로그 보관 기간 설정
📊 로그 분석
- Kibana를 사용하여 로그 시각화 및 분석
- 로그 패턴 분석을 통한 이상 징후 탐지
로그 로테이션
/home/humanframe/logs/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 0640 tomcat tomcat
sharedscripts
postrotate
/bin/kill -USR1 $(cat /home/humanframe/tomcat/logs/catalina.pid 2>/dev/null) 2>/dev/null || true
endscript
}
10.6.3 정기 유지보수
유지보수 항목
🔄 패치 및 업데이트
- 보안 패치 적용
- 라이브러리 업데이트
- 기능 개선
⚡ 성능 최적화
- 데이터베이스 인덱스 최적화
- 쿼리 튜닝
- 캐시 설정 조정
🧹 데이터 정리
- 불필요한 데이터 삭제
- 로그 파일 정리
- 임시 파일 정리
🔒 보안 점검
- 취약점 스캔
- 접근 권한 검토
- 보안 설정 검토
유지보수 일정
| 주기 | 점검 항목 |
|---|---|
| 일일 점검 | 시스템 상태 확인, 오류 로그 확인, 백업 완료 여부 확인 |
| 주간 점검 | 성능 지표 분석, 디스크 공간 확인, 보안 로그 검토 |
| 월간 점검 | 데이터베이스 최적화, 불필요한 데이터 정리, 보안 패치 적용 |
| 분기별 점검 | 전체 시스템 점검, 성능 테스트, 재해 복구 테스트 |
배포 및 운영 핵심 포인트
- 체계적인 배포 프로세스: 개발 → 테스트 → 운영 단계별 검증
- 환경별 설정 관리: Spring Profile을 활용한 환경별 설정 분리
- 자동화된 백업: 정기적인 데이터베이스 및 파일 시스템 백업
- 지속적인 모니터링: 시스템 상태 및 성능 지표 모니터링
- 정기 유지보수: 보안 패치, 성능 최적화, 데이터 정리