hmk run dev
크레브 dev 본문
비즈니스 로직
1. 구글 소셜 로그인
2. 유튜버 인증(크레브 어드민에서 수락해주는 건가??)
- 유튜버 인증은 로그인 시점부터 정해짐
> 버튼 자체에 조건부 렌더링이 걸려서 인증, 비인증 사용자의 버튼 자체가 다름!
3. addCreve에서 협찬 등록
4. creve에서 협찬 요청 > /applyproduct/apply/sendmail/creator Controller에서 리마인드 메시지 발송 (sendKakaoAsync)
- pc, mobile UserAgent를 구분해서 view를 보여주는 것 같음.
> 계속 유지할 프로젝트라면 반응형으로 구현이 시급한 것 같습니다..!
- 파일 구조
java : controller, service 역할적 구분이 아닌 페이지 기반으로 분리해
contoller, service, dto, dao 등 필요한 파일을 모아놓음
front : 자바 파일과 마찬가지
tiles : tiles-default에 구조가 잡혀 있다. tilesBase는 pc > layout > layout.js로 되어있다. (추후 글로벌 함수 글로벌 css 같은 것들을 넣어놓고 개별로 쓰인 코드 리팩터링)
DB table( 테이블명 중 'tb_' 생략 )
content - 메인 페이지 콘텐츠 테이블
user - 회원들 정보 저장
comment - 댓글 저장, TYPE으로 어디에 등록한 댓글인지 구분하는 것 같음
협찬요청 협찬 요청 시
tp_product - 협찬 물품 목록
- PRODUCT_STATE : 9(검수 중), 11(모집 중)
- TOTAL_CNT : 아마 모집 최대 인원? 인 것 같다
- CURRENT_CNT : TOTAL_CNT 보다 작아야 협찬 리스트 목록에 뜬다.
> 협찬 요청 시 CNT++
- APPLY_DATE_ST : 모집 시작 날짜
- APPLY_DATE_END : 모집 마감 날짜
tb_apply_product - 협찬 요청 시 해당 물품 정보와 신청한 요청한 유저의 정보가 들어감( tp_product, many to one )
- cancel_YN : 협찬 취소 가능
- APPLY_STATE :
- RESULT_STATE : 협찬 결과 상태 값인 듯?? 어드민에서 처리하는 건가?
tb_click_all - 액션 로그(모든 유저의 움직임 저장)
tb_product_basket - 목록
- 클릭 시 INSERT
- 재 클릭 시 DEL_YN = 'N'으로 수정
tb_order - 결제주문
개인적으로 생각하는 개선사항
일단 제한된 시간 안에 빠르게 서비스를 배포하고 프로젝트를 마감해주신 분께 존중의 박수를 보내드립니다 :)
남이 작성한 코드는 비판하기 쉽고 저 또한 아직 미천한 실력이지만 며칠 동안 훑어보면서 크레브에 프로젝트에 대한 개선사항을 적어 봤습니다.
주석 꼼꼼히 - DTO 등에 포함 이유 새로운 분이 봐도 이해할 수 있게(작성자 작성 or 추가 날짜 기재 포함)
슬라이더나 세부 콘텐츠가 바뀌는 경우 or 카테고리 선택을 할 뿐인데 페이지가 다시 로드되고 스크롤 또한 맨 위로 이동
> 유저 경험과 리소스 모두 낭비
> 제이쿼리나 순수 자바스크립트를 이용한 empty(), append()를 활용해 페이지 수정 추천
Constants.java 파일을 만들고 키 or 코드들 모아서 관리(secretKey 등은 properties 파일에)
ex) s3키, 주요 상태 코드(결제상태 같은), oauth키 등등.......
아래와 같은 Constants.java 파일로 코드 관리
package com.workerman.config;
public class Constants {
/****************** BEGIN profile ******************************************************************/
public static final String SPRING_PROFILE_DEVELOPMENT = "dev";
public static final String SPRING_PROFILE_STAGE = "stage";
public static final String SPRING_PROFILE_LOCAL = "local";
public static final String SPRING_PROFILE_PRODUCTION = "prod";
/****************** END profile ******************************************************************/
/****************** BEGIN AWS ******************************************************************/
public static final long ACCESS_TOKEN_VALIDITY_SECONDS = 300*60*60;
public static final String HEADER_STRING = "Authorization";
public static final String TOKEN_PREFIX = "Bearer ";
public static final String ERROR_EMPTY_KEY = "조회를 위한 key값이 누락 됐습니다.";
/* S3 CONSTANTS */
// TODO : 명칭 정리 필요함. properties 처리...
public final static String WORK_UPLOAD_BUCKET_NAME = "upload-key";
public final static String WORK_ACCESSKEY = "access_key";
public final static String WORK_SECRETKEY = "secret-key";
/****************** BEGIN END ******************************************************************/
/****************** Begin Image Type ******************************************************************/
public final static String IMG_TYPE_SAMPLE = "SAMPLE"; // sample
public final static String IMG_TYPE_CUSTOMER = "CUSTOMER"; // 고객사업자등록증사본
//public final static String IMG_TYPE_CUSTOMER_BRANCH = "CUSTOMER_BRANCH"; // 고객지점사업자등록증사본
public final static String IMG_TYPE_PARTNER_BUSS = "IMG_TYPE_PARTNER_BUSS"; // 사업자번호 사본
public final static String IMG_TYPE_PARTNER_ACCT = "PARTNER_ACCT"; // 파트너 통장사본
public final static String IMG_TYPE_CUSTOMER_BUSS = "IMG_TYPE_CUSTOMER_BUSS"; // 사업자번호 사본
public final static String IMG_TYPE_CUSTOMER_BRANCH_BUSS = "IMG_TYPE_CUSTOMER_BRANCH_BUSS"; // 사업자번호 사본
public final static String IMG_TYPE_CUSTOMER_BRANCH_ACCT = "IMG_TYPE_CUSTOMER_BRANCH_ACCT"; // 통장 사본
public final static String IMG_TYPE_VENDOR_BUSS = "IMG_TYPE_VENDOR_BUSS"; // 거래처 사업자등록증사본
public final static String IMG_TYPE_VENDOR_ACCT = "IMG_TYPE_VENDOR_ACCT"; // 거래처 통장사본
public final static String IMG_TYPE_MATERIAL = "IMG_TYPE_MATERIAL"; // 자재 이미지
public final static String IMG_TYPE_MATERIAL_REQ = "IMG_TYPE_MATERIAL_REQ"; // 자재 요청 이미지
public final static String IMG_TYPE_DISBURSEMENT = "IMG_TYPE_DISBURSEMENT"; // 지출결의 영수증 이미지
public final static String IMG_TYPE_EXPENSES = "IMG_TYPE_EXPENSES"; // 비용처리 증빙 이미지
public final static String IMG_TYPE_PAYMENT = "IMG_TYPE_PAYMENT"; // 매출관리 증빙 이미지
public final static String IMG_TYPE_MATERIAL_PCS = "IMG_TYPE_MATERIAL_PCS"; //구매거래명세서 이미지
public final static String IMG_TYPE_DAILY_REPORT = "IMG_TYPE_DAILY_REPORT"; // 작업일지 이미지
public final static String IMG_TYPE_WORK_REG = "IMG_TYPE_WORK_REG"; // 작업등록 이미지
public final static String IMG_TYPE_ADMIN = "IMG_TYPE_ADMIN"; // 어드민프로필 이미지
public final static String IMG_TYPE_INSPECTION_FLOOR = "IMG_TYPE_INSPECTION_FLOOR"; // 점검 도면 이미지
/****************** End Image Type ******************************************************************/
/****************** BEGIN 이벤트 처리 메시지 ******************************************************************/
public static final String EVENT_DELETE_SUCCESS = "삭제 됐습니다.";
public static final String EVENT_SAVE_SUCCESS = "저장되었습니다.";
public static final String EVENT_UPDATE_SUCCESS = "수정 됐습니다.";
public static final String EVENT_SELECT_SUCCESS = "조회 됐습니다.";
/****************** END 이벤트 처리 메시지 ******************************************************************/
/****************** BEGIN return code ******************************************************************/
public static final String RETURN_SUCCESS = "00";
public static final String RETURN_DUPLICATE = "98";
public static final String RETURN_ERROR = "99";
/****************** END return code ******************************************************************/
/****************** BEGIN init code vlaue ******************************************************************/
public static final String STATE_NORMAL = "00";
public static final String DELETED = "Y";
public static final String NOT_DELETED = "N";
/****************** END init code vlaue ******************************************************************/
/****************** BEGIN req stat : 자재요청상태 ******************************************************************/
public static final String REQ_STAT_REG = "01"; // 등록
public static final String REQ_STAT_PCS = "02"; // 구매
public static final String REQ_STAT_OUT = "03"; // 출고
public static final String REQ_STAT_READY = "04"; // 중비오나료
/****************** END req stat ******************************************************************/
/****************** BEGIN pcs stat : 구매요청상태 ******************************************************************/
public static final String PCS_STAT_INPUT = "01"; // 등록
public static final String PCS_STAT_REQ_PAY = "02"; // 결제요청
public static final String PCS_STAT_REQ_COMP = "03"; // 결제완료
public static final String PCS_STAT_INCOME = "04"; // 입고
/****************** END pcs stat ******************************************************************/
/****************** BEGIN 입출고타입 code ******************************************************************/
public static final String BOUND_TYPE_IN = "01";
public static final String BOUND_TYPE_OUT = "02";
/****************** END 입출고타입 code ******************************************************************/
/****************** BEGIN 결제범위 code ******************************************************************/
public static final String PAY_SCOPE_ALL = "01";
public static final String PAY_SCOPE_PART = "02";
/****************** END 입출고타입 code ******************************************************************/
/****************** BEGIN 파트너 구분 text ******************************************************************/
public static final String PARTNER_TYPE_01 = "01";// 개인
public static final String PARTNER_TYPE_02 = "02";// 법인
public static final String PARTNER_TYPE_03 = "03";// 개인사업자
public static final String PARTNER_TYPE_99 = "99";// 기타
/****************** END 작업상태 text ******************************************************************/
}
tiles에 메인 템플릿을 지정해 자주 쓰이는 글로벌 함수 등을 모듈화 해놓기(tiles-default)
> 아래처럼 자주 쓰이는 날짜 포맷, 금액 포맷, ajax요청, 파일 업로드 요청 등의 함수들을 모듈화 해서 사용
/* common utils script */
var Utils = {
// is not empty
isNotEmpty: function (param) {
if (typeof param === "object") {
if (param == undefined || param == "" || param == null || param.length == 0) {
return false;
}
else {
return true;
}
}
else {
if (param == undefined || param == "" || param == null) {
return false;
}
else {
return true;
}
}
},
// is empty
isEmpty: function (param) {
if (param == undefined || param == null) {
return true;
}
if (typeof param === "object") {
if (param == undefined || param == "" || param == null || param.length == 0) {
return true;
}
else {
return false;
}
}
else {
if (param == undefined || param == "" || param == null) {
return true;
}
else {
return false;
}
}
},
// get param
getParamByName: function (name, uri) {
uri = uri || window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), results = regex.exec(uri);
if (!results) return null;
if (!results[2]) return "";
return decodeURIComponent(results[2].replace(/\+/g, " "));
},
// replace all
replace: function (str, trg, chg) {
if (str == 'undefined' || str == undefined || str == null) return '';
str = str + "";
return str.split(trg).join(chg);
},
// remove all
remove: function (str, trg) {
if (str == 'undefined' || str == undefined || str == null) return '';
str = str + "";
return str.split(trg).join('');
},
// remove comma
rmComma: function (str) {
if (str == 'undefined' || str == undefined || str == null) return '';
str = str + "";
return str.split(',').join('');
},
// round
round: function (num, st) {
if (Utils.isEmpty(st)) return num;
let e1 = "e+0";
let e2 = "e-0";
if (!Utils.isEmpty(st)) {
e1 = "e+" + st;
e2 = "e-" + st;
}
return +(Math.round(num + e1) + e2);
},
// call ajax
requestAjax: function (desc, url, param, callback, asyncYn) {
var that = this, url;
var returnData; // only async false return value
console.log("★★★★★★★★★★★★★★★★★★ call ajax ★★★★★★★★★★★★★★★★★★");
console.log("★ desc :", desc);
console.log("★ url :", url);
console.log("★ param :", param);
console.log("★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★");
$.ajax({
type: "POST",
//dataType: "json",
data: JSON.stringify(param),
contentType: "application/json",
async: asyncYn == undefined || asyncYn == null ? true : asyncYn,
timeout: 3 * 60 * 1000,
url: url,
//xhrFields:{withCredentials: true},
beforeSend: function (xhr) {
$("#content-loader-id").show();
xhr.setRequestHeader("Authorization", getAuthToken());
callback && callback.beforeSend && callback.beforeSend();
},
success: function (response) {
//console.log("suc!!", response);
//console.log(JSON.stringify(response))
returnData = response;
//console.log("request success", returnData['CATEGORY'].length);
//if(response.ResponseCode && response.ResponseCode.code == 104){}
callback && callback.success && callback.success(response);
},
error: function (request, status, error) {
$("#content-loader-id").hide();
console.log("error", JSON.stringify(error));
console.log("error", request.status);
console.log("error", request.responseText);
//callback && callback.error && callback.error();
alert(desc + ' 실행중에 에러가 발생했습니다.\n관리자에게 문의하세요.');
},
complete: function (response) {
$("#content-loader-id").hide();
callback && callback.complete && callback.complete();
}
});
return returnData;
},
// call multipart ajax
requestMultiAjax: function (desc, url, formname, callback) {
var that = this, url;
var returnData; // only async false return value
console.log("★★★★★★★★★★★★★★★★★★ call ajax ★★★★★★★★★★★★★★★★★★");
console.log("★ desc :", desc);
console.log("★ url :", url);
console.log("★ form name :", formname);
console.log("★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★");
var frm = $('#' + formname)[0];
var data = new FormData(frm);
$.when(
$.ajax({
type: "POST",
enctype: 'multipart/form-data',
url: url,
data: data,
processData: false,
contentType: false,
cache: false,
timeout: 3 * 60 * 1000,
beforeSend: function (xhr) {
$("#content-loader-id").show();
xhr.setRequestHeader("Authorization", getAuthToken());
//xhr.setRequestHeader("req_type", "ajax");
},
success: function (response) {
$("#content-loader-id").hide();
// alert('success')
callback && callback.success && callback.success(response);
},
error: function (e) {
$("#content-loader-id").hide();
// alert('fail');
}
})
).then(function (data, textStatus, jqXHR) {
//alert( jqXHR.status ); // Alerts 200
return 'success';
}).fail(function (result, status, responseobj) {
//alert('falield');
return 'fail';
});
;
},
// call multipart ajax
AdminrequestMultiAjax: function (desc, url, formname, callback) {
var that = this, url;
var returnData; // only async false return value
console.log("★★★★★★★★★★★★★★★★★★ call ajax ★★★★★★★★★★★★★★★★★★");
console.log("★ desc :", desc);
console.log("★ url :", url);
console.log("★ form name :", formname);
console.log("★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★");
var frm = $('#' + formname)[0];
var data = new FormData(frm);
$.when(
$.ajax({
type: "POST",
enctype: 'multipart/form-data',
url: url,
data: data,
processData: false,
contentType: false,
cache: false,
timeout: 3 * 60 * 1000,
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", getAuthToken());
//xhr.setRequestHeader("req_type", "ajax");
},
success: function (response) {
// alert('success')
callback && callback.success && callback.success(response);
},
error: function (e) {
alert('중복된 아이디 입니다.');
}
})
).then(function (data, textStatus, jqXHR) {
//alert( jqXHR.status ); // Alerts 200
return 'success';
}).fail(function (result, status, responseobj) {
alert('중복된 아이디 입니다.');
return 'fail';
});
;
},
// get today
getToday: function (delimeter) {
var changeDate = new Date();
var y = changeDate.getFullYear();
var m = changeDate.getMonth() + 1;
var d = changeDate.getDate();
if (m < 10) { m = "0" + m; }
if (d < 10) { d = "0" + d; }
var gubunja = delimeter || "";
var resultDate = y + gubunja + m + gubunja + d;
return resultDate;
},
// gen comma
comma: function (num) {
num = Utils.remove(num, ',');
if (isNaN(num)) return "0";
return new Intl.NumberFormat().format(num);
},
// buss no
bussNo: function (val) {
if (val == undefined || val.length != 10) return val;
else {
return val.substr(0, 3) + "-" + val.substr(3, 2) + "-" + val.substr(5, 5);
}
},
// phone number
phone: function (val) {
if (val == undefined || val.length != 11) {
return val;
} else {
return val.substr(0, 3) + "-" + val.substr(3, 4) + "-" + val.substr(7, 4);
}
},
// json string true/false
isJsonString: function (str) {
try {
var json = JSON.parse(str);
return (typeof json === 'object');
} catch (e) {
return false;
}
},
// nvl
nvl: function (str, replace) {
try {
if (Utils.isEmpty(str)) {
if (Utils.isEmpty(replace)) {
return '';
}
else {
return replace;
}
} else {
return str;
}
} catch (e) {
return str;
}
},
// link button create
linkButton: function (str) {
try {
if (Utils.isEmpty(str)) {
return '';
}
else if (str.indexOf("http://") > -1) {
let _link = str;
let tmp = '<button onclick="window.open(\'' + str + '\',\'window_name\',\'height=500,location=no,status=no,scrollbars=yes\');">button</button>';
console.log("link", tmp);
return tmp;
}
else {
return str;
}
} catch (e) {
return str;
}
},
// datetime
getDatetime: function (str) {
try {
if (Utils.isEmpty(str)) return '';
let date = new Date(str);
let year = date.getFullYear();
let month = date.getMonth() + 1;
let dt = date.getDate();
hh = date.getHours();
mm = date.getMinutes();
if (dt < 10) { dt = '0' + dt; }
if (month < 10) { month = '0' + month; }
if (hh < 10) { hh = '0' + hh; }
if (mm < 10) { mm = '0' + mm; }
return year + "-" + month + "-" + dt + " " + hh + ":" + mm;
} catch (e) {
return str;
}
},
// date, datetime
getDate: function (str) {
try {
if (Utils.isEmpty(str)) return '';
str = Utils.remove(str, "-");
str = Utils.remove(str, ".");
if (str.length == 8) {
return str.substr(0, 4) + "-" + str.substr(4, 2) + "-" + str.substr(6, 2);
}
else if (str.length == 12) {
return str.substr(0, 4) + "-" + str.substr(4, 2) + "-" + str.substr(6, 2) + " " + str.substr(8, 2) + ":" + str.substr(10, 2)
}
else return str;
} catch (e) {
return str;
}
}, // get today
getDayOfWeek: function (str) {
let week = ['일', '월', '화', '수', '목', '금', '토'];
return week[new Date(str).getDay()];
},
getMaskingJumin: function (str) {
let _jumin = '';
if (!Utils.isEmpty(str) && str.length == 7) {
_jumin = str.substring(0, 6) + "-" + str.substring(6, 7) + "******";
} else {
_jumin = str;
}
return _jumin;
}
}
메인 카테고리 등 주요 코드들은 DB로 관리되면 좋겠습니다.
mainCategoryList.put("PRIZEMONEY", "후원금");
mainCategoryList.put("OFFLINE", "방문체험");
mainCategoryList.put("BEAUTY", "뷰티/패션");
mainCategoryList.put("FOOD", "푸드");
mainCategoryList.put("DIGITAL", "전자제품");
mainCategoryList.put("LIFE", "생활용품");
mainCategoryList.put("CULTURE", "문화생활");
mainCategoryList.put("ETC", "기타");
controller의 코드를 최소화하고 비즈니스 로직 수행은 service가 위주로 담당하게 코드를 짰으면 좋겠다는 개인적인 생각입니다..! (컨트롤러엔 되도록이면 조건에 따른 service호출, model 등등이 있길 희망! )
> service에 여러 로직이 포함될 경우 트랜잭션 처리도 가능하기 때문...!
RDBMS의 기능 JOIN을 사용하지 않고 DTO를 계속 넘겨주며 DB에 커넥션을 하는 코드가 많음 DB와 연결 횟수가 많아짐 > DB 부담이 높아짐
> 결론 : 여러 번의 DB 커넥션이 아닌 하나의 쿼리로 처리할 수 있는 경우가 많음
tb_code 같은 테이블을 생성해 자주 쓰이는 값들을 코드를 따서 관리하면 좋겠습니다.
> tb_product를 예로 들어보면 CAMPAIGN_TYPE과 CAMPAIGN_LEVEL 등의 칼럼에 데이터가 VARCHAR 형태로 들어가 있는습니다.
> 이것을 tb_code에
> code_gb(코드 구분) = 'CAMPAIGN_TYPE' / code_value(코드 값) = '01' 이런 식으로 관리해 join 해서 사용
> DB 디스크를 많이 절약 가능
DTO에 설명 주석 등이 없어 사실 상 타입제한 이외에는 기능이 없는 것 같습니다.
빠르게 개발하기 위해서 생략하셨다면 아래와 같이 CommonDao를 등록해 dto, 타입 제한없이 개발가능해 개발시간이 대폭 낮아질 것 같습니다.
/**
* 데이터베이스 연결클래스
*/
@Repository("commonDao")
public class CommonDao {
@Autowired
@Qualifier("sqlSessionTemplate")
private SqlSession sessionTemplate;
/**
* 암호화메서드
*/
public void encrypt(Object obj){
if(obj instanceof EncryptionInterface){
((EncryptionInterface)obj).encrypt();
}
}
/**
* 암호화메서드
*/
public void encrypt(Object obj, boolean isEncrypt){
if(isEncrypt && obj instanceof EncryptionInterface){
((EncryptionInterface)obj).encrypt();
}
}
/**
* 복호화메서드
*/
public void decrypt(Object obj){
if(obj instanceof EncryptionInterface){
((EncryptionInterface)obj).decrypt();
}
}
/**
* 복호화메서드
*/
public void decryptList(List<?> objectList){
for (Object object : objectList) {
decrypt(object);
}
}
/**
* 쿼리조회 - 오브젝트리턴
*/
// public Object queryForObject(String qureyId){
//
// Object object = sessionTemplate.selectOne(qureyId);
//
// decrypt(object);
//
// return object;
// }
@SuppressWarnings("unchecked")
public Map<String, Object> queryForObject(String qureyId){
Object object = sessionTemplate.selectOne(qureyId);
decrypt(object);
return (Map<String, Object>)object;
}
public Object queryForObjectNoCast(String qureyId, Object obj){
Object object = sessionTemplate.selectOne(qureyId, obj);
decrypt(object);
return object;
}
/**
* 쿼리조회 - 오브젝트리턴
*/
// public Object queryForObject(String qureyId, Object obj){
//
// encrypt(obj);
//
// Object object = sessionTemplate.selectOne(qureyId, obj);
//
// decrypt(object);
//
// return object;
// }
@SuppressWarnings("unchecked")
public Map<String, Object> queryForObject(String qureyId, Object obj){
encrypt(obj);
Object object = sessionTemplate.selectOne(qureyId, obj);
decrypt(object);
return (Map<String, Object>)object;
}
public String queryForString(String qureyId, Object obj){
encrypt(obj);
Object object = sessionTemplate.selectOne(qureyId, obj);
decrypt(object);
return (String)object;
}
public int queryForInt(String qureyId, Object obj){
encrypt(obj);
Object object = sessionTemplate.selectOne(qureyId, obj);
decrypt(object);
return (int)object;
}
public float queryForFloat(String qureyId, Object obj){
encrypt(obj);
Object object = sessionTemplate.selectOne(qureyId, obj);
decrypt(object);
return (float)object;
}
/**
*
* 쿼리조회 - 리스트 오브젝트리턴
*/
@SuppressWarnings("rawtypes")
public List queryForList(String qureyId, Object obj){
encrypt(obj);
List<?> objectList = sessionTemplate.selectList(qureyId, obj);
decryptList(objectList);
return objectList;
}
/**
* 쿼리조회 - 리스트 오브젝트리턴
*/
@SuppressWarnings("rawtypes")
public List queryForList(String qureyId){
List<?> objectList = sessionTemplate.selectList(qureyId);
decryptList(objectList);
return objectList;
}
/**
* 암호화 - 세션템플릿 update 값 리턴
*/
public int update(String qureyId, Object obj){
encrypt(obj, true);
return sessionTemplate.update(qureyId, obj);
}
/**
* 암호화 - 세션템플릿 insert 값 리턴
*/
public int insert(String qureyId, Object obj){
encrypt(obj, true);
return sessionTemplate.insert(qureyId, obj);
}
/**
* 암호화 - 세션템플릿 delete 값 리턴
*/
public int delete(String qureyId, Object obj){
encrypt(obj, true);
return sessionTemplate.delete(qureyId, obj);
}
public int delete(String qureyId){
return sessionTemplate.delete(qureyId);
}
}
아래와 같이 dto없이 Map<String, Object>로 간단하게 사용가능
@Autowired
private CommonDao commonDao;
/**
* 구매요청 조회
* @param param
* @return
* @throws Exception
*/
public List<Map<String, Object>> listMaterialPcs(Map<String, Object> param) throws Exception{
return (List<Map<String, Object>>)commonDao.queryForList("material_pcs.listMaterialPcs", param);
}
/**
* 구매요청 조회 count
* @param param
* @return
* @throws Exception
*/
public int listMaterialPcsCnt(Map<String, Object> param) throws Exception{
return (Integer)commonDao.queryForInt("material_pcs.listMaterialPcsCnt", param);
}
/**
* 구매요청 조회 sum price
* @param param
* @return
* @throws Exception
*/
public Map<String, Object> getMaterialPcsPriceSum(Map<String, Object> param) throws Exception{
return (Map<String, Object>)commonDao.queryForObject("material_pcs.getMaterialPcsPriceSum", param);
}
local, dev, prod 환경구분 & 환경에 따른 CI/CD 구축
아래와 같이 개발환경에 따라 properties 파일을 나누고
pom.xml에 profile을 나누어 관리하면 CI/CD를 구축할때 dev, prod를 편하게 나누어 관리할 수 있습니다.
<profiles>
<profile>
<id>local</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<env>local</env>
</properties>
</profile>
<profile>
<id>dev</id>
<properties>
<env>dev</env>
<log.level>debug</log.level>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<outputDirectory>/home/ubuntu/test</outputDirectory>
<warName>${war.file.name}</warName>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>prod</id>
<properties>
<env>prod</env>
</properties>
<build>
<!-- <directory>${deploy.target.directory}</directory> -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<outputDirectory>/home/ubuntu/test</outputDirectory>
<warName>${war.file.name}</warName>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
'company' 카테고리의 다른 글
팀을 위하는 개발자란? (0) | 2024.03.30 |
---|