<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jm_dae.log</title>
        <link>https://velog.io/</link>
        <description>즐겁게 개발</description>
        <lastBuildDate>Wed, 28 Aug 2024 08:11:32 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jm_dae.log</title>
            <url>https://velog.velcdn.com/images/jm_dae/profile/37ee7c19-5328-4219-ad2f-8cd6b5f8b1ec/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jm_dae.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jm_dae" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[localStorage vs sessionStorage]]></title>
            <link>https://velog.io/@jm_dae/localStorage-vs-sessionStorage</link>
            <guid>https://velog.io/@jm_dae/localStorage-vs-sessionStorage</guid>
            <pubDate>Wed, 28 Aug 2024 08:11:32 GMT</pubDate>
            <description><![CDATA[<p>localStorage와 sessionStorage는 둘 다 저장소로서의 기능은 대부분 동일하다.</p>
<p>하지만 sessionStorage의 경우 세션이 종료되면 저장된 데이터도 함께 사라진다는 점이 다른점이다.</p>
<ul>
<li>localStorage<ul>
<li>로컬에 도메인 별로 지속되는 storage</li>
<li>localStorage는 시간제한이 없고 브라우저가 꺼져도 죽지 않는다.</li>
<li>값을 지우려면 직접 지워줘야한다.</li>
</ul>
</li>
<li>sessionStorage<ul>
<li>세션이 (프로세스, 텝, 브라우저) 종료될 때까지 지속되는 storage</li>
<li>localStorage는 소멸 타이밍이 없다. 즉 직접 지워야한다. 그리나 sessionStorage는 세션의 종료시 죽음을 맞이한다.</li>
</ul>
</li>
</ul>
<p>쿠키는 서버측과 클라이언트측 양쪽에서 쿠키 데이터를 사용하는 api가 존재한다.</p>
<p>이와 달리 localStorage는 로컬환경에서만 컨트롤된다.</p>
<p>또한 localStorage는 기간 기능이 없어서 소멸 기간을 정해주지 못한다.</p>
<p>localStorage는 자바스크립트 객체 자체를 넣는 것이 가능하다</p>
<p>sessionStorage는 다른 탭이라면 데이터가 공유되지 않는다.</p>
<p>localStorage의 키와 값은 반드시 문자열이어야한다. 다른 자료형을 사용하게 되면 문자열로 자동 변환된다.</p>
<p>localStorage와 sessionStorage의 데이터가 갱신될 때 storage 이벤트가 실행이 된다.</p>
<ul>
<li>key - 변경된 데이터의 키</li>
<li>oldValue - 이전 값(키가 새롭게 추가되었다면 null)</li>
<li>newValue - 새로운 값(키가 삭제되었다면 null)</li>
<li>url - 갱신이 일어난 문서의 url</li>
<li>storageArea - 갱신이 일어난 localStorage나 sessionStorage 객체</li>
</ul>
<p>event.storageArea에는 스토리지 객체가 포함되어 있다. storage 이벤트는 sessionStorage나 localStorage가 변경될 때 모두 발생하기 때문에 스토리지 종류에 상관없이 실제 수정이 일어나면 응답이 가능하다.</p>
<p>참고 </p>
<ul>
<li><a href="https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-localStorage-sessionStorage">https://inpa.tistory.com/entry/JS-📚-localStorage-sessionStorage</a></li>
<li><a href="https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-%EC%BF%A0%ED%82%A4Cookie-%EB%8B%A4%EB%A3%A8%EA%B8%B0">https://inpa.tistory.com/entry/JS-📚-쿠키Cookie-다루기</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[async/await vs Promise]]></title>
            <link>https://velog.io/@jm_dae/asyncawait-vs-Promise</link>
            <guid>https://velog.io/@jm_dae/asyncawait-vs-Promise</guid>
            <pubDate>Tue, 20 Aug 2024 07:08:03 GMT</pubDate>
            <description><![CDATA[<p>먼저 <strong>비동기 작업</strong>이란 특정 코드의 로직이 끝날 때까지 기다리지 않고, <strong>나머지 코드를 먼저 실행</strong>하는 것이다. 비동기 프로그래밍은 웹에서 메인 스레드를 차단하지 않고 시간 소모적인 작업을 <strong>병렬적</strong>으로 수행할 수 있도록 하는 중요한 기능이다.</p>
<h3 id="promise">Promise</h3>
<p><strong>Promise</strong>는 비동기 함수의 결과를 담고 있는 <strong>독자적인 객체</strong>이다. 비동기 작업이 끝날 때까지 결과를 기다리는 것이 아니라, <strong>결과를 제공하겠다는 약속</strong>을 반환한다는 의미이다.
<strong>Promise</strong> 객체는 <strong>resolve</strong>와 <strong>reject</strong>로 나눠져서 성공과 실패 메서드로 나누어진다.
<strong>Promise</strong> 객체 내부에서 <strong>resolve</strong>를 호출하게 되면 바로 <strong>.then메서드</strong>로 이어져서 콜백함수에서 성공에 대한 추가 처리를 진행한다.
반대로 <strong>Promise</strong>객체 내부에서 <strong>reject</strong>를 호출하게 되면 바로 <strong>.catch</strong>메서드로 이어져서 추가적인 처리가 진행된다.
<strong>.finally</strong> 키워드는 프로미스가 이행되거나 거부되는 것과 <strong>상관없이 실행</strong>할 콜백함수를 등록하여 처리할 수 있다.
promise의 상태에는 <strong>진행중: pending, 성공: fulfilled, 실패: rejected</strong>가 있다.</p>
<h3 id="asyncawait">async/await</h3>
<p>함수 앞에 <strong>async</strong>를 붙이면 <strong>&quot;이 함수는 비동기적인 함수이고 Promise 를 반환한다&quot;</strong>라고 선언하는 것과 같다. async를 붙이게되면 어떤 값을 리턴하든 <strong>무조건 프로미스 객체</strong>로 감싸져 <strong>반환</strong>된다는 특징이 있습니다.
<strong>await</strong>를 붙이면, 해당 <strong>Promise의 상태가 바뀔 때까지 코드가 기다려야한다</strong>. Promise가 성공 상태 또는 실패 상태로 바뀌기 전까지는 다음 연산을 시작하지 않는 것과 같다.
async/await내부에서 Promise.resolve(fulfilled), Promise.reject(rejected)와 같이 프로미스 상태를 다르게 지정할 수 있다.</p>
<pre><code>async function resolveP() {
    return Promise.resolve(2);
}
async function rejectP() {
    return Promise.reject(2);
}</code></pre><p>async 함수 내부에서 예외 throw를 해도 실패(rejected)상태의 프로미스객체를 반환하고 return을 하지 않아도 undefined가 처리되지만 어쨌든 프로미스 객체를 반환하게 된다.</p>
<h3 id="asyncawait-vs-promise">async/await vs Promise</h3>
<p><strong>Promise</strong>는 <strong>.then</strong>메서드를 연속적으로 사용하여 <strong>비동기 처리</strong>를 하지만 <strong>async/await</strong>는 <strong>await</strong>키워드로 <strong>비동기 처리를 기다리고 있다</strong>는 것을 <strong>직관적</strong>으로 표현한다는 것을 알 수 있다. <strong>async/await</strong>는 <strong>비동기적 접근 방식</strong>을 <strong>동기적</strong>으로 작성할 수 있게 해주어 코드가 <strong>간결</strong>해지고 <strong>가독성</strong>이 높아져 <strong>유지보수</strong>를 용이하게 해준다.(단, 순서에 상관없이 데이터를 불러오는 상황에서 <strong>await를 막무가내</strong>로 사용하면 <strong>오히려 성능이 저하되는 문제</strong>가 발생한다.)</p>
<pre><code>fetch(&#39;api&#39;)
    .then(response =&gt; response.json())
    .then(data =&gt; )
    .then(response =&gt; )
    .then(data =&gt; )
    .then()
    .catch()</code></pre><p> <strong>.then메서드</strong>를 연속적으로 사용하면 코드가 길어지지고 가독성이 안좋아지지만</p>
<pre><code> async function getData() {
     const response = await fetch(&#39;/api&#39;);
       const data = await response.json();
       const response2 = await fetch(&#39;/api2&#39;);
    ...
 }
 getData();</code></pre><p> 위와 같이 <strong>async/await</strong>를 사용하게 된다면 훨씬 <strong>직관적</strong>이고 <strong>간결</strong>한 것을 확인할 수 있다.</p>
<p><strong>Promise.then()방식</strong>의 에러 처리는 <strong>catch()</strong> 핸들러를 중간 중간에 명시함으로써 에러를 받아야하는 <strong>번거로움</strong>이 있지만 <strong>async/await</strong>와 같은 비동기 처리에 대해서 에러를 처리하려면 <strong>try/catch문</strong>을 씌우면 되게 된다.</p>
<pre><code>function fetchResource(url) {
    fetch(url)
        .then(res =&gt; res.json())
        .then(data =&gt; )
        .catch(err =&gt; );
}</code></pre><pre><code>async function func() {
    try {
        const res = await fetch(url);
        const data = await res.json();
    } catch (err) {
    }
}
func();</code></pre><p>위와 같이 async/await는 try/catch문으로 감싸면돼서 <strong>간결</strong>하고 <strong>편리</strong>하다.</p>
<h3 id="await의-단점-보완논블록킹promiseall">await의 단점 보완(논블록킹/Promise.all)</h3>
<h4 id="논블록킹">논블록킹</h4>
<p>데이터를 불러올 때 <strong>순서에 상관없이</strong> 데이터를 불러오는 상황이면 await를 사용하지 않고 미리 <strong>논블록킹</strong>으로 실행을 하고 난 다음에 프로미스 객체 결과 변수를 await를 통해서 꺼내쓰면 된다. </p>
<pre><code>function getApple() {
    return new Promise((resolve, reject) =&gt; {
        setTimeout(() =&gt; resolve(&quot;apple&quot;), 1000);
    })
}
function getBanana() {
    return new Promise((resolve, reject) =&gt; {
        setTimeout(() =&gt; resolve(&quot;banana&quot;), 1000);
    })
}

async function getFruites() {
    console.time();
    let a = await getApple();
    let b = await getBanana();
    console.log(a, b);
    console.timeEnd();
}
getFruites();</code></pre><hr>
<p>밑에 캡쳐한 코드는 vue를 활용하여 작성한 코드이다.
<img src="https://velog.velcdn.com/images/jm_dae/post/141f368f-33fd-4d25-9352-6a52ce6663de/image.png" alt=""></p>
<p>위와 같이 async/await를 요청하게 된다면 a를 받은 다음에 b를 실행하기 때문에 시간이 오래걸린다. 이를 해결하기 위해서는 아래와 같이 작성해주면 된다.
<img src="https://velog.velcdn.com/images/jm_dae/post/3aa7df65-8045-4e1c-a1e2-a188db41733f/image.png" alt=""></p>
<pre><code>async function getFruites() {
    console.time();
    let getApplePromise = getApple();
    let getBananaPromise = getBanana();
    // 위와 같이 async함수를 논블록킹으로 작성하면 백단에서 독립적으로 거의 동시에 실행되게 된다.
    let a = await getApplePromise;
    let b = await getBananaPromise;
    // 결과 변수를 await를 통해 꺼내온다.
    console.log(a, b);
    console.timeEnd();
}
getFruites();</code></pre><p><img src="https://velog.velcdn.com/images/jm_dae/post/4a4d9034-3bf3-442f-9bf8-d7b2548e7de1/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/2bc3ca14-0398-498e-8a29-d2f51ba9bac6/image.png" alt=""></p>
<h4 id="promiseall">Promise.all</h4>
<p><strong>Promise.all</strong>은 배열 인자의 각 프로미스 비동기 함수들이 resolved가 모두 되어야 결과를 리턴 받는다. <strong>배열인자</strong>의 각 프로미스 함수들은 <strong>제각각 비동기 논블록킹으로 실행</strong>되어 시간을 단축할 수 있다.</p>
<pre><code>async function getFruites() {
    console.time();
    let [ a, b ] = await Promise.all([getApple(), getBanana()]);
    console.log(a, b);
    console.timeEnd();
}
getFruites();</code></pre><p><img src="https://velog.velcdn.com/images/jm_dae/post/82cd94ef-c860-4499-bb9d-07dad81d8775/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/99c418c8-21f8-46ab-abb3-13d2afe3e06a/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CSS :not(:last-child)에 관해서]]></title>
            <link>https://velog.io/@jm_dae/CSS-notlast-child%EC%97%90-%EA%B4%80%ED%95%B4%EC%84%9C</link>
            <guid>https://velog.io/@jm_dae/CSS-notlast-child%EC%97%90-%EA%B4%80%ED%95%B4%EC%84%9C</guid>
            <pubDate>Mon, 03 Jun 2024 00:22:22 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/jm_dae/post/cd40aab6-c5f9-4758-ace3-561512e8b069/image.png" alt=""></p>
<p>React를 배우는 중에 :not(:last-child)구문을 만나게 되었다. 처음봤기때문에 바로 해석하기 쉽지 않았다. 
하지만 코드는 읽고 해석할 수 있게 쓰여졌기때문에 찾아보고 해석하면 금방 이해할 수 있었다.
:not()은 특정 조건을 제외하라는 말이고 :last-child는 부모 요소의 마지막 자식을 의미한다. 그러면 :not(:last-child)은 부모 요소이 마지막 자식을 제외하고 요소를 적용하라는 말이다.
즉,마지막 요소를 제외하고 margin-bottom을 16px로 하라는 소리다. 
프로그래밍 언어는 처음보는 언어가 있을 수 있다. 그럴때마다 당황하지 않고 찾아보면서 공부하는 자세가 중요한 것 같다. 이 방대한 지식을 다 외우고 있을 수 없기때문이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[응용된 삼항연산자(삼항연산자 안에 삼항연산자 및 삼항연산자와 객체 전개 구문)]]></title>
            <link>https://velog.io/@jm_dae/%EC%9D%91%EC%9A%A9%EB%90%9C-%EC%82%BC%ED%95%AD%EC%97%B0%EC%82%B0%EC%9E%90%EC%82%BC%ED%95%AD%EC%97%B0%EC%82%B0%EC%9E%90-%EC%95%88%EC%97%90-%EC%82%BC%ED%95%AD%EC%97%B0%EC%82%B0%EC%9E%90-%EB%B0%8F-%EC%82%BC%ED%95%AD%EC%97%B0%EC%82%B0%EC%9E%90%EC%99%80-%EA%B0%9D%EC%B2%B4-%EC%A0%84%EA%B0%9C-%EA%B5%AC%EB%AC%B8</link>
            <guid>https://velog.io/@jm_dae/%EC%9D%91%EC%9A%A9%EB%90%9C-%EC%82%BC%ED%95%AD%EC%97%B0%EC%82%B0%EC%9E%90%EC%82%BC%ED%95%AD%EC%97%B0%EC%82%B0%EC%9E%90-%EC%95%88%EC%97%90-%EC%82%BC%ED%95%AD%EC%97%B0%EC%82%B0%EC%9E%90-%EB%B0%8F-%EC%82%BC%ED%95%AD%EC%97%B0%EC%82%B0%EC%9E%90%EC%99%80-%EA%B0%9D%EC%B2%B4-%EC%A0%84%EA%B0%9C-%EA%B5%AC%EB%AC%B8</guid>
            <pubDate>Fri, 31 May 2024 06:03:54 GMT</pubDate>
            <description><![CDATA[<ol>
<li>삼항연산자 안에 삼항연산자</li>
</ol>
<p>className = {this.state.clicked ? (this.state.validate ? &#39;success&#39; : &#39;failure&#39;) : &quot;&quot; }</p>
<p>위와 같은 문장이 있었다. 이런 문장을 처음봐서 그런지 해석하는 데 시간이 걸렸다. 
이제는 한번 해석해봐서 그런지 어떤 의미로 쓴지 수월하게 이해할 수 있었다. 
먼저 this.state.clicked이 true이면 (this.state.validate ? &#39;success&#39; : &#39;failure&#39;)을 해석하고 false면 &quot;&quot; 빈 문자열을 출력하라는 의미였다. 
그 다음 this.state.clicked가 true면 (this.state.validate ? &#39;success&#39; : &#39;failure&#39;)로 들어가서 해석해야한다. 여기서 this.state.validate 가 true이면 &#39;success&#39;를 출력하고 false이면 &#39;failure&#39;을 출력한다는 의미였다. 
즉, this.state.clicked -&gt; true -&gt; this.state.validate -&gt; true -&gt; &#39;success&#39;
this. state.clicked -&gt; true -&gt; this.state.validate -&gt; false -&gt; &#39;faliure&#39;라고 할 수 있다. 
this.state.clicked -&gt; false -&gt; &quot;&quot;라고 해석할 수 있다.</p>
<ol start="2">
<li>삼항연산자와 객체전개구문</li>
</ol>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/6f916e37-fae9-4e0c-9be6-30a3336b3285/image.png" alt=""></p>
<p>todo.id === id ? {...todo, checked : !todo.checked} : todo</p>
<p>위의 문장을 보면 todo.id 와 id가 같으면 {...todo, checked : !todo.checked} 다르면 todo를 그대로 호출한다는 얘기이다. 
여기까지는 삼항 연산자니까 잘 알았는데 이제 {...todo, checked : !todo.checked}가 문제였다. 먼저 ...todo는 todo의 모든 속성을 새로운 객체로 풀어서 복사한다는 의미이다.그리고 checked : !todo.checked를 해석해보면 todo의 checked 속성을 : !todo.checked지금 가지고 있는 checked속성을 반대 값으로 저장하자는 얘기이다.
즉, todo.id가 id와 같다면 checked 속성을 반대로 저장하라는 소리고 todo.id가 id와 다르면 기존에 있던 todo를 그대로 호출하라는 소리이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React parsing error]]></title>
            <link>https://velog.io/@jm_dae/React-parsing-error</link>
            <guid>https://velog.io/@jm_dae/React-parsing-error</guid>
            <pubDate>Fri, 31 May 2024 05:01:50 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/jm_dae/post/92fe632c-fc29-43d5-ac19-4331868f1c87/image.png" alt=""></p>
<p>음 이거는 별거 아니지만 위의 사진처럼 parsing error가 뜨는 것을 보았다. 
오류를 자세히 보면 &#39;SubApp&#39; has already been declared.라고 떠있는 것을 볼 수 있다. 이 문장의 뜻만 봐도 이미 선언되었다는 것을 알 수 있었다. 
&#39;응? 어디서 내가 선언을 했나?&#39; 하고 아래로 내려가서 &#39;export default한 부분에서 두번 선언을 했나?&#39; 하고 봤지만 정확하게 한번만 export default SubApp;으로 선언된 것을 확인했다. 그럼 왜그러지? 하고 위에서 부터 천천히 봤는데 import SubApp from &#39;../ex34_delete/SubApp&#39;;으로 엉뚱한 SubApp이 선언된 것을 확인했다. 하지만 vsCode는 이걸 잡아주지 못했다. 그래서 확인하는 데 시간이 걸렸던 것 같다.
이런 오류를 처음보면 왜 그런지 모르지만 찾아보고 나면 다음부터는 쉽게 보이기때문에 공부를 해야한다는 것을 깨달았다. 그래서 경험이 필요한 것 같다. 오류를 보면 감사해야할 것 같다. 내가 알아가고 배울 수 있는 시간이기 때문이다.ㅎㅎ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JPA에서 on절을 사용하지 않아도 되는 이유]]></title>
            <link>https://velog.io/@jm_dae/JPA%EC%97%90%EC%84%9C-on%EC%A0%88%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EC%A7%80-%EC%95%8A%EC%95%84%EB%8F%84-%EB%90%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</link>
            <guid>https://velog.io/@jm_dae/JPA%EC%97%90%EC%84%9C-on%EC%A0%88%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EC%A7%80-%EC%95%8A%EC%95%84%EB%8F%84-%EB%90%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</guid>
            <pubDate>Fri, 31 May 2024 00:31:51 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/jm_dae/post/8e8519f6-1803-4df7-a198-7e4b92e5ae43/image.png" alt=""></p>
<p>먼저 위의 문장을 보면 boardJPQLQuery.leftJoin(reply).on(reply.board.eq(board));를 보면 on절을 명시해줘도 문제가 없었다. 
하지만 밑에 문장 boardJPQLQuery.leftJoin(board.member, member);에서 원래는 on절을 사용해서 board와 member를 연결해줬는데 이렇게 하면 오류가 났다.
이유는 board.member, member로 엔티티 관계가 이미 정의되어 있어 있어서 암시적으로 조인 조건을 처리할 수 있기 때문에 on 절이 필요하지 않습니다.
반면 위에 boardJPQLQuery.leftJoin(reply)처럼 엔티티 관계가 정의가 되어있지 않는 경우에는 on절을 명시적으로 사용해줘야한다.</p>
<p>JPA를 사용할때 내부적으로 어떻게 돌아가는지 확인하기 쉽지않아서 관계를 설정하는 데 있어서 사용하기 어려웠지만 유동적으로 변화에 빠르게 대응할 수 있다는 큰 장점이 있기 때문에 유용하다는 생각이 들었다. 어떤 것도 장점만 있지않고 어떤 것도 단점만 있지 않다고 생각합니다. 자신의 상황에 맞게 유동적으로 필요한 기술을 사용하는 것이 중요한 것 같습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[spring boot) static에서 static에 있는 파일을 참조할 때]]></title>
            <link>https://velog.io/@jm_dae/spring-boot-static%EC%97%90%EC%84%9C-static%EC%97%90-%EC%9E%88%EB%8A%94-%ED%8C%8C%EC%9D%BC%EC%9D%84-%EC%B0%B8%EC%A1%B0%ED%95%A0-%EB%95%8C</link>
            <guid>https://velog.io/@jm_dae/spring-boot-static%EC%97%90%EC%84%9C-static%EC%97%90-%EC%9E%88%EB%8A%94-%ED%8C%8C%EC%9D%BC%EC%9D%84-%EC%B0%B8%EC%A1%B0%ED%95%A0-%EB%95%8C</guid>
            <pubDate>Thu, 30 May 2024 00:27:56 GMT</pubDate>
            <description><![CDATA[<p>spring boot를 활용해서 프로젝트를 진행하면 많은 것을 알게 되었다. 사소한 것에서 잘 안되는 때도 있었고 정말 복잡한 문제도 있었다. 그 중에서 이번에 만나 오류는 제 생각에는 간단한 오류였다. 하지만 구글에 찾아봐도 잘 나와있지 않아서 수정하는데 생각보다 시간이 걸렸다.</p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/bdf8ae1f-e96b-49b3-96e5-7088dc89d67a/image.png" alt=""></p>
<p>다음 사진을 보면 static 폴더 안에 assets(이미지 저장하는 폴더), css, js등의 폴더가 들어있다. 저는 이 assets 폴더 안 main에 있는 banner들을 css 폴더 안에 main에서 참조하고 싶었다. 처음에는 원래 하던거 처럼 templates에서 static을 참조하듯이 절대결로로 해줬는데 작동하지 않았다. 밑에 사진은 templates에서 static을 절대경로로 참조한 예이다.</p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/01c3cc38-af10-4a58-a863-efa7a23a0f37/image.png" alt=""></p>
<p>그래서 찾아보고 이것 저것 해보았더니 결과는 static에서 static안에 있는 파일을 참조할 때는 상대경로로 불러와야한다는 것이였다. 
즉, templates에서 static을 참조할 때는 절대경로로 하면되고 static에서 static안에 있는 것을 참조할 때는 상대경로로 지정해줘야한다. 
맨 위에 사진 보시면 url(&quot;&quot;)와 url()의 차이는 없는 것으로 보여집니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[spring boot 500번 에러...]]></title>
            <link>https://velog.io/@jm_dae/spring-boot-500%EB%B2%88-%EC%97%90%EB%9F%AC</link>
            <guid>https://velog.io/@jm_dae/spring-boot-500%EB%B2%88-%EC%97%90%EB%9F%AC</guid>
            <pubDate>Wed, 29 May 2024 00:27:10 GMT</pubDate>
            <description><![CDATA[<p>앞에서 마주한 400번 에러를 처리하니까 500번에러는 마주했다.ㅎㅎㅎ
어쩔 수 없지... 천천히 처리하는 수 밖에...</p>
<blockquote>
<p>GET <a href="http://localhost:12000/replies/list/440?page=1&amp;size=10">http://localhost:12000/replies/list/440?page=1&amp;size=10</a> 500 (Internal Server Error)</p>
</blockquote>
<p>제가 마주한 오류는 위와 같은 500번 에러였다. 찾아보니까 500번 에러는 서버에서 데이터를 처리하는 과정에서 문제가 있는 것이였다. 
클라이언트에서는 파라미터를 잘 보냈는데 서버에서 처리하는 과정에서 문제가 있는 것이라 생각했다. 어쩔 수 없이 서버 쪽에서 log를 다 찍어보면서 확인하는 수 밖에 없었다. 
일단 먼저 서버측 문제니까 intellij로 가봤다.</p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/2d3f0b10-6767-416a-8c37-392d3a70d63e/image.png" alt=""></p>
<p>서버에 찍힌 오류문장을 천천히 보니까 getMemberId가 두번이나 호출되서 나오는 것을 확인할 수 있었다. domain이나 DTO에서 memberId를 두번이나 가져오려고 해서 생긴 것이라고 생각했다. 
확인 결과 ReplyDTO 부분에 memberid가 중복되어서 넘어오는 것을 확인하고 ReplyDTO를 수정해줬더니 오류가 해결되었다. </p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/d75fc700-bd3b-41b6-b8d1-d8ea21b09f3e/image.png" alt=""></p>
<p>JPA를 사용하면 변화에 대처하기 좋고 유연하게 데이터베이스를 설계할 수 있지만 연관관계에 있어서 설계할때 주의를 해야한다는 것을 알게 되었다. 아니면 지금처럼 데이터가 중복되어서 넘어오는 경우가 있을 수 있다는 것을 깨달았다. 각자가 가지고 있는 오류가 다르므로 일단 500번 에러라는 것을 확인했으면 서버쪽을 확인해보자.서버쪽에 찍힌 로그를 확인하고 로그가 안 찍혔으면 로그를 하나하나 찍어보면서 추적하는 것이 중요할 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[spring boot 400번 에러...]]></title>
            <link>https://velog.io/@jm_dae/spring-boot-400%EB%B2%88-%EC%97%90%EB%9F%AC</link>
            <guid>https://velog.io/@jm_dae/spring-boot-400%EB%B2%88-%EC%97%90%EB%9F%AC</guid>
            <pubDate>Mon, 27 May 2024 00:22:47 GMT</pubDate>
            <description><![CDATA[<p>프로젝트를 진행하면서 에러에 대해서 너무 많이 마주쳤다. 그 중에서 400번 에러에 대해서 제가 해결한 방법에 대해서 적어보려고 합니다. </p>
<blockquote>
<p>GET <a href="http://localhost:12000/replies/list/undefined?page=1&amp;size=10">http://localhost:12000/replies/list/undefined?page=1&amp;size=10</a> 400 (Bad Request)</p>
</blockquote>
<p>콘솔을 확인했을 때 위와 같은 오류 메세지를 마주쳤다. 일단 먼저 결론부터 말하자면 400오류는 클라이언트에서 서버로 정보를 보낼 때 문제가 있다는 뜻입니다. 즉 클라이언트에서 request를 보낼때 매개변수에 문제가 있을 가능성이 있다고 판단했습니다. 그래서 오류 메세지를 천천히 보니까 <a href="https://localhost:12000/replies/list/undefined">https://localhost:12000/replies/list/undefined</a>? 라고 나오는 것을 볼 수 있습니다. 클라이언트에서 replies/list 로 get요청을 보내는 과정에서 undefined로 매개변수가 잘 안들어 간 것 같다는 생각을 했습니다. 그래서 request를 보내는 front단을 확인해보았습니다.</p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/b28d6554-0170-4501-9a73-b3fde06eab59/image.png" alt=""></p>
<p>역시나 request를 보낼 때 정의되지 않은 매개변수가 들어간 것을 볼 수 있었습니다. controller에서 정의한 변수값과 다른 이름으로 선언되어있었습니다. 그래서 그 부분을 수정하고 나니까 화면이 제대로 작동하는 것을 확인할 수 있었습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[main에 잘 못 올렸다고?]]></title>
            <link>https://velog.io/@jm_dae/main%EC%97%90-%EC%9E%98-%EB%AA%BB-%EC%98%AC%EB%A0%B8%EB%8B%A4%EA%B3%A0</link>
            <guid>https://velog.io/@jm_dae/main%EC%97%90-%EC%9E%98-%EB%AA%BB-%EC%98%AC%EB%A0%B8%EB%8B%A4%EA%B3%A0</guid>
            <pubDate>Sun, 12 May 2024 07:09:18 GMT</pubDate>
            <description><![CDATA[<p>이번에 spring boot 수업이 끝나고 또 한번 프로젝트를 진행했다. 이번에 우리 팀이 하게 되는 작업은 반려동물에 대한 정보를 주고 받는 커뮤니트 홈페이지를 만들기로 했다. 제가 맡은 파트는 카카오맵 API를 받아서 정보를 뿌려주는 작업과 유기동물 API를 불러와서 화면에 보여주는 작업을 진행했다. 
항상 그랬지만 프로젝트하면서 배우는게 참 많았다. 모르는 부분을 혼자 찾아보기도 하고 그래도 잘 안되면 팀원들한테 물어보기도 하면서 너무 많이 배웠다. 그 중에 하나 배운 것이 프로젝트 진행 중에 gitHub main branch에 잘 못 올렸을 때 대처방법이다. 
보통 main branch를 하나 만들고 그 밑에 frontend, backend 브랜치를 만들어서 frontend와 backend 브랜치에 각각 작업한 기능들을 합치고 최종적으로 main에 frontend와 backend를 합치는 방법을 구사한다.
그래서 main 브랜치 영역은 프로젝트의 최종 본이라고 보면된다. 
하지만 프로젝트를 하다보면 실수로  main에 올리는 경우가 있다. 원래는 proteced를 해서 main을 막아놓고 default 브랜치를 backend나 frontend로 해서 이런 사고를 미연에 방지할 수 있다. 저희는 이렇게 될거라는 생각을 못 한 것도 있고 잘 알지 못 했어서 main에 못 올리게하는 장치를 걸지 못 했다.
만약 main에 프로젝트를 실수로 올렸다면 sourcetree를 활용해서 되돌릴 수 있다. sourcetree가 아니여도 할 수 있겠지만 sourcetree는 모든 브랜치들을 직관적으로 볼 수 있고 사용하기 편하다는 장점이 있다. 이 작업을 진행하기 전에 main에 올린 브랜치를 백업해두거나 모르겠으면 파일 전체를 백업해두는 것을 추천한다. 
먼저 main에 잘 못 올렸다면 sourcetree로 가서 main으로 체크아웃을 진행한다. main 브랜치로 체크아웃이 되었다면 되돌리고 싶은 시점을 찾는다. </p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/0a81e20f-0d3f-4800-a140-c57097d10fe3/image.png" alt=""></p>
<p>위에 그림 처럼 되돌리고 싶은 위치에 우클릭을 해서 &#39;이 커밋까지 현재 브랜치를 초기화&#39;를 클릭해준다. 그리고 HARD를 체크해서 확인을 눌러주면 main 브랜치가 해당 위치로 돌아간다. 여기서 끝이 아니다.
이렇게 하면 pull에 엄청 많은 숫자의 pull이 생성될 것이다. 이건 절대 받으면 안된다. 그러면 다시 main으로 돌아가는 꼴이 된다. 왜냐하면 지금은 로컬 main을 초기화 한 것이지 원격까지 초기화 한 것이 아니다. 따라서 해당 파일에서 cmd 창을 열어서 &#39;git push -f&#39;를 입력해주면 원격으로 로컬에 있는 main 브랜치가 올라가게 된다. -f는 강제로 올린다는 말이다. 
아까 맨 처음에 main으로 체크아웃을 했기때문에 따로 체크아웃을 해줄 필요가 없다. </p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/b6514b2a-efa7-403a-a01d-431f005bf50c/image.png" alt=""></p>
<p>위에 그림을 보면 main -&gt; main (forced update)로 실행된 것을 볼 수 있다. 
이렇게 main을 올리더라도 해결방법이 있으니 당황하지 않아도 된다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[executeQuery, executeUpdate 뭐가 달라]]></title>
            <link>https://velog.io/@jm_dae/executeQuery-executeUpdate-%EB%AD%90%EA%B0%80-%EB%8B%AC%EB%9D%BC</link>
            <guid>https://velog.io/@jm_dae/executeQuery-executeUpdate-%EB%AD%90%EA%B0%80-%EB%8B%AC%EB%9D%BC</guid>
            <pubDate>Mon, 15 Apr 2024 00:24:57 GMT</pubDate>
            <description><![CDATA[<p>DB와 연결하기 위해 DAO를 작성하고 있었다. sql문을 작성해서 executeQuery나 executeUpdate로 DB에 주입하는 것은 알았지만 둘의 정확한 차이를 알지 못 했다. 왜 executeQuery를 쓸 때가 있고 executeUpdate를 쓸 때가 있는지 몰라서 공부해봤다.
executeQuery와 executeUpdate는 똑같이 sql문을 DB에 주입하는 것은 맞지만 사용에 있어서 차이가 있었다.
executeQuery는 select문 처럼 DB에 있는 데이터를 꺼내올 때 사용하는 것이다.
executeUpdate는 DB에 있는 데이터를 조작할 때 사용하는 메서드라는 것을 알았다. 여기에 해당하는 대표적인 sql문은 insert, delete, update등이 있다.
그러니까 executeUpdate는 Update가 있으니까 뭔가 데이터를 업데이트할 때 사용한다고 생각하면 구분하기 편할 것 같다. execute는 실행하다는 뜻이 있으니 &#39;업데이트를 실행한다.&#39;라고 이해해봐야겠다.
executeQuery는 단순히 &#39;쿼리를 실행한다.&#39;라고 이해하려고 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[session, cookie이해하고 싶다]]></title>
            <link>https://velog.io/@jm_dae/session-cookie%EC%9D%B4%ED%95%B4%ED%95%98%EA%B3%A0-%EC%8B%B6%EB%8B%A4</link>
            <guid>https://velog.io/@jm_dae/session-cookie%EC%9D%B4%ED%95%B4%ED%95%98%EA%B3%A0-%EC%8B%B6%EB%8B%A4</guid>
            <pubDate>Sun, 14 Apr 2024 07:38:54 GMT</pubDate>
            <description><![CDATA[<p>자바를 활용해서 웹이랑 통신하기 위해서는 session과 cookie라는 저장공간에 대한 이해가 필요해보였다. 
먼저 session은 서버에 저장하는 공간이다. 서버에 저장하므로 주로 ID, 비밀번호와 같은 민감한 정보를 저장한다. 저장은 session에 하고 브라우저한테는 JSESSIONID를 부여해서 사용자를 구별할 수 있는 키값을 부여한다. JSESSIONID는 처음에 접속할 때 한번 부여되며 서버공간에서는 일정시간이 지나면 session 공간을 소멸시킨다. 왜냐하면 너무 많은 사용자가 session공간을 가지고 있으면 메모리에 부하가 오기 때문이다.
처음에 부여하는 JSESSIONID 키값을 활용해서 cookie를 저장하는 것이다. 한마디로 &#39;나 이런 사람(JSESSIONID)인데 여기에(cookie에 담길 정보) 접속할거야&#39;라는 request를 보내면 서버는 사용자를 확인하고 저장할 cookie를 담아서 response를 보낸다. 그러면 브라우저 상에 cookie가 저장되는 패턴이다. 처음 접속할 때 JSESSIONID값을 부여받고 다음부터는 cookie값만 저장하게 된다. 한마디로 cookie는 브라우저에 저장하는 공간이다. 사용자가 어떤 활동하는 지를 브라우저에 저장한다.
예를 들면 요즘은 이 cookie를 활용해서 사용자가 접속한 사이트를 분석해서 사용자에게 적합한 광고를 띄워주는 것으로 활용한다. 사실 cookie로 가장 많이 활용하는 것은 장바구니 기능이다. 해당 사용자가 어떤 상품을 장바구니에 담았는지를 저장한다.</p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/4ba9ca25-18eb-40b6-8d0a-4cbb760797b4/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[sendRedirect와 RequestDispatcher 차이가 뭐야]]></title>
            <link>https://velog.io/@jm_dae/sendRedirect%EC%99%80-RequestDispatcher-%EC%B0%A8%EC%9D%B4%EA%B0%80-%EB%AD%90%EC%95%BC</link>
            <guid>https://velog.io/@jm_dae/sendRedirect%EC%99%80-RequestDispatcher-%EC%B0%A8%EC%9D%B4%EA%B0%80-%EB%AD%90%EC%95%BC</guid>
            <pubDate>Thu, 11 Apr 2024 13:19:50 GMT</pubDate>
            <description><![CDATA[<p>저는 jsp를 통해서 브라우저에 화면을 띄우는 과정에서 sendRedirect와 RequestDispatcher가 똑같이 브라우저에 jsp를 띄우는 거 아니야? 뭐가 다른거야? 배우기는 했지만 가지고 있는 지식이 많지 않아서 확실하게 이해가 되지 않았다. 그래서 복습하는 과정에서 이해해보려고 노력했다.
먼저 sendRedirect는 request정보를 완전히 없애서 새로운 url로 할당한다는 것이였습니다. 한마디로 표현하자면 데이터를 갖지 않고 브라우저에 출력한다는 뜻입니다. 
그렇다면 RequestDispatcher는 뭘까요. requestDispatcher는 이름에도 있듯이 request정보를 가지고 url을 브라우저에 띄우는 것입니다. 한마디로 데이터를 가지고 브라우저에 출력하는 것을 뜻합니다. 
이렇게 보시다시피 둘의 차이점은 브라우저가 요청한 request정보를 가지고 url를 출력하냐 그렇지 않냐의 차이입니다.(이름으로 보면 request가 있고 없고로 구분하면 되겠죠?ㅎㅎ)
여기서 또 궁금했던 것이 그럼 forward방식과 include방식이 뭔차이인가 입니다. 
일단 forward방식과 include방식은 RequestDispatcher의 2가지 방법이라고 할 수 있습니다.
RequestDispatcher의 첫번째 forward방식은 a.jsp에서 b.jsp로 제어권을 넘기고 b.jsp로 브라우저에 출력하는 것입니다. 한마디로 b.jsp내용만 브라우저에 출력하는 것입니다.
RequestDispatcher의 두번째 방식은 include방식인데 이 방식은 a.jsp에서 제어권을 b.jsp로 넘긴다음 b.jsp의 내용을 가져와서 다시 a.jsp 내용을 브라우저에 출력하는 것이라고 생각하면 됩니다. 한마디로 b.jsp내용을 가져와서 a.jsp에서 같이 브라우저로 전송한다고 생각하면 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/c9e86fff-2c0c-4c6a-88a1-60e795decb02/image.png" alt=""></p>
<p>그래서 sendRedirect와 RequestDispatcher가 어디서 사용되는데?
RequestDispatcher는 request정보를 가지고 있기 때문에 보통 controller에서 doGet 메서드에서 많이 활용된다. 왜냐하면 브라우저에서 요청한 request정보를 가지고 다시 화면에 출력해줘야하기 때문이다.
controller에서 doPost 메서드에서는 주로 정보를 저장하고 처리하는 과정을 진행하므로 정보를 다 처리하고 나서 sendRedirect를 사용해서 브라우저에 새로운 화면을 띄운다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[<요즘 개발자> 독서 회고]]></title>
            <link>https://velog.io/@jm_dae/%EC%9A%94%EC%A6%98-%EA%B0%9C%EB%B0%9C%EC%9E%90</link>
            <guid>https://velog.io/@jm_dae/%EC%9A%94%EC%A6%98-%EA%B0%9C%EB%B0%9C%EC%9E%90</guid>
            <pubDate>Wed, 03 Apr 2024 14:30:02 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/jm_dae/post/e23fc7a7-282e-49fd-8deb-7750399c1082/image.jpg" alt=""></p>
<p>저는 공부할 때 뭔가 내가 공부하는 부분이 눈에 보이면 공부하기 훨씬 쉽고 생각하기 편할 것 같다는 생각에 건축공학과를 전공으로 선택하게 되었는데 막상 가서 공부하니까 저와 굉장히 안 맞는 느낌이 팍팍 들었습니다.
여러가지 이유가 있지만 직접 공사현장에 나가봐야한다는 것인데 그 공사현장이 정해져있지 않고 계속 달라진다는 것이였습니다. 이렇게 되면 제 삶이 안정적이지 않을 것 같았습니다. 그래서 많이 고민하고 생각하면서 주변의 조언도 있었고 제가 찾아본 결과 개발자의 길을 가고 싶다는 생각을 했습니다. 졸업을 할 때 쯤에 우연히 좋은 기회를 갖게 되어서 지금 6개월 과정의 개발자 교육을 받고 있습니다. 지금은 약 4개월차이고 실질적으로는 3개월정도 교육을 받았습니다. 이렇게 3개월정도 교육을 받으면서 느낀 생각이 &#39;이 일은 내가 오래할 수 있겠다.&#39;, &#39;어렵지만 재밌다.&#39;, &#39;오래하고 싶다.&#39;</p>
<p>개발자를 하겠다고 마음을 먹고 나서 &#39;내가 갈 수 있는 길이 크게 뭐가 있지? 어떻게 학습을 해야하지? 어떤 방향으로 나아가야하지? 자격증은 필요한가? 남들은 이것저것 많이하는데 남들하는 것을 따라하는게 맞나? 지금 배우고 있는 것도 이해가 잘 안되고 어려운데 다른 공부를 하는게 맞나?&#39; 하는 고민들이 많았습니다. 남들을 따라하기에는 다들 공부하러온 신입개발자들이고 저는 그들을 보고 따라하는 것이 아니라 먼저 간 사람들의 말을 들어야한다고 생각했습니다. 그래서 교보문고에 가서 책을 찾아보니까 &lt;요즘 개발자&gt;라는 책이 눈에 들어왔습니다. &#39;이 책이다!&#39; 생각해서 바로 구매하고 읽기 시작했습니다. 확실히 먼저 길을 가본 사람들의 말을 들으니까 저의 앞으로의 방향이 좀 잡히는 것 같고 어떻게 공부를 해야하는 지 조금은 명확해진 느낌이였습니다. 이제는 흔들리지 않고 &quot;나다운&quot; 공부를 할 수 있을 것 같습니다. </p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/49407c95-f2f0-41ad-bdff-e825a2b28f24/image.jpg" alt=""></p>
<p>[What Makes a Great Software Engineer] 논문에 나오는 탁월한 엔지니어의 다섯 가지 주요 역량은 아래와 같다고 한다.</p>
<ol>
<li>Be a competent coder 좋은 코드를 만든다.</li>
<li>Maximize current value of your work 작업의 현재 가치를 극대화한다</li>
<li>Practice informed decision-making 데이터에 기반하여 의사 결정한다.</li>
<li>Enable others to make decisions efficiently 동료의 효과적인 의사 결정을 돕느다.</li>
<li>Continuously learn 꾸준히 학습한다.</li>
</ol>
<p>위의 다섯가지 역량을 다 갖추면 좋겠지만 실질적으로 한계가 있고 자기가 잘하는 것도 있을텐데 자기가 잘 할 수 있는 부분을 노력해서 브랜딩해야한고 했습니다.
제가 생각했을 때 위의 역량 중에서 제가 잘 할 수 있는 부분은 2. Maximize current value of your work 작업의 현재 가치를 극대화하고 4. Enable others to make decisions efficiently 동료의 효과적인 의사결정을 돕고 5. Continuously learn 꾸준히 학습한다는 역량이라고 생각한다.</p>
<p>먼저 2. 작업의 현재 가치를 극대화하는 역량은 제가 무언가를 할 때 나에게 필요한 것이 무엇인지 내가 배울 것은 무엇인지 생각하는 경향이 있습니다. project 기간에도 velog를 썼던 이유도 여기에 있습니다. 내가 몰랐던 부분이 계속 생기니까 이 부분에 대해서 정리하고 싶었고 기록해서 기억에 더 오래 남게 하고 싶었습니다. 그리고 현재 가치를 극대화시키기 위해서 책도 읽으면서 외부의 자극을 얻고 input만 하는 것이 아니라 output도 하려고 노력하고 있습니다. 
4. 동료의 효과적인 의사결정을 돕는 역량은 제가 잘하는 게 사람들과 화합하고 사람의 마음을 공감하고 이해하는 능력이라고 생각합니다. 저는 자기계발 책을 많이 읽으면서 사람의 마음을 이해하는 능력이 커졌다고 생각합니다. 어릴 때는 관계에 대해서 생각도 많아지고 해서 데일 카네기의 [인간관계론]이란 책도 읽으면서 관계에 대해서 고민도 많이 했던 것 같습니다. 사람이 살아가면서 사람과의 관계를 안 갖고 살아갈 수는 없다고 생각하는 입장이여서 그런지 사람과 관계를 맺는 것도 중요하다고 생각합니다. 이 세상에는 혼자할 수 있는 일은 없습니다. 크게 생각하면 자신의 소득활동도 다른 사람이 있기 때문에 가능한 것이라고 생각합니다. 혼자 살아간다면 소득활동따위는 필요하지가 않다고 생각합니다. 제가 이렇게 관계에 대해서 생각하는 게 많기 때문에 동료와 소통을 더 잘 하고 효과적인 의사결정을 할 수 있게 더 노력해보려고 합니다.
5. 꾸준히 학습하는 역량도 제가 이 개발자라는 직업을 선택한 것부터 꾸준히 할 수 있는 일이라고 생각해서 선택하게 되었습니다. 저는 뭔가를 꾸준히 하는 것을 잘 합니다. 아침밥도 맨날 사과, 닭가슴살, 오트밀을 먹고 출퇴근 길에는 책을 읽는 등 뭔가를 꾸준히 하는 것을 잘합니다. 이렇게 잘하는 이유도 제가 꾸준히 할 수 있겠다 생각되는 일만 하기 때문입니다. 누군가는 아침에 맨날 그렇게 먹는게 질리지 않냐고 물어보는데 저는 저렇게 먹는게 맛있고 저런 식단을 찾기까지 여러 시도를 많이 해봤습니다. 아침에 샐러드도 먹어보고 계란도 먹어보고 요거트도 먹어봤는데 꾸준히 먹을 수 없겠다는 생각이 들었습니다. 사과, 닭가슴살, 오트밀 먹는 것이 가장 간편하고 맛도 있었습니다. 이렇게 저는 꾸준히 하는 것에 자신있습니다. 
개발자에 관심을 가지게 되고 공부를 하면서 저랑 잘 맞을 것 같다는 생각이 들었습니다. 저는 뭔가 꾸준히 공부하고 성장하는 것을 좋아하는데 저의 이런 성격과 정말 잘 맞다고 생각했습니다. 단기간에 밤을 새워가면서 하루만 산다는 마음으로는 못하지만 계속 꾸준히 할 수는 있을 것 같았습니다. 그래서 저는 지금 주말에도 계속 조금이라도 공부하고 발전하지만 밤 새워서는 못 하고 있습니다. 항상 아침에 30분 일찍 와서 공부하고 끝나면 잠깐 운동한 다음에 집에서 다시 공부하는 생활을 하고 있습니다. 
<img src="https://velog.velcdn.com/images/jm_dae/post/af1a1068-4a6d-439a-87b0-e2970ebc23f3/image.jpg" alt="">
<img src="https://velog.velcdn.com/images/jm_dae/post/769b2b2b-5be4-4ad0-9e8d-73133d6aa179/image.jpg" alt=""></p>
<p>책에서 원하는 방향을 찾기 위해서 자신에게 강력한 욕구가 무엇인지 생각해보는 과정이 필요하다고 하면서 한국비폭력대화교육원에서 제공하는 욕구와 관련된 키워드를 제시해주었습니다.
저는 그 중에서 도전, 배움, 운동을 제가 생각하는 욕구 세 가지로 골랐습니다.
도전은 어떤 일을 하던지 한발짝 앞으로 나아가기 위해서는 필요하다고 생각합니다. 저는 지금까지 도전을 하는 삶을 살아왔다고 생각합니다. 저는 재수에 도전했고 편입에 도전했습니다. 저는 도전만 한 것이 아니라 정말 열심히 했습니다. 하지만 열심히만으로는 안되는 것을 깨달았고 방향을 잡고 가야한다고 생각했습니다. (그래서 지금 개발자의 길을 걷기위해서 방향을 잡으려고 이 책을 집어들었다.) 저는 노력의 에너지가 좋은 방향으로 가기 위해서 어려운 시험에 통과했다는 사람들의 책도 읽었고 실패를 돌아보면서 변화를 주었습니다. 지금도 개발자가 되기위해서 도전하고 있다고 생각합니다. 저도 도전을 할 때 안 가본 길이라 두렵고 망설여질 때가 있는데 그럴때마다 &#39;남들도 했는데&#39; 라는 생각이나 &#39;당연히 처음에는 낯설고 어색하지&#39; 라는 생각으로 일단 해보는 경향이 있는 것 같습니다. 이런 저 자신을 봤을 때 도전을 하는 자세가 저를 더 발전시키고 있다고 생각합니다. 책에서 이런 글을 봤습니다. &quot;꿈이 크면 깨져도 조각이 크다&quot; 라는 글을 봤는데 저한테 실패해도 되니까 계속 높은 곳을 바라보게 하는 글이라는 생각이 들었습니다.<br>다음은 배움인데 항상 배우려고 노력하는 자세가 필요하다고 생각합니다. 그래서 계속 책을 읽는 것도 있습니다. 저는 개발자로 들어선 순간 계속 배움의 연속이겠다고 생각했습니다. IT분야는 변화가 빠른 곳이고 방대한 내용들이 있어서 계속해서 배우고 이해해나가야한다고 생각했습니다. 
마지막으로 운동인데 제가 자기계발 책도 많이 읽고 편입할 때는 공부에 관련된 책도 많이 읽었는데 거의 빼놓지 않고 하는 말이 운동이였습니다. 그만큼 운동이 중요하니까 계속해서 책에서 강조한다고 생각합니다. 저도 많이 느끼는 것이 운동을 하면 실제로 머리가 맑아지는 느낌을 느꼈습니다. 실제로 몸과 뇌는 연결되어있어서 몸을 움직이면 뇌도 같이 활성화되어서 집중력도 올라간다고 합니다. 너무 어려운 내용을 배웠을 때 잠깐 운동하고 와서 내용을 다시보면 이해될 때도 있고 집중이 잘되는 느낌을 받았습니다. 공부를 하면 운동하는 시간을 아까워하는데 운동을 해보시면 확실히 다르다는 것을 느끼실겁니다. 저는 또 꾸준히 오래 배우고 노력할 거기때문에 운동을 통해서 지치지 않는 체력을 만들려고 합니다. 바쁘더라도 꾸준히 운동하는 습관을 갖는 것이 좋은 것 같습니다. 운동하는 시간말고 유튜브보고 인스타그램보는 시간을 줄이는 것이 더 현명한 선택이라고 생각합니다. 
<img src="https://velog.velcdn.com/images/jm_dae/post/eda4c21d-0a60-42af-ba75-349ed671e2bd/image.jpg" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/2a81a184-6b6e-4bd9-bce7-4e7388ce5783/image.jpg" alt=""></p>
<p>글을 쓰다보니까 엄청 길게 썼는데 이 책에 마지막에서는 이렇게 나와있습니다.&quot;처음부터 위대한 일을 해내려고 애쓰면 쉽게 넘어집니다. 큰 성공을 만들어내려면 작은 성고에 먼저 집중해야 합니다.&quot;, &quot;훌륭한 개발자가 되는 길은 짧은 스프린트가 아니라 장기적인 마라톤과 같습니다.&quot;, &quot;목적지가 아니라 여정임을 기억하세요&quot;.
뭔가 빨리 이루려고 하지말고 한걸음 한걸음 내딛는 발걸음을 즐기면서 가는 것이 중요하다는 생각이 들었습니다. 지금 배우고 알아가는 과정이 재밌어서 앞으로도 조급해하지 않고 천천히 배우면서 성장하고 싶습니다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JSTL 아래와 같은 오류가 뜬다면
Error: 절대 URI인 [http://java.sun.com/jsp/jstl/core]을(를), web.xml 또는 이 애플리케이션과 함께 배치된 JAR 파일 내에서 찾을 수 없습니다.]]></title>
            <link>https://velog.io/@jm_dae/JSTL-%EC%95%84%EB%9E%98%EC%99%80-%EA%B0%99%EC%9D%80-%EC%98%A4%EB%A5%98%EA%B0%80-%EB%9C%AC%EB%8B%A4%EB%A9%B4Error-%EC%A0%88%EB%8C%80-URI%EC%9D%B8-httpjava.sun.comjspjstlcore%EC%9D%84%EB%A5%BC-web.xml-%EB%98%90%EB%8A%94-%EC%9D%B4-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98%EA%B3%BC-%ED%95%A8%EA%BB%98-%EB%B0%B0%EC%B9%98%EB%90%9C-JAR-%ED%8C%8C%EC%9D%BC-%EB%82%B4%EC%97%90%EC%84%9C-%EC%B0%BE%EC%9D%84-%EC%88%98-%EC%97%86%EC%8A%B5%EB%8B%88%EB%8B%A4</link>
            <guid>https://velog.io/@jm_dae/JSTL-%EC%95%84%EB%9E%98%EC%99%80-%EA%B0%99%EC%9D%80-%EC%98%A4%EB%A5%98%EA%B0%80-%EB%9C%AC%EB%8B%A4%EB%A9%B4Error-%EC%A0%88%EB%8C%80-URI%EC%9D%B8-httpjava.sun.comjspjstlcore%EC%9D%84%EB%A5%BC-web.xml-%EB%98%90%EB%8A%94-%EC%9D%B4-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98%EA%B3%BC-%ED%95%A8%EA%BB%98-%EB%B0%B0%EC%B9%98%EB%90%9C-JAR-%ED%8C%8C%EC%9D%BC-%EB%82%B4%EC%97%90%EC%84%9C-%EC%B0%BE%EC%9D%84-%EC%88%98-%EC%97%86%EC%8A%B5%EB%8B%88%EB%8B%A4</guid>
            <pubDate>Tue, 02 Apr 2024 14:36:55 GMT</pubDate>
            <description><![CDATA[<p>JSTL을 활용해서 데이터를 불러올 때 아래와 같은 오류가 뜬다면 jstl파일의 위치를 확인해야한다.</p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/1dbbfa90-80d6-4bcb-8533-6791aa547974/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/8691f617-c4c4-4f2f-a1cc-4a5ef3faadb2/image.png" alt=""></p>
<p>저는 WEB-INF파일 안에 lib에 jstl을 넣었는데 제대로 작동을 하지 않았다. 분명 맞게 넣었는데 이상했다. 저와 같은 고민을 하시는 분은 밑에를 따라해보시기바랍니다.</p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/195089ff-ae34-4031-8d6f-f7de6782541c/image.png" alt=""></p>
<p>일단 maven repository에 가서 jstl을 검색해서 jar파일이 있는 것을 다운 받는다.</p>
<p>jstl.jar파일을 직접 tomcat안에 있는 lib에 넣는 작업을 진행한다. tomcat안에 lib파일에 직접 집어넣으니까 바로 실행이 잘되는 것을 확인할 수 있었다.
<img src="https://velog.velcdn.com/images/jm_dae/post/85937278-4228-412d-8d2a-88611f8dcf53/image.png" alt=""></p>
<p>정말 알고나면 별거 아닌데 알기 전까지는 괴롭고 힘들다. 오류가 났을 때는 침착하게 오류코드를 확인하고 오류코드에 대한 확신이 없으면 구글링해서 나보다 앞서간 사람들의 조언을 들어보자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[tomcat을 사용 중에 아래와 같은 오류를 만난다면...
could not publish server configuration for tomcat v9.0 server at localhost.]]></title>
            <link>https://velog.io/@jm_dae/tomcat%EC%9D%84-%EC%82%AC%EC%9A%A9-%EC%A4%91%EC%97%90-%EC%95%84%EB%9E%98%EC%99%80-%EA%B0%99%EC%9D%80-%EC%98%A4%EB%A5%98%EB%A5%BC-%EB%A7%8C%EB%82%9C%EB%8B%A4%EB%A9%B4...could-not-publish-server-configuration-for-tomcat-v9.0-server-at-localhost</link>
            <guid>https://velog.io/@jm_dae/tomcat%EC%9D%84-%EC%82%AC%EC%9A%A9-%EC%A4%91%EC%97%90-%EC%95%84%EB%9E%98%EC%99%80-%EA%B0%99%EC%9D%80-%EC%98%A4%EB%A5%98%EB%A5%BC-%EB%A7%8C%EB%82%9C%EB%8B%A4%EB%A9%B4...could-not-publish-server-configuration-for-tomcat-v9.0-server-at-localhost</guid>
            <pubDate>Mon, 01 Apr 2024 14:02:41 GMT</pubDate>
            <description><![CDATA[<p>제목에 보이는 오류를 만났을 때 직감적으로 전에 project를 실행한 것이 아직 tomcat에 남아 있다는 것을 알 수 있었다. 그래서 아래 그림에서 와 같이 Tomcat에 걸려있는 project를 제거했다.
<img src="https://velog.velcdn.com/images/jm_dae/post/2a5193c0-d7cd-4ba1-87d4-e94fde039bff/image.png" alt=""></p>
<p>하지만 제거했는데도 불구하고 같은 오류가 나왔다. 
그래서 찾아본 결과 Web Modules에는 아직 전에 했던 project가 걸려있는 것을 알 수 있었다.
<img src="https://velog.velcdn.com/images/jm_dae/post/f6db0085-cbfe-46c9-a2eb-e729affff14f/image.png" alt="">
바로 위와 같이 tomcat에 들어가서 Modules 탭을 확인하고 전에 사용한 project가 있는면 선택하고 remove해줘야 한다. 참 알고나면 쉬운데 모르는 오류를 만나면 당황스럽고 시간을 많이 잡아먹는다. 이런 과정도 공부라고 생각하고 다음에 만나면 빠르게 해보려고 노력해야겠다. 문제를 만나면 배우려고 노력해야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[git과 sourcetree, eclipse 연동 문제...]]></title>
            <link>https://velog.io/@jm_dae/git%EA%B3%BC-sourcetree-eclipse-%EC%97%B0%EB%8F%99-%EB%AC%B8%EC%A0%9C</link>
            <guid>https://velog.io/@jm_dae/git%EA%B3%BC-sourcetree-eclipse-%EC%97%B0%EB%8F%99-%EB%AC%B8%EC%A0%9C</guid>
            <pubDate>Fri, 29 Mar 2024 15:02:22 GMT</pubDate>
            <description><![CDATA[<p>이번에 프로젝트가 끝나고 BackEnd쪽 수업을 진행했다. docker를 이용해서 oracle과 mysql을 연결하고 eclipse를 통해서 DB와 연동하면서 웹에 데이터를 찍어낼 수 있는 수업을 진행하고 있다. 정말 알고 싶었던 부분이고 궁금했던 부분이고 어떻게 DB에서 server를 거쳐서 Web까지 데이터가 전송이 되는지 어렵겠지만 알고 싶고 이해하고 싶었다. git과 eclipse를 연동하는 과정에서 부터 막혔다.
오랜만에 sourcetree로 깃을 연동을 했는데 eclipse를 열어보니까 연동이 잘 안되어있었다. 분명 파일에 git init 한 다음 Sourcetree로 와서 강사님 git이랑 연동을 했는데 eclipse에서는 연동이 안되어 있었다.
<img src="https://velog.velcdn.com/images/jm_dae/post/200ade58-2b60-4f6f-b292-d324099db8e2/image.png" alt=""></p>
<p>위에 사진처럼 maser와 orgin/master가 들어와 있어야하는데 안들어 와 있었다. 이 문제는 정말 단순했던게 sourcetree에서 한번 pull을 당겨오거나 push를 해보면 eclipse에서 알아서 master와 orgin/master가 연동이 되는 것을 확인할 수 있었다.</p>
<p>다음에 잘 가져왔는데 아무래도 Web이랑 server랑 DB를 다 연결하는 거다보니까 일반 project가 아닌 Dynamic Web Project로 파일을 만들었다. 하지만 pull로 파일을 가져오는 과정에서 계속 Dynamic Web Project가 아닌 그냥 일반 project 파일로 들어오는 것이였다. 결론적으로 말하자면 .gitignore문제였다.
<img src="https://velog.velcdn.com/images/jm_dae/post/69690d2e-ca95-4d84-b933-6b0674ba4e54/image.png" alt=""></p>
<p>gitignore에 주석처리 되어 있는 부분이 원래는 들어가 있었다. 그래서 파일이 제대로 넘어가지 않고 일반 project파일로 들어오는 것이였다.
근데 그 전에 혼자서 해결하기 위해서 끙끙거리면서 일반 project파일을 Dynamic Web Project로 바꾸는 작업을 했는데 2가지만 확인하면된다.
먼저 pull을 당겨오면 tomcat 라이브러리가 잘 들어가 있는지 두번째는 Project facets 에서 Dynamic Web Module, java, javascript 가 잘 체크가 되어 있는지 확인해야한다.</p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/49ebdf03-000d-4344-b378-c87b0aa0e042/image.png" alt=""></p>
<p>tomcat라이브러리가 없다면 먼저 maven에서 다운받는 것이 우선이고 다운을 받았고 server와 연동을 해줬다면 build path들어가서 Server Runtime에 Tomcat이 잘 들어와 있나 확인해줘야한다.
활성화되어있지 않다면 Classpath를 눌러서 add Library에서 추가해줘야한다. 이렇게 해서 라이브러리에 추가가 된다면 오류를 잡을 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/5a245dbc-064c-4453-8a74-2437b8d0a69a/image.png" alt=""></p>
<p>아 그리고 이렇게 라이브러리를 추가했는데도 오류가 뜨는 경우가 있는데 이럴때는 파일을 우클릭해서 위의 그림처럼 java EE Tools-&gt; Update EAR Libraries를 누르면 된다.</p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/7dfacfb4-465b-47f8-9fea-1293d926f09f/image.png" alt=""></p>
<p>이건 앞에서 말했듯이 일반 project로 들어와서 계속 삽질하고 찾아보다가 알게 되었는데 Project Facets에서 Dynamic Web Modul, java, javascript가 선택이 되어 있어야지 일반 project가 Dynamic Web Project로 바뀌는 것을 확인할 수 있다. 파일은 바꼈으나 서버가 잘 실행이 안되는 거 봐서는 위에 언급했듯이 gitignore에서 파일을 빼고 보내는 것이 아닌지 확인해야한다.</p>
<p>항상 git을 연동하는 데에서 너무 많은 시간을 소비하고 있다. 그래도 협업을 위해서는 계속해서 이렇게 git 문제에 부딪힐 때마다 공부하고 기록하고 회고하려고 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[css display...none, inline-block, inline, block 에 대하여...]]></title>
            <link>https://velog.io/@jm_dae/css-display...none-inline-block-inline-block-%EB%AD%90-%EC%9D%B4%EB%A6%AC-%EB%A7%8E%EC%95%84</link>
            <guid>https://velog.io/@jm_dae/css-display...none-inline-block-inline-block-%EB%AD%90-%EC%9D%B4%EB%A6%AC-%EB%A7%8E%EC%95%84</guid>
            <pubDate>Thu, 28 Mar 2024 01:47:55 GMT</pubDate>
            <description><![CDATA[<p>프로젝트를 하면서 hover 기능을 넣을 일이 있었는데 hover를 하니까 글씨가 나오면서 밑에 있는 줄이 깨지더라고요. hover를 했을 때 나오는 글은 display 속성을 none으로 했는데 왜 깨지는 지 이유를 알 수 없었습니다. 옆에서 보던 훌륭한 팀원분이 display속성을 visibility:&#39;hidden&#39;;으로 바꿔보라고 권유해서 바꿨는데 라인이 안깨지고 hover했을 때 글씨가 나오더라고요. 그래서 display와 visibility에 대해서 찾아보기로 했죠. 
먼저 display 속성에서 none, block, inline, inline-block이 있습니다.</p>
<ol>
<li>먼저 display: none;은 visibility hidden과 유사하면서 다른 점이 있습니다. none은 화면에 글을 출력하지도 않고 공간을 차지하지도 않습니다. 반면에 hidden은 글을 출력하지 않는 건 똑같지만 공간을 차지하고 있습니다. 말 그래도 hidden 뒤에 숨어 있는거죠. 동적인 효과에서는 랜더링 문제로 visibility를 사용해야한다고 했다. </li>
<li>display: block; 은 div, p, h, li태그 등 큰 단위가 이에 해당되며 기본적으로 가로영역을 모두 차지한다. 그랫 block 처리를 하게 되면 자동으로 다음 글은 줄바꿈이 되어버린다.</li>
<li>display: inline;은 span, b, i, a 태그 등 작은 단위가 이에 해당되며 block과 달리 줄바꿈이 되지 않는다. 또한 width와 height속성을 지정할 수 없어서 글자크기만큼만 속성을 추가할 수 있다. inline은 글씨나 문장에 효과를 주기위해 존재하는 속성이라고 생각하면쉽다. </li>
<li>display: inline-block; 은 block 요소와 inline요소가 결합된거라고 생각하면 되는데 width와 height를 지정할 수 있지만 줄바꿈은 되지 않는다. 한마디로 글씨나 문장에 box처리해서 효과를 줄 수 있다. </li>
</ol>
<p>display 배운긴 배웠는데 정확하게는 몰랐는데 이번에 프로젝트를 계기로 조금 더 정확하게 알게되고 이해한거 같아서 좋다. 이렇게 사소한거라도 모르는 내용이 있으면 구글링하고 알아보고 이해하고 정리하는 습관을 가져야겠다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[내 정보 공개 여부 DB에 안 들어가서 input type radio에서 checkbox로 수정]]></title>
            <link>https://velog.io/@jm_dae/%EB%82%B4-%EC%A0%95%EB%B3%B4-%EA%B3%B5%EA%B0%9C-%EC%97%AC%EB%B6%80-DB%EC%97%90-%EC%95%88-%EB%93%A4%EC%96%B4%EA%B0%80%EC%84%9C-input-type-radio%EC%97%90%EC%84%9C-checkbox%EB%A1%9C-%EC%88%98%EC%A0%95</link>
            <guid>https://velog.io/@jm_dae/%EB%82%B4-%EC%A0%95%EB%B3%B4-%EA%B3%B5%EA%B0%9C-%EC%97%AC%EB%B6%80-DB%EC%97%90-%EC%95%88-%EB%93%A4%EC%96%B4%EA%B0%80%EC%84%9C-input-type-radio%EC%97%90%EC%84%9C-checkbox%EB%A1%9C-%EC%88%98%EC%A0%95</guid>
            <pubDate>Thu, 28 Mar 2024 00:05:27 GMT</pubDate>
            <description><![CDATA[<p>내 정보 공개 여부를 처음에 radio를 사용해서 &quot;공개&quot;, &quot;비공개&quot;로 클릭할 수 있게 했는데 &quot;공개&quot;를 선택했을 때는 js에서 받아서 server로 값을 옮기는데 &quot;비공개&quot;로 바꾸고 보내니까 잘 안보내지더라고요. 두 개가 &quot;공개&quot;, &quot;비공개&quot; 나눠져있어서 &quot;공개&quot;를 선택한 것과 비공개를 선택한 것을 나눠서 DB에 넣어야하는데 그렇게 2개를 연동하는게 쉽지 않았다. 
radio type은 두 개의 버튼이 독립적으로 DB에 데이터 값이 작용하는 듯했다. 
그래서 여러가지 방법을 선택하다가 input type을 radio가 아니라 checkbox로 하기로 정했다. checkbox로 하게 되면 선택했거나 선택안했거나 이 2가지 경우이기 때문에 그리고 버튼이 1개이기 때문에 js에서 인식하고 Server쪽으로 데이터를 옮기기에 적합해보였다. 
공개 여부를 checkbox로 바꾸고 js 코드를 아래와 같이 작성했다.</p>
<pre><code>document.getElementById(&quot;disclosure&quot;).addEventListener(&quot;click&quot;, (event) =&gt;{
            if(event.target.value === &quot;true&quot;){
                event.target.value = &quot;false&quot;
            }else{
                event.target.value = &quot;true&quot;;
            }

        })</code></pre><p>원래의 값을 html에서 input의 value값을 true로 해놓은 상태이고 이것을 server로 보낼 대는 false로 처리하기 위해서 위와같이 if문을 활용해서 작성했다. </p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/110962cb-50f4-4074-a251-6e3feaf1b09d/image.png" alt=""></p>
<p>그리고 데이터 값을 넣어줄 때 삼항연산자를 활용해서 데이터 값이 들어가게 처리해줬다.</p>
<p><img src="https://velog.velcdn.com/images/jm_dae/post/a60d4bd5-e0c1-4d55-96f9-b41d8abe8fe3/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[vh, vw 에 대하여...]]></title>
            <link>https://velog.io/@jm_dae/vh-vw-%EA%B7%B8%EA%B2%8C-%EB%AD%94%EB%8D%B0</link>
            <guid>https://velog.io/@jm_dae/vh-vw-%EA%B7%B8%EA%B2%8C-%EB%AD%94%EB%8D%B0</guid>
            <pubDate>Mon, 25 Mar 2024 08:38:28 GMT</pubDate>
            <description><![CDATA[<p>css를 작성하는 과정에서 background가 제대로 들어가지를 않더라고요... 훌륭하시 팀원분이 height를 100vh로 사용해보라고 도움을 주셔서 사용했는데 background가 잘 들어가는 것을 확인할 수 있었습니다.
팀원분이 알려줬을 때는 아 저거 그냥 쓰면 되는가 보다하고 넘겼는데 나중에도 이런 상황이 오면 혼자 해결을 못 할 것 같다는 느낌에 vh, vw에 대해서 공부를 했습니다. 그리고 css에서는 정렬하는 게 쉽지 않기도 하고 이것저것 디테일한 부분까지 알아야지 정확하게 정렬을 할 수 있을 것 같다는 느낌이 프로젝트를 하면서 강하게 들어서 프로젝트가 끝나고 나서 혼자 찾아보게 되었습니다.
일단 1vh는 viewport height의 줄임말로 뷰포트의 100분의 1을 의미합니다. 그러면 1vw는 viewport width로 뷰포트의 100분의 1을 의미합니다. 예를 들면 브라우저 높이가 900px이라고 하면 1vh = 9px이 되고 브라우저 너비가 800px이라고 하면 1vw = 8px이 됩니다. 
그래서 저의 팀원분도 100vh로 높이를 지정해보라고 하신 말이 전체 화면의 높이 만큼 background를 지정하라는 말이 였습니다. 참 알고나면 별거 아닌데 모르면 힘들죠... 스스로 배우고 찾아보고 공부하는 것도 오래걸리는 일이고요. 
아무튼 vh와 vw는 상대적인 값을 나타내므로 전체적인 크기를 잡는 것도 유용하고 html 프레임을 정렬하는 데 있어서도 편할 것 같다는 생각을 했습니다. css에서 까다롭다고 생각한 것이 정렬이 였는데 이렇게 사소한 단위를 알아야지 정렬을 하기 용이할 것 같았습니다. 
제가 또 정렬하는 데 있어서 F12을 정말 많이 사용해서 내가 수정하고 싶은 부분이 어느 부분에 해당하는 지 확인하고 해당 부분을 수정작업을 하니까 시간도 줄어들고 어느부분이 잘 못 됐는지 정확하게 파악하기 용이했습니다.</p>
]]></description>
        </item>
    </channel>
</rss>