Java에서 Optional이라는 기능이 존재합니다.

그런데 제대로, 문제없이, 읽기 좋은 소스로 작성하려면 생각보다 조금 신경 써야할 부분들이 있습니다.

 - 실제 프로덕트 코드에서 개발자들이 실수하는 경우를 많이 봤음 << 중요, 실수가 잦다면 코드 퀄리티를 관리해야하는 관리자 입장에서는 프로젝트 컨벤션으로 사용 금지로 해야할 수도 있음

 

그리고 개인적으로는 fast-fail형태가 맞다고 생각하기에 파라미터 검사(데이터 검사)를 앞쪽에서 잘 해야한다고 생각합니다. 

이후 코드는 최대한 읽기 좋게 작성하고, 성능을 생각하면 불필요하게 컴퓨팅 파워를 쓰는 코드 자체를 없애는게 맞다고 생각합니다.(임베디드 개발했던 경험을 떠올려봐도.... 컴퓨터에게 불필요한 일 자체를 시키면 안됨)

 

 

검색해서 메모 목적으로 몇가지 참고 내용을 작성해둡니다.


Java Optional의 API Note를 보면 Optional을 개발한 Brian Goetz도 의도한 형태로 사용하지 않는 경우가 많아서인지 Note까지 작성해뒀습니다.(사실 언어 설계자가 의도한데로만 사용하도록 개발/설계해뒀으면 하는 아쉬움이..)

 

1. Java Optional API Note

2. 기타 참고 링크들

아직 Jsp를 쓰는 프로젝트에서 Maven multi module 프로젝트를 셋팅했는데, JSP를 못 찾는 문제가 발생했습니다.

IntelliJ Working directory에 $MODULE_WORKING_DIR$ 를 셋팅해주면 문제가 해결됩니다.
- 참고 링크

샘플

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.util.Locale;

/**
 * 월 달력 생성기
 *
 * @author
 */
public class Test {

	public static void main(String[] args) {

		final int addMonth = 2; //2개월 후 데이터 생성

		DateTimeFormatter fmtMonth = DateTimeFormat.forPattern("yyyyMM");
		DateTimeFormatter fmtDay = DateTimeFormat.forPattern("yyyyMMdd");

		//대상 월
		DateTime now = DateTime.now();
		String strTargetMonth = now.plus(Period.months(addMonth)).toString(fmtMonth);

		DateTime dt = DateTime.parse(strTargetMonth, fmtMonth);

		int startDay = dt.dayOfMonth().getMinimumValue();
		int endDay = dt.dayOfMonth().getMaximumValue();

		String strDay;
		String dayOfWeek;
		//boolean isHoliDay = false;
		for (int i = startDay; i <= endDay; i++) {
			strDay = strTargetMonth + StringUtils.leftPad(Integer.toString(i), 2, "0");
			dayOfWeek = DateTime.parse(strDay, fmtDay).dayOfWeek().getAsShortText(Locale.KOREA);

			System.out.println(String.format("%s | %s", strDay, dayOfWeek));

		}

	}
}

Spring에서 예외 핸들링 중 특정 예외에서 어떤 경우에는 json으로 응답하고 어떤 경우에는 유저에게 에러 페이지를 보여줘야하는 경우가 존재합니다.

이런 경우 간단히 처리하는 예제 소스입니다.(더 좋은 방법이 있을 수 있지만 고민이 필요)

 

 

/**
	 * 최상위 예외(Exception) 처리
	 * - 에러로그를 남겨서 담당자에게 이메일 발송(logback에 설정 됨)하여 알 수 있도록 하기 위함
	 * - 유저에게 에러 페이지를 보여주기 위해서 ModelAndViewDefiningException를 사용(DispatcherServlet에서 view 처리됨)
	 *
	 * @param ex
	 * @return
	 */
	@ExceptionHandler(Exception.class)
	public ResponseEntity<Object> RootException(Exception ex) throws ModelAndViewDefiningException {

		errorLog("RootException", ex);
		log.debug("exception class ===> {}", ex.getClass().getSimpleName());

		if (CommonUtil.isAjaxReq(HttpRequestUtil.getCurrentRequest())) { //ajax라면 json으로 응답
			RtnVO rtnVO = new RtnVO();
			rtnVO.setErrorCd(ErrorCd.SYSTEM_ERROR.name());
			rtnVO.setMsg("서버 에러가 발생했습니다. 담당자에게 문의하세요");
			return new ResponseEntity<>(rtnVO, ErrorCd.SYSTEM_ERROR.getStatus());
		}

		ModelAndView mav = new ModelAndView();
		mav.setViewName("forward:/error/serverError"); //ajax 요청이 아니라면 유저에게 에러메시지 페이지를 보여줌(/error/serverError는 에러 페이지 랜더링용 공용 URL) 
		throw new ModelAndViewDefiningException(mav);
	}

참고로 DispatcherServlet.java에서 ModelAndViewDefiningException 처리가 되어있다.

 

Java의 java.time.LocalDateTime관련 자주 사용하는 몇 가지를 메모 목적으로 정리합니다.

  • 예전 java 1.7까지는 joda를 많이 사용했고, Java기본 패키지에 포함된 이후에도 바쁘면 joda를 사용했습니다.
  • 가능하면 java 기본 패키지를 사용하는게 좋습니다.
  • 계속해서 내용은 추가할 예정입니다.

 

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;

/**
 * Java의 java.time.LocalDateTime 관련 몇가지 사용 예 - 작성중
 * - joda를 많이 썻던 개발자들을 위해 샘플 작성
 *
 * @author
 */
public class LocalDateTimeSample {

	public static ZoneId pstZoneId = ZoneId.of("America/Los_Angeles"); //PST는 ZoneId가 'America/Los_Angeles' 임
	public static ZoneId pdtZoneId = ZoneId.of("GMT-07:00"); //PDT는 ZoneId가 'GMT-07:00' 임. 참고: https://savvytime.com/converter/pdt-to-kst-utc/aug-1-2021/3am

	public static DateTimeFormatter FMT_YMDHIS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

	/**
	 * Java의 java.time.LocalDateTime 관련 몇가지 샘플
	 *
	 * @param args
	 */
	public static void main(String[] args) {

		System.out.println("\n");

		final Date now = new Date();

		System.out.println(String.format("java.util.Date 타입의 현재 일시: %s\n\n", now));

		LocalDateTime ldt = LocalDateTime.ofInstant(now.toInstant(), ZoneId.systemDefault());
		System.out.println(String.format("java.util.Date를 java.time.LocalDateTime 로 변환:%s\n", ldt));

		//혹은 아래와 유사하하게 Date객체로 변환 가능
		//Instant instant = utcZonedDateTime.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime().atZone(ZoneId.of("UTC")).toInstant();
		//java.util.Date.from(instant);

		final String pattern = "yyyy-MM-dd-HH:mm";
		System.out.println(String.format("LocalDateTime을 패턴 '%s'으로 포맷팅: %s\n", pattern, ldt.format(DateTimeFormatter.ofPattern(pattern))));

		System.out.println(String.format("1일 후는: %s", ldt.plusDays(1).format(FMT_YMDHIS)));
		System.out.println(String.format("3일전은: %s", ldt.minusDays(3).format(FMT_YMDHIS)));

		String ymd = "20220501";

		DateTimeFormatter fmtYmd = DateTimeFormatter.ofPattern("yyyyMMdd");
		LocalDate dateYmd = LocalDate.parse(ymd, fmtYmd);
		System.out.println(String.format("%s 문자열을 포맷팅 후 date객체 변환 결과: %s", ymd, dateYmd));

		LocalDate toDay = LocalDate.now();
		System.out.println(String.format("오늘은 '%s' 입니다.", toDay));
		System.out.println(String.format("이번달의 1일은 '%s' 입니다.", toDay.withDayOfMonth(1)));

		System.out.println("\n");
		ZoneId defaultZoneId = ZoneId.systemDefault();
		Date firstMonthDayDT = Date.from(toDay.atStartOfDay(defaultZoneId).toInstant());
		System.out.println(String.format("이번달의 1일의 java date타입은 '%s' 입니다.", firstMonthDayDT));

		System.out.println("\n");
		System.out.println("원본 LocalDateTime: " + ldt);
		System.out.println("\t초 미만 절삭: " + ldt.truncatedTo(ChronoUnit.SECONDS));
		System.out.println("\t분 미만 절삭: " + ldt.truncatedTo(ChronoUnit.MINUTES));
		System.out.println("\t시간 미만 절삭: " + ldt.truncatedTo(ChronoUnit.HOURS));
		System.out.println("\t일 미만 절삭: " + ldt.truncatedTo(ChronoUnit.DAYS));
	}
}

 

결과

코드 실행 결과

 

1. 쿼리 부분 예

<!-- 해당 유저ID가 존재하는지 체크(존재시 1 리턴으로 boolean 체크됨) -->
<select id="isExistUser" parameterType="String" resultType="boolean">
    /* user.isExistUser */
    SELECT
    EXISTS
    (SELECT 1 FROM user WHERE user_id = #{userId} LIMIT 1) #LIMIT 1은 없어도 무방하지만 방어차원에서
</select>



2. java부분 예(DAO영역)

public boolean isExistUser(String userId) {
    return sqlSession.selectOne(NAMESPACE + "isExistUser", userId);
}

Spring valid 자주 사용하는 내용/샘플 정리

 - 필요시 복붙 목적으로 메모해둔 글인점을 감안해주세요

 

//${validatedValue}를 이용하면 검증대상 값을 가져올 수 있음
@NotBlank(message = "'authKey' cannot be null or empty")
@Size(max = 50, message = "The 'authKey' must be a maximum of {max}. But the request is [${validatedValue}].")
private String authKey;
  1. 신규 개발자 입사 또는 성능 문제 발생시 공유하는 java 코딩 방법
  2.  모두 지킬 수는 없지만 알고 있으면 좋은 내용


p.s. 생각날때 개인 의견 추가 및 링크들 추가 예정

+ Recent posts