<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>hh_nebula.log</title>
        <link>https://velog.io/</link>
        <description>공부하고 기록하고 복습하고</description>
        <lastBuildDate>Sat, 28 Jan 2023 14:32:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>hh_nebula.log</title>
            <url>https://velog.velcdn.com/images/hh_nebula/profile/7eb4388e-de92-49f1-935d-313060f89998/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. hh_nebula.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hh_nebula" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[디자인 패턴 및 추상 팩토리]]></title>
            <link>https://velog.io/@hh_nebula/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EB%B0%8F-%EC%B6%94%EC%83%81-%ED%8C%A9%ED%86%A0%EB%A6%AC</link>
            <guid>https://velog.io/@hh_nebula/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EB%B0%8F-%EC%B6%94%EC%83%81-%ED%8C%A9%ED%86%A0%EB%A6%AC</guid>
            <pubDate>Sat, 28 Jan 2023 14:32:00 GMT</pubDate>
            <description><![CDATA[<p>백엔드 웹 개발에서 가장 대표적인 MVC 패턴을 제대로 이해하기 위해서는 먼저 소프트웨어 디자인 패턴에 대한 이해가 필요하다.</p>
<h3 id="디자인-패턴이란">디자인 패턴이란?</h3>
<p>디자인 패턴은 처음에는 건축학적 관점에서 출발한 개념이었으나 1994년 <code>GoF</code>의 <code>Design Patterns: Elements of Reusable Object-Oriented Software</code> 를 통해 소프트웨어 설계에서 공통적으로 발생하는 문제에 대한 재사용 가능한 솔루션으로 제시되었다.</p>
<p>물론 완벽한 설계는 없으며 시대의 흐름에 따라 달라질 수 있지만, 시행착오를 통해 스스로 터득해야 할 문제를 정리해둔 솔루션이 있다면 당연히 검토할 가치가 있는 것이다.</p>
<p>GoF의 디자인 패턴은 생성, 구조, 행동, 동시실행 등의 문제에 대해 여러 패턴을 제시하고 있으며 UML 클래스 다이어그램을 이용해 구조를 표현하고 있다.</p>
<p>UML이란 <code>Unified Modeling Language</code> 의 약어로 객체지향 설계와 구현을 지원하기 위해 만들어진 일종의 모델링 언어다. 프로그래밍 언어와 같은 형태는 아니고 시스템 분석, 설계에 필요한 내용을 여러 다이어그램 형태로 정의한 규격이다.</p>
<h3 id="추상-팩토리-패턴이란">추상 팩토리 패턴이란?</h3>
<p>Factory는 &#39;공장&#39;이란 의미로 디자인 패턴에서 객체를 생성하는 역할을 의미한다. &#39;추상적&#39;이라는 의미를 가진 Abstract는 자바의 추상 클래스에서도 사용되는 표현으로 구체적인 내용의 구현을 하위 객체에 위임하는 모델이다. 따라서 추상 팩토리는 객체를 생성하는 것을 별도로 구현하되 관련된 구체적인 구현을 하위 클래스에서 담당하게 하는 설계 모델로 이해할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/hh_nebula/post/7f21d8d0-77dc-4227-a5d7-c22007f38397/image.png" alt=""></p>
<p>객체지향 프로그래밍은 클래스로부터 여러 객체를 생성하고 이들을 활용하는 구조이다. 따라서 프로그램에서 객체를 직접 생성하는 것이 당연하면서도 프로그램에 종속성을 만드는 요인이되기도 한다.</p>
<h3 id="추상-팩토리-예시">추상 팩토리 예시</h3>
<pre><code class="language-java">ProductDao productDao = new ProductDao();
dao.insert(data);</code></pre>
<ul>
<li><p>ProductDao Class
데이터베이스 연동을 구현한 클래스</p>
</li>
<li><p>insert() Method
파라메터로 전달받은 데이터를 데이터베이스에 저장하는 메서드</p>
</li>
</ul>
<p>위 코드는 문제가 없어 보이지만 ProductDao라는 클래스에 대한 종속성을 만들게 된다.</p>
<p>예를 들어 현재 시스템에서 오라클 데이터베이스를 사용하고, ProductDao 클래스 역시 오라클에 맞게 제작된 클래스라 가정하자. 이 경우 데이터베이스를 MySQL 또는 다른 데이터베이스로 교체할 경우 ProductDao를 MySQL에 맞게 다시 구현해야 한다.</p>
<p>그런데 상황에 맞게 오라클 혹은 MySQL에서 실행되어야 한다면 현재 프로그램의 전반적인 구조를 수정할 수밖에 없을 것이다. 추상 팩토리 패턴은 이러한 경우 유용하게 사용할 수 있다. 직접적인 객체 생성 대신 팩토리 클래스에 객체 생성을 위임하는 구조이기 때문이다.</p>
<p>다음 코드는 패턴 구조를 적용한 경우 클라이언트에서 팩토리를 사용하는 부분만 예로 든 것이다. 패턴 적용에 대한 이해를 돕기 위한 것으로 전체 패턴을 구현한 것이 아니다.</p>
<pre><code class="language-java">ProductDao productDao = new ProductDao(&quot;oracle&quot;);
dao.insert(data);</code></pre>
<ul>
<li><p>ProductDao Class
추상 클래스 또는 인터페이스이다. ProductDao 추상 클래스를 상속받는 OracleDao, MySQLDao 등의 클래스가 존재한다.</p>
</li>
<li><p>DAOFactory
오라클이나 MySQL용으로 구현된 ProductDao 타입의 객체를 생성해서 리턴한다.</p>
</li>
</ul>
<p>위의 예시와 같이 생성자의 파라메터로 특정 인스턴스를 요청할 수도 있고 .xml 설정 파일 등을 이용해 코드 수정 없이 확장 가능한 구조도 가능하다.</p>
<p>최근에는 개발자가 직접 애플리케이션 실행을 위한 모든 환경을 설계하고 개발하는 형태가 아니라 프레임워크, 컨테이너 기반으로 개발하기 때문에 직접적인 패턴 구현에 대한 고민은 줄어들었다. 하지만 소프트웨어 설계에서 디자인 패턴은 여전히 중요한 개념이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[빌드 도구]]></title>
            <link>https://velog.io/@hh_nebula/%EB%B9%8C%EB%93%9C-%EB%8F%84%EA%B5%AC</link>
            <guid>https://velog.io/@hh_nebula/%EB%B9%8C%EB%93%9C-%EB%8F%84%EA%B5%AC</guid>
            <pubDate>Fri, 27 Jan 2023 18:45:47 GMT</pubDate>
            <description><![CDATA[<h3 id="빌드-도구란">빌드 도구란?</h3>
<p>프로그래밍을 배우는 입장에서는 단순한 실습 예제 소스로 구성된 프로그램을 만들기 때문에 코드 이외의 부분에 대해서는 고려할 사항이 거의 없다. 그러나 실제 프로젝트에서는 직접 작성해야 할 수십 개의 클래스와 여러 외부 라이브러리로 구성되는 경우가 많다. 또한 프로그램의 실제 구현 코드 외에 테스트를 위한 코드도 존재하며 프로젝트 규모가 커질수록 개발자에게 비효율적인 여러 요소가 있을 수 있다.</p>
<p>복잡한 프로젝트의 소스를 체계적으로 컴파일하고 관련 라이브러리의 버전이나 종속성 관리를 쉽게 도와줄 방법이 필요하다.</p>
<p>이를 위해 가장 오래된 자바 빌드 도구로는 Ant가 있으며 2004년에는 아파치 프로젝트로 Maven이 새롭게 나오게 되었다. 이후 오랜 기간 Maven은 절대 다수가 사용하는 자바 빌드 도구가 되었으며 특히 스프링 프레임워크 개발에서 기본 빌드 도구로 활용되었다. 시간이 지남에 따라 좀 더 유연하면서도 복잡한 처리를 쉽게 하기 위한 요구 사항의 증대로 2012년 Gradle이 나오게 되었고 안드로이드 앱 개발의 기본 빌드 도구가 되었다. 현재 Maven과 Gradle이 가장 대표적인 빌드 도구다.</p>
<h3 id="빌드-도구-선택하기">빌드 도구 선택하기</h3>
<p>지금 당장은 Maven과 Gradle 중 무엇을 선택해도 전혀 상관없다. 또한 빌드 도구를 잘 사용하기 위해서는 많은 경험이 필요하고 프로젝트 규모가 어느 정도 되어야 제대로 된 활용이 가능하기 때문에 초급 개발자 수준에서는 빌드 도구 선택에 대해 지나치게 고민할 필요가 없다.</p>
<p>스프링 프레임워크나 안드로이드의 경우 개발도구에서 기본적으로 빌드 관련 설정과 실행을 연계해주기 때문에 빌드 도구가 잘 이해되지 않는다고 어려워할 필요도 없다.</p>
<p>각각의 빌드 도구에 대한 특징은 다음과 같다.</p>
<ul>
<li><p>설정방식
Maven은 빌드 설정을 <code>pom.xml</code> 파일에 작성하는데, XML 구조이기 때문에 프로젝트가 커질수록 스크립트의 내용이 길어지고 가독성이 떨어지는 문제가 있다.
Gradle은 Groovy라고 하는 JVM 기반 언어를 통해 프로그램 구조로 설정한다. 따라서 훨씬 적은 양의 스크립트로 짧고 간결하게 작성할 수 있다.</p>
</li>
<li><p>다중 프로젝트
Maven은 다중 프로젝트에서 특정 설정을 다른 모듈에서 사용하려면 상속을 받아야 한다.
Gradle은 설정 주입 방식을 사용하여 다중 프로젝트에 적합하다.</p>
</li>
<li><p>개발환경
안드로이드 프로젝트는 기본적으로 Gradle을 사용한다.
스프링 프레임워크 기반 프로젝트는 Maven, Gradle 중에 선택할 수 있다.
이클립스는 Maven에 친화적이고 IntelliJ는 Gradle에 친화적이다.</p>
</li>
</ul>
<p>프로젝트 규모나 설정 조건에 따라 다르기는 하지만 Gradle이 Maven보다 10~100배 성능 향상이 있다고 알려져 있다. 이에 따라 Maven도 지속적으로 사용되고 있지만 최신 프로젝트에서는 Gradle 사용 비중이 더 높다.</p>
<h3 id="리포지토리">리포지토리</h3>
<p>빌드 도구를 사용하는 주요 목적 두 가지는 컴파일/실행 설정과 라이브러리 설정이다. 이 중에서도 라이브러리 설정은 꼭 알아두어야 한다.</p>
<p>만일 필요한 라이브러리가 많을 경우 개발자가 일일이 해당 라이브러리의 홈페이지를 찾아 다운로드하고 복사하는 과정을 수행하는 것이 상당히 번거로울 것이다. 필요한 라이브러리가 또 다른 라이브러리를 참조하는 경우 해당 라이브러리도 필요한데 이들 관계는 또 어떻게 할 것이며, 버전에 따른 업데이트나 특정 버전 설치 등 너무나도 복잡한 문제가 발생하게 된다.</p>
<p>빌드 도구를 사용하면 꼭 필요한 핵심 라이브러리만 설정 파일에 등록해두면 해당 라이브러리에서 필요로 하는 다른 라이브러리는 자동으로 함께 설치되기 때문에 신경 쓸 필요가 없다는 이점이 있다.</p>
<p>리포지토리는 이러한 라이브러리를 통합 보관하는 일종의 저장소이며, 설정 파일의 내용을 참고해 해당 라이브러리를 글로벌 저장소로부터 로컬 저장소로 다운로드한 다음 프로젝트에 복사하는 과정을 거쳐 사용하게 된다. 해당 라이브러라기 로컬 저장소에 있다면 인터넷에서 다운로드하지 않고 바로 사용할 수 있다. 필요에 따라서는 개발 회사가 자신들에게 필요한 라이브러리만 저장하거나 자체 라이브러리 저장을 위한 저장소를 두고 사용하기도 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JSTL]]></title>
            <link>https://velog.io/@hh_nebula/JSTL</link>
            <guid>https://velog.io/@hh_nebula/JSTL</guid>
            <pubDate>Fri, 27 Jan 2023 14:58:38 GMT</pubDate>
            <description><![CDATA[<h3 id="jstl이란">JSTL이란?</h3>
<p>JSTL은 JSP에서 스크립트릿, 즉 자바 코드 블록을 사용하지 않고 HTML 형식을 유지하면서 조건문, 반복문, 간단한 연산과 몇몇 유용한 기능을 손쉽게 사용할 수 있도록 지원하기 위해 만들어진 표준 커스텀태그 라이브러리다.</p>
<p>커스텀 태그에서 살펴본 것처럼 서버에서만 해석할 수 있는 구조로 인해 디자이너와의 협업에 불편한 부분이 있고, 개발 과정에서 UI 확인을 위해 서버를 통해야만 하는 비효율적인 문제가 존재한다. 이러한 문제점은 모바일 환경 중심의 front-end 개발 트렌드와는 다소 거리가 있다.</p>
<p>규격상 JSTL은 core, xml, II8N(다국어 처리), 데이터베이스, 함수 등으로 구성되어 있으나 뷰 중심의 JSP 구현에는 core 정도만 사용된다.</p>
<h3 id="jstl-라이브러리-설치">JSTL 라이브러리 설치</h3>
<p>JSTL은 표준 규격으로만 존재하기 때문에 개발에 적용하기 위해서는 실제 구현된 라이브러리가 필요하다. 여러 구현 버전이 있지만 Apache Standard Taglib를 주로 사용한다.</p>
<ul>
<li>maven의 경우</li>
</ul>
<pre><code class="language-xml">&lt;dependency&gt;
    &lt;groupId&gt;javax.servlet&lt;/groupId&gt;
    &lt;artifactId&gt;jstl&lt;/artifactId&gt;
&lt;/dependency&gt;</code></pre>
<p>pom.xml에 dependency를 추가한다.</p>
<pre><code class="language-java">&lt;%@ taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot;%&gt;</code></pre>
<p>jsp에 taglib 지시어를 추가한다.</p>
<h3 id="core-라이브러리">core 라이브러리</h3>
<p>core 라이브러리는 변수 처리, 흐름 제어, URL 관리, 출력 등 가장 기본적인 기능을 구현해둔 라이브러리다. 제일 많이 사용되는 기능인 흐름 제어와 관련된 태그를 살펴본다.</p>
<pre><code>&lt;!-- 조건문 --&gt;
&lt;c:if test=&quot;조건식&quot;&gt;
    조건식이 참일 경우 출력될 내용
    else if는 없다.
&lt;/c:if&gt;

&lt;!-- 반복문 --&gt;
&lt;c:forEach var=&quot;user&quot; items=&quot;${userInfo}&quot; varStatus=&quot;status&quot;&gt;
    index : ${status.index}
    count : ${status.count}
    name : ${user.name}
&lt;/c:forEach&gt;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[커스텀 태그와 EL]]></title>
            <link>https://velog.io/@hh_nebula/%EC%BB%A4%EC%8A%A4%ED%85%80-%ED%83%9C%EA%B7%B8%EC%99%80-EL</link>
            <guid>https://velog.io/@hh_nebula/%EC%BB%A4%EC%8A%A4%ED%85%80-%ED%83%9C%EA%B7%B8%EC%99%80-EL</guid>
            <pubDate>Fri, 27 Jan 2023 14:38:06 GMT</pubDate>
            <description><![CDATA[<h3 id="커스텀-태그란">커스텀 태그란?</h3>
<p>커스텀 태그란 사용자 정의 태그를 의미한다. 즉 스크립트릿 사용을 줄이고 태그와 같은 형태로 프로그램 코드를 대체하거나 재활용 가능한 구조를 통해 태그 라이브러리로 활용하고자 개발된 규격이다. 외형적인 형태는 XML(HTML) 태그 구조이지만 서블릿 형태로 변환될 때 자바 코드로 변경되어 퉁합되는 방식이다.</p>
<p>커스텀 태그를 사용하기 위해서는 <code>taglib</code> 지시어를 사용하여 커스텀 태그가 어디에 정의되어 있는지를 먼저 선언해야 하며 태그에 사용할 접두어를 지정해야 한다.</p>
<p>커스텀 태그는 잘 사용하면 매우 편리하지만 커스텀 태그 자체가 서버에서 해석되는 구조이며, 프로젝트가 특정 커스텀 태그에 종속될 수 있다는 문제 때문에 커스텀 태그를 직접 만드는 방식은 점차 줄어들고 있다.</p>
<blockquote>
<p>대신 커스텀 태그 기술로 만들어진 JSTL이 자바 웹 개발에 꼭 필요한 요소가 되었다.</p>
</blockquote>
<pre><code class="language-java">&lt;!-- 태그파일의 위치와 해당 태그를 사용할 때 작성할 접두어를 지정 --&gt;
&lt;%@ taglib tagdir=&quot;/WEB-INF/tags&quot; prefix=&quot;m&quot; %&gt;

&lt;!-- 접두어 m 을 사용하여 태그를 작성 --&gt;
&lt;m:printData product=&quot;web&quot; /&gt;</code></pre>
<ul>
<li>태그파일로 정의된 커스텀 태그를 사용하여 <code>/WEB-INF/tags/printData.tag</code> 파일로부터 태그 정의를 가져온다.</li>
<li>m은 태그 앞에 붙일 접두어로 태그 파일명이 태그이름이 된다.</li>
</ul>
<p>앞의 useBean 액션 역시 커스텀 태그 기술을 통해 만들어진 것으로 기본 JSP 규격에 포함되어 있기 때문에 표준 액션이라 불린다.</p>
<h3 id="el이란">EL이란?</h3>
<p>표현 언어는 주로 EL이라고 불리며 현재 페이지의 자바 객체 혹은 application, session, request, page와 같은 scope object에 저장된 자바 빈 객체를 손쉽게 접근하고 사용할 수 있게 해준다. 기본적으로 데이터를 표현하기 위한 용도로 설계되었지만 제한된 객체 참조가 가능하며 해당 객체의 메서드 호출도 가능하다.</p>
<p>EL은 단순한 출력 외에도 사칙연산, 비교연산, 논리연산, 3항 연산 등을 지원한다. 이러한 연산기능은 핵심 로직의 구현보다는 상황에 따라 출력값을 변경하는 정도의 용도로 사용하는것이 좋다.</p>
<p>EL의 장점은 다음과 같다.</p>
<ul>
<li>간단한 구문으로 쉽게 변수 또는 객체를 참조할 수 있다.</li>
<li>데이터가 없거나 null 객체를 참조할 때 에러가 발생하지 않는다.</li>
</ul>
<p>EL을 통해 scope object에 저장된 자바 빈 객체를 참조하는 방법은 다음과 같다.</p>
<pre><code>${저장이름.변수명}

&lt;h2&gt;사용자 정보&lt;/h2&gt;
이름 : ${userInfo.name}</code></pre><ul>
<li>세션에 <code>userInfo</code> 라는 이름으로 저장된 객체가 있으므로 해당 객체를 사용하여 접근한다.</li>
</ul>
<p><code>User</code> 클래스에 <code>name</code> 변수가 <code>private</code>로 선언되어 있을 경우 직접 참조가 불가능하다. 이때 클래스에 <code>getter()</code> 메서드가 있다면 EL에서는 해당 변수명을 사용하여 내부적으로 <code>getter()</code>를 호출할 수 있다.</p>
<p>기타 연산과 배열, 맵 등 데이터 접근은 다음과 같다.</p>
<pre><code class="language-java">${10 + 20} // 사칙연산
${10 * 20} // 논리연산
${true &amp;&amp; false} // 논리연산
${10 &gt;= 20} // 논리연산
${userInfo.name == &quot;여름&quot; ? &quot;냉면&quot; : &quot;호빵&quot;} // 3항연산

${arrayList[0]} // 배열
${hashMap[&quot;name&quot;]} // 맵</code></pre>
<p>EL은 기본적으로 모든 scope에서 자바 빈 객체를 찾는다. 만일 특정 scope만을 대상으로 참조할 경우 <code>내장객체명Scope.속성이름</code>으로 사용할 수 있다.</p>
<pre><code>${requestScope.userInfo.name}
${sessionScope.userInfo.name}</code></pre><p>만일 scope object에 속성으로 저장된 것이 아니라 request의 파라메터로 전달된 값의 경우라면 위 형식처럼 참조할 수 없다. 이 경우에는 <code>request.getParameter(&quot;pramName&quot;)</code> 과 같이 사용하며 EL에서는 <code>${param.paramName}</code> 으로 사용한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[액션 태그와 자바 빈]]></title>
            <link>https://velog.io/@hh_nebula/%EC%95%A1%EC%85%98-%ED%83%9C%EA%B7%B8%EC%99%80-%EC%9E%90%EB%B0%94-%EB%B9%88</link>
            <guid>https://velog.io/@hh_nebula/%EC%95%A1%EC%85%98-%ED%83%9C%EA%B7%B8%EC%99%80-%EC%9E%90%EB%B0%94-%EB%B9%88</guid>
            <pubDate>Thu, 26 Jan 2023 16:15:39 GMT</pubDate>
            <description><![CDATA[<h3 id="액션-태그란">액션 태그란?</h3>
<p>액션 태그란 JSP에서 객체 생성과 공유, 페이지 이동과 전달, 태그 파일 작성 등에 필요한 기능을 제공하는 일종의 커스텀 태그다. 표준 액션이라고도 불리며 커스텀 태그 기반이지만 별도의 taglib 지시어 사용 없이 jsp 접두어를 사용한다.</p>
<p>액션 태그는 JSP에서 프로그램적인 요소를 많이 구현하거나 컨트롤러로 활용할 때 유용하다. 이러한 기능은 기본적으로 서블릿에서도 가능하지만 개발자가 직접 코들르 구현하여 처리해야 한다. 반면 액션 태그는 JSP 파일에서 커스텀 태그의 구조적인 특징을 살려 HTML 형태로 프로그램 요소를 처리할 수 있기 때문에 간편하다는 장점이 있다.</p>
<p>요즘은 JSP의 역할이 축소되어 있어 액션 태그의 실무 활용은 권장되지 않아 간략히 살펴본다.</p>
<table>
<thead>
<tr>
<th>액션 태그</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>jsp:forward</td>
<td>request와 response 객체를 포함해 다른 페이지로 포워드함</td>
</tr>
<tr>
<td>jsp:include</td>
<td>다른 페이지의 실행 결과를 포함시킴</td>
</tr>
<tr>
<td>jsp:useBeans</td>
<td>자바 빈즈 객체를 생성하거나 불러옴</td>
</tr>
<tr>
<td>jsp:setProperty</td>
<td>자바 빈즈 객체의 속성에 값을 할당함</td>
</tr>
<tr>
<td>jsp:getProperty</td>
<td>자바 빈즈 객체의 속성값을 출력함</td>
</tr>
<tr>
<td>jsp:param</td>
<td>include, forward 액션 사용 시 파라메터 값을 수정하거나 추가함</td>
</tr>
</tbody></table>
<h3 id="java-bean">Java Bean</h3>
<p>객체지향 프로그래밍의 핵심 콘셉트는 컴포넌트 모델로, 프로그램 모듈화를 위해 컴포넌트를 사용한다. 따라서 컨테이너 기반으로 운영되는 시스템에서는 여러 객체를 활용하기 위하여 단순하면서도 정영화된 구조를 통해 동일한 방식으로 객체를 다루는 방법을 제공할 수 있어야 한다.</p>
<p>자바 빈은 자바의 재활용 가능한 컴포넌트 모델을 말하는 것으로, 웹 개발에만 국한된 개념이 아니며 POJO라고 하는 단순한 구조를 가진다. POJO란 특정 기술이나 프레임워크에 종속하지 아니하고 기본 생성자와 멤버 변수에 대한 getter setter 메서드를 제공하고 직렬화 할 수 있는 자바 클래스를 의미한다.</p>
<p><img src="https://velog.velcdn.com/images/hh_nebula/post/e0a0b506-9694-4352-9671-c0a18487500f/image.png" alt=""></p>
<p>예를 들어 데이터베이스의 테이블 구조와 연동되어 데이터를 표현하기 위한 클래스를 엔티티 클래스 혹은 DO라고 하는데 기본적으로 테이블 칼럼에 해당하는 private 멤버 변수와 getter setter 메서드로 구성할 수 있다.</p>
<p>자바 빈 구조는 다음과 같다.</p>
<ul>
<li>parameter가 없는 기본 생성자로 구성된다.</li>
<li>파일 혹은 네트워크를 통해 객체를 주고받을 수 있는 직렬화 구조가 가능하다.</li>
<li>getter setter 메서드를 통해 멤버 변수에 접근한다.</li>
</ul>
<h3 id="java-bean-class">Java Bean Class</h3>
<p>다음은 회원 관리를 위한 Member 클래스를 자바 빈 구조로 만든 것이다.</p>
<pre><code class="language-java">public class MemberBean {

    private String id;
    private String password;
    private String email;
    private int age;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}</code></pre>
<p>getter/setter 메서드의 이름은 get/set + 대문자로 시작되는 변수명의 형태를 사용한다. 기본적으로 인자를 받아 현재 멤버 변수에 값을 대입하거나 현재 값을 리턴하는 구조이다. 메서드 내에서 추가적으로 필요한 기능을 구현할 수 있으며 이러한 구조는 <code>객체지향에서 캡슐화의 한 형태</code> 이기도 하다.</p>
<blockquote>
<p>스프링 빈이란 스프링 프레임워크의 경우에도 컨테이너 기반으로 객체의 생성과 소멸 등을 관리하게 되는데 이러한 객체를 스프링 빈이라고 한다. 이러한 객체는 컨테이너를 통해 공유하거나 참조할 수 있다.</p>
</blockquote>
<h3 id="usebean-액션">useBean 액션</h3>
<p>JSP에서 자바 빈 객체를 생성하거나 참조하기 위한 액션이다. 매우 유용한 기능이지만 JSP를 단순히 뷰 역할로만 사용한다면 사용할 일이 없다.</p>
<p>기본적인 동작 방식은 다음과 같다.</p>
<ol>
<li>useBean을 이용해 만든 객체의 범위는 지정하는 속성인 scope에 주어진 id의 객체가 있는지 확인한다.</li>
<li>객체가 없다면 새로 객체를 생성하고 해당 scope에 저장한다.</li>
</ol>
<p>기본 구문과 사용 예는 다음과 같다.</p>
<pre><code class="language-html">&lt;jsp:useBean id=&quot;instanceName&quot; scope=&quot;page | request | session | application&quot;
class=&quot;packageName.className&quot; type=&quot;packageName.className&quot;
beanName=&quot;packageName.className&quot;&gt;
&lt;/jsp:useBean&gt;</code></pre>
<ul>
<li>id
자바 빈을 특정 scope에 저장하거나 가져올 때 사용하는 이름이며, 현재 페이지에서는 해당 인스턴스를 참조하기 위한 변수명이 된다.</li>
<li>scope
해당 클래스 타입의 객체를 저장하거나 가지고 오는 범위로 내장객체의 일부다.</li>
<li>class
생성하거나 참조하려는 객체의 클래스명이며 반드시 패키지명까지 명시해야 한다. 추상 클래스나 인터페이스는 사용할 수 없다.</li>
<li>type
특정 타입의 클래스를 명시할 때 사용한다. 추상 클래스나 인터페이스, 일반 클래스가 될 수 있으며 class 속성의 클래스에서 상속 혹은 구현이 이루어져야 한다.</li>
<li>beanName
type과 beanName 사용을 통해 class 속성을 대체할 수 있다.</li>
</ul>
<h3 id="usebean의-활용">useBean의 활용</h3>
<p>HTML 폼에서 입력한 값을 자바 객체로 연동할 때 useBean을 주로 활용한다. 예를 들어 회원가입 페이지에서 아이디, 이름, 전화번호, 주소 등 여러 정보를 입력하고 가입하는 경우, 입력값을 받아 Member 객체에 넣고 이를 데이터베이스에 저장하기 위한 메서드 호출에 인자로 전달해야 한다.</p>
<p>이 때 useBean 액션을 사용하면 다음 코드와 같이 간단한 처리가 가능하다.</p>
<pre><code class="language-html">&lt;jsp:useBean id=&quot;m&quot; class=&quot;com.my.Member&quot; /&gt;
&lt;jsp:setProperty name=&quot;m&quot; property=&quot;*&quot; /&gt;

&lt;%
   MemberDao dao = new MemberDao();
   dao.insertDb(m);
%&gt;</code></pre>
<ul>
<li>page scope로 새로운 Member 클래스 인스턴스를 생성한 후 m이라는 이름으로 속성에 저장한다.</li>
<li>setProperty는 HTML <code>&lt;form&gt;</code> 태그의 name 속성값을 해당 객체의 setter 메서드를 이용해 저장한다.</li>
<li>property 속성에는 멤버 변수명 혹은 <code>*</code>을 사용해 전체 변수를 한 번에 지정할 수 있다.</li>
</ul>
<h3 id="include-액션">include 액션</h3>
<p>include 액션은 include 지시어와 마찬가지로 다른 페이지를 포함한다는 점에서 동일하지만 처리 과정에서 차이가 있다. include 지시어에서는 include된 파일 구조를 모두 포함해 하나의 파일로 컴파일한 다음 처리한다. 반면 include 액션은 include된 파일을 각각 호출해 처리된 결과만 포함해 보여주는 형식이다.</p>
<p>만약 <code>main.jsp</code>에서 <code>header.jsp</code>를 포함한다고 할 때 include 지시어는 두 파일을 합쳐 <code>main_jsp.java</code>로 만든 다음 서블릿 형태로 등록한다. 하지만 include 액션의 경우 <code>main_jsp.java</code>와 <code>header_jsp.java</code>의 두 파일을 각각 컴파일하고 서블릿 형태로 등록하게 된다.</p>
<p>다음 예제 코드는 include 액션을 사용하여 <code>main.jsp</code>에 <code>header.jsp</code>를 포함시킨 경우로, <code>main.jsp</code>를 호출하면 <code>header.jsp</code>의 실행 결과가 포함되어 출력된다.</p>
<pre><code class="language-html">&lt;!-- main.jsp --&gt;
&lt;jsp:include page=&quot;header.jsp&quot;&gt;
    &lt;jsp:param name=&quot;title&quot; value=&quot;My Homepage&quot; /&gt;
&lt;/jsp:include&gt;

&lt;!-- header.jsp --&gt;
&lt;h2&gt;&lt;%= request.getParameter(&quot;title&quot;) %&gt;&lt;/h2&gt;</code></pre>
<ul>
<li><code>main.jsp</code>에서 <code>header.jsp</code>를 include할 때 <code>&lt;jsp:param&gt;</code>에서 title을 통해 My Homepage라는 값을 전달한다. 그리고 <code>header.jsp</code>는 <code>&lt;h2&gt;</code> 부분에서 전달받은 제목을 출력하는 형태가 된다.</li>
</ul>
<h3 id="forward-액션">forward 액션</h3>
<p>forward 액션은 클라이언트 요청을 다른 페이지로 전환하는 액션으로 리디렉션 <code>response.sendRedirect()</code>과 기능적으로 유사하다. 클라이언트 요청과 다른 새로운 페이지 혹은 서블릿으로 이동하는 점은 두 방법이 동일하다고 할 수 있지만 내부적으로는 차이가 있다.</p>
<p>리디렉션은 서버가 클라이언트에게 새로운 페이지로 다시 접속하도록 응답을 보내고, 응답을 받은 클라이언트가 다시 새로운 페이지로 접속하는 방식이다. 하지만 forward 액션은 클라이언트가 새롭게 접속하는 것이 아니라 서버에서 내부적으로 새로운 페이지로 이동하고 그 페이지의 내용을 클라이언트에게 응답으로 전달한다.</p>
<p>단순한 페이지 이동이 필요한 경우라면 리디렉션이 적합하다. 하지만 최초 request를 유지하거나 request의 setAttribute()로 속성값을 저장한 경우에 이를 유지하면서 페이지를 이동하려면 forward 액션을 사용해야 한다. include 액션과 마찬가지로 파라미터의 추가가 가능하다.</p>
<p>JSP를 뷰로 사용하는 경우 forward 액션을 사용할 일은 없으며 주로 서블릿 컨트롤러에서 <code>request.getRequestDispatcher.forward()</code>와 같이 사용하게 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[템플릿 데이터와 스크립트 요소]]></title>
            <link>https://velog.io/@hh_nebula/%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%99%80-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9A%94%EC%86%8C</link>
            <guid>https://velog.io/@hh_nebula/%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%99%80-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9A%94%EC%86%8C</guid>
            <pubDate>Thu, 19 Jan 2023 12:46:56 GMT</pubDate>
            <description><![CDATA[<h3 id="템플릿-데이터란">템플릿 데이터란?</h3>
<p>템플릿 데이터란 JSP의 화면 구성요소를 말한다. 시작 부분의 page 지시어를 제외하면 JSP 파일의 전반적인 구조는 HTML의 문서구조를 따른다. 따라서 일반적인 HTML 파일처럼 CSS, 자바스크립트도 사용할 수 있다.</p>
<p>기본적으로 HTML5를 사용하며 문서 구조 중심으로 간략하게 작성하고 데이터 표현은 JSTL과 EL을 사용한다. 화면 디자인을 위해 자체적인 CSS 정의 이외에도 Bootstrap과 같은 라이브러리를 사용할 수 있으며, REST API 호출을 위해 Axios 같은 자바스크립트 라이브러리 역시 사용할 수 있다.</p>
<p>다만 React, Vue와 같은 자바스크립트 요소는 프론트엔드 개발 기술로 JSP와 함께 사용하지 않는다.</p>
<h3 id="스크립트-요소">스크립트 요소</h3>
<p>JSP는 HTML과 자바 코드를 섞어 사용할 수 있는데, 이때 사용되는 자바 코드를 스크립트 요소라고 한다. 현재는 JSP 파일에서 직접적인 자바 코드는 거의 사용하지 않지만 기본적인 내용은 이해하고 있어야 한다.</p>
<p>JSP에서 스크립트를 사용하기 위한 태그는 다음과 같다.</p>
<p><code>&lt;%! %&gt;</code> 선언 태그</p>
<ul>
<li>JSP가 서블릿 코드로 변환될 때 <code>_jspService()</code> 메서드 안에 들어가게 되므로 JSP에서는 일반 자바 코드와 달리 멤버 변수나 메서드 선언은 기본적으로 불가능하다.</li>
<li>멤버 변수나 메서드 선언이 필요하다면 사용할 수는 있으나 권장하지 않는다.</li>
</ul>
<p><code>&lt;%= %&gt;</code> 표현 태그</p>
<ul>
<li>웹 브라우저를 통해 클라이언트에 전달될 자바 표현식을 포함한다.</li>
<li>out.println()의 인자로 적합한 모든 자바 코드가 가능하다.</li>
<li>사칙연산, 메서드 호출, 변숫값 출력 등에 사용된다.</li>
<li>EL로 대체할 수 있다.</li>
</ul>
<pre><code class="language-java">&lt;h2&gt;&lt;%= member.getUserName() %&gt;&lt;/h2&gt;
&lt;%= java.time.LocalDateTime.now() %&gt;</code></pre>
<p><code>&lt;% %&gt;</code> 스크립트릿 태그</p>
<ul>
<li>모든 자바코드의 사용이 가능하다. 단, <code>_jspService()</code> 메서드 내에 포함되는 것을 고려해야 한다.</li>
<li>서블릿 코드로 변환될 때 모든 HTML은 out.write() 형태로 변경된다.</li>
<li>HTML과 스크립트릿을 중간에 섞어 사용하는 것도 가능하다.</li>
<li>MVC 패턴 적용과 JSTL + EL로 대체할 수 있다.</li>
</ul>
<p>다음은 로그인 페이지에서 입력한 이름을 가져와 화면에 출력한 다음 사용자 목록을 for 문을 이용해 출력하는 부분의 JSP 코드이다. for 문에서 out.println()을 이용해 이름과 이메일을 출력하지 않고 표현 태그를 사용한다는 점을 주의한다.</p>
<pre><code class="language-java">&lt;% String name = request.getParameter(&quot;userName&quot;); %&gt;

&lt;h2&gt;&lt;%= name %&gt;&lt;/h2&gt;
&lt;hr&gt;

&lt;table&gt;
    &lt;% for(Member member : memberList) { %&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;%= member.name %&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= member.email %&gt;&lt;/td&gt;
        &lt;/tr&gt;
    &lt;% } %&gt;
&lt;/table&gt;</code></pre>
<ul>
<li>request.getParameter()는 HTTP 파라메터 값을 가져온다.</li>
<li>반복문을 사용할 때 자바코드와 HTML 혼용이 가능하다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JSP 지시어]]></title>
            <link>https://velog.io/@hh_nebula/JSP-%EC%A7%80%EC%8B%9C%EC%96%B4</link>
            <guid>https://velog.io/@hh_nebula/JSP-%EC%A7%80%EC%8B%9C%EC%96%B4</guid>
            <pubDate>Thu, 19 Jan 2023 11:49:26 GMT</pubDate>
            <description><![CDATA[<h3 id="지시어란">지시어란?</h3>
<p>지시어는 JSP 파일의 속성을 기술하는 요소로, JSP 컨테이너에 해당 페이지를 어떻게 처리해야 하는지를 전달하는 내용을 담고 있다. 지시어는 크게 page, include, taglib으로 나눌 수 있으며, 각각의 속성이 다르다.</p>
<p>기본 형식은 다음과 같다.</p>
<pre><code>&lt;%@ 지시어 속성=&quot;값&quot; %&gt;</code></pre><h3 id="page-지시어">page 지시어</h3>
<p>page 지시어는 현재 JSP 페이지를 컨테이너에서 처리하는데 필요한 각종 속성을 기술하기 위해 사용하며 소스코드 맨 앞에 위치한다.</p>
<p>page 지시어의 구문과 사용 형식은 다음과 같다.</p>
<pre><code class="language-java">&lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
    pageEncoding=&quot;UTF-8&quot; import=&quot;java.util.*&quot; errorPage=&quot;error.jsp&quot; %&gt;</code></pre>
<ul>
<li>language
현재 페이지의 스크립트 언어를 지정하는 속성이다. 스펙상 다른 언어도 가능하지만 자바를 기본 언어로 한다.</li>
<li>contextType
현재 페이지의 파일 형식을 지정하는 속성이다. 클라이언트 요청에 응답할 때 전달하는 HTTP 헤더 정보가 된다.</li>
<li>pageEncoding
JSP 파일을 컨테이너가 처리할 때 사용하느 캐릭터 인코딩을 지정하는 속성이다. 올바른 한글 처리를 위해서는 UTF-8로 지정해야 한다.</li>
<li>import
JSP 파일 내에서 자바 코드를 직접 사용하는 경우 일반 자바 코드와 마찬가지로 클래스에 대한 패키지 import가 필요하다.</li>
<li>errorPage
현재 JSP 요청 처리 중에 에러가 발생하는 경우 서버 에러를 클라이언트에 전달하지 않고 별도의 페이지에서 처리하기 위한 속성이다. JSP에서 에러 페이지 설정을 넣는 것보다는 서버 설정을 사용하는 것을 권장한다.</li>
</ul>
<h3 id="include-지시어">include 지시어</h3>
<p>include 지시어는 다른 파일을 포함하기 위한 지시어로, 사용된 위치에 특정 파일(HTML, jsp)을 불러온다. 컨테이너에서는 포함된 파일을 하나로 처리하며 자바 소스를 생성한 뒤 서블릿으로 컴파일한다. 즉 include에 사용된 파일의 내용을 모두 포함한 하나의 서블릿 코드로 생성되어 컴파일되는 것이다.</p>
<p>포함되는 파일의 경우 해당 파일을 직접 요청해서 실행하는 것이 아니라면 page 지시어, HTML 기본 태그 구성요소 등 개별 구성요소를 갖출 필요는 없다.</p>
<p>include 지시어는 원하는 위치에 자유롭게 사용할 수 있으며 다음과 같이 사용한다.</p>
<pre><code class="language-java">&lt;%@ include file=&quot;파일 위치&quot; %&gt;</code></pre>
<ul>
<li>file
포함하고자 하는 파일의 경로를 지정하며 상대 경로, 절대 경로를 사용할 수 있다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hh_nebula/post/6e193e95-74ac-4321-8d27-e303a72f908b/image.png" alt=""></p>
<h3 id="taglib-지시어">taglib 지시어</h3>
<p>taglib 지시어는 JSP의 태그 확장 매커니즘인 커스텀 태그를 사용하기 위한 지시어이다.</p>
<p>taglib 지시어의 구문과 사용 형식은 다음과 같다.</p>
<pre><code class="language-java">&lt;%@ taglib ( uri=&quot;태그 라이브러리 경로&quot; 혹은 tagdir=&quot;태그 파일 경로&quot; ) prefix=&quot;태그 접두어&quot; %&gt;</code></pre>
<ul>
<li>uri
태그 라이브러리 위치로 태그를 정의하고 있는 .tld 파일 경로를 나타낸다.</li>
<li>tagdir
태그 파일로 태그를 구현한 경우 태그 파일 경로를 나타낸다.</li>
<li>prefix
해당 태그를 구분해서 사용하기 위한 접두어다.</li>
</ul>
<p>다음은 태그 파일로 커스텀 태그를 구현한 예시로 <code>[WEB-INF/tags]</code> 폴더에 있는 <code>printData.tag</code> 파일에 태그에서 처리할 내용이 작성되어 있다.</p>
<pre><code class="language-java">&lt;%@ taglib tagdir=&quot;/WEB-INF/tags&quot; prefix=&quot;m&quot; %&gt;
...
&lt;h2&gt;&lt;m:printData /&gt;&lt;/h2&gt;</code></pre>
<ul>
<li>접두어 m을 이용하여 printData.tag 태그를 사용한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JSP 개요]]></title>
            <link>https://velog.io/@hh_nebula/JSP-%EA%B0%9C%EC%9A%94</link>
            <guid>https://velog.io/@hh_nebula/JSP-%EA%B0%9C%EC%9A%94</guid>
            <pubDate>Thu, 19 Jan 2023 11:00:01 GMT</pubDate>
            <description><![CDATA[<p>JSP는 서블릿의 화면단 처리의 어려움을 해결하기 위해 등장하였으며, HTML과 데이터를 조합하기 위해 다음과 같은 특징과 구성요소를 가진다.</p>
<h3 id="jsp의-특징">JSP의 특징</h3>
<ul>
<li>HTML 페이지에 자바 코드를 직접 사용한다.</li>
<li>서블릿 컨테이너에 의해 관리되는 내장객체의 생명 주기를 이용하여 페이지 간 속성을 관리한다.</li>
<li>커스텀 태그 기술을 사용하여 코드를 태그화(action, JSTL 등)한다.</li>
<li>EL을 통해 데이터를 표현한다.</li>
</ul>
<p>즉 JSP는 서블릿에서 데이터 표현의 불편함을 해결하기 위해 나온 뷰 템플릿 기술의 하나로, HTML 형식의 문서 구조에 자바 코드 혹은 다른 전용 표기법을 사용해 프로그램 요소를 쉽게 구현할 수 있도록 도와준다. 내부적으로는 서블릿으로 변환되어 실행되는 구조다.</p>
<h3 id="jsp의-구성요소">JSP의 구성요소</h3>
<ul>
<li>지시어</li>
<li>액션</li>
<li>템플릿 데이터</li>
<li>스크립트 요소</li>
<li>커스텀 태그와 EL</li>
</ul>
<p>각각의 구성요소는 고유의 표기법과 속성을 가지지만 서블릿 형태의 소스로 변환되는 과정에서 자바 코드로 바뀌게 된다.</p>
<h3 id="jsp의-동작과정">JSP의 동작과정</h3>
<p>JSP는 기본적으로 HTML 문서의 텍스트 파일 형식을 가지지만 컴파일된 JSP는 단순한 파일이 아니라 컨테이너에서 서블릿 객체로서 관리된다. 다시 말해 컴파일이 완료되면 JSP는 더이상 파일로부터 처리되는 구조가 아니라 컨테이너에 로드된 서블릿으로 동작하는 구조가 되는 것이다. 따라서 서블릿 컨테이너는 JSP 파일을 서블릿 구조의 .java 소스코드로 변환하여 컴파일을 수행한다.</p>
<p><img src="https://velog.velcdn.com/images/hh_nebula/post/3485f2dd-d270-4d3e-a40d-f5ab93cb0646/image.png" alt=""></p>
<ol>
<li>hello.jsp 소스코드를 작성하고 웹 애플리케이션을 배포한다.</li>
<li>클라이언트 요청에 컨테이너는 해당 .jsp의 클래스 변환 여부를 확인한다.</li>
<li>변환되지 않았다면 hello_jsp.java 파일을 생성하고 .class로 컴파일한다.</li>
<li>jspInit() 메서드를 통해 클라이언트 요청을 처리한다.</li>
<li><code>_jspService()</code> 메서드를 통해 클라이언트 요청을 처리한다.</li>
<li>컨테이너 종료 혹은 관리 도구에 의해 서블릿 jspDestroy() 호출로 종료된다.</li>
</ol>
<h3 id="jsp의-장점">JSP의 장점</h3>
<ul>
<li>HTML 파일에 자바 기술을 거의 무한대로 사용할 수 있으며, 비교적 쉽게 프로그래밍할 수 있다.</li>
<li>커스텀 태그 라이브러리 등 JSP 개발에 도움이 되는 확장 태그 구조를 사용할 수 있다.</li>
<li>서블릿으로 변환되어 실행되므로 서블릿 기술의 장점을 모두 가진다.</li>
<li>MVC 패턴, 스프링 프레임워크 등 잘 설계된 구조를 적용할 수 있어 체계가 잡히면 개발 생산성이 향상되고 성능이 보장된다.</li>
<li>모든 개발이 서버에서 이루어지므로 개발의 집중화를 통한 효율이 있을 수 있다.</li>
</ul>
<h3 id="jsp의-단점">JSP의 단점</h3>
<ul>
<li>화면 구송요소를 변경하면 JSP &gt; Java &gt; Class &gt; Servlet 실행 과정을 거치므로 개발 과정에서 사소한 UI 변경일지라도 매번 확인하는 데 시간이 소요된다.</li>
<li>개발자와 디자이너 간 역할 분담에 제약이 있다.</li>
<li>JSP 파일의 화면 디자인 확인에도 반드시 서블릿 컨테이너의 실행이 필요하다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Servlet 코드 분석]]></title>
            <link>https://velog.io/@hh_nebula/%EC%84%9C%EB%B8%94%EB%A6%BF-%EC%BD%94%EB%93%9C-%EB%B6%84%EC%84%9D</link>
            <guid>https://velog.io/@hh_nebula/%EC%84%9C%EB%B8%94%EB%A6%BF-%EC%BD%94%EB%93%9C-%EB%B6%84%EC%84%9D</guid>
            <pubDate>Thu, 19 Jan 2023 10:23:44 GMT</pubDate>
            <description><![CDATA[<h3 id="서블릿-기본-구조">서블릿 기본 구조</h3>
<pre><code class="language-java">import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(&quot;/hello&quot;)
public class HelloServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // ...
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // ...
    }

}
</code></pre>
<ul>
<li><p>@WebServlet 어노테이션
현재 클래스가 서블릿 클래스라는 것을 컨테이너에 알리고 URL Mapping을 진행한다.</p>
</li>
<li><p>doGet()
GET 요청을 처리하는 메서드</p>
</li>
<li><p>doPost()
POST 요청을 처리하는 메서드</p>
</li>
</ul>
<h3 id="doget">doGet()</h3>
<p>GET 요청을 처리하는 메서드로 request, response를 parameter로 한다. 
ServletException과 IOException을 throws로 하기 있기 때문에 호출하는 쪽에서 예외처리를 해줘야 한다.</p>
<pre><code class="language-java">@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    response.getWriter().append(&quot;served at: &quot;).append(request.getContextPath());
}</code></pre>
<ul>
<li>getWriter()
java.io.PrintWriter 클래스 타입의 객체를 리턴한다.</li>
<li>request.getContextPath()
웹 애플리케이션 경로를 리턴하는 메서드<pre><code class="language-java">@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
  response.setContentType(&quot;text/html; charset=utf-8&quot;);
  PrintWriter out = response.getWriter();
  out.append(&quot;&lt;!DOCTYPE html&gt;&quot;).append(&quot;&lt;html&gt;&quot;).append(&quot;&lt;head&gt;&quot;)...
}</code></pre>
</li>
<li>응답 콘텐츠 타입 설정과 한글 추력을 위해 response.setContentType() 메서드를 사용한다.</li>
<li>PrintWriter는 출력 스트림으로 클라이언트에 전달할 출력문 작성에 사용된다.</li>
<li>response.getWriter()로 출력 스트림을 가져온다.</li>
<li>출력 스트림을 이용해 HTML 형식으로 데이터와 결합해 출력한다.</li>
</ul>
<h3 id="dopost">doPost()</h3>
<p>POST 요청을 처리하는 메서드로 단순히 doGet()을 호출하도록 되어있다. REST API 구현이 아닌 일반 서블릿 구현이라면 GET, POST를 내부적으로 동일하게 처리한다. 물론 GET, POST를 구분해 처리해야하는 경우라면 당연히 별도의 코드로 구성할 수 있다.</p>
<pre><code class="language-java">@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    doGet(request, response);
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[페이지 이동과 정보 공유 시나리오]]></title>
            <link>https://velog.io/@hh_nebula/%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%9D%B4%EB%8F%99%EA%B3%BC-%EC%A0%95%EB%B3%B4-%EA%B3%B5%EC%9C%A0-%EC%8B%9C%EB%82%98%EB%A6%AC%EC%98%A4</link>
            <guid>https://velog.io/@hh_nebula/%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%9D%B4%EB%8F%99%EA%B3%BC-%EC%A0%95%EB%B3%B4-%EA%B3%B5%EC%9C%A0-%EC%8B%9C%EB%82%98%EB%A6%AC%EC%98%A4</guid>
            <pubDate>Thu, 19 Jan 2023 08:28:26 GMT</pubDate>
            <description><![CDATA[<h3 id="로그인">로그인</h3>
<p>로그인 후 세션을 이용해 사용자 이름을 저장하고 메인 화면으로 이동하는 경우</p>
<ol>
<li>클라이언트가 로그인한다.</li>
<li>컨트롤러는 request.getParameter()를 통해 클라이언트의 id와 password를 확인한다.</li>
<li>로그인 정보가 맞을 경우 사용자 이름이나 기타 정보를 세션에 저장한다.</li>
<li>메인 화면으로 리디렉션 한다.</li>
</ol>
<pre><code class="language-java">// Controller
session.setAttribute(&quot;name&quot;, &quot;홍길동&quot;);
response.sendRedirect(&quot;/main.jsp&quot;);</code></pre>
<pre><code class="language-html">&lt;!-- main.jsp --&gt;
&lt;div id=&quot;name&quot;&gt;${name}&lt;/div&gt;</code></pre>
<h3 id="게시판-목록">게시판 목록</h3>
<p>데이터베이스 연동을 통해 리스트 형태의 데이터를 저장하고 JSP에서 사용하는 경우</p>
<ol>
<li>컨트롤러는 DB로부터 게시판의 첫 번째 페이지 데이터를 가지고 온다.</li>
<li>request에 리스트 형태로 데이터를 저장한다.</li>
<li>목록 화면으로 포워딩한다.</li>
</ol>
<pre><code class="language-java">// Controller
List&lt;Notice&gt; noticeList = dao.getNoticeList();
request.setAttribute(&quot;noticeList&quot;, noticeList);
request.getRequestDispatcher(&quot;/notice.jsp&quot;).forward(request, response);</code></pre>
<p>session과 달리 request에 저장된 데이터는 페이지 리디렉션을 이용하면 전환할 때 데이터가 소멸되므로 포워딩 방식을 사용해야 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[속성 관리]]></title>
            <link>https://velog.io/@hh_nebula/%EC%86%8D%EC%84%B1-%EA%B4%80%EB%A6%AC</link>
            <guid>https://velog.io/@hh_nebula/%EC%86%8D%EC%84%B1-%EA%B4%80%EB%A6%AC</guid>
            <pubDate>Thu, 19 Jan 2023 08:20:45 GMT</pubDate>
            <description><![CDATA[<h3 id="속성-관리">속성 관리</h3>
<p>컨테이너는 서블릿 관리를 위해 몇몇 객체를 자동으로 생성하고 유지하는데, 이러한 객체 중 속성 관리 기능을 제공하며 특정 범위 동안 유지되는 객체를 Scope Object 라고 한다. 각각의 객체는 관리 목적에 따라 별도의 메서드로 구현된 기능을 가지고 있고 공통적으로 <code>key-value</code> 형태의 Map 자료구조를 가진다.</p>
<p>이를 활용하면 페이지 간, 사용자 간 데이터 공유가 가능하다. JSP 역시 서블릿으로 변환되기 때문에 동일하다고 볼 수 있으며, useBean 액션의 scope에 사용되는 page, request, session, application이 여기에 해당한다.</p>
<p>이러한 객체는 각각 생성, 소멸 시기가 정해져 있고 서로 다른 JSP, 서블릿 간의 데이터 전달이나 공유를 위한 용도로 활용된다.</p>
<h3 id="scope-object-종류-및-특징">Scope Object 종류 및 특징</h3>
<p><img src="https://velog.velcdn.com/images/hh_nebula/post/b216fa28-ef8d-4fe4-bdf7-abd1eadbc9bc/image.png" alt=""></p>
<p>Request와 Session을 주로 활용하게 되며 모든 사용자가 공유하거나 웹 애플리케이션 전체에서 참조가 필요한 경우 Web Context를 사용할 수 있다.</p>
<p>이러한 객체는 속성을 저장하고 참조하기 위해 다음 메서드가 공통적으로 제공된다.</p>
<pre><code class="language-java">setAttribute(String name, Object value); // 속성 저장
Object getAttribute(String name); // 속성 참조</code></pre>
<ul>
<li>name : 속성을 저장하고 참조하기 위한 값</li>
<li>속성은 Object 타입으로 모든 자바 클래스 타입이 가능하다.</li>
<li>getAttribute()의 리턴은 Object이므로 적절한 형변환이 필요하다.</li>
</ul>
<p>```java
String name = &quot;홍길동&quot;;
request.setAttribute(&quot;name&quot;, name);
String name = (String) request.getAttribute(&quot;name&quot;);</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[정보공유]]></title>
            <link>https://velog.io/@hh_nebula/%EC%A0%95%EB%B3%B4%EA%B3%B5%EC%9C%A0</link>
            <guid>https://velog.io/@hh_nebula/%EC%A0%95%EB%B3%B4%EA%B3%B5%EC%9C%A0</guid>
            <pubDate>Thu, 19 Jan 2023 00:23:30 GMT</pubDate>
            <description><![CDATA[<h3 id="정보공유">정보공유</h3>
<p>WWW는 비연결형 구조의 HTTP를 사용하기 때문에 페이지 요청과 응답이 완료되면 연결이 유지되지 않는다. 따라서 클라이언트가 다른 페이지를 요청할 때 부가적인 정보가 없다면 서버는 클라이언트의 현재 상태를 알 수 없기 때문에 처음 접속한 것과 마찬가지로 인식할 수밖에 없다.</p>
<p>이러한 문제를 해결하기 위해 사용하는 방법으로 URL rewriting, 쿠키, 세션이 있다.</p>
<h3 id="url-rewriting">URL rewriting</h3>
<p>HTTP의 Query String을 이용하는 방식으로 URL에 파라미터를 추가해 서버로 요청하는 형식이다. 이 방식은 정보 유지를 위해 파라미터를 매 페이지마다 확인하고 계속 추가해주어야 하며 복잡한 정보 유지는 어렵다는 문제점이 있다.</p>
<pre><code class="language-URL">https://www.example.com/page/page?param1=value&amp;param2=value....</code></pre>
<h3 id="쿠키">쿠키</h3>
<p>쿠키란 클라이언트에 저장되는 작은 정보를 의미한다. 서버의 요청에 의해 브라우저가 저장하게 되며 서버가 요청할 때 제공하는 형식이다. 쿠키의 특징은 다음과 같다.</p>
<ul>
<li>파일로 클라이언트의 컴퓨터에 저장되는 방식이며 보안상 문제가 있을 수 있다.</li>
<li>광고 혹은 기타 목적으로 사용자의 이용 행태 추적에 이용될 수 있으며, 이러한 목적의 경우 사용자 정보 활용 동의가 필요하다.</li>
<li>연속되는 페이지 이동에 대한 정보 저장보다는 재방문 등의 확인 용도로 많이 사용된다.</li>
<li><code>name=value</code> 형식이며 유효 기간, 요청 경로, 도메인 지정 등의 부가 속성을 포함한다.</li>
<li>주로 자바스크립트를 통해 처리하지만 HttpOnly 설정으로 서버에서만 사용할 수 있도록 설정 가능하다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hh_nebula/post/c5fd9598-60e3-4a01-9b22-3713e3fd0c1f/image.png" alt=""></p>
<ol>
<li>서버에서 쿠키를 생성한다.</li>
<li>쿠키를 응답 헤더에 넣어 클라이언트로 전송한다.</li>
<li>웹 브라우저는 쿠키를 하드 디스크 혹은 브라우저 메모리에 저장한다.</li>
<li>쿠키에 지정된 경로에 요청 시 받은 쿠키를 서버에 전송한다.</li>
</ol>
<ul>
<li>서블릿에서 쿠키를 저장하는 방법<pre><code class="language-java">response.addCookie(new Cookie(&quot;name&quot;, &quot;Hong Gil Dong&quot;));
response.addCookie(new Cookie(&quot;tel&quot;, &quot;010-1234-1234&quot;));
response.addCookie(new Cookie(&quot;email&quot;, &quot;gildong@naver.com&quot;));</code></pre>
위의 코드는 HTTP 응답으로 클라이언트에 전달된다.</li>
</ul>
<h3 id="세션">세션</h3>
<p>세션은 클라이언트가 웹 애플리케이션 서버에 접속할 때 서버 쪽에 생성되는 공간으로 내부적으로는 세션 아이디를 통해 참조된다. 즉 브라우저는 서버에 접속할 때 발급받은 세션 아이디를 기억하고 서버는 해당 세션 아이디로 할당된 영역에 접근하는 형식이다.</p>
<ul>
<li>세션 유효 시간이나 브라우저 종료 전까지 유지되므로 서로 다른 페이지에서도 정보 공유가 가능하다.</li>
<li>로그인 유지, 장바구니, 컨트롤러 구현 등에서 다양하게 사용된다.</li>
<li>사용자마다 생성되는 공간으로, 동시에 많은 사용자가 세션을 통해 대량의 데이터를 관리한다면 충분한 메모리를 비롯한 세션 관리 대책이 필요하다.</li>
</ul>
<p>세션이라는 개념은 자바 웹 개발에만 있는 개념이 아니며 Scope Object 중 하나로 속성 관리와 함께 자바 웹 개발에서 중요한 개념이니 잘 알아둬야 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[페이지 이동]]></title>
            <link>https://velog.io/@hh_nebula/%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%9D%B4%EB%8F%99</link>
            <guid>https://velog.io/@hh_nebula/%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%9D%B4%EB%8F%99</guid>
            <pubDate>Thu, 19 Jan 2023 00:23:13 GMT</pubDate>
            <description><![CDATA[<p>웹 프로그래밍에서 서블릿이 주로 사용되는 영역은 MVC 패턴 중 컨트롤러에 해당한다. 컨트롤러는 사용자의 요청을 받아 데이터베이스와 연동 등의 작업을 처리한 다음 결과에 따라 적절한 페이지로 전환해주는 기능을 담당한다. 이때 페이지 이동과 함께 페이지 간 정보 공유 기법에 대한 이해가 필요하다.</p>
<h3 id="페이지-이동">페이지 이동</h3>
<p>컨트롤러에서 사용자 요청을 처리한 다음에는 적절한 뷰로 이동할 수 있어야 한다. 이때 뷰에서 보여줄 데이터를 포함해서 이동해야 하는 경우와 그렇지 않아도 되는 경우가 있다.</p>
<p>데이터를 포함하지 않는 경우 해당 페이지로 바로 리디렉션할 수 있다. 혹은 세션에 데이터를 저장한 경우라면 세션이 유효한 동안 모든 페이지에서 세션 정보를 참조할 수 있어 리디렉션을 통해서도 데이터 참조가 가능하다.</p>
<p>JSP, 서블릿 모두 <code>response.sendRedirect()</code> 를 사용할 수 있다.</p>
<pre><code class="language-java">response.sendRedirect(&quot;main.jsp&quot;);</code></pre>
<p>데이터를 포함하는 경우 request 속성으로 데이터를 넣은 후 원하는 페이지로 포워딩해야 한다. 데이터 활용 목적에 따라 session이나 application을 사용할 수도 있으며 여러 데이터를 포함하는 것도 가능하다.</p>
<p>데이터를 포함하여 포워딩할 경우 아래와 같다</p>
<ul>
<li>JSP<pre><code class="language-java">&lt;%
 request.setAttribute(&quot;key&quot;, value);
 pageContext.forward(&quot;userInfo.jsp&quot;);
%&gt;</code></pre>
</li>
<li>Servlet<pre><code class="language-java">doGet(...) {
  ...
  request.setAttribute(&quot;key&quot;, value);
  RequestDispatcher dispatcher = request.getRequestDispatcher(&quot;userInfo.jsp&quot;);
  dispatcher.forward(request, response);
}</code></pre>
</li>
<li>Spring
인자로 전달된 모델 객체에 원하는 데이터를 저장하고 뷰 페이지 이름을 리턴한다.
리턴되는 문자열 값은 뷰 페이지의 이름이며 확장자는 생략한다.<pre><code class="language-java">@GetMapping(&quot;userinfo&quot;)
public String getMemberInfo(int id, Model model) {
  ...
  model.addAttribute(&quot;key&quot;, value);
  return &quot;userInfo&quot;;
}</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Servlet Class 생명 주기]]></title>
            <link>https://velog.io/@hh_nebula/Servlet-Class-%EC%83%9D%EB%AA%85-%EC%A3%BC%EA%B8%B0</link>
            <guid>https://velog.io/@hh_nebula/Servlet-Class-%EC%83%9D%EB%AA%85-%EC%A3%BC%EA%B8%B0</guid>
            <pubDate>Wed, 18 Jan 2023 09:34:03 GMT</pubDate>
            <description><![CDATA[<h3 id="서블릿의-생명주기">서블릿의 생명주기</h3>
<p>서블릿은 컨테이너에 의해 동작하므로 객체의 생성 및 종료 과정도 컨테이너 안에서 이루어진다. 이와 같이 객체의 생성에서 종료에 이르는 과정을 생명 주기라고 하며, 개발자는 필요에 따라 해당 생명 주기 안에서 적절한 기능을 구현할 수 있어야 한다.</p>
<ul>
<li>또한 웹의 특성상 비연결 구조로 인해 웹 페이지 간 데이터 공유가 되지 않는 문제 해결을 위해 컨테이너에 의해 생성되고 관리되는 특별한 객체인 Scope Object를 잘 활용할 수 있어야 한다.</li>
</ul>
<p>서블릿 클래스는 기본적으로 doGet(), doPost()와 같이 HTTP 요청 메서드에 따라 필요한 메서드를 오버라이딩해 구현하며, 서블릿 컨테이너에 의해 객체의 생성과 소멸 등이 관리되므로 필요에 따라 특정 생명 주기 이벤트에 동작하는 메서드를 구현하기도 한다.</p>
<p><img src="https://velog.velcdn.com/images/hh_nebula/post/ff908586-4652-483d-954c-b315ad7d98c2/image.png" alt=""></p>
<ol>
<li>사용자 URL 요청에 따른 서블릿을 실행한다.</li>
<li>이때 서블릿 인스턴스가 생성되지 않았다면 인스턴스를 생성한 후 init() 메서드를 호출한다.</li>
<li>이미 객체가 생성되어 있는 경우라면 각 요청별로 서블릿 컨테이너에서 스레드를 생성해 서블릿의 service() 메서드를 호출한다.</li>
<li>사용자 요청에 따라 doGet(), doPost() 등의 메서드를 호출한다.</li>
<li>서블릿 컨테이너의 종료를 포함해 서블릿 변경 등 기존 서블릿을 종료해야 할 때 destroy() 메서드를 호출한다.</li>
</ol>
<h3 id="servlet-초기화--init">Servlet 초기화 : init()</h3>
<p>클라이언트의 요청이 들어오면 컨테이너는 해당 서블릿이 메모리에 있는지 확인한다. 해당 서블릿이 메모리에 없다면 서블릿을 메모리에 적재해야 하는데 이 때 서블릿의 init() 메서드가 호출되며 각종 초기화 작업을 수행한다.</p>
<p>즉 init() 메서드는 처음 한번만 실행되므로 해당 서블릿에 각각의 스레드에서 공통적으로 사용하기 위해 필요한 작업이 있다면 init() 메서드를 오버라이딩해서 구현한다.</p>
<p>만일 실행 중 서블릿이 변경되는 경우에는 기존 서블릿은 종료되고 다시 시작되면서 init() 메서드가 호출된다.</p>
<h3 id="요청응답--service">요청/응답 : service()</h3>
<p>init() 메서드는 최초 한번만 수행되고 이 후 요청은 스레드로 실행되며 service() 메서드를 통해 각각 doGet()이나 doPost()로 분기된다. 이때 파라메터로 HttpServletRequest와 HttpServletResponse 클래스 타입인 request와 response 객체가 제공되는데, 사용자 요청처리는 request로, 응답 처리는 response 객체로 처리한다.</p>
<h3 id="servlet-종료--destroy">Servlet 종료 : destroy()</h3>
<p>컨테이너로부터 서블릿 종료 요청이 있을 때 destory() 메서드를 호출한다. init() 메서드와 마찬가지로 한번만 실행되며 서블릿이 종료되면서 정리해야할 작업이 있을 때는 destroy() 메서드를 오버라이딩해서 구현하면 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Servlet Class 구조]]></title>
            <link>https://velog.io/@hh_nebula/Servlet-Class-%EA%B5%AC%EC%A1%B0</link>
            <guid>https://velog.io/@hh_nebula/Servlet-Class-%EA%B5%AC%EC%A1%B0</guid>
            <pubDate>Wed, 18 Jan 2023 09:22:54 GMT</pubDate>
            <description><![CDATA[<h3 id="서블릿-클래스의-구조">서블릿 클래스의 구조</h3>
<p>서블릿 자체는 자바로 구현하지만 서블릿 컨테이너에 해당 클래스가 서블릿임을 알려야 하며 어떤 URL에서 실행해야 하는지 등록하는 과정이 필요하다.</p>
<p>서블릿 클래스는 <code>javax.servlet.Servlet</code> 인터페이스를 구현한 추상 클래스인 GenericServlet 클래스와 HttpServlet 클래스 중 하나를 상속해 구현하는 형태이다.</p>
<p>웹 프로그래밍의 대부분은 HTTP 프로토콜에 최적화되어 있는 HttpServlet 클래스를 상속해 구현하는 것이 좋다.</p>
<pre><code class="language-java">// HttpServlet 클래스 상속
public Class MyServlet extends HttpServlet {

    // Get 방식
    public doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        // Get 방식 요청 시 처리할 내용
    }

    // Post 방식
    public doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        // Post 방식 요청 시 처리할 내용
    }

}</code></pre>
<p>doGet(), doPost() 메서드에서 파라메터로 사용되는 request, response는 서블릿 컨테이너가 클라이언트 요청과 응답을 처리할 수 있도록 서블릿에 제공하는 객체로 클라이언트와 상호작용에 필요한 다양한 메서드를 제공한다.</p>
<p>request와 response는 session, application과 함께 JSP의 내장객체이기도 하며 속성 관리 기능을 이용해 컨트롤러와 뷰 페이지 간 데이터 전달 등의 목적에도 사용된다.</p>
<h3 id="httpservletrequest">HttpServletRequest</h3>
<p>HttpServletRequest 클래스는 HTTP 프로토콜의 request 정보를 서블릿에 전달하기 위한 목적으로 사용한다. 헤더 정보, 파라메터, 쿠키, URL, URI 등의 정보를 읽어드리는 메서드와 HTTP Body의 Stream을 읽어들이는 메서드를 가지고 있다.</p>
<p>서블릿 컨테이너에서 생성되고 클라이언트 요청이 doGet(), doPost()로 전달될 때 파라메터로 함께 전달되며 서블릿에서 클라이언트와 연결되어 처리할 작업은 모두 HttpServletRequest를 통해야 한다.</p>
<p><a href="https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html">메서드 목록 링크</a></p>
<h3 id="httpservletresponse">HttpServletResponse</h3>
<p>HttpServletRequest와 마찬가지로 클라이언트와 연결된 처리가 가능하며 서버에서 클라이언트로 전달하려는 목적을 위한 기능으로 구성된다. 서블릿 컨테이너는 요청 클라이언트에 응답을 보내기 위한 HttpServletResponse 객체를 생성하여 서블릿에 전달한다.</p>
<p>서블릿은 해당 객체를 이용하여 content type, 응답 코드, 응답 메시지 등을 전송할 수 있다.</p>
<p><a href="https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletResponse.html">메서드 목록 링크</a></p>
<h3 id="서블릿-정보-등록">서블릿 정보 등록</h3>
<p>서블릿 클래스 자체만으로는 톰캣에서 실행이 불가능하므로 web.xml 이나 어노테이션으로 서블릿임을 선언해야 한다.</p>
<p>아래 내용은 web.xml의 작성 예시이며 지금은 거의 사용하지 않는다.</p>
<pre><code class="language-xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;&gt;
&lt;web-app ...&gt;
    &lt;servlet&gt;
        &lt;servlet-name&gt;HelloWorld&lt;/servlet-name&gt;
        &lt;servlet-class&gt;package.servle.HelloServlet&lt;/servlet-class&gt;
    &lt;/servlet&gt;
    &lt;servlet-mapping&gt;
        &lt;servlet-name&gt;HelloWorld&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/hello&lt;/url-pattern&gt;
    &lt;/servlet-mapping&gt;
&lt;/web-app&gt;</code></pre>
<p>서블릿 3.0 부터는 자바 어노테이션을 사용하여 다음과 같이 등록한다.</p>
<pre><code class="language-java">@WebServlet(urlPatterns = &quot;/hello&quot;)
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        ...
    }
}</code></pre>
<p>urlPatterns란 어떤 클라이언트 요청에 해당 서블릿을 실행할지 지정하는 것으로 여러 URL을 등록할 수 있다. 패턴 형식으로 특정한 경우에 실행되도록 설정하는 것도 가능하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Servlet 개요]]></title>
            <link>https://velog.io/@hh_nebula/Servlet-%EA%B0%9C%EC%9A%94</link>
            <guid>https://velog.io/@hh_nebula/Servlet-%EA%B0%9C%EC%9A%94</guid>
            <pubDate>Wed, 18 Jan 2023 08:50:10 GMT</pubDate>
            <description><![CDATA[<h3 id="서블릿의-개요">서블릿의 개요</h3>
<p>서블릿은 자바로 만들어진 프로그램을 서버에서 실행하기 위해 만들어졌다.</p>
<p>서블릿은 특히 웹 서비스 개발에 특화되어 있는데 데이터베이스 연동, 외부 서비스 연동을 통해 정적인 웹에 동적인 정보 제공을 가능하게 한다.</p>
<p>서블릿은 순수 자바 코드로 작성되며, 코드 자체만 보면 일반적인 자바 클래스와 다르지 않다. 다만 HttpServlet 클래스를 상속하여 서블릿 등록에 필요한 정보를 추가해야 하며, 서블릿 단독으로 실행할 수 없고 서블릿 컨테이너를 통해야 한다.</p>
<h3 id="서블릿-동작-과정">서블릿 동작 과정</h3>
<p><img src="https://velog.velcdn.com/images/hh_nebula/post/3d2ae5e9-755e-45c4-8d60-2eec08af0b70/image.png" alt=""></p>
<ol>
<li>HttpServlet 클래스를 상속받는 서블릿 클래스를 구현한다.</li>
<li>컨테이너는 URL Mapping 설정을 참고하여 서블릿을 등록한다.</li>
<li>서블릿 객체 생성 및 init() 메서드를 실행한다.</li>
<li>클라이언트 요청은 스레드로 동시 처리되며 각각 service() 메서드를 호출한다.</li>
<li>service() 메서드는 doGet(), doPost() 등 프로토콜에 따른 메서드를 호출한다.</li>
<li>컨테이너 종료 혹은 웹 애플리케이션 종료 시점에 destroy() 메서드를 실행한다.</li>
<li>서블릿을 등록 해제한다.</li>
</ol>
<h3 id="서블릿의-장단점">서블릿의 장단점</h3>
<p>장점</p>
<ul>
<li>자바를 기반으로 하므로 자바 API를 모두 사용할 수 있다.</li>
<li>운영체제나 하드웨어의 영향을 받지 않으므로 한번 개발된 애플리케이션은 다양한 서버 환경에서도 실행할 수 있다.</li>
<li>웹 애플리케이션에서 효율적인 자료 공유 방법을 제공한다.</li>
<li>다양한 오픈소스 라이브러리와 개발도구를 활용할 수 있다.</li>
</ul>
<p>단점</p>
<ul>
<li>HTML 응답을 위해서는 출력문으로 문자열 결합을 사용해야 한다.</li>
<li>서블릿에서 HTML을 포함할 경우 화면 수정이 어렵다.</li>
<li>HTML 폼의 데이터 처리가 불편하다.</li>
<li>기본적으로 단일 요청과 응답을 처리하는 구조로 다양한 경로의 URL 접근을 하나의 클래스에서 처리하기 어렵다.</li>
</ul>
<p>서블릿은 웹에서 호출 가능한 자바 프로그램 규격이지만, 그 자체만으로는 실제 서비스 개발에서 앞의 단점과 같이 여러 제약이 있다. 따라서 실제 자바 웹 개발에는 서블릿과 함께 다음과 같은 조합으로 구현하게 된다.</p>
<ul>
<li>화면 구성을 위해 JSP와 같은 템플릿 엔진을 사용한다.</li>
<li>REST API 구현을 위해서는 JAX-RS를 사용한다.</li>
<li>복잡한 서비스 구현을 위해 프론트 컨트롤러 모델 등을 사용한다.</li>
</ul>
<p>이 외에도 보안과 인증, 성능, 개발 생산성 등의 문제를 고려할 때 스프링 프레임워크 등을 사용하고 핵심 기능 구현에 집중하는 것이 바람직하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자바 웹 개발 개요 요약]]></title>
            <link>https://velog.io/@hh_nebula/%EC%9E%90%EB%B0%94-%EC%9B%B9-%EA%B0%9C%EB%B0%9C-%EA%B0%9C%EC%9A%94-%EC%9A%94%EC%95%BD</link>
            <guid>https://velog.io/@hh_nebula/%EC%9E%90%EB%B0%94-%EC%9B%B9-%EA%B0%9C%EB%B0%9C-%EA%B0%9C%EC%9A%94-%EC%9A%94%EC%95%BD</guid>
            <pubDate>Wed, 18 Jan 2023 08:38:53 GMT</pubDate>
            <description><![CDATA[<p>서블릿을 실행하기 위해서는 톰캣과 같은 서블릿 컨테이너가 필요하며 이러한 서버 소프트웨어는 일반적으로 WAS로 불린다.</p>
<p>JSP는 서블릿에서 HTML과 데이터 결합을 손쉽게 처리하기 위해 만들어졌다. 하지만 단순한 HTML 문법만으로는 처리할 수 없기 때문에 자바 코드를 중간중간 사용해야한다는 문제가 있다.</p>
<p>JSP의 구조적 문제를 해결하기 위해 커스텀 태그를 기반으로 하는 JSTL 및 EL이 도입되었다.</p>
<p>REST는 네트워크상에서 클라이언트와 서버 사이의 통신을 구현하는 방법 중 하나이다.</p>
<p>JAX-RS란 자바에서 REST-API 개발을 위한 서버 프로그램의 표준 규격이다. 특히 호환성을 위해서라면 JAX-RS를 사용하는 것이 좋다.</p>
<p>스프링 프레임워크는 자바 기반의 오픈소스 프레임워크로 Java EE에서 요구하는 수준의 복잡한 기능을 Java EE를 사용하지 않고 구현하고자 시작한 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring Framework]]></title>
            <link>https://velog.io/@hh_nebula/Spring-Framework</link>
            <guid>https://velog.io/@hh_nebula/Spring-Framework</guid>
            <pubDate>Wed, 18 Jan 2023 00:14:42 GMT</pubDate>
            <description><![CDATA[<h3 id="스프링-프레임워크란">스프링 프레임워크란?</h3>
<p><img src="https://velog.velcdn.com/images/hh_nebula/post/dfc4d9f2-5e05-4bbc-94c9-ba54d41e9eb6/image.png" alt=""></p>
<p>자바 웹 개발의 핵심은 자바와 서블릿이라 볼 수 있지만 성능과 안정성, 보안, 다른 서비스와의 연계 등 단순한 기능 외에 고려할 사항이 많다. 이러한 문제를 해결하기 위해 Java EE가 탄생했으나 스펙의 복잡함과 구현의 어려움으로 완전히 정착되지는 못했다.</p>
<p>스프링 프레임워크는 자바 기반의 오픈소스 프레임워크로 Java EE에서 요구하는 수준의 복잡한 기능을 Java EE를 사용하지 않고 구현하고자 시작한 것이다.</p>
<p>스프링 프레임워크의 특징은 다음과 같다.</p>
<ul>
<li><p>경량 컨테이너
객체 생성, 소멸과 같은 생명 주기를 관리하며 스프링 컨테이너로부터 필요한 객체를 얻어 올 수 있다.</p>
</li>
<li><p>제어의 역행 지원 ( IoC )
메서드나 객체의 호출 제어권이 사용자가 아닌 프레임워크에 있어 필요에 따라 스프링에서 사용자의 코드를 호출한다.</p>
</li>
<li><p>의존성 주입 지원 ( DI )
각 계층이나 서비스 간에 의존성이 존재할 경우 프레임워크가 서로 연결 해준다.</p>
</li>
<li><p>관점 지향 프로그래밍 지원 ( AOP )
트랜잭션이나 로깅, 보안과 같이 여러 모듈에서 공통적으로 사용하는 기능의 경우 해당 기능을 분리하여 관리할 수 있다.</p>
</li>
</ul>
<h3 id="스프링-부트란">스프링 부트란?</h3>
<p><img src="https://velog.velcdn.com/images/hh_nebula/post/40b7b0ad-f2f9-49cd-9d9f-b83c9f6f9737/image.png" alt=""></p>
<p>스프링 프레임워크는 핵심 프레임워크 외에 여러 서브 프로젝트로 구성되어 있으며 실제 사용은 주로 스프링 부트를 통해 이루어진다. 스프링 부터는 스프링 프레임워크 프로젝트를 손쉽게 시작할 수 있도록 하며 개발과 관련한 스프링 구성요소를 편하게 관리할 수 있도록 한다.</p>
<p>스프링 부트의 주요 특징은 리액티브 스택과 서블릿 스택을 구분하고 있다는 점이다.</p>
<ul>
<li><p>서블릿 스택
기존과 같이 서블릿 API에 기반한 동기 방식의 블로킹 I/O 구조를 사용하며 하나의 요청은 하나의 스레드로 처리된다. 아파치 톰캣과 같은 서블릿 컨테이너를 사용하며 전통적인 Spring MVC 기반의 서버 프로그램 개발과 JPA, JDBC, NoSQL 데이터베이스 지원을 포함한다.</p>
</li>
<li><p>리액티브 스택
새로운 비동기 논블로킹 I/O 구조를 사용하며 멀티코어 시스템의 장점을 살리고 대규모 사용자 접속을 처리하는데 유용한 구조로 설계되어 있다. 네티, 언더토우 및 서블릿 3.1 이상의 컨테이너를 사용하며 Spring WebFlux라고 하는 새로운 프레임워크를 사용해 개발한다. 리액티브 스택은 다음과 같은 구현에 적합하다 <code>비동기 논블로킹 리액티브 개발</code> <code>효율적으로 동작하는 고성능 웹 애플리케이션</code> <code>서비스 간 호출이 많은 마이크로 서비스 아키텍쳐 구현</code></p>
</li>
</ul>
<h3 id="동기비동기-블로킹이란">동기/비동기 블로킹이란?</h3>
<p>동기 방식은 요청 후 응답을 받을 때 까지 대기하는 방식을 말한다. 대기하는 동안 다른 일을 처리할 수 없는 상태인 블로킹이 되어 요청에 시간이 많이 걸리는 경우 비효율적인 방법이다.</p>
<p>비동기 방식은 즉각적인 응답 결과가 필요 없는 경우 요청 후 응답을 기다리지 않고 다른 일을 하다가 응답이 오면 그때 해당 응답을 처리하는 방식으로 대기시간 없이 다른 일을 할 수 있다는 장점이 있다.</p>
<h3 id="스프링-프레임워크의-조합">스프링 프레임워크의 조합</h3>
<p>스프링 프레임워크 자체는 방대하기 때문에 프로젝트 규모와 성격에 따라 적절한 요소를 조합해 사용해야 한다. 일반적으로 많이 사용하는 조합은 다음과 같다.</p>
<ul>
<li>Spring Boot : MVC Web, REST API 개발</li>
<li>Spring Data JDBC/JPA/MongoDB/REST : 데이터베이스 연동</li>
<li>Spring Security : 로그인 관리 및 OAuth2 인증 연동</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[REST API & JAX-RS]]></title>
            <link>https://velog.io/@hh_nebula/REST-API-JAX-RS</link>
            <guid>https://velog.io/@hh_nebula/REST-API-JAX-RS</guid>
            <pubDate>Tue, 17 Jan 2023 23:58:47 GMT</pubDate>
            <description><![CDATA[<p>HTTP와 JSON을 함께 사용하여 Open API를 구현하는 형태로 많이 사용되는 REST에 대해 간략히 살펴본다.</p>
<h3 id="rest-api란">REST API란?</h3>
<p>REST는 Representational State Transfer의 약어로 네트워크상에서 클라이언트와 서버 사이의 통신을 구현하는 방법 중 하나이며, 대부분의 Open API는 REST 아키텍쳐를 기반으로 만들어져 있다.</p>
<p>클라이언트가 서버로 요청을 보냈을 때 서버가 이에 대한 응답으로 보내주는 Resource의 상태를 Representation이라고 할 수 있으며, 하나의 Resource는 여러 형태의 Representation으로 전달할 수 있는 것을 말한다.</p>
<p><img src="https://velog.velcdn.com/images/hh_nebula/post/fc2ab038-d33d-4e1a-be7c-b24a565e0366/image.png" alt=""></p>
<p>Representation 의 종류로는 json, xml, text, rss 등이 있다.</p>
<p>원래 REST의 의미는 서버 응답을 앞에서 언급한 다양한 형태로 전달하는 개념으로 웹, 즉 HTTP의 기본 응답이 HTML인데 이를 JSON 등 다른 규격을 사용하는 것으로 접근한 것이다.</p>
<p>이에 따라 웹을 단순히 브라우저에서 콘텐츠를 이용하는 브라우저 서비스가 아닌 데이터를 주고받기 위한 API 서비스의 형태로 발전시킨 계기가 된다.</p>
<h3 id="rest의-장점">REST의 장점</h3>
<p>이러한 접근의 장점은 안정되고 검증된 웹 기술을 그대로 사용할 수 있다는 점이다. 예를 들어 서버 프로그램으로 자바, 서블릿 등을 사용할 수 있고, 스프링 프레임 워크 혹은 IBM, Oracle 등의 서버 솔루션을 그대로 사용할 수도 있어 성능, 안정성, 보안, 백업, 분산 등 여러 인프라의 재활용이 가능하다.</p>
<p>이러한 REST 방식 이전에는 원격으로 데이터를 주고받는 서비스를 구현하기 위해 별도의 프로토콜을 가지는 클라이언트-서버 통신 프로그램을 개발해야 했다. 이 과정에서 인증이나 보안, 서버 프로그램의 성능과 안정성과 같은 여러 문제를 개발자에 의존해 해결해야 했다. 이러한 서버 프로그램에 기존 웹 기술을 사용하는 발상은 획기적이었고, 프론트엔드 중심 개발의 발전과 함께 REST 혹은 RESTful API 형태로 정착하게 되었다.</p>
<h3 id="rest-api의-동작구조">REST API의 동작구조</h3>
<p><img src="https://velog.velcdn.com/images/hh_nebula/post/a391843b-b778-47c0-b822-9886cd946530/image.png" alt=""></p>
<ol>
<li>클라이언트는 웹, 스마트폰 앱, 자동차, 냉장고 등 모두 가능하다.</li>
<li>URL/URI를 이용하여 서버에 HTTP 규격을 따라 요청한다.</li>
<li>서버 프로그램은 자바, 서블릿, Node.js, 파이썬 등 모든 언어가 가능하다.</li>
<li>처리 결과는 보통 JSON 규격을 사용한다.</li>
<li>웹에서는 응답받은 데이터를 웹의 화면 처리에 사용한다.</li>
<li>그 외 데스크톱, 스마트폰, 자동차/냉장고 앱에서는 화면 UI에 필요한 데이터 구성에 사용한다.</li>
</ol>
<p>이러한 구조를 통해 날씨 정보를 제공하는 REST API 서비스를 활용하면 웹 화면은 물론이고 스마트폰 앱, 냉장고 모니터 등에서도 날씨 정보를 보여주는 것이 가능하다</p>
<h3 id="jax-rs란">JAX-RS란?</h3>
<p>자바에서 REST API 개발을 위한 서버 프로그램의 표준 규격이다. 현재 자바 웹 개발에서 REST API를 구현하는 방법은 JAX-RS 또는 스프링 프레임워크의 RestController를 사용하는 방법이 있다. 스프링 프레임워크 없이 개발한다면 JAX-RS를 사용해야 하고, 스프링 프레임워크를 사용한다면 두 방법 중 한 가지를 선택해서 사용할 수 있다.</p>
<p>호환성을 위해서라면 JAX-RS를 사용하는 것이 좋고 스프링만 사용한다면 스프링의 RestController를 사용하는 것이 편리하다. 세부적인 차이가 있지만 기본 구조나 방법은 유사하다.</p>
<pre><code class="language-java">// JAX-RS 방식

@Path(&quot;/addebook&quot;)
public class RestApiService {

    Logger logger = Logger.getLogger(&quot;RestApiService&quot;);
    AddrBookDAO dao = new AddrBookH2DAO();

    @GET
    @Path(&quot;list&quot;)
    @Produces(MediaType.APPLICATION_JSON)
    public List&lt;AddrBook&gt; getList() {
        List&lt;addrBook&gt; datas = dao.getAll();
        logger.info(&quot;API call: /list &quot;);
        return dats;
    }

}</code></pre>
<ul>
<li>@Path(&quot;/addrbook&quot;) : 현재 클래스에서 처리할 URL의 진입점을 의미한다.</li>
<li>@GET : 지정된 URL 요청을 GET 방식으로 호출했을 때 동작하도록 한다.</li>
<li>@Path(&quot;/list&quot;) : 메서드가 실행될 URI를 요청한다.
( 클래스의 하위이므로 /addrbook/list 가 된다. )</li>
<li>@Produces(MediaType.APPLICATION_JSON) : 리턴되는 데이터를 JSON 형식으로 지정한다.</li>
</ul>
<p>위의 코드와 같이 주로 @로 시작하는 자바 어노테이션을 사용해 클래스와 메서드에 필요한 정보를 제공하는 것만으로 별도의 데이터 변환 과정 없이 손쉽게 API 서버 프로그램 개발이 가능하다. 톰캣을 실행하는 것만으로 서버가 동작하고 기존의 다른 웹 서비스도 함께 운영이 가능하다.</p>
<p>앞의 코드를 그대로 사용하고 REST API만 스프링 프레임워크를 사용하는 경우 다음과 같이 작성할 수 있다.</p>
<pre><code class="language-java">// 스프링 프레임워크 방식

@RestController
@RequestMapping(&quot;/addrbook&quot;)
public class RestApiService {

    Logger logger = Logger.getLogger(&quot;RestApiService&quot;);
    AddrBookDAO dao = new AddrBookH2DAO();

    @GetMapping(&quot;list&quot;)
    public List&lt;AddrBook&gt; getList() {
        List&lt;addrBook&gt; datas = dao.getAll();
        logger.info(&quot;API call: /list &quot;);
        return dats;
    }

}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[JSTL/EL]]></title>
            <link>https://velog.io/@hh_nebula/JSTLEL</link>
            <guid>https://velog.io/@hh_nebula/JSTLEL</guid>
            <pubDate>Tue, 17 Jan 2023 21:48:54 GMT</pubDate>
            <description><![CDATA[<h3 id="jstlel">JSTL/EL</h3>
<p>앞에서 살펴본 JSP의 구조적 문제를 해결하기 위해 커스텀 태그를 기반으로 하는 JSTL/EL이 도입되었다.</p>
<pre><code class="language-html">&lt;table&gt;
    &lt;% for(type variable : variables)&gt; { %&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;%= variable.attribute1&gt;&lt;/td&gt;
            &lt;td&gt;&lt;%= variable.attribute2&gt;&lt;/td&gt;
        &lt;/tr&gt;
    &lt;% } %&gt;
&lt;/table&gt;</code></pre>
<p>이 코드는 아래와 같이 개선할 수 있다.</p>
<pre><code class="language-html">&lt;table&gt;
    &lt;c:forEach var=&quot;variable&quot; items=&quot;${variables}&quot;&gt;
        &lt;tr&gt;
            &lt;td&gt;${variable.attribute1}&lt;/td&gt;
            &lt;td&gt;${variable.attribute2}&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/c:forEach&gt;
&lt;/table&gt;</code></pre>
<p>&lt;c:forEach&gt; 태그는 반복문을 제공하는 JSTL 커스텀 태그이다.
${...}의 형태는 표현 언어로 Java 객체의 멤버 출력이 가능하다.</p>
<p>JSP보다 훨씬 구조적이고 가독성도 높아진 것을 확인할 수 있다. 이와 같은 프로그램 구조는 MVC 패턴과 함께 Servlet과 결합되어 오랫동안 Java 웹 개발의 정석으로 자리 잡아왔다.</p>
<p>단점은 화면 구조를 서버에서 빌드하는 구조이기 때문에 모든 실행이 서블릿 컨테이너를 통해야 한다는 점이다. 예시로 &lt;c:forEach&gt; 태그나 ${...}, &lt;% %&gt; 같은 JSP 구문은 클라이언트에서 해석할 수 없으므로 사소한 변경도 서버를 통해 실행되어야 한다.</p>
<p>이는 개발 생산성과 디자이너와의 협업 등에서 큰 문제가 된다.</p>
<h3 id="jsp-대체-솔루션">JSP 대체 솔루션</h3>
<p>JSP의 주된 대체 솔루션인 스프링 프레임워크와 Vue.js에서 사용하는 형식을 간단하게 살펴본다.</p>
<p>스프링 프레임워크의 기본 템플릿 엔진인 타임리프를 사용하는 경우 다음과 같다.</p>
<pre><code class="language-HTML">&lt;table&gt;
    &lt;tr data-th-each=&quot;variable : ${variables}&quot;&gt;
        &lt;td data-th-text=&quot;${variable.attribute1}&quot;&gt;attribute&lt;/td&gt;
        &lt;td data-th-text=&quot;${variable.attribute2}&quot;&gt;attribute&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;</code></pre>
<p>JSP와 EL 부분은 동일하지만 JSTL 대신 HTML 태그에 <code>data-*-</code> 속성을 사용하는 형태라 서버 실행 없이도 디자인 확인이 가능한 구조다. 변수로 출력되는 데이터 이외 기본값 출력이 가능하다.</p>
<p>만일 Vue.js를 이용해 프론트엔트 개발 방식으로 클라이언트 사이드 랜더링을 사용한다면 다음과 같다.</p>
<pre><code class="language-HTML">&lt;table&gt;
    &lt;tr v-for=&quot;variable in variables&quot;&gt;
        &lt;td&gt;{{variable.attribute1}}&lt;/td&gt;
        &lt;td&gt;{{variable.attribute2}}&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;</code></pre>
<p>타임리프와 유사하게 <code>v-*</code> 형태의 속성을 사용하고 있으며 프론트앤드 방식이기 때문에 해당 속성은 자바스크립트로 동작하는 Vue.js에서 처리하게 된다.</p>
<p>로직을 처리하기 위한 방법과 데이터 핸들링하는 방법 등에서 차이가 있으나 HTML과 데이터 그리고 로직을 조합하는 방식이 모두 유사한 것을 확인할 수 있다.</p>
]]></description>
        </item>
    </channel>
</rss>