<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>king-dong-gun</title>
        <link>https://velog.io/</link>
        <description>백엔드를 공부하고 있는 초보 개발자입니다.</description>
        <lastBuildDate>Wed, 25 Feb 2026 00:55:33 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>king-dong-gun</title>
            <url>https://velog.velcdn.com/images/king-dong-gun/profile/e8705c70-f27d-45be-94bd-4e0633fe709d/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. king-dong-gun. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/king-dong-gun" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Spring 요청값 바인딩 요약 (@PathVariable / @ModelAttribute / @RequestBody)]]></title>
            <link>https://velog.io/@king-dong-gun/Spring-%EC%9A%94%EC%B2%AD%EA%B0%92-%EB%B0%94%EC%9D%B8%EB%94%A9-%EC%9A%94%EC%95%BD-PathVariable-ModelAttribute-RequestBody</link>
            <guid>https://velog.io/@king-dong-gun/Spring-%EC%9A%94%EC%B2%AD%EA%B0%92-%EB%B0%94%EC%9D%B8%EB%94%A9-%EC%9A%94%EC%95%BD-PathVariable-ModelAttribute-RequestBody</guid>
            <pubDate>Wed, 25 Feb 2026 00:55:33 GMT</pubDate>
            <description><![CDATA[<h3 id="1-pathvariable-url-경로">1) <code>@PathVariable</code> (URL 경로)</h3>
<ul>
<li><strong>언제 쓰나:</strong> 특정 “대상(리소스)”을 <strong>명확히 식별</strong>해야 할 때 (1건 조회/수정/삭제)</li>
<li><strong>이유:</strong> URL 자체가 “무슨 대상을 다루는지”를 표현 → 로그/권한/캐시/디버깅이 명확</li>
<li><strong>예시</strong><ul>
<li><code>GET /api/building/qr/setting/1</code> → 1번 조회</li>
<li><code>DELETE /api/building/qr/setting/1</code> → 1번 삭제</li>
<li><code>PATCH /api/building/qr/setting/1</code> → 1번 수정</li>
</ul>
</li>
</ul>
<hr>
<h3 id="2-modelattribute-쿼리스트링폼-필드-→-객체-바인딩">2) <code>@ModelAttribute</code> (쿼리스트링/폼 필드 → 객체 바인딩)</h3>
<ul>
<li><strong>언제 쓰나:</strong> 목록 조회에서 <strong>검색/필터/정렬/페이징 조건</strong>을 여러 개 받을 때</li>
<li><strong>이유:</strong> 조건이 많고 optional이 많아 <strong>DTO로 묶기 편함</strong> + URL로 재현/공유/디버깅 쉬움</li>
<li><strong>예시</strong><ul>
<li><code>GET /api/building/qr/setting?buildingSeq=626&amp;searchText=3층&amp;page=1</code></li>
</ul>
</li>
<li><strong>참고:</strong> 단일 파라미터는 <code>@RequestParam</code>을 많이 씀</li>
</ul>
<hr>
<h3 id="3-requestbody-요청-body-json-등">3) <code>@RequestBody</code> (요청 Body: JSON 등)</h3>
<ul>
<li><strong>언제 쓰나:</strong> <strong>생성/수정</strong>처럼 “저장할 데이터(payload)”를 통째로 보낼 때</li>
<li><strong>이유:</strong> 필드가 많거나 구조가 복잡한 데이터를 URL로 보내기 어렵고, 검증(@Valid)도 쉬움</li>
<li><strong>예시</strong><ul>
<li><code>POST /api/building/qr/setting</code><ul>
<li>Body: <code>{ &quot;buildingSeq&quot;: 626, &quot;placeName&quot;: &quot;3층 복도&quot; }</code></li>
</ul>
</li>
<li><code>PATCH /api/building/qr/setting/1</code><ul>
<li>PathVariable로 대상(1번) + Body로 변경값 전달</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="한-줄-정리">한 줄 정리</h3>
<ul>
<li><strong>PathVariable = “어떤 대상인가(ID)”</strong></li>
<li><strong>ModelAttribute = “조회 조건(필터/페이지/정렬)”</strong></li>
<li><strong>RequestBody = “저장/변경할 내용(payload)”</strong></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[파일 업로드 시 content type application/octet-stream not supported 에러 (415 Error)]]></title>
            <link>https://velog.io/@king-dong-gun/%ED%8C%8C%EC%9D%BC-%EC%97%85%EB%A1%9C%EB%93%9C-%EC%8B%9C-content-type-applicationoctet-stream-not-supported-%EC%97%90%EB%9F%AC-415-Error</link>
            <guid>https://velog.io/@king-dong-gun/%ED%8C%8C%EC%9D%BC-%EC%97%85%EB%A1%9C%EB%93%9C-%EC%8B%9C-content-type-applicationoctet-stream-not-supported-%EC%97%90%EB%9F%AC-415-Error</guid>
            <pubDate>Thu, 09 Jan 2025 07:41:24 GMT</pubDate>
            <description><![CDATA[<p>기존에 있던 등록창에서 파일 업로드 기능을 새로 추가해야해 코드를 리팩토링 하였다.</p>
<p>기존에 있던 데이터들은 <code>json</code> 타입으로 넘어간다.</p>
<pre><code class="language-javascript">var data = Object.assign($(&quot;#formAdd&quot;).serializeObject(), {
    gatewayCluster: $(&quot;#gatewayCluster&quot;).val(),
    status: &quot;ENABLED&quot;,
    methods: makeMethods(),
    apiPolicy: $(&quot;#apiPolicy&quot;).val(),
    billPolicy: $(&quot;#billPolicy&quot;).val(),
    service: $(&quot;#service&quot;).val(),
    engineApi: $(&quot;#engineApi&quot;).val(),
    customRouteUri: $(&quot;#customRouteUri&quot;).val(),
    extras: makeSpringProperties(),
    scopes: $scopes,
    keywords: $(&quot;#keywords&quot;).val()
});

formData.append(&quot;request&quot;, JSON.stringify(data));</code></pre>
<p>여기에 파일 업로드를 추가해야하는데, 파일은 <code>multipart/form-data</code>로 넘겨야 하기 때문에, 따로 <code>formData</code>를 추가했다.</p>
<pre><code class="language-javascript">function completeRegistration() {
        // 1) 중복 체크 및 데이터 검증
        if (globalVars.dupCheckFlag === &quot;N&quot;) {
            alert(&quot;오픈 API URI 중복 체크를 진행 해주세요&quot;);
            return false;
        }
        if (!dataValidation()) return false;

        // 2) JSON 데이터 구성
        var $scopes = [];
        if ($(&quot;#scopeList&quot;).find(&quot;:checked&quot;).val() !== &quot;&quot;) {
            $scopes = $(&quot;#scopeList&quot;).find(&quot;:checked&quot;).map(function (i, d) {
                return { id: d.value };
            }).toArray();
        }

        var data = Object.assign($(&quot;#formAdd&quot;).serializeObject(), {
            gatewayCluster: $(&quot;#gatewayCluster&quot;).val(),
            status: &quot;ENABLED&quot;,
            methods: makeMethods(),
            apiPolicy: $(&quot;#apiPolicy&quot;).val(),
            billPolicy: $(&quot;#billPolicy&quot;).val(),
            service: $(&quot;#service&quot;).val(),
            engineApi: $(&quot;#engineApi&quot;).val(),
            customRouteUri: $(&quot;#customRouteUri&quot;).val(),
            extras: makeSpringProperties(),
            scopes: $scopes,
            keywords: $(&quot;#keywords&quot;).val()
        });

        if (!confirm(&quot;편집 내용을 저장하시겠습니까?&quot;)) return;

        // 3) 파일 가져오기
        const file = document.getElementById(&quot;fileInput&quot;).files[0];
        const formData = new FormData();

        // 4) 파일 존재 시 추가
        if (file) {
            formData.append(&quot;uploadedFile&quot;, file);
        } else if (globalVars.currentFileId) {
            // 기존 파일 유지
            data.fileId = globalVars.currentFileId;
        }

          // 5) 기존 json 추가
        formData.append(&quot;request&quot;, JSON.stringify(data));

        // 6) Ajax multipart/form-data 요청
        $.ajax({
            url: &quot;/my-url&quot;,  // 정확한 백엔드 경로 확인
            type: &quot;POST&quot;,
            data: formData,
            processData: false,    // jQuery가 데이터를 처리하지 않도록 설정
            contentType: false,    // jQuery가 Content-Type 헤더를 설정하지 않도록 설정
            success: function (d) {
                if (d.error) {
                    alert(&quot;오류가 발생했습니다.\n&quot; + d.message);
                    return false;
                }
                alert(&quot;성공적으로 처리되었습니다.&quot;);
                $(&quot;.m_modal&quot;).removeClass(&quot;on&quot;);
                $(&quot;body&quot;).css(&quot;overflow&quot;, &quot;auto&quot;);
                searchPart();  // 예: 목록 갱신 함수
            },
            error: function (xhr, status, err) {
                alert(&quot;업로드 중 오류 발생: &quot; + err);
            }
        });
    }</code></pre>
<p>하지만....</p>
<blockquote>
<p>2025-01-09 14:11:21.496  WARN 1 --- [io-8080-exec-10] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type &#39;application/octet-stream&#39; not supported]</p>
</blockquote>
<p>백엔드 Controller에서 내가 생각한 multipart/form-data로 넘어가지 않는 듯 했다.</p>
<h3 id="이슈">이슈</h3>
<blockquote>
<p>스프링에서 이미지 업로드를 할때 Json 데이터를 Multipart로 같이 보내는 경우 Content-Type을 application/json으로 명시해줘주지 않으면 application/octet-stream not supported 예외가 발생</p>
</blockquote>
<h3 id="해결법">해결법</h3>
<blockquote>
<p>JSON.stringify를 통해 javascript object를 생성하고 blob 객체의 타입을 application/json으로 만들어서 formdata에 append를 한다.</p>
</blockquote>
<p>아래의 코드를</p>
<pre><code class="language-javascript">formData.append(&quot;request&quot;, JSON.stringify(data));</code></pre>
<p>이렇게 수정</p>
<pre><code class="language-javascript">formData.append(&quot;request&quot;, new Blob([JSON.stringify(data)], { type: &quot;application/json&quot; }), &quot;request.json&quot;);</code></pre>
<p>Spring Controller에도</p>
<pre><code class="language-java">    @PostMapping(
            value = &quot;/my-url&quot;,
            consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE
    )</code></pre>
<p><img src="https://velog.velcdn.com/images/king-dong-gun/post/860fb221-b2bc-4df3-ab15-b6fcecd61568/image.png" alt=""></p>
<p>명시적으로 <code>consumes</code>와 <code>produces</code>를 삽입한다.</p>
<h3 id="content-type-헤더와-consumes-설정">Content-Type 헤더와 Consumes 설정</h3>
<h4 id="consumes">Consumes</h4>
<p> 클라이언트가 서버에게 보내는 데이터 타입을 명시한다.</p>
<p><code>@RequestMapping</code>의 <code>consumes</code> 설정과 <code>Content-Type request</code></p>
<p>헤더가 일치할 경우에 URL이 호출된다.</p>
<h4 id="content-type">Content-Type</h4>
<p>HTTP 메시지(요청과 응답 모두)에 담겨 보내는 데이터 형식을 알려주는 헤더이다. 즉, 현재 리퀘스트 또는 리스폰스의 바디에 들어 있는 데이터가 어떤 타입인지를 나타낸다.</p>
<h4 id="http-요청이-get방식인-경우">HTTP 요청이 <code>GET방식</code>인 경우</h4>
<p>무조건 URL 끝에 쿼리스트링(key=value) 형식이기 때문에 </p>
<p><code>Content-Type</code> 헤더가 굳이 필요없으므로 <code>Content-Type</code>은 <code>POST방식</code>이나 <code>PUT방식</code>처럼  <code>BODY</code>에 데이터를 싣어 보낼 때 중요하다.</p>
<p><img src="https://velog.velcdn.com/images/king-dong-gun/post/a2448f0b-928d-4f42-8b54-e50c98696bdb/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/king-dong-gun/post/61d214ab-e09e-4d87-b832-531b3af83266/image.png" alt=""></p>
<blockquote>
<p>이제 매핑이 된다....!!!!</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[XML (Extensible Markup Language)이란?]]></title>
            <link>https://velog.io/@king-dong-gun/XML-Extensible-Markup-Language%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@king-dong-gun/XML-Extensible-Markup-Language%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Fri, 20 Dec 2024 01:46:17 GMT</pubDate>
            <description><![CDATA[<h3 id="xml은-데이터를-구조화하고-교환하기-위한-마크업-언어로-사람이-읽을-수-있으며-기계가-이해할-수-있는-형식으로-데이터를-표현한다-html과-비슷하게-태그-기반으로-데이터를-기술하지만-사용자-정의-태그를-지원하며-데이터의-의미를-정의하는-데-초점을-맞춘다-웹-java-애플리케이션-설정-파일로서-사용이-많이-된다">XML은 데이터를 구조화하고 교환하기 위한 마크업 언어로, 사람이 읽을 수 있으며 기계가 이해할 수 있는 형식으로 데이터를 표현한다. HTML과 비슷하게 태그 기반으로 데이터를 기술하지만, 사용자 정의 태그를 지원하며 데이터의 의미를 정의하는 데 초점을 맞춘다. (웹, Java 애플리케이션 설정 파일로서 사용이 많이 된다)</h3>
<blockquote>
<h4 id="마크업markup언어란">마크업(MarkUp)언어란?</h4>
<p>마크업 언어는 &quot;마크(Mark)&quot;로 둘러싸인 언어로 &quot;태크(Tag)&quot;로 둘러싸였다고도 표현한다. HTML, XML 등의 마크업 언어들은 문서의 구조를 정의하고 쉽게 설명하면 문서의 골격에 해당하는 부분을 작성하는데 사용한다.</p>
</blockquote>
<h3 id="1-특징">1. 특징</h3>
<h4 id="1-데이터-저장-및-교환">1) 데이터 저장 및 교환</h4>
<ul>
<li>XML은 플랫폼 간 데이터 교환을 위해 사용한다.</li>
<li>ex) 웹 서비스에서 서버와 클라이언트 간의 데이터를 전달</li>
</ul>
<h4 id="2-유연한-구조">2). 유연한 구조</h4>
<ul>
<li>태그를 사용자가 정의할 수 있어서 특정 데이터 요구에 맞게 설계가 가능하다.</li>
<li>ex) <code>book</code>, <code>employee</code>등등 이와 같은 태그들을 자유롭게 정의</li>
</ul>
<h4 id="3-계층적-구조">3). 계층적 구조</h4>
<ul>
<li>부모와 자식 관계를 통해 데이터의 계층적 관계를 나타낸다.</li>
<li>ex) <code>root</code>아래에서 여러 자식 태그가 포함</li>
</ul>
<h4 id="4-쉬운-이해">4). 쉬운 이해</h4>
<ul>
<li>직관적이고 텍스트 기반이라 사람이 쉽게 이해가 가능</li>
</ul>
<h4 id="5-플랫폼-독립성">5). 플랫폼 독립성</h4>
<ul>
<li>운영체제나 언어에 상관없이 데이터를 표현하고 교환 가능</li>
</ul>
<h3 id="2-역할">2. 역할</h3>
<h4 id="데이터-저장">데이터 저장</h4>
<ul>
<li>XML파일은 데이터를 저장하고 파일로 기록하는데 사용한다.<h4 id="데이터-전송">데이터 전송</h4>
</li>
<li>네트워크를 통해 데이터를 전송하는데 사용한다. </li>
<li>ex) 웹 서비스<h4 id="구성-설정-파일">구성 설정 파일</h4>
</li>
<li>시스템이나 어플리케이션의 설정 정보를 XML 형식으로 저장한다.</li>
<li>ex) Tomcat의 <code>server.xml</code>, Spring의 <code>applicationContext.xml</code><h4 id="문서-형식-정의">문서 형식 정의</h4>
</li>
<li>XML 스키마 또는 DTD로 XML 문서의 구조와 데이터를 검증 할수 있다.</li>
</ul>
<h3 id="3-구조">3. 구조</h3>
<h4 id="1-선언부">1) 선언부</h4>
<ul>
<li>XML 문서의 첫번째 줄로, 문서의 버전과 인코딩 정보를 표시한다.<pre><code class="language-XML">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</code></pre>
</li>
</ul>
<h4 id="2-루트-요소-root">2) 루트 요소 (root)</h4>
<ul>
<li>XML의 최상위 요소로 모든 데이터가 여기에 포함된다.<pre><code class="language-XML">&lt;root&gt;
  ...
&lt;/root&gt;</code></pre>
</li>
</ul>
<h4 id="3-요소-element">3) 요소 (Element)</h4>
<ul>
<li>데이터를 포함하는 태그, 시작과 종료 태그로 구성된다.<pre><code class="language-XML">&lt;name&gt;King-Dong-Gun&lt;/name&gt;</code></pre>
</li>
</ul>
<h4 id="4-속성-attribute">4) 속성 (Attribute)</h4>
<ul>
<li>요소의 추가 정보를 제공한다. <code>key = &quot;value&quot;</code>의 형식으로 작성<pre><code class="language-XML">&lt;book title=&quot;XML Study&quot; author=&quot;King-Dong-Gun&quot; /&gt;</code></pre>
</li>
</ul>
<h4 id="5-데이터-내용-content">5) 데이터 내용 (Content)</h4>
<ul>
<li>요소 안에 포함된 실제 데이터 값<pre><code class="language-XML">&lt;name&gt;King-Dong-Gun&lt;/name&gt;</code></pre>
</li>
</ul>
<h4 id="6-주석">6) 주석</h4>
<ul>
<li>문서의 가독성을 높이기 위한 설명<pre><code class="language-XML">&lt;!-- Hi Hello Bye GoodBye --&gt;</code></pre>
</li>
</ul>
<h3 id="4-사용-예시">4. 사용 예시</h3>
<ul>
<li>도서 정보를 저장하고 표현</li>
</ul>
<pre><code class="language-XML">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;library&gt;
    &lt;!-- 루트 요소: 도서관 전체 --&gt;
    &lt;book id=&quot;1&quot;&gt;
        &lt;!-- 책 제목 --&gt;
        &lt;title&gt;XML Fundamentals&lt;/title&gt;
        &lt;!-- 책 저자 --&gt;
        &lt;author&gt;John Doe&lt;/author&gt;
        &lt;!-- 책 가격 및 통화 단위 --&gt;
        &lt;price currency=&quot;USD&quot;&gt;29.99&lt;/price&gt;
    &lt;/book&gt;
    &lt;book id=&quot;2&quot;&gt;
        &lt;!-- 두 번째 책 정보 --&gt;
        &lt;title&gt;Advanced XML&lt;/title&gt; &lt;!-- 책 제목 --&gt;
        &lt;author&gt;Jane Smith&lt;/author&gt; &lt;!-- 책 저자 --&gt;
        &lt;price currency=&quot;EUR&quot;&gt;35.00&lt;/price&gt; &lt;!-- 책 가격 및 통화 단위 --&gt;
    &lt;/book&gt;
&lt;/library&gt;</code></pre>
<ul>
<li>Java에서 DOM 파서로 XML을 읽고 데이터를 출력<pre><code class="language-java">import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*;
</code></pre>
</li>
</ul>
<p>public class XMLParserExample {
    public static void main(String[] args) {
        try {
            // XML 파일 로드
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(&quot;library.xml&quot;);</p>
<pre><code>        // 루트 요소 가져오기
        Element root = doc.getDocumentElement();
        System.out.println(&quot;Root Element: &quot; + root.getNodeName());

        // 모든 &lt;book&gt; 요소 가져오기
        NodeList bookList = doc.getElementsByTagName(&quot;book&quot;);
        for (int i = 0; i &lt; bookList.getLength(); i++) {
            Element book = (Element) bookList.item(i);
            System.out.println(&quot;Book ID: &quot; + book.getAttribute(&quot;id&quot;));
            System.out.println(&quot;Title: &quot; + book.getElementsByTagName(&quot;title&quot;).item(0).getTextContent());
            System.out.println(&quot;Author: &quot; + book.getElementsByTagName(&quot;author&quot;).item(0).getTextContent());
            Element price = (Element) book.getElementsByTagName(&quot;price&quot;).item(0);
            System.out.println(&quot;Price: &quot; + price.getTextContent() + &quot; &quot; + price.getAttribute(&quot;currency&quot;));
            System.out.println();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}</code></pre><p>}</p>
<pre><code>
- 출력결과
```yml
Root Element: library
Book ID: 1
Title: XML Fundamentals
Author: John Doe
Price: 29.99 USD

Book ID: 2
Title: Advanced XML
Author: Jane Smith
Price: 35.00 EUR</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[(javaScript) TypeError: document.getElementById(...).value is not a function 해결방법]]></title>
            <link>https://velog.io/@king-dong-gun/javaScript-TypeError-document.getElementById....value-is-not-a-function</link>
            <guid>https://velog.io/@king-dong-gun/javaScript-TypeError-document.getElementById....value-is-not-a-function</guid>
            <pubDate>Wed, 18 Dec 2024 00:33:23 GMT</pubDate>
            <description><![CDATA[<p>이 에러 로그는 <code>document.getElementById()</code>가 잘못 사용되었을 때 발생한다.</p>
<p><img src="https://velog.velcdn.com/images/king-dong-gun/post/550229aa-9b23-4fb4-b391-379feabb24f6/image.png" alt=""></p>
<p>문제의 원인은 <code>document.getElementById()</code>의 결과는 <code>HTMLInputElement</code> 이라고 나오는데, <code>value</code>는 <strong>속성(property)</strong>이지 <strong>함수</strong>가 아니기 때문에 <code>document.getElementById(&quot;id값&quot;)</code> 뒤에 <code>.value();</code> 와 같은 괄호 형태의 함수를 사용하여 나오는 에러이다.</p>
<p>그렇기 때문에 <code>.value()</code> 대신 <code>.value</code> 를 사용하면 오류가 해결된다.</p>
<blockquote>
<p><em>보통은 다 오타이다.....</em></p>
</blockquote>
<ol>
<li><code>.value</code></li>
</ol>
<ul>
<li>속성(property)으로, HTML 요소의 값을 가져오거나 설정할 때 사용한다,</li>
<li>주로 <code>input</code>, <code>textarea</code>, <code>select</code>와 같은 폼 요소에서 사용한다.</li>
<li>순수 JavaScript에서 HTML 요소의 값을 읽거나 설정할 때 사용한다.<pre><code class="language-javascript">const value = document.getElementById(&quot;inputId&quot;).value;
document.getElementById(&quot;inputId&quot;).value = &quot;new value&quot;;
</code></pre>
</li>
</ul>
<pre><code>
2. `.value()`
- 함수(method) 호출 방식
- 주로 JavaScript 객체나 라이브러리에서 값을 가져오거나 처리하는 메서드 형태로 사용한다.
&gt; 예를 들어, jQuery에서는 `.val()` 함수를 사용하여 요소의 값을 가져온다.

```javascript
const value = $(&quot;#inputId&quot;).val(); // jQuery 사용
</code></pre><h4 id="결론">결론</h4>
<p>HTML 표준 DOM 요소에서는 <code>.value</code>를 사용하고,
라이브러리(jQuery 등)에서는 제공되는 <code>.value()</code> 또는 <code>.val()</code> 메서드를 사용한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[java.lang.NoClassDefFoundError 오류]]></title>
            <link>https://velog.io/@king-dong-gun/java.lang.NoClassDefFoundError-%EC%98%A4%EB%A5%98</link>
            <guid>https://velog.io/@king-dong-gun/java.lang.NoClassDefFoundError-%EC%98%A4%EB%A5%98</guid>
            <pubDate>Thu, 05 Dec 2024 06:06:30 GMT</pubDate>
            <description><![CDATA[<h1 id="javalangnoclassdeffounderror"><code>java.lang.NoClassDefFoundError</code></h1>
<aside>
💡

<p><code>java.lang.NoClassDefFoundError</code>는 Java 런타임 환경에서 <strong>클래스를 로드하려고 했으나 실패한 경우</strong> 발생하는 오류이다. 이 오류는 <strong>컴파일 타임</strong>에는 문제가 없었지만, <strong>런타임</strong>에 해당 클래스를 찾을 수 없을 때 발생한다.</p>
</aside>

<h3 id="주요-원인"><strong>주요 원인</strong></h3>
<ol>
<li><strong>클래스가 JAR 파일에 포함되지 않음</strong><ul>
<li>애플리케이션이 실행 중 필요한 클래스를 포함하는 JAR 파일이나 라이브러리가 클래스패스에 없을 때 발생</li>
<li>예: <code>commons-el</code> 의존성이 추가되지 않았거나 JAR 파일에 포함되지 않은 경우.</li>
</ul>
</li>
<li><strong>클래스가 의존성 충돌로 인해 로드되지 않음</strong><ul>
<li>프로젝트에 동일한 이름의 클래스가 여러 의존성(JAR)에서 정의되어 충돌이 발생</li>
</ul>
</li>
<li><strong>컴파일 타임과 런타임 클래스 패스 불일치</strong><ul>
<li>개발 환경에서는 잘 동작하지만, 빌드 후 배포 시 런타임 환경에서 클래스패스 설정이 누락되거나 잘못된 경우 발생</li>
</ul>
</li>
<li><strong>클래스가 동적으로 로드될 때 (Reflection)</strong><ul>
<li><code>Class.forName()</code> 또는 <code>ClassLoader</code>를 사용해 동적으로 클래스를 로드하려는 경우 해당 클래스가 클래스패스에 없다면 발생</li>
</ul>
</li>
<li><strong>JAR 파일 손상</strong><ul>
<li>클래스가 포함된 JAR 파일이 손상되었거나 잘못된 방식으로 패키징된 경우 발생</li>
</ul>
</li>
</ol>
<hr>
<aside>
💡

<h3 id="classnotfoundexception과의-차이점"><strong><code>ClassNotFoundException</code>과의 차이점</strong></h3>
</aside>

<ul>
<li><strong><code>ClassNotFoundException</code></strong>:<ul>
<li><code>Class.forName()</code> 또는 <code>ClassLoader</code> 같은 동적 로딩 메서드에서 클래스가 없을 때 발생.</li>
<li>주로 개발자가 직접 처리 가능한 경우.</li>
</ul>
</li>
<li><strong><code>NoClassDefFoundError</code></strong>:<ul>
<li>런타임 시 JVM이 클래스 파일을 로드하려 했으나 실패.</li>
<li>컴파일 시 문제가 없었더라도 런타임 환경에서만 발생.</li>
</ul>
</li>
</ul>
<blockquote>
<p><code>NoClassDefFoundError</code> 가 발생하면 의존하는 라이브러리의 버전이 서로 맞지 않아 발생하는  경우가 대부분이므로 <code>build.gradle</code> 파일을 확인해보자.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring Boot 배포 war to jar(내장 톰켓 사용) ]]></title>
            <link>https://velog.io/@king-dong-gun/Spring-Boot-%EB%B0%B0%ED%8F%AC-war-to-jar%EB%82%B4%EC%9E%A5-%ED%86%B0%EC%BC%93-%EC%82%AC%EC%9A%A9</link>
            <guid>https://velog.io/@king-dong-gun/Spring-Boot-%EB%B0%B0%ED%8F%AC-war-to-jar%EB%82%B4%EC%9E%A5-%ED%86%B0%EC%BC%93-%EC%82%AC%EC%9A%A9</guid>
            <pubDate>Thu, 05 Dec 2024 06:04:24 GMT</pubDate>
            <description><![CDATA[<h2 id="외장-톰켓을-내장-톰켓으로-변경하기">외장 톰켓을 내장 톰켓으로 변경하기</h2>
<h3 id="war파일을-jar파일로-변경하는-것은-간단하다">.war파일을 .jar파일로 변경하는 것은 간단하다.</h3>
<ol>
<li><strong>build.gradle</strong></li>
</ol>
<pre><code class="language-java">
plugins {    

id &#39;org.springframework.boot&#39; version &#39;2.7.18&#39;    

id &#39;io.spring.dependency-management&#39; version &#39;1.0.11.RELEASE&#39;  

id &#39;java&#39;

// jar로 빌드하므로 war값은 주석처리

// id &#39;war&#39;*

}`

// 그리고 jar 빌드시 추가 설정이 들어간다

compileOnly &#39;org.springframework.boot:spring-boot-starter-tomcat&#39;

runtimeOnly &#39;org.springframework.boot:spring-boot-starter-tomcat&#39;

// =====================================================================

// WAR 플러그인은 2개의 의존 구성을 더한다.
// 1. providedCompile
// 2. providedRuntime
// 이 구성들은 컴파일이나 런타임 시에는 필요하지만 WAR 파일로 배포될 때는 제외된다.
// WAR 파일로 빌드될 때 Spring Boot의 내장 톰캣은 제외되도록 하기 위해 `implementation`이 아닌 `providedRuntime`으로 톰캣 라이브러리가 선언되어 있을 것이다. 이를 제거한다.

// jar 빌드시 필요없는 설정    

//providedRuntime(&#39;org.springframework.boot:spring-boot-starter-tomcat&#39;)
//providedCompile &#39;org.springframework.boot:spring-boot-starter-tomcat&#39;</code></pre>
</aside>

<ol>
<li><strong>SpringBootServletInitializer 상속 제거</strong></li>
</ol>
<pre><code class="language-java">
@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(MyApplication.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}</code></pre>
<ul>
<li><code>SpringBootServletInitializer</code>은?</li>
</ul>
<p><code>SpringBootServletInitializer</code>는 <code>War</code> 파일을 생성하기 위해서 상속받는 클래스 이므로 <code>Jar</code> 로 배포할 것이면 상속 받지 않아도 된다.</p>
<ol>
<li><strong>build 하기</strong></li>
</ol>
<ul>
<li>인텔리제이의 오른쪽 상단 메뉴바의 <code>gradle</code> 버튼을 클릭</li>
</ul>
<p><img src="https://velog.velcdn.com/images/king-dong-gun/post/be0b0e0c-3194-468d-9bdd-a6b72da1bd05/image.png" alt=""></p>
<ul>
<li><code>claen</code> 으로 <code>build &gt; lib</code> 삭제 후 <code>build</code></li>
</ul>
<p><img src="https://velog.velcdn.com/images/king-dong-gun/post/8363282c-9233-4edb-ac33-f58b6545803a/image.png" alt=""></p>
<hr>
<ol>
<li><strong>putty를 이용하여 yml 재설정</strong></li>
</ol>
<aside>
👉

<p>통상적으로 <code>war</code>에서는 <code>webapp</code> 파일을 사용하고 <code>jar</code> 에서는 <code>resources &gt; static</code> 을 사용하므로 파일을 전체적으로 옮겨주었다.</p>
</aside>

<pre><code class="language-java">spring:
  web:
     resources:
     // Spring Boot가 정적 리소스를 제공할 디렉터리를 지정
          static-locations: classpath:/static/   
  thymeleaf:
         // Thymeleaf 템플릿 파일이 위치한 디렉터리를 설정
          prefix: classpath:/templates/
          suffix: .html
          mode: HTML
          encoding: UTF-8
          enabled: true
          cache: false
          check-template-location: true
          servlet:
                content-type: text/html
  jackson:
        // 기본 시간대 설정
          time-zone: Asia/Seoul
  mvc:
          // Spring MVC에서 URL 매칭 전략을 설정
    pathmatch:
        matching-strategy: ant_path_matcher
      // 정적 리소스의 매핑 패턴을 설정
    static-path-pattern: &quot;/**&quot;


apptomo:
         // 비밀번호 강도 설정
  security:
          password:
                  lifetime: 90
                  warn-lifetime-expire-before: 7
                  strength: 10</code></pre>
<hr>
<ol>
<li><strong>.jar 파일 실행!!</strong></li>
</ol>
<p><img src="https://velog.velcdn.com/images/king-dong-gun/post/61336dfa-21d3-42c7-ae09-69d708e87956/image.png" alt=""></p>
<p>.jar 파일이 있는 디렉토리에 접근해 .jar 파일 실행</p>
<pre><code class="language-java">java --add-opens java.base/java.lang=ALL-UNNAMED    
     --add-opens java.base/java.lang.reflect=ALL-UNNAMED   
     -Dspring.config.location=/sw/apptomo/tomcat/yml/application-dev-postgresql.yml  
     -Dspring.profiles.active=dev-postgresql   
     -jar apptomo-portal-4.jar</code></pre>
<aside>

<ol>
<li><p><code>--add-opens java.base/java.lang=ALL-UNNAMED</code>: 일부 라이브러리(예: Spring Framework)가 리플렉션을 통해 비공개 메서드 또는 클래스에 접근해야 할 때 필요</p>
</li>
<li><p><code>--add-opens java.base/java.lang.reflect=ALL-UNNAMED</code>: 리플렉션 작업 중 <code>java.lang.reflect</code> 패키지에 접근할 수 있도록 허용</p>
</li>
<li><p><code>-Dspring.config.location=/sw/apptomo/tomcat/yml/application-dev-postgresql.yml</code>: 애플리케이션 경로를 명시적으로지정</p>
</li>
<li><p><code>-Dspring.profiles.active=dev-postgresql</code>: 특정 프로파일을 활성화하여, 해당 환경에 맞는 설정이 적용</p>
</li>
<li><p><code>-jar apptomo-portal-4.jar</code>: <code>.jar</code>파일 실행</p>
</li>
</ol>
</aside>

<p><img src="https://velog.velcdn.com/images/king-dong-gun/post/f1cdf607-d4ec-4174-8f60-c1f3b995fe13/image.png" alt=""></p>
<p><strong>이렇게 실행이된다!!!!!!</strong></p>
<hr>
<ol>
<li><strong>시큐리티 브레이크 포인트</strong>….</li>
</ol>
<p><img src="https://velog.velcdn.com/images/king-dong-gun/post/68cd939f-9818-45c2-adeb-1e96c1a1b17d/image.png" alt=""></p>
<p>서버 연결은 완료 되었지만, js, css등등 파일들을 못읽는 상황이 발생했다.</p>
<p>이 문제는 Spring Security 설정에서 따로 정적 리소스들을 허용해주지 않았기 때문에 매핑하지 못한다.</p>
<ol>
<li><strong>Spring Securty에서 정적 리소스 허용</strong></li>
</ol>
<pre><code class="language-java">@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers(
        &quot;/res/**&quot;,             // 정적 리소스 허용
        &quot;/resources/**&quot;,
        &quot;/favicon.ico&quot;,
        &quot;/robots.txt&quot;,
        &quot;/prf&quot;);
    super.configure(web);
}</code></pre>
<ol>
<li><strong>HTTP 보안 설정</strong></li>
</ol>
<pre><code class="language-java">// authorizeRequests에서 /res/**를 permitAll()로 추가해야 정적 리소스에 대한 접근을 보장
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers(
                &quot;/res/**&quot;
            &quot;/&quot;,
            &quot;/open/**&quot;,
            &quot;/session&quot;,
            // 추가 경로들
        ).permitAll()
        .anyRequest().authenticated();
}</code></pre>
<ol>
<li><strong>커스텀 ResourceHandler 추가</strong></li>
</ol>
<pre><code class="language-java">    // Spring Boot가 정적 리소스 매핑을 처리하지 못하는 경우 명시적으로 ResourceHandler를 추가
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler(&quot;/res/**&quot;)
                .addResourceLocations(&quot;classpath:/static/res/&quot;)
                .setCachePeriod(cachePeriod);
        registry.addResourceHandler(&quot;/favicon.ico&quot;)
                .addResourceLocations(&quot;classpath:/static/favicon.ico&quot;)
                .setCachePeriod(cachePeriod);
    }</code></pre>
<p><img src="https://velog.velcdn.com/images/king-dong-gun/post/d5259248-e3e5-4a33-9d65-d03aac297233/image.png" alt=""></p>
<hr>
<aside>
👉

<p>이렇게 <code>.war</code> 에서 <code>.jar</code> 로 파일이 변경되면서 내장 톰켓 설정을 완료했다….!</p>
</aside>]]></description>
        </item>
        <item>
            <title><![CDATA[안녕하세요 초짜 개발자입니다.]]></title>
            <link>https://velog.io/@king-dong-gun/%EC%95%88%EB%85%95%ED%95%98%EC%84%B8%EC%9A%94-%EC%B4%88%EC%A7%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9E%85%EB%8B%88%EB%8B%A4</link>
            <guid>https://velog.io/@king-dong-gun/%EC%95%88%EB%85%95%ED%95%98%EC%84%B8%EC%9A%94-%EC%B4%88%EC%A7%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9E%85%EB%8B%88%EB%8B%A4</guid>
            <pubDate>Thu, 27 Jun 2024 09:10:39 GMT</pubDate>
            <description><![CDATA[<p>java~springboot까지 정리.......할게 많다....</p>
]]></description>
        </item>
    </channel>
</rss>