<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ruinak_4127.log</title>
        <link>https://velog.io/</link>
        <description>Nil Desperandum &lt;절대 절망하지 마라&gt;</description>
        <lastBuildDate>Tue, 11 Jan 2022 00:40:46 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>ruinak_4127.log</title>
            <url>https://velog.velcdn.com/images/ruinak_4127/profile/633eb209-cd10-4965-98ee-2fdcde912b86/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ruinak_4127.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ruinak_4127" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Error]]></title>
            <link>https://velog.io/@ruinak_4127/Error</link>
            <guid>https://velog.io/@ruinak_4127/Error</guid>
            <pubDate>Tue, 11 Jan 2022 00:40:46 GMT</pubDate>
            <description><![CDATA[<h3 id="contextloaderlistener-에러-해결-방법">ContextLoaderListener 에러 해결 방법</h3>
<p>참고 : <a href="https://myblog.opendocs.co.kr/archives/1657">https://myblog.opendocs.co.kr/archives/1657</a></p>
<h3 id="tomcat-port-번호-중복-해결">Tomcat port 번호 중복 해결</h3>
<p>참고 : <a href="https://ffoorreeuunn.tistory.com/426">https://ffoorreeuunn.tistory.com/426</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CDATA ( <![CDATA[..]]]]><![CDATA[> )]]></title>
            <link>https://velog.io/@ruinak_4127/CDATA-CDATA</link>
            <guid>https://velog.io/@ruinak_4127/CDATA-CDATA</guid>
            <pubDate>Mon, 27 Dec 2021 01:48:22 GMT</pubDate>
            <description><![CDATA[<h2 id="개념">개념</h2>
<ul>
<li>쿼리를 작성할 때, &#39;&lt;&#39;, &#39;&gt;&#39;, &#39;&amp;&#39;를 사용해야하는 경우가 생기는데 xml에서 그냥 사용할 경우 태그로 인식하는 경우가 종종 있습니다.</li>
<li>이럴 경우 에러를 뱉어내기 때문에 &#39;태그가 아니라 실제 쿼리에 필요한 코드&#39;라고 알려줘야 한다. </li>
<li>그때 사용하는 것이 &amp;lt![CDATA[...]]&gt; 이다.</li>
<li>한 마디로 &lt;&gt;(부등호),&amp;(앤드),||(오아) 등을 닫는 부등호가 아니라 문자열로 처리하라는 뜻입니다.</li>
<li>어렵게 말하자면 &quot;XML parser&quot;를 하지 말아라 이겁니다.
<img src="https://images.velog.io/images/ruinak_4127/post/7b3d6279-9688-4240-9b3a-bce8c69be24d/Screenshot_2.png" alt=""><h2 id="문법">문법</h2>
<pre><code>&lt;![CDATA[
쿼리 내용
]]&gt;</code></pre></li>
<li>CDATA 안에 쿼리를 사용하면 쿼리 내용의 괄호나 특수문자를 XML parser로 인식하지 않고 &quot;문자열&quot;로 인식합니다.<h2 id="예시">예시</h2>
<h3 id="전체-쿼리-cdata-사용">전체 쿼리 CDATA 사용</h3>
<pre><code>&lt;select id=&quot;getUserList&quot; resultMap=&quot;UserVO&quot;&gt;
&lt;![CDATA[
SELECT *
FROM user
WHERE id &gt; 3
]]&gt;
&lt;/select&gt;</code></pre><h3 id="조건문-중간에-cdata-사용">조건문 중간에 CDATA 사용</h3>
</li>
<li>if 문<pre><code>&lt;select id=&quot;getUser&quot; resultType=&quot;UserVO&quot;&gt;
SELECT * FROM user
&lt;if test=&quot;id != null&quot;&gt;
  where id  &lt;![CDATA[&lt;]]&gt; 3;
&lt;/if&gt;
&lt;/select&gt;</code></pre></li>
<li>choose 문<pre><code>&lt;select id=&quot;getUser&quot; resultMap=&quot;UserVO&quot;&gt;
&lt;![CDATA[
  SELECT *
  FROM user
  WHERE  1=1
]]&gt;
&lt;choose&gt;
  &lt;when test=&#39;id != null and user_type ==&quot;1&quot;&#39;&gt;
    &lt;![CDATA[
      salary &gt; 100
    ]]&gt;
  &lt;/when&gt;
  &lt;otherwise&gt;
    &lt;![CDATA[
      salary &lt; 100
    ]]&gt;
  &lt;/otherwise&gt;
&lt;/choose&gt;
&lt;/select&gt;</code></pre></li>
</ul>
<h4 id="출처--httpsjava119tistorycom70">출처 : <a href="https://java119.tistory.com/70">https://java119.tistory.com/70</a></h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[Core Tag( <c: ?> 태그]]></title>
            <link>https://velog.io/@ruinak_4127/curl-%ED%83%9C%EA%B7%B8</link>
            <guid>https://velog.io/@ruinak_4127/curl-%ED%83%9C%EA%B7%B8</guid>
            <pubDate>Mon, 27 Dec 2021 01:20:06 GMT</pubDate>
            <description><![CDATA[<h2 id="curl-태그">&lt;c:url&gt; 태그</h2>
<ul>
<li>&lt;c:url&gt; 태그는 URL에 자동으로 Context Path 를 붙여주는 일을 합니다. 컨텍스트를 변경하더라도 URL을 수정할 필요가 없게 됩니다.<h3 id="curl-태그-사용법">&lt;c:url&gt; 태그 사용법</h3>
</li>
<li>이 태그는 jstl core 태그에 포함되어 있으므로 &lt;c:url&gt; 을 사용하려면 아래와 같은 taglib 지시자를 페이지 상단에 포함하여야 합니다.<pre><code>&lt;%@ taglib prefix=&quot;c&quot; uri=&quot;http://java.sun.com/jsp/jstl/core&quot; %&gt;</code></pre></li>
<li>일반적인 사용법은 아래와 같습니다.<pre><code>&lt;img src=&quot;&lt;c:url value=&#39;/images/btn/add.png&#39; /&gt;&quot; /&gt;</code></pre></li>
<li>웹애플리케이션의 컨텍스트 패스가 http://도메인/site/ 로 되어 있다면 위의 코드는 출력시 아래와 같이 변환됩니다.<pre><code>&lt;img src=&quot;/site/images/btn/add.png&quot; /&gt;</code></pre></li>
<li>&lt;c:url&gt; 태그를 사용할 때 생성된 URL의 끝에  jsessionid 가 붙을 경우를 주의해야 합니다. </li>
<li>컨텍스트 패스가 추가가 되므로 대부분의 경우 아래의 코드는 잘 동작합니다.<pre><code>&lt;img src=&quot;&lt;c:url value=&#39;/&#39; /&gt;/images/btn/add.png&quot; /&gt;</code></pre></li>
<li>하지만 서버 설정에 때라 세션 아이디가 URL에 붙는 경우가 있습니다. </li>
<li>이런 경우 위 코드는 출력이 다음과 같에 만들어져 오류가 발생합니다.<pre><code>&lt;img src=&quot;/site/;jsessiond=xxxxxx/images/btn/add.png&quot; /&gt;</code></pre></li>
<li>&amp;lta&gt; 태그에 사용될 때 URL에 GET 방식으로 전달되는 파라미터가 많이 사용됩니다. </li>
<li>아래와 같은 형식입니다.<pre><code>&lt;a href=&quot;&lt;c:url value=&#39;/userSearch.do?name=홍길동&amp;page=3&#39; /&gt;&quot;&gt;3 페이지&lt;/a&gt;</code></pre></li>
<li>조회값이 계속 URL에 따라 다녀야 할 경우 입니다. </li>
<li>이 경우 name의 값을 URL 인코딩을 해야 하는데 &amp;ltparam&gt; 프로퍼티를 사용해서 인코딩 할 수 있습니다.<pre><code>&lt;c:url value=&quot;/userSearch.do&quot; var=&quot;url&quot;&gt;
&lt;c:param name=&quot;name&quot; value=&quot;홍길동&quot; /&gt;
&lt;c:param name=&quot;page&quot; value=&quot;3&quot; /&gt;
&lt;/c:url&gt;
</code></pre></li>
</ul>
<p><a href="${url}">3 페이지</a></p>
<pre><code>- &lt;c:url&gt; 태그의 var 속성은 생성된 URL을 변수에 할당하여 다른곳에 사용할 수 있도록 해 줍니다.
- var 속성이 유용하게 사용될 수 있는 곳에 &lt;form:form&gt; 태그 입니다. 
- &lt;form:form&gt; 태그의 action 속성에는 &lt;c:url&gt; 태그를 사용할 수 없습니다. 
- 그러므로 변수에 셋팅한 후에 폼 태그에서 사용할 수 있습니다.</code></pre><p>&lt;c:url value=&quot;/insert.do&quot; var=&quot;insertUrl&quot; /&gt;
&lt;form:form action=&quot;${insertUrl}&quot;&gt;
...</p>
</form>
```
- 참고로 <c:url> 태그를 사용하지 않고도 jsp 컨텍스트 패스를 붙이려면 다음과 같이 사용하면 되겠습니다.
```
<form:form action="${pageContext.request.contextPath}/insert.do">
...
</form>
```

<h4 id="출처-httpsoffbyonetistorycom319-쉬고-싶은-개발자">출처: <a href="https://offbyone.tistory.com/319">https://offbyone.tistory.com/319</a> [쉬고 싶은 개발자]</h4>
<h2 id="cout-태그">&lt;c:out&gt; 태그</h2>
<ul>
<li>&lt;c:out&gt;은 화면에 결과값을 표출할 때 사용합니다.</li>
<li>스크립틀릿의 &lt;%= %&gt;와 비슷합니다.</li>
<li>간단한 &#39; . &#39; 표기법으로 사용이 편리합니다.<ul>
<li>ex&gt; &lt;c:out value=&quot;data.name&quot; /&gt;<h3 id="cout-태그-속성">&lt;c:out&gt; 태그 속성</h3>
<img src="https://images.velog.io/images/ruinak_4127/post/6e75a9ca-6708-4283-b0e3-d08c81898897/Screenshot_1.png" alt=""><h3 id="cout-태그-사용법">&lt;c:out&gt; 태그 사용법</h3>
<pre><code>&lt;c:set var=&quot;data&quot; value=&quot;c태그 테스트입니다.&quot; /&gt;
&lt;c:out value=&quot;${&#39;안녕하세요&#39;}&quot;/&gt; &lt;br /&gt;
&lt;c:out value=&quot;${data}&quot;/&gt;</code></pre></li>
</ul>
</li>
<li>결과<ul>
<li>안녕하세요</li>
<li>c태그 테스트입니다.<h4 id="출처--httpsblognavercomobject0108221198650648-jstl-core-tag---cout-사용하기">출처 : <a href="https://blog.naver.com/object0108/221198650648">https://blog.naver.com/object0108/221198650648</a> [JSTL] Core Tag - &lt;c:out&gt; 사용하기</h4>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[@SuppressWarnings ?]]></title>
            <link>https://velog.io/@ruinak_4127/SuppressWarnings</link>
            <guid>https://velog.io/@ruinak_4127/SuppressWarnings</guid>
            <pubDate>Thu, 23 Dec 2021 07:55:54 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/ruinak_4127/post/97d0e4ce-604c-4fbc-bd7f-983b3fbce088/Screenshot_27.png" alt=""></p>
<ul>
<li><p>SuppressWarning 어노테이션을 사용하여 컴파일 단위의 서브세트와 관련된 컴파일 경고를 사용하지 않도록 설정할 수 있습니다.</p>
</li>
<li><p>한 개일때 : @SuppressWarnings(&quot;resource&quot;)</p>
</li>
<li><p>두 개일때 : @SuppressWarnings({&quot;resource&quot;, &quot;unchecked&quot;})
<img src="https://images.velog.io/images/ruinak_4127/post/9d47fd6d-6917-44c2-b84e-2d6db0954d58/Screenshot_26.png" alt=""></p>
</li>
</ul>
<h4 id="출처-httpsktkotistorycomentryjava의-suppresswarnings-사용하기-ktko-개발-블로그와-여행-일기">출처: <a href="https://ktko.tistory.com/entry/Java%EC%9D%98-SuppressWarnings-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0">https://ktko.tistory.com/entry/Java의-SuppressWarnings-사용하기</a> [KTKO 개발 블로그와 여행 일기]</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[DAO vs DTO vs VO]]></title>
            <link>https://velog.io/@ruinak_4127/DAO-vs-DTO-vs-VO</link>
            <guid>https://velog.io/@ruinak_4127/DAO-vs-DTO-vs-VO</guid>
            <pubDate>Thu, 23 Dec 2021 07:45:53 GMT</pubDate>
            <description><![CDATA[<h2 id="1-daodata-access-object">1. DAO(Data Access Object)</h2>
<ul>
<li><p>데이터베이스의 data에 접근하기 위한 객체이며 데이터베이스 접근을 하기 위한 로직과 비즈니스 로직을 분리하기 위해 사용합니다.</p>
</li>
<li><p>사용자는 자신이 필요한 Interface를 DAO에게 던지고 DAO는 이 Interface를 구현한 객체를 사용자에게 편리하게 사용할 수 있도록 반환합니다.</p>
</li>
<li><p>DAO는 데이터베이스와 연결할 Connection까지 설정되어 있는 경우가 많습니다.</p>
</li>
<li><p>현재 쓰이는 MyBatis 등을 사용할 경우 커넥션풀까지 제공되고 있기 때문에 DAO를 별도로 만드는 경우는 드뭅니다.</p>
</li>
</ul>
<h2 id="2-dtodata-transfer-object">2. DTO(Data Transfer Object)</h2>
<ul>
<li><p>VO라고도 표현하며 계층 간 데이터 교환을 위한 자바 빈즈(Java Beans)입니다.</p>
</li>
<li><p>데이터베이스 레코드의 데이터를 매핑하기 위한 데이터 객체를 말합니다. </p>
</li>
<li><p>DTO는 보통 로직을 가지고 있지 않고 data와 그 data에 접근을 위한 getter, setter만 가지고 있습니다.</p>
</li>
<li><p>정리하면 DTO는 Database에서 Data를 얻어 Service나 Controller 등으로 보낼 때 사용하는 객체를 말합니다. </p>
</li>
</ul>
<h3 id="dto-클래스-예제">DTO 클래스 예제</h3>
<pre><code>public class PersonDTO {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}</code></pre><ul>
<li><p>위의 클래스를 보면 getter/setter가 존재합니다.</p>
</li>
<li><p>여기서 중요한 건 Property(프로퍼티) 개념인데 자바는 Property가 문법적으로 제공되지 않습니다.</p>
</li>
<li><p>자바에서 Property라는 개념을 사용하기 위해 지켜야 할 약속이 있습니다.</p>
</li>
<li><p>setter/getter에서 set과 get 이후에 나오는 단어가 Property라고 약속하는 것이며, 위 클래스에서 프로퍼티는 name과 age입니다.</p>
</li>
<li><p>중요한 것은 프로퍼티가 멤버 변수 name, age로 결정되는 것이 아닌 getter/setter에서의 name과 age 임을 명심해야 합니다.</p>
</li>
<li><p>멤버 변수는 아무렇게 지어도 영향이 없고 getter/setter로 프로퍼티(데이터)를 표현한다는 것입니다.</p>
</li>
<li><p>자바는 다양한 프레임워크에서 데이터 자동화 처리를 위해 리플렉션 기법을 사용하는데, 데이터 자동화 처리에서 제일 중요한 것은 표준 규격입니다. </p>
</li>
<li><p>예를 들어 위 클래스 DTO에서 프로퍼티가 name, age라면 name, age의 키값으로 들어온 데이터는 리플렉션 기법으로 setter를 실행시켜 데이터를 넣을 수 있습니다.</p>
</li>
<li><p>중요한 것은, 우리가 setter를 요청하는 것이 아닌 프레임워크 내부에서 setter가 실행된다는 점입니다.</p>
</li>
<li><p>layer 간(특히 서버 =&gt; 뷰로 이동 등)에 데이터를 넘길 때 DTO를 쓰면 편하다는 것이 이런 이유 때문입니다. </p>
</li>
<li><p>뷰에 있는 form에서 name 필드 값을 프로퍼티에 맞춰 넘겼을 때 받아야 하는 곳에서 일일이 처리하는 것이 아니라 name 속성의 이름과 매칭되는 프로퍼티에 자동적으로 DTO가 인스턴스화되어 PersonDTO를 자료형으로 값을 받을 수 있습니다. </p>
</li>
</ul>
<h2 id="3-vovalue-object">3. VO(Value Object)</h2>
<ul>
<li><p>VO는 DTO와 혼용해서 쓰이긴 하지만 미묘한 차이가 있습니다.</p>
</li>
<li><p>VO는 값 오브젝트로써 값을 위해 쓰입니다. </p>
</li>
<li><p>자바는 값 타입을 표현하기 위해 불변 클래스를 만들어 사용하는데, 불변이라는 것은 read only 특징을 가집니다.</p>
</li>
<li><p>DTO와 VO의 공통점은 넣어진 데이터를 getter를 통해 사용하므로 주 목적은 같으나 DAO는 가변적인 성격을 가진 클래스이며(setter 활용) 그에 비해 VO는 불변의 성격을 가졌기에 차이점이 있습니다.</p>
</li>
</ul>
<h4 id="출처--httpsmblognavercomcjhol2107221757079506">출처 : <a href="https://m.blog.naver.com/cjhol2107/221757079506">https://m.blog.naver.com/cjhol2107/221757079506</a></h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 분석하기]]></title>
            <link>https://velog.io/@ruinak_4127/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%B6%84%EC%84%9D%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ruinak_4127/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%B6%84%EC%84%9D%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 23 Dec 2021 05:57:24 GMT</pubDate>
            <description><![CDATA[<h2 id="1-maven-dependencies">1. Maven Dependencies</h2>
<p><img src="https://images.velog.io/images/ruinak_4127/post/06373e65-4ddc-4d39-a254-ca9630983b3c/Screenshot_23.png" alt=""></p>
<ul>
<li><p>Maven Dependencies는 Maven에서 자동적으로 받아오는 라이브러리들을 확인할 수 있는 곳입니다.
<img src="https://images.velog.io/images/ruinak_4127/post/f4c237f6-8d41-44be-9997-8d021d855bb4/Screenshot_22.png" alt=""></p>
</li>
<li><p>프로젝트 내에서 태그를 이용해 간단하게 라이브러리를 추가할 수 있는데, 이 역할을 pom.xml이 담당합니다.</p>
<h3 id="ltproperties">&amp;ltproperties&gt;</h3>
</li>
<li><p>&amp;ltproperties&gt;&amp;lt/properties&gt; 태그는 변수의 개념으로 많이 사용되는 변수를 성넝해서 밑에서 편하게 쓰기 위해서 사용합니다.</p>
<ul>
<li>많이 사용되는 값을 변수로 지정하며, 수정의 용이함이 있기에 일일이 찾아서 수정할 필요가 없습니다.
<img src="https://images.velog.io/images/ruinak_4127/post/976dcfbf-72af-46f0-a94c-bf3dc65817f7/Screenshot_24.png" alt=""></li>
</ul>
</li>
<li><p>위 이미지에서와 같이 &lt;egovframework.rte.version&gt;3.1.0&lt;/egovframework.rte.version&gt;처럼 변수 선언을 해놓으면 아래와 같이 중복되는 부분에서 ${egovframework.rte.version}로 사용할 수 있습니다.</p>
<ul>
<li>만약 버전이 바뀌면 선언한 곳의 버전만 수정해 주면 됩니다.
<img src="https://images.velog.io/images/ruinak_4127/post/044c4e60-6ed7-4ce3-b52b-6b5503c33cfc/Screenshot_25.png" alt=""><h3 id="ltrepositories">&amp;ltrepositories&gt;</h3>
</li>
</ul>
</li>
<li><p>&amp;ltrepositories&gt;&amp;lt/repositories&gt; 태그는 실제 라이브러리를 다운 받을 장소를 의미합니다.</p>
<h3 id="ltdependency">&amp;ltdependency&gt;</h3>
</li>
<li><p>&amp;ltdependency&gt;&amp;lt/dependency&gt; 태그는 하나의 라이브러리를 의미하며 알아둬야 할 중요한 태그입니다.</p>
</li>
<li><p>이태그를 이용해서 라이브러리를 추가하거나 삭제할 수 있습니다.</p>
</li>
<li><p>번거롭게 원하는 라이브러리를 직접 다운받아 폴더에 넣지 않아도 태그 하나로 라이브러리를 추가할 수 있습니다.</p>
</li>
</ul>
<h2 id="2-webxml">2. web.xml</h2>
<p><img src="https://images.velog.io/images/ruinak_4127/post/4a87979f-6a7d-4e81-80ed-1b63b8601a23/Screenshot_21.png" alt=""></p>
<ul>
<li><p>web.xml은 tomcat(WAS)이 최초 구동될 때, WEB-INF 디렉토리에 존재하는 web.xml을 읽고, 그에 해당하는 웹 어플리케이션 설정을 구성합니다.</p>
</li>
<li><p>서버가 구동되면 제일 먼저 인식하는 파일입니다.</p>
<h3 id="스프링-context-설정">스프링 context 설정</h3>
<pre><code>&lt;context-param&gt;
      &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
      &lt;param-value&gt;/WEB-INF/spring/root-context.xml&lt;/param-value&gt;
&lt;/context-param&gt;

</code></pre></li>
</ul>
<p>출처: <a href="https://to-dy.tistory.com/14">https://to-dy.tistory.com/14</a> [todyDev]</p>
<pre><code>- 스프링 context 설정 파일 목록을 불러오기 위한 곳입니다.

- &amp;ltparam-value&gt;에서 context 경로를 설정할 수 있습니다.
### DispatcherServlet 설정</code></pre><servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
</servlet>
```
- &ltservlet> 태그를 이용해서 DispatcherServlet을 설정할 수 있습니다.
### 요청 URL
```
<servlet-mapping>
     <servlet-name>appServlet</servlet-name>
     <url-pattern>/</url-pattern>
</servlet-mapping>
```
- 요청 URL 패턴을 설정합니다.

<ul>
<li><p>서블릿에서 어떠한 요청을 할 때, 이 패턴을 통해서만 요청이 전달됩니다.</p>
</li>
<li><p>html 등의 직접적인 요청은 전달되지 않으며 보통 *.do를 사용</p>
</li>
</ul>
<h2 id="3-servlet-contextxml">3. servlet-context.xml</h2>
<ul>
<li>서블릿이란 자바에서 동적 웹 프로젝트를 개발할 때, 사용자의 요청과 응답을 처리해주는 역할을 합니다.</li>
</ul>
<h3 id="viewresolver-설정">ViewResolver 설정</h3>
<pre><code>&lt;beans:bean class=&quot;org.springframework.web.servlet.view.InternalResourceViewResolver&quot;&gt;
        &lt;beans:property name=&quot;prefix&quot; value=&quot;/WEB-INF/views/&quot; /&gt;
        &lt;beans:property name=&quot;suffix&quot; value=&quot;.jsp&quot; /&gt;
    &lt;/beans:bean&gt;


출처: https://to-dy.tistory.com/14 [todyDev]</code></pre><ul>
<li><p>Controller에서 ModelAndView로 뷰이름을 설정하는데 이 뷰이름과 매칭되는 것을 찾기 위해 사용됩니다.</p>
</li>
<li><p>Controller에서 처리한 결과를 생성할 View를 결정합니다.</p>
</li>
<li><p>서블릿 설정이 자동으로 prefix와 suffix를 붙이는 역할을 합니다.</p>
<h3 id="bean-설정">Bean 설정</h3>
<pre><code>&lt;context:component-scan base-package=&quot;com.tody.lovely&quot; /&gt;
</code></pre></li>
</ul>
<p>출처: <a href="https://to-dy.tistory.com/14">https://to-dy.tistory.com/14</a> [todyDev]</p>
<pre><code>- 스프링에서 사용하는 Bean을 일일이 xml 선언하지 않고 필요한 것을 어노테이션을 자동으로 인식하게 해줍니다.

## 4. root-context.xml</code></pre><?xml version="1.0" encoding="UTF-8"?>
<p><beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"></p>
<pre><code>&lt;!-- Root Context: defines shared resources visible to all other web components --&gt;</code></pre></beans>
```
- 스프링 관련 여러가지 설정 파일들을 등록하여 읽을 수 있는 곳입니다.

<ul>
<li>구조를 재정의하면서 context-*.xml로 변경되어 여러 설정 파일들을 등록하게 됩니다.</li>
</ul>
<h2 id="5-controller">5. Controller</h2>
<h3 id="controller">@Controller</h3>
<pre><code>@Controller
public class HomeController {</code></pre><ul>
<li><p>Controller 애노테이션을 설정한 것입니다.</p>
</li>
<li><p>웹 클라이언트에서 들어온 요청을 해당 비즈니스 로직으로 분기시켜주고, 수행 결과의 응답을 해주는 Dispatcher 역할을 합니다.</p>
<h3 id="requestmapping">@RequestMapping</h3>
<pre><code>@RequestMapping(value = &quot;/&quot;, method = RequestMethod.GET)
public String home(Locale locale, Model model) {</code></pre></li>
<li><p>웹 클라이언트에서 들어온 요청에 해당하는 비즈니스 로직을 찾아주는 역할을 합니다.</p>
</li>
<li><p>value에 적힌게 요청 url인데, jsp에서 주는 경로와 다르면 찾지를 못하기 때문에 오타나 url 주소에 주의해야 합니다.</p>
</li>
<li><p>method에 GET 방식인지 POST 방식인지 알 수 있습니다.</p>
<h3 id="modelandview-model">ModelAndView Model</h3>
<pre><code>model.addAttribute(&quot;serverTime&quot;, formattedDate );
</code></pre></li>
</ul>
<p>return &quot;home&quot;</p>
<pre><code>- model.addAttribute(&quot;serverTime&quot;, formattedDate );는 비즈니스 로직을 수행한 결과를 화면에 보내주는 역할을 합니다.

- serverTime이라는 이름으로 formattedDate를 전송함을 의미합니다.

- return &quot;home&quot;은 수행 결과를 어디로 보내줄 지 명시합니다.

- home은 home.jsp 파일을 의미하고 서블릿 설정에서 자동으로 prefix와 suffix를 붙여줍니다.

## 6. jsp(View)
### ModelAndView View
- model로 보내진 serverTime이 view에서 ${serverTime} 방식으로 사용됨을 볼 수 있습니다. 

- ${serverTime} 부분에서 서버에서 넘어온 결과(formattedDate)를 화면에 보여줍니다.

## 7. test 디렉토리
- 삭제해도 된다. 

## 8. log4j.xml
- Log4j는 자바기반의 로깅 유틸리티로 Apache에서 만든 오픈소스 라이브러리입니다.

- 개발을 할 때 콘솔에 내용을 찍어 보고 싶을 때 system.out.println(); 을 사용해 보았을 것인데, 그게 바로 로그입니다.

- 스프링에서는 system.out.println();를 출력하게 되면 성능에 큰 영향을 미치므로 안씁니다.

- 그러므로 성능에 영향을 주지 않는 Log4j를 주로 사용한다.

- Log4j는 옵션 설정을 통해서 선택적으로 로그를 남기거나 특정 파일에 로그를 생성하는 등 다양한 이점을 가지고 있다.

#### 출처 : https://to-dy.tistory.com/14</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[@Controller와 @RestController]]></title>
            <link>https://velog.io/@ruinak_4127/Controller%EC%99%80-RestController-hgop929t</link>
            <guid>https://velog.io/@ruinak_4127/Controller%EC%99%80-RestController-hgop929t</guid>
            <pubDate>Mon, 20 Dec 2021 08:41:42 GMT</pubDate>
            <description><![CDATA[<h2 id="controller-와-restcontroller">@Controller 와 @RestController</h2>
<ul>
<li><p>Spring에서 컨트롤러를 지정해주기 위한 어노테이션은 @Controller와 @RestController가 있습니다.</p>
</li>
<li><p>전통적인 Spring MVC 컨트롤러인 @Controller와 RESTful 웹 서비스의 컨트롤러인 @RestController의 주요한 차이점은</p>
</li>
<li><p>HTTP Response Body가 생성되는 방식입니다.</p>
</li>
<li><p>@Controller의 역할은 Model 객체를 만들어 데이터를 담고 View를 반환하는 것이고,</p>
</li>
<li><p>@RestController는 단순히 객체만을 반환하고 객체 데이터는 JSON 또는 XML 형식으로 HTTP 응답에 담아 전송합니다.</p>
</li>
<li><p>물론 @Controller도 @ResponseBody를 사용해서 만들 수 있지만 이런 방식은 RESTful 웹 서비스의 기본 동작이기 때문에</p>
</li>
<li><p>Spring은 @Controller와 @ResponseBody의 동작을 조합한 @RestController를 도입했습니다.</p>
</li>
<li><p>아래의 코드는 Spring MVC에서 동일한 동작을 합니다.</p>
</li>
</ul>
<pre><code>@Controller
@ResponseBody
public class MVCController {
    business logic...
}

@RestController
public class RestFulController {
    business logic...
}</code></pre><ul>
<li>@RestController는 @Controller와 @ResponseBody의 동작을 하나로 결합한 컨트롤러라 보시면 됩니다.</li>
</ul>
<h2 id="spring에서-controller와-restcontroller의-차이점">Spring에서 @Controller와 @RestController의 차이점</h2>
<ul>
<li><p>@Controller는 클래스를 Spring MVC 컨트롤러로 표시하는데 사용되고, @RestController는 RESTful 웹 서비스에서 사용되는 특수 컨트롤러이며 @Controller + @Response와 동일하다.</p>
</li>
<li><p>@Controller와 @RestController의 주요 차이점 중 하나는 @RestController를 표시하면 모든 메소드가 뷰 대신 객체로 작성된다.</p>
</li>
<li><p>@Controller는 @Component 주석이 달려있고, @RestController는 아래와 같이 @Controller와 @ResponseBody 주석이 달린 편의 컨트롤러이다.</p>
<pre><code>@Target(value=TYEP) 
@Retention(value=RUNTIME) 
@Documented 
@Component 
public @interface Controller 
</code></pre></li>
</ul>
<p>@Target(value=TYEP) 
@Retention(value=RUNTIME) 
@Documented 
@Controller 
@ResponseBody 
public @interface RestController</p>
<p>```</p>
<h2 id="일반적인-spring-mvc-work-flow">일반적인 Spring MVC Work-flow</h2>
<h3 id="controller---view">Controller - View</h3>
<ul>
<li>@Controller는 주로 View를 반환하기 위해 사용합니다. 아래와 같은 과정을 통해 Spring MVC Container는 Client의 요청으로부터 View를 반환합니다.
<img src="https://images.velog.io/images/ruinak_4127/post/1adfc0c2-8ae2-4291-9025-bd1b37023907/Screenshot_6.png" alt=""></li>
<li>@Controller가 View를 반환하기 위해서는 View Resolver가 사용되며, ViewResolver 설정에 맞게 View를 찾아 렌더링 합니다.</li>
</ul>
<h3 id="controller---data">Controller - Data</h3>
<ul>
<li>Spring MVC의 컨트롤러에서도 Data를 반환해야 하는 경우도 있습니다. 데이터를 반환하기 위해 @ResponseBody 어노테이션을 사용해주면, 이를 통해 Controller도 JSON 형태로 데이터를 반환할 수 있습니다.
<img src="https://images.velog.io/images/ruinak_4127/post/079e56c4-80fb-4ab6-a6d6-c2e8011b3811/Screenshot_7.png" alt=""></li>
</ul>
<ol>
<li><p>Client는 URI 형식으로 웹 서비스에 요청을 보낸다.</p>
</li>
<li><p>Mapping되는 Handler와 그 Type을 찾는 DispatcherServlet이 요청을 인터셉트한다.</p>
</li>
<li><p>@ResponseBody를 사용하여 Client에게 JSON 형태로 데이터를 반환한다.</p>
</li>
</ol>
<h3 id="restcontroller">RestController</h3>
<ul>
<li><p>@RestController는 Spring MVC Controller에 @ResponseBody가 추가된 것입니다. 이로써 당연한 것은</p>
</li>
<li><p>RestController의 주용도는 JSON 형태로 객체 데이터를 반환하는 것입니다.
<img src="https://images.velog.io/images/ruinak_4127/post/4ff80294-0915-4b00-9804-d71494d9f617/Screenshot_8.png" alt=""></p>
</li>
</ul>
<ol>
<li><p>Client는 URI 형식으로 웹 서비스에 요청을 보낸다.</p>
</li>
<li><p>Mapping되는 Handler와 그 Type을 찾는 DispatcherServlet이 요청을 인터셉트한다.</p>
</li>
<li><p>RestController는 해당 요청을 처리하고 데이터를 반환한다.</p>
<h4 id="출처-httpsdev-cocotistorycom84-슬기로운-개발생활😃">출처: <a href="https://dev-coco.tistory.com/84">https://dev-coco.tistory.com/84</a> [슬기로운 개발생활😃]</h4>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[Service와 ServiceImpl]]></title>
            <link>https://velog.io/@ruinak_4127/Service%EC%99%80-ServiceImpl</link>
            <guid>https://velog.io/@ruinak_4127/Service%EC%99%80-ServiceImpl</guid>
            <pubDate>Mon, 20 Dec 2021 07:22:55 GMT</pubDate>
            <description><![CDATA[<h1 id="다형성">다형성</h1>
<h2 id="service와-serviceimpl">Service와 ServiceImpl</h2>
<ul>
<li><p>다형성(polymorphism)이란 하나의 객체가 여러 가지 타입을 가질 수 있는 것을 의미한다. </p>
</li>
<li><p>자바에서는 보통 부모 클래스를 자식이 상속받아 기능을 확장하거나 변경하는 방식으로 쓴다. </p>
</li>
<li><p>이걸 오늘의 주제인 Service와 ServiceImpl에 대입해서 본다면, Service라는 부모를 ServiceImpl이라는 자식이 상속받게 되는 것이다.</p>
<h2 id="impl의-의미">Impl의 의미</h2>
</li>
<li><p>근데 왜 이름들이 Service와 ServiceImpl인걸까? 그건 부모인 Service를 interface로 만들고, 자식인 ServiceImpl 클래스가 부모를 상속받아 implement하는 구현체이기 때문이다. </p>
</li>
<li><p>이렇게 직관적으로 자식 클래스의 이름을 ~Impl로 짓는 것은 해외의 개발자들도 따르는 naming convention이다.</p>
</li>
<li><p>이제 부모와 자식이라고 부르는 대신에 interface인 Service를 역할, 이걸 상속받는 자식 클래스인 ServiceImpl을 구현이라고 나눠서 생각하면 쉽게 이해할 수 있다.</p>
</li>
</ul>
<h2 id="예시">예시</h2>
<ul>
<li><p>방금 전에 “키보드”에 대한 예시를 들었다. </p>
</li>
<li><p>이걸 역할과 구현으로 나눠보면, “타자를 치는” 역할을 구현하기 위해 사용자는 빨간색 빛이 나는 키보드 A를 쓸 수도 있고, 무지개색 키보드 B를 쓸 수도 있다. 바꿔도 키보드의 역할에는 영향이 없다. </p>
</li>
<li><p>이걸 Service와 ServiceImpl로 생각하면 KeyboardService라는 interface를 implement하는 AkeyboardServiceImpl과 BkeyboardServiceImpl class들이 “타자를 치는” 기능을 구현하는 것이다.</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/ruinak_4127/post/abaa40ff-cb35-4c5e-b14f-c5ce879986dd/Screenshot_5.png" alt=""></p>
<h2 id="결론">결론</h2>
<ul>
<li>이렇게 역할과 구현으로 나누게 되면 역할 부분을 새로운 방식으로 구현해야 할 때 구현하는 부분만 손쉽게 바꿀 수 있게 되기 때문에 Service라는 interface를 만든 후 해당 역할을 구현하는 ServiceImpl class를 만들게 되는 것이다!<h4 id="출처--httpsitzjamie96githubio20210124spring-service-and-serviceimpl">출처 : <a href="https://itzjamie96.github.io/2021/01/24/spring-service-and-serviceimpl/">https://itzjamie96.github.io/2021/01/24/spring-service-and-serviceimpl/</a></h4>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring MVC Life Cycle]]></title>
            <link>https://velog.io/@ruinak_4127/Spring-MVC-Life-Cycle</link>
            <guid>https://velog.io/@ruinak_4127/Spring-MVC-Life-Cycle</guid>
            <pubDate>Mon, 20 Dec 2021 07:15:35 GMT</pubDate>
            <description><![CDATA[<h2 id="spring-mvc-처리-흐름">Spring MVC 처리 흐름</h2>
<p><img src="https://images.velog.io/images/ruinak_4127/post/c0a8f7cc-7b5f-4dc2-8479-3f41a842edf1/Screenshot_4.png" alt=""></p>
<ul>
<li>브라우저로 부터 요청(Request)을 받고 응답(Response)하기까지 Spring MVC의 처리 흐름은 위와 같다.</li>
</ul>
<h3 id="1-filter">1. Filter</h3>
<ul>
<li><p>먼저 브라우저로부터 요청이 들어오면 일단 Filter을 거치게 된다. </p>
</li>
<li><p>Filter에서 하는 대표적인 처리를 보면 Encoding이 있다.</p>
</li>
</ul>
<h3 id="2-dispatcherservlet">2. DispatcherServlet</h3>
<ul>
<li><p>다음으로 DispatcherServlet이 Controller에 요청을 전달하기 전에 가로챈다. </p>
</li>
<li><p>요청을 가로챈 후 HandlerMapping을 통해 요청에 해당하는 적절한 Controller을 찾게 된다. </p>
</li>
<li><p>그리고 DispatcherServlet에 그것을 전달한다.</p>
</li>
</ul>
<h3 id="3-handleradapter">3. HandlerAdapter</h3>
<ul>
<li><p>DispatcherServlet은 실행할 Controller 정보를 HandlerAdapter에 전달하게 된다.</p>
</li>
<li><p>HandlerAdapter는 해당 Controller을 호출하게 된다.</p>
</li>
</ul>
<h3 id="4-controller">4. Controller</h3>
<ul>
<li><p>Controller에서는 전달된 요청을 처리한다. </p>
</li>
<li><p>예를 들어 게시판의 글 목록을 가져오는 요청을 받으면 Controller는 게시판 Service를 호출하고 Service에서는 DAO를 통해 게시판 글 목록을 가져오게 된다.  </p>
</li>
<li><p>요청을 처리한 후 그 결과를 Model에 담고, View의 이름을 HandlerAdapter에게 전달하게 된다.</p>
</li>
</ul>
<h3 id="5-viewresolver">5. ViewResolver</h3>
<ul>
<li>전달받은 View의 이름을 가지고 ViewResolver에서 매핑된 View를 찾아서 반환한다.</li>
</ul>
<h3 id="6-dispatcherservlet">6. DispatcherServlet</h3>
<ul>
<li>DispatcherServlet은 반환된 View를 넘기게 된다.</li>
</ul>
<h4 id="출처-httpsall-recordtistorycom164-세상의-모든-기록">출처: <a href="https://all-record.tistory.com/164">https://all-record.tistory.com/164</a> [세상의 모든 기록]</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[전자정부 표준 프레임워크?]]></title>
            <link>https://velog.io/@ruinak_4127/%EC%A0%84%EC%9E%90%EC%A0%95%EB%B6%80-%ED%91%9C%EC%A4%80-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC</link>
            <guid>https://velog.io/@ruinak_4127/%EC%A0%84%EC%9E%90%EC%A0%95%EB%B6%80-%ED%91%9C%EC%A4%80-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC</guid>
            <pubDate>Mon, 20 Dec 2021 04:41:05 GMT</pubDate>
            <description><![CDATA[<h1 id="전자정부-표준프레임워크란-">전자정부 표준프레임워크란 ?</h1>
<h2 id="소프트웨어-프레임워크의-정의">소프트웨어 프레임워크의 정의</h2>
<ul>
<li><p>효율적인 정보시스템 개발을 위한 코드 라이브러리, 인터페이스 규약(API; Application Programming Interface), 설정정보 등의 집합으로서 소프트웨어 구성에 필요한 기본 뼈대를 제공</p>
</li>
<li><p>광의(廣義)적으로 정보시스템의 개발․운영을 지원하는 도구 및 가이드 등을 포함</p>
<h2 id="전자정부-표준프레임워크-개념">전자정부 표준프레임워크 개념</h2>
</li>
<li><p>자바 기반의 시스템 개발․운영 시 필요한 기본기능들을 표준화하여 미리 구현해 둔 것으로, 개발자는 이를 활용 업무 기능을 구현한 후 조립함으로써 전체 시스템 완성 가능
<img src="https://images.velog.io/images/ruinak_4127/post/93f95896-40a5-4216-a302-54b7ed06c352/Screenshot_1.png" alt=""></p>
<h2 id="등장배경-및-목적">등장배경 및 목적</h2>
</li>
<li><p>“전자정부 표준프레임워크”는 공공사업에 적용되는 개발프레임워크의 표준정립으로 응용 SW 표준화, 품질 및 재사용성 향상을 목표로 합니다. 이를 통해 “전자정부 서비스의 품질향상” 및 “정보화 투자 효율성 향상”을 달성하고 대 중 소기업이 동일한 개발기반 위에서 공정경쟁이 가능하게 함</p>
<h2 id="표준프레임워크의-특징">표준프레임워크의 특징</h2>
<h3 id="개방형-표준open-standard-준수">개방형 표준(open standard) 준수</h3>
</li>
<li><p>오픈소스 기반의 범용화되고 공개된 기술의 활용으로 특정 사업자에 대한 종속성 배제</p>
<h3 id="상용-솔루션-연계">상용 솔루션 연계</h3>
</li>
<li><p>상용 솔루션과 연계가 가능한 표준을 제시하여 상호운용성 보장</p>
<h3 id="국가적-표준화-지향">국가적 표준화 지향</h3>
</li>
<li><p>민 관 학계로 구성된 자문협의회를 통해 국가적 차원의 표준화 수행</p>
<h3 id="변화-유연성">변화 유연성</h3>
</li>
<li><p>각 서비스의 모듈화로 교체가 용이하며 인터페이스 기반 연동으로 모듈간 변경영향 최소화</p>
<h2 id="표준프레임워크-연동의-효과">표준프레임워크 연동의 효과</h2>
<p><img src="https://images.velog.io/images/ruinak_4127/post/8e678e24-861f-42ab-a282-b3bdb5792d14/Screenshot_2.png" alt=""></p>
</li>
</ul>
<h1 id="표준프레임워크의-구성요소">표준프레임워크의 구성요소</h1>
<h2 id="실행환경">실행환경</h2>
<ul>
<li>자바 기반의 응용시스템 개발 시 필수적인 기능을 패턴화하여 미리 구현해 둔 라이브러리 코드 묶음<h2 id="개발환경">개발환경</h2>
</li>
<li>설계, 구현, 테스트 등 개발 생명주기(life cycle)상에 필요한 지원도구 모음<h2 id="운영환경">운영환경</h2>
</li>
<li>표준프레임워크를 기반으로 개발한 시스템에 대하여 운영 시에 필요한 의사소통 및 모니터링 도구 모음<h2 id="관리환경">관리환경</h2>
</li>
<li>표준프레임워크에 대한 기술지원, 업그레이드 등을 관리하기 위한 표준프레임워크센터 내부 업무시스템</li>
</ul>
<p>☞ 포털(<a href="http://www.egovframe.go.kr)%EC%97%90%EC%84%9C">http://www.egovframe.go.kr)에서</a> 검색 및 다운로드 가능</p>
<p>☞ 개발환경은 패키지로 다운로드 받아 사용하며, 실행환경은 개발 시 환경파일 설정을 통해 자동으로 다운로드 및 설정됨</p>
<p>☞ 운영환경은 별도 패키지로 다운로드할 수 있으며 선택적 활용 가능</p>
<p>☞ 관리환경은 표준프레임워크 지원․유지관리 전담조직인 한국정보화진흥원(NIA)에서 운영하는 시스템으로 외부로 직접적으로 제공되지 않음(일부 “기술지원” 신청 등만 제공)</p>
<h1 id="표준프레임워크의-라이선스-정책은">표준프레임워크의 라이선스 정책은?</h1>
<ul>
<li><p>표준프레임워크는 그 자체로 OSS(Open Source Software)로써 누구나 무료로 활용가능하며, 아파치(Apache) 라이선스 2.0 및 MIT 라이선스(모바일 표준프레임워크 부분)를 채택하고 있음</p>
</li>
<li><p>표준프레임워크를 구성하는 OSS가 가진 개별 라이선스 중 배포 상호주의 조항을 가진 라이선스(예; CDDL, LGPL, EPL, CPL 등)는 그대로 유지</p>
</li>
<li><p>배포 상호주의 조항이 없는 OSS와 Glueware는 아파치 라이선스를 준용</p>
</li>
<li><p>배포 상호주의 조항 : OSS를 제3자에게 배포할 때 원 라이선스와 동일한 라이선스로 배포하도록 요구하는 조항</p>
</li>
<li><p>Glueware : OSS를 사용하지 않은 순수 개발 소스코드</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[용어 정의]]></title>
            <link>https://velog.io/@ruinak_4127/%EC%9A%A9%EC%96%B4-%EC%A0%95%EC%9D%98</link>
            <guid>https://velog.io/@ruinak_4127/%EC%9A%A9%EC%96%B4-%EC%A0%95%EC%9D%98</guid>
            <pubDate>Sat, 13 Nov 2021 12:58:06 GMT</pubDate>
            <description><![CDATA[<h2 id="java">Java</h2>
<h3 id="객체-지향-프로그래밍의-특징">객체 지향 프로그래밍의 특징</h3>
<ul>
<li><strong>객체</strong> : 우리가 실생활에서 쓰는 모든 것</li>
<li><strong>객체 지향 프로그래밍</strong> : 프로그램 구현에 필요한 객체를 파악하고 역할이 무엇인지를 정의하여 상호작용을 통해 프로그램을 만드는 것을 말합니다.<h2 id="spring">Spring</h2>
</li>
<li><strong>의존성 주입</strong> : 어떤 객체가 사용하는 의존 객체를 직접 만들어 사용하는게 아니라, 주입 받아 사용하는 방법</li>
<li><strong>MVC 패턴</strong> : Model, View, Controller 개념이 합쳐지면서 생긴 방식으로 소프트웨어 공학에서 사용되는 디자인 패턴<ul>
<li><strong>Model</strong> : Model은 Controller에서 받은 데이터를 저장하는 역할을 하며, 뷰나 컨트롤러의 정보를 알아서는 안 됨<ul>
<li><strong>View</strong> : Controller로 부터 받은 Model 데이터를 바탕으로 사용자에게 표현하며, 모델과 컨트롤러의 정보를 알아서는 안 됨</li>
</ul>
</li>
<li><strong>Controller</strong> : 사용자가 접근 한 URL에 따라 요청을 파악하고 URL에 맞는 Method를 호출하여 Service와 함께 Business Logic을 처리한다. 최종적으로 나온 결과는 Model에 저장을 하고, View에 던져준다.</li>
</ul>
</li>
<li><strong>AOP</strong> : Aspect Oriented Programming의 약자로 관점 지향 프로그래밍이라고 불립니다. 관점 지향은 쉽게 말해 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 각각 모듈화하겠다는 것</li>
<li><strong>트랜잭션</strong> : DB에서 여러 작업을 진행하다가 문제가 생겼을 경우 이전 상태로 롤백하기 위해 사용되는 것, 트랜잭션은 더 이상 쪼갤 수 없는 최소 작업 단위를 의미<h2 id="jsp">JSP</h2>
</li>
<li><strong>servlet</strong> : 자바를 사용하여 웹페이지를 동적으로 생성하는 서버측 프로그램 혹은 그 사양을 말하며, 흔히 &quot;서블릿&quot;이라 불린다. 자바 서블릿은 웹 서버의 성능을 향상하기 위해 사용되는 자바 클래스의 일종</li>
<li><strong>Session Life Cycle</strong><ul>
<li>생성 : 최초로 request.getSession()이 호출될 때 container가 생성</li>
<li>사용 : 클라이언트가 세션 ID를 이용해 접속, request.getSession()을 통해 사용중인 HttpSession 객체 획득 후 사용</li>
<li>종료 : invalidate()가 호출되거나, 세션이 타임아웃 되었을 때 container가 소멸 </li>
</ul>
</li>
<li><strong>Session</strong><ul>
<li>사용자 정보를 서버에 저장</li>
<li>클라이언트의 최초 접속 시 새로운 세션을 생성하고 세션 ID 전송</li>
<li>이후 접속마다 클라이언트가 세션 ID 재전송</li>
<li>서버는 세션 ID에 해당하는 세션 정보를 획득</li>
<li>세션 ID 전송 수단으로 쿠키를 사용할 수 있음</li>
</ul>
</li>
<li><strong>Cookie</strong><ul>
<li>브라우저를 통해 사용자 정보를 클라이언트에 저장 </li>
<li>(name, value) 쌍으로 이루어진 정보</li>
<li>초기에 웹 서버에 의해 HTTP Header에 포함되어 클라이언트에게 전송</li>
<li>이후에 접속마다 클라이언트가 웹 서버에게 재전송</li>
<li>보안적 취약성으로 인해 중요 정보를 저장하지 않아야 함</li>
</ul>
</li>
<li><strong>EL표현식</strong> : 자바 빈의 프로퍼티, 값을 JSP의 표현식 &lt;%= %&gt;이나 액션 태그 <a href="jsp:useBean">jsp:useBean</a>를 사용하는것 보다 쉽고 간결하게 꺼낼수 있게 하는 기술</li>
<li><strong>JSTL</strong> : 정식 명칭은 자바서버 페이지 표준 태그 라이브러리(JavaServer Pages Standard Tag Library)이고 줄여서 JSTL이라 부른다. 위키피디아를 참조하자면, JSTL은 Java EE 기반의 웹 애플리케이션 개발 플랫폼을 위한 컴포넌트 모음</li>
<li><strong>스크립트릿</strong> : JSP페이지에서 자바 코드를 실행할 때 사용되는 코드의 블록을 말한다.</li>
<li><strong>Bean</strong> : 애플리케이션의 핵심을 이루는 객체이며, Spring IoC(Inversion of Control) 컨테이너에 의해 인스턴스화, 관리, 생성</li>
<li><strong>액션 태그</strong> : JSP 페이지 내에서 어떤 동작을 하도록 지시하는 태그</li>
<li><strong>JDBC</strong> : 자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API<h2 id="html--css">HTML / CSS</h2>
</li>
<li><strong>HTML</strong> : Hypertext Markup Languaged의 약자로 프로그래밍 언어는 아니고, 우리가 보는 웹페이지가 어떻게 구조화되어 있는지 브라우저로 하여금 알 수 있도록 하는 마크업 언어</li>
<li><strong>CSS</strong> : Cascading Style Sheets의 약자로 HTML이나 XML로 작성된 문서의 표시 방법을 기술하기 위한 스타일 시트 언어<h2 id="javascript">JavaScript</h2>
</li>
<li><strong>JavaScript</strong> : 복잡한 무언가(주기적으로 내용이 갱신되는 기능이나 능동적인 지도, 변화하는 2D/3D 그래픽, 동영상 등)를 웹페이지에 적용할 수 있게 하는 스크립트 혹은 프로그래밍 언어<h2 id="database">DataBase</h2>
<h3 id="dmldata-manipulation-language--데이터-조작어">DML(Data Manipulation Language) : 데이터 조작어</h3>
</li>
<li>SLECET, INSERT, UPDATE, DELETE</li>
<li>SLECET : 데이터베이스에 들어 있는 데이터를 조회하거나 검색하기 위한 명령어를 말하는 것으로 RETRIEVE 라고도 합니다.</li>
<li>INSERT, UPDATE, DELETE : 데이터베이스의 테이블에 들어 있는 데이터에 변형을 가하는 종류(데이터 삽입, 수정, 삭제)의 명령어들을 말합니다. <h3 id="ddldata-definition-language--데이터-정의어">DDL(Data Definition Language) : 데이터 정의어</h3>
</li>
<li>CREATE, ALTER, DROP, RENAME, TRUNCATE </li>
<li>테이블과 같은 데이터 구조를 정의하는데 사용되는 명령어들로 (생성, 변경, 삭제, 이름변경) 데이터 구조와 관련된 명령어들을 말합니다.<h3 id="dcldata-control-language--데이터-제어어">DCL(Data Control Language) : 데이터 제어어</h3>
</li>
<li>GRANT, REVOKE</li>
<li>데이터베이스에 접근하고 객체들을 사용하도록 권한을 주고 회수하는 명령어들을 말합니다.<h3 id="tcltransaction-control-language--트랜잭션-제어어">TCL(Transaction Control Language) : 트랜잭션 제어어</h3>
</li>
<li>COMMIT, ROLLBACK, SAVEPOINT</li>
<li>논리적인 작업의 단위를 묶어서 DML에 의해 조작된 결과를 작업단위(트랜잭션) 별로 제어하는 명령어를 말합니다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL 추가 정리]]></title>
            <link>https://velog.io/@ruinak_4127/SQL</link>
            <guid>https://velog.io/@ruinak_4127/SQL</guid>
            <pubDate>Thu, 04 Nov 2021 02:41:00 GMT</pubDate>
            <description><![CDATA[<h1 id="dcl-관련">DCL 관련</h1>
<h2 id="계정-생성-및-제어">계정 생성 및 제어</h2>
<h3 id="계정-생성-user200-사용자id와-1234-암호를-이용">계정 생성 user200 사용자ID와 1234 암호를 이용</h3>
<pre><code>CREATE USER user200 IDENTIFIED BY 1234;</code></pre><h3 id="계정-비밀번호-변경-1234---2345로-변경">계정 비밀번호 변경 1234 -&gt; 2345로 변경</h3>
<pre><code>ALTER USER user200 IDENTIFIED BY 2345;</code></pre><h3 id="권한-부여">권한 부여</h3>
<h4 id="connect--접속-권한">CONNECT : 접속 권한</h4>
<h4 id="resource--객체생성-수정-삭제">RESOURCE : 객체(생성, 수정, 삭제)</h4>
<h4 id="dba--데이터입력-수정-조회-삭제">DBA : 데이터(입력, 수정, 조회, 삭제)</h4>
<pre><code>GRANT CONNECT, RESOURCE, DBA TO TESTER;</code></pre><h1 id="새로운-테이블-생성">새로운 테이블 생성</h1>
<pre><code>CREATE TABLE USERTBL2(
    U_ID VARCHAR2(30),
    U_PW VARCHAR2(200),
    U_NAME VARCHAR2(20),
    U_AGE NUMBER,
    U_PHONE VARCHAR2(20),
    U_DAY DATE
);</code></pre><h2 id="설정-변경">설정 변경</h2>
<h3 id="id에-기본키-추가">ID에 기본키 추가</h3>
<pre><code>ALTER TABLE USERTBL2 ADD PRIMARY KEY(U_ID);</code></pre><h3 id="새로운-컬럼-추가--이메일">새로운 컬럼 추가 : 이메일</h3>
<pre><code>ALTER TABLE USERTBL2 ADD U_EMAIL VARCHAR2(50);</code></pre><h3 id="이름-컬럼에-not-null-추가-modify-사용">이름 컬럼에 NOT NULL 추가, MODIFY 사용</h3>
<pre><code>ALTER TABLE USERTBL2 MODIFY U_NAME NOT NULL;</code></pre><h3 id="컬럼의-길이-변경-20---24">컬럼의 길이 변경 20 -&gt; 24</h3>
<pre><code>ALTER TABLE USERTBL2 MODIFY U_NAME VARCHAR2(24);</code></pre><h2 id="데이터-관리">데이터 관리</h2>
<h3 id="데이터-추가">데이터 추가</h3>
<pre><code>INSERT INTO USERTBL2(U_ID, U_PW, U_NAME, U_AGE, U_PHONE, U_DAY, U_EMAIL)
VALUES (&#39;JOIN&#39;, &#39;123&#39;, &#39;가입&#39;, &#39;19&#39;, &#39;010-1478-9632&#39;, CURRENT_DATE, &#39;123@123.COM&#39;);</code></pre><h3 id="데이터-수정">데이터 수정</h3>
<pre><code>UPDATE USERTBL2 SET U_NAME = &#39;회원가입&#39; WHERE U_ID = &#39;JOIN&#39;;</code></pre><h3 id="삭제하기">삭제하기</h3>
<pre><code>DELETE FROM USERTBL2 WHERE U_ID = &#39;JOIN&#39;;
DROP TABLE USERTBL2;</code></pre><h3 id="정렬-조회">정렬 조회</h3>
<pre><code>SELECT * FROM ITEM ORDER BY I_NAME ASC;</code></pre><h3 id="특정-컬럼만-조회하기">특정 컬럼만 조회하기</h3>
<pre><code>SELECT I_NAME, I_PRICE, I_COUNT FROM ITEM ORDER BY I_PRICE DESC;</code></pre><h3 id="특정-컬럼-조회-및-날짜의-포멧-변경">특정 컬럼 조회 및 날짜의 포멧 변경</h3>
<pre><code>SELECT I_NO, I_NAME, TO_CHAR(I_DAY, &#39;YYYY-MM-DD HH24:MI&#39;) FROM ITEM ORDER BY I_NO ASC;</code></pre><h3 id="필요한-컬럼-값과-날짜-숫자-포멧-변경-물품-번호별-정렬">필요한 컬럼 값과 날짜, 숫자 포멧 변경, 물품 번호별 정렬</h3>
<pre><code>SELECT 
    I_NO, I_NAME, TO_CHAR(I_PRICE, &#39;999,999&#39;) STR_PRICE,
    TO_CHAR(I_DAY, &#39;YYYY-MM-DD HH24&#39;) STR_DATE
FROM
    ITEM;</code></pre><h3 id="페이지네이션--테이블을-페이지처럼-볼-수-있게-해줌">페이지네이션 : 테이블을 페이지처럼 볼 수 있게 해줌</h3>
<pre><code>SELECT * FROM 
    (
        SELECT 
            I_NO, I_NAME, TO_CHAR(I_PRICE, &#39;999,999&#39;) STR_PRICE,
            TO_CHAR(I_DAY, &#39;YYYY-MM-DD HH24&#39;) STR_DATE,
            ROW_NUMBER() OVER (ORDER BY I_NO ASC) ROWN
        FROM
            ITEM
    )
WHERE ROWN BETWEEN 1 AND 10;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[ORACLE 실습 내용]]></title>
            <link>https://velog.io/@ruinak_4127/ORACLE-%EC%8B%A4%EC%8A%B5-%EB%82%B4%EC%9A%A9</link>
            <guid>https://velog.io/@ruinak_4127/ORACLE-%EC%8B%A4%EC%8A%B5-%EB%82%B4%EC%9A%A9</guid>
            <pubDate>Wed, 03 Nov 2021 08:02:02 GMT</pubDate>
            <description><![CDATA[<pre><code>-- DDL 정의어
-- 회원가입용 테이블(ID, Passwrod, Name, Age, Phone, Day)
CREATE TABLE usertbl(
    ID VARCHAR2(30) PRIMARY KEY,
    PASSWORD VARCHAR2(200),
    NAME VARCHAR2(30),
    AGE NUMBER,
    PHONE VARCHAR2(30),
    DAY DATE
);
-- VARCHAR는 가변 길이
-- PRIMARY KEY는 기본값이며 중복 안 됨

-- DML 조작어
-- INSERT, UPDATE, DELETE, SELECT
-- 형식 : INSERT INTO 테이블명(컬렴명) VALUES(값들)
INSERT INTO usertbl(ID, PASSWORD, NAME, AGE, PHONE, DAY)
VALUES(&#39;test&#39;, &#39;1234&#39;, &#39;테스터&#39;, &#39;20&#39;, &#39;010-1234-5678&#39;, CURRENT_DATE);
-- COMMIT은 적용
COMMIT;
-- ROLLBACK은 되돌리기
ROLLBACK;

-- INSERT : 하나의 행 데이터 추가
INSERT INTO usertbl(ID, PASSWORD, NAME, AGE, PHONE, DAY)
VALUES(&#39;ASK&#39;, &#39;1234&#39;, &#39;질문자&#39;, &#39;20&#39;, &#39;010-1234-5678&#39;, CURRENT_DATE);
COMMIT;

-- DELETE : 하나의 행 데이터 삭제
DELETE FROM USERTBL;
ROLLBACK;
DELETE FROM usertbl WHERE ID = &#39;ASK&#39;;
DELETE FROM usertbl WHERE NAME = &#39;테스터&#39;;
DELETE FROM usertbl WHERE AGE = &#39;20&#39;;

-- UPDATE : 행 데이터 수정
UPDATE USERTBL SET NAME = &#39;기자&#39; WHERE ID = &#39;ASK&#39;;
COMMIT;
UPDATE USERTBL SET AGE = &#39;25&#39;, PHONE = &#39;010-9876-5432&#39; WHERE ID = &#39;test&#39;;
UPDATE USERTBL SET ID = &#39;TEST&#39; WHERE ID = &#39;test&#39;;

-- SELECT : 데이터 조회
SELECT * FROM USERTBL;
SELECT ID FROM USERTBL;
SELECT PASSWORD FROM USERTBL;
SELECT NAME FROM USERTBL;
SELECT AGE FROM USERTBL;
SELECT PHONE FROM USERTBL;
SELECT DAY FROM USERTBL;

-------------------------------------------------------------
-------------------------------------------------------------
-- 물품 테이블명 : ITEM
-- 번호, 이름, 설명, 가격, 수량, 등록일
-- 번호는 PRIMARY KEY

-- 테이블 생성
CREATE TABLE ITEM(
    NO NUMBER PRIMARY KEY,
    NAME VARCHAR2(100),
    CONTENT CLOB,
    PRICE NUMBER,
    COUNT NUMBER,
    DAY TIMESTAMP
);

-- SEQUENCE 생성
CREATE SEQUENCE SEQ_ITEM_NO START WITH 1 INCREMENT BY 1 NOCACHE NOMAXVALUE;

-- ITEM 테이블에 데이터 입력
INSERT INTO ITEM(NO, NAME, CONTENT, PRICE, COUNT, DAY) 
VALUES(SEQ_ITEM_NO.NEXTVAL, &#39;맥주&#39;, &#39;보리로 만든 술&#39;, 3500, 20, CURRENT_DATE);
INSERT INTO ITEM(NO, NAME, CONTENT, PRICE, COUNT, DAY) 
VALUES(SEQ_ITEM_NO.NEXTVAL, &#39;소주&#39;, &#39;한국 증류주&#39;, 4000, 30, CURRENT_DATE);
INSERT INTO ITEM(NO, NAME, CONTENT, PRICE, COUNT, DAY) 
VALUES(SEQ_ITEM_NO.NEXTVAL, &#39;와인&#39;, &#39;포도로 만든 발효주&#39;, 4900, 12, CURRENT_DATE);
INSERT INTO ITEM(NO, NAME, CONTENT, PRICE, COUNT, DAY) 
VALUES(SEQ_ITEM_NO.NEXTVAL, &#39;럼&#39;, &#39;용설과로 만든 비싼 술&#39;, 24900, 1, CURRENT_DATE);
INSERT INTO ITEM(NO, NAME, CONTENT, PRICE, COUNT, DAY) 
VALUES(SEQ_ITEM_NO.NEXTVAL, &#39;보드카&#39;, &#39;감자로 만든 독한 술&#39;, 18900, 1, CURRENT_DATE);
COMMIT;
SELECT * FROM ITEM;
UPDATE ITEM SET COUNT = &#39;5&#39; WHERE COUNT = &#39;1&#39;;

-------------------------------------------------------------
-------------------------------------------------------------
-- 주문 테이블명 : REQUEST 
-- 주문 번호, 주문 수량, 주문 일자, 주문자 정보, 물품 정보
-- 주문 번호는 PRIMARY KEY
-- 주문자 정보는 USER의 ID와 일치
-- 물품 정보는 ITEM의 NO와 일치

CREATE TABLE REQUEST(
    NO NUMBER PRIMARY KEY,
    COUNT NUMBER,
    DAY TIMESTAMP,
    R_ID VARCHAR2(30),
    R_ITEM NUMBER
);

-- 외래키 제약조건
-- 주문자 정보, 물품 정보
ALTER TABLE REQUEST ADD FOREIGN KEY(R_ID) REFERENCES USERTBL(ID);
ALTER TABLE REQUEST ADD FOREIGN KEY(R_ITEM) REFERENCES ITEM(NO);

-- 시퀀스 생성, 주문 번호에 사용
CREATE SEQUENCE SEQ_REQUEST_NO START WITH 1 INCREMENT BY 1 NOCACHE NOMAXVALUE;

-- 주문하기
INSERT INTO REQUEST(NO, COUNT, DAY, R_ID, R_ITEM)
VALUES (SEQ_REQUEST_NO.NEXTVAL, 5, CURRENT_DATE, &#39;TEST&#39;, 1);

INSERT INTO REQUEST(NO, COUNT, DAY, R_ID, R_ITEM)
VALUES (SEQ_REQUEST_NO.NEXTVAL, 10, CURRENT_DATE, &#39;TEST&#39;, 3);

INSERT INTO REQUEST(NO, COUNT, DAY, R_ID, R_ITEM)
VALUES (SEQ_REQUEST_NO.NEXTVAL, 3, CURRENT_DATE, &#39;TEST&#39;, 5);

INSERT INTO REQUEST(NO, COUNT, DAY, R_ID, R_ITEM)
VALUES (SEQ_REQUEST_NO.NEXTVAL, 20, CURRENT_DATE, &#39;ASK&#39;, 2);

SELECT * FROM USERTBL;
SELECT * FROM ITEM;
SELECT * FROM REQUEST;

-- 사용자 3명 추가
INSERT INTO USERTBL(ID, PASSWORD, NAME, AGE, PHONE, DAY)
VALUES (&#39;ABC&#39;, &#39;1234&#39;, &#39;일반인&#39;, 30, &#39;010-1122-3344&#39;, CURRENT_DATE);

INSERT INTO USERTBL(ID, PASSWORD, NAME, AGE, PHONE, DAY)
VALUES (&#39;QWE&#39;, &#39;1234&#39;, &#39;자영업자&#39;, 30, &#39;010-5566-7788&#39;, CURRENT_DATE);

INSERT INTO USERTBL(ID, PASSWORD, NAME, AGE, PHONE, DAY)
VALUES (&#39;ZXC&#39;, &#39;1234&#39;, &#39;소비자&#39;, 30, &#39;010-5555-6666&#39;, CURRENT_DATE);

SELECT * FROM USERTBL;

-- 물품 3개 추가
INSERT INTO ITEM(NO, NAME, CONTENT, PRICE, COUNT, DAY)
VALUES (SEQ_ITEM_NO.NEXTVAL, &#39;브랜디&#39;, &#39;와인을 증류한 증류주&#39;, 69800, 3, CURRENT_DATE);

INSERT INTO ITEM(NO, NAME, CONTENT, PRICE, COUNT, DAY)
VALUES (SEQ_ITEM_NO.NEXTVAL, &#39;버번위스키&#39;, &#39;오크통위스키&#39;, 119800, 7, CURRENT_DATE);

INSERT INTO ITEM(NO, NAME, CONTENT, PRICE, COUNT, DAY)
VALUES (SEQ_ITEM_NO.NEXTVAL, &#39;샹그리아&#39;, &#39;가벼운 주류&#39;, 7900, 16, CURRENT_DATE);

SELECT * FROM ITEM;

-- 주문 6개 추가
INSERT INTO REQUEST(NO, COUNT, DAY, R_ID, R_ITEM)
VALUES (SEQ_REQUEST_NO.NEXTVAL, 6, CURRENT_DATE, &#39;ABC&#39;, 8);

INSERT INTO REQUEST(NO, COUNT, DAY, R_ID, R_ITEM)
VALUES (SEQ_REQUEST_NO.NEXTVAL, 2, CURRENT_DATE, &#39;ZXC&#39;, 7);

INSERT INTO REQUEST(NO, COUNT, DAY, R_ID, R_ITEM)
VALUES (SEQ_REQUEST_NO.NEXTVAL, 3, CURRENT_DATE, &#39;QWE&#39;, 7);

INSERT INTO REQUEST(NO, COUNT, DAY, R_ID, R_ITEM)
VALUES (SEQ_REQUEST_NO.NEXTVAL, 2, CURRENT_DATE, &#39;ZXC&#39;, 6);

INSERT INTO REQUEST(NO, COUNT, DAY, R_ID, R_ITEM)
VALUES (SEQ_REQUEST_NO.NEXTVAL, 1, CURRENT_DATE, &#39;QWE&#39;, 8);

INSERT INTO REQUEST(NO, COUNT, DAY, R_ID, R_ITEM)
VALUES (SEQ_REQUEST_NO.NEXTVAL, 1, CURRENT_DATE, &#39;ABC&#39;, 6);

SELECT * FROM REQUEST;
COMMIT;

-- 현재 시퀀스 값 가져오기
SELECT SEQ_REQUEST_NO.CURRVAL FROM DUAL;
SELECT SEQ_ITEM_NO.CURRVAL FROM DUAL;
-- 수동으로 숫자 바꾸기
ALTER SEQUENCE SEQ_REQUEST_NO INCREMENT BY -9;
ROLLBACK;

-------------------------------------------------------------
-------------------------------------------------------------
-- USERTBL
-- 전체 조회하기
SELECT * FROM USERTBL;
SELECT ID, PASSWORD, NAME, AGE, PHONE, DAY FROM USERTBL;

-- 26살 이상만 조회
SELECT * FROM USERTBL WHERE AGE &gt; 25;
-- 25살 이상, ID가 TEST인 것 조회
SELECT * FROM USERTBL WHERE AGE &gt;= 25 AND ID = &#39;TEST&#39;;
-- 25살 이하이거나 ID가 ABC인 것 조회
SELECT * FROM USERTBL WHERE AGE &lt;= 25 OR ID = &#39;ABC&#39;;
-- NAME 기준으로 내림차순 정렬
SELECT * FROM USERTBL ORDER BY NAME DESC;
-- NAME 기준으로 오름차순 정렬
SELECT * FROM USERTBL ORDER BY NAME ASC;

-- 나이가 20 이상인 사람만 이름을 기준으로 내림차순 정렬
SELECT * FROM USERTBL WHERE AGE &gt;= 20 ORDER BY NAME DESC;

-- 개수 구하기
SELECT COUNT(*) FROM USERTBL;
-- 최대값 구하기
SELECT MAX(AGE) FROM USERTBL;
-- 최소값 구하기
SELECT MIN(AGE) FROM USERTBL;
-- 합계, 평균 구하기
SELECT SUM(AGE), AVG(AGE) FROM USERTBL;

--------------- 평균 나이 이상인 회원의 정보 조회 ---------------
SELECT * FROM USERTBL WHERE AGE &gt;= (SELECT AVG(AGE) FROM USERTBL);

-------------------------------------------------------------
-------------------------------------------------------------
-- ITEM
SELECT * FROM ITEM;

-- 가격이 20000원 이상인 항목 출력
SELECT * FROM ITEM WHERE PRICE &gt;= 20000;
-- 재고 수량이 10개 미만인 것을 40개로 변경
--SELECT * FROM ITEM WHERE COUNT &lt; 10;
UPDATE ITEM SET COUNT = &#39;40&#39; WHERE COUNT &lt; 10;
-- 재고 수량 평균
SELECT AVG(COUNT) FROM ITEM;
-- 물품번호 1번인 항목의 가격을 4000으로 변경
--SELECT * FROM ITEM WHERE NO = &#39;1&#39;;
UPDATE ITEM SET PRICE = &#39;4000&#39; WHERE NO = &#39;1&#39;;
-- 판매 가격이 가장 높은 물품을 출력
SELECT * FROM ITEM WHERE PRICE = (SELECT MAX(PRICE) FROM ITEM);
-- 주문조회하기
SELECT * FROM REQUEST, ITEM WHERE REQUEST.R_NO = ITEM.I_NO;

-- 뷰만들기 : 조회한 정보를 바탕으로 뷰 만들기(성능적인 부분)
CREATE VIEW REQUESTITEM_VIEW AS SELECT * FROM REQUEST, ITEM 
WHERE REQUEST.R_NO = ITEM.I_NO;
-- 뷰 조회하기
SELECT * FROM REQUESTITEM_VIEW;

SELECT * FROM REQUEST, USERTBL WHERE REQUEST.R_ID = USERTBL.U_ID;
CREATE VIEW REQUESTUSER_VIEW AS SELECT * FROM REQUEST, USERTBL 
WHERE REQUEST.R_ID = USERTBL.U_ID;
-- 뷰 조회하기
SELECT * FROM REQUESTUSER_VIEW;

-------------------------------------------------------------
-------------------------------------------------------------
/* dept02 테이블
    deptno      숫자, 기본키
    dname       가변길이 6자
*/
/* emp02 테이블
    empno       숫자, 기본키
    name        가변길이 10자 not null
    deptno      숫자 not null
    position    가변길이 10자로 &quot;사원, 대리, 과장, 부장&quot;만 가능
    pay         숫자, not null
    pempno      숫자
    regdate date로
*/
-- DEPT02 테이블 생성
CREATE TABLE DEPT02 (
    DEPTNO NUMBER PRIMARY KEY,
    DNAME VARCHAR2(12)
);
-- EMP02 테이블 생성
CREATE TABLE EMP02(
    EMPNO NUMBER PRIMARY KEY,
    NAME VARCHAR2(20) NOT NULL,
    DEPTNO NUMBER NOT NULL,
    POSITION VARCHAR2(20) CHECK (POSITION IN (&#39;사원&#39;, &#39;대리&#39;, &#39;과장&#39;, &#39;부장&#39;)),
    PAY NUMBER NOT NULL,
    P_EMPNO NUMBER,
    DAY DATE
);

-- 외래키 적용
ALTER TABLE EMP02 ADD FOREIGN KEY(DEPTNO) REFERENCES DEPT02(DEPTNO);
-- 시퀀스 생성
CREATE SEQUENCE SEQ_EMP02_EMPNO START WITH 1 INCREMENT BY 1 NOCACHE NOMAXVALUE;

-- DEPT02 데이터 추가
INSERT INTO DEPT02(DEPTNO, DNAME)
VALUES (&#39;101&#39;, &#39;영업부&#39;);
INSERT INTO DEPT02(DEPTNO, DNAME)
VALUES (&#39;102&#39;, &#39;총무부&#39;);
INSERT INTO DEPT02(DEPTNO, DNAME)
VALUES (&#39;103&#39;, &#39;기획부&#39;);
INSERT INTO DEPT02(DEPTNO, DNAME)
VALUES (&#39;104&#39;, &#39;홍보부&#39;);
SELECT * FROM DEPT02;
COMMIT;

-- EMP02 데이터 추가
INSERT INTO EMP02(EMPNO, NAME, DEPTNO, POSITION, PAY, P_EMPNO, DAY)
VALUES (SEQ_EMP02_EMPNO.NEXTVAL, &#39;김독자&#39;, 101, &#39;부장&#39;, 500, NULL, CURRENT_DATE);
INSERT INTO EMP02(EMPNO, NAME, DEPTNO, POSITION, PAY, P_EMPNO, DAY)
VALUES (SEQ_EMP02_EMPNO.NEXTVAL, &#39;한수영&#39;, 102, &#39;부장&#39;, 450, NULL, CURRENT_DATE);
INSERT INTO EMP02(EMPNO, NAME, DEPTNO, POSITION, PAY, P_EMPNO, DAY)
VALUES (SEQ_EMP02_EMPNO.NEXTVAL, &#39;이상아&#39;, 101, &#39;과장&#39;, 400, NULL, CURRENT_DATE);
INSERT INTO EMP02(EMPNO, NAME, DEPTNO, POSITION, PAY, P_EMPNO, DAY)
VALUES (SEQ_EMP02_EMPNO.NEXTVAL, &#39;이현성&#39;, 103, &#39;과장&#39;, 350, NULL, CURRENT_DATE);
INSERT INTO EMP02(EMPNO, NAME, DEPTNO, POSITION, PAY, P_EMPNO, DAY)
VALUES (SEQ_EMP02_EMPNO.NEXTVAL, &#39;이길영&#39;, 101, &#39;대리&#39;, 310, NULL, CURRENT_DATE);
INSERT INTO EMP02(EMPNO, NAME, DEPTNO, POSITION, PAY, P_EMPNO, DAY)
VALUES (SEQ_EMP02_EMPNO.NEXTVAL, &#39;이지혜&#39;, 102, &#39;과장&#39;, 400, NULL, CURRENT_DATE);
INSERT INTO EMP02(EMPNO, NAME, DEPTNO, POSITION, PAY, P_EMPNO, DAY)
VALUES (SEQ_EMP02_EMPNO.NEXTVAL, &#39;한초희&#39;, 102, &#39;대리&#39;, 320, NULL, CURRENT_DATE);
INSERT INTO EMP02(EMPNO, NAME, DEPTNO, POSITION, PAY, P_EMPNO, DAY)
VALUES (SEQ_EMP02_EMPNO.NEXTVAL, &#39;한명오&#39;, 103, &#39;사원&#39;, 380, NULL, CURRENT_DATE);
INSERT INTO EMP02(EMPNO, NAME, DEPTNO, POSITION, PAY, P_EMPNO, DAY)
VALUES (SEQ_EMP02_EMPNO.NEXTVAL, &#39;유중혁&#39;, 101, &#39;사원&#39;, 280, NULL, CURRENT_DATE);
INSERT INTO EMP02(EMPNO, NAME, DEPTNO, POSITION, PAY, P_EMPNO, DAY)
VALUES (SEQ_EMP02_EMPNO.NEXTVAL, &#39;공필두&#39;, 104, &#39;사원&#39;, 250, NULL, CURRENT_DATE);

SELECT * FROM EMP02;
COMMIT;
SELECT * FROM EMP02, DEPT02 WHERE EMP02.DEPTNO = DEPT02.DEPTNO;

CREATE VIEW COMPANY_VIEW AS SELECT * FROM EMP02, DEPT02 
WHERE EMP02.E_DEPTNO = DEPT02.DEPTNO;
SELECT * FROM COMPANY_VIEW;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[오라클 SQL 정리]]></title>
            <link>https://velog.io/@ruinak_4127/%EC%98%A4%EB%9D%BC%ED%81%B4-SQL-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@ruinak_4127/%EC%98%A4%EB%9D%BC%ED%81%B4-SQL-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Wed, 03 Nov 2021 05:22:30 GMT</pubDate>
            <description><![CDATA[<h1 id="ddl-정의어">DDL 정의어</h1>
<h2 id="새로운-table-생성">새로운 Table 생성</h2>
<h3 id="table-정보">Table 정보</h3>
<ul>
<li>Table 명 : USERTBL</li>
<li>Column명 : ID, PASSWORD, NAME, AGE, PHONE, DAY</li>
<li>ID는 PRIMARY KEY로 지정<h3 id="table-생성-형식">Table 생성 형식</h3>
<pre><code>CREATE TABLE USERTBL(
  ID VARCHAR2(30) PRIMARY KEY,
  PASSWORD VARCHAR2(200),
  NAME VARCHAR2(30),
  AGE NUMBER,
  PHONE VARCHAR2(30),
  DAY DATE
);</code></pre></li>
</ul>
<h1 id="dml-조작어">DML 조작어</h1>
<ul>
<li>INSERT, UPDATE, DELETE, SELECT<h2 id="insert">INSERT</h2>
</li>
<li>하나의 행 데이터 추가<h3 id="insert-형식">INSERT 형식</h3>
</li>
<li>INSERT INTO Table 명(Column 명) VALUES(값들);<h3 id="usertbl에-insert로-데이터-추가">USERTBL에 INSERT로 데이터 추가</h3>
<pre><code>INSERT INTO usertbl(ID, PASSWORD, NAME, AGE, PHONE, DAY)
VALUES(&#39;test&#39;, &#39;1234&#39;, &#39;테스터&#39;, &#39;20&#39;, &#39;010-1234-5678&#39;, CURRENT_DATE);
</code></pre></li>
</ul>
<p>INSERT INTO usertbl(ID, PASSWORD, NAME, AGE, PHONE, DAY)
VALUES(&#39;ask&#39;, &#39;1234&#39;, &#39;질문자&#39;, &#39;20&#39;, &#39;010-2344-6788&#39;, CURRENT_DATE);</p>
<pre><code>- ID가 test, ask인 2개의 행 생성

## DELETE
- 행 데이터 삭제
- 원하는 행을 삭제 시 WHERE 절을 이용
### DELETE 형식
#### 전체 데이터 삭제
- DELETE FROM Table명;
#### 원하는 행 삭제
- DELETE FROM Table명 WHERE Column명 = &#39;VALUE&#39;;
### USERTBL에서 DELETE</code></pre><p>// 테이블 내 데이터 전체 삭제
DELETE FROM USERTBL;</p>
<p>// ID가 ask인 행 삭제 = 1개 삭제
DELETE FROM usertbl WHERE ID = &#39;ask&#39;;</p>
<p>// NAME이 테스터인 행 삭제 = 1개 삭제
DELETE FROM usertbl WHERE NAME = &#39;테스터&#39;;</p>
<p>// AGE가 20인 행 삭제 = 2개 삭제
DELETE FROM usertbl WHERE AGE = &#39;20&#39;;</p>
<pre><code>
## UPDATE
- 행 데이터 수정
- SET을 이용해서 수정할 데이터 값 지정
- WHERE 절 사용해서 수정할 위치 지정
- PRIMARY KEY도 수정 가능
### UPDATE 형식
#### 한 개의 데이터 수정
- UPDATE Table명 SET Column명 = &#39;수정할 VALUE&#39; WHERE Column명 = &#39;VALUE&#39;;
#### 여러 개의 데이터 수정
- UPDATE Table명 SET Column명1 = &#39;수정할 VALUE1&#39;, Column명2 = &#39;수정할 VALUE2&#39;  WHERE Column명 = &#39;VALUE&#39;;
### USERTBL의 값 UPDATE</code></pre><p>// 하나의 값 수정
UPDATE USERTBL SET NAME = &#39;기자&#39; WHERE ID = &#39;ASK&#39;;</p>
<p>// 여러 값 수정
UPDATE USERTBLE SET AGE = 25, PHONE = &#39;010-9876-5432&#39; WHERE ID = &#39;test&#39;;</p>
<p>// PRIMARY KEY 수정
UPDATE USERTBL SET ID = &#39;TEST&#39; WHERE ID = &#39;test&#39;;</p>
<pre><code>
## SELECT
- 원하는 Table, Column 조회 
### SELECT 형식
#### 전체 Column 조회
- SELECT * FROM Table 명;
#### 원하는 Column 조회
- SELECT Column명 FROM Table 명;
### USERTBL에서 SELECT</code></pre><p>// 전체 조회
SELECT * FROM USERTBL;</p>
<p>// ID만 조회
SELECT ID FROM USERTBL;</p>
<p>// PASSWORD만 조회
SELECT PASSWORD FROM USERTBL;</p>
<p>// NAME만 조회
SELECT NAME FROM USERTBL;</p>
<p>// AGE만 조회
SELECT AGE FROM USERTBL;</p>
<p>// PHONE만 조회
SELECT PHONE FROM USERTBL;</p>
<p>// DAY만 조회
SELECT DAY FROM USERTBL;</p>
<pre><code>
# SEQUENCE
- SEQUENCE : 자동으로 숫자가 증가되는 변수
- SEQUENCE명 : SEQ_Table명_Column명
- NOCACHE: 메모리에 시퀀스 값 할당 안함
- NOMAXVALUE 디폴트 값은 1028-1
## SEQUENCE 생성 및 사용
### SEQUENCE 생성 형식</code></pre><p>CREATE SEQUENCE SEQENCE명 START WITH 시작 번호 INCREAMENT BY 증가량 NOCACHE NOMAXVALUE;</p>
<pre><code>### ITEM에서 SEQUENCE 생성 및 사용</code></pre><p>// SQUENCE 생성
CREATE SEQUENCE SEQ_ITEM_NO START WITH 1 INCREMENT BY 1 NOCACHE NOMAXVALUE;</p>
<p>// SEQUENCE 사용해서 데이터 입력
INSERT INTO ITEM(NO, NAME, CONTENT, PRICE, COUNT, DAY) 
VALUES(SEQ_ITEM_NO.NEXTVAL, &#39;맥주&#39;, &#39;보리로 만든 술&#39;, 3500, 20, CURRENT_DATE);</p>
<p>INSERT INTO ITEM(NO, NAME, CONTENT, PRICE, COUNT, DAY) 
VALUES(SEQ_ITEM_NO.NEXTVAL, &#39;소주&#39;, &#39;한국 증류주&#39;, 4000, 30, CURRENT_DATE);</p>
<p>INSERT INTO ITEM(NO, NAME, CONTENT, PRICE, COUNT, DAY) 
VALUES(SEQ_ITEM_NO.NEXTVAL, &#39;와인&#39;, &#39;포도로 만든 발효주&#39;, 4900, 12, CURRENT_DATE);</p>
<p>INSERT INTO ITEM(NO, NAME, CONTENT, PRICE, COUNT, DAY) 
VALUES(SEQ_ITEM_NO.NEXTVAL, &#39;럼&#39;, &#39;용설과로 만든 비싼 술&#39;, 24900, 1, CURRENT_DATE);</p>
<p>INSERT INTO ITEM(NO, NAME, CONTENT, PRICE, COUNT, DAY) 
VALUES(SEQ_ITEM_NO.NEXTVAL, &#39;보드카&#39;, &#39;감자로 만든 독한 술&#39;, 18900, 1, CURRENT_DATE);</p>
<pre><code>
# 외래키 설정
- 테이블의 Column을 다른 테이블의 Column과 연결 
### 외래키 생성 형식
- ALTER TABLE 테이블명 ADD FOREIGN KEY(컬럼명) REFERENCES 연결할 테이블명(연결할 컬럼명);</code></pre><p>-- 외래키 제약조건
-- 주문자 정보
ALTER TABLE REQUEST ADD FOREIGN KEY(R_ID) REFERENCES USERTBL(ID);
-- 물품 정보
ALTER TABLE REQUEST ADD FOREIGN KEY(R_ITEM) REFERENCES ITEM(NO);
```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[용어 정리]]></title>
            <link>https://velog.io/@ruinak_4127/%EC%9A%A9%EC%96%B4-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@ruinak_4127/%EC%9A%A9%EC%96%B4-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Mon, 01 Nov 2021 15:39:16 GMT</pubDate>
            <description><![CDATA[<h2 id="데이터-분석-및-시각화">데이터 분석 및 시각화</h2>
<h3 id="beautifulsoup">BeautifulSoup</h3>
<ul>
<li>인터넷 문서의 구조에서 명확한 데이터를 추출하고 처리하는 가장 쉬운 라이브러리입니다.<h3 id="selenium">Selenium</h3>
</li>
<li>가장 유명한 브라우저 자동화도구입니다.</li>
<li>실제 웹브라우저를 켜는 과정을 거치기 때문에 selenium을 이용하면 동적 페이지에서도 데이터를 수집할 수 있습니다.</li>
<li>실제 웹 브라우저가 동작하기 때문에 JS로 렌더링이 완료된 후의 DOM결과물에 접근이 가능합니다.<h3 id="pyplot">pyplot</h3>
</li>
<li>멧플롯립 안에 포함된 서브모듈입니다. </li>
<li>여러 기능이 존재하고, 많이 사용되는데, 간단한 시각화의 경우는 파이플롯만으로 처리하는 경우가 많습니다. </li>
<li>주피터 노트북 화면 안에 시각화 결과가 표시되도록 설정이 가능합니다.<h3 id="seaborn">seaborn</h3>
</li>
<li>Matplotlib을 기반으로 다양한 색상 테마와 통계용 차트 등의 기능을 추가한 시각화 패키지이다. </li>
<li>기본적인 시각화 기능은 Matplotlib 패키지에 의존하며 통계 기능은 Statsmodels 패키지에 의존한다.<h3 id="django">Django</h3>
</li>
<li>파이썬으로 만들어진 무료 오픈소스 웹 애플리케이션 프레임워크(web application framework)입니다. </li>
<li>쉽고 빠르게 웹사이트를 개발할 수 있도록 돕는 구성요소로 이루어진 웹 프레임워크랍니다.</li>
</ul>
<h2 id="android">Android</h2>
<h3 id="4대-컴포넌트">4대 컴포넌트</h3>
<h4 id="1-액티비티activity">1. 액티비티(Activity)</h4>
<ul>
<li>Activity 클래스를 상속받아서 사용하며 UI(user interface) 화면을 구성하는 요소입니다.</li>
<li>엑티비티란 사용자와 애플리케이션과 상호작용하는 단일화면을 말합니다(액티비티 2개 이상 display 불가능).</li>
<li>모든 안드로이드 애플리케이션은 액티비티로 구성되어있습니다.</li>
<li>사용하려면 무조건 manifest에 파일 선언이 필수이며 사용할때 액티비티는 생명주기(Life cycle)를 사용하여 재정의후 원하는 기능들을 새롭게 건축할 수 있습니다.<h4 id="2-서비스service">2. 서비스(Service)</h4>
</li>
<li>Service 클래스를 상속받아서 사용합니다.</li>
<li>장시간으로 지속적으로 background에서 실행되는 컴포넌트입니다.</li>
<li>애플리케이션을 사용하면서 유투브나 음원 스트리밍 앱에서 재생하고 다른 앱을 실행해도 노래가 지속적으로 재생되는걸 생각하면 됩니다.</li>
<li>서비스는 메인스레드에서 동작하기때문에 서비스 내에서 별도의 쓰레드를 생성하여 작업을 처리해야합니다.<h4 id="3-방송-수신자broadcast-receiver">3. 방송 수신자(Broadcast Receiver)</h4>
</li>
<li>방송 수신자는 안드로이드 os로부터 발생하는 각종 이벤트에 따라 원하는 작업을 수행할 수 있습니다.</li>
<li>배터리 부족, 언어설정 변경, 문자수신,네트워크 끊김, 앱 초기화 등등 배터리가 없다면 모든 앱에 &#39;배터리가없다!&#39;라는 방송을 합니다.</li>
<li>문자 수신도 동일합니다 문자를 받는다면 그 문자를 받고 브로드캐스트 리시버를 구현하면 특정 이벤트를 처리할 수 있습니다.<h4 id="4-콘텐트-제공자content-provider">4. 콘텐트 제공자(Content Provider)</h4>
</li>
<li>애플리케이션 사이에서 각 데이터를 공유할수 있도록 사용되는 컴포넌트입니다.</li>
<li>데이터베이스(DB)를 공유하기 위해 사용하며 애플리케이션 간의 데이터 공유를 위해 표준화된 인터페이스를 제공합니다.</li>
<li>SQLite DB , Web ,파일 입출력 등을 통해서 데이터를 관리합니다.</li>
<li>기본적으로 내장되있는 DB를 읽고 쓰기에 대한 퍼미션만있다면 데이터 접근이 가능합니다.</li>
<li>반대로 이야기하자면, 외부 애플리케이션이 현재 실행 중인 애플리케이션 안에 있는 데이터베이스(DB)에 함부로 접근하지 못하게 할 수 있으면서 내가 공유하고싶은 부분은 공유해줄 수 있게 합니다.<h3 id="intent">Intent</h3>
</li>
<li>Intent는 명시적 인텐트와 암시적 인텐트로 구분됩니다.</li>
<li>명시적 인텐트 : 인텐트에 클래스 객체나 컴포넌트 이름을 지정하여 호출될 대상을 확실히 알 수 있는 경우</li>
<li>암시적 인텐트 : 호출될 대상의 속성들을 지정했지만 호출될 대상이 달라질 수 있는 경우</li>
<li>어플리케이션 구성요소(컴포넌트) 간에 작업 수행을 위한 정보를 전달하는 역할을 한합니다.</li>
<li>컴포넌트A가 컴포넌트B를 호출할 때 필요한 정보를 담고 있으며, 이 정보에는 호출되는 컴포넌트B의 이름이 명시적으로 표시되기도 하고, 속성들이 암시적으로 표시되기도 합니다.</li>
<li>호출된 컴포넌트B가 호출한 컴포넌트A로 어떠한 결과를 전달할 때도 인텐트가 사용됩니다.<h3 id="recyclerview">RecyclerView</h3>
</li>
<li>목록을 화면에 출력해주고 동적으로 표현해주는 컨테이너입니다. </li>
<li>리사이클러뷰는 간단한 코드만으로 ListView, GridView로 바꿀 수 있습니다.</li>
<li>가장 복잡한 컨테이너지만 가장 많이 사용되는 것이 바로 리사이클러뷰입니다. <h3 id="fragment">Fragment</h3>
</li>
<li>앱 UI의 재사용 가능한 부분을 나타냅니다.</li>
<li>프래그먼트는 자체 레이아웃을 정의 및 관리하고 자체 수명 주기를 보유하며 자체 입력 이벤트를 처리할 수 있습니다.</li>
<li>프래그먼트는 독립적으로 존재할 수 없고 활동이나 다른 프래그먼트에서 호스팅되어야 합니다.</li>
<li>프래그먼트의 뷰 계층 구조는 호스트 뷰 계층 구조의 일부가 되거나 여기에 연결됩니다.</li>
</ul>
<h2 id="html--css--javascript">HTML / CSS / JavaScript</h2>
<h3 id="html">HTML</h3>
<ul>
<li>Hyper Text Markup Language 약어로 HyperText(웹 페이지에서 다른 페이지로 이동할 수 있도록 하는 것) 기능을 가진 문서를 만드는 언어입니다. </li>
<li>다시 말해, 구조를 설계할 때 사용되는 언어로 hyper link 시스템을 가지고 있으며, 흔히 말하는 웹 페이지를 위한 마크업 언어라고 할 수 있습니다.<h3 id="css">CSS</h3>
</li>
<li>Cascading Style Sheets 약자로 HTML, XHTML, XML 같은 문서의 스타일를 꾸밀 때 사용하는 스타일 시트 언어입니다.</li>
<li>HTML로 문서의 뼈대를 만들면 CSS는 이 문서의 화장을 맡고 있는 셈입니다.  </li>
<li>글꼴이나, 배경색, 너비와 높이, 위치 등을 지정하거나, 웹 브라우저, 스크린 크기, 장치에 따라서 화면을 다르게  표시될 수 있도록 지정할 수도 있습니다.<h3 id="javascript">JavaScript</h3>
</li>
<li>HTML과 CSS로 만들어진 웹페이지를 동적으로 변경해주는 언어입니다. </li>
<li>경고창을 띄우고, 탭인터페이스를 만들고, Drag &amp; Drop 기능의 웹에플리케이션을 만들 수 있습니다.</li>
</ul>
<h2 id="spring-framework">Spring Framework</h2>
<h3 id="mybatis">MyBatis</h3>
<ul>
<li>객체 지향 언어인 자바의 관계형 데이터베이스 프로그래밍을 좀 더 쉽게 할 수 있게 도와 주는 개발 프레임 워크입니다.</li>
<li>JDBC를 통해 데이터베이스에 엑세스하는 작업을 캡슐화하고 일반 SQL 쿼리, 저장 프로 시저 및 고급 매핑을 지원하며 모든 JDBC 코드 및 매개 변수의 중복작업을 제거 합니다.</li>
<li>Mybatis에서는 프로그램에 있는 SQL쿼리들을 한 구성파일에 구성하여 프로그램 코드와 SQL을 분리할 수 있는 장점을 가지고 있습니다.<h3 id="jpa">JPA</h3>
</li>
<li>JPA(Java Persistence API)는 자바 진영의 ORM 기술 표준입니다.</li>
<li>JPA가 제공하는 API를 사용하면 객체를 DB에 저장하고 관리할 때, 개발자가 직접 SQL을 작성하지 않아도 됩니다.</li>
<li>JPA가 개발자 대신 적절한 SQL을 생성해서 DB에 전달하고, 객체를 자동으로 Mapping 해줍니다.</li>
<li>JPA는 내부적으로 JDBC API를 활용하는데 개발자가 직접 JDBC API를 활용하면 패러다임 불일치, SQL 의존성 등으로 인해 효율성이 떨어집니다.</li>
<li>JPA를 활용한다면 모든 SQL에 대해 개발자 대신 JPA가 자동으로 해결해 준다는 점에서 생산성을 크게 높입니다.<h3 id="mvc-패턴">MVC 패턴</h3>
</li>
<li>MVC패턴은 디자인패턴 중 하나로 Model, View, Controller의 약자 입니다. </li>
<li>하나의 애플리케이션, 프로젝트를 구성할 때 그 구성요소를 세가지의 역할로 구분한 패턴입니다. </li>
<li>모델은 컨트롤러에 컨트롤러는 뷰에 뷰는 다시 유저 유저는 다시 컨트롤러를 향해서 갑니다.<h4 id="모델">모델</h4>
</li>
</ul>
<ol>
<li>사용자가 편집하길 원하는 모든 데이터를 가지고 있어야 한다.</li>
<li>뷰나 컨트롤러에 대해서 어떤 정보도 알지 말아야 한다.</li>
<li>변경이 일어나면, 변경 통지에 대한 처리방법을 구현해야만 한다.<h4 id="뷰">뷰</h4>
</li>
<li>모델이 가지고 있는 정보를 따로 저장해서는 안된다.</li>
<li>모델이나 컨트롤러와 같이 다른 구성요소들을 몰라야 된다.</li>
<li>변경이 일어나면 변경통지에 대한 처리방법을 구현해야만 한다.<h4 id="컨트롤러">컨트롤러</h4>
</li>
<li>모델이나 뷰에 대해서 알고 있어야 한다.</li>
<li>모델이나 뷰의 변경을 모니터링 해야 한다.<h3 id="spring-aop">Spring AOP</h3>
</li>
</ol>
<ul>
<li>Aspect Oriented Programming의 약자로 관점 지향 프로그래밍이라고 불립니다.</li>
<li>모듈화란 어떤 공통된 로직이나 기능을 하나의 단위로 묶는 것을 말합니다.</li>
<li>로직을 모듈화한다는 것은 코드들을 부분적으로 나누어서 모듈화하겠다는 의미입니다.<h4 id="aop의-주요-개념">AOP의 주요 개념</h4>
</li>
<li>Aspect : 위에서 설명한 흩어진 관심사를 모듈화 한 것. 주로 부가기능을 모듈화함.</li>
<li>Target : Aspect를 적용하는 곳 (클래스, 메서드 .. )</li>
<li>Advice : 실질적으로 어떤 일을 해야할 지에 대한 것, 실질적인 부가기능을 담은 구현체</li>
<li>JointPoint : Advice가 적용될 위치, 끼어들 수 있는 지점. 메서드 진입 지점, 생성자 호출 시점, 필드에서 값을 꺼내올 때 등 다양한 시점에 적용가능</li>
<li>PointCut : JointPoint의 상세한 스펙을 정의한 것. &#39;A란 메서드의 진입 시점에 호출할 것&#39;과 같이 더욱 구체적으로 Advice가 실행될 지점을 정할 수 있음<h4 id="스프링-aop-특징">스프링 AOP 특징</h4>
</li>
<li>프록시 패턴 기반의 AOP 구현체, 프록시 객체를 쓰는 이유는 접근 제어 및 부가기능을 추가하기 위해서입니다.</li>
<li>스프링 빈에만 AOP를 적용 가능합니다.</li>
<li>모든 AOP 기능을 제공하는 것이 아닌 스프링 IoC와 연동하여 엔터프라이즈 애플리케이션에서 가장 흔한 문제(중복코드, 프록시 클래스 작성의 번거로움, 객체들 간 관계 복잡도 증가 ...)에 대한 해결책을 지원하는 것이 목적입니다.<h3 id="트랜잭션">트랜잭션</h3>
</li>
<li>트랜잭션(Transaction)은 데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산들을 의미합니다.<h4 id="트랜잭션의-특징">트랜잭션의 특징</h4>
</li>
</ul>
<ol>
<li>트랜잭션은 데이터베이스 시스템에서 병행 제어 및 회복 작업 시 처리되는 작업의 논리적 단위입니다.</li>
<li>사용자가 시스템에 대한 서비스 요구 시 시스템이 응답하기 위한 상태 변환 과정의 작업단위입니다.</li>
<li>하나의 트랜잭션은 Commit되거나 Rollback 됩니다.<h3 id="인터셉터">인터셉터</h3>
</li>
</ol>
<ul>
<li>특정 URI로 요청시 Controller로 가는 요청을 가로채는 역할을 합니다.<h3 id="ajax">Ajax</h3>
</li>
<li>Asynchronous Javascript And Xml(비동기식 자바스크립트와 xml)의 약자입니다.</li>
<li>자바스크립트를 이용해 서버와 브라우저가 비동기 방식으로 데이터를 교환할 수 있는 통신 기능입니다.</li>
<li>브라우저가 가지고있는 XMLHttpRequest 객체를 이용해서 전체 페이지를 새로 고치지 않고도 페이지의 일부만을 위한 데이터를 로드하는 기법입니다.</li>
<li>쉽게 말하자면 자바스크립트를 통해서 서버에 데이터를 비동기 방식으로 요청하는 것이다.<h3 id="openapi">OpenAPI</h3>
</li>
<li>오픈 API 또는 공개 API는 개발자라면 누구나 사용할 수 있도록 공개된 API를 말하며, 개발자에게 사유 응용 소프트웨어나 웹 서비스의 프로그래밍적인 권한을 제공합니다.</li>
</ul>
<h2 id="database">Database</h2>
<h3 id="dmldata-manipulation-language--데이터-조작어">DML(Data Manipulation Language) : 데이터 조작어</h3>
<ul>
<li>SLECET, INSERT, UPDATE, DELETE</li>
<li>SLECET : 데이터베이스에 들어 있는 데이터를 조회하거나 검색하기 위한 명령어를 말하는 것으로 RETRIEVE 라고도 합니다.</li>
<li>INSERT, UPDATE, DELETE : 데이터베이스의 테이블에 들어 있는 데이터에 변형을 가하는 종류(데이터 삽입, 수정, 삭제)의 명령어들을 말합니다. <h3 id="ddldata-definition-language--데이터-정의어">DDL(Data Definition Language) : 데이터 정의어</h3>
</li>
<li>CREATE, ALTER, DROP, RENAME, TRUNCATE </li>
<li>테이블과 같은 데이터 구조를 정의하는데 사용되는 명령어들로 (생성, 변경, 삭제, 이름변경) 데이터 구조와 관련된 명령어들을 말합니다.<h3 id="dcldata-control-language--데이터-제어어">DCL(Data Control Language) : 데이터 제어어</h3>
</li>
<li>GRANT, REVOKE</li>
<li>데이터베이스에 접근하고 객체들을 사용하도록 권한을 주고 회수하는 명령어들을 말합니다.<h3 id="tcltransaction-control-language--트랜잭션-제어어">TCL(Transaction Control Language) : 트랜잭션 제어어</h3>
</li>
<li>COMMIT, ROLLBACK, SAVEPOINT </li>
<li>논리적인 작업의 단위를 묶어서 DML에 의해 조작된 결과를 작업단위(트랜잭션) 별로 제어하는 명령어를 말합니다.</li>
</ul>
<h2 id="jsp--servlet">JSP / SERVLET</h2>
<h3 id="서블릿">서블릿</h3>
<h3 id="life-cycle">Life Cycle</h3>
<h3 id="session">Session</h3>
<h3 id="cookie">Cookie</h3>
<h3 id="el표현식">EL표현식</h3>
<h3 id="jstl">JSTL</h3>
<h3 id="스크립트릿-선언">스크립트릿 선언</h3>
<h3 id="bean">Bean</h3>
<h3 id="액션-태그">액션 태그</h3>
<h3 id="jdbc">JDBC</h3>
<h2 id="java">Java</h2>
<h3 id="객체지향-프로그래밍의-특징">객체지향 프로그래밍의 특징</h3>
<ul>
<li>우리가 실생활에서 쓰는 모든 것을 객체라 하며, 객체 지향 프로그래밍은 프로그램 구현에 필요한 객체를 파악하고 각각의 객체들의 역할이 무엇인지를 정의하여 객체들 간의 상호작용을 통해 프로그램을 만드는 것을 말합니다. </li>
<li>객체는 클래스라는 틀에서 생겨난 실체(instance)입니다. </li>
<li>객체 지향 프로그램은 객체와 객체 간의 연결로 되어 있으며 각각의 객체 안에 자료구조와 알고리즘이 들어있는 것입니다.</li>
</ul>
<ol>
<li>추상화(abstraction)</li>
</ol>
<ul>
<li>객체들의 공통적인 특징(기능, 속성)을 도출하는 것</li>
<li>객체지향적 관점에서는 클래스를 정의하는 것을 추상화라고 할 수 있다.(클래스가 없는 객체지향 언어도 존재 ex.JavaScript)</li>
</ul>
<ol start="2">
<li>캡슐화(encapsulation)</li>
</ol>
<ul>
<li>실제로 구현되는 부분을 외부에 드러나지 않도록 하여 정보를 은닉할 수 있다.</li>
<li>객체가 독립적으로 역할을 할 수 있도록 데이터와 기능을 하나로 묶어 관리하는 것
코드가 묶여있어서 오류가 없어 편리하다.</li>
<li>데이터를 보이지 않고 외부와 상호작용을 할 때는 메소드를 이용하여 통신을 한다. 보통 라이브러리로 만들어서 업그레이드해 사용할 수 있다.</li>
</ul>
<ol start="3">
<li>상속성(inheritance)</li>
</ol>
<ul>
<li>하나의 클래스가 가진 특징(함수, 데이터)을 다른 클래스가 그대로 물려받는 것</li>
<li>이미 작성된 클래스를 받아서 새로운 클래스를 생성하는 것</li>
<li>기존 코드를 재활용해서 사용함으로써 객체지향 방법의 중요한 기능 중 하나에 속한다.</li>
</ul>
<ol start="4">
<li>다형성(polymorphism)</li>
</ol>
<ul>
<li>약간 다른 방법으로 동작하는 함수를 동일한 이름으로 호출하는 것</li>
<li>동일한 명령의 해석을 연결된 객체에 의존하는 것</li>
<li>오버라이딩(Overriding), 오버로딩(Overloading)<ul>
<li>오버라이딩(Overriding) : 부모클래스의 메소드와 같은 이름을 사용하며 매개변수도 같되 내부 소스를 재정의하는 것</li>
<li>오버로딩(Overloading) : 같은 이름의 함수를 여러 개 정의한 후 매개변수를 다르게 하여 같은 이름을 경우에 따라 호출하여 사용하는 것</li>
</ul>
</li>
</ul>
<ol start="5">
<li>동적바인딩(Dynamic Binding)</li>
</ol>
<ul>
<li>가상 함수를 호출하는 코드를 컴파일할 때, 바인딩을 실행시간에 결정하는 것.</li>
<li>파생 클래스의 객체에 대해, 기본 클래스의 포인터로 가상 함수가 호출될 때 일어난다.</li>
<li>함수를 호출하면 동적 바인딩을 통해 파생 클래스에 오버라이딩 된 함수가 실행</li>
<li>프로그래밍의 유연성을 높여주며 파생 클래스에서 재정의한 함수의 호출을 보장(다형 개념 실현)<h3 id="추상-클래스">추상 클래스</h3>
<h3 id="인터페이스">인터페이스</h3>
<h3 id="캐스팅">캐스팅</h3>
<h3 id="오버로딩">오버로딩</h3>
<h3 id="오버라이딩">오버라이딩</h3>
<h3 id="객체-생성">객체 생성</h3>
<h3 id="메서드">메서드</h3>
<h3 id="예외-처리">예외 처리</h3>
<h3 id="컬렉션">컬렉션</h3>
<h3 id="제네릭">제네릭</h3>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Flutter 실습]]></title>
            <link>https://velog.io/@ruinak_4127/Flutter-%EC%8B%A4%EC%8A%B5</link>
            <guid>https://velog.io/@ruinak_4127/Flutter-%EC%8B%A4%EC%8A%B5</guid>
            <pubDate>Thu, 21 Oct 2021 01:55:47 GMT</pubDate>
            <description><![CDATA[<h1 id="실습">실습</h1>
<h2 id="clone-coding">clone-coding</h2>
<ul>
<li>dribble.com의 Sweet Sew를 보고 따라서 만들어보는 연습을 해봅니다.<h2 id="결과">결과</h2>
<img src="https://images.velog.io/images/ruinak_4127/post/fb7a9b84-61d4-4f54-b2b7-19b94c7c17cf/Screenshot_1.jpg" alt=""><h2 id="전체-코드">전체 코드</h2>
<pre><code>// ignore_for_file: prefer_const_literals_to_create_immutables, prefer_const_constructors
import &#39;package:flutter/material.dart&#39;;
</code></pre></li>
</ul>
<p>// main 스레드는 runApp 을 실행시키고 종료됩니다.
void main() {
  // 비동기로 실행됨(이벤트 루프에 등록된다)
  runApp(FirstApp());
  // sleep(Duration(seconds: 2));
  // print(&quot;main 종료&quot;);
}</p>
<p>class FirstApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SafeArea(
        child: Scaffold(
          body: Center(
            child: Column(
              children: [
                // SizedBox를 이용해서 여백 주기
                SizedBox(
                  // SizedBox의 높이 설정
                  height: 20,
                ),
                // assets 폴더의 banner 이미지 불러오기
                Image.asset(
                  &quot;assets/banner.jpg&quot;,
                  // 이미지의 너비 설정
                  width: 300,
                  // 이미지의 높이 설정
                  height: 400,
                  // 이미지의 비율을 가득차게 설정
                  fit: BoxFit.fill,
                ), // 여백 주기
                SizedBox(height: 20),
                Text(
                  &quot;NeedLework&quot;,
                  style: TextStyle(
                    // Text 크기 설정
                    fontSize: 40,
                    // Text 굵기 설정
                    fontWeight: FontWeight.w800,
                  ),
                ),
                // SizedBox를 이용해서 여백 주기
                SizedBox(height: 5),
                Text(
                  &quot;is voguish&quot;,
                  style: TextStyle(
                    fontSize: 32,
                    fontWeight: FontWeight.w600,
                  ),
                ), // 여백 주기
                SizedBox(height: 15),
                Text(
                  &quot;Handicraft lessons from&quot;,
                  style: TextStyle(
                    // Text 색상 설정
                    color: Colors.black45,
                    fontSize: 18,
                  ),
                ), // 여백 주기
                SizedBox(height: 5),
                Text(
                  &quot;the best designers&quot;,
                  style: TextStyle(
                    color: Colors.black45,
                    fontSize: 18,
                  ),
                ), // 여백 주기
                SizedBox(height: 15),
                RaisedButton(
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(18.0),
                  ),
                  child: Container(
                    // 버튼의 너비 설정
                    width: 140,
                    // 버튼의 높이 설정
                    height: 50,
                    alignment: Alignment.center,
                    child: Text(
                      &quot;Get Started&quot;,
                      style: TextStyle(
                        color: Colors.white,
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                  ),
                  onPressed: () {
                    print(&quot;버튼 클릭됨&quot;);
                  },
                  // 버튼의 배경 색상 설정
                  color: Color(0xff262524),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}</p>
<p>```</p>
<h1 id="의문점">의문점</h1>
<ul>
<li>전체 배경색상은 어떻게 지정하는가?</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Flutter Button의 종류 - 3가지]]></title>
            <link>https://velog.io/@ruinak_4127/Flutter-Button-InkWell</link>
            <guid>https://velog.io/@ruinak_4127/Flutter-Button-InkWell</guid>
            <pubDate>Wed, 20 Oct 2021 09:08:49 GMT</pubDate>
            <description><![CDATA[<h1 id="button">Button</h1>
<ul>
<li>플러터에는 버튼의 종류가 다양합니다.<h2 id="raisedbutton">RaisedButton</h2>
</li>
<li>플러터에서 가장 기본적인 버튼입니다.<h3 id="onpressed">onPressed</h3>
</li>
<li>Column 내부에 RaisedButton을 지정해줍니다.</li>
<li>onPressed를 이용해서 click을 사용할 수 있습니다.</li>
<li>child를 이용해서 Text를 지정할 수 있습니다.
<img src="https://images.velog.io/images/ruinak_4127/post/2f7a3cea-b006-46ff-8f48-e78aeeae77ea/Screenshot_1.jpg" alt=""><pre><code>class FirstApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
  return MaterialApp(
    home: SafeArea(
      child: Scaffold(
        body: Column(
          children: [
            RaisedButton(
              onPressed: () {
                print(&quot;RaisedButton 클릭됨&quot;);
              },
              child: Text(&quot;레이즈드버튼&quot;),
            )
          ],
        ),
      ),
    ),
  );
}
}</code></pre><h3 id="elevation">elevation</h3>
</li>
<li>버튼의 그림자 효과를 줘서 높이감을 나타낼 수 있으며, 값에 따라 높이감을 더 많이 줄 수 있습니다.<h3 id="borderradius">borderRadius</h3>
</li>
<li>shape를 이용해서 버튼의 모서리를 둥글게 바꿔줄 수 있습니다.
<img src="https://images.velog.io/images/ruinak_4127/post/7a389947-6853-448d-94dd-1cfe47102ff5/Screenshot_2.jpg" alt=""><pre><code>...
RaisedButton(
onPressed: () {
  print(&quot;RaisedButton 클릭됨&quot;);
},
child: Text(&quot;레이즈드버튼&quot;),
// elevation는 그림자 효과
elevation: 10,
// shape
shape: RoundedRectangleBorder(
  borderRadius: BorderRadius.circular(27.5),
),
)
...</code></pre><h3 id="padding">padding</h3>
</li>
<li>다른 언어에서와 마찬가지로 버튼 내부에 여백을 지정할 수 있습니다.<h2 id="flatbutton">FlatButton</h2>
</li>
<li>테두리선이 없는 버튼처럼 생기지 않은 버튼입니다.</li>
<li>FlatButton은 직접 커스터마이징을 좀 해줘야 합니다.
<img src="https://images.velog.io/images/ruinak_4127/post/69a7004c-1680-4b0e-89db-582dc33b052c/Screenshot_3.jpg" alt=""><pre><code>...
FlatButton(
onPressed: () {
  print(&quot;FlatButton 클릭됨&quot;);
},
child: Text(&quot;플랫버튼&quot;),
),
...</code></pre></li>
<li>RaisedButton이 FlatButton보다 기본 elevation이 더 높아 조금 더 버튼같아 보입니다.</li>
<li>여러 종류의 버튼을 동시에 사용할 필요가 없으므로 RaisedButton을 사용하는 것을 권장합니다.<h2 id="커스텀-버튼">커스텀 버튼</h2>
</li>
<li>직접 버튼을 만들기 위해서 Container를 하나 지정해주고 색상과 문자를 설정해줍니다.
<img src="https://images.velog.io/images/ruinak_4127/post/72518635-ceb6-4628-8975-ac3ed2b52a5f/Screenshot_4.jpg" alt=""><pre><code>...
Container(
color: Colors.lightBlue,
child: Text(&quot;커스텀 버튼&quot;),
)
...</code></pre></li>
<li>Container를 Widget으로 감싸 InkWell로 바꿔줍니다.</li>
<li>InkWell로 감싸서 onTap을 적용시켜 주면 버튼처럼 작동을 할 수 있습니다.
<img src="https://images.velog.io/images/ruinak_4127/post/e1429374-2b48-496f-a734-fe2c9b73eeaf/Screenshot_5.jpg" alt=""><pre><code>...
InkWell(
onTap: (){
  print(&quot;커스텀 버튼 클릭됨&quot;);
},
child: Container(
  color: Colors.lightBlue,
  child: Text(&quot;커스텀 버튼&quot;),
),
)
...</code></pre></li>
</ul>
<h1 id="전체-코드">전체 코드</h1>
<pre><code>// ignore_for_file: prefer_const_literals_to_create_immutables, prefer_const_constructors
import &#39;package:flutter/material.dart&#39;;

// main 스레드는 runApp 을 실행시키고 종료됩니다.
void main() {
  // 비동기로 실행됨(이벤트 루프에 등록된다)
  runApp(FirstApp());
  // sleep(Duration(seconds: 2));
  // print(&quot;main 종료&quot;);
}

class FirstApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SafeArea(
        child: Scaffold(
          body: Column(
            children: [
              RaisedButton(
                onPressed: () {
                  print(&quot;RaisedButton 클릭됨&quot;);
                },
                color: Colors.green,
                child: Text(&quot;레이즈드버튼&quot;),
                // 그림자 효과
                elevation: 10,
                // 테두리 모서리
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(27.5),
                ),
                // 여백
                padding: EdgeInsets.all(30),
              ),
              FlatButton(
                onPressed: () {
                  print(&quot;FlatButton 클릭됨&quot;);
                },
                color: Colors.deepPurpleAccent,
                child: Text(&quot;플랫버튼&quot;),
              ),
              InkWell(
                onTap: (){
                  print(&quot;커스텀 버튼 클릭됨&quot;);
                },
                child: Container(
                  color: Colors.lightBlue,
                  child: Text(&quot;커스텀 버튼&quot;),
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Flutter Image 위젯]]></title>
            <link>https://velog.io/@ruinak_4127/Flutter-Image-%EC%9C%84%EC%A0%AF</link>
            <guid>https://velog.io/@ruinak_4127/Flutter-Image-%EC%9C%84%EC%A0%AF</guid>
            <pubDate>Wed, 20 Oct 2021 07:17:48 GMT</pubDate>
            <description><![CDATA[<h1 id="image-위젯">Image 위젯</h1>
<h2 id="image-사용-설정">Image 사용 설정</h2>
<h3 id="assets-폴더-생성">assets 폴더 생성</h3>
<ul>
<li>프로젝트에서 [new -&gt; Directory]를 선택해서 assets라는 새로운 폴더를 만들어줍니다.
<img src="https://images.velog.io/images/ruinak_4127/post/7f9f950a-6163-4833-bf3a-a18ab26b26e1/Screenshot_1.jpg" alt=""><img src="https://images.velog.io/images/ruinak_4127/post/ed38640e-13ca-4c80-97ca-3808a9edbdfe/Screenshot_2.jpg" alt=""><h3 id="pubspecyaml-설정-변경">pubspec.yaml 설정 변경</h3>
</li>
<li>폴더를 만든 후 pubspec.yaml이라는 설정파일에 들어가서 assets:의 주석을 풀고, 추가로 -assets/를 입력합니다.</li>
<li>assets를 자원폴더로 쓰겠다는 의미입니다.
<img src="https://images.velog.io/images/ruinak_4127/post/07a4ed7d-f72b-4acd-be20-4972bcba9034/Screenshot_3.jpg" alt=""></li>
<li>입력을 완료한 후 우측 상단의 Pub get을 눌러주면 동기화가 완료되며 사용할 수 있게 됩니다.<h3 id="gif-이미지-파일-준비">gif 이미지 파일 준비</h3>
</li>
<li>구글에서 gif 이미지 파일을 하나 받아서 준비해줍니다.
<img src="https://images.velog.io/images/ruinak_4127/post/8a8eaf71-12de-421c-954c-13085f631aed/pikachu.gif" alt=""></li>
<li>준비한 gif 파일을 assets 폴더에 넣어줍니다.
<img src="https://images.velog.io/images/ruinak_4127/post/5a4a1ae6-6d14-4053-845a-f91c4c11f22f/Screenshot_5.jpg" alt=""><h2 id="디바이스에-출력하기">디바이스에 출력하기</h2>
</li>
<li>body에 Image.asset을 이용해서 사용하려는 이미지의 경로를 지정하면 디바이스에 출력이 됩니다.
<img src="https://images.velog.io/images/ruinak_4127/post/45de77ca-d516-4508-89c5-e05ccbf63536/Screenshot_6.jpg" alt=""><pre><code>class FirstApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
  return MaterialApp(
    home: SafeArea(
      child: Scaffold(
        body: Image.asset(&quot;assets/pikachu.gif&quot;),
      ),
    ),
  );
}
}</code></pre><h2 id="추가-조작">추가 조작</h2>
<h3 id="사이즈-조절---fit-boxfit">사이즈 조절 - fit: Boxfit</h3>
</li>
<li>이미지 경로 뒤에 ( , )를 이용해서 다른 스타일들도 설정할 수 있습니다.</li>
<li>너비와 높이를 지정할 수 있으며, 둘 중 하나의 값만 지정하면 비율에 따라서 나머지가 조절됩니다.</li>
<li>fit: Boxfit을 사용하면 크기 내에서 원하는 비율로 이미지를 출력할 수 있습니다.
<img src="https://images.velog.io/images/ruinak_4127/post/eee54332-5420-4b93-a5f3-cdf3a9637a6c/Screenshot_7.jpg" alt=""><pre><code>...
body: Image.asset(
&quot;assets/pikachu.gif&quot;,
width: 100,
height: 300,
fit: BoxFit.fill,
),
...</code></pre><h3 id="위치-조절---center">위치 조절 - Center</h3>
</li>
<li>Image.asset에서 Alt + Enter를 해보면 Center로 감쌀 수 있습니다.</li>
<li>Center로 감싸면 화면의 정중앙에 배치가 됩니다.
<img src="https://images.velog.io/images/ruinak_4127/post/a72345ba-afb0-46d2-9827-69d8be63f0a1/Screenshot_8.jpg" alt=""><pre><code>...
body: Center(
child: Image.asset(
  &quot;assets/pikachu.gif&quot;,
  width: 300,
  height: 200,
  fit: BoxFit.fill,
),
...</code></pre><h3 id="위치-조절---alignment">위치 조절 - Alignment</h3>
</li>
<li>Center를 사용하지 않고도 중앙에 배치할 수 있습니다.</li>
<li>Image.asset을 Container로 감싼 후 alignment 값을 0을 줌으로써 정중앙에 배치할 수 있습니다.<pre><code>body: Container(
alignment: Alignment(0.0, 0.0),
child: Image.asset(
  &quot;assets/pikachu.gif&quot;,
  width: 300,
  height: 200,
  fit: BoxFit.fill,
),</code></pre></li>
</ul>
<h1 id="전체-코드">전체 코드</h1>
<pre><code>// ignore_for_file: prefer_const_literals_to_create_immutables, prefer_const_constructors
import &#39;package:flutter/material.dart&#39;;

// main 스레드는 runApp 을 실행시키고 종료됩니다.
void main() {
  // 비동기로 실행됨(이벤트 루프에 등록된다)
  runApp(FirstApp());
  // sleep(Duration(seconds: 2));
  // print(&quot;main 종료&quot;);
}

class FirstApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SafeArea(
        child: Scaffold(
          body: Container(
            alignment: Alignment(0.0, 0.0),
            child: Image.asset(
              &quot;assets/pikachu.gif&quot;,
              width: 300,
              height: 200,
              fit: BoxFit.fill,
            ),
          ),
        ),
      ),
    );
  }
}
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Flutter Text 위젯]]></title>
            <link>https://velog.io/@ruinak_4127/Flutter-Text-%EC%9C%84%EC%A0%AF</link>
            <guid>https://velog.io/@ruinak_4127/Flutter-Text-%EC%9C%84%EC%A0%AF</guid>
            <pubDate>Mon, 18 Oct 2021 14:58:18 GMT</pubDate>
            <description><![CDATA[<h1 id="text-위젯">Text 위젯</h1>
<ul>
<li><p>Text 위젯에는 클래스인 TextStyle을 이용해서 스타일을 바꿔줄 수 있습니다.</p>
</li>
<li><p>TextStyle은 클래스이므로 생성자 위치에 값을 넣어주면 됩니다.</p>
</li>
<li><p>폰트 색상, 배경색상, 폰트 크기, 폰트 두께 등을 변경할 수 있습니다.</p>
<h2 id="textstyle---text-스타일링">TextStyle - Text 스타일링</h2>
</li>
<li><p>style을 이용해서 TextStyle을 사용합니다.
<img src="https://images.velog.io/images/ruinak_4127/post/859dced3-0a6e-46f2-b421-f5af188cdeda/Screenshot_1.jpg" alt=""></p>
<pre><code>class FirstApp extends StatelessWidget {

@override
Widget build(BuildContext context) {
  return MaterialApp(
    home: SafeArea(
      child: Scaffold(
        body: Text(
          &quot;안녕&quot;,
          style: TextStyle(
            color: Colors.red,
            fontSize: 30,
            backgroundColor: Colors.blue,
            fontWeight: FontWeight.w800,
          ),
        ),
      ),
    ),
  );
}
}</code></pre><h2 id="textalign---text-정렬">TextAlign - Text 정렬</h2>
</li>
<li><p>Text는 범위가 배경범위 안에서 돌기 때문에 TextAlign을 이용해서 정렬을 할 수 없습니다.</p>
</li>
<li><p>TextAlign을 사용하기 위해서는 Text를 Container로 감싸줍니다.
<img src="https://images.velog.io/images/ruinak_4127/post/e5929c6a-0246-4315-a03c-1d216d1d02fc/Screenshot_3.jpg" alt=""></p>
<pre><code>...
body: Container(
 child: Text(
   &quot;안녕&quot;,
   textAlign: TextAlign.right,
   style: TextStyle(
     color: Colors.red,
     fontSize: 30,
     backgroundColor: Colors.blue,
     fontWeight: FontWeight.w800,
   ),
 ),
),
...</code></pre></li>
<li><p>감싸고 보면은 Container의 영역은 자식인 Text의 영역만큼만 차지합니다.</p>
</li>
<li><p>Container는 항상 자식의 크기에 맞춰지며, 자식이 없으면 부모의 크기에 맞춰집니다.</p>
</li>
<li><p>Container의 가로와 세로를 지정해주면 확장이 됩니다.</p>
</li>
<li><p>double.infinity를 사용하면 끝까지 확장이 됩니다.</p>
</li>
<li><p>이제 alignment를 사용하면 텍스트의 위치를 바꿀 수 있습니다.
<img src="https://images.velog.io/images/ruinak_4127/post/021be9a2-8f94-4590-9595-b7fbc23f10b4/Screenshot_4.jpg" alt=""></p>
<pre><code>body: Container(
height: double.infinity,
width: double.infinity,
color: Colors.green,
alignment: Alignment(1.0, 1.0),
child: Text(
  &quot;안녕&quot;,
  style: TextStyle(
    color: Colors.red,
    fontSize: 30,
    backgroundColor: Colors.blue,
    fontWeight: FontWeight.w800,
  ),
),
),</code></pre><h2 id="textrich---여러-개의-text-넣기">Text.rich - 여러 개의 Text 넣기</h2>
</li>
<li><p>Text를 여러 개 넣고 싶다면 Text를 Row로 감싸줍니다.</p>
</li>
<li><p>Row로 감싸면 Text가 왼쪽으로 정렬이됩니다.</p>
</li>
<li><p>Row가 왼쪽 끝에서부터 오른쪽 끝까지 다 차지하고 있으므로 alignment가 적용이 안됩니다.
<img src="https://images.velog.io/images/ruinak_4127/post/0efed489-fae1-4d84-ae3d-c2c56a8608fc/Screenshot_5.jpg" alt=""></p>
<pre><code>body: Container(
height: double.infinity,
width: double.infinity,
color: Colors.green,
alignment: Alignment(1.0, 1.0),
child: Row(
  children: [
    Text(
      &quot;안녕&quot;,
      style: TextStyle(
        color: Colors.red,
        fontSize: 30,
        backgroundColor: Colors.blue,
        fontWeight: FontWeight.w800,
      ),
    ),
  ],
),
),</code></pre></li>
<li><p>Text를 하나 추가하고 길게 적으면 화면을 벗어나면서 깨지게됩니다.
<img src="https://images.velog.io/images/ruinak_4127/post/2c986024-50b0-4b75-8db4-71469ada0019/Screenshot_6.jpg" alt=""></p>
</li>
<li><p>이와 같이 Row는 사용할 수 없으므로 Text.rich( )를 사용합니다.</p>
</li>
<li><p>Text.rich 내부에 TextSpan을 사용하면 화면을 넘어가는 긴 문장이 오는 경우 다음 줄로 넘어갑니다.
<img src="https://images.velog.io/images/ruinak_4127/post/02f13a2a-11e0-4359-b16a-a2dbe7ec7c90/Screenshot_7.jpg" alt=""></p>
<pre><code>body: Container(
height: double.infinity,
width: double.infinity,
color: Colors.green,
alignment: Alignment(1.0, 1.0),
child: Text.rich(
  TextSpan(children: [
    TextSpan(text: &quot;안녕&quot;),
    TextSpan(text: &quot;안녕하세요안녕하세요안녕하세요안녕하세요안녕하세요안녕하세요안녕하세요&quot;),
  ]),
),
),</code></pre></li>
<li><p>Text.rich를 사용하면 내부의 텍스트를 구분해서 스타일링할 수 있습니다.
<img src="https://images.velog.io/images/ruinak_4127/post/861cc79e-33e8-47fa-8865-6cf78e9354c4/Screenshot_8.jpg" alt=""></p>
</li>
</ul>
<h1 id="전체-코드">전체 코드</h1>
<pre><code>// ignore_for_file: prefer_const_literals_to_create_immutables, prefer_const_constructors
import &#39;package:flutter/material.dart&#39;;

// main 스레드는 runApp 을 실행시키고 종료됩니다.
void main() {
  // 비동기로 실행됨(이벤트 루프에 등록된다)
  runApp(FirstApp());
  // sleep(Duration(seconds: 2));
  // print(&quot;main 종료&quot;);
}

class FirstApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SafeArea(
        child: Scaffold(
          body: Container(
            height: double.infinity,
            width: double.infinity,
            color: Colors.green,
            alignment: Alignment(1.0, 1.0),
            child: Text.rich(
              TextSpan(children: [
                TextSpan(text: &quot;안녕&quot;, style: TextStyle(color: Colors.red)),
                TextSpan(text: &quot;안녕하세요안녕하세요안녕하세요안녕하세요안녕하세요안녕하세요안녕하세요안녕하세요&quot;),
              ]),
            ),
          ),
        ),
      ),
    );
  }
}
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Flutter ListView]]></title>
            <link>https://velog.io/@ruinak_4127/Flutter-ListView</link>
            <guid>https://velog.io/@ruinak_4127/Flutter-ListView</guid>
            <pubDate>Sat, 16 Oct 2021 12:58:16 GMT</pubDate>
            <description><![CDATA[<h1 id="listview">ListView</h1>
<ul>
<li>높이 지정을 디바이스의 크기보다 크게 지정하게 되면 아래와 같이 깨지게 됩니다.
<img src="https://images.velog.io/images/ruinak_4127/post/62fc02ce-7285-47cf-ab7c-2e7a6aa11168/Screenshot_1.jpg" alt=""><pre><code>// main 스레드는 runApp 을 실행시키고 종료됩니다.
void main() {
// 비동기로 실행됨(이벤트 루프에 등록된다)
runApp(FirstApp());
// sleep(Duration(seconds: 2));
// print(&quot;main 종료&quot;);
}
</code></pre></li>
</ul>
<p>class FirstApp extends StatelessWidget {
  const FirstApp({Key? key}) : super(key: key);</p>
<p>  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SafeArea(
        child: Scaffold(
          // Column은 가로는 가지고 있지만 세로는 가지고 있지 않음
          body: Column(
            // Column은 배열로 감싸져 있음
            children: [
              Container(
                height: 500,
                color: Colors.blue,
              ),
              Container(
                height: 300,
                color: Colors.red,
              ),
            ],
          ),
        ),
      ),
    );
  }</p>
<pre><code>- 이럴 때 Column 대신에 ListView로 바꾸면 스크롤이 달리게 되어 깨지지 않습니다.
![](https://images.velog.io/images/ruinak_4127/post/879a042f-5a9f-4297-bbe0-7f092f4f6294/Screenshot_2.jpg)</code></pre><p>...</p>
<p>child: Scaffold(
 body: ListView(
   children: [</p>
<p>...</p>
<pre><code>- 일반적으로 앱에서 키보드가 올라오면 화면이 깨지게 되어있습니다.
- 키보드를 사용할때 ListView를 사용하면 화면깨짐 없이 사용할 수 있습니다.

## ListView.builder
- 리스트뷰 빌더는 Container를 반복할 수 있습니다.
- Container 내부에 문자를 넣고 싶을땐 child 속성을 이용해서 Text를 넣어줍니다.
- itemCount를 이용해서 반복 횟수를 지정할 수 있습니다.
![](https://images.velog.io/images/ruinak_4127/post/ca2bb2f1-81a3-4dcb-b3ad-8e4a208d8943/Screenshot_3.jpg)</code></pre><p>class FirstApp extends StatelessWidget {</p>
<p>  // 배열 선언
  final colorCodes = [600, 500, 300, 200, 100];</p>
<p>  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SafeArea(
        child: Scaffold(
          body: ListView.builder(
            // itemCount를 이용해서 반복 횟수 지정가능
            itemCount: 5,
            itemBuilder: (BuildContext context, int index) {
              return Container(
                height: 50,
                // 컬러에 값을 넣으면 색상의 진하기를 지정할 수 있음
                color: Colors.amber[colorCodes[index]],
                child: Text(&quot;번호 ${index}&quot;),
              );
            },
          ),
        ),
      ),
    );
  }
}</p>
<pre><code>
## padding
- padding과 EdgeInsets을 사용해서 간격을 띄울 수 있습니다.
- EdgeInsets.symmetric(vertical: ? ) : 상단
- padding: EdgeInsets.all(?) : 모든 방향
![](https://images.velog.io/images/ruinak_4127/post/c5c04f4f-6176-4cc8-9dde-9a77dda9743d/Screenshot_4.jpg)![](https://images.velog.io/images/ruinak_4127/post/8c9c0a01-8c26-4a0e-a391-f4a041c92915/Screenshot_5.jpg)</code></pre><p>class FirstApp extends StatelessWidget {
  // 배열 선언
  final colorCodes = [600, 500, 300, 200, 100];</p>
<p>  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SafeArea(
        child: Scaffold(
          body: ListView.builder(
            // padding을 사용하면
            padding: EdgeInsets.all(10),
            // itemCount를 이용해서 반복 횟수 지정가능
            itemCount: 5,
            itemBuilder: (BuildContext context, int index) {
              return Container(
                height: 50,
                // 컬러에 값을 넣으면 색상의 진하기를 지정할 수 있음
                color: Colors.amber[colorCodes[index]],
                child: Text(&quot;번호 ${index}&quot;),
              );
            },
          ),
        ),
      ),
    );
  }
}</p>
<pre><code>### ListView 사이 간격 주기
- ListView 사이에 간격을 주기 위해서 Column으로 전체를 잡아주고 height 값을 작게 가지는 Container를 하나 추가해줍니다.
![](https://images.velog.io/images/ruinak_4127/post/e60215a5-4322-42ae-a56f-c8080a607cdf/Screenshot_6.jpg)</code></pre><p>return Column(
  children: [
    Container(
      padding: EdgeInsets.all(10),
      height: 50,
      // 컬러에 값을 넣으면 색상의 진하기를 지정할 수 있음
      color: Colors.amber[colorCodes[index]],
      child: Text(&quot;번호 ${index}&quot;),
    ),
    Container(
      height: 5,
    )
  ],
);</p>
<pre><code>- double.infinity를 사용하면 화면의 끝까지 다 채울 수 있습니다.
![](https://images.velog.io/images/ruinak_4127/post/51718f10-129e-4187-bd8f-e192ff62595f/Screenshot_7.jpg)
- 배열의 데이터도 뿌릴 수 있습니다.
![](https://images.velog.io/images/ruinak_4127/post/7b0ac548-1467-4be9-82c3-9ca19c204044/Screenshot_8.jpg)</code></pre><p>body: ListView.builder(
  // padding을 사용하면
  padding: EdgeInsets.all(10),
  // itemCount를 이용해서 반복 횟수 지정가능
  itemCount: 5,
  itemBuilder: (BuildContext context, int index) {
    return Column(
      children: [
        Container(
          padding: EdgeInsets.all(10),
          // double.infinity는 상수값으로 가로를 끝까지 다 채움
          width: double.infinity,
          height: 50,
          // 컬러에 값을 넣으면 색상의 진하기를 지정할 수 있음
          color: Colors.amber[colorCodes[index]],
          child: Text(&quot;데이터 : ${data[index]}&quot;),
        ),
        // ListView 사이 여백 넣기
        Container(
          height: 5,
        )
      ],
    );
  },
),</p>
<pre><code>
# 메서드 추출하기
- 내가 추출하고 싶은 부분에서 **Ctrl + Alt + M**을 사용하면 메서드로 추출이 가능합니다.
- 코드를 깔끔하게 만들 수 있습니다.
![](https://images.velog.io/images/ruinak_4127/post/aa4703ac-8488-4cc9-8b1b-74135d2b8513/Screenshot_9.jpg)![](https://images.velog.io/images/ruinak_4127/post/02f0372a-746a-44d8-9a46-6e326ca91e1c/Screenshot_10.jpg)
# ListTile
- ListTile은 return type이 ListTile입니다.
- ListTile뿐만 아니라 대부분 statelessWidget이나 statefulWidget의 자식이므로 결론적으로는 Widget의 자식입니다.
- return type으로 Widget을 사용할 수 있습니다.</code></pre><p>  Widget buildColumn(int index) {
    return ListTile();
  }</p>
<pre><code>## title과 subtitle
- title과 subtitle은 아래와 같이 사용할 수 있습니다.
![](https://images.velog.io/images/ruinak_4127/post/9293de85-71e9-4327-9ec5-39be86e68574/Screenshot_11.jpg)</code></pre><p>Widget buildColumn(int index) {
  return ListTile(
    title: Text(&quot;제목&quot;),
    subtitle: Text(&quot;부제목&quot;),
  );
}</p>
<pre><code>## leading
- leading에는 widget이 들어올 수 있습니다.
- 일반적으로 leading에는 사진이나 아이콘을 주로 사용합니다.
![](https://images.velog.io/images/ruinak_4127/post/46f66dcd-fdda-4274-9fba-1a305216b463/Screenshot_12.jpg)</code></pre><p>return ListTile(
  title: Text(&quot;제목&quot;),
  subtitle: Text(&quot;부제목&quot;),
  // leading에는 widget이 들어올 수 있습니다.
  // 일반적으로 leading에는 사진이나 아이콘을 주로 사용합니다.
  leading: Icon(Icons.account_box_sharp),
);</p>
<pre><code>## onTap
- onTap에는 return 값이 없는 void가 들어갑니다.
- return 값이 없는 void는 익명함수로 만들면 됩니다.
- 아래와 같이 넣고 ListView를 클릭하면 눌러짐이 출력됩니다.
![](https://images.velog.io/images/ruinak_4127/post/6bc14440-8174-44d9-8351-b6ba0fe597ab/Screenshot_13.jpg)</code></pre><p>return ListTile(
  title: Text(&quot;제목&quot;),
  subtitle: Text(&quot;부제목&quot;),
  // leading에는 widget이 들어올 수 있습니다.
  // 일반적으로 leading에는 사진이나 아이콘을 주로 사용합니다.
  leading: Icon(Icons.account_box_sharp),
  // onTap에는 return 값이 없는 void가 들어갑니다.
  // return 값이 없는 void는 익명함수로 만들면 됩니다.
  onTap: () {
    // ListView를 클릭하면 눌러짐이 출력됩니다.
    print(&quot;눌러짐&quot;);
  },
);</p>
<pre><code>## 구분선 만들기
- ListTile을 Column으로 감싸줍니다.
- ListTile이 끝나는 부분에 Container를 새로 넣어서 높이를 1로 하고 검정색으로 지정해주면 선처럼 보입니다.
![](https://images.velog.io/images/ruinak_4127/post/b9f052a3-b3fd-4ea8-85ad-60cead630eb2/Screenshot_14.jpg)</code></pre><p>return Column(
  children: [
    ListTile(
      title: Text(&quot;제목&quot;),
      subtitle: Text(&quot;부제목&quot;),
      // leading에는 widget이 들어올 수 있습니다.
      // 일반적으로 leading에는 사진이나 아이콘을 주로 사용합니다.
      leading: Icon(Icons.account_box_sharp),
      // onTap에는 return 값이 없는 void가 들어갑니다.
      // return 값이 없는 void는 익명함수로 만들면 됩니다.
      onTap: () {
        // ListView를 클릭하면 눌러짐이 출력됩니다.
        print(&quot;눌러짐&quot;);
      },
    ),
    Container(
      height: 1,
      color: Colors.black,
    )
  ],
);</p>
<pre><code>
## 구분선 응용
- 아래와 같이 Row와 Container를 이용해서 나만의 구분선을 디자인할 수 있습니다.
![](https://images.velog.io/images/ruinak_4127/post/27911068-f1ee-414e-9717-0d2e4d81914a/Screenshot_15.jpg)</code></pre><p>Widget buildColumn(int index) {
  return Column(
    children: [
      ListTile(
        title: Text(&quot;제목&quot;),
        subtitle: Text(&quot;부제목&quot;),
        // leading에는 widget이 들어올 수 있습니다.
        // 일반적으로 leading에는 사진이나 아이콘을 주로 사용합니다.
        leading: Icon(Icons.account_box_sharp),
        // onTap에는 return 값이 없는 void가 들어갑니다.
        // return 값이 없는 void는 익명함수로 만들면 됩니다.
        onTap: () {
          // ListView를 클릭하면 눌러짐이 출력됩니다.
          print(&quot;눌러짐&quot;);
        },
      ),
      Row(
        children: [
          Expanded(
            flex: 3,
            child: Container(
              height: 1,
              color: Colors.black,
            ),
          ),
          Expanded(
            flex: 1,
            child: Container(
              child: Icon(Icons.accessibility_sharp),
            ),
          ),
          Expanded(
            flex: 3,
            child: Container(
              height: 1,
              color: Colors.red,
            ),
          ),
        ],
      )
    ],
  );
}</p>
<pre><code>
# 정리(핵심)!!
- ListView는 내가 가지고 있는 자식들이 화면을 벗어날 때 사용하면 스크롤이 생깁니다.
- 데이터베이스나 API를 사용해서 데이터를 가져와서 뿌릴때, builder를 사용해서 뿌리면 됩니다.
- 메서드를 추출할 때는 Ctrl + Alt + M을 사용합니다.
- 기본적인 리스트의 형태를 표현하고 싶을때는 ListTile을 사용하는게 편합니다.
    - 다른 형태로 만들고 싶으면 Column, Row, Container를 이용해서 구현하면 됩니다.

# 최종 코드</code></pre><p>// ignore_for_file: prefer_const_literals_to_create_immutables, prefer_const_constructors
import &#39;package:flutter/material.dart&#39;;</p>
<p>// main 스레드는 runApp 을 실행시키고 종료됩니다.
void main() {
  // 비동기로 실행됨(이벤트 루프에 등록된다)
  runApp(FirstApp());
  // sleep(Duration(seconds: 2));
  // print(&quot;main 종료&quot;);
}</p>
<p>class FirstApp extends StatelessWidget {
  // 배열 선언
  final colorCodes = [600, 500, 300, 200, 100];
  final data = [&#39;가&#39;, &#39;나&#39;, &#39;다&#39;, &#39;라&#39;, &#39;마&#39;];</p>
<p>  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SafeArea(
        child: Scaffold(
          body: ListView.builder(
            // padding을 사용하면
            padding: EdgeInsets.all(10),
            // itemCount를 이용해서 반복 횟수 지정가능
            itemCount: 5,
            itemBuilder: (BuildContext context, int index) {
              return buildColumn(index);
            },
          ),
        ),
      ),
    );
  }</p>
<p>  Widget buildColumn(int index) {
    return Column(
      children: [
        ListTile(
          title: Text(&quot;제목&quot;),
          subtitle: Text(&quot;부제목&quot;),
          // leading에는 widget이 들어올 수 있습니다.
          // 일반적으로 leading에는 사진이나 아이콘을 주로 사용합니다.
          leading: Icon(Icons.account_box_sharp),
          // onTap에는 return 값이 없는 void가 들어갑니다.
          // return 값이 없는 void는 익명함수로 만들면 됩니다.
          onTap: () {
            // ListView를 클릭하면 눌러짐이 출력됩니다.
            print(&quot;눌러짐&quot;);
          },
        ),
        Row(
          children: [
            Expanded(
              flex: 3,
              child: Container(
                height: 1,
                color: Colors.black,
              ),
            ),
            Expanded(
              flex: 1,
              child: Container(
                child: Icon(Icons.accessibility_sharp),
              ),
            ),
            Expanded(
              flex: 3,
              child: Container(
                height: 1,
                color: Colors.red,
              ),
            ),
          ],
        )
      ],
    );
  }
}</p>
<pre><code>

</code></pre>]]></description>
        </item>
    </channel>
</rss>