<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>HD</title>
    <link>https://hune.tistory.com/</link>
    <description>개발을 하면서 기억하기위해 남기는 블로그입니다.</description>
    <language>ko</language>
    <pubDate>Mon, 17 Aug 2026 23:05:40 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>hunecenter</managingEditor>
    <image>
      <title>HD</title>
      <url>https://tistory1.daumcdn.net/tistory/3033907/attach/0601d63b46f64563a6f636fd930b948f</url>
      <link>https://hune.tistory.com</link>
    </image>
    <item>
      <title>오라클 테이블 구조 복사 &amp;amp; 데이터 복사</title>
      <link>https://hune.tistory.com/82</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테이블 구조 및 데이터 복사하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;CREATE TABLE &lt;span style=&quot;color: #0593d3;&quot;&gt;신규테이블명&lt;/span&gt; AS SELECT&lt;span style=&quot;color: #0593d3;&quot;&gt; *&lt;/span&gt; FROM &lt;span style=&quot;color: #0593d3;&quot;&gt;복사할테이블명&lt;/span&gt; [WHERE]&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테이블 구조만 복사하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;CREATE TABLE &lt;span style=&quot;color: #0593d3;&quot;&gt;신규테이블명&lt;/span&gt; AS SELECT &lt;span style=&quot;color: #0593d3;&quot;&gt;*&lt;/span&gt; FROM &lt;span style=&quot;color: #0593d3;&quot;&gt;복사할테이블명&lt;/span&gt; WHERE &lt;span style=&quot;color: #0593d3;&quot;&gt;1=2&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot; data-remove=&quot;true&quot;&gt;테이블이 존재할경우, 데이터만 복사하기(구조가 같은경우)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;INSERT INTO &lt;span style=&quot;color: #0593d3;&quot;&gt;복사대상테이블명&lt;/span&gt; SELECT &lt;span style=&quot;color: #0593d3;&quot;&gt;*&lt;/span&gt; FROM &lt;span style=&quot;color: #0593d3;&quot;&gt;원본테이블명&lt;/span&gt; [WHERE]&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot; data-remove=&quot;true&quot;&gt;테이블이 존재할경우, 데이터만 복사하기(구조가 다를경우)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;INSERT INTO &lt;span style=&quot;color: #0593d3;&quot;&gt;복사대상테이블명&lt;/span&gt; &lt;span style=&quot;color: #0593d3;&quot;&gt;(COL1, COL2)&lt;/span&gt; SELECT &lt;span style=&quot;color: #0593d3;&quot;&gt;COL1, COL2&lt;/span&gt; FROM &lt;span style=&quot;color: #0593d3;&quot;&gt;원본테이블명&lt;/span&gt; [WHERE]&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>DB/ORACL</category>
      <author>hunecenter</author>
      <guid isPermaLink="true">https://hune.tistory.com/82</guid>
      <comments>https://hune.tistory.com/82#entry82comment</comments>
      <pubDate>Mon, 19 May 2025 11:38:08 +0900</pubDate>
    </item>
    <item>
      <title>로그인 세션 시간 표시</title>
      <link>https://hune.tistory.com/81</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;은행권이나 홈텍스 등에서 많이 볼수있는 화면이다.&amp;nbsp; 아래사진과 같이 고객의 요청으로 해당 시간을 표시되고 시간이 다되면 로그아웃이 되는 기능을 구현해보았다. (연장기능은 제외)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;726&quot; data-origin-height=&quot;110&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HFM0k/btrTu2XGNGu/H1hk4NggRpQmKfA4TKGpK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HFM0k/btrTu2XGNGu/H1hk4NggRpQmKfA4TKGpK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HFM0k/btrTu2XGNGu/H1hk4NggRpQmKfA4TKGpK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHFM0k%2FbtrTu2XGNGu%2FH1hk4NggRpQmKfA4TKGpK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;726&quot; height=&quot;110&quot; data-origin-width=&quot;726&quot; data-origin-height=&quot;110&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[작업]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가적으로 작업할 소스는 3개이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- filter Java 생성&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자가 로그인을 할때 web.xml의 session-conifg에 지정된 시간 cookie를 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- web.xml session-config(session 시간), 생성한 filter 등록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- jsp로 사용자 화면구성&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;script로 cookie를 가져와 사용자 화면에&amp;nbsp; 세션 시간표시&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;우선 servlet filter를 모르고 작업하는 사람들도 있을수 있기에 한번 읽어보고 이해하고 작업하면 좋겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;a href=&quot;https://atoz-develop.tistory.com/entry/Servlet-Filter-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://atoz-develop.tistory.com/entry/Servlet-Filter-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1670893280052&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Servlet Filter 사용하기&quot; data-og-description=&quot;Servlet Filter 사용하기 Filter의 개념과 사용하는 이유 필터는 서블릿 실행 전, 후에 어떤 작업을 하고자 할때 사용한다. 예를 들어 클라이언트가 보낸 데이터의 암호를 해제한다거나, 서블릿이 실&quot; data-og-host=&quot;atoz-develop.tistory.com&quot; data-og-source-url=&quot;https://atoz-develop.tistory.com/entry/Servlet-Filter-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0&quot; data-og-url=&quot;https://atoz-develop.tistory.com/entry/Servlet-Filter-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/U6ras/hyQTKX50Wq/uDUDRkKZZs75yg97XIrmkk/img.png?width=800&amp;amp;height=153&amp;amp;face=0_0_800_153,https://scrap.kakaocdn.net/dn/VbKcl/hyQTM9rBuD/0hcDzLPI1DNszj3ISw8sw1/img.png?width=800&amp;amp;height=153&amp;amp;face=0_0_800_153,https://scrap.kakaocdn.net/dn/Gwt1s/hyQRT3rm5e/kTvm9EKL93CnWiGppYlR1K/img.png?width=1362&amp;amp;height=261&amp;amp;face=0_0_1362_261&quot;&gt;&lt;a href=&quot;https://atoz-develop.tistory.com/entry/Servlet-Filter-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://atoz-develop.tistory.com/entry/Servlet-Filter-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/U6ras/hyQTKX50Wq/uDUDRkKZZs75yg97XIrmkk/img.png?width=800&amp;amp;height=153&amp;amp;face=0_0_800_153,https://scrap.kakaocdn.net/dn/VbKcl/hyQTM9rBuD/0hcDzLPI1DNszj3ISw8sw1/img.png?width=800&amp;amp;height=153&amp;amp;face=0_0_800_153,https://scrap.kakaocdn.net/dn/Gwt1s/hyQRT3rm5e/kTvm9EKL93CnWiGppYlR1K/img.png?width=1362&amp;amp;height=261&amp;amp;face=0_0_1362_261');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Servlet Filter 사용하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Servlet Filter 사용하기 Filter의 개념과 사용하는 이유 필터는 서블릿 실행 전, 후에 어떤 작업을 하고자 할때 사용한다. 예를 들어 클라이언트가 보낸 데이터의 암호를 해제한다거나, 서블릿이 실&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;atoz-develop.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[JAVA]&lt;/h4&gt;
&lt;pre id=&quot;code_1670892380575&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package module.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

/**
 * 
 * @Class Name  : SessionFilter.java
 * @Description :  Session time Filter
 * @Modification Information
 *
 *    수정일              수정자         수정내용
 *    -------  -------  -------------------
 *    2022.12.13.  HD    최초생성
 *
 * @author HD
 * @since 2022.12.13.
 * @version 1.0
 * @see javax.servlet.Filter
 */

public class SessionFilter implements Filter {
	
	/** org.slf4j.Logger */
	private static final Logger LOG = LoggerFactory.getLogger( SessionFilter.class );
	
	/** org.springframework.web.context.WebApplicationContext */
	private WebApplicationContext context;
	
	/**
	 * 필터 초기화
	 * @param filterConfig javax.servlet.FilterConfig
	 * @throws ServletException javax.servlet.ServletException
	 */
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		context = WebApplicationContextUtils.getWebApplicationContext( filterConfig.getServletContext() );
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		HttpServletResponse httpResponse = (HttpServletResponse) response;
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        long serverTime = System.currentTimeMillis();
        long sessionExpireTime = serverTime + httpRequest.getSession().getMaxInactiveInterval() * 1000;
        Cookie cookie = new Cookie(&quot;egovLatestServerTime&quot;, &quot;&quot; + serverTime);
        //cookie.setSecure(true);
        cookie.setPath(&quot;/&quot;);
        httpResponse.addCookie(cookie);
        cookie = new Cookie(&quot;egovExpireSessionTime&quot;, &quot;&quot; + sessionExpireTime);
        cookie.setPath(&quot;/&quot;);
        
        httpResponse.addCookie(cookie);

        chain.doFilter(request, response);
	}
	
	/**
	 * 필터 종료 메소드
	 */
	@Override
	public void destroy() {
		/*
		 * EMPTY METHOD
		 */
	}


}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1670892446373&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; &amp;lt;!-- 2022-12-13 sessionFilter 추가 --&amp;gt;
 &amp;lt;filter&amp;gt;
 	&amp;lt;filter-name&amp;gt;SessionFilter&amp;lt;/filter-name&amp;gt;
    &amp;lt;filter-class&amp;gt;module.filter.SessionFilter&amp;lt;/filter-class&amp;gt; (패키지명+클래스파일명)
 &amp;lt;/filter&amp;gt;
 &amp;lt;filter-mapping&amp;gt;
 	&amp;lt;filter-name&amp;gt;SessionFilter&amp;lt;/filter-name&amp;gt;
    &amp;lt;url-pattern&amp;gt;*&amp;lt;/url-pattern&amp;gt;
 &amp;lt;/filter-mapping&amp;gt;
 
 &amp;lt;!--session 시간 30분 --&amp;gt;
 &amp;lt;session-config&amp;gt;
 	&amp;lt;session-timeout&amp;gt;30&amp;lt;/session-timeout&amp;gt;
 &amp;lt;/session-config&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[html &amp;amp; script]&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1670893446462&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script&amp;gt;
function getCookie(cname) {
	 	  var name = cname + &quot;=&quot;;
	 	  var decodedCookie = decodeURIComponent(document.cookie);
	 	  var ca = decodedCookie.split(';');
	 	  for(var i = 0; i &amp;lt;ca.length; i++) {
	 	    var c = ca[i];
	 	    while (c.charAt(0) == ' ') {
	 	      c = c.substring(1);
	 	    }
	 	    if (c.indexOf(name) == 0) {
	 	      return c.substring(name.length, c.length);
	 	    }
	 	  }
	 	  return &quot;&quot;;
	 	}
	  
	  	function pad(n, width) {
	  	  n = n + '';
	  	  return n.length &amp;gt;= width ? n : new Array(width - n.length + 1).join('0') + n;
	  	}
	  
		var objLeftTime;
		var objClickInfo;
		var latestTime;
		var expireTime;
		var timeInterval = 1000; // 1초 간격 호출
		var firstLocalTime = 0;
		var elapsedLocalTime = 0;
		var stateExpiredTime = false;
		var logoutUrl = &quot;로그아웃 URL&quot;;
		var timer;
	  
		function init() {
			objLeftTime = document.getElementById(&quot;leftTimeInfo&quot;);
			
			if (objLeftTime == null) {
				console.log(&quot;'leftTimeInfo' ID is not exist!&quot;);
				return;
			}
			//objClickInfo = document.getElementById(&quot;clickInfo&quot;);
			//console.log(objLeftTime.textContent);

			latestTime = getCookie(&quot;egovLatestServerTime&quot;);
			expireTime = getCookie(&quot;egovExpireSessionTime&quot;);
			//console.log(&quot;latestServerTime = &quot;+latestTime);
			//console.log(&quot;expireSessionTime = &quot;+expireTime);
			
			elapsedTime = 0;
			firstLocalTime = (new Date()).getTime();
			showRemaining();
			
			timer = setInterval(showRemaining, timeInterval); // 1초 간격 호출
		}

		function showRemaining() {
			elapsedLocalTime = (new Date()).getTime() - firstLocalTime;
			
			var timeRemaining = expireTime - latestTime - elapsedLocalTime;
			if ( timeRemaining &amp;lt; timeInterval ) {
				clearInterval(timer);
				objLeftTime.innerHTML = &quot;00:00:00&quot;;
				//objClickInfo.text = '시간만료'; //시간만료
				stateExpiredTime = true;
				alert('로그인 세션시간이 만료 되었습니다.');//로그인 세션시간이 만료 되었습니다.
				//$(&quot;#logoutForm&quot;).submit();
				// reload content main page
				$(&quot;#sessionInfo&quot;).hide();

				//parent.frames[&quot;_content&quot;].location.href = logoutUrl;
				//parent.frames[&quot;_content&quot;].location.reload();

				return;
			}
			var timeHour = Math.floor(timeRemaining/1000/60 / 60); 
			var timeMin = Math.floor((timeRemaining/1000/60) % 60);
			var timeSec = Math.floor((timeRemaining/1000) % 60);
			
			objLeftTime.innerHTML = pad(timeHour,2) +&quot;:&quot;+ pad(timeMin,2) +&quot;:&quot;+ pad(timeSec,2);
			
		}
  &amp;lt;/script&amp;gt;
  
  &amp;lt;html&amp;gt;
  	&amp;lt;!-- 시간변경되는부분 --&amp;gt;
  	&amp;lt;span id=&quot;leftTimeInfo&quot;&amp;gt;00:00:00&amp;lt;/span&amp;gt; 
   &amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[참고]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:com:v3.10:sec:login_session_management&quot;&gt;https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:com:v3.10:sec:login_session_management&lt;/a&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1670893526474&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;egovframework:com:v3.10:sec:login_session_management    [eGovFrame]&quot; data-og-description=&quot;로그인후 만료시간까지의 남은 시간을 표시한다. 세션에 객체 정보 저장, 취득, 제거의 기능을 갖으며 HttpServletRequest 객체의 HttpSession 정보를 사용하여 처리된다. 유형대상소스설명비고 Filteregovf&quot; data-og-host=&quot;www.egovframe.go.kr&quot; data-og-source-url=&quot;https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:com:v3.10:sec:login_session_management&quot; data-og-url=&quot;https://www.egovframe.go.kr/wiki/doku.php?id=egovframework%3Acom%3Av3.10%3Asec%3Alogin_session_management&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/iUZbH/hyQRRxKCNZ/W9IDT4zDpby6vvdNnfitF1/img.png?width=1008&amp;amp;height=626&amp;amp;face=0_0_1008_626,https://scrap.kakaocdn.net/dn/ymZqv/hyQRVUvNoN/4pif5rEOB13XxielEvO7Gk/img.png?width=998&amp;amp;height=614&amp;amp;face=0_0_998_614&quot;&gt;&lt;a href=&quot;https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:com:v3.10:sec:login_session_management&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:com:v3.10:sec:login_session_management&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/iUZbH/hyQRRxKCNZ/W9IDT4zDpby6vvdNnfitF1/img.png?width=1008&amp;amp;height=626&amp;amp;face=0_0_1008_626,https://scrap.kakaocdn.net/dn/ymZqv/hyQRVUvNoN/4pif5rEOB13XxielEvO7Gk/img.png?width=998&amp;amp;height=614&amp;amp;face=0_0_998_614');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;egovframework:com:v3.10:sec:login_session_management [eGovFrame]&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;로그인후 만료시간까지의 남은 시간을 표시한다. 세션에 객체 정보 저장, 취득, 제거의 기능을 갖으며 HttpServletRequest 객체의 HttpSession 정보를 사용하여 처리된다. 유형대상소스설명비고 Filteregovf&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.egovframe.go.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JAVA</category>
      <category>eGov</category>
      <category>Java</category>
      <category>Login</category>
      <category>session</category>
      <author>hunecenter</author>
      <guid isPermaLink="true">https://hune.tistory.com/81</guid>
      <comments>https://hune.tistory.com/81#entry81comment</comments>
      <pubDate>Tue, 13 Dec 2022 10:05:40 +0900</pubDate>
    </item>
    <item>
      <title>FCM(firebase) 연동</title>
      <link>https://hune.tistory.com/80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;-하이브리드 앱 프로젝트중 클라이언트쪽에서 PUSH알림 기능을 요구해 FCM연동을 처음접하게되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-PUSH알림은 사용자가 Q&amp;amp;A를 작성하고 관리자가 답변또는 그해당글을 볼때 발송된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-이번 프로젝트 하이브리드 앱에 FMC연동 프로세스는 이렇다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;[프로세스]&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 98.4887%; height: 139px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 22px;&quot;&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 22px;&quot;&gt;순서&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 22px;&quot;&gt;프로세스&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 22px;&quot;&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 22px;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 22px;&quot;&gt;사용자가 앱을 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 19px;&quot;&gt;2&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;앱실행시 백단에 만들어 놓은 api url호출 UUID, firebaseToken을 post로 값 전달&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 19px;&quot;&gt;3&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;UUID, firebaseToken를 DB에 저장&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 19px;&quot;&gt;4&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;UUID DB값을 조회해 로그인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 19px;&quot;&gt;5&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;로그인 사용자가 Q&amp;amp;A글을 작성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 19px;&quot;&gt;6&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;관리자가 답글을 달거나 해당 글을 보면 사용자한테 &lt;br /&gt;알림(PUSH) firebaseToken값을 DB로 조회 FCM API호출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;7&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;핸드폰에서 PUSH 메시지를 클릭했을때 해당앱이 켜짐&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 해당 소스 내용을 참고해서 커스텀 및 Controller를 작성하면 될거같다!&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;[model]&lt;/h3&gt;
&lt;pre id=&quot;code_1667799830484&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class FCMMessage
{
  private boolean validate_only;
  private Message message;

  public static FCMMessageBuilder builder()
  {
    return new FCMMessageBuilder(); } 
  public FCMMessage(boolean validate_only, Message message) { this.validate_only = validate_only; this.message = message; } 
  public boolean isValidate_only() { return this.validate_only; } 
  public Message getMessage() { return this.message; }


  public static class FCMMessageBuilder
  {
    private boolean validate_only;
    private FCMMessage.Message message;

    public FCMMessageBuilder validate_only(boolean validate_only)
    {
      this.validate_only = validate_only; return this; } 
    public FCMMessageBuilder message(FCMMessage.Message message) { this.message = message; return this; } 
    public FCMMessage build() { return new FCMMessage(this.validate_only, this.message); } 
    public String toString() { return &quot;FCMMessage.FCMMessageBuilder(validate_only=&quot; + this.validate_only + &quot;, message=&quot; + this.message + &quot;)&quot;; } 
  }
  public static class Message {
    private FCMMessage.Notification notification;
    private String token; // 특정 device에 알림을 보내기위해 사용

    public static MessageBuilder builder() { return new MessageBuilder(); } 
    public Message(FCMMessage.Notification notification, String token) { this.notification = notification; this.token = token; } 
    public FCMMessage.Notification getNotification() { return this.notification; } 
    public String getToken() { return this.token; }


    public static class MessageBuilder
    {
      private FCMMessage.Notification notification;
      private String token;

      public MessageBuilder notification(FCMMessage.Notification notification)
      {
        this.notification = notification; return this; } 
      public MessageBuilder token(String token) { this.token = token; return this; } 
      public FCMMessage.Message build() { return new FCMMessage.Message(this.notification, this.token); } 
      public String toString() { return &quot;FCMMessage.Message.MessageBuilder(notification=&quot; + this.notification + &quot;, token=&quot; + this.token + &quot;)&quot;; }  } 
  }
  
  /**
   * // 모든 mobile os를 아우를수 있는 Notification
   * @author JHY
   *
   */
  public static class Notification {  
	private String title;
    private String body;
    private String image;

    public static NotificationBuilder builder() { return new NotificationBuilder(); } 
    public Notification(String title, String body, String image) { this.title = title; this.body = body; this.image = image; } 
    public String getTitle() { return this.title; } 
    public String getBody() { return this.body; } 
    public String getImage() { return this.image; }


    public static class NotificationBuilder
    {
      private String title;
      private String body;
      private String image;

      public NotificationBuilder title(String title)
      {
        this.title = title; return this; } 
      public NotificationBuilder body(String body) { this.body = body; return this; } 
      public NotificationBuilder image(String image) { this.image = image; return this; } 
      public FCMMessage.Notification build() { return new FCMMessage.Notification(this.title, this.body, this.image); } 
      public String toString() { return &quot;FCMMessage.Notification.NotificationBuilder(title=&quot; + this.title + &quot;, body=&quot; + this.body + &quot;, image=&quot; + this.image + &quot;)&quot;; }

    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;[Service]&lt;/h3&gt;
&lt;pre id=&quot;code_1667799879052&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface FirebaseService {

	/** 결과_성공 */
	public static final String RESULT_SUCCESS = &quot;SUCCESS&quot;;
	
	/** 사용자 code 없음 */
	public static final String NO_USER_CODE = &quot;NO_USER_CODE&quot;;
	
	/** firebase 토큰 없음 */
	public static final String NO_FIREBASE_TOKEN= &quot;NO_FIREBASE_TOKEN&quot;;
	
	/** 결과_실패  */
	public static final String RESULT_FAIL = &quot;FAIL&quot;;
	
	//public final String MESSAGING_SCOPE = &quot;https://www.googleapis.com/auth/cloud-platform&quot;;
	public final String MESSAGING_SCOPE = &quot;https://www.googleapis.com/auth/firebase.messaging&quot;;
	public final String[] SCOPES = { MESSAGING_SCOPE };
    
    public final String PROJECT_ID = &quot;push-apps-58e3d&quot;;
	
    //https://firebase.google.com/docs/cloud-messaging/migrate-v1 참고
    public final String API_URL = &quot;https://fcm.googleapis.com/v1/projects/&quot;+PROJECT_ID+&quot;/messages:send&quot;;
	
	//토큰 취득
	public abstract String getAccessToken() throws IOException;
	
	//메시지 발송
	public abstract void sendMessageTo(String userCode, String title, String body, String link) throws IOException;
	
	// 파라미터를 FCM이 요구하는 body 형태로 만들어준다.
	public abstract String makeMessage(String targetToken, String title, String body, String link) throws JsonProcessingException;
	
	//앱 실행시 userCode, firebaseToken값 체크
	public abstract JsonObject firebaseToeknChk(MobilePwd mobilePwd);
	
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;[ServiceImpl]&lt;/h3&gt;
&lt;pre id=&quot;code_1667800181865&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service(&quot;FirebaseService&quot;)
public class FirebaseServiceImpl implements  FirebaseService{
	
	private static final Logger LOG = LoggerFactory.getLogger( FirebaseServiceImpl.class );
	
	/**
	 * 토큰 취득
	 * &amp;lt;br&amp;gt;
	 * doc : https://firebase.google.com/docs/cloud-messaging/auth-server
	 */
	@Override
	public String getAccessToken() throws IOException {
    	//doc URL 참고
		 String firebaseConfigPath = &quot;../firebase/test.json&quot;;
		
		 /*InputStream resource = new FileInputStream(firebaseConfigPath);
		 try ( BufferedReader reader = new BufferedReader(
		   new InputStreamReader(resource)) ) {
		     String readerStr = reader.lines()
		       .collect(Collectors.joining(&quot;\n&quot;));
		     System.out.println(&quot;파일 읽는지 확인 : &quot; + readerStr);
		 }*/
		 
	     GoogleCredentials googleCredentials = GoogleCredentials
	             .fromStream(new FileInputStream(firebaseConfigPath))
	             .createScoped(Arrays.asList(SCOPES));
	     googleCredentials.refresh();
	     return googleCredentials.getAccessToken().getTokenValue();
	}

	/**
	 * PUSH 메시지 발송
	 * &amp;lt;br&amp;gt;
	 * doc : https://firebase.google.com/docs/cloud-messaging/auth-server
	 */
	@Override
	public void sendMessageTo(String userCode, String title, String body, String link) throws IOException {
		if(!&quot;&quot;.equals(ReplaceNull(userCode))) {
			UserInfo userInfo = userDao.getUserInfo(userCode);//회원조회
			if(userInfo!=null) {
				if(!&quot;&quot;.equals(ReplaceNull(userInfo.getUserPin()))) {
					String message = makeMessage(userInfo.getUserPin(), title, body, link);

					OkHttpClient client = new OkHttpClient();
			        RequestBody requestBody = RequestBody.create(MediaType.parse(&quot;application/json; charset=utf-8&quot;),message);
			        Request request = new Request.Builder()
			                .url(API_URL)
			                .post(requestBody)
			                .addHeader(HttpHeaders.AUTHORIZATION, &quot;Bearer &quot; + getAccessToken())
			                .addHeader(HttpHeaders.CONTENT_TYPE, &quot;application/json; UTF-8&quot;)
			                .build();

			        Response response = client.newCall(request).execute();
			        /**
			         * success message
			         * &amp;lt;br&amp;gt;
			         * {
			  		 *	 &quot;name&quot;: &quot;projects/${projectid}/messages/0:1666597000351490%e54c69bfe54c69bf&quot;
					 * }

			         */
			        LOG.info(&quot;result message : &quot;+response.body().string());
				}
				
			}
			
		}
		
	}

	/**
	 * 메시지 생성
	 * &amp;lt;br&amp;gt;
	 * doc : https://firebase.google.com/docs/cloud-messaging/send-message#java_3
	 * &amp;lt;br&amp;gt;
	 * json 형태
	 * &amp;lt;br&amp;gt;
	 * {
	 *    &quot;message&quot;:{
	 *       &quot;token&quot;:&quot;bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...&quot;,
	 *       &quot;notification&quot;:{
	 *         &quot;body&quot;:&quot;This is an FCM notification message!&quot;,
	 *         &quot;title&quot;:&quot;FCM Message&quot;
	 *       }
	 *    }
	 * }
	 */
	@Override
	public String makeMessage(String targetToken, String title, String body, String link) throws JsonProcessingException {
		// object를 json 형태 String 으로 반환
		ObjectMapper objectMapper = new ObjectMapper();
		
		FCMMessage fcmMessage = FCMMessage.builder()
                .message(FCMMessage.Message.builder()
                        .token(targetToken)
                        .notification(FCMMessage.Notification.builder()
                                .title(title)
                                .body(body)
                                .image(null)
                                .build()
                        )
                        .build()
                )
                .validate_only(false)
                .build();
		
		LOG.info(&quot;fcmMessage json : &quot;+objectMapper.writeValueAsString(fcmMessage));
		
        return objectMapper.writeValueAsString(fcmMessage);
	}

	/**
	 * 
	 */
	@Override
	public JsonObject firebaseToeknChk(String uuid, String firebaseToken) {
		//회원 UUID, FIREBASE_TOKEN등록
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;[참고]&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://firebase.google.com/docs/cloud-messaging&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://firebase.google.com/docs/cloud-messaging&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1667800517403&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Firebase 클라우드 메시징&quot; data-og-description=&quot;Firebase 클라우드 메시징(FCM)은 비용 없이 안정적으로 메시지를 보낼 수 있는 플랫폼 간 메시징 솔루션입니다.&quot; data-og-host=&quot;firebase.google.com&quot; data-og-source-url=&quot;https://firebase.google.com/docs/cloud-messaging&quot; data-og-url=&quot;https://firebase.google.com/docs/cloud-messaging?hl=ko&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://firebase.google.com/docs/cloud-messaging&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://firebase.google.com/docs/cloud-messaging&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Firebase 클라우드 메시징&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Firebase 클라우드 메시징(FCM)은 비용 없이 안정적으로 메시지를 보낼 수 있는 플랫폼 간 메시징 솔루션입니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;firebase.google.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://sol-devlog.tistory.com/11&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://sol-devlog.tistory.com/11&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1667800529732&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[SpringBoot] FCM을 통해 Push알림 보내보기&quot; data-og-description=&quot;( + 진행 당시, 기능 구현에 집중하다보니 전체적인 설계나 코드가 클린하지 못할 수 있으니 이 부분은 리팩토링 하면서 적용하시면 좋을 것 같아요! :) ) 현재 참여하고 있는 IT연합 동아리 YAPP에&quot; data-og-host=&quot;sol-devlog.tistory.com&quot; data-og-source-url=&quot;https://sol-devlog.tistory.com/11&quot; data-og-url=&quot;https://sol-devlog.tistory.com/11&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bkFXGa/hyQveMemow/vxHLUMc1EYqnCajV1SyOg1/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/bwanq6/hyQtxzR4xY/lhjJe0gg7aXNXHKaLGWyK1/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/eBa5t/hyQtApPQr9/GO0EBsSvA5KBFX6KsIogk1/img.png?width=1280&amp;amp;height=528&amp;amp;face=0_0_1280_528&quot;&gt;&lt;a href=&quot;https://sol-devlog.tistory.com/11&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://sol-devlog.tistory.com/11&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bkFXGa/hyQveMemow/vxHLUMc1EYqnCajV1SyOg1/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/bwanq6/hyQtxzR4xY/lhjJe0gg7aXNXHKaLGWyK1/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/eBa5t/hyQtApPQr9/GO0EBsSvA5KBFX6KsIogk1/img.png?width=1280&amp;amp;height=528&amp;amp;face=0_0_1280_528');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[SpringBoot] FCM을 통해 Push알림 보내보기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;( + 진행 당시, 기능 구현에 집중하다보니 전체적인 설계나 코드가 클린하지 못할 수 있으니 이 부분은 리팩토링 하면서 적용하시면 좋을 것 같아요! :) ) 현재 참여하고 있는 IT연합 동아리 YAPP에&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;sol-devlog.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JAVA</category>
      <category>FCM</category>
      <category>Firebase</category>
      <category>Java</category>
      <category>spring</category>
      <author>hunecenter</author>
      <guid isPermaLink="true">https://hune.tistory.com/80</guid>
      <comments>https://hune.tistory.com/80#entry80comment</comments>
      <pubDate>Mon, 7 Nov 2022 14:56:25 +0900</pubDate>
    </item>
    <item>
      <title>Java @Scheduled Cron 표현식</title>
      <link>https://hune.tistory.com/79</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;매번 프로젝트 스케쥴 걸때마다 찾아다녀서 기억 할겸 기록!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cron 표현식의 각 시간단위는 아래의 범위로 구성 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;(Cron 표현식 6~7자리)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;초&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;분&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;시&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;일&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;월&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;요일&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;년도&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0 ~ 59&lt;/td&gt;
&lt;td&gt;0 ~ 59&lt;/td&gt;
&lt;td&gt;0 ~ 23&lt;/td&gt;
&lt;td&gt;1 ~ 31&lt;/td&gt;
&lt;td&gt;1 ~ 12&lt;/td&gt;
&lt;td&gt;0 ~ 6&lt;/td&gt;
&lt;td&gt;*생략가능*&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 id=&quot;Cron%--%ED%--%-C%ED%--%--%EC%-B%-D%--%ED%-A%B-%EC%--%--%EB%AC%B-%EC%-E%--&quot; data-ke-size=&quot;size23&quot;&gt;&lt;u&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;@scheduled 옵션&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 222px;&quot; border=&quot;1&quot; data-ke-style=&quot;style15&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;옵션&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;내용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 37px;&quot;&gt;
&lt;td style=&quot;height: 37px;&quot;&gt;&lt;b&gt;fixedDelay&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 37px;&quot;&gt;이전 작업이 종료된 후 설정 시간만큼 기다린 후에 시작한다. (밀리세컨드)&lt;br /&gt;&lt;b&gt;@Scheduled(&lt;b&gt;fixedDelay = 1000&lt;/b&gt;)&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 37px;&quot;&gt;
&lt;td style=&quot;height: 37px;&quot;&gt;&lt;b&gt;fixedRate&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 37px;&quot;&gt;이전 작업이 종료되지 않아도 설정된 시간마다 시작한다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;(밀리세컨드)&lt;br /&gt;&lt;b&gt;@Scheduled(&lt;b&gt;fixedRate&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;= 1000&lt;/b&gt;)&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 37px;&quot;&gt;
&lt;td style=&quot;height: 37px;&quot;&gt;&lt;b&gt;initialDelay&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 37px;&quot;&gt;작업 시작 시, 설정된 시간만큼 기다린 후 시작한다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;(밀리세컨드)&lt;br /&gt;&lt;b&gt;@Scheduled(&lt;b&gt;fixedRate&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;= 1000,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;initialDelay = 2000&lt;/b&gt;&lt;/b&gt;)&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 74px;&quot;&gt;
&lt;td style=&quot;height: 74px;&quot;&gt;&lt;b&gt;cron&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 74px;&quot;&gt;원하는 시간대를 설정하여 작업을 실행한다.&lt;b&gt;&lt;br /&gt;@Scheduled(cron = &quot;* * * * * *&quot;)&amp;nbsp;&lt;br /&gt;(초(0-59), 분(0-59), 시간(0-23), 일(1-31), 월(1-12), 요일(1-7, 1:일, 7:토))&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 37px;&quot;&gt;
&lt;td style=&quot;height: 37px;&quot;&gt;&lt;b&gt;zone&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 37px;&quot;&gt;시간대를 설정 한다. 미설정 시 로컬 시간대가 적용된다.&lt;br /&gt;&lt;b&gt;@Scheduled(cron = &quot;* * * * * *&quot;, zone = &quot;Asia/Seoul&quot;)&amp;nbsp;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 id=&quot;Cron%--%ED%--%-C%ED%--%--%EC%-B%-D%--%ED%-A%B-%EC%--%--%EB%AC%B-%EC%-E%--&quot; data-ke-size=&quot;size23&quot;&gt;&lt;u&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Cron 표현식 특수문자&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;*&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 모든 값(매시, 매일, 매주처럼 사용한다.)&lt;/li&gt;
&lt;li&gt;?&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 특정 값이 아닌 어떤 값이든 상관 없음&lt;/li&gt;
&lt;li&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 범위를 지정할 때&lt;/li&gt;
&lt;li&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 여러 값을 지정할 때&lt;/li&gt;
&lt;li&gt;/&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 증분값, 즉 초기값과 증가치를 설정할 때&lt;/li&gt;
&lt;li&gt;L&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 지정할 수 있는 범위의 마지막 값 표시&lt;/li&gt;
&lt;li&gt;W&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 가장 가까운 평일(weekday)을 설정할 때&lt;/li&gt;
&lt;li&gt;#&lt;span&gt;&amp;nbsp;&lt;/span&gt;: N번 째 특정 요일을 설정할 때&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 id=&quot;Cron%--%ED%--%-C%ED%--%--%EC%-B%-D%--%ED%-A%B-%EC%--%--%EB%AC%B-%EC%-E%--&quot; data-ke-size=&quot;size23&quot;&gt;&lt;u&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Cron 표현식 예시&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1664861740395&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//매 10분마다
@Scheduled( cron = &quot;0 0/10 * * * *&quot;)

//매 3시간마다
@Scheduled( cron = &quot;0 0 0/3 * * *&quot;)

//2018년도 매일 14시 30분마다
@Scheduled( cron = &quot;0 30 14 * * * 2018&quot;)

//매일 10시 ~ 19시 사이에 10분 간격으로
@Scheduled( cron = &quot;0 0/10 10-19 * * *&quot;)

//매일 10시와 19시에만 10분 간격으로
@Scheduled( cron = &quot;0 0/10 10,19 * * *&quot;)

//매달 25일 01시 30분에
@Scheduled( cron = &quot;0 30 1 25 * *&quot;)

//매주 월, 금요일 10시와 19시 사이 10분마다
@Scheduled( cron = &quot;0 10 10-19 ? * MON,FRI&quot;)

//매달 마지막날 15시 30분
@Scheduled( cron = &quot;0 30 15 L * *&quot;)

//2021~2022년 매월의 마지막 토요일 오후 1시 20분
@Scheduled( cron = &quot;0 20 13 ? * 6L 2021-2022&quot;)

//매 10분마다
@Scheduled( cron = &quot;0 0/10 * * * *&quot;)

//매 3시간마다
@Scheduled( cron = &quot;0 0 0/3 * * *&quot;)

//2022년도 매일 14시 30분마다
@Scheduled( cron = &quot;0 30 14 * * * 2022&quot;)

//매일 10시 ~ 19시 사이에 10분 간격으로
@Scheduled( cron = &quot;0 0/10 10-19 * * *&quot;)

//매일 10시와 19시에만 10분 간격으로
@Scheduled( cron = &quot;0 0/10 10,19 * * *&quot;)

//매달 25일 01시 30분에
@Scheduled( cron = &quot;0 30 1 25 * *&quot;)

//매주 월, 금요일 10시와 19시 사이 10분마다
@Scheduled( cron = &quot;0 10 10-19 ? * MON,FRI&quot;)

//매달 마지막날 15시 30분
@Scheduled( cron = &quot;0 30 15 L * *&quot;)

//2021~2022년 매월의 마지막 토요일 오후 1시 20분
@Scheduled( cron = &quot;0 20 13 ? * 6L 2021-2022&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 id=&quot;Cron%--%ED%--%-C%ED%--%--%EC%-B%-D%--%ED%-A%B-%EC%--%--%EB%AC%B-%EC%-E%--&quot; data-ke-size=&quot;size23&quot;&gt;&lt;u&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;JAVA 사용 예시&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1664870159246&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * @Class Name  : SchdulService.java
 * @Description :  
 * @Modification Information
 *
 *    수정일              수정자         수정내용
 *    -------  -------  -------------------
 *    2022. 10. 4.	HD    	최초생성
 *
 * @author HD
 * @since 2022. 10. 4.
 * @version 1.0
 * @see
 */
@Component
public class SchdulService {
 
	@Scheduled( cron = &quot;0 */1 * * * ?&quot; ) //1분에 한번(테스트용)
	public void startSchdulService(){
		System.out.println(&quot;1분마다 스케쥴 실행&quot;);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 id=&quot;Cron%--%ED%--%-C%ED%--%--%EC%-B%-D%--%ED%-A%B-%EC%--%--%EB%AC%B-%EC%-E%--&quot; data-ke-size=&quot;size23&quot;&gt;&lt;u&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;참고링크&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Cron#CRON_expression&quot;&gt;https://en.wikipedia.org/wiki/Cron#CRON_expression&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1664861766547&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;cron - Wikipedia&quot; data-og-description=&quot;From Wikipedia, the free encyclopedia Jump to navigation Jump to search Job scheduler for Unix-like operating systems The cron command-line utility is a job scheduler on Unix-like operating systems. Users who set up and maintain software environments use c&quot; data-og-host=&quot;en.wikipedia.org&quot; data-og-source-url=&quot;https://en.wikipedia.org/wiki/Cron#CRON_expression&quot; data-og-url=&quot;https://en.wikipedia.org/wiki/Cron#CRON_expression&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/rFwXD/hyP0EMDJjB/bhdZ3KoZzfzF5xNUY1ryn0/img.gif?width=1040&amp;amp;height=608&amp;amp;face=0_0_1040_608,https://scrap.kakaocdn.net/dn/bAINBO/hyP0x7SPXw/Tkv1iphbWx8cDVEKAVZjuK/img.gif?width=800&amp;amp;height=468&amp;amp;face=0_0_800_468,https://scrap.kakaocdn.net/dn/cnkytU/hyP0E0ah3o/BQLMlLRwrQ7KkQrk7jpy8K/img.gif?width=640&amp;amp;height=374&amp;amp;face=0_0_640_374&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Cron#CRON_expression&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://en.wikipedia.org/wiki/Cron#CRON_expression&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/rFwXD/hyP0EMDJjB/bhdZ3KoZzfzF5xNUY1ryn0/img.gif?width=1040&amp;amp;height=608&amp;amp;face=0_0_1040_608,https://scrap.kakaocdn.net/dn/bAINBO/hyP0x7SPXw/Tkv1iphbWx8cDVEKAVZjuK/img.gif?width=800&amp;amp;height=468&amp;amp;face=0_0_800_468,https://scrap.kakaocdn.net/dn/cnkytU/hyP0E0ah3o/BQLMlLRwrQ7KkQrk7jpy8K/img.gif?width=640&amp;amp;height=374&amp;amp;face=0_0_640_374');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;cron - Wikipedia&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;From Wikipedia, the free encyclopedia Jump to navigation Jump to search Job scheduler for Unix-like operating systems The cron command-line utility is a job scheduler on Unix-like operating systems. Users who set up and maintain software environments use c&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;en.wikipedia.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://sun-p.tistory.com/115&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://sun-p.tistory.com/115&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1664861826072&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;98DAY / 스프링 스케쥴러 CRON식&quot; data-og-description=&quot;스프링 스케쥴러 https://spring.io/guides/gs/scheduling-tasks/ CRON 크론 표현식 &amp;nbsp;초 &amp;nbsp; |&amp;nbsp; 분&amp;nbsp; | 시 | 일&amp;nbsp; |&amp;nbsp; 월&amp;nbsp; | 요일 |&amp;nbsp; 연도 0~59 | 0~59 | 0~23 | 1~31 | 1~12 |&amp;nbsp; 0~6 | 생략가능 요일 : 0 (일..&quot; data-og-host=&quot;sun-p.tistory.com&quot; data-og-source-url=&quot;https://sun-p.tistory.com/115&quot; data-og-url=&quot;https://sun-p.tistory.com/115&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/jNQKu/hyP0Ke2rkW/ydSUgLvd4Z8QDodlVqNKqk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/caIOHr/hyP0KMTZ14/z011CckSDtf6Dl9eJ8yI61/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://sun-p.tistory.com/115&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://sun-p.tistory.com/115&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/jNQKu/hyP0Ke2rkW/ydSUgLvd4Z8QDodlVqNKqk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/caIOHr/hyP0KMTZ14/z011CckSDtf6Dl9eJ8yI61/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;98DAY / 스프링 스케쥴러 CRON식&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;스프링 스케쥴러 https://spring.io/guides/gs/scheduling-tasks/ CRON 크론 표현식 &amp;nbsp;초 &amp;nbsp; |&amp;nbsp; 분&amp;nbsp; | 시 | 일&amp;nbsp; |&amp;nbsp; 월&amp;nbsp; | 요일 |&amp;nbsp; 연도 0~59 | 0~59 | 0~23 | 1~31 | 1~12 |&amp;nbsp; 0~6 | 생략가능 요일 : 0 (일..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;sun-p.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;http://www.cronmaker.com/;jsessionid=node0e22c4uy0l2pwjt8qafmy2wl4508784.node0?0&quot;&gt;http://www.cronmaker.com/;jsessionid=node0e22c4uy0l2pwjt8qafmy2wl4508784.node0?0&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;(cronmaker &lt;span style=&quot;background-color: #ffffff;&quot;&gt;Quartz cron방식으로 생성 테스트&lt;/span&gt;)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1664861858100&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;CronMaker&quot; data-og-description=&quot;&quot; data-og-host=&quot;www.cronmaker.com&quot; data-og-source-url=&quot;http://www.cronmaker.com/;jsessionid=node0e22c4uy0l2pwjt8qafmy2wl4508784.node0?0&quot; data-og-url=&quot;http://www.cronmaker.com/;jsessionid=node0e22c4uy0l2pwjt8qafmy2wl4508784.node0?0=&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;http://www.cronmaker.com/;jsessionid=node0e22c4uy0l2pwjt8qafmy2wl4508784.node0?0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://www.cronmaker.com/;jsessionid=node0e22c4uy0l2pwjt8qafmy2wl4508784.node0?0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;CronMaker&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.cronmaker.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>JAVA</category>
      <category>@Scheduled</category>
      <category>cron</category>
      <category>Java</category>
      <category>scheduled</category>
      <author>hunecenter</author>
      <guid isPermaLink="true">https://hune.tistory.com/79</guid>
      <comments>https://hune.tistory.com/79#entry79comment</comments>
      <pubDate>Tue, 4 Oct 2022 14:40:05 +0900</pubDate>
    </item>
    <item>
      <title>Tomcat Server.xml 암호화 (feat.AES)</title>
      <link>https://hune.tistory.com/77</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 중에 Server.xml DB Resource 부분에 url, id, password 암호화를 할수없냐는 문의가 들어와서 찾아 보고 적용을 해보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;암호화하는 역할을 하는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;DataSourceFactory&lt;/b&gt;&lt;/span&gt;를 가지고 참조해 소스를 수정 및 추가를 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업한 소스는 총2개이다 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Encryptor.java, EncryptedDataSourceFactory.java&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;u&gt;※EncryptedDataSourceFactory의 full path 기억하기&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;[&lt;b&gt;Encryptor.java&lt;/b&gt;]&lt;/h3&gt;
&lt;pre id=&quot;code_1655948067256&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package secured;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

public class Encryptor {

    private static final String ALGORITHM = &quot;AES&quot;;
	
    private static final String defaultSecretKey = &quot;SecretKeyTest&quot;;//AES secretKey

    private Key secretKeySpec;

    public Encryptor() throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException,
            UnsupportedEncodingException {
        this(null);
    }

    public Encryptor(String secretKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
            UnsupportedEncodingException {
        this.secretKeySpec = generateKey(secretKey);
    }

    public String encrypt(String plainText) throws InvalidKeyException, NoSuchAlgorithmException,
            NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
        byte[] encrypted = cipher.doFinal(plainText.getBytes(&quot;UTF-8&quot;));
        return asHexString(encrypted);
    }

    public String decrypt(String encryptedString) throws InvalidKeyException, IllegalBlockSizeException,
            BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
        byte[] original = cipher.doFinal(toByteArray(encryptedString));
        return new String(original);
    }

    private Key generateKey(String secretKey) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        if (secretKey == null) {
            secretKey = defaultSecretKey;
        }
        byte[] key = (secretKey).getBytes(&quot;UTF-8&quot;);
        MessageDigest sha = MessageDigest.getInstance(&quot;SHA-1&quot;);
        key = sha.digest(key);
        key = Arrays.copyOf(key, 16); // use only the first 128 bit

        KeyGenerator kgen = KeyGenerator.getInstance(&quot;AES&quot;);
        kgen.init(128); // 192 and 256 bits may not be available

        return new SecretKeySpec(key, ALGORITHM);
    }

    private final String asHexString(byte buf[]) {
        StringBuffer strbuf = new StringBuffer(buf.length * 2);
        int i;
        for (i = 0; i &amp;lt; buf.length; i++) {
            if (((int) buf[i] &amp;amp; 0xff) &amp;lt; 0x10) {
                strbuf.append(&quot;0&quot;);
            }
            strbuf.append(Long.toString((int) buf[i] &amp;amp; 0xff, 16));
        }
        return strbuf.toString();
    }

    private final byte[] toByteArray(String hexString) {
        int arrLength = hexString.length() &amp;gt;&amp;gt; 1;
        byte buf[] = new byte[arrLength];
        for (int ii = 0; ii &amp;lt; arrLength; ii++) {
            int index = ii &amp;lt;&amp;lt; 1;
            String l_digit = hexString.substring(index, index + 2);
            buf[ii] = (byte) Integer.parseInt(l_digit, 16);
        }
        return buf;
    }

    public static void main(String[] args) throws Exception {
    	Encryptor aes = new Encryptor(defaultSecretKey);
    	String url =&quot;jdbc:mysql://127.0.0.1:3306/testDb?characterEncoding=UTF-8&quot;;
    	System.out.println(&quot;url:&quot; + aes.encrypt(url));
    	String testid = &quot;test&quot;;
    	System.out.println(&quot;Id:&quot; + aes.encrypt(testid));
    	String testpassword = &quot;test&quot;;
    	System.out.println(&quot;Pw:&quot; + aes.encrypt(testpassword));
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[EncryptedDataSourceFactory.java]&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1655948933163&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package secured;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.util.Properties;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.naming.Context;
import javax.sql.DataSource;

import org.apache.tomcat.jdbc.pool.DataSourceFactory;
import org.apache.tomcat.jdbc.pool.PoolConfiguration;
import org.apache.tomcat.jdbc.pool.XADataSource;

public class EncryptedDataSourceFactory extends DataSourceFactory {


    private Encryptor encryptor = null;

    public EncryptedDataSourceFactory() {
        try {
            encryptor = new Encryptor(); // If you've used your own secret key, pass it in...
        } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public DataSource createDataSource(Properties properties, Context context, boolean XA) throws InvalidKeyException,
            IllegalBlockSizeException, BadPaddingException, SQLException, NoSuchAlgorithmException,
            NoSuchPaddingException {
        // Here we decrypt our password.
        PoolConfiguration poolProperties = EncryptedDataSourceFactory.parsePoolProperties(properties);
        poolProperties.setUrl(encryptor.decrypt(poolProperties.getUrl())); //dbConUrl 복호화
        poolProperties.setUsername(encryptor.decrypt(poolProperties.getUsername())); //username복호화
        poolProperties.setPassword(encryptor.decrypt(poolProperties.getPassword())); //password복호화
        /*
        setValidationQuery Option
        SELECT 1(mysql), SELECT 1 FROM DUAL(oracle), SELECT 1(mssql) 
        */
        poolProperties.setValidationQuery(&quot;SELECT 1&quot;);
        poolProperties.setTestWhileIdle(true);
        poolProperties.setTimeBetweenEvictionRunsMillis(720000);//2시간 단위로 SELECT 1 검증
        
        // The rest of the code is copied from Tomcat's DataSourceFactory.
        if (poolProperties.getDataSourceJNDI() != null &amp;amp;&amp;amp; poolProperties.getDataSource() == null) {
            performJNDILookup(context, poolProperties);
        }
        org.apache.tomcat.jdbc.pool.DataSource dataSource = XA ? new XADataSource(poolProperties)
                : new org.apache.tomcat.jdbc.pool.DataSource(poolProperties);
        dataSource.createPool();

        return dataSource;
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[Encryptor.java bulid]&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;989&quot; data-origin-height=&quot;155&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ogm1Y/btrFvrEhHy2/i6x1mcyGe3dh2w1xzVELFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ogm1Y/btrFvrEhHy2/i6x1mcyGe3dh2w1xzVELFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ogm1Y/btrFvrEhHy2/i6x1mcyGe3dh2w1xzVELFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fogm1Y%2FbtrFvrEhHy2%2Fi6x1mcyGe3dh2w1xzVELFK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;989&quot; height=&quot;155&quot; data-origin-width=&quot;989&quot; data-origin-height=&quot;155&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;server.xml에 암호화한 값들을 넣어주기위해 Encryptor.java를 먼저 컴파일해서 값을 확인해본다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[jar 추출]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(순서) - Export -&amp;gt; java에 JAR file -&amp;gt; JAR file에 경로와 jar파일명 설정후 Finish (하단 이미지 참조)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageslideblock alignCenter&quot; data-image=&quot;[{&amp;quot;src&amp;quot;:&amp;quot;https://blog.kakaocdn.net/dn/bs32c3/btrFwSHz86z/Jo6IMX4WM73vCeknQKBZok/img.png&amp;quot;},{&amp;quot;src&amp;quot;:&amp;quot;https://blog.kakaocdn.net/dn/c82VCJ/btrFuUfCvM3/dspnhjylZuO5aTyzOy95v1/img.png&amp;quot;},{&amp;quot;src&amp;quot;:&amp;quot;https://blog.kakaocdn.net/dn/b8ZTdW/btrFyKCxXfA/9Vj4XIg6LZzasju5vPGOk1/img.png&amp;quot;}]&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span class=&quot;image-wrap selected&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bs32c3/btrFwSHz86z/Jo6IMX4WM73vCeknQKBZok/img.png&quot; data-url=&quot;https://blog.kakaocdn.net/dn/bs32c3/btrFwSHz86z/Jo6IMX4WM73vCeknQKBZok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bs32c3/btrFwSHz86z/Jo6IMX4WM73vCeknQKBZok/img.png&quot; loading=&quot;lazy&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbs32c3%2FbtrFwSHz86z%2FJo6IMX4WM73vCeknQKBZok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;550&quot; data-is-animation=&quot;false&quot;/&gt;&lt;/span&gt;&lt;span class=&quot;image-wrap &quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c82VCJ/btrFuUfCvM3/dspnhjylZuO5aTyzOy95v1/img.png&quot; data-url=&quot;https://blog.kakaocdn.net/dn/c82VCJ/btrFuUfCvM3/dspnhjylZuO5aTyzOy95v1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c82VCJ/btrFuUfCvM3/dspnhjylZuO5aTyzOy95v1/img.png&quot; loading=&quot;lazy&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc82VCJ%2FbtrFuUfCvM3%2FdspnhjylZuO5aTyzOy95v1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;550&quot; data-is-animation=&quot;false&quot;/&gt;&lt;/span&gt;&lt;span class=&quot;image-wrap &quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8ZTdW/btrFyKCxXfA/9Vj4XIg6LZzasju5vPGOk1/img.png&quot; data-url=&quot;https://blog.kakaocdn.net/dn/b8ZTdW/btrFyKCxXfA/9Vj4XIg6LZzasju5vPGOk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8ZTdW/btrFyKCxXfA/9Vj4XIg6LZzasju5vPGOk1/img.png&quot; loading=&quot;lazy&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8ZTdW%2FbtrFyKCxXfA%2F9Vj4XIg6LZzasju5vPGOk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;550&quot; data-is-animation=&quot;false&quot;/&gt;&lt;/span&gt;&lt;button class=&quot;btn btn-prev&quot;&gt;&lt;span class=&quot;ico-prev&quot;&gt;이전&lt;/span&gt;&lt;/button&gt;&lt;button class=&quot;btn btn-next&quot;&gt;&lt;span class=&quot;ico-next&quot;&gt;다음&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;
  &lt;div class=&quot;mark&quot;&gt;&lt;span data-index=&quot;0&quot;&gt;0&lt;/span&gt;&lt;span data-index=&quot;1&quot;&gt;1&lt;/span&gt;&lt;span data-index=&quot;2&quot;&gt;2&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[Server.xml 설정]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Resource 부분에 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;factory=&quot;com.github.tomcatEncryptModule.EncryptedDataSourceFactory&quot;&lt;/b&gt;&lt;/span&gt;를 추가해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1655949359836&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;Resource auth=&quot;Container&quot; 
      		factory=&quot;com.github.tomcatEncryptModule.EncryptedDataSourceFactory&quot; #여기가 중요
			driverClassName=&quot;com.mysql.jdbc.Driver&quot;
			maxActive=&quot;50&quot; 
			maxIdle=&quot;10&quot; 
			maxWait=&quot;-1&quot; 
			name=&quot;jdbc/testDB&quot; 
			password=&quot;암호화값&quot; 
			type=&quot;javax.sql.DataSource&quot; 
			url=&quot;암호화값&quot; 
			username=&quot;암호화값&quot;/&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;서버 재기동후 정상으로 작동되는지 확인!!&lt;/b&gt;&lt;/h4&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;friends1&quot; data-emoticon-name=&quot;014&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/014.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/014.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[적용후 개인생각]&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;만약 이걸 각 프로젝트마다 defaultSecretKey가 바뀐다 생각을 하면 소스 수정후 jar로 묶는 작업이 번거로울수 있다보니 해당 지정된 properties파일을 생성해서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;properties에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;defaultSecretKey&lt;/span&gt;&lt;/span&gt;관리 변수를 추가후 관리 해주는 방안도 있을거 같다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1655957115555&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//예시
//AES secretKey
private static final String defaultSecretKey = properties.getProperty(&quot;SecretKey&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[jar 파일]&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/xrtjW/btrKkm5Wary/7nOZ3zzJqUTTIsFi4EKEWk/tomcatEncryptModule-0.0.1.jar?attach=1&amp;amp;knm=tfile.jar&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;tomcatEncryptModule-0.0.1.jar&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.13MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[git url]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/hunecenter94/tomcat-jdbc-encrypt-module&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/hunecenter94/tomcat-jdbc-encrypt-module&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1661220096930&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - hunecenter94/tomcat-jdbc-encrypt-module: tomcatEncryptModule (server.xml) Aes Encrypt &amp;amp; Decrypt&quot; data-og-description=&quot;tomcatEncryptModule (server.xml) Aes Encrypt &amp;amp; Decrypt - GitHub - hunecenter94/tomcat-jdbc-encrypt-module: tomcatEncryptModule (server.xml) Aes Encrypt &amp;amp; Decrypt&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/hunecenter94/tomcat-jdbc-encrypt-module&quot; data-og-url=&quot;https://github.com/hunecenter94/tomcat-jdbc-encrypt-module&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/F1S17/hyPxhksoft/X3PB1x788suTSkphDXEXO0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/hunecenter94/tomcat-jdbc-encrypt-module&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/hunecenter94/tomcat-jdbc-encrypt-module&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/F1S17/hyPxhksoft/X3PB1x788suTSkphDXEXO0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - hunecenter94/tomcat-jdbc-encrypt-module: tomcatEncryptModule (server.xml) Aes Encrypt &amp;amp; Decrypt&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;tomcatEncryptModule (server.xml) Aes Encrypt &amp;amp; Decrypt - GitHub - hunecenter94/tomcat-jdbc-encrypt-module: tomcatEncryptModule (server.xml) Aes Encrypt &amp;amp; Decrypt&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[참조]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;http://www.jdev.it/encrypting-passwords-in-tomcat/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;http://www.jdev.it/encrypting-passwords-in-tomcat/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1655947849156&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Encrypting passwords in Tomcat &amp;ndash; JDev&quot; data-og-description=&quot;Apache Tomcat is by far the most popular (open source) web server and Java servlet container. It has been around for a long time and &amp;ndash; at the time of writing this post &amp;ndash; has reached version 7.0.29. As&amp;nbsp;Apache rightfully claims on its web site, Tomcat p&quot; data-og-host=&quot;www.jdev.it&quot; data-og-source-url=&quot;http://www.jdev.it/encrypting-passwords-in-tomcat/&quot; data-og-url=&quot;http://www.jdev.it/encrypting-passwords-in-tomcat/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;http://www.jdev.it/encrypting-passwords-in-tomcat/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://www.jdev.it/encrypting-passwords-in-tomcat/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Encrypting passwords in Tomcat &amp;ndash; JDev&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Apache Tomcat is by far the most popular (open source) web server and Java servlet container. It has been around for a long time and &amp;ndash; at the time of writing this post &amp;ndash; has reached version 7.0.29. As&amp;nbsp;Apache rightfully claims on its web site, Tomcat p&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.jdev.it&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jar-download.com/artifacts/org.apache.tomcat/tomcat-jdbc/7.0.19/source-code/org/apache/tomcat/jdbc/pool/DataSourceFactory.java&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://jar-download.com/artifacts/org.apache.tomcat/tomcat-jdbc/7.0.19/source-code/org/apache/tomcat/jdbc/pool/DataSourceFactory.java&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1655947851944&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;org.apache.tomcat.jdbc.pool.DataSourceFactory Maven / Gradle / Ivy&quot; data-og-description=&quot;org.apache.tomcat tomcat-jdbc 7.0.19 compile group: 'org.apache.tomcat', name: 'tomcat-jdbc', version: '7.0.19' //Thanks for using https://jar-download.com libraryDependencies += &amp;quot;org.apache.tomcat&amp;quot; % &amp;quot;tomcat-jdbc&amp;quot; % &amp;quot;7.0.19&amp;quot; //Thanks for using https://jar&quot; data-og-host=&quot;jar-download.com&quot; data-og-source-url=&quot;https://jar-download.com/artifacts/org.apache.tomcat/tomcat-jdbc/7.0.19/source-code/org/apache/tomcat/jdbc/pool/DataSourceFactory.java&quot; data-og-url=&quot;https://jar-download.com/artifacts/org.apache.tomcat/tomcat-jdbc/7.0.19/source-code/org/apache/tomcat/jdbc/pool/DataSourceFactory.java&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://jar-download.com/artifacts/org.apache.tomcat/tomcat-jdbc/7.0.19/source-code/org/apache/tomcat/jdbc/pool/DataSourceFactory.java&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jar-download.com/artifacts/org.apache.tomcat/tomcat-jdbc/7.0.19/source-code/org/apache/tomcat/jdbc/pool/DataSourceFactory.java&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;org.apache.tomcat.jdbc.pool.DataSourceFactory Maven / Gradle / Ivy&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;org.apache.tomcat tomcat-jdbc 7.0.19 compile group: 'org.apache.tomcat', name: 'tomcat-jdbc', version: '7.0.19' //Thanks for using https://jar-download.com libraryDependencies += &quot;org.apache.tomcat&quot; % &quot;tomcat-jdbc&quot; % &quot;7.0.19&quot; //Thanks for using https://jar&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jar-download.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://tomcat.apache.org/tomcat-8.0-doc/api/org/apache/tomcat/jdbc/pool/DataSourceFactory.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://tomcat.apache.org/tomcat-8.0-doc/api/org/apache/tomcat/jdbc/pool/DataSourceFactory.html&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1656310036844&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;DataSourceFactory (Apache Tomcat 8.0.53 API Documentation)&quot; data-og-description=&quot;JNDI object factory that creates an instance of BasicDataSource that has been configured based on the RefAddr values of the specified Reference, which must match the names and data types of the BasicDataSource bean properties. Properties available for conf&quot; data-og-host=&quot;tomcat.apache.org&quot; data-og-source-url=&quot;https://tomcat.apache.org/tomcat-8.0-doc/api/org/apache/tomcat/jdbc/pool/DataSourceFactory.html&quot; data-og-url=&quot;https://tomcat.apache.org/tomcat-8.0-doc/api/org/apache/tomcat/jdbc/pool/DataSourceFactory.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://tomcat.apache.org/tomcat-8.0-doc/api/org/apache/tomcat/jdbc/pool/DataSourceFactory.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://tomcat.apache.org/tomcat-8.0-doc/api/org/apache/tomcat/jdbc/pool/DataSourceFactory.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;DataSourceFactory (Apache Tomcat 8.0.53 API Documentation)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;JNDI object factory that creates an instance of BasicDataSource that has been configured based on the RefAddr values of the specified Reference, which must match the names and data types of the BasicDataSource bean properties. Properties available for conf&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;tomcat.apache.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;</description>
      <category>WAS/Tomcat</category>
      <category>AES</category>
      <category>Java</category>
      <category>Tomcat</category>
      <category>암호화</category>
      <author>hunecenter</author>
      <guid isPermaLink="true">https://hune.tistory.com/77</guid>
      <comments>https://hune.tistory.com/77#entry77comment</comments>
      <pubDate>Thu, 23 Jun 2022 10:58:39 +0900</pubDate>
    </item>
    <item>
      <title>리눅스 톰켓 한글 깨짐 현상 해결</title>
      <link>https://hune.tistory.com/76</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. server.xml 확인&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;656&quot; data-origin-height=&quot;87&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/I31uC/btrvsazsAlQ/eKErcoa4PKlvIaawm0nHDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/I31uC/btrvsazsAlQ/eKErcoa4PKlvIaawm0nHDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/I31uC/btrvsazsAlQ/eKErcoa4PKlvIaawm0nHDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FI31uC%2FbtrvsazsAlQ%2FeKErcoa4PKlvIaawm0nHDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;656&quot; height=&quot;87&quot; data-origin-width=&quot;656&quot; data-origin-height=&quot;87&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. Tomcat/bin 디렉토리에 setenv.sh shell 파일 작성&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1646746307192&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;JAVA_OPTS=&quot;$JAVA_OPTS -Dfile.encoding=\&quot;utf-8\&quot;&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;u&gt;위와 같이 작성후 톰켓을 재기동하면 된다!!&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;u&gt;[참고]&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a href=&quot;https://wiper2019.tistory.com/226&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://wiper2019.tistory.com/226&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1646746374276&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Tomcat] catalina.sh 와 setenv.sh&quot; data-og-description=&quot;스프링으로 외부 속성파일의 값을 @value 어노테이션으로 스프링 빈에 주입할 수 있다. 그런데 아무리 뒤져봐도 프로퍼티 파일에 관련된 내용이 없어 도대체 이 값이 어디서 가져오는 건지 찾아&quot; data-og-host=&quot;wiper2019.tistory.com&quot; data-og-source-url=&quot;https://wiper2019.tistory.com/226&quot; data-og-url=&quot;https://wiper2019.tistory.com/226&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ARVa3/hyNEkCCRsl/PTQG8CYDia9xeXKhoM69kk/img.png?width=800&amp;amp;height=540&amp;amp;face=0_0_800_540,https://scrap.kakaocdn.net/dn/rSkax/hyNEiEML89/z9f4OZd8yiLqFvV1kgxJm0/img.png?width=800&amp;amp;height=540&amp;amp;face=0_0_800_540&quot;&gt;&lt;a href=&quot;https://wiper2019.tistory.com/226&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://wiper2019.tistory.com/226&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ARVa3/hyNEkCCRsl/PTQG8CYDia9xeXKhoM69kk/img.png?width=800&amp;amp;height=540&amp;amp;face=0_0_800_540,https://scrap.kakaocdn.net/dn/rSkax/hyNEiEML89/z9f4OZd8yiLqFvV1kgxJm0/img.png?width=800&amp;amp;height=540&amp;amp;face=0_0_800_540');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Tomcat] catalina.sh 와 setenv.sh&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;스프링으로 외부 속성파일의 값을 @value 어노테이션으로 스프링 빈에 주입할 수 있다. 그런데 아무리 뒤져봐도 프로퍼티 파일에 관련된 내용이 없어 도대체 이 값이 어디서 가져오는 건지 찾아&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;wiper2019.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://bboks.net/380&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://bboks.net/380&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>WAS/Tomcat</category>
      <category>Shell</category>
      <category>Tomcat</category>
      <author>hunecenter</author>
      <guid isPermaLink="true">https://hune.tistory.com/76</guid>
      <comments>https://hune.tistory.com/76#entry76comment</comments>
      <pubDate>Tue, 8 Mar 2022 22:43:12 +0900</pubDate>
    </item>
    <item>
      <title>유튜브 API데이터 가져오기</title>
      <link>https://hune.tistory.com/75</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[리소스 유형]&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;636&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LfjFf/btruZQ9E89V/Jzb8pQzj4UBaLfi4u5JLR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LfjFf/btruZQ9E89V/Jzb8pQzj4UBaLfi4u5JLR1/img.png&quot; data-alt=&quot;유튜브 리소스 유형&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LfjFf/btruZQ9E89V/Jzb8pQzj4UBaLfi4u5JLR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLfjFf%2FbtruZQ9E89V%2FJzb8pQzj4UBaLfi4u5JLR1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;865&quot; height=&quot;636&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;636&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;유튜브 리소스 유형&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[작업]&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;863&quot; data-origin-height=&quot;206&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3myLs/btruWRNYOaa/mJGY4whVkFN3TWNWxkTkK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3myLs/btruWRNYOaa/mJGY4whVkFN3TWNWxkTkK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3myLs/btruWRNYOaa/mJGY4whVkFN3TWNWxkTkK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3myLs%2FbtruWRNYOaa%2FmJGY4whVkFN3TWNWxkTkK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;863&quot; height=&quot;206&quot; data-origin-width=&quot;863&quot; data-origin-height=&quot;206&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[지원되는 작업]&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;869&quot; data-origin-height=&quot;747&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Wl6ns/btruWQO6vc7/Ig41dBCTJWal7gQCJEzqNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Wl6ns/btruWQO6vc7/Ig41dBCTJWal7gQCJEzqNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Wl6ns/btruWQO6vc7/Ig41dBCTJWal7gQCJEzqNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWl6ns%2FbtruWQO6vc7%2FIg41dBCTJWal7gQCJEzqNk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;869&quot; height=&quot;747&quot; data-origin-width=&quot;869&quot; data-origin-height=&quot;747&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[소스]&lt;/h4&gt;
&lt;pre id=&quot;code_1646375945374&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$(document).ready(function() {
	youtube('cnt', 'playListId', 'key');
});

function youtube(cnt, playListId, key){
	$.ajax({
		type: &quot;GET&quot;,
		dataType: &quot;jsonp&quot;,
		cache: false,
		async: false,
		url : &quot;https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&amp;amp;playlistId=&quot;+playListId+&quot;&amp;amp;key=&quot;+key,
		success: function(response) {
			if(response.items.length &amp;gt; 0){
				for(var i = 0; i &amp;lt;cnt; i++){
					var youtube = '&amp;lt;li&amp;gt;';
					youtube += &quot;&amp;lt;a target='_blank' href='https://www.youtube.com/watch?v=&quot;+response.items[i].snippet.resourceId.videoId+&quot;&amp;amp;list=&quot;+response.items[i].snippet.playlistId+&quot;' title='새창 열기'&amp;gt;&quot;;
					youtube += '&amp;lt;img src=&quot;' + response.items[i].snippet.thumbnails.standard.url + '&quot; alt=&quot;유튜브_'+i+'_번째글&quot;&amp;gt;';
					youtube += &quot;&amp;lt;p class='desc'&amp;gt;&quot;;
					youtube += &quot;&amp;lt;span&amp;gt;&quot;;
					youtube += response.items[i].snippet.title;
					youtube += &quot;&amp;lt;/span&amp;gt;&quot;;
					youtube += &quot;&amp;lt;/p&amp;gt;&quot;;
					youtube += &quot;&amp;lt;/a&amp;gt;&quot;;
					youtube += &quot;&amp;lt;/li&amp;gt;&quot;;
					$(&quot;#youtubeSlider&quot;).append(youtube); //해당 append 해줄 id 또는 class
				}
			}
		}
	});
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;[youtube 무료 건수]&amp;nbsp;&lt;br /&gt;Queries&amp;nbsp;/일 10,000건 &lt;br /&gt;Queries&amp;nbsp;/분&amp;nbsp;/사용자&amp;nbsp;180,000건 &lt;br /&gt;Queries&amp;nbsp;/분 1,800,000건&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[참고]&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developers.google.com/youtube/v3/docs/playlists/list&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developers.google.com/youtube/v3/docs/playlists/list&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1646375471724&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Playlists: list &amp;nbsp;|&amp;nbsp; YouTube Data API &amp;nbsp;|&amp;nbsp; Google Developers&quot; data-og-description=&quot;Playlists: list API 요청 매개변수와 일치하는 재생목록의 모음을 반환합니다. 예를 들어 인증된 사용자가 보유한 전체 재생목록을 검색하거나, 고유 ID를 통해 하나 또는 여러 개의 재생목록을 검색&quot; data-og-host=&quot;developers.google.com&quot; data-og-source-url=&quot;https://developers.google.com/youtube/v3/docs/playlists/list&quot; data-og-url=&quot;https://developers.google.com/youtube/v3/docs/playlists/list?hl=ko&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://developers.google.com/youtube/v3/docs/playlists/list&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developers.google.com/youtube/v3/docs/playlists/list&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Playlists: list &amp;nbsp;|&amp;nbsp; YouTube Data API &amp;nbsp;|&amp;nbsp; Google Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Playlists: list API 요청 매개변수와 일치하는 재생목록의 모음을 반환합니다. 예를 들어 인증된 사용자가 보유한 전체 재생목록을 검색하거나, 고유 ID를 통해 하나 또는 여러 개의 재생목록을 검색&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developers.google.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://brunch.co.kr/@joypinkgom/99&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://brunch.co.kr/@joypinkgom/99&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1646375205569&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;16화 유튜브&amp;nbsp;API - 12. 할당량 최적화&quot; data-og-description=&quot;오늘은 할당량(Quota) 이야기를 해 볼까 한다. 유튜브(Youtube) API - 3.API 살펴보기&amp;nbsp;글에서 할당량과 최적화의 필요에 대해 간단히 다룬 바 있다. 할당량이란 API 남용을 막고 자원을 관리하기 위해 구&quot; data-og-host=&quot;brunch.co.kr&quot; data-og-source-url=&quot;https://brunch.co.kr/@joypinkgom/99&quot; data-og-url=&quot;https://brunch.co.kr/@joypinkgom/99&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cECptE/hyNB5Zj6gW/YNvN24OpHyCpRvT8baNgt0/img.png?width=1280&amp;amp;height=433&amp;amp;face=0_0_1280_433,https://scrap.kakaocdn.net/dn/RFkZQ/hyNBZdJBf8/1SVaXVmp7pLCWFHPeaVic1/img.png?width=500&amp;amp;height=500&amp;amp;face=0_0_500_500,https://scrap.kakaocdn.net/dn/nKvgR/hyNATzqImT/3QIjjFPA9NIvKt1mL7gE61/img.png?width=1280&amp;amp;height=507&amp;amp;face=0_0_1280_507&quot;&gt;&lt;a href=&quot;https://brunch.co.kr/@joypinkgom/99&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://brunch.co.kr/@joypinkgom/99&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cECptE/hyNB5Zj6gW/YNvN24OpHyCpRvT8baNgt0/img.png?width=1280&amp;amp;height=433&amp;amp;face=0_0_1280_433,https://scrap.kakaocdn.net/dn/RFkZQ/hyNBZdJBf8/1SVaXVmp7pLCWFHPeaVic1/img.png?width=500&amp;amp;height=500&amp;amp;face=0_0_500_500,https://scrap.kakaocdn.net/dn/nKvgR/hyNATzqImT/3QIjjFPA9NIvKt1mL7gE61/img.png?width=1280&amp;amp;height=507&amp;amp;face=0_0_1280_507');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;16화 유튜브&amp;nbsp;API - 12. 할당량 최적화&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 할당량(Quota) 이야기를 해 볼까 한다. 유튜브(Youtube) API - 3.API 살펴보기&amp;nbsp;글에서 할당량과 최적화의 필요에 대해 간단히 다룬 바 있다. 할당량이란 API 남용을 막고 자원을 관리하기 위해 구&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;brunch.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>javascript/유튜브</category>
      <author>hunecenter</author>
      <guid isPermaLink="true">https://hune.tistory.com/75</guid>
      <comments>https://hune.tistory.com/75#entry75comment</comments>
      <pubDate>Fri, 4 Mar 2022 15:39:19 +0900</pubDate>
    </item>
    <item>
      <title>페이스북 무기한 토큰 방법 (다른방법)</title>
      <link>https://hune.tistory.com/74</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hune.tistory.com/47?category=808762&quot;&gt;https://hune.tistory.com/47?category=808762&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1644890063771&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;facebook 무기한 토큰 만들기2 (feat.2021-08-19)&quot; data-og-description=&quot;1. 토큰 생성 2. 토큰 기간 확장 &amp;nbsp;확장된 새 액세스 토큰 복사 3. 무기한 토큰 생성 2번에서 생성한 토큰을 액세스 토큰에 붙여 놓기 filed쪽에 me?fields=access_token 작성후 제출 버튼 클릭 호출된 access_&quot; data-og-host=&quot;hune.tistory.com&quot; data-og-source-url=&quot;https://hune.tistory.com/47?category=808762&quot; data-og-url=&quot;https://hune.tistory.com/47&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/490B7/hyNpbz4qHC/QCYGBkt7QvBBKMSxt6i1AK/img.png?width=800&amp;amp;height=362&amp;amp;face=0_0_800_362,https://scrap.kakaocdn.net/dn/dC77N7/hyNpkjtroL/oQNuEanS89JXM6qvjdPIOK/img.png?width=800&amp;amp;height=362&amp;amp;face=0_0_800_362,https://scrap.kakaocdn.net/dn/okKdR/hyNqz69Dt1/mjAeNZIKakhaf7RMz2vYX0/img.png?width=1896&amp;amp;height=832&amp;amp;face=0_0_1896_832&quot;&gt;&lt;a href=&quot;https://hune.tistory.com/47?category=808762&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hune.tistory.com/47?category=808762&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/490B7/hyNpbz4qHC/QCYGBkt7QvBBKMSxt6i1AK/img.png?width=800&amp;amp;height=362&amp;amp;face=0_0_800_362,https://scrap.kakaocdn.net/dn/dC77N7/hyNpkjtroL/oQNuEanS89JXM6qvjdPIOK/img.png?width=800&amp;amp;height=362&amp;amp;face=0_0_800_362,https://scrap.kakaocdn.net/dn/okKdR/hyNqz69Dt1/mjAeNZIKakhaf7RMz2vYX0/img.png?width=1896&amp;amp;height=832&amp;amp;face=0_0_1896_832');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;facebook 무기한 토큰 만들기2 (feat.2021-08-19)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;1. 토큰 생성 2. 토큰 기간 확장 &amp;nbsp;확장된 새 액세스 토큰 복사 3. 무기한 토큰 생성 2번에서 생성한 토큰을 액세스 토큰에 붙여 놓기 filed쪽에 me?fields=access_token 작성후 제출 버튼 클릭 호출된 access_&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hune.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;위 링크의 1번,2번,4번 내용은같다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3번 작업(수정)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;filed쪽에 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;me?fields=access_token&lt;/span&gt;&lt;/b&gt; or &amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;me?fields=accounts&lt;/b&gt;&lt;/span&gt;&amp;nbsp;로 작성후 제출 버튼 클릭(2022-02-15 작성)&lt;/li&gt;
&lt;li&gt;하단 사진과 같이 access_token이 무기한 토큰이다.&lt;/li&gt;
&lt;li&gt;밑에 access_token을 복사해서 만료일이 (받지 않음) 인지 체크하면 완료!&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;860&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0d1SF/btrtoBdaW2T/eDJOC5arSvXPkWuQtGdHB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0d1SF/btrtoBdaW2T/eDJOC5arSvXPkWuQtGdHB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0d1SF/btrtoBdaW2T/eDJOC5arSvXPkWuQtGdHB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0d1SF%2FbtrtoBdaW2T%2FeDJOC5arSvXPkWuQtGdHB1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;860&quot; height=&quot;533&quot; data-origin-width=&quot;860&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>javascript/페이스북 SNS</category>
      <author>hunecenter</author>
      <guid isPermaLink="true">https://hune.tistory.com/74</guid>
      <comments>https://hune.tistory.com/74#entry74comment</comments>
      <pubDate>Tue, 15 Feb 2022 10:58:50 +0900</pubDate>
    </item>
    <item>
      <title>JAVA 접근장치, 운영체제, 브라우저 확인</title>
      <link>https://hune.tistory.com/73</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;고객의 요청에 의해 접근장치, 운영체제, 브라우저를 확인해서 로그를 남겨 달라는 말에 따로 ClientUtil.class로 빼서 구현을 해보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[pom.xml 기입]&lt;/h4&gt;
&lt;pre id=&quot;code_1644539251003&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
	&amp;lt;groupId&amp;gt;com.github.ua-parser&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;uap-java&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.4.3&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[소스]&lt;/h4&gt;
&lt;pre id=&quot;code_1644538905380&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package project.client.util;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ua_parser.Client;
import ua_parser.Parser;

/**
 * Client Utility Class
 * @Class Name  : ClientUtil.java
 * @Description :
 * @Modification Information
 *
 *    수정일        수정자        수정내용
 *    -----------  --------  -------------------
 *    2022.02.10.   HD        최초생성
 *
 * @author HD
 * @since 2022.02.10
 * @version 1.0
 */

public class ClientUtil {

    private static final Logger LOG = LoggerFactory.getLogger(ClientUtil.class.getName());
    
    /**
     * &amp;lt;pre&amp;gt;
     * 접근장치를 반환하는 메소드
     * &amp;lt;/pre&amp;gt;
     * @param request HttpServletRequest
     * @return 접근장치 문자열
     */
    public static String getAcesEqpmt(HttpServletRequest request) {
        String headerStr = request.getHeader( &quot;User-Agent&quot; ).toUpperCase();
        String acesEqpmt = &quot;PC&quot;;
        
        if ( headerStr.contains( &quot;MOBILE&quot; ) || headerStr.contains( &quot;MOBI&quot; ) ) {
            acesEqpmt = &quot;MOBILE&quot;;
        }

        return acesEqpmt;
    }
    
    /**
     * &amp;lt;pre&amp;gt;
     * 운영체제를 반환하는 메소드
     * &amp;lt;/pre&amp;gt;
     * @param request HttpServletRequest
     * @return 운영체제 문자열
     */
    public static String getOs(HttpServletRequest request) {
        String headerStr = request.getHeader( &quot;User-Agent&quot; );
        String os = &quot;&quot;;
        
        try {
            Parser parser = new Parser();
            Client client = parser.parse( headerStr );
            os = client.os.family;
        } catch ( IOException e ) {
            LOG.error(&quot;ERROR : &quot;,e.getMessage());
        }
        
        return os;
    }
    
    /**
     * &amp;lt;pre&amp;gt;
     * 브라우저 이름을 반환하는 메소드
     * &amp;lt;/pre&amp;gt;
     * @param request HttpServletRequest
     * @return 브라우저 이름 문자열
     */
    public static String getBrowserNm(HttpServletRequest request) {
        String headerStr = request.getHeader( &quot;User-Agent&quot; ).toUpperCase();
        String browser = &quot;&quot;;

        if ( headerStr.indexOf(&quot;TRIDENT&quot;) &amp;gt; -1 || headerStr.indexOf(&quot;MSIE&quot;) &amp;gt; -1 ) { //IE

            if ( headerStr.indexOf(&quot;TRIDENT/7&quot;) &amp;gt; -1 ) {
                browser = &quot;IE 11&quot;;
            } else if ( headerStr.indexOf(&quot;TRIDENT/6&quot;) &amp;gt; -1 ) {
                browser = &quot;IE 10&quot;;
            } else if ( headerStr.indexOf(&quot;TRIDENT/5&quot;) &amp;gt; -1 ) {
                browser = &quot;IE 9&quot;;
            } else if ( headerStr.indexOf(&quot;TRIDENT/4&quot;) &amp;gt; -1 ) {
                browser = &quot;IE 8&quot;;
            } else if ( headerStr.indexOf(&quot;EDG&quot;) &amp;gt; -1 || headerStr.indexOf(&quot;EDGE&quot;) &amp;gt; -1 ) {
                browser = &quot;IE Edge&quot;;
            }

        } else if ( headerStr.indexOf(&quot;WHALE&quot;) &amp;gt; -1 ) { //네이버 WHALE
            browser = &quot;Whale&quot;;
        } else if ( headerStr.indexOf(&quot;OPERA&quot;) &amp;gt; -1 || headerStr.indexOf(&quot;OPR&quot;) &amp;gt; -1 ) { //오페라
            browser = &quot;Opera&quot;;
        } else if ( headerStr.indexOf(&quot;FIREFOX&quot;) &amp;gt; -1 ) { //파이어폭스
            browser = &quot;Firefox&quot;;
        } else if ( headerStr.indexOf(&quot;SAFARI&quot;) &amp;gt; -1 &amp;amp;&amp;amp; headerStr.indexOf(&quot;CHROME&quot;) == -1 ) { //사파리
            browser = &quot;Safari&quot;;
        } else if ( headerStr.indexOf(&quot;CHROME&quot;) &amp;gt; -1 ) { //크롬
            browser = &quot;Chrome&quot;;
        } else {
            browser = &quot;Other&quot;;
        }

        //LOG.debug(&quot;userAgent 확인 [&quot;+userAgent+&quot;]&quot;);
        //LOG.debug(&quot;브라우저/버전 확인 [&quot;+browser+&quot;]&quot;);

        return browser;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[참고]&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/ua-parser/uap-java&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/ua-parser/uap-java&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1644539311219&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - ua-parser/uap-java: Java implementation of ua-parser&quot; data-og-description=&quot;Java implementation of ua-parser. Contribute to ua-parser/uap-java development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/ua-parser/uap-java&quot; data-og-url=&quot;https://github.com/ua-parser/uap-java&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/pluqz/hyNmCj9cIn/Lzkobg2N5C1JjIxlI1sCKk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/ua-parser/uap-java&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/ua-parser/uap-java&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/pluqz/hyNmCj9cIn/Lzkobg2N5C1JjIxlI1sCKk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - ua-parser/uap-java: Java implementation of ua-parser&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Java implementation of ua-parser. Contribute to ua-parser/uap-java development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@ggong/User-agent-%EC%A0%95%ED%99%95%ED%95%98%EA%B2%8C-%ED%95%B4%EC%84%9D%ED%95%98%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://velog.io/@ggong/User-agent-%EC%A0%95%ED%99%95%ED%95%98%EA%B2%8C-%ED%95%B4%EC%84%9D%ED%95%98%EA%B8%B0&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1644539566078&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;User-agent 정확하게 해석하기&quot; data-og-description=&quot;user agent는 HTTP 요청을 보내는 디바이스와 브라우저 등 사용자 소프트웨어의 식별 정보를 담고 있는 request header의 한 종류이다. 임의로 수정될 수 없는 값이고, 보통 HTTP 요청 에러가 발생했을 때 &quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@ggong/User-agent-%EC%A0%95%ED%99%95%ED%95%98%EA%B2%8C-%ED%95%B4%EC%84%9D%ED%95%98%EA%B8%B0&quot; data-og-url=&quot;https://velog.io/@ggong/User-agent-정확하게-해석하기&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dWC1N5/hyNnYMGKld/zyaxCpmQlIr2vkmHfMxOt1/img.png?width=950&amp;amp;height=500&amp;amp;face=0_0_950_500&quot;&gt;&lt;a href=&quot;https://velog.io/@ggong/User-agent-%EC%A0%95%ED%99%95%ED%95%98%EA%B2%8C-%ED%95%B4%EC%84%9D%ED%95%98%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@ggong/User-agent-%EC%A0%95%ED%99%95%ED%95%98%EA%B2%8C-%ED%95%B4%EC%84%9D%ED%95%98%EA%B8%B0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dWC1N5/hyNnYMGKld/zyaxCpmQlIr2vkmHfMxOt1/img.png?width=950&amp;amp;height=500&amp;amp;face=0_0_950_500');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;User-agent 정확하게 해석하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;user agent는 HTTP 요청을 보내는 디바이스와 브라우저 등 사용자 소프트웨어의 식별 정보를 담고 있는 request header의 한 종류이다. 임의로 수정될 수 없는 값이고, 보통 HTTP 요청 에러가 발생했을 때&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JAVA</category>
      <category>Java</category>
      <category>OS</category>
      <category>ua-parser</category>
      <category>User-Agent</category>
      <category>브라우저</category>
      <category>접근장치</category>
      <author>hunecenter</author>
      <guid isPermaLink="true">https://hune.tistory.com/73</guid>
      <comments>https://hune.tistory.com/73#entry73comment</comments>
      <pubDate>Sat, 12 Feb 2022 10:32:52 +0900</pubDate>
    </item>
    <item>
      <title>log 파일을 실시간으로 볼때 유용한 TailMe</title>
      <link>https://hune.tistory.com/72</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;- 에디터로 매번 보다가 실시간 볼수있는 파일을 찾아서 올려봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 사용법은 *.log 확장자 파일을 넣으면 실시간으로 로그확인이 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/1gFAp/btrsVJKSr67/mkP1i9od1skkGKh6J2xFCk/TailMe.zip?attach=1&amp;amp;knm=tfile.zip&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;TailMe.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.88MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Util</category>
      <category>log</category>
      <category>TailMe</category>
      <category>Was</category>
      <category>web server</category>
      <author>hunecenter</author>
      <guid isPermaLink="true">https://hune.tistory.com/72</guid>
      <comments>https://hune.tistory.com/72#entry72comment</comments>
      <pubDate>Thu, 10 Feb 2022 10:53:25 +0900</pubDate>
    </item>
  </channel>
</rss>