<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>m_jae.log</title>
        <link>https://velog.io/</link>
        <description>하고싶은게 많은 대학생입니다 :)</description>
        <lastBuildDate>Tue, 23 Jan 2024 12:54:39 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>m_jae.log</title>
            <url>https://velog.velcdn.com/images/m_jae/profile/9983e26d-dcb1-485e-ba72-d79cf2432097/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. m_jae.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/m_jae" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[ArchitecturePattern(아키텍쳐패턴)& DesignPattern(디자인패턴)]]></title>
            <link>https://velog.io/@m_jae/ArchitecturePattern%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90%ED%8C%A8%ED%84%B4-DesignPattern%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@m_jae/ArchitecturePattern%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90%ED%8C%A8%ED%84%B4-DesignPattern%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Tue, 23 Jan 2024 12:54:39 GMT</pubDate>
            <description><![CDATA[<p>처음 아키텍쳐라는 말을 접했을때 초보자인 나에게 굳이 그것까지 알아야 할까? 라는 의구심이 들었다. 그러나 처음 개념을 잡고 간다면, 매우 유용하다고 주변에서 들었다. 그래서 WeGoToghether의 두번째 주제인 아키텍쳐패턴 과 디자인패턴 대해 알아보려고 한다. </p>
<p>내용에 대해 작성하기 전에 저희 WeGoToghether 회장님이 만드신 자료를 올려두겠습니다.
<a href="%5Bhttps://www.notion.so/Sprint-1-1-22-1-29-5218c96a5b2b4291a53984721e6606a2?pvs=4#c2b2a290e49e4861a544439d66f56f50%5D">송하영의 노션</a></p>
<ul>
<li>아키텍쳐란? 시스템을 구축했던 사람들이 만들어낸 시스템의 형태<h1 id="architecture패턴">Architecture패턴</h1>
</li>
</ul>
<h3 id="architecturepattern을-사용하는-이유">ArchitecturePattern을 사용하는 이유</h3>
<p>현대로 올수록 협업 하는 일이 많아 지고 있습니다. 이럴 경우 많은 개발자들과 소통하는 경우가 많습니다. 그렇기에, 우리는 아키텍쳐 패턴을 통해 구조화할 필요가 있습니다.
코드의 분리 및 조직화 , 유연성 및 확장성 , 재사용성 향상 , 테스트 용이성 , 성능최적화 등 ... 즉, 개발 프로세스를 더 효율적으로 향상 시키기 위한 존재</p>
<h1 id="아키텍쳐-패턴">아키텍쳐 패턴</h1>
<ul>
<li>아키텍쳐 패턴은 아키텍쳐 설계단계에서 정보를 분류하는 기준과 각 정보간의 연결 방법을 제시한다.</li>
<li>소프트웨어의 구조를 패턴화 한 것을 의미함</li>
</ul>
<p>한마디로!! 아키텍쳐 설계 도구라고 볼 수 있다!!</p>
<h1 id="디자인-패턴">디자인 패턴</h1>
<p>숙련된 개발자가 프로그래밍을 진행하다보면, 자주 익숙한 문제를 마주치게 된다. 다른 개발자들도 마찬가지로 그러한 경험을 한다. 그러니 모두가, 동일하게 겪는 뻔한 문제에 대한 일반적인 해결책을 정의하고 그에 명칭을 붙여 필요할 때마다 사용하는 것의 필요성을 느끼게 된다. 그런 필요에 의해 정의된 일반적인 해결책들이 바로 <strong>디자인 패턴</strong>이다.</p>
<p>디자인 패턴은 주로 객체지향 프로그래밍에서 사용되며, 코드의 유연성, 확장성, 재사용성을 증가시키는데 목적이 있다. 또한 앞선 개발자들이 겪었던 실패를 건너뛰어 작업 시간을 단축시켜주는 편리한 도구이다</p>
<p>한마디로!! 디자인 패턴은 실제 코드 작성에서 마주치는 문제들에 대한 일반적인 풀이를 제시한다.</p>
<p><a href="https://www.linkedin.com/pulse/architectural-pattern-vs-design-praveen-kumar-kushwaha/">링크텍스트</a>
위의 원문을 의역해서 적어보았다.</p>
<h1 id="아키텍쳐-패턴-vs-디자인-패턴">아키텍쳐 패턴 VS 디자인 패턴</h1>
<p>아키텍쳐 패턴과 디자인 패턴은 매우 가깝게 연관되어 있기에, 두개를 비교하는데 많은 혼란을 겪곤 한다. 밑에서 두가지의 유사성과 다른점에 대해 알아보자.</p>
<ul>
<li>아키텍쳐 패턴은 디자인 패턴보다 더 큰 의미를 가진다. 디자인 패턴은 구체적인 소프트웨어와 관련된 일을 제공하는 반면, 아키텍쳐 패턴은 비지니스 문제를 위한 해결책을 제공한다. 다시 말하면 아키텍쳐 패턴은 추상적인 관점에 중점을 둔다면, 디자인 패턴은 구현관점에 중점을 둔다.</li>
<li>디자인 패턴의 구현은 낮은 수준에서 정의된 반면 , 아키텍쳐 패턴은 높은 수준에서 정의된다. 즉, 동일한 아키텍쳐 패턴이라도 프로젝트마다 많이 다를 수 있다.</li>
<li>하나의 아키텍쳐 패턴은 많은 디자인 패턴을 사용하여 구현 될 수 있다.</li>
</ul>
<h1 id="아키텍쳐-패턴과-디자인-패턴의-특징">아키텍쳐 패턴과 디자인 패턴의 특징</h1>
<p>개발자에게는 <strong>아키텍쳐 패턴</strong>을 사용한 아키텍쳐 설계가 작업 능률을 향상시키고, 수정 유연성을 확보하며 완성도를 보장해준다.</p>
<p><strong>디자인 패턴</strong> 사용은 개발 속도를 단축해주고 빠른 시간 내에 앞선 이들의 지혜를 습득시켜 준다. (그러나 디자인 패턴은 우리가 어떤 도메인을 가지고 어떤 문제를 풀이하고 있는지 고려해주지 않는다.)</p>
<p>설명을 아주 쉽게 설명해준 보노님의 블로그링크!!
<a href="https://velog.io/@haeun_/%EC%86%8C%EC%84%A4%EA%B0%80%EC%9D%98-%EC%9E%85%EC%9E%A5%EC%97%90%EC%84%9C-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90-%ED%8C%A8%ED%84%B4-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4#%EC%8B%9C%EB%82%98%EB%A6%AC%EC%98%A4-%EC%9E%91%EC%84%B1%EC%9D%98-%EB%BC%88%EB%8C%80">보노님블로그</a></p>
<p>조금 헷갈린게 있다면 mvc,mvp,mvvm등은 디자인 패턴인줄 알았으나,
아키텍쳐 패턴 이었다는점...!!
다음 포스팅에서는 패턴의 종류에 대해 작성할게요!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[4. 보안측면]]></title>
            <link>https://velog.io/@m_jae/4.-%EB%B3%B4%EC%95%88%EC%B8%A1%EB%A9%B4-1f9dfb05</link>
            <guid>https://velog.io/@m_jae/4.-%EB%B3%B4%EC%95%88%EC%B8%A1%EB%A9%B4-1f9dfb05</guid>
            <pubDate>Mon, 08 Jan 2024 09:13:23 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/m_jae/post/fbdf9756-f567-4421-ac19-f8062c34b1bc/image.jpeg" alt=""></p>
<h2 id="4-보안측면">4. 보안측면</h2>
<h2 id="4-1-https-와-ssl--tls--데이터-전송의-보안">4-1 HTTPS 와 SSL / TLS : 데이터 전송의 보안</h2>
<p>HTTPS</p>
<ul>
<li>HTTP Secure 혹은 HTTP over SSL/TLS</li>
<li>HTTP와 달리 HTTPS는 전송 데이터를 암호화한다.</li>
</ul>
<p>HTTPS의 장점</p>
<ul>
<li>통신하고자 하는 서버가 신뢰할 수 있는 서버인지 판별할 수 있다.</li>
<li>통신 과정에서 데이터가 노출될 가능성이 적다.</li>
</ul>
<p>SSL/TLS를 알아보기 전에 이들이 사용하는 암호화 방법에 대해 간략하게 알아보고 넘어가도록 하겠습니다.
대칭키 암호화 / 공개키 암호화</p>
<ul>
<li>대칭키 암호화 - 하나의 키로 암호화 및 복호화를 진행하는 과정
  이는 빠르다는 장점이 있지만 누군가가 중간에 키를 가로채게 되면 해킹의 위험이 있다.</li>
<li>공개키 암호화 - 서로 다른 두키(공개키,개인키)로 암호화 복호화 하는 과정을 거치게 된다.
  공개키: 누구나 가질 수 있는키 , 개인키: 소유자 한명만 가질 수 있다.
  이를 통해 안전하게 암호화가 가능하지만, 속도 측면에서 느리다.
  <img src="https://velog.velcdn.com/images/m_jae/post/a536ac86-a47c-41d8-b353-b75f6b52e25e/image.png" alt=""></li>
</ul>
<p>SSL</p>
<ul>
<li>SSL(Secure Scokets Layer)은 암호화 기반 인터넷 보안 프로토콜이다. 전달되는 모든 데이터를 암호화하고 특정한 유형의 사이버 공격도 차단한다. SSL은 TLS(Transport Layer Security) 암호화의 전신이기도 한다.</li>
</ul>
<p>TLS</p>
<ul>
<li>TLS 는 SSL의 업데이트 버전으로 SSL의 최종버전인 3.0과 TLS의 최초버전의 차이는 크지않으며, 이름이 바뀐것은 SSL을 개발한 Netscape가 업데이트에 참여하지 않게 되어 소유권 변경을 위해서였다고 한다.
결과적으로 TLS는 SSL의 업데이트 버전이며 명칭만 다르다고 볼 수 있다.</li>
</ul>
<p>SSL 인증서와 SSL Handshake에 탑재된 기술</p>
<ul>
<li>하나의 키로 암호화/복호화를 수행하는 대칭키 암호화 방식</li>
<li>한 쌍의 키 페어로 암호화/복호화를 수행하는 비대칭키 암호화 방식</li>
<li>통신 대상을 서로가 확인하는 신분 확인</li>
<li>믿을 수 있는 SSL 인증서를 위한 디지털 서명</li>
<li>디지털 서명을 해주는 인증 기관 (CA)</li>
<li>공개키를 안전하게 전달하고 공유하기 위한 프로토콜</li>
<li>암호화된 메세지의 변조 여부를 확인하는 메세지 무결성 알고리즘</li>
</ul>
<p><img src="https://velog.velcdn.com/images/m_jae/post/554cbc41-131f-4eb7-bc84-ae2f01519772/image.png" alt=""></p>
<p>실제 데이터는 대칭키 방식으로 암호화를 하고
대칭키의 키를 공개키 방식으로 암호화한다.</p>
<p>컴퓨터와 컴퓨터가 네트워크를 이용하여 통신을 할 때는 내부적으로 악수, 세션, 세션 종료 이렇게 3가지 단계가 있다.</p>
<p>1) 악수 (handshake)</p>
<ul>
<li>사람과 사람이 소통을 할 때 먼저 악수를 하듯,</li>
<li>SSL 방식을 이용하여 통신을 하는 브라우저와 서버 역시 악수(handshake)를 한다.</li>
</ul>
<p>① 클라이언트가 서버에 접속한다. (Client Hello)
 이 단계에서 다음과 같은 정보들을 서버로 전송한다.</p>
<ul>
<li>클라이언트 측에서 생성한 랜덤 데이터</li>
<li>클라이언트가 지원하는 암호화 방식</li>
<li>세션 아이디</li>
</ul>
<p>② 서버는 Client Hello에 대한 응답으로 Server Hello를 한다.
다음과 같은 정보들을 클라이언트로 전송한다.</p>
<ul>
<li>서버 측에서 생성한 랜덤 데이터</li>
<li>서버가 선택한 암호화 방식</li>
<li>인증서</li>
</ul>
<p>③ 클라이언트는 서버의 인증서를 발급한 CA가 자신이 내장한 CA의 리스트에 있는지 확인한다.
확인 결과 서버를 통해서 다운받은 인증서가 내장된 CA 리스트에 포함되어 있다면
해당 CA의 공개키를 이용해서 암호화되어있는 인증서를 복호화한다.</p>
<p>위에서 언급했듯 비공개키로 암호화된 인증서를 공개키로 복호화한다는 것은
인증서는 CA의 개인키로 암호화된 문서임이 암시적으로 보증된 것이다.</p>
<p>즉, 클라이언트는 인증서를 전송한 서버를 믿을 수 있게 된 것이다.
<strong>복호화를 통해 클라이언트는 인증서에 들어있는 서버 공개키를 획득한다.</strong></p>
<p>④ 클라이언트는 주고받은 랜덤 데이터를 조합해 pre master secret이라는 키를 생성한다.
아까 인증서에서 복호화해낸 서버의 공개키로 pre master secret 키를 암호화해서 서버로 전송하면
서버는 자신의 비공개키로 pre master secret키를 복호화한다.
이제 클라이언트, 서버 둘 다 pre master secret키를 가지고 있게 된다.</p>
<p>⑤ 서버와 클라이언트 모두 pre master secret을 일련의 과정을 거쳐서 master secret으로 만든다.
 이렇게 만든 master secret으로  session key를 생성한다.</p>
<p>⑥ 핸드쉐이크 단계의 종료를 서로에게 알린다.</p>
<p>2) 세션
서버와 클라이언트가 실제로 데이터를 주고받는 단계이다.
정보를 세션키값을 이용해 대칭키 방식으로 암호화해서 전송한다.</p>
<p>3) 세션 종료
데이터 전송이 끝나면 SSL 통신이 끝났음을 서로에게 알려주고 세션키는 폐기한다.</p>
<p><a href="https://study-recording.tistory.com/11">링크텍스트</a></p>
<h2 id="4-2-csrfcross-site-request-forgery와-xsscross-site-scripting-공격방지">4-2 CSRF(Cross-Site-Request-Forgery)와 XSS(Cross-Site Scripting) 공격방지</h2>
<h2 id="1csrf">1.CSRF</h2>
<p>CSRF(cross-site-request-forgery) 의 줄임말로 웹 취약점 중 하나이다.
공격자가 희생자의 권한을 도용하여 특정 웹 사이트의 기능을 실행하게 할 수 있으며 이는 희생자의 의도와는 무관하게 이루어진다.</p>
<p>우선 몇가지 조건이 갖춰져야 한다.
     - 희생자가 공격자가 만든 피싱 사이트에 접속할 것
    - 희생자가 위조 요청을 보낼 사이트에 로그인 되어 있을 것</p>
<p>이러한 전제 조건이 필요한 이유는 CSRF는 직접적으로 공격을 하는것이 아니라 하나의 희생양을 통해 대신 공격하게끔 설정 하기 때문이다.</p>
<p><img src="https://velog.velcdn.com/images/m_jae/post/f4e5ce1b-8d3e-400b-820b-7101ca1ac031/image.png" alt=""></p>
<ol>
<li>희생양이 로그인이 되어 있는채로 피싱사이트에 접근</li>
<li>해당 페이지에서 희생양이 악성행위를 하도록 하는 행위가 전달 됨</li>
<li>서버에서는 이 행위를 전달 받을때, 희생양의 쿠키에 들어있는 sessionId를 확인하게 되는데, 이것이 유효하다고 판단하고, 행동을 실행 한다.</li>
</ol>
<p>핵심 개념
쿠키에 sessionid를 이용하는 것이다. 서버는 클라이언트의 쿠키 헤더에 들어있는 sessionid가 유효한지를 판단하는 허점을 파고 든것이다.</p>
<p><a href="https://devscb.tistory.com/123">링크텍스트</a></p>
<h2 id="2xss">2.XSS</h2>
<p>다른 공격방법과 다르게 클라이언트를 공격하는 기법이다. CSS가 맞는 표기법이지만 이미 약어로 사용되어 있기에 XSS로 표기한다.
<img src="https://velog.velcdn.com/images/m_jae/post/ed41d6a1-b8dc-4906-817d-dd6bdf68840a/image.png" alt=""></p>
<p>여기에는 3가지 방식이 존재한다.</p>
<p>Reflected XSS </p>
<ul>
<li>공격자가 악성 스크립트를 클라이언트에게 직접 전달하여 공격하는 방식이다.
<img src="https://velog.velcdn.com/images/m_jae/post/4391478b-3303-4582-88f9-59893f2bd1f2/image.png" alt="">
공격자는 악성스크립트가 포함된 URL을 이메일, 메신저 등을 통해 사용자가 클릭할 수 있도록 유도한다. 사용자가 악성스크립트가 삽입된 URL을 클릭하거나 공격자에 의해 악의적으로 조작된 게시물을 클릭했을 때 사용자의 브라우저에서 악성스크립트가 실행된다.</li>
</ul>
<p>Stored XSS</p>
<ul>
<li>공격자의 악성스크립트가 데이터베이스에 저장되고 이 값을 출력하는 페이지에서 피해가 발생한다.
<img src="https://velog.velcdn.com/images/m_jae/post/f996ddc4-36bf-4259-b069-4b8adff5d975/image.png" alt=""></li>
</ul>
<p>공격자는 악성스크립트가 포함된 게시물을 작성하여 게시판 등 사용자가 접근할 수 있는 페이지에 업로드한다. 이때 사용자가 악성스크립트가 포함된 게시물을 요청하면, 공격자가 삽입한 악성스크립트가 사용자 측에서 동작하게 된다.</p>
<p>공격자의 악성스크립트가 서버에 저장되어 불특정 다수를 대상으로 공격에 이용될 수 있어 Reflected XSS보다 공격 대상의 범위가 훨씬 크다.</p>
<p>Dom Based XSS</p>
<ul>
<li>공격자의 악성스크립트가 DOM 영역에서 실행됨으로써 서버와의 상호작용 없이 브라우저 자체에서 악성스크립트가 실행되는 취약점이다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/m_jae/post/848911be-7c63-41d4-b9af-9309ae2fa74b/image.png" alt=""></p>
<p> DOM 영역에 변화가 생기면 브라우저는 서버로 패킷을 보내지 않고 DOM 영역에서 페이지를 변환시킨다. 따라서 DOM의 일부로 실행되기 때문에 브라우저 자체에서 악성스크립트가 실행된다.</p>
<p>여기서 DOM이란?</p>
<ul>
<li>Document Object Model의 약자로, HTML요소를 JavaScript Object처럼 조작할 수 있는 Model이다.</li>
<li>HTML의 작은 부분까지 접근할 수 있는 구조로, DOM을 이용하여 HTML로 구성된 웹페이지를 동적으로 움직이게 만들 수 있다.
<img src="https://velog.velcdn.com/images/m_jae/post/ab8a72a7-1443-4572-be47-3675160b93b7/image.png" alt="">
DOM의 구조는 트리구조로, body가 가장 상위에 있고, 아래에 여러 구성요소가 부모-자식 관계를 가지고 있다.</li>
</ul>
<p><a href="https://www.fis.kr/ko/major_biz/cyber_safety_oper/attack_info/security_news?articleSeq=3408">링크텍스트</a></p>
<h2 id="3입력-데이터-검증과-취약점-방지">3.입력 데이터 검증과 취약점 방지</h2>
<p>위에서 알아본 공격들에 대비책들이 필요할것이다.</p>
<p>SQL 삽입</p>
<ul>
<li>웹 응용 프로그램에 SQL을 삽입하여 내부 데이터베이스 서버의 데이터 유출 변조, 관리자 인증 우회</li>
<li>동적 쿼리에 사용되는 입력 데이터에 예약어 및 특수문자를 입력되지 않게 함으로 방지</li>
</ul>
<p>경로 조작 및 삽입</p>
<ul>
<li>데이터 입출력 경로 조작하여 서버 자원 수정 및 삭제</li>
<li>경로 순회 공격을 막는 필터 사용으로 방지</li>
</ul>
<p>크로스사이트 스크립팅(XSS)</p>
<ul>
<li>웹 페이지에 악의적인 스크립트 삽입, 방문자의 정보 탈취</li>
<li>HTML 태그 제한, 특수 문자를 다른 문자로 치환함으로 방지</li>
</ul>
<p>운영체제 명령어 삽입</p>
<ul>
<li>외부 입력값을 통해 시스템 명령어의 실행을 유도함으로써 권한 탈취, 시스템 장애를 유발하는 보안 약점</li>
<li>시스템 명령 전달 X, 외부 입력값 검증 없이 내부 명령어 사용하지 않음으로 방지</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[3.프론트엔드와 백엔드 상호작용]]></title>
            <link>https://velog.io/@m_jae/3.%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%EC%99%80-%EB%B0%B1%EC%97%94%EB%93%9C-%EC%83%81%ED%98%B8%EC%9E%91%EC%9A%A9</link>
            <guid>https://velog.io/@m_jae/3.%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%EC%99%80-%EB%B0%B1%EC%97%94%EB%93%9C-%EC%83%81%ED%98%B8%EC%9E%91%EC%9A%A9</guid>
            <pubDate>Mon, 08 Jan 2024 09:11:46 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/m_jae/post/7cc60814-efe5-4d9b-98da-1c951e47f3ae/image.jpeg" alt=""></p>
<h2 id="3프론트엔드와-백엔드-상호작용">3.프론트엔드와 백엔드 상호작용</h2>
<h2 id="3-1-restful-api--클라이언트와-서버-간의-통신-규약"><em><strong>3-1 RESTful API : 클라이언트와 서버 간의 통신 규약</strong></em></h2>
<p><img src="https://velog.velcdn.com/images/m_jae/post/bc0c7d8d-fde3-482f-b50d-34f1b793fe87/image.png" alt="">
<strong>REST API 란</strong></p>
<ul>
<li>REST API 에서 REST는 Representational State Transfer 의 약자로 소프트웨어 프로그램 아키텍처의 한 형식 입니다.</li>
<li>즉, 자원을 이름 (자원의 표현) 으로 구분하여 해당 자원의 상태 (정보)를 주고 받는 모든 것을 의미한다.</li>
<li>월드 와이드 웹 (WWW) 과 같은 분산 하이퍼미디어 시스템을 위한 소프트웨어 개발 아키텍처의 한 형식</li>
</ul>
<p><strong>구체적인 개념</strong></p>
<ul>
<li>HTTP URI를 통해 자원을 명시하고, HTTP Method (POST, GET, PUT, DELETE)를 통해 해당 자원에 대한 CRUD OPERATION을 적용하는 것을 의미한다.</li>
<li>즉, REST는 자원 기반의 구조 (ROA: Resource Oriented Architecture) 설계의 중심에 Resoure가 있고 HTTP Method를 통해 Resource를 처리하도록 설계된 아키텍쳐를 의미한다.</li>
<li>웹의 모든 자원에 고유한 ID인 HTTP URI 를 부여한다.</li>
</ul>
<p><strong>RESTful APIs를 만드는 이유</strong></p>
<ul>
<li>RESTful APIs 개발하는 가장 큰 이유는 Client Side를 정형화된 플랫폼이 아닌 모바일, PC, 어플리케이션 등 플랫폼에 제약을 두지 않는 것을 목표로 했기 때문 입니다.</li>
<li>즉, 2010년 이전만 해도 Server Side에서 데이터를 전달해주는 Client 프로그램의 대상은 PC 브라우저로 그 대상이 명확 했다. 그렇다 보니 그냥 JSP ASP PHP 등을 잉요한 웹페이지를 구성하고 작업을 진행하면 됐다.</li>
<li>하지만 스마트 기기들이 등장하면서 TV, 스마트 폰, 테블릿 등 Client 프로그램이 다양화 되고 그에 맞춰 Server를 일일이 만다는 것이 꽤 비효율적인 일이 되어 버렸다.</li>
<li>이런 과정에서 개발자들은 Client Side를 전혀 고려하지 않고 메시지 기반, XML, JSON과 같은 Client에서 바로 객체로 치환 가능한 형태의 데이터 통신을 지향하게 되면서 Server와 Client의 역할을 분리하게 되었다.</li>
</ul>
<blockquote>
<p>이런 변화를 겪으면서 필요해진 것은 HTTP 표준 규약을 지키면서 API를 만드는 것이다.</p>
</blockquote>
<p><strong>REST의 구성</strong></p>
<p>자원(Resource) - URL
행위(Verb) - Http Method
표현(Representations)</p>
<p><strong>1. 자원 (Resource) URL</strong></p>
<ul>
<li>모든 자원에 고유한 ID가 존재하고, 이 자원은 Server에 존재한다.</li>
<li>자원을 구별하는 ID는 /orders/order_id/1 와 같은 HTTP URI 이다.</li>
</ul>
<p><strong>2. 행위 (Verb) - Http Method</strong></p>
<ul>
<li>HTTP 프로토콜의 Method를 사용한다.</li>
<li>HTTP 프로토콜은 GET, POST, PUT, DELETE와 같은 메서드를 제공한다.</li>
</ul>
<p><strong>3. 표현 (Representaion of Resource)</strong></p>
<ul>
<li>Client가 자원의 상태 (정보)에 대한 조작을 요청하면 Server는 이에 적절한 응답 (Representation)을 보낸다</li>
<li>REST에서 하나의 자원은 JSON, XML, TEXT, RSS 등 여러 형태의 Representation으로 나타낼 수 있다.</li>
<li>현재는 JSON으로 주고 받는 것이 대부분이다.</li>
</ul>
<p><strong>REST 특징</strong></p>
<p>a. 클라이언트 / 서버 구조</p>
<p>클라이언트는 유저와 관련된 처리를, 서버는 REST API를 제공함으로써 각각의 역활이 확실하게 구분되고 일괄적인 인터페이스로 분리되어 작동할 수 있게 한다.
REST Server: API를 제공하고 비지니스 로직 처리 및 저장을 책임진다.
Client: 사용자 인증이나 context (세션, 로그인 정보) 등을 직접 관리하고 책임진다.
서로 간 의존성이 줄어든다.</p>
<p>b. 무상태성 (Stateless)</p>
<p>REST는 HTTP의 특성을 이용하기 떄문에 무상태성을 갖는다.
즉 서버에서 어떤 작업을 하기 위해 상태정보를 기억할 필요가 없고 들어온 요청에 대해 처리만 해주면 되기 때문에 구현이 쉽고 단순해진다.</p>
<p>c. 캐시 처리 가능 (Cacheable)</p>
<p>HTTP라는 기존 웹표준을 사용하는 REST의 특징 덕분에 기본 웹에서 사용하는 인프라를 그대로 사용 가능하다.
대량의 요청을 효율적으로 처리하기 위해 캐시가 요구된다.
캐시 사용을 통해 응답시간이 빨라지고 REST Server 트랜잭션이 발생하지 않기 때문에 전체 응답시간, 성능, 서버의 자원 이용률을 향상 시킬 수 있다.</p>
<p>d. 자체 표현 구조 (Self - descriptiveness)</p>
<p>JSON을 이용한 메시지 포멧을 이용하여 직관적으로 이해할 수 있고 REST API 메시지만으로 그 요청이 어떤 행위를 하는지 알 수 있다.</p>
<p>e. 계층화 (Layered System)</p>
<p>클라이언트와 서버가 분리되어 있기 때문에 중간에 프록시 서버, 암호화 계층 등 중간매체를 사용할 수 있어 자유도가 높다</p>
<p>f. 유니폼 인터페이스 (Uniform)</p>
<p>Uniform Interface는 Http 표준에만 따른다면 모든 플랫폼에서 사용이 가능하며, URI로 지정한 리소스에 대한 조작을 가능하게 하는 아키텍쳐 스타일을 말한다
URI로 지정한 Resource에 대한 조작을 통일되고 한정적인 인터페이스로 수행한다.
즉, 특정 언어나 기술에 종속되지 않는다.</p>
<h2 id="3-2--graphql--api-쿼리에-대한-기본-이해"><strong>3-2  GraphQL : API 쿼리에 대한 기본 이해</strong></h2>
<p>GraphQL 은 한 문장으로 얘기하자면 페이스북에서 만든 API 를 위한 쿼리 언어 라고 할 수 있다.</p>
<p>GraphQL 은 웹 클라이언트가 데이터를 서버로부터 효율적으로 가져오는 것이 목적인 쿼리 언어이고,
SQL 은 데이터베이스 시스템에 저장된 데이터를 효율적으로 가져오는 것이 목적인 쿼리 언어이다.</p>
<p><strong>URL 엔드포인트</strong>
REST API 는 URL + METHOD 를 조합하기 때문에 정말 다양한 엔드포인트가 존재하지만,
GraphQL 은 엔드포인트가 하나만 존재한다. (/graphql)</p>
<p>하나의 엔드포인트를 가지고, 쿼리 조합을 통해 데이터를 요청한다.</p>
<p>X) Book, Library 에 대한 API 를 설계할 때</p>
<p>REST API 의 경우
/library/book
/library
/library/book/{id}
처럼 설계해야 하지만</p>
<p>GrahpQL 의 경우에는 /graphql 엔드포인트에 요청에 따라 쿼리로 조합해서 요청하면 되기 때문에 API 가 점점 늘어남에 따라 URL 을 설계하고 만들어주지 않아도 된다.</p>
<pre><code>query {
    library {
        book {
            name
        }
       }
}
</code></pre><p><strong>response 데이터</strong>
REST API 의 경우 return 되는 response 데이터가 정해져 있다.
그렇기 때문에 이전 API response 에 다른 컬럼들이 추가되면 해당 파일을 계속 수정해줘야하고, API 별로 response 가 다 다르면 그에 따른 DTO 를 각각 다 만들어줘야 한다.</p>
<p>하지만, GraphQL 은 쿼리로 요청하기 때문에 클라이언트가 원하는 데이터를 쏙쏙 뽑아 커스터마이징 해서 사용할 수 있다 !</p>
<p>EX) 전체 책을 가져오는 API 에서는 id, title 만 return 하고 아이디별 책을 가져오는 API 에서는 id, title, content 를 가져와야 할 때</p>
<p>REST API 의 경우</p>
<pre><code>class BookDTO {
    Long id;
    String title;
}

class BookDTO2 {
    Long id;
    String title;
    String content;
}</code></pre><p>이렇게 DTO 를 2개 만들고 return 해주거나 ... 아니면 다른 방식을 사용해야하는다.</p>
<p>하지만, Graphl 에서는 Book 모델에 데이터가 있으면 클라이언트에서 커스터마이징하게 요청해서 사용할 수 있다
<a href="https://velog.io/@somday/RESTful-API-%EC%9D%B4%EB%9E%80">링크텍스트</a></p>
<p><strong>GraphQL 구조</strong>
GraphQL 은 객체에 대한 특정 필드를 매우 간단하게 요청할 수 있다.</p>
<pre><code>{
    hero {
        name
    }
}</code></pre><p>이 쿼리를 간단하게 설명하자면 hero 객체에 대해서 name 필드 데이터를 리턴해줘라 인데 이렇게 요청하면 아래과 같은 결과가 나오게 된다.</p>
<pre><code>{
    &quot;data&quot;: {
        &quot;hero&quot;: {
            &quot;name&quot;: &quot;R2-D2&quot;
        }
    }
}</code></pre><p>graphql 의 특징 중 하나인데 결과는 요청한 양식과 동일하게 리턴된다.</p>
<p>자세한 GraphQL의 구조는 아래링크를 참조하면 좋을 듯 하다.
[링크텍스트](<a href="https://velog.io/@soyeon207/GraphQL-GraphQL-%EC%9D%B4%EB%9E%80">https://velog.io/@soyeon207/GraphQL-GraphQL-%EC%9D%B4%EB%9E%80</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2. 데이터베이스와 사용자 데이터 관리]]></title>
            <link>https://velog.io/@m_jae/2.-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4%EC%99%80-%EC%82%AC%EC%9A%A9%EC%9E%90-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B4%80%EB%A6%AC</link>
            <guid>https://velog.io/@m_jae/2.-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4%EC%99%80-%EC%82%AC%EC%9A%A9%EC%9E%90-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B4%80%EB%A6%AC</guid>
            <pubDate>Mon, 08 Jan 2024 09:10:37 GMT</pubDate>
            <description><![CDATA[<h2 id="2-데이터베이스와-사용자-데이터-관리">2. 데이터베이스와 사용자 데이터 관리</h2>
<h2 id="2-1-사용자-데이터-모델링--사용자-정보의-데이터베이스-구조-설계"><em><strong>2-1 사용자 데이터 모델링 : 사용자 정보의 데이터베이스 구조 설계</strong></em></h2>
<p>데이터 모델링의 세가지 관점:</p>
<ol>
<li>데이터 관점 : 업무와 데이터, 데이터간의 관계성</li>
<li>프로세스 관점 : 업무가 실제로, 무엇을 하는지</li>
<li>데이터와 프로세스의 상관관점 : 처리하는 일의 방법에 따라 데이터가 어떤 영향을 받고 있는지
여기서 모델링을 하는것은 데이터 관점이다.</li>
</ol>
<ul>
<li><p>데이터 모델링의 중요성 및 유의점
: 잘못된 데이터 모델링으로 인한 변경 작업으로 전체 시스템에 큰 영향을 미칠 수 있다는 것
복합한 정보 요구사항의 간결한 표현
: 간결한 데이터 모델링은 사용자들이 파악하기 쉽고 빠르다.
데이터 품질
: 데이터 보관 기간 ↑ 가치 ↑ ( 활용을 많이 하게 되기 때문)</p>
</li>
<li><p>데이터 모델링의 3단계 진행
추상화 수준에 따라 <strong>개념적, 논리적, 물리적</strong> 데이터 모델링</p>
</li>
</ul>
<p><strong>개념적</strong> 데이터 모델링
추상화 수준이 높고 업무 중심적이며 포괄적인 수준의 모델링.</p>
<p>조직, 사용자의 요구사항 분석 -&gt; 핵심 엔티티와 관계성을 반결 -&gt; 엔티티 관계 다이어그램 생성.
시스템 기능에 대해 논의할 수 있는 기반을 형성하며 데이터 요구사항을 발견하는 것을 지원하는 단계.</p>
<p><strong>논리적</strong> 데이터 모델링
업무의 구체적인 모습과 흐름에 따른 구체화된 업무 중심의 데이터 모델링.</p>
<p>key, 속성, 관계 등을 정확하게 표현하며 재사용성↑
비즈니스 정보와 논리적인 구조와 규칙을 명확하게 표현
비즈니스 데이터에 존재하는 사실들을 인식, 기록함
신뢰성있는 데이터 구조를 얻기 위해 일관성을 확보, 중복 제거, 엔티티 속성 적절함을 고려한다.
식별자 확정, 정규화, m:m 관계 해소, 참조 무결성 규칙 정의 등으로 모델을 상세화 한다.</p>
<p><strong>물리적</strong> 데이터 모델링
실제 DB의 저장구조에 따른 테이블 스페이스, 성능 등 물리적인 성격을 고려하여 설계.</p>
<p>물리적 스키마 : 데이터가 컴퓨터에 저장되는 방법 정의
테이블, 칼럼 등 물리적 저장 구조와 사용될 저장 장치, 자료를 추출하기 위해 사용될 접근 방법 사용.</p>
<p>참고 자료
<a href="https://velog.io/@hiy7030/SQLD-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%AA%A8%EB%8D%B8%EB%A7%81%EC%9D%98-%EC%9D%B4%ED%95%B4">링크텍스트</a></p>
<h2 id="2-2-sql-vs-nosql--데이터베이스-선택-기준"><em><strong>2-2 SQL vs NoSQL : 데이터베이스 선택 기준</strong></em></h2>
<p>관계형 데이터베이스 :
관계형 데이터베이스 관리 시스템 (Relational Database Management System, RDBMS)
관계형 데이터베이스 관리 시스템을 따로 RDBMS라고 부른다.</p>
<p>MySQL
Oracle
SQLite
MariaDB
PostgresSQL</p>
<p><strong>SQL</strong>
관계형 데이터베이스 관리 시스템(RDBMS)의 데이터를 관리하기 위해 설계된 특수 목적의 프로그래밍 언어이다.
관계형 데이터베이스 관리 시스템에서 자료의 검색과 관리, 데이터베이스 스키마 생성과 수정, 데이터베이스 객체 접근 조정 관리를 위해 고안되었다.</p>
<p>관계형 데이터베이스에서는 모두 초창기 관계 데이터베이스 시스템을 위해 만들어진 SQL이라는 언어를 사용 하므로(문법이 조금씩 다른 부분도 있다.) 관계형 데이터베이스를 SQL이라고 부르는 것이다. 즉, SQL은 관계형 데이터베이스 전용 프로그래밍 언어이다.
<strong>장점</strong></p>
<ul>
<li>명확하게 정의된 스키마, 데이터 무결성 보장</li>
<li>관계는 각 데이터를 중복없이 한번만 저장</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>덜 유연함. 데이터 스키마를 사전에 계획하고 알려야 함. (나중에 수정하기 힘듬)</li>
<li>관계를 맺고 있어서 조인문이 많은 복잡한 쿼리가 만들어질 수 있음</li>
<li>대체로 수직적 확장만 가능함</li>
</ul>
<p>비관계형 데이터베이스 :
비관계형 데이터베이스란 관계형 데이터베이스를 뺀 나머지 유형을 총칭하는 뜻이다. 마치 한국어 외에는 다 외국어인 것 처럼 관계형 데이터베이스가 아닌 모든 곳에서는 NoSQL인 것이다.</p>
<p>주의할 점은 NoSQL 데이터베이스 또는 비관계형 데이터베이스로도 관계 데이터를 저장할 수 있다. 유연한 스키마를 제공하며, 대량의 데이터와 높은 사용자 부하에서도 손쉽게 확장이 가능하다.</p>
<p>관계형 데이터베이스에서는 데이터를 입력할 때 스키마에 맞게 입력해야 하는 반면, NoSQL에서는 데이터를 읽어올 때 스키마에 따라 데이터를 읽어 온다. 이런 방식을 ‘schema on read’라고도 한다.</p>
<p>읽어올 때에만 데이터 스키마가 사용된다고 하여, 데이터를 쓸 때 정해진 방식이 없다는 의미는 아니다.
데이터를 입력하는 방식에 따라, 데이터를 읽어올 때 영향을 미친다.</p>
<p><strong>장점</strong></p>
<ul>
<li>스키마가 없어서 유연함.언제든지 저장된 데이터를 조정하고 새로운 필드 추가 가능</li>
<li>데이터는 애플리케이션이 필요로 하는 형식으로 저장됨.</li>
<li>데이터 읽어오는 속도 빨라짐</li>
<li>수직 및 수평 확장이 가능해서 애플리케이션이 발생시키는 모든 읽기/쓰기 요청 처리 가능</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>유연성으로 인해 데이터 구조 결정을 미루게 될 수 있음</li>
<li>데이터 중복을 계속 업데이트 해야 함</li>
<li>데이터가 여러 컬렉션에 중복되어 있기 때문에 수정 시 모든 컬렉션에서 수행해야 함 (SQL에서는 중복 데이터가 없으므로 한번만 수행이 가능)</li>
</ul>
<p><strong>NoSQL 데이터베이스 유형</strong></p>
<p><strong>Key-Value 타입</strong></p>
<ul>
<li>속성을 Key-Value의 쌍으로 나타내는 데이터를 배열 형태로 저장한다.</li>
<li>Key는 속성 이름을 뜻하고, Value는 속성에 연결된 데이터 값을 의미한다.</li>
<li>대표적인 Key-Value 형식에 데이터베이스에는 Redis, Amazon DynamoDB 등이 있다.</li>
</ul>
<p><strong>문서형(Document) 데이터베이스</strong></p>
<ul>
<li>데이터를 테이블이 아닌 문서처럼 저장하는 데이터베이스를 의미한다.</li>
<li>많은 문서형 데이터베이스에서 JSON과 유사한 형식의 데이터를 문서화하여 저장한다.</li>
<li>각각의 문서는 하나의 속성에 대한 데이터를 가지고 있고, 컬렉션이라는 그룹으로 묶어 관리한다.</li>
<li>대표적인 문서형 데이터베이스에는 MongoDB 등이 있다.</li>
</ul>
<p><strong>Wide-Column Store 데이터베이스</strong></p>
<ul>
<li>데이터베이스의 열(column)에 대한 데이터를 집중적으로 관리하는 데이터베이스이다.</li>
<li>각 열에는 key-value 형식으로 데이터가 저장되고, 컬럼 패밀리(column families)라고 하는 열의 집합체 단위로 데이터를 처리할 수 있다.</li>
<li>하나의 행에 많은 열을 포함할 수 있어서 유연성을 높다.</li>
<li>데이터 처리에 필요한 열을 유연하게 선택할 수 있다는 점에서 규모가 큰 데이터 분석에 주로 사용되는 데이터베이스 형식이다.</li>
<li>대표적인 Wide-Column 데이터베이스에는 Apache Cassandra, Apache HBase 등이 있다.</li>
</ul>
<p><strong>그래프(Graph) 데이터베이스</strong></p>
<ul>
<li>자료구조의 그래프와 비슷한 형식으로 데이터 간의 관계를 구성하는 데이터베이스이다.</li>
<li>노드(nodes)에 속성별(entities)로 데이터를 저장한다.</li>
<li>각 노드간 관계는 선(edge)으로 표현한다.</li>
<li>대표적인 그래프 데이터베이스에는 Neo4J, InfiniteGraph 등이 있다.</li>
</ul>
<p><em><strong>SQL과 NoSQL 비교</strong></em></p>
<p>스키마 (Schema)
<strong>SQL</strong></p>
<p>고정된 형식의 스키마가 필요하다. 다시 말해, 처리하려는 데이터 속성별로 열(column)에 대한 정보를 미리 정해두어야 한다.
스키마는 나중에 변경할 수 있지만, 이 경우 데이터베이스 전체를 수정하거나 오프라인(down-time)으로 전환할 필요가 있다. 즉, 수정이 힘들다.
<strong>NoSQL</strong></p>
<p>관계형 데이터베이스보다 동적으로 스키마의 형태를 관리할 수 있다.
행을 추가할 때 즉시 새로운 열을 추가할 수 있고, 개별 속성에 대해서 모든 열에 대한 데이터를 반드시 입력하지 않아도 된다.</p>
<p><strong>SQL과 NoSQL 선택 기준</strong></p>
<p>NoSQL 기반의 비관계형 데이터베이스가 확장성이나 속도면에서 더 뛰어나다.
그러나 고차원으로 구조화된 SQL 기반의 데이터베이스가 더 좋은 성능을 보여주는 서비스도 있다.</p>
<p><strong>SQL 기반의 관계형 데이터베이스를 사용하기 좋은 경우</strong>
1.데이터베이스의 ACID 성질을 준수해야 하는 경우</p>
<ul>
<li>SQL을 사용하면 데이터베이스와 상호 작용하는 방식을 정확하게 규정할 수 있기 때문에 데이터베이스에서 데이터를 처리할 때 발생할 수 있는 예외적인 상황을 줄이고, 데이터베이스의 무결성을 보호할 수 있다.</li>
<li>전자 상거래를 비롯한 모든 금융 서비스를 위한 소프트웨어 개발 에서는 반드시 데이터베이스의 ACID 성질을 준수해야 한다.</li>
<li>그래서 이런 경우에는 일반적으로 SQL을 이용한 관계형 데이터베이스를 사용한다.</li>
</ul>
<p>ACID란</p>
<ul>
<li>Atomicity(원자성)</li>
<li>Consistency(일관성)</li>
<li>Isolation(격리성)</li>
<li>Durability(지속성)</li>
</ul>
<p>2.소프트웨어에 사용되는 데이터가 구조적이고 일관적인 경우</p>
<ul>
<li>소프트웨어(프로젝트)의 규모가 많은 서버를 필요로 하지 않고 일관된 데이터를 사용하는 경우, 관계형 데이터베이스를 사용하는 경우가 많다.</li>
<li>다양한 데이터 유형과 높은 트래픽을 지원하도록 설계된 NoSQL 데이터베이스를 사용해야만 하는 이유가 없기 때문이다.</li>
</ul>
<p>3.관계를 맺고 있는 데이터가 자주 변경되는 애플리케이션의 경우</p>
<ul>
<li>NoSQL에서는 여러 컬렉션을 모두 수정해야 하기 때문에 비효율적이다.</li>
</ul>
<p><strong>NoSQL 기반의 비관계형 데이터베이스를 사용하기 좋은 경우</strong></p>
<p>1.정형화되지 않은 대용량의 데이터를 저장하는 경우</p>
<ul>
<li>대부분의 NoSQL 데이터베이스는 저장할 수 있는 데이터의 유형에 제한이 없다. 즉, 필요에 따라, 언제든지 데이터의 새 유형을 추가할 수 있다.</li>
<li>소프트웨어 개발에 정형화 되지 않은 많은 양의 데이터가 필요한 경우, NoSQL을 적용하는 것이 더 효율적일 수 있다.</li>
</ul>
<p>2.클라우드 컴퓨팅 및 저장공간을 최대한 활용하는 경우</p>
<ul>
<li>클라우드 기반으로 데이터베이스 저장소를 구축하면, 저렴한 비용의 솔루션을 제공받을 수 있다.</li>
<li>소프트웨어에 데이터베이스의 확장성이 중요하다면, 별다른 번거로움 없이 확장할 수 있는 NoSQL 데이터베이스를 사용하는 것이 좋다.</li>
</ul>
<p>3.빠르게 서비스를 구축하는 과정에서 데이터 구조를 자주 업데이트 하는 경우</p>
<ul>
<li>스키마를 미리 준비할 필요가 없기 때문에 빠르게 개발하는 과정에 매우 유리하다.</li>
<li>시장에 빠르게 프로토타입을 출시해야 하는 경우가 이에 해당한다.</li>
<li>소프트웨어 버전별로 많은 다운타임(데이터베이스 서버를 오프라인으로 전환하여 데이터 처리를 진행하는 작업 시간) 없이 데이터 구조를 자주 업데이트 해야하는 경우, 스키마를 매번 수정해야 하는 관계형 데이터베이스 보다 NoSQL 기반의 비관계형 데이터베이스를 사용하는 게 더 적합하다.</li>
</ul>
<p>4.읽기를 자주 하지만, 데이터 변경은 자주 없는 경우</p>
<ul>
<li>성능과 비용적인 측면에서 이득을 얻을 수 있다.</li>
</ul>
<p><a href="https://velog.io/@octo__/SQL-vs-NoSQL">링크텍스트</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[1. 사용자 인증(Authentication)과 권한 부여(Authorization)에 대한 이해]]></title>
            <link>https://velog.io/@m_jae/Here-we-go</link>
            <guid>https://velog.io/@m_jae/Here-we-go</guid>
            <pubDate>Sun, 07 Jan 2024 19:16:48 GMT</pubDate>
            <description><![CDATA[<p> User Management Theory 에 관해정리해보려 한다..
 #사용자 인증(Authentication)과 권한 부여(Authorization)에 대한 이해</p>
<h2 id="1-사용자-인증authentication과-권한-부여authorization에-대한-이해">1. 사용자 인증(Authentication)과 권한 부여(Authorization)에 대한 이해</h2>
<h2 id="1-1-인증과-권한-부여의-차이-이해">1-1 인증과 권한 부여의 차이 이해</h2>
<p>사용자 인증 -  컴퓨터 보안에서 말하는 인증이란 어떤 실체가 그 실체가 맞는지 확인하는 것이다.
여기에는 4가지 유형이 있다.</p>
<ol>
<li>지식 기반 인증(What you know)
 • 고객이 알고있는 정보 기반으로 인증 
 • 비밀번호 등 
 • 유추가 가능하고 유출의 우려가 있음</li>
<li>소유 기반 인증(What you have)
 • 고객이 소유하고 있는 것을 기반으로 인증
 • 공인인증서, 시크리트 카드, OTP, 문자인증 등 
 • 지식 기반 인증과 함께 사용되면 강력함 
 • 복제/분실의 우려 존재</li>
<li>생체(존재) 기반 인증(What you are)
 • 고객이 가지고 있는 고유한 생체적 특징을 기반으로 인증 
 • 지문인증, 홍체인증 등 
 • 분실이나 도난의 위험이 없고 복제가 어려움 
 • 재발급이나 변경이 안되므로 복제가 될 경우 위험 
 • 인증 실패(본인거부)의 가능성</li>
<li>행위 기반 인증(What you do)
 • 주체가 하는 행위 기반으로 인증
 • 걸음걸이, 서명, 음성 등</li>
</ol>
<p>권한부여 - 인증에 성공한 사용자여도 부여된 권한 범위 내에서 애플리케이션 리소스에 접근할 수 있어야함을 의미한다. 즉, 사용자 인증을 거친 사용자라도 권한에 따라 제한이 될 수 있는것이다.</p>
<h2 id="1-2-세션-기반-인증--쿠키와-서버-사이드-세션">1-2 세션 기반 인증 : 쿠키와 서버 사이드 세션</h2>
<p>사이트를 이용하다 보면 몇일이 지나도 로그인이 되어있거나, 몇분뒤 곧바로 세션이 만료되었다는 문구를 본적이 있을 것이다. 여기서 사용되는 개념이 쿠키 와 세션이기에 개념정리를 먼저 하겠다.</p>
<p><em>쿠키</em>  - 쿠키란 서버가 사용자에게 보내는 작은 조각 개념이다. 서버에서 쿠키를 제공하면 이를 사용자 브라우저는 저장해놓았다가, 이후 서버에 재요청을 할때 데이터와 함께 보낸다. 서버는 이를 보고, 동일한 브라우저인지 아닌지 구분한다. 이를 이용하여 로그인 상태를 유지할 수 있다. 그러나 해킹의 위험이 있다.</p>
<p><em>세션</em> - 세션은 쿠키와 다르게 정보를 서버측에 저장하는 방식이다. 사용자 브라우저에서 요청시 sessionid를 생성하고 제공하면, 사용자는 데이터를 보낼때 마다, session id를 헤더에 추가하여 보낸다. 세션은 서버에 저장하기에 쿠키보다 비교적 안정적이다. 그러나 세션은 종료시 session id를 삭제 해버린다.</p>
<p><em>세션기반 인증</em> -
<img src="https://velog.velcdn.com/images/m_jae/post/feba74eb-e587-41f8-b513-df6cf9de0bb4/image.png" alt="">
사용자가 인증을 할 때, 서버는 이러한 정보를 저장하고, 이를 세션(Session)이라고 부른다. 대부분의 경우에는 메모리에 저장하는데, 로그인 중인 사용자가 늘어날 경우에는 서버의 RAM에 부하가 걸리게 된다. 이를 피하기 위해 데이터베이스에 저장을 하기도 하는데, 이러한 방식 역시 데이터베이스에 무리를 줄 수 있다.</p>
<h2 id="1-3-토큰-기반-인증-jwt-사용-방법">1-3 토큰 기반 인증 (JWT 사용 방법)</h2>
<p>토큰인증 방식은 인증을 받은 사용자에게 토큰을 제공하고, 요청을 할때 토큰을 같이 보내도록 하여 유효성 검사를 하는 방식이다. 이렇게 한다면 서버측에서 관리하지 않아도 되기에 부담을 줄일 수 있다.
<img src="https://velog.velcdn.com/images/m_jae/post/b452e2b5-9554-4efc-948d-8c11be259395/image.png" alt="">
이러한 토큰은 클라이언트 측에 저장되기 때문에 서버는 완전히 Stateless하며, 클라이언트와 서버의 연결고리가 없기 때문에 확장하기에 매우 적합하다. 만약 사용자 정보가 서버 측 세션에 저장된 경우에 서버를 확장하여 분산처리 한다면, 해당 사용자는 처음 로그인 했었던 서버에만 요청을 받도록 설정을 해주어야 한다. 하지만 토큰을 사용한다면 어떠한 서버로 요청이 와도 상관이 없다.</p>
<h2 id="1-4-oauth-외부-서비스를-이용한-인증-방법">1-4 Oauth: 외부 서비스를 이용한 인증 방법</h2>
<p>직접 서버에서 인증과 관련된 로직을 처리할 필요 없이 인증을 중개하는 외부 서버를 이용한기술</p>
<ul>
<li>권한 : OAuth는 인증뿐만 아니라 권한도 관리합니다. 사용자의 권한에 따라 접근할 수 있는 데이터가 다르도록 설정이 가능합니다. </li>
<li>프로토콜 : 특정한 프로그램을 지칭하는게 아니라 일종의 규격입니다. Facebook, Google, Naver 등은 OAuth라는 규격에 맞춰 인증 및 권한을 대행관리 해줍니다</li>
<li>외부서비스 : 우리가 만들고 있는 서비스를 이야기합니다. 외부 서비스를 위한 서비스인 OAuth는 우리 서비스의 인증 및 권한부여를 관리를 대행해줍니다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/m_jae/post/cbca54f8-d3b6-49b7-bdd5-a29ea74dcdda/image.png" alt=""></p>
<p>Authorization Server: 권한을 관리하는 서버. Access Token과 Refresh Token을 발급 및 재발급해주는 역할
Resource Server: OAuth 2.0을 관리하는 서버(Google, Facebook, Kakao 등)의 자원을 관리하는 서버. 우리가 만드는 서버의 자원을 관리하는 곳이 아니라, OAuth 2.0 관리 서버의 자체 API를 의미한다.</p>
<p>과정</p>
<ol>
<li>Resource Owner(사용자)가 Client(우리 서버)에게 인증 요청을 한다.</li>
<li>Client는 Authorization Request를 통해 Resource Owner에게 인증할 수단(Google 로그인, Facebook 로그인 URL)을 보낸다.</li>
<li>Resource Owner는 해당 Request를 통해 인증을 진행하고, 인증을 완료했다는 신호로  Authorization Grant를 URL에 실어 Client에게 보낸다.</li>
<li>Client는 해당 Authorization Grant(권한증서)를 Authorization Server에 보낸다.</li>
<li>Authorization Server는 권한증서를 확인한 후, 유저가 맞다면 Client에게 Access Token, Refresh Token, 그리고 유저의 프로필 정보(id 포함) 등을 발급해준다.</li>
<li>Client는 해당 Access Token을 DB에 저장하거나 Resource Owner에게 넘긴다.</li>
<li>Resource Owner가 Resource Server에 자원이 필요하면, Client는 Access Token을 담아 Resource Server에 요청한다.</li>
<li>Resource Server는 Access Token이 유효한지 확인한 후, Client에게 자원을 보낸다.</li>
<li>만일 Access Token이 만료됐거나 위조됐다면, Client는 Authorization Server에 Refresh Token을 보내 Access Token을 재발급받는다.</li>
<li>그 후 다시 Resource Server에 자원을 요청한다.</li>
<li>만일 Refresh Token도 만료되었을 경우 Resource Owner는 새로운 Authorization Grant를 Client에게 넘겨야한다. (이는, 사용자가 다시 로그인을 해야된다는 뜻이다.)</li>
</ol>
<p>장점 : 회원가입이라는 귀찮은 절차를 없애고, 사용자가 빠르게 회원가입을 할 수 있다.
    접근하고 싶은 정보들은 사용자들이 미리 권한 내용을 확인하고 허락하기에 쉽게 접근할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[나의 첫 velog..]]></title>
            <link>https://velog.io/@m_jae/%EB%82%98%EC%9D%98-%EC%B2%AB-velog</link>
            <guid>https://velog.io/@m_jae/%EB%82%98%EC%9D%98-%EC%B2%AB-velog</guid>
            <pubDate>Wed, 03 Jan 2024 07:04:36 GMT</pubDate>
            <description><![CDATA[<p>20240102 나의 첫 블로그.. 오늘부터 시작해 꾸준히 작성해 보려 한다.
첫번째로는 작년에 과제를 하며 해결 했던 몇가지 문제들을 다시 되짚어 보겠다.</p>
<p>#알람</p>
<blockquote>
<p>09시에 알람이 울린다고 할 때, 현재 시간을 입력 받고 알람이 울리기까지 남은 시간이나 알람이 울린 후 지난 시간을 출력하는 프로그램을 작성하세요.</p>
</blockquote>
<p>java</p>
<pre><code class="language-**">import java.util.Scanner;
public class week2 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.print(&quot;현재 시간을 입력하세요 (HH 형식): &quot;);
        int h = sc.nextInt();
        if (0 &gt; h || h &gt; 23) {
            System.out.printf(&quot;잘못된 입력 형식 입니다.&quot;);
            System.exit(0);
        }

        System.out.print(&quot;현재 분을 입력하세요 (mm 형식): &quot;);
        int m = sc.nextInt();
        if (0 &gt; m || m &gt;= 60) {
            System.out.printf(&quot;잘못된 입력 형식입니다.&quot;);
            System.exit(0);
        }
        if (0 &lt;= h &amp;&amp; h &lt; 9) {
            if (0 &lt; m &amp;&amp; m &lt; 60) {
                h = 9 - (h + 1);
                m = 60 - m;
                System.out.printf(&quot;알림이 울리기까지 %d시간 %d분 남았습니다&quot;, h, m);
            } else if (m == 0) {
                h = 9 - h;
                System.out.printf(&quot;알림이 울리기까지 %d시간 %d분 남았습니다.&quot;, h, m);
            }
        } else if (9 &lt;= h &amp;&amp; h &lt;= 23) {
            h = h - 9;
            System.out.printf(&quot;알림이 울린지 %d시간 %d분 지났습니다.&quot;, h, m);
        }
    }
}</code></pre>
<p>여기서 날짜를  지정할 수 없기에 09시에 알람이 울린다 하였을때, 16시를 입력하면 이것이 알람이 울리기 전인지 후인지 구분이 불가능하기에 이부분은 생략하고 진행하였다.</p>
<p>해당코드는 조금만 생각하면 쉽게 접근이 가능했다. 핵심은 &#39;시&#39;를 9시 이전인 경우와 그이후로 나눠 9시 이후의 시간은 전부 시간이 지난것으로 판단되게 하고, &#39;분&#39;이 0일때와 아닐때를 나눠서 접근하면 쉬운접근이 가능해 진다</p>
<p>#로또번호
<img src="https://velog.velcdn.com/images/m_jae/post/bf463090-5932-47e3-8464-51eb4018388d/image.png" alt=""></p>
<pre><code>import java.util.Scanner;
import java.util.Arrays;

public class week3 {
    public static void main(String[] args) {
        int arr[] = new int[6];//로또 번호 저장 배열
        int my[] = new int[6];//입력받은 번호 저장 배열
        Scanner sc = new Scanner(System.in);
        for (int i = 0; i &lt; 6; i++) {
            arr[i] = (int) (Math.random() * 45 + 1);//로또 번호 생성
        }
        for (int j = 0; j &lt; 6; j++) {//배열 길이가 6이 될때 까지
            System.out.print(&quot;로또 번호를 입력하세요 (1부터 45사이의 숫자, 중복 없이) :&quot;);//배열 입력 받음
            my[j] = sc.nextInt();// 배열 입력 받음
            for (int k = 0; k &lt; j; k++) {//입력받은 배열중 중복 배열 검열
                if (my[j] == my[k] &amp;&amp; j != k) {// 배열을 입력받았을때 자기자신을 제외하고 중복되는 숫자가 있는경우
                    System.out.println(&quot;이미 입력한 번호입니다. 중복없이 입력하세요.&quot;);
                    Arrays.copyOf(my, j);//중복 배열 제외 후 배열 재설정
                    j--;// j값 줄이고 해당 배열번호에 다시 입력 받기 위함
                }
                //System.out.printf(Arrays.toString(my)); 배열 잘 들어가는지 확인용 코드
            }
        }
        System.out.printf(&quot;로또 당첨 번호 : %s\n&quot;,Arrays.toString(my)); //로또번호 출력
        System.out.printf(&quot;사용자 번호 : %s\n&quot;,Arrays.toString(arr)); // 사용자 번호 출력
        int num = 0;// 당첨 갯수 확인용 변수
        for (int i = 0; i &lt; 6; i++) {
            for (int k = 0; k &lt; 6; k++) {
                if (my[i] == arr[k]) {// 로또번호와 일치하는 사용자 번호가 있다면
                    num++;// 갯수 +1
                }
            }
        }
        switch (num) {// 갯수에 따른 결과 반환
            case 0, 1, 2:
                System.out.println(&quot;꽝입니다. 일치하는 번호가 2개 이하입니다.&quot;);
                break;

            case 3:
                System.out.println(&quot;4등니다. 일치하는 번호가 3개입니다.&quot;);
                break;

            case 4:
                System.out.println(&quot;3등니다. 일치하는 번호가 4개입니다.&quot;);
                break;

            case 5:
                System.out.println(&quot;2등니다. 일치하는 번호가 5개입니다.&quot;);
                break;

            case 6:
                System.out.println(&quot;1등니다. 일치하는 번호가 6개입니다.&quot;);
                break;
        }
    }
}
</code></pre><p>로또 번호를 생성하기 위해 math.random을 이용하여 1부터 45까지의 숫자를 받아오게 설정하였다. 그 이후에는 6개(1부터45)의 숫자를 입력받아 해당 번호들이 같은지 비교하면 되는것이다. 여기서 중요한점은 같은지 비교를 할때 자기자신은 제외하고 5개의 숫자를 비교한다는점이다.</p>
<p>#GUI를 이용한 계산기
다음과 같은 GUI 모양을 가진 스윙 프레임을 작성하세요.
버튼은 JButton 사용.
텍스트는 Jlabel 사용.
입력창은 JTextField 사용.<img src="https://velog.velcdn.com/images/m_jae/post/50637f03-7630-4335-b410-d04fd6050952/image.png" alt="">
<img src="blob:https://velog.io/21b27a8f-de10-4c16-ab54-8a4fcc5e25ba" alt="업로드중.."></p>
<pre><code>import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

class NorthPanel extends JPanel { //tf1영역
    private JTextField text1;

    public NorthPanel(JTextField textField) {
        text1 = textField;
        setLayout(new FlowLayout());
        setBackground(Color.LIGHT_GRAY);
        add(new JLabel(&quot;연산수식&quot;));
        add(text1);
    }

    public JTextField getop() {
        return text1;
    }
}

class CenterPanel extends JPanel {
    private JButton[] label = new JButton[16];
    private String[] cal = {&quot;0&quot;, &quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;, &quot;6&quot;, &quot;7&quot;, &quot;8&quot;, &quot;9&quot;, &quot;CE&quot;, &quot;=&quot;, &quot;+&quot;, &quot;-&quot;, &quot;*&quot;, &quot;/&quot;};
    private JTextField tf1;
    private JTextField tf2;

    public CenterPanel(JTextField textField1, JTextField textField2) {
        tf1 = textField1;
        tf2 = textField2;

        setLayout(new GridLayout(4, 4, 5, 5));


        for (int i = 0; i &lt; 16; i++) { //버튼 영역의 색 설정
            label[i] = new JButton(cal[i]);
            label[i].setOpaque(true);
            if (i == 10 || i == 11) {
                label[i].setForeground(Color.BLACK);
            } else if (i &gt;= 12) {
                label[i].setBackground(Color.YELLOW);
            } else {
                label[i].setBackground(Color.GRAY);
            }

            add(label[i]);
        }



        for (int i = 0; i &lt; 16; i++) { //버튼에 액션리스너 추가
            if (i &lt;= 9 || i &gt;= 12) {
                label[i].addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        JButton tempButton = (JButton) e.getSource();
                        String s1 = tf1.getText();
                        tf1.setText(s1 + tempButton.getText());
                    }
                });
            }
        }

        // 버튼 처리
        label[10].addActionListener(new ActionListener() {// ce버튼 사용시 tf1,tf2의 내용을 지움
                                        public void actionPerformed(ActionEvent e) {
                                            tf1.setText(&quot;&quot;);
                                            tf2.setText(&quot;&quot;);
                                        }
                                    }
        );
        label[11].addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String expression = tf1.getText();
                int result = 0;

                // 연산 수행
                try {
                    // 연산자 추출
                    char operator = &#39; &#39;;
                    for (char c : expression.toCharArray()) {
                        if (c == &#39;+&#39; || c == &#39;-&#39; || c == &#39;*&#39; || c == &#39;/&#39;) {
                            operator = c;
                            break;
                        }
                    }

                    // 정수 부분만 추출한 후 해당 값을 통해 연산
                    String[] operands = expression.split(&quot;[\\+\\-\\*\\/]&quot;);
                    int operand1 = Integer.parseInt(operands[0].trim());
                    int operand2 = Integer.parseInt(operands[1].trim());

                    // 연산자에 따라 계산 수행
                    switch (operator) {
                        case &#39;+&#39;:
                            result = operand1 + operand2;
                            break;
                        case &#39;-&#39;:
                            result = operand1 - operand2;
                            break;
                        case &#39;*&#39;:
                            result = operand1 * operand2;
                            break;
                        case &#39;/&#39;:
                            result = operand1 / operand2;
                            break;
                        default:
                            tf2.setText(&quot;Error&quot;);
                            return;
                    }

                    // 계산 결과를 tf2에 표시
                    tf2.setText(String.valueOf(result));

                    // tf1의 내용을 지움
                    tf1.setText(&quot;&quot;);
                } catch (Exception ex) {
                    // 예외 처리: 유효하지 않은 표현식 등
                    tf2.setText(&quot;Error&quot;);
                }

            }
        });
    }
}


class SouthPanel extends JPanel {
    private JTextField tf2;

    public SouthPanel(JTextField textField2) { //맨밑의 판
        tf2 = textField2;

        setLayout(new FlowLayout());
        setBackground(Color.BLACK);
        JLabel resultLabel = new JLabel(&quot;계산결과&quot;);
        resultLabel.setForeground(Color.WHITE);  // 흰색으로 글씨 색상 지정
        add(resultLabel);
        add(tf2);
    }
}

public class week6 extends JFrame {
    public week6() {
        setTitle(&quot;산술 계산기&quot;);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Container c = getContentPane();
        c.setLayout(new BorderLayout());

        JTextField tf1 = new JTextField(20);
        JTextField tf2 = new JTextField(20);

        NorthPanel northPanel = new NorthPanel(tf1);
        CenterPanel centerPanel = new CenterPanel(tf1, tf2);
        SouthPanel southPanel = new SouthPanel(tf2);

        c.add(northPanel, BorderLayout.NORTH);
        c.add(centerPanel, BorderLayout.CENTER);
        c.add(southPanel, BorderLayout.SOUTH);

        setSize(400, 400);
        setVisible(true);
    }
}</code></pre><p>해당문제는 GUI로 표현된 계산기를 만들어야하는것이다. north,center,south,로 나눠서 문제를 해결해야한다. 계산기 기능을 만드는것은 어렵지 않았으나, GUI쪽을 다루려다 보니 어려운 부분들이 많았다.</p>
]]></description>
        </item>
    </channel>
</rss>