<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Log on</title><link>https://taetaetae.github.io/tags/log/</link><description>Recent content in Log on</description><generator>Hugo</generator><language>en</language><lastBuildDate>Sun, 04 Oct 2020 15:39:15 +0000</lastBuildDate><atom:link href="https://taetaetae.github.io/tags/log/index.xml" rel="self" type="application/rss+xml"/><item><title>그런 개발자로 괜찮은가 - '로그 &amp; 모니터링' 편</title><link>https://taetaetae.github.io/2020/10/04/a-good-developer-in-terms-of-log-and-monitoring/</link><pubDate>Sun, 04 Oct 2020 15:39:15 +0000</pubDate><guid>https://taetaetae.github.io/2020/10/04/a-good-developer-in-terms-of-log-and-monitoring/</guid><description>&lt;p>　캐릭터를 육성하며 게임하는 경우를 생각해 보자. 더 좋은 아이템을 얻거나 퀘스트를 달성하기 위해 당신은 다양한 방법을 통해 캐릭터를 성장시킨다. 사냥을 하다 체력이 떨어지게 되면 물약을 먹고, &lt;!--more -->캐릭터의 능력 중 부족한 부분이 있으면 훈련을 더 하거나 그에 맞는 아이템을 장착하게 된다. 이렇게 캐릭터의 &amp;lsquo;상태&amp;rsquo;를 적절한 UI를 통해 사용자에게 알려주기 때문에 &amp;lsquo;확인&amp;rsquo;이 가능하고 &amp;lsquo;대응&amp;rsquo;이 가능하게 된다.&lt;/p>
&lt;p>　우리가 만드는 애플리케이션 또한 위에서 이야기 한 게임상의 캐릭터가 아닐까 싶다. 복잡한 스펙을 다양한 테스트 케이스를 만들며 로직 동작에는 이상이 없음을 확인했다면 그걸로 만족할 수 있을까? 개발자의 &amp;lsquo;레벨&amp;rsquo;은 이 부분에서 차이가 난다고 생각한다. 운영환경에 출시한 애플리케이션에 에러가 나는지, 트래픽이 얼마나 들어오고 있고 트래픽의 유형은 또 어떠한지, 요청에 대한 응답속도는 어떻고 서버의 시스템 지표에는 문제가 없는지 등등. 애플리케이션의 유형에 따라 다양하겠지만 적절한 로그를 이용하여 애플리케이션의 &amp;lsquo;상태&amp;rsquo;를 확인하고 문제가 있다면 &amp;lsquo;대응&amp;rsquo;하는 게 꼭 필요하다고 생각한다.&lt;/p>
&lt;p>　이번 포스팅에서는 크게 로깅과 모니터링에 대해 알아보고자 한다. 이를 통해 애플리케이션의 &amp;lsquo;개발&amp;rsquo;에만 집중하고 있던 관점을 보다 더 높은 곳에서 바라보며 애플리케이션의 &amp;lsquo;운영&amp;rsquo; 측면에서도 고민해 보는 기회가 되었으면 한다.&lt;/p>
&lt;blockquote>
&lt;p>필자는 서버 개발자이다 보니 글의 내용이 다소 서버 개발자의 시선에서 작성하게 되었다. 하지만 &amp;lsquo;개발자&amp;rsquo;라면 유형만 다르지 대부분 비슷하기 때문에 크게 다르지 않다고 생각한다.&lt;/p>&lt;/blockquote>
&lt;h2 id="로그는-어떤걸-어떻게-남겨야-할까">로그는 어떤걸, 어떻게 남겨야 할까?&lt;/h2>
&lt;p>　﻿로그가 왜 필요한지에 대한 내용은 다루지 않겠다. (굳이 말하지 않아도 그만큼 중요하다는 표현이 더 어울릴 수도 있겠다.) 그렇다면 우선 어떤 로그를 남겨야 할까?&lt;/p>
&lt;figure>&lt;a class="lightgallery" href="https://taetaetae.github.io/images/a-good-developer-in-terms-of-Log-and-Monitoring/talk.jpg" title="/images/a-good-developer-in-terms-of-Log-and-Monitoring/talk.jpg" data-thumbnail="/images/a-good-developer-in-terms-of-Log-and-Monitoring/talk.jpg" data-sub-html="&lt;h2>필자가 꿈나무 시절때 나누었던 조직장님과의 대화 내용&lt;/h2>">
 &lt;img
 class="lazyload"
 src="https://taetaetae.github.io/svg/loading.min.svg"
 data-src="https://taetaetae.github.io/images/a-good-developer-in-terms-of-Log-and-Monitoring/talk.jpg"
 data-srcset="https://taetaetae.github.io/images/a-good-developer-in-terms-of-Log-and-Monitoring/talk.jpg, https://taetaetae.github.io/images/a-good-developer-in-terms-of-Log-and-Monitoring/talk.jpg 1.5x, https://taetaetae.github.io/images/a-good-developer-in-terms-of-Log-and-Monitoring/talk.jpg 2x"
 data-sizes="auto"
 alt="/images/a-good-developer-in-terms-of-Log-and-Monitoring/talk.jpg" width="40%" />
 &lt;/a>&lt;figcaption class="image-caption">필자가 꿈나무 시절때 나누었던 조직장님과의 대화 내용&lt;/figcaption>
 &lt;/figure>
&lt;p>　﻿아직까지도 기억에 남아있는 예전 조직 장님과의 대화. 일단 로그는 최대한 많이 (과하게) 남겨야 한다고 생각한다. 그다음 불필요한 로그들은 제거하거나 레벨을 낮추는 등 상황에 맞도록 커스터마이징이 필요하다. 경험을 해보면 알겠지만 운영환경에 애플리케이션을 배포하고 서비스를 운영하다 보면 개발 환경에서 만나기 어렵거나 경험해보지 못한 상황이 발생하곤 한다. 이럴 때 상황에 맞는 로그들이 있다면 미리 남겨둔 로그를 통해 더 효과적으로 상황을 파악할 수 있다. 트래픽의 정보(request url, parameter, UA, remote ip 등)를 남겨서 외부에서 호출하는 형태를 분석하는데 활용할 수도 있고, 애플리케이션에서 외부로 호출을 하고 난 뒤에 받는 응답에 대해서 로그를 남겨두면 외부 통신의 오류를 파악하는 데 도움이 될 수 있다. 어떤 로그를 남겨야 하는가에 대한 고민은 운영하는 애플리케이션이 어떤 행동을 하는가에 관점을 두고 고민해보면 좀 더 쉽게 찾을 수 있을 것이라 생각한다.&lt;/p>
&lt;p>　로그를 남기는 방법 또한 다양하다. 시스템 로컬에 파일로 남기거나 특정 로그 서버를 설정하여 여러 대의 서버 로그를 한곳에서 볼 수도 있다. 다만 로그를 &amp;lsquo;남기는&amp;rsquo; 것 또한 하나의 비용에 포함되기 때문에 애플리케이션의 기능에 최대한 영향이 가지 않도록 최대한 빠른 시간 내에 처리가 되도록 해야 한다. (혹은 비동기로 남기거나 등)&lt;/p>
&lt;p>　로그를 남기는 이유 중 가장 큰 이유는 &amp;lsquo;나중에 보기 위해서&amp;rsquo;이다. 그만큼 한번 로그를 남길 때에도 보기 좋게 남겨야 한다. 예컨대, 아래에 적어놓은 로그 방식의 경우 작은 차이지만 나중에 볼 때 꽤 큰 차이를 유발한다.
﻿&lt;/p>
&lt;ul>
&lt;li>안좋은 예&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-java" data-lang="java">&lt;span class="line">&lt;span class="cl">&lt;span class="k">try&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="p">...&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">catch&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Exception&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">){&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="n">log&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">Error&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// 어떤 상황이지..?&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>보다 조금 더 좋은 예&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-java" data-lang="java">&lt;span class="line">&lt;span class="cl">&lt;span class="k">try&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="p">...&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">catch&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Exception&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">){&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="n">log&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">Error&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;url : &amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;, parameter : &amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">parameter&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;, remote ip : &amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">remoteIp&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// 로그는 가급적 자세하게 !&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="로그가-가져다-주는-또-다른-세상">로그가 가져다 주는 또 다른 세상&lt;/h2>
&lt;p>　로그는 또 다른 데이터가 될 수 있다. 글 목록을 보여주는 웹페이지가 있다고 가정해보자. 이때 사용자들이 어떤 글을 더 많이 읽는지 &amp;lsquo;클릭 지표&amp;rsquo;에 대한 로그를 남겨 둔다면 &amp;lsquo;인기글&amp;rsquo; 같은 또 다른 웹 페이지가 나올 수 있을 것 같다. 만약 그 페이지가 회원만 읽을 수 있는 페이지라면 &amp;lsquo;20대 남성이 월요일 오후에 많이 읽는 글&amp;rsquo; 같이 회원의 정보를 조합하여 새로운 데이터를 만들 수 있게 된다. 이러한 데이터들은 보다 더 좋은 서비스를 할 수 있게 도와줄 수 있는 밑거름이 되고 그 바탕은 로그라는 걸 명심하자.&lt;/p></description></item></channel></rss>