<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[RSS Feed of sharkslee0.github.io]]></title><description><![CDATA[안녕하세요 :)]]></description><link>https://sharkslee0.github.io</link><generator>GatsbyJS</generator><lastBuildDate>Sun, 20 Jul 2025 12:13:02 GMT</lastBuildDate><item><title><![CDATA[[Network] HTTP와 HTTPS]]></title><description><![CDATA[HTTP와 HTTPS HTTP(Hyper Text Transfer Protocol)는 서버/클라이언트 모델에 따라 데이터를 주고받기 위한 프로토콜이다. 즉, HTTP는 인터넷에서 하이퍼 텍스트를 교환하기 위한 통신 규약이며, 8…]]></description><link>https://sharkslee0.github.io/http-vs-https/</link><guid isPermaLink="false">https://sharkslee0.github.io/http-vs-https/</guid><pubDate>Mon, 23 Sep 2024 00:00:00 GMT</pubDate><content:encoded>&lt;figure&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; margin-bottom: 16px;&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/8d88887225da1f9346d842abd1f7699d/59f54/http-vs-https-01.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 17.64705882352941%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA0UlEQVR42mXO207DMAwG4L7/W3GBhBAINAYsNMuho2mObZjUNm0vfoxAk9AuPsV27MQVe3woL2xXnl73hTFeuJREXRNUP4rCal7e3lk5sPoK+6iXSt/e4Jnf426/g7Me0TqE1iCYDvGPpzx6j9T3sM5BKgUhFeiDf45CopLU7GzA6dRC1BxZaGRjkdvuF8VnuhukRsoZMUaklBDJOI6YpulinmdUTaPho0fTfkJxji8azsOAHBOGENHTA+efU2l0tKUxBj4EBKoty4J1XS+2bcM37YQl9PCuLbUAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;http vs https 01&apos; title=&apos;&apos; src=&apos;/static/8d88887225da1f9346d842abd1f7699d/ca1dc/http-vs-https-01.png&apos; srcset=&apos;/static/8d88887225da1f9346d842abd1f7699d/e7570/http-vs-https-01.png 170w,
/static/8d88887225da1f9346d842abd1f7699d/f46e7/http-vs-https-01.png 340w,
/static/8d88887225da1f9346d842abd1f7699d/ca1dc/http-vs-https-01.png 680w,
/static/8d88887225da1f9346d842abd1f7699d/59f54/http-vs-https-01.png 792w&apos; sizes=&apos;(max-width: 680px) 100vw, 680px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption&gt;출처: https://www.cloudflare.com/ko-kr/learning/ssl/what-is-https/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2&gt;HTTP와 HTTPS&lt;/h2&gt;
&lt;p&gt;HTTP(Hyper Text Transfer Protocol)는 서버/클라이언트 모델에 따라 데이터를 주고받기 위한 프로토콜이다. 즉, HTTP는 인터넷에서 하이퍼 텍스트를 교환하기 위한 통신 규약이며, 80번 포트를 사용한다.&lt;/p&gt;
&lt;h3&gt;HTTP의 문제점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;HTTP는 평문 통신이기 때문에 도청이 가능하다.&lt;/li&gt;
&lt;li&gt;HTTP는 통신 상대를 검증하지 않기 때문에 피싱이나 중간자 공격(Man-in-the-Middle Attack)에 취약하다.&lt;/li&gt;
&lt;li&gt;데이터의 무결성을 보장하지 않기 때문에, 데이터가 전송 중에 변경되거나 조작될 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;HTTPS(HTTP over SSL, HTTP over TLS, HTTP Secure)는 HTTP에 데이터 암호화가 추가된 프로토콜이며, HTTP와 달리 443번 포트를 사용한다. HTTPS의 가장 큰 특징은 HTTP가 가지고 있던 보안 문제를 해결한다는 것이다. 즉, HTTPS는 &lt;strong&gt;암호화, 인증, 완전성 보장&lt;/strong&gt;을 지원한다.&lt;/p&gt;
&lt;h2&gt;SSL과 TLS&lt;/h2&gt;
&lt;p&gt;넷스케이프가 SSL(Secure Socket Layer)을 발명하고, 점차 폭넓게 사용되다가 표준화 기구인 IETF의 관리로 넘어가면서 TLS(Transport Layer Security)로 이름이 바뀌었다. TLS 1.0은 SSL 3.0을 계승한 것이다.&lt;br&gt;
물론 TLS가 발전하면서 차이점도 존재하지만, 동작 방식은 유사하니 이 글에서는 같은 의미로 설명한다.&lt;/p&gt;
&lt;h2&gt;대칭키 암호화와 비대칭키 암호화&lt;/h2&gt;
&lt;h3&gt;대칭키 암호화&lt;/h3&gt;
&lt;figure&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; margin-bottom: 16px;&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/735838ae354b376e7c746868b4cbcd3e/c0214/http-vs-https-02.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 54.70588235294118%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABxUlEQVR42m1SW27aUBD1ihoJiRWwGiQipb/pPyuABfSjQUL5hCZIreqKFqkQ2yIEFbCNMfhV2/Xj+hITfCE51GpSkd6vufM6Z84M9/jqua47mUxkWTZNY7lcapo2m83m8/l2u0V0v98/Z3Kvi9M0jaIoIcQPIu93SGkSBEGSJLvd7ijzuBjtUbx5OIA0P9+9b0swNpsHvCzL/lO8//tgB3Fyf5/m9q1sfR9qMIAZEZrQ9VHyCzIay7Ofl58k3YkO3222Wq0s22F/2HaHyyu+7/6y/x2bA0lIoigKIYSxzAsIoSkCnudBM1VRHcfBN6Ybx/WR4Pu+qqrQD3S4MAyRJIriYDDodDpf+S9xFFFKRUHo9Xr9/g9RlD5cXFxfX0F81/Vy5XmeR1MujuPxeGzbdqvVKhaLJ29Ozs7enlYqH9vt4fDWMIxGo1EoFEqlUrlcPn93/q3bXSx0gIMah62ANqzpdFqtVuv1umOjqSNJkiAIo9FocHNTq9WazSYWBkaABZJpmjiHw8y6rq8Mw/P9XIZcD8TACB1JTJ5FPmjhe7gcaLlerzksdqEtAI4PwtA8PwZMrioKaAMNfsZY7g/DAH7LshhjTz8OUAU2xg4+AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;http vs https 02&apos; title=&apos;&apos; src=&apos;/static/735838ae354b376e7c746868b4cbcd3e/ca1dc/http-vs-https-02.png&apos; srcset=&apos;/static/735838ae354b376e7c746868b4cbcd3e/e7570/http-vs-https-02.png 170w,
/static/735838ae354b376e7c746868b4cbcd3e/f46e7/http-vs-https-02.png 340w,
/static/735838ae354b376e7c746868b4cbcd3e/ca1dc/http-vs-https-02.png 680w,
/static/735838ae354b376e7c746868b4cbcd3e/c0214/http-vs-https-02.png 796w&apos; sizes=&apos;(max-width: 680px) 100vw, 680px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption&gt;출처: https://www.ssl2buy.com/wiki/symmetric-vs-asymmetric-encryption-what-are-differences&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;클라이언트와 서버가 동일한 키를 사용하여 암호화/복호화를 진행한다.&lt;/li&gt;
&lt;li&gt;키가 노출되면 매우 위험하지만, 연산 속도가 빠르다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;그런데, 이 대칭키를 어떻게 양쪽이 공유할 수 있을까? 대칭키가 중간에 갈취당한다면 큰 문제가 될 것이다. 이러한 대칭키 암호화 방식의 한계로, 비대칭키 암호화 방식이 등장하였다.&lt;/p&gt;
&lt;h3&gt;비대칭키(공개키) 암호화&lt;/h3&gt;
&lt;figure&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; margin-bottom: 16px;&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/a4c7c0fc6770b337f41a2b8aadcb6e08/c0214/http-vs-https-03.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 54.70588235294118%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABzElEQVR42m1Sy27aQBT1HyEh8QV8DVIqseoikbrkC+ATChKLSpFoGtiElgipAdtJEKoAUz+wsWsbZsbxS3js5CSpojTprO77nHvuCPfv3m63W61Wi8XC0I3tdquqv/GWy2UYhsgWRfFSKbxvTtOUUkYpcX3bdnePNiGMBYfD4U3l22ZUxHGcZTxJo/bg08fmqWHT+4JjYpZl/2ku/r4c9l3IkjSBkSTJ7Wrw5UL2SQQ3uIvCKH5VXPyDzHm2+LW8lE49asAFVU3XdN2gLIA7utYHP6buH/v12gIQVFVVFCUIGOc5CdwoZkh4vgfZEHccBy4JYuwPAN/31+s1JMzzXCCEoEiSpMlk0u/3hxffoRCElURxPB5fXf2UJPlzu31+/s2yTNd1ITs6h8MhhgqMsfl8btt2r9erVCqlUqler384Ojr72ru5uTVNs9PplMvlarVaq9WOT44vRyNN0wHueZ5AKQVtWDhso9FotVqOjaGOLMuiKM5ms8l02mw2u93ufr8HI8ACybIssHjcWdf1jWl6vv8sw7MeyIERJgZPgr0oDC0Mw9hsNlEUCTispmoAh4M0jgklUIRfslYU0AYa4hxiPsUJ2SOOn8c5fwAjjk3czwOjDQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;http vs https 03&apos; title=&apos;&apos; src=&apos;/static/a4c7c0fc6770b337f41a2b8aadcb6e08/ca1dc/http-vs-https-03.png&apos; srcset=&apos;/static/a4c7c0fc6770b337f41a2b8aadcb6e08/e7570/http-vs-https-03.png 170w,
/static/a4c7c0fc6770b337f41a2b8aadcb6e08/f46e7/http-vs-https-03.png 340w,
/static/a4c7c0fc6770b337f41a2b8aadcb6e08/ca1dc/http-vs-https-03.png 680w,
/static/a4c7c0fc6770b337f41a2b8aadcb6e08/c0214/http-vs-https-03.png 796w&apos; sizes=&apos;(max-width: 680px) 100vw, 680px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption&gt;출처: https://www.ssl2buy.com/wiki/symmetric-vs-asymmetric-encryption-what-are-differences&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;두 개의 키 중 하나로 암호화하면, 나머지 키로만 복호화가 가능하다.
&lt;ul&gt;
&lt;li&gt;예를 들어 A 키와 B 키가 하나의 쌍이라면, A 키로 암호화하면 B 키로 복호화할 수 있고, B 키로 암호화하면 A 키로 복호화할 수 있다.&lt;/li&gt;
&lt;li&gt;둘 중 하나를 공개키라 하고, 다른 하나를 개인키로 정한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;클라이언트는 공개키를 가지고, 서버는 개인키를 가진다.
&lt;ul&gt;
&lt;li&gt;공개키는 이름에서 알 수 있듯이 누구나 가질 수 있다. 대신, 개인키는 서버만이 가지고 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;키가 노출되더라도 비교적 안전하지만, 연산 속도가 느리다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;우리가 네이버에서부터 정보를 받았을 때, 이게 진짜 네이버에서 온 정보인지 어떻게 알 수 있을까?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;네이버에서 우리에게 보내는 정보 중 일부가 네이버의 개인키로 암호화되어 있다.&lt;/li&gt;
&lt;li&gt;네이버의 개인키로 암호화된 정보를 복호화할 수 있는 것은 우리가 가진 네이버의 공개키뿐이다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;만약 우리가 가진 네이버의 공개키로 온전히 복호화할 수 있다면, 그것은 네이버에서 온 정보일 것이다.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 예시는 단순히 인증을 이해하기 위한 예시이며, 비대칭키 암호화를 사용하면 이렇게 인증을 할 수 있다는 것만 확인한다. 실제로 서버의 인증은 이후에 설명할 SSL 인증서를 통해 진행된다.&lt;/p&gt;
&lt;h2&gt;SSL 인증서&lt;/h2&gt;
&lt;p&gt;SSL 인증서는 클라이언트와 서버 간의 통신을 제3자가 보증해주는 전자화된 문서이다. 클라이언트가 서버에 접속한 직후에 서버는 클라이언트에게 이 인증서 정보를 전달한다. 클라이언트는 이 인증서가 신뢰할만한 것인지 검증한 후 다음 절차를 진행한다.&lt;/p&gt;
&lt;p&gt;이 SSL 인증서를 통해 앞서 언급한 HTTP의 보안 문제를 해결한다. 즉, SSL 인증서의 기능은 크게 다음과 같다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;클라이언트가 접속한 서버가 신뢰할 수 있는 서버임을 보장한다.&lt;/li&gt;
&lt;li&gt;SSL 통신에 사용할 공개키를 클라이언트에게 제공한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;CA(Certificate Authority)&lt;/h3&gt;
&lt;p&gt;앞서 말했듯, 인증서의 역할 중 하나는 클라이언트가 접속한 서버가 신뢰할 수 있는 서버임을 보장하는 것이다. 그럼 누가 보증을 해줄까? 이를 인증하는 공인된 민간 기업들이 있다. 이러한 기업들을 CA라고 한다. SSL을 통해 암호화된 통신을 제공하려는 서비스는 CA를 통해 인증서를 구입해야 한다.&lt;/p&gt;
&lt;h3&gt;SSL 인증서의 내용&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;서비스의 정보&lt;/strong&gt; (인증서를 발급한 CA, 서비스의 도메인 등)
&lt;ul&gt;
&lt;li&gt;클라이언트가 접속한 서버가 클라이언트가 의도한 서버가 맞는지에 대한 내용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;서버 측의 공개키&lt;/strong&gt; (공개키의 내용, 공개키의 암호화 방법)
&lt;ul&gt;
&lt;li&gt;서버와 통신할 때 사용할 공개키와 그 공개키의 암호화 방법&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;서비스의 도메인, 공개키와 같은 정보는 서비스가 CA로부터 인증서를 구입할 때 제출해야 한다. 이 내용들은 CA에 의해서 암호화되는데, 이때 사용하는 암호화 방식이 공개키(비대칭키) 방식이다. &lt;strong&gt;CA는 자신의 CA 개인키를 이용해서 서비스에서 제출한 인증서를 서명한다.&lt;/strong&gt; CA의 개인키는 절대로 유출되어서는 안 된다. 그리고, 우리가 사용하는 브라우저에는 CA들의 목록과 그들의 공개키가 내장되어 있다.&lt;/p&gt;
&lt;h2&gt;SSL 인증서가 서비스를 보증하는 방법&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;웹 브라우저가 서버에 접속할 때 서버는 제일 먼저 클라이언트에게 인증서를 제공한다.&lt;/li&gt;
&lt;li&gt;브라우저는 이 인증서를 발급한 CA가 자신이 내장한 CA의 리스트에 있는지를 확인한다.&lt;/li&gt;
&lt;li&gt;확인 결과 서버에서 받은 인증서가 내장된 CA 리스트에 포함되어 있다면, 해당 CA의 공개키를 이용해서 인증서를 복호화한다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CA의 공개키를 이용해서 인증서를 복호화할 수 있다는 것은 이 인증서가 CA의 개인키에 의해 암호화된 것을 의미한다.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;해당 CA의 개인키를 가지고 있는 CA는 해당 CA밖에 없기 때문에, 서버가 제공한 인증서가 CA에 의해 올바르게 발급된 것이라는 것을 의미한다.&lt;/li&gt;
&lt;li&gt;즉, CA에 의해 발급된 인증서라는 것은 접속한 사이트가 CA에 의해 검토되었다는 것을 의미하고, CA의 검토를 통과했다는 것은 해당 서비스가 신뢰할 수 있다는 것을 의미한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이렇게 해서 인증서가 서버의 신뢰성을 제공하는 방법을 알아봤다. 그런데 의문점이 남는다. 인증서에 포함된 서버의 공개키는 어떤 용도로 사용될까?&lt;/p&gt;
&lt;h2&gt;SSL의 동작 방법&lt;/h2&gt;
&lt;p&gt;비대칭키 암호화 방식만을 사용하면 컴퓨팅 파워가 많이 소모되기 때문에 SSL 인증서에서는 &lt;strong&gt;대칭키 방식과 비대칭키 방식 모두를 사용&lt;/strong&gt;한다. 클라이언트와 서버가 주고받는 실제 정보는 대칭키 방식으로 암호화하고, 이 대칭키를 비대칭키 방식으로 암호화하여 클라이언트와 서버가 공유한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;실제 데이터 : 대칭키 방식&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;대칭키 방식의 키 : 비대칭키 방식&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;컴퓨터와 컴퓨터가 네트워크를 통해 통신을 할 때 내부적으로 3단계를 거친다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Handshake → 전송 → 세션 종료&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이러한 과정에서 SSL이 어떻게 데이터를 암호화하여 전달하는지 알아보자.&lt;/p&gt;
&lt;figure&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; margin-bottom: 16px;&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/b6c3265b63fd50ce949c3df89a6326d2/92fa7/http-vs-https-04.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 57.05882352941176%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB70lEQVR42lVRTW8TQQzd30q5c+APcAROHJA4wQFVIqUCwSkcAkpR06ZJ01aFhgbytd+zu2N7PLOz3aQtZUKERKwnz4w19rP9PP3PmLUQGMaZL6BQ2ugNi+I4SVO9GfbWaS6a56iwDDOb8EIa68LrH8boVOA0onGictKl2Ux279qWTJwEsD+IumOIyJT/sQAoP5STxJ1aMSte82lvYU1nkr84mL8+HD9rT1rffFFAKgmVAlKklGblqiOAVni3sDe1/X1V1tYws2eNnmR0OC36M3nkwyjMXFkglqTWyJBSoKyAwTTdOQ3en0wbJ/6xX9SV9VzD3Wn68uhno//jVW/cGfmEMgdwG3DIQAkg4e6FPJvLjxfY/J46fzyHJAo9Uy5F8GU4eHzWe355+mQ+bgESoSDM/iJXlBtGQDZZ7y7dXgS7t8l2lXfCSHhsrmo5uI4adfzhOt5RSZ/Ystseo1aFJsEkDIYgM+2/y7tbw88P4s69Onxj7I2n7a2Zvw2+bl22H4b794tfu0zSoK8xYpWzQgfNhOiaCCwMKxyWMMR8Np3NHXNlcWRFW8UHldiD9ALJLRhWoNzRMqYafZRCBU08f+T3nzpfRs0CVjo7zSo2S13WulwWcjWwm1NRtgZT4cjB6Zad2/gT+i0TNV0L2lR/ANh5UJE5gHSTAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;http vs https 04&apos; title=&apos;&apos; src=&apos;/static/b6c3265b63fd50ce949c3df89a6326d2/ca1dc/http-vs-https-04.png&apos; srcset=&apos;/static/b6c3265b63fd50ce949c3df89a6326d2/e7570/http-vs-https-04.png 170w,
/static/b6c3265b63fd50ce949c3df89a6326d2/f46e7/http-vs-https-04.png 340w,
/static/b6c3265b63fd50ce949c3df89a6326d2/ca1dc/http-vs-https-04.png 680w,
/static/b6c3265b63fd50ce949c3df89a6326d2/02d09/http-vs-https-04.png 1020w,
/static/b6c3265b63fd50ce949c3df89a6326d2/9d567/http-vs-https-04.png 1360w,
/static/b6c3265b63fd50ce949c3df89a6326d2/92fa7/http-vs-https-04.png 2918w&apos; sizes=&apos;(max-width: 680px) 100vw, 680px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption&gt;SSL Handshake는 TCP 레이어의 3-way Handshake 이후에 진행된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SSL Handshake&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Client Hello: 클라이언트가 서버에 접속하고, 클라이언트는 서버에 다음과 같은 정보를 전달한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;클라이언트에서 생성한 랜덤 데이터&lt;/li&gt;
&lt;li&gt;클라이언트가 지원하는 암호화 방식&lt;/li&gt;
&lt;li&gt;세션 아이디: 이미 SSL Handshaking을 했다면 비용과 시간 절약을 위해 기존 세션을 재활용하는데 이를 위한 식별자 (이 과정에서는 크게 중요하지 않다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Server Hello: 서버는 Client Hello에 대한 응답으로 Server Hello 과정을 거치며, 클라이언트에 다음과 같은 정보를 전달한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;서버에서 생성한 랜덤 데이터&lt;/li&gt;
&lt;li&gt;서버가 지원하는 암호화 방식&lt;/li&gt;
&lt;li&gt;인증서&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;클라이언트는 서버에게서 받은 인증서가 CA가 발급한 것인지를 확인하기 위해 클라이언트에 내장된 CA 리스트를 확인한다.&lt;/p&gt;
&lt;p&gt;만약, 그 리스트에 인증서가 없다면 사용자에게 경고 메시지를 출력한다. 인증서가 CA에 의해 발급된 것인지 확인하기 위해 내장된 CA의 공개키로 복호화를 시도한다. 만약 복호화에 성공하면 CA의 개인키로 암호화된 것이기 때문에 신뢰할 수 있다.&lt;/p&gt;
&lt;p&gt;클라이언트는 자신이 생성한 랜덤 데이터와 서버에서 받은 랜덤 데이터를 조합하여 pre master secret이라는 키를 생성한다. 이 pre master secret이라는 키를 서버에도 전달해야 하는데, 이때 &lt;strong&gt;공개키 방식&lt;/strong&gt;으로 암호화한다.&lt;/p&gt;
&lt;p&gt;복호화된 인증서 안에는 서버가 생성한 공개키가 들어있다고 했었다. 클라이언트는 성공적으로 인증서를 복호화하면 서버 측에서 만든 공개키를 획득하게 된다. 클라이언트는 인증서에서 얻은 서버의 공개키로 pre master secret 값을 암호화하여 서버에 전달한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;서버는 그 공개키에 대한 개인키를 가지고 있기 때문에 pre master secret 값을 얻어낼 수 있다. 이제 클라이언트와 서버 모두 pre master secret 값을 공유하게 되었다. 클라이언트와 서버는 각각 일련의 과정을 통해 pre master secret에서 master secret 값을 만들어내고, 이 master secret으로 세션키를 생성한다. 이 세션키를 이용하여 서버와 클라이언트는 실제 데이터를 &lt;strong&gt;대칭키 방식&lt;/strong&gt;으로 암호화하여 주고받는다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;전송(세션)&lt;/strong&gt;&lt;br&gt;
실제로 클라이언트와 서버가 데이터를 주고받는 단계이다. 이전 단계에서 얻은 세션키를 이용하여 대칭키 방식으로 데이터를 암호화하고 상대방에게 전달한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;세션 종료&lt;/strong&gt;&lt;br&gt;
데이터 전송이 끝나면 서로에게 SSL 통신이 끝났음을 알린다. 세션 종료 후 세션키를 폐기하여 보안을 유지한다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;참고 자료&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=H6lpFRpyl14&quot;&gt;https://www.youtube.com/watch?v=H6lpFRpyl14&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=0cfUVrQW_yg&amp;#x26;list=PLCZ-8rvakaqbplQZAoUku8uuxUgbLQm-1&quot;&gt;https://www.youtube.com/watch?v=0cfUVrQW_yg&amp;#x26;list=PLCZ-8rvakaqbplQZAoUku8uuxUgbLQm-1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://opentutorials.org/course/228/4894&quot;&gt;https://opentutorials.org/course/228/4894&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ko.gadget-info.com/difference-between-ssl&quot;&gt;https://ko.gadget-info.com/difference-between-ssl&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[[Java] Exception에 대한 고찰]]></title><description><![CDATA[프로그램이 자바 언어의 제약을 벗어난다면, JVM은 Exception으로 프로그램에게 에러를 발생시킨다. 예시로 정해진 배열의 범위를 벗어나 접근하는 경우가 있다. 또한, 프로그램은 를 사용해서 명시적으로 Exception…]]></description><link>https://sharkslee0.github.io/java-exception/</link><guid isPermaLink="false">https://sharkslee0.github.io/java-exception/</guid><pubDate>Mon, 05 Aug 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;프로그램이 자바 언어의 제약을 벗어난다면, JVM은 Exception으로 프로그램에게 에러를 발생시킨다. 예시로 정해진 배열의 범위를 벗어나 접근하는 경우가 있다. 또한, 프로그램은 &lt;code class=&quot;language-text&quot;&gt;throws&lt;/code&gt;를 사용해서 명시적으로 Exception을 발생시킬 수 있다. 이러한 자바의 Exception의 종류와 동작 방식 등에 대해 알아보자.&lt;/p&gt;
&lt;h2&gt;Exception의 종류&lt;/h2&gt;
&lt;figure&gt;
   &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 400px; margin-bottom: 16px;&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/a32d8b4866f9de65f0a75be0e86712ff/d9f49/java-exception-hierarchy.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 81.17647058823529%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAABJ0AAASdAHeZh94AAADKElEQVR42l1RWU9TQRi9L/wCDaLUaEtsK3V7MxpN1Oi7Pmh8kBgTHlyi4v7gglFRkBBkMZHWKChSFyCIEDEqgkApvWytUIrVUqCoCC3UtvfOPg6tipqczEwy3/m+c84nUU4SwBRTCryTkereYF1/qP5DuLZvqs4VHp3+wRgiv8v+hjR3EUgQUGJRCsLtnqnjlcNH78pZFc7MouaTVm/PSAiiGKKEcCrwPxlzjhhTEeKchxQyPE28QTw8jT4HoS8IFIQpUcVwzkUhZBzPkwlSwYms8J7doYx96q6d+HYxEz0YZgx3B9RXnkjjh5l6V7jeGWp0RxuHQGAWcCGBJcgghnQ6ryQ5kpJCkkT37oVciIEIqeW9+Eztt8Nl9kN3bJnFLaeqPDltzPVFFWScIAvDoK4Gl99HlQ9QxT1gtxFBjo/+OIP7p8nALGvzTvUHoq6JaJvn24wq9BMyH5hoFYeIjs2G2PgYnwggv4+O+/jECA/46PeA+GQUIRhjf2X2K20KYsLprNXauSBlMM3o1K7o0+ndOoMzzdibnPo144BoLVaiQJX+Q6aIYiDIIieloWFo/Ubfth2ftm4f3LDJu3mLZ9sOz4bNk6fPUc4SZBI3nICYzP7Iju+MQsaE7ZloBAlrnDEKOANx2SJFZS6Q35CgowtmXya5N2FOLs3NAznX8Y25B80vwFdzVOvj7q/4zWfU6keto/SdD4uzZQQ1+1CHX5Xg/XK4cEnfUu37FI0tRdO+KNWeoulYlCovWaYka3DGfusgKpR53tvQhWrvtZeT2c/9+a2RIplbHEBCVquiN8mr1rYYTB0rTe+MAumtRpPNtOaHYRU9cvTpgFLYppx/6DicX51V2nQw72n2E1eJHZV3K5JaVTWq03evXtdsNL3Qr3xtSBePJkO6aDesM8SOHKuSp85WyFdrh67UDF181HP52cCVGvelZ25LR3BOdmzBYiXNiLQGRauPLF8hTqA1xNKM0WQNyNj/2E0K7LxEZkUOfquLFjlYcRcv7OIWGUrQ5UQlpdhsQWVmXGaGZWaUgNmCS2+DhhcDk8DmB/ZRYB+bR+cY6AkoPwHWo+3goq/8OgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;java exception hierarchy&apos; title=&apos;&apos; src=&apos;/static/a32d8b4866f9de65f0a75be0e86712ff/d9f49/java-exception-hierarchy.png&apos; srcset=&apos;/static/a32d8b4866f9de65f0a75be0e86712ff/e7570/java-exception-hierarchy.png 170w,
/static/a32d8b4866f9de65f0a75be0e86712ff/f46e7/java-exception-hierarchy.png 340w,
/static/a32d8b4866f9de65f0a75be0e86712ff/d9f49/java-exception-hierarchy.png 400w&apos; sizes=&apos;(max-width: 400px) 100vw, 400px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
   &lt;figcaption&gt;출처: https://www.javamex.com/tutorials/exceptions/exceptions_hierarchy.shtml&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Exception은 Throwable 클래스 혹은 그 서브클래스들의 인스턴스로 표현된다. 즉, Throwable 클래스와 그의 모든 서브클래스는 모두 예외를 나타내는 클래스들이다.&lt;/p&gt;
&lt;p&gt;Throwable 클래스의 직접 서브클래스(direct subclass)로는 Exception 클래스와 Error 클래스가 있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Exception 클래스는 일반적인 프로그램에서 복구를 시도할 수 있는 모든 예외의 상위 클래스이다. RuntimeException은 Exception 클래스의 직접 서브클래스이다.&lt;/li&gt;
&lt;li&gt;Error 클래스는 일반적인 프로그램에서 복구가 기대되지 않는 모든 예외의 상위 클래스이다. 대표적인 예인 &lt;code class=&quot;language-text&quot;&gt;OutOfMemoryError&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;StackOverflowError&lt;/code&gt;와 같이 발생하더라도 개발자가 어찌할 수 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Exception은 크게 Unchecked Exception과 Checked Exception으로 나뉜다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unchecked Exception : Error 클래스, RuntimeException 클래스와 그의 서브 클래스를 말한다. 위 그림에서 빨간색에 해당하는 부분이다.&lt;/li&gt;
&lt;li&gt;Checked Exception : Unchecked Exception(RuntimeException) 클래스가 아닌 모든 Exception의 서브 클래스를 말한다. 위 그림에서 빨간색이 아닌 파란색에 해당하는 부분이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Unchecked Exception&lt;/h3&gt;
&lt;p&gt;Unchecked Exception은 &lt;u&gt;Error 클래스, RuntimeException 클래스와 그의 서브 클래스&lt;/u&gt;를 말한다.&lt;/p&gt;
&lt;p&gt;컴파일 타임에 예외 처리를 위한 핸들러의 유무를 확인하지 않는다. Exception 처리가 강제되지 않아 개발자가 예외 처리 핸들러를 구현하지 않아도 된다. 물론, 원하는 경우에는 &lt;code class=&quot;language-text&quot;&gt;catch&lt;/code&gt;문을 사용해서 예상되는 RuntimeException 예외를 처리해줄 수 있다.&lt;/p&gt;
&lt;p&gt;Error 클래스는 시스템 레벨의 심각한 문제를 나타내며, 일반적으로 개발자가 이를 처리할 수 있는 방법이 거의 없다. 예를 들어, &lt;code class=&quot;language-text&quot;&gt;OutOfMemoryError&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;StackOverflowError&lt;/code&gt;와 같은 오류는 복구가 거의 불가능한 상황을 의미한다. 이러한 이유로 개발자는 애플리케이션 코드에서 &lt;code class=&quot;language-text&quot;&gt;Error&lt;/code&gt; 클래스에 대한 처리를 시도하지 않는 것이 일반적이다. 그렇기에 Unchecked Exception이라고 할 때는 RuntimeException과 그 하위 클래스를 주로 의미한다.&lt;/p&gt;
&lt;h3&gt;Checked Exception&lt;/h3&gt;
&lt;p&gt;Checked Exception 클래스는 &lt;u&gt;Unchecked Exception 클래스가 아닌 모든 Exception 클래스&lt;/u&gt;이다. 즉, RuntimeException 클래스 이외의 모든 Exception 클래스의 서브 클래스이다.&lt;/p&gt;
&lt;p&gt;자바는 Checked Exception에 대한 핸들러를 포함하도록 강제하여, 컴파일 타임에 Checked Exception에 대한 핸들러가 있는지 확인한다. 개발자는 예외 처리 핸들러를 반드시 포함해야 한다. &lt;code class=&quot;language-text&quot;&gt;catch&lt;/code&gt;문으로 처리하거나 &lt;code class=&quot;language-text&quot;&gt;throws&lt;/code&gt;를 이용해서 다른 곳에서 처리하도록 해야 한다. 이런 예외 처리 핸들러의 유무를 컴파일 타임에 확인함으로써 처리되지 않는 예외의 수를 줄일 수 있다.&lt;/p&gt;
&lt;h2&gt;예외 처리 방식&lt;/h2&gt;
&lt;p&gt;예외를 처리하는 방식에는 예외 복구, 예외처리 회피, 예외 전환 등 3가지 방법이 있다.&lt;/p&gt;
&lt;h3&gt;예외 복구&lt;/h3&gt;
&lt;p&gt;예외 상황을 파악하고 문제를 해결해서 정상 상태로 돌려놓는 방법이다.&lt;/p&gt;
&lt;p&gt;사용자가 특정 파일을 읽으려는데 파일이 없어 &lt;code class=&quot;language-text&quot;&gt;IOException&lt;/code&gt;이 발생하는 경우, 다른 파일을 선택하도록 유도하는 것으로 해결할 수 있다. 혹은 DB에 접속하는데에 실패하여 &lt;code class=&quot;language-text&quot;&gt;SQLException&lt;/code&gt;이 발생하는 경우, 여러 번 재시도하도록 할 수도 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; maxretry &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MAX_RETRY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maxretry&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SomeException&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;finally&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;RetryFailedException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 출처: 토비의 스프링 3.1 Vol.1 p286&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이처럼 사용자에게는 원하는 것처럼 동작하지 않았기 때문에 예외 상황으로 비쳐지더라도 애플리케이션에서는 정상적인 흐름에 따라 진행되어야 한다. 물론, 단순히 에러 메시지를 사용자에게 보여주는 것은 예외 복구로 볼 수 없다.&lt;/p&gt;
&lt;h3&gt;예외처리 회피&lt;/h3&gt;
&lt;p&gt;자신이 예외 처리를 하지 않고 자신을 호출한 곳에서 예외 처리를 하도록 던져버리는 것이다. &lt;code class=&quot;language-text&quot;&gt;throws&lt;/code&gt;문을 활용해서 예외 발생시 바로 던져버리거나, &lt;code class=&quot;language-text&quot;&gt;catch&lt;/code&gt;문으로 일단은 잡아 로그를 남기고 다시 예외를 던진다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SQLException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SQLException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SQLException&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// 로그 출력&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 출처: 토비의 스프링 3.1 Vol.1 p287&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;예외 전환&lt;/h3&gt;
&lt;p&gt;예외처리 회피와 같이 &lt;code class=&quot;language-text&quot;&gt;throws&lt;/code&gt;를 이용해서 자신을 호출한 곳에서 예외를 처리하도록 한다. 하지만, 예외처리 회피와 달리 적절한 다른 예외로 바꾸어 던진다는 특징이 있다.&lt;/p&gt;
&lt;p&gt;예외 전환은 보통 두 가지 목적으로 사용된다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;발생한 예외를 그대로 던지는 것이 예외 상황을 적절히 설명하지 못하는 경우, 더 구체적인 의미를 가진 예외로 바꾸기 위해 사용한다.&lt;/p&gt;
&lt;p&gt;예를 들어, 새로운 사용자를 등록하는데 이미 같은 아이디의 사용자가 존재하는 경우 &lt;code class=&quot;language-text&quot;&gt;SQLException&lt;/code&gt;이 발생한다. 하지만, 외부에 그대로 &lt;code class=&quot;language-text&quot;&gt;SQLException&lt;/code&gt;을 던져버리면 서비스 계층에서는 왜 &lt;code class=&quot;language-text&quot;&gt;SQLException&lt;/code&gt;이 발생했는지, 처리할 수 있는 것인지, 어떻게 처리할 지 등을 알 수 없다. 중복된 아이디에 대한 예외는 충분히 처리할 수 있기 때문에 적절한 예외로 바꾸어 던지는 것이 좋다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DuplicateUserIdException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SQLException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SQLException&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getErrorCode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MysqlErrorNumbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;ER_DUP_ENTRY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
         &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DuplicateUserIdException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
         &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 출처: 토비의 스프링 3.1 Vol.1 p289&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;예외 처리를 쉽고 단순하게 만들기 위해서 사용한다.&lt;/p&gt;
&lt;p&gt;주로 예외 처리를 강제하는 Checked Exception에서 Unchecked Exception으로 바꾸는 경우에 사용한다. 예외 복구를 할 수 없거나 비즈니스적으로 의미가 없는 Checked Exception이라면 빠르게 RuntimeException으로 바꿔서 던지는 편이 좋다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;발생한 예외를 다른 예외로 전환하는 경우, 원래 발생한 예외를 담아 중첩 예외를 만드는 것이 좋다. 중첩 예외는 &lt;code class=&quot;language-text&quot;&gt;getCause()&lt;/code&gt; 메소드를 이용해서 처음 발생한 예외가 무엇인지 파악할 수 있다.&lt;/p&gt;
&lt;h2&gt;JVM에서 예외를 처리하는 방법 (예외 발생 시 동작 방법)&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;예외가 발생하면 JVM은 Exception 객체를 생성한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Exception 객체가 생성되는 과정에서 &lt;code class=&quot;language-text&quot;&gt;fillInStackTrace&lt;/code&gt; 메소드가 호출된다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;fillInStackTrace&lt;/code&gt; 메소드 호출로 JVM은 예외 발생 시점의 호출 스택에서 각 스택 프레임 정보를 수집하고, 해당 정보가 Exception 객체의 스택 트레이스로 채워진다.&lt;/p&gt;
&lt;p&gt;이때 수집되는 스택 프레임의 정보로는 클래스 이름, 메소드 이름, 파일 이름, 라인 번호 등등이 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// 스택 트레이스 예시
Exception in thread &quot;main&quot; java.lang.NullPointerException: Cannot load from object array because &quot;BOJ2563.papers&quot; is null
  at BOJ2563.setUp(BOJ2563.java:45)
  at BOJ2563.main(BOJ2563.java:15)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;호출된 메소드의 스택을 역순으로 올라가면서(unwinding the stack) Exception을 처리할 수 있는 예외 처리 핸들러가 있는지 확인한다.&lt;/p&gt;
&lt;figure&gt;
   &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; margin-bottom: 16px;&apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/c71ac2635bfc89028b09808f9b2d2159/fe486/java-exception-stack-unwinding.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 56.470588235294116%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABzklEQVR42n1Si3KbMBD0/39Vp51pm5km46T1A2xeBmMDAkkg3thbnbCbTJv0NIsQ6FbavVvgFn3fo6oqVKrCOIxQjcI6tmAnO+wzFx4P4GscqiOaoTU5Vz3+jgU9pmkyZEVRIM9zcD0zwfDJ+oyv9jc8Rk/Y8A0sYWMltnBPPhpVf0xYliWCIJhveCPuhg6HOsKpTxG3Z8TdjIOKUA8NknOCLMvAOUfb3m58vc6E96APFFVZacIeh+KIkM8I8lCvIwQa/WWAFNLsb5oGSql/CclD+tG0DUpZwgkcI/m782CwPL1gyy08pz/hxB5KTUjRdR0YYyaX3v94SDLTNDVgGUMhObbFDl6li6EOCNsjoi7GXnqI2QlKq7gTCiHMPAzDq4dhGJpT6ro2vozTiLTMZsgMZ54gESnyusBFDzqU9lMu5fzXQ5KcFKmW/AXL+BmrfIN1sTGSV3wLOejCsQJSSlOQcRxfq0xSXdeF7/vwPC0njtFqoxlnWCYvsLkNW+heLB24yoNTu4iY7sW6wXuxIHa6MlWLQMUxRZoGPPpL/Ng/4ddxDSvbwWJ7ONKH6meJl8vl/T58G3QAeUgg6dQeNJNXJJHWggtTxLdS74S/AXQOR8ordqqxAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;java exception stack unwinding&apos; title=&apos;&apos; src=&apos;/static/c71ac2635bfc89028b09808f9b2d2159/ca1dc/java-exception-stack-unwinding.png&apos; srcset=&apos;/static/c71ac2635bfc89028b09808f9b2d2159/e7570/java-exception-stack-unwinding.png 170w,
/static/c71ac2635bfc89028b09808f9b2d2159/f46e7/java-exception-stack-unwinding.png 340w,
/static/c71ac2635bfc89028b09808f9b2d2159/ca1dc/java-exception-stack-unwinding.png 680w,
/static/c71ac2635bfc89028b09808f9b2d2159/fe486/java-exception-stack-unwinding.png 768w&apos; sizes=&apos;(max-width: 680px) 100vw, 680px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
   &lt;figcaption&gt;출처: https://www.geeksforgeeks.org/exceptions-in-java/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;만약 예외 처리 핸들러를 발견하지 못하면, JVM은 해당 스레드를 종료시키며, 메인 스레드에서 예외가 처리되지 않으면 프로그램도 종료된다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;예외 처리 비용&lt;/h2&gt;
&lt;p&gt;일반적으로 예외 처리 비용은 비싸다고 알려져 있다. 그럼 왜 비싸고, 얼마나 비싼 것일까?&lt;/p&gt;
&lt;p&gt;우선, Baeldung의 &lt;a href=&quot;https://www.baeldung.com/java-exceptions-performance&quot;&gt;Performance Effects of Exceptions in Java&lt;/a&gt; 글에서 성능 측정을 한 결과는 다음과 같았다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Benchmark&lt;/span&gt;                                                 &lt;span class=&quot;token class-name&quot;&gt;Mode&lt;/span&gt;  &lt;span class=&quot;token class-name&quot;&gt;Cnt&lt;/span&gt;    &lt;span class=&quot;token class-name&quot;&gt;Score&lt;/span&gt;   &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;  &lt;span class=&quot;token class-name&quot;&gt;Units&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;ExceptionBenchmark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;createExceptionWithoutThrowingIt       avgt   &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;16.605&lt;/span&gt; ± &lt;span class=&quot;token number&quot;&gt;0.988&lt;/span&gt;  ms&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;op
&lt;span class=&quot;token class-name&quot;&gt;ExceptionBenchmark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;doNotThrowException                    avgt   &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;    &lt;span class=&quot;token number&quot;&gt;0.047&lt;/span&gt; ± &lt;span class=&quot;token number&quot;&gt;0.006&lt;/span&gt;  ms&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;op
&lt;span class=&quot;token class-name&quot;&gt;ExceptionBenchmark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;throwAndCatchException                 avgt   &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;16.449&lt;/span&gt; ± &lt;span class=&quot;token number&quot;&gt;0.304&lt;/span&gt;  ms&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;op
&lt;span class=&quot;token class-name&quot;&gt;ExceptionBenchmark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;throwExceptionAndUnwindStackTrace      avgt   &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;326.560&lt;/span&gt; ± &lt;span class=&quot;token number&quot;&gt;4.991&lt;/span&gt;  ms&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;op
&lt;span class=&quot;token class-name&quot;&gt;ExceptionBenchmark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;throwExceptionWithoutAddingStackTrace  avgt   &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;    &lt;span class=&quot;token number&quot;&gt;1.185&lt;/span&gt; ± &lt;span class=&quot;token number&quot;&gt;0.015&lt;/span&gt;  ms&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;op&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 글과 &lt;a href=&quot;https://shipilev.net/blog/2014/exceptional-performance/&quot;&gt;The Exceptional Performance of Lil&apos; Exception&lt;/a&gt; 글에서의 결론은 다음과 같다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;예외가 발생하고 처리하는 과정은 일반적인 상황에 비해 더 많은 비용이 든다. 진정으로 예외가 필요한 곳에서만 예외 처리를 사용하자.&lt;/li&gt;
&lt;li&gt;try~catch문 자체는 성능에 큰 영향을 주지 않는다.&lt;/li&gt;
&lt;li&gt;예외 처리 비용의 대부분은 &lt;strong&gt;스택 트레이스를 구성하는 것&lt;/strong&gt;과 &lt;strong&gt;스택을 역순으로 따라가며 예외 처리 핸들러를 찾는 과정&lt;/strong&gt;에서 발생한다.&lt;/li&gt;
&lt;li&gt;스택 트레이스를 구성하는 데에 드는 비용은 Exception 객체가 생성되는 시점의 호출 스택 깊이에 비례한다.&lt;/li&gt;
&lt;li&gt;예외를 캐싱하거나 &lt;code class=&quot;language-text&quot;&gt;fillInStackTrace&lt;/code&gt; 메소드를 오버라이드함으로써 최적화를 이룰 수 있다. 스택 트레이스의 정보가 생성되지 않을 수 있기 때문에 매우 특수한 경우에만 진행해야 한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;(번외) Checked Exception에 대한 이슈&lt;/h2&gt;
&lt;p&gt;개발자에게 예외 처리를 강제하는 Checked Exception에 대한 이슈가 있다.&lt;/p&gt;
&lt;p&gt;무조건 예상되는 예외를 처리하도록 하여 서비스의 안정성을 도모하고자 했지만, 이를 귀찮게 느낀 개발자들은 &lt;code class=&quot;language-text&quot;&gt;catch&lt;/code&gt;문으로 잡아만 두고 아무런 처리도 하지 않는다거나, 의미 없이 &lt;code class=&quot;language-text&quot;&gt;throws Exception&lt;/code&gt;만 한다는 것이다. Checked Exception이 처음 등장했을 때와 다르게 최근에는 Unchecked Exception을 사용하자는 의견이 많아지고 있다고 한다.&lt;/p&gt;
&lt;p&gt;더 자세한 내용은 아래 글을 참고하자.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://velog.io/@eastperson/Java%EC%9D%98-Checked-Exception%EC%9D%80-%EC%8B%A4%EC%88%98%EB%8B%A4-83omm70j&quot;&gt;https://velog.io/@eastperson/Java의-Checked-Exception은-실수다-83omm70j&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;참고 자료&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;토비의 스프링 3.1 Vol.1 4장&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.oracle.com/javase/specs/jls/se22/jls22.pdf&quot;&gt;https://docs.oracle.com/javase/specs/jls/se22/jls22.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.oracle.com/javase/specs/jvms/se22/jvms22.pdf&quot;&gt;https://docs.oracle.com/javase/specs/jvms/se22/jvms22.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/36343209/which-part-of-throwing-an-exception-is-expensive&quot;&gt;https://stackoverflow.com/questions/36343209/which-part-of-throwing-an-exception-is-expensive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.baeldung.com/java-exceptions-performance&quot;&gt;https://www.baeldung.com/java-exceptions-performance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://shipilev.net/blog/2014/exceptional-performance/&quot;&gt;https://shipilev.net/blog/2014/exceptional-performance/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://meetup.nhncloud.com/posts/47&quot;&gt;https://meetup.nhncloud.com/posts/47&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item></channel></rss>