<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>yeong.log</title>
        <link>https://velog.io/</link>
        <description>[올리 공부기록] 한계단씩 꾸준히 성장하기</description>
        <lastBuildDate>Tue, 10 Jan 2023 05:12:58 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>yeong.log</title>
            <url>https://velog.velcdn.com/images/olive_yeong/profile/954233e2-05a5-4207-9936-7895d1141fa9/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. yeong.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/olive_yeong" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[SQL] 다이나믹 쿼리 Dynamic Query]]></title>
            <link>https://velog.io/@olive_yeong/SQL-%EB%8B%A4%EC%9D%B4%EB%82%98%EB%AF%B9-%EC%BF%BC%EB%A6%AC-Dynamic-Query</link>
            <guid>https://velog.io/@olive_yeong/SQL-%EB%8B%A4%EC%9D%B4%EB%82%98%EB%AF%B9-%EC%BF%BC%EB%A6%AC-Dynamic-Query</guid>
            <pubDate>Tue, 10 Jan 2023 05:12:58 GMT</pubDate>
            <description><![CDATA[<h2 id="💻동적쿼리">💻동적쿼리</h2>
<blockquote>
<p>정적쿼리 : 어떤 조건 또는 상황에도 변경되지 않는 쿼리문
동적쿼리 : 특정 조건들이나 상황에 따라 변경되는 쿼리문</p>
</blockquote>
<ul>
<li>다이나믹쿼리의 조건문을 통해서 다른 조건이 대입해서 중복되는 쿼리들을 최소화 시킬 수 있다.</li>
</ul>
<hr>

<h2 id="🎲다이나믹-쿼리-종류">🎲다이나믹 쿼리 종류</h2>
<h3 id="1-if">1. if</h3>
<ul>
<li>마이바티스에서 가장 많이 사용되는 요소.</li>
<li>파라미터로 받아온 값을 조건절로 걸러서 조건절 등을 추가할 때 사용한다.</li>
<li>파라미터 타입 안에 다른 타입(클래스)가 포함되어 캡슐화를 이룰 경우, .(dot) 연산자로 변수 접근이 가능하다.</li>
</ul>
<h3 id="2-choose">2. Choose</h3>
<ul>
<li>else if가 없기 때문에 대신 choose로 사용된다.</li>
</ul>
<pre><code>&lt;choose&gt; : 크게 감싸고,
&lt;when test=&quot;조건&quot;&gt; : 조건을 걸고,
&lt;otherwise&gt; : 기타요소를 넣는다.
&lt;/otherwise&gt;
&lt;/when&gt;
&lt;/choose&gt;</code></pre><h3 id="3-trim-where-set">3. Trim (where, set)</h3>
<ul>
<li>여러 구문 중 하나만 실행</li>
<li>WHERE 조건을 자동으로 생성하며 문법상 맞게 맞춰준다.
```
//where 사용시</li>
</ul>
<ol>
<li><where>
     <if test="조건">
      </if>
</where>
</li>
<li><trim prefix="WHERE" prefixOverrids="AND">
        <if test="조건">
        </if>
</trim>

</li>
</ol>
<p>//set 사용시</p>
<ol>
<li><trim prefix="SET" suffix Overrids=",">
        <if test="조건">
        </if>
</trim>
```

</li>
</ol>
<h3 id="4-foreach">4. forEach</h3>
<ul>
<li>Collection의 반복 처리 기능을 담당한다.<pre><code>&lt;foreach collection=&quot;array&quot; item=&quot;배열명&quot; separator=&quot;,&quot;&gt;
  #{배열명}
&lt;/foreach&gt;</code></pre></li>
<li>Collection에는 배열이나 리스트만 사용이 가능하다.</li>
<li>Separator는 안에 담긴 Object들을 구분시켜줄 기호이다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SQL] OVER(), ROLLUP, GROUPING  ]]></title>
            <link>https://velog.io/@olive_yeong/D-OVER-ROLLUP-GROUPING</link>
            <guid>https://velog.io/@olive_yeong/D-OVER-ROLLUP-GROUPING</guid>
            <pubDate>Fri, 06 Jan 2023 07:47:56 GMT</pubDate>
            <description><![CDATA[<h1 id="1-over-">1. over() ?</h1>
<ul>
<li>group by를 사용하지 않고, 어떤 값을 가준으로 합 합이나, 카운트, min, max, avg 등의 집계 함수값을 구해서 일반 데이터와 함께 출력할 수 있다.</li>
</ul>
<blockquote>
<p> A, B, C, D 라는 기준으로 두 개씩 묶어서 합계를 구하고 싶을 때, ROLLUP()을 쓰기는 아주 번거롭기 때문에, 묶고 싶은 조건을 PARTITION BY로 묶어 OVER()함수를 사용할 수 있다.</p>
</blockquote>
<pre><code>SELECT
        coutry, year, profit,
        SUM(profit) OVER(PARTITION BY country) AS country_profit
FROM    sales;</code></pre><br>
<hr>
<br>

<h1 id="2-rollup-">2. ROLLUP ?</h1>
<ul>
<li>여러 항목으로 GROUP BY를 한 다움, 중간 그룹별로 통계값이 필요한 경우에 유용한 함수이다.</li>
<li>주로 분류해야 되는 값이 많은 데이터를 다룰 때, 통계를 내야할 때 사용한다.</li>
</ul>
<pre><code>SELECT
        country, year, genre, SUM(sales)
FROM
        booksales
GROUP BY country, year, genre WITH ROLLUP;</code></pre><ul>
<li><p>ROLLUP을 한 경우, 중간중간 그룹마다 통계값이 생성된다.</p>
</li>
<li><p>현재는 ROLLUP과 ORDER BY는 같이 지원되지 않는다.</p>
<br>
<hr>
<br>
# 3. GROUPING ?
</li>
<li><p>ROLLUP과 함께 쓰기 좋은 함수로, ROLLUP한 중간 통계값이 NULL이 나오기 때문에, 실제로 NULL인 값과 혼동될 우려가 있다. 이럴 때, 어떤 값이 롤업으로 그루핑 된 것인지 알 수 있게 하는 것이 GROUPING 함수이다.</p>
</li>
<li><p>그룹함수에 의해 컬럼 값이 소계나 총합 등 집계된 데이터일 경우, 1을 리턴하고 만약 집계된 데이터가 아니면 0을 리턴한다.</p>
</li>
</ul>
<blockquote>
<p>1, 0으로 리턴되는 방식을 이용하여,
소계값일 때(1일 때)의 그루핑 이름을 달고,
NULL값일 때(0일 때)의 그루핑 이름을 달아 구별할 수 있다.</p>
</blockquote>
<pre><code>SELECT CASE
            WHEN GROUPING(country) = 1 THEN &#39;나라별 합계&#39;
            WHEN country IS NULL THEN &#39;나라 null값 합계&#39;
FROM sales;</code></pre><ul>
<li>GROUPING은 소계, 집계함수값인지 이분법적으로 구분해주기 때문에, GROUP BY로 취합된 값은 NULL과 동일시 되어 0을 리턴한다.</li>
</ul>
<br>
<hr>
<br>

<h4 id="참고자료">참고자료</h4>
<hr>

<p><a href="https://jhnyang.tistory.com/473">https://jhnyang.tistory.com/473</a></p>
<p><a href="https://jinjungs.github.io/til/210805_TIL/">https://jinjungs.github.io/til/210805_TIL/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring]EgovMap이란?]]></title>
            <link>https://velog.io/@olive_yeong/SpringEgovMap%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@olive_yeong/SpringEgovMap%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Fri, 06 Jan 2023 07:03:00 GMT</pubDate>
            <description><![CDATA[<h1 id="egovmap">EgovMap</h1>
<ol>
<li>전자정부프레임워크에서 제공하는 제네릭 타입(java의 Map클래스와 동일)</li>
<li>Map형태의 클래스로 iBatis parameterClass 또는 resultClass에서 사용할 수 있도록 제공되는 클래스<hr>
## resultClass란?</li>
</ol>
<ul>
<li>어떠한 DB에서 조회한 결과를 가져올 때, 결과값의 포맷을 가진 클래스라고 생각하면 된다.<h3 id="map과-egovmap-차이점">Map과 egovMap 차이점</h3>
</li>
<li>egovMap은 자동으로 컬럼을 맵핑할 수 있는 객체 이름을 생성해준다.</li>
</ul>
<blockquote>
<p>예) SQL문의 user_id를 사용하고자 할 때,
Map은 &#39;user_id&#39;로 컬럼을 참조한다.
EgovMap은 &#39;userId&#39;로 컬럼을 참조한다.</p>
</blockquote>
<ul>
<li>컬럼명의 _다음 알파벳은 대문자로 인식하며, 컬럼명에서 대문자는 소문자 변수로 맵핑된다. (user_id -&gt; userId, userId -&gt; userid)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[spring] 
java.lang.IllegalStateException: Failed to load ApplicationContext 오류해결]]></title>
            <link>https://velog.io/@olive_yeong/spring-java.lang.IllegalStateException-Failed-to-load-ApplicationContext-%EC%98%A4%EB%A5%98%ED%95%B4%EA%B2%B0</link>
            <guid>https://velog.io/@olive_yeong/spring-java.lang.IllegalStateException-Failed-to-load-ApplicationContext-%EC%98%A4%EB%A5%98%ED%95%B4%EA%B2%B0</guid>
            <pubDate>Wed, 26 Oct 2022 00:49:21 GMT</pubDate>
            <description><![CDATA[<h2 id="1-문제">1. 문제</h2>
<p>예제를 따라하면서 JUnit으로 test를 해보려고 하는데
root-context.xml에서 hikari와 driverClassName를 찾을 수 없다고 뜨는 오류가 발생하였다.</p>
<blockquote>
<p>PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property &#39;driverClassName&#39; threw exception; nested exception is java.lang.NoClassDefFoundError: Unable to find Log4j2 as default logging library. Please provide a logging library and configure a valid spyLogDelegator name in the properties file.
ERROR: org.springframework.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@561b6512] to prepare test instance [org.zerock.serivce.SampleTxServiceTests@2e6ba49a]
java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:108)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:246)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:93)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)</p>
</blockquote>
<p>그래서 root-context.xml를 살펴보았지만 오타나 빠진 부분은 없이 완벽했는데도 고쳐지지가 않아서 문제 원인을 찾아보았다.
오류코드에서 log4j2가 찾아지지 않는다는 caused가 뜨는게 보였다.</p>
<h2 id="2-해결">2. 해결</h2>
<p>pom에서 두 개의 메이븐을 추가해주니, 오류가 사라지고 정상적으로 테스트가 작동되었다.</p>
<p><img src="https://velog.velcdn.com/images/olive_yeong/post/decc1d8b-edcb-4e07-bf0d-848709653ea8/image.PNG" alt=""></p>
<p>(출처:<a href="https://jwj1699.tistory.com/14">https://jwj1699.tistory.com/14</a>)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[spring] Textarea에서 첫 줄에 공백 생기는 오류 해결하기]]></title>
            <link>https://velog.io/@olive_yeong/spring-Textarea%EC%97%90%EC%84%9C-%EC%B2%AB-%EC%A4%84%EC%97%90-%EA%B3%B5%EB%B0%B1-%EC%83%9D%EA%B8%B0%EB%8A%94-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@olive_yeong/spring-Textarea%EC%97%90%EC%84%9C-%EC%B2%AB-%EC%A4%84%EC%97%90-%EA%B3%B5%EB%B0%B1-%EC%83%9D%EA%B8%B0%EB%8A%94-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 19 Oct 2022 06:44:22 GMT</pubDate>
            <description><![CDATA[<h2 id="1-문제">1. 문제</h2>
<p><img src="https://velog.velcdn.com/images/olive_yeong/post/959ffe0b-0666-4395-9cae-426787d046b0/image.PNG" alt=""></p>
<p>게시판에서 read 화면에서는 내가 입력한대로 내용이 잘 나오게 출력이 되는데</p>
<p><img src="https://velog.velcdn.com/images/olive_yeong/post/59e70fec-1527-45c1-9aa5-86b3b04efcdc/image.PNG" alt="">
수정화면으로 넘어가면 이상하게 Text area 부분 앞에 공백이 생긴다. 저 상태로 저장을 하고, 다시 수정 화면으로 들어가면 공백이 두 배로 늘어나 있는 오류가 발생한다..</p>
<h2 id="2-해결">2. 해결</h2>
<p>구글링 해본 결과 나와 같은 오류가 나는 사람들이 많아서 생각보다 쉽게 오류를 해결했다.</p>
<pre><code>&lt;div class=&quot;form-group&quot;&gt;
&lt;label&gt;Text area&lt;/label&gt;
&lt;textarea class=&quot;form-control&quot; rows=&quot;3&quot; name=&quot;content&quot;&gt;
&lt;c:out value=&quot;${board.content }&quot;/&gt;&lt;/textarea&gt;
&lt;/div&gt;</code></pre><p>(오류코드)</p>
<pre><code>&lt;div class=&quot;form-group&quot;&gt;
&lt;label&gt;Text area&lt;/label&gt;
&lt;textarea class=&quot;form-control&quot; rows=&quot;3&quot; name=&quot;content&quot;&gt;&lt;c:out value=&quot;${board.content }&quot;/&gt;&lt;/textarea&gt;
&lt;/div&gt;</code></pre><p>(수정코드)</p>
<p>코드가 너무 길어서 tab으로 잘라놨는데
그 공백이 textarea에 같이 인식이 되어 나타나는 오류였다. 공백을 없애고 1열로 나열해서 코드를 작성하니까 공백은 나타나지 않았다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[spring] 모달창 안 뜨는 오류해결하기]]></title>
            <link>https://velog.io/@olive_yeong/spring-%EB%AA%A8%EB%8B%AC%EC%B0%BD-%EC%95%88-%EB%9C%A8%EB%8A%94-%EC%98%A4%EB%A5%98%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@olive_yeong/spring-%EB%AA%A8%EB%8B%AC%EC%B0%BD-%EC%95%88-%EB%9C%A8%EB%8A%94-%EC%98%A4%EB%A5%98%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 19 Oct 2022 05:10:41 GMT</pubDate>
            <description><![CDATA[<h2>1. 문제</h2>
스프링 웹 프로젝트를 배우면서 게시판에 글을 작성하고 등록할 때 뜨는 모달창을 만들다가 오류가 발생하였다.

<p> <img src="https://velog.velcdn.com/images/olive_yeong/post/b650b293-088c-4c4f-8860-782544dfeb10/image.PNG" alt=""></p>
<p>등록 버튼을 누르면 이렇게 정상적으로 떠야 하는데 내 코드에선 등록은 되지만 모달창이 뜨지를 않았다.</p>
<pre><code>            &lt;script type=&quot;text/javascript&quot;&gt;
            $(document).ready(function(){

                var result=&#39;&lt;c:out value=&quot;${result}&quot;/&gt;&#39;;

                checkModal(result);

                function checkModal(result){
                    if(result===&#39;&#39;){
                        return;
                    }
                    if(parseInt(result)&gt;0){
                        $(&quot;.modal-body&quot;).html(&quot;게시글 &quot;+parseInt(result)+&quot; 번이 등록되었습니다.&quot;);
                    }

                    $(&quot;#myModal&quot;).modal(&quot;show&quot;);
                }

                $(&quot;#regBtn&quot;).on(&quot;click&quot;, function(){
                    self.location=&quot;/board/register&quot;;
                });
            });
           &lt;/script&gt;
</code></pre><p>jsp파일에서 jQuery를 이용한 모달창 코드이다.
정상적이라면 result값이 jsp파일로 넘어와야하는데 h1태그로 result를 불러와도 값이 입력되지 않아서 원인이 뭔지 찾아보고 있었다.</p>
<p><img src="https://velog.velcdn.com/images/olive_yeong/post/51533ebd-7f03-4516-a293-594fbb2c07ee/image.png" alt="">
(이건 브라우저창에서 본 내 코드... result값이 &quot;&quot;으로 나와서 바로 return이 되어버린다.)</p>
<h2 id="2-원인분석">2. 원인분석</h2>
<h3 id="1-jquery와-bootstrap-위치-제대로-정하기">1) jquery와 bootstrap 위치 제대로 정하기</h3>
<p>스프링에서 jquery를 사용하기 위해서는 스크립트 링크를 잘 넣어줘야 한다.
오류가 나는 원인 중 하나는 jquery가 bootstrap보다 밑에 있다면 제대로 작동을 안하기 때문에 위쪽으로 옮겨주면 해결이 될 수 있다.</p>
<pre><code>    &lt;script src=&quot;https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js&quot;&gt;&lt;/script&gt; 
    &lt;script src=&quot;/resources/vendor/bootstrap/js/bootstrap.min.js&quot;&gt;&lt;/script&gt;</code></pre><p>하지만 난 header에 jquery를 넣었고, footer에 bootstrap이 있었기 때문에 이것도 안 먹혔다.</p>
<h3 id="2-selectkey-이용하기">2) SelectKey 이용하기</h3>
<p> 두번째로 생각한 원인은 SelectKey이다. 인덱스(bno)는 쿼리에서 자동으로 입력이 될 수 있게 해놨다. 자동으로 생성된 인덱스를 바로 사용해야 할 경우 SelectKey 메서드를 이용한다.</p>
<pre><code>&lt;insert id=&quot;insertSelectKey&quot;&gt;
&lt;selectKey keyProperty=&quot;bno&quot; order=&quot;BEFORE&quot; resultType=&quot;long&quot;&gt;
select seq_board.nextval from dual
&lt;/selectKey&gt;
insert into tbl_board(bno, title, content, writer)
values (#{bno},#{title},#{content},#{writer})
&lt;/insert&gt;
</code></pre><p>(Mapper.xml에서 입력된 SelectKey 쿼리.
before를 사용해서 인덱스값을 지정하고, 테이블에 넣어준다.)</p>
<pre><code>    @Override
    public void register(BoardVO board) {

        log.info(&quot;register.......&quot;+ board);
        mapper.insertSelectKey(board);
    }</code></pre><p>(ServiceImpl.java에서 사용된 SelectKey)</p>
<p>찾아본 결과 SelectKey값은 제대로 입력했고, 오류도 나지 않았다.</p>
<h2 id="3-문제해결">3. 문제해결</h2>
<p>모든 코드가 오류가 나지 않고 정상 작동한다면 어딘가에서 내가 오타를 낸 것이고, 이름값에서 문제가 생긴 것일 것이다.</p>
<p>그리고 정말 사소한 곳에서 원인을 발견했다.</p>
<pre><code>    @PostMapping(&quot;/register&quot;)
    public String register(BoardVO board, RedirectAttributes rttr) {
        log.info(&quot;register: &quot;+board);
        service.register(board);
        rttr.addFlashAttribute(&quot;register&quot;,board.Bno());
        return &quot;redirect:/board/list&quot;;
    }</code></pre><p>addFlashAttribute에서 이름을 &quot;register&quot;로 적어놓고서,</p>
<pre><code>$(document).ready(function(){

var result=&#39;&lt;c:out value=&quot;${result}&quot;/&gt;&#39;;

checkModal(result);</code></pre><p>jquery에선 result로 부르고 있었으니, 나올 일이 없었다... 둘 이름을 통일하니 바로 정상 작동이 되고 브라우저에서도 인덱스값이 정확하게 입력된다.</p>
<p>아직도 어디부분에서 정보가 가져와지는데 정확하게 알지 못해서 생기는 오류라고 생각한다.
좀 더 제대로 자세하게 공부해야지...</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring] MVC Controller]]></title>
            <link>https://velog.io/@olive_yeong/Spring-MVC-Controller</link>
            <guid>https://velog.io/@olive_yeong/Spring-MVC-Controller</guid>
            <pubDate>Sat, 15 Oct 2022 08:08:19 GMT</pubDate>
            <description><![CDATA[<h2 id="requestmapping">RequestMapping</h2>
<h3 id="1-requestmapping">1. @RequestMapping</h3>
<p>: 현재 클래스의 모든 메서드들의 기본적인 URL경로를 지정해준다.
: 클래스 선언과 메서드선언 둘 다 가능하다.</p>
<h3 id="2-requestmapping의-변화">2. @RequestMapping의 변화</h3>
<p>: @Controller는 추가적인 속성을 지정할 수 없지만, @RequestMapping은 속성을 지정할 수 있다.
: method 속성을 지정하여, POST, GET방식을 구분해서 사용할 수 있다.
: GET방식을 이용할 땐, 주소창에 &#39;?name=aaa&amp;age=10&#39;과 같은 형태로 입력을 할 수 있다.</p>
<pre><code>@RequestMapping(value=&quot;/basic&quot;, method= {RequestMethod.GET, RequestMethod.POST})
    public void basicGet() { // get, post 방식 둘 다 지원가능
        log.info(&quot;basic get.................&quot;);
    }</code></pre><h3 id="3-controller의-파라미터-수집과-변환">3. Controller의 파라미터 수집과 변환</h3>
<p>: Controller의 가장 편리한 기능은 파라미터가 자동으로 수집되는 기능이 있다.
: 이 기능을 위해 DTO 클래스를 만들어 이용한다.
: Lombok의 @Date 기능을 사용하면 getter/setter을 만들지 않아도 자동으로 처리가 된다.</p>
<pre><code>import lombok.Data;

@Data
public class SampleDTO {

    private String name;
    private int age;
}</code></pre><p>: Controller가 파라미터를 수집하는 방식은 파라미터 타입에 따라 자동으로 변환하는 방식을 이용한다. 예를 들어 int age를 자동으로 숫자로 변화되는 것을 볼 수 있다.</p>
<p>:@RequestParam이란, 파라미터로 사용된 변수의 이름과 전달되는 파라미터의 이름이 다른 경우에 유용하게 사용된다.</p>
<pre><code>
    @GetMapping(&quot;/ex02&quot;) // @RequestParam : 파라미터 변수의 이름과, 전달되는 파라미터의 이름이 다른 경우에 쓰인다.
    public String ex02 (@RequestParam(&quot;name&quot;) String name, @RequestParam(&quot;age&quot;) int age) {
        log.info(&quot;name: &quot;+name);
        log.info(&quot;age: &quot;+age);

        return &quot;ex02&quot;;
    }
</code></pre><h3 id="4-리스트-배열-처리">4. 리스트, 배열 처리</h3>
<pre><code>    @GetMapping(&quot;/ex02List&quot;) // List타입으로 자동 생성되어 여러 개의 파라미터가 넘어와도 하나의 리스트에 다 담긴다.
    public String ex02List(@RequestParam(&quot;ids&quot;)ArrayList&lt;String&gt; ids) {

        log.info(&quot;ids: &quot;+ids);

        return &quot;ex02List&quot;;
    }</code></pre><p>: 리스트 타입의 파라미터를 지정해놓으면, 위의 코드에서 ids 값을 여러 개를 입력을 하도 하나의 리스트에 묶어서 출력이 된다.</p>
<pre><code>
    @GetMapping(&quot;/ex02Array&quot;) //배열타입도 List와 같은 결과.
    public String ex02Array(@RequestParam(&quot;ids&quot;) String[] ids) {
        log.info(&quot;array ids: &quot;+Arrays.toString(ids));

        return &quot;ex02Array&quot;;
    }</code></pre><p>: 배열도 리스트 타입과 마찬가지로 동일하게 처리가 가능하다.</p>
<pre><code>@Data
public class SampleDTOList {

    private List&lt;SampleDTO&gt; list;

    public SampleDTOList() {
        list = new ArrayList&lt;&gt;();
    }
}</code></pre><pre><code>    @GetMapping(&quot;/ex02Bean&quot;) // 여러 개의 객체를 만들고 싶을 때 사용한다. 
    public String ex02Bean(SampleDTOList list) {
        log.info(&quot;list dtos: &quot;+list);
        return &quot;ex02Bean&quot;;
    }</code></pre><p>: 위 코드는 객체 리스트를 사용하여, 여러 개의 객체를 한번에 처리해야 할 때 사용한다.
: SampleDTOList 타입을 파라미터로 사용하는 메서드를 작성하여 주소창에 &#39;?list[0].name=aaa&amp;list[1].name=bbb&#39; 형식으로 입력을 하면, 각각의 객체 형식으로 호출이 가능하다.
: 입력을 할 때, 오류가 발생한다면, &#39;[&#39;=%5B, &#39;]&#39;=%5D로 변경하도록 한다.</p>
<h3 id="5-intibinder">5. @IntiBinder</h3>
<p>: 파라미터 수집을 다른 용어로는 &#39;binding&#39;이라고 한다. 경우에 따라서는 파라미터를 변환해서 처리해야 하는 경우도 존재한다.
: 예를 들어, 주소창에 날짜를 입력할 때, 문자열을 Date형식으로 변환할 때 사용이 가능하다.</p>
<pre><code>    @InitBinder // 날짜 같은 문자열을 Date 타입으로 변환해주는 어노테이션
    public void initBinder(WebDataBinder binder) {
        SimpleDateFormat dataFormat = new SimpleDateFormat(&quot;yyyy-MM-dd&quot;);
        binder.registerCustomEditor(java.util.Date.class, new CustomDateEditor(dataFormat, false));
    }</code></pre><p>: 주소창에 &#39;?dueDate=2022-10-15&#39;과 같이 호출했다면 서버에서는 정상적으로 파라미터를 수집해서 처리한다.</p>
<h3 id="6-datetimeformat">6. @DateTimeFormat</h3>
<p>: @InitBinder 말고도 @DateTimeFormat을 이용해서 날짜 문자열을 Date타입으로 변환이 가능하다.</p>
<pre><code>@Data
public class TodoDTO {

    private String title;

    @DateTimeFormat(pattern = &quot;yyyy/MM/dd&quot;) //@InitBinder 대신 쓸 수 있다. 대신 binder어노테이션은 죽여야 된다.
    private Date dueDate;
}</code></pre><p>: 주소창에 &#39;?dueDate=2022/10/15&#39;과 같이 호출했자면 서버에서는 정상적으로 파라미터를 수집해서 처리한다.
: 단, 이 어노테이션을 사용할 때는 @InitBinder은 죽여야한다.</p>
<h3 id="7-model-데이터-전달자">7. Model: 데이터 전달자</h3>
<p>: Model 객체는 JSP에 컨트롤러에서 생성ㅇ된 데이터를 담아서 전달하는 역할을 하는 존재이다. 
:리스트 페이지 번호를 파라미터로 전달받고, 실제 데이터를 View로 전달해야 하는 경우, 파라미터들에 대한 처리 후 결과를 전달해야 하는 경우에 많이 쓰인다.</p>
<h3 id="8-modelattribute">8. @ModelAttribute</h3>
<p>: @ModelAttribute는 강제로 전달받은 파라미터를 Model에 담아서 전달하도록 할 때 필요한 어노테이션이다.
: int형식의 데이터는 화면까지 전달되지 않으므로, 이 어노테이션을 사용하여 출력이 가능하도록 도와준다.</p>
<pre><code>    @GetMapping(&quot;/ex04&quot;) // @ModelAttribute : int타입의 테이터를 화면까지 전달해주는 어노테이션
                         // 기본 자료형을 사용할 땐 반드시 붙여주어야 한다.
    public String ex04(SampleDTO dto, @ModelAttribute(&quot;page&quot;) int page) {

        log.info(&quot;dto: &quot;+dto);
        log.info(&quot;page: &quot;+page);

        return &quot;/sample/ex04&quot;;
    }</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring] 데이터 변환하기]]></title>
            <link>https://velog.io/@olive_yeong/Spring-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B3%80%ED%99%98%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@olive_yeong/Spring-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B3%80%ED%99%98%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 28 Sep 2022 12:24:17 GMT</pubDate>
            <description><![CDATA[<h3 id="1-propertyediter">1. propertyEditer</h3>
<ul>
<li>양방형 타입 변환, 특정 타입이나 이름의 필드에 적용이 가능하다.<ul>
<li>필드에 이름을 지정해주면, 그 이름인 정보에만 사용이 가능하다.</li>
<li>디폴트 프로퍼티 : 스프링이 기본적으로 제공해주는 프로퍼티.
커스텀 프로퍼티 : 사용자가 직접 구현. propertyEditorSupport를 상속하면 편리하다.</li>
<li>모든 컨트롤러 내에서의 변환 : WebBinderInitializer를 구현 후 등록
특정 컨트롤러 내에서의 변환 : 컨트롤러에 @initBinder가 붙은 메서드를 작성 
[디폴트 property] (<a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/propertyeditors/package-summary.html">https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/propertyeditors/package-summary.html</a>) 
↑이곳에서 기본 프로퍼티들을 확인해볼 수 있습니다.</li>
</ul>
</li>
</ul>
<h3 id="2-converter">2. Converter</h3>
<ul>
<li>단방향 타입 변환 (타입A → 타입B)</li>
<li>property Editor의 단점을 개선하기 위한 것</li>
<li>인스턴스 변수를 사용하지 않는다. (싱글톤으로 사용 가능)</li>
<li>conversionService : 여러 Converter를 등록 가능</li>
<li>모든 컨트롤러 내에서의 변환 : ConfigurableWebBiningInitializer를 설정해서 사용
특정 컨트롤러 내에서의 변환 : 컨트롤러에 @InitBinder가 붙은 메서드를 작성</li>
</ul>
<h3 id="3-formatter">3. Formatter</h3>
<ul>
<li>양방형 타입 변환</li>
<li>바인딩할 필드에 적용한다.</li>
<li>@NumberFormat, @DateFormat</li>
</ul>
<hr>
<h3 id="실습">&lt;실습&gt;</h3>
<p><img src="https://velog.velcdn.com/images/olive_yeong/post/0a95b813-c05d-4379-9d73-adcf6bbf42df/image.png" alt=""></p>
<ol>
<li><p>Controller에서 save메서드에 Bindingresult 객체를 설정해줍니다.</p>
<br>
![](https://velog.velcdn.com/images/olive_yeong/post/a4f53735-01d7-4555-803b-fc263bb5b430/image.png)
</li>
<li><p>그 위에 InitBinder 애노테이션을 설정해주고, 원하는 Date형식을 SimpleDateFormat으로 정해줍니다. 이러면 기본형식인 yyyy/mm/dd로 입력을 하지 않아도 데이터를 인식하고 출력을 해줍니다.</p>
<br>
![](https://velog.velcdn.com/images/olive_yeong/post/aa9d66a0-c47e-49f5-abc9-4a9e3ccbf72f/image.png)</li>
<li><p>객체의 종류에 따라 설정을 달리할 수 있는데, 2번째 binder줄은 String[]객체를 #으로 나눠, 한 개의 요소가 아니라 리스트에 각각의 요소로 넣을 수가 있습니다.</p>
</li>
</ol>
<hr>
<h3 id="풀지-못한-오류">&lt;풀지 못한 오류&gt;</h3>
<p><img src="https://velog.velcdn.com/images/olive_yeong/post/4c663b19-0b22-4f1b-b02b-c1e67ff72c88/image.png" alt="">
sts의 디폴트 인코팅을 UTF-8로 업데이트를 하고, text파일을 저장하려고 했는데
<img src="https://velog.velcdn.com/images/olive_yeong/post/e2b0aa8c-feb7-48a7-be27-1cfa019b0c8c/image.png" alt="">
에러 메시지가 뜨며 저장이 안되고 있다ㅜㅜ restart를 하니 한글도 갑자기 다 깨져버렸는데, 어떻게 해야될지 찾아봐도 안 나오는 상황이다ㅜㅜ
반응이 느린건지 내일 다시 시도를 해봐야겠다.</p>
]]></description>
        </item>
    </channel>
</rss>