<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ysj_log.log</title>
        <link>https://velog.io/</link>
        <description>개발자 공부</description>
        <lastBuildDate>Wed, 21 Aug 2024 00:24:39 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>ysj_log.log</title>
            <url>https://velog.velcdn.com/images/ysj_log/profile/beec7d28-8801-4c9c-9a56-7c5616ace1b2/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ysj_log.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ysj_log" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[부트스트랩 사용법]]></title>
            <link>https://velog.io/@ysj_log/%EB%B6%80%ED%8A%B8%EC%8A%A4%ED%8A%B8%EB%9E%A9-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@ysj_log/%EB%B6%80%ED%8A%B8%EC%8A%A4%ED%8A%B8%EB%9E%A9-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Wed, 21 Aug 2024 00:24:39 GMT</pubDate>
            <description><![CDATA[<p>01: Bootstrap 개요</p>
<p>1) Bootstrap 이란?
부트스트랩은 전세계적으로 가장 많이 사용되는 오픈소스 CSS 라이브러리 입니다. 부트스트랩을 기반으로 하는 다양한 응용 라이브러리가 있으며 부트스트랩에 일부를 보완해 여러분들만의 CSS 라이브러리를 구축해 나갈수 있습니다.</p>
<p>부트스트랩을 제대로 사용하기 위해서는 앞에서 배운 HTML과 CSS 의 기본개념을 확실하게 이해하고 있어야 합니다. 특히 DOM, CSS의 상속관계, 선택자, 블럭/인라인, position 등에 대한 완전한 이해가 필요 합니다.</p>
<p>만일 부트스트랩을 잘 사용할 수 있게 된다면 다른 CSS라이브러리들도 얼마든지 도입해 사용할 수 있는 능력을 갖추게 되었다고 볼 수 있습니다.</p>
<p>2) Bootstrap 시작하기
부트스트랩의 세부 설정이나 테마를 수정해 개발하거나 react, vue 등의 프론트엔드 프레임워크에서 부트스트랩을 사용하는 경우 전체 라이브러리를 다운받아 새롭게 빌드해서 사용하는 개념으로 접근할 수 있지만 백엔드 기반의 웹프로그램이나 간단한 프론트엔드 웹프로그램을 개발하는 경우에는 CDN(Contents Delivery Network) 을 통해 부트스트랩 css 와 자바스크립트 라이브러리를 포함하는 것만으로도 사용이 가능 합니다.</p>
<p>react, vue 와 같은 프론트엔드 프레임워크에서 기본 Bootstrap 을 사용하는 방법도 있지만 jQuery 사용에 따른 문제점이나 기타 프레임워크 구조를 일관되게 적용하기 위해 해당 프레임워크용으로 별도 제작된 Bootstrap 플러그인을 사용하기도 합니다. react-bootstrap, bootstrap-vue 등이 이에 해당 합니다.
Bootstrap CDN
부트스트랩의 최신버전은 4.3.1 이며 다음과 같이 외부 스타일시트를 <head></head> 사이에 추가 하면 바로 부트스트랩을 사용할 수 있습니다.</p>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
Bootrap JavaScript
부트스트랩의 일부 컴포넌트들은 이벤트에 반응하는 구조로 되어 있어 jQuery를 비롯한 몇몇 자바스크립트 라이브러리를 필요로 합니다.

<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<p>코드가 길어진 이유는 integrity 와 crossorigin 속성 때문인데 이들은 보안과 관련된 것으로 자바스크립를 이용한 보안공격에 대비한 것으로 사용하는 것을 권장 합니다.</p>
<p>3) 알아둘 사항
부트스트랩은 일관된 디자인 적용을 위해 기본 HTML 태그들의 기본 CSS속성들을 재정의 하거나 수정된 초기값을 사용하고 있습니다.</p>
<p>box-sizing
박스 요소들의 일관된 사이즈 계산을 위해 전체 태그에 대해 box-sizing 속성을 border-box 로 변경해 사용하고 있습니다. 이는 일부 서드파티 라이브러리(Google Maps, Google Custom Search Engin 등)에 영향을 미칠수 있습니다. 이경우 필요한 클래스들에 대해 box-sizing 을 content-box 로 오버라이딩해서 사용해야 합니다.</p>
<p>.selector-for-some-widget {
  box-sizing: content-box;
}
HTML 속성 초기화
앞에서 언급한것 처럼 기본 HTML 속성들중 일부는 수정되거나 재정의 되어 있습니다. 부트스트랩을 처음 시작하는 경우에는 자세한 내용을 몰라도 괜찮지만 보다 정확한 구조를 이해하고 정밀한 조정이 필요한 경우 세부적인 사항을 알고 있으면 도움이 됩니다.</p>
<p>해당 내용은 본 강좌의 범위를 벗어나므로 자세한 사항은 다음 링크를 참고하기 바랍니다.</p>
<p><a href="https://getbootstrap.com/docs/4.3/content/reboot/">https://getbootstrap.com/docs/4.3/content/reboot/</a></p>
<p>4) 부트스트랩 사용법
부트스트랩 CSS 적용만으로 기본적으로 HTML 태그 속성들이 부트스트랩에 맞게 초기화 되어 기본 태그만 사용해도 기존과는 조금 다르게 나타 납니다. 부트스트랩을 이용해 화면을 제작하는 것은 부트스트랩에서 정의된 다양한 클래스(컴포넌트)들을 HTML에 적용하고 부가적인 속성이나 레이아웃과 관련된 속성들을 정의한 클래스들을 조합해 나가는 과정 으로 이해할 수 있습니다.</p>
<p>&lt;태그 class=&quot;bs_class1 bs_class2 ...&quot;&gt;
예를 들어 부트스트랩에서는 다음과 같은 버튼을 제공하는데 버튼사용을 위해서는 btn 이라는 클래스를 기본으로 하고 btn-success 와 같이 추가적인 클래스를 함께 사용해 디자인을 적용하는 방식입니다.</p>
<p><button type="button" class="btn">Basic</button>
<button type="button" class="btn btn-primary">Primary</button>
<button type="button" class="btn btn-secondary">Secondary</button>
<button type="button" class="btn btn-success">Success</button>
<button type="button" class="btn btn-info">Info</button>
<button type="button" class="btn btn-warning">Warning</button>
<button type="button" class="btn btn-danger">Danger</button>
<button type="button" class="btn btn-dark">Dark</button>
<button type="button" class="btn btn-light">Light</button>
<button type="button" class="btn btn-link">Link</button>
이외에 좀더 복잡한 구조의 컴포넌트들이 정의 되어 있고 border, margin, padding, color, align, width, height 등과 같은 속성들을 사용하기 쉽도록 만든 유틸리티 클래스들이 있으며 이들역시 조합해서 사용하는 것이 가능 합니다.</p>
<p>02: BS 컨테이너와 그리드</p>
<p>1) 컨테이너(Container)
컨테이너는 CSS에서 배운것 처럼 화면구성요소들을 묶기 위한 틀 입니다. 보통 <div> 태그들을 중첩해 사용하는 형식을 취하며 부트스트랩도 동일합니다. 다만 전체 구조를 잡기위해 부트스트랩에서는 두가지 컨테이너 모델을 제공하고 있습니다.</p>
<p>container</p>
<p>반응형으로 동작하며 고정폭을 가지고 있습니다. width 설정과 margin 설정을 통해 컨테이너와 브라우저 윈도우 사이의 여백을 조정할 수 있습니다.</p>
<p>container-fluid</p>
<p>viewport 전체 폭을 모두 차지하는 컨테이너 박스 입니다.</p>
<p>2) 그리드(Grid)
그리드는 테이블과 유사하게 화면을 분할해 원하는 레이아웃을 잡기위해 정의된 것으로 부트스트랩에서는 12개의 컬럼 구조를 사용할 수 있으며 5개의 화면크기와 관련된 옵션을 제공 합니다.</p>
<p>flexbox: 부트스트랩의 그리드는 flexbox(Flexible Box Layout Module)에 기반하고 있으며 flexbox 는 기존의 float, display, position 등을 이용한 박스 배치를 컨테이너 안에서 중심축을 기반으로 일관된 방식으로 배치하는 것이 가능합니다.
12 그리드 컬럼
화면을 12개의 컬럼으로 분할할 수 있으며 필요에 따라 컬럼을 묶어 더 큰 크기의 컬럼으로 사용할수도 있습니다.</p>
<p>5 그리드 옵션
부트스트랩의 그리드 시스템은 화면크기에 따라 사용할 수 있는 5개의 옵션을 제공합니다.</p>
<p>.col- (extra small devices - 화면크기 &lt; 576px)
.col-sm- (small devices - 화면크기 ≥ 576px)
.col-md- (medium devices - 화면크기 ≥ 768px)
.col-lg- (large devices - 화면크기 ≥ 992px)
.col-xl- (xlarge devices - 화면크기 ≥ 1200px)
부트스트랩에서는 기본적으로 em 이나 rem 단위를 사용하지만 그리드 컨테이너의 폭을 계산하는데는 viewport 를 따라 px 을 사용합니다.</p>
<p>기본 사용법
row 와 col-<em>-</em> 클래스를 사용해 화면크기에 따른 컬럼과 로우를 지정하고 부가적인 유틸리티 클래스로 조정해 나가는 방식 입니다.</p>
<p>col-sm-1 //sm 사이즈의 1컬럼 크기
col-md-2 //md 사이즈의 2컬럼 크기
다음은 동일한 width 를 가지는 컬럼을 정의한 것입니다. 전체 화면폭을 분할하게 되고 화면 크기에 따라 크기는 비율에 따라 조정되지만 배치가 바뀌지는 않습니다.</p>
<div class="row">
  <div class="col">.col</div>
  <div class="col">.col</div>
  <div class="col">.col</div>
</div>

<p>다음은 화면크기를 지정한 반응형 레이아웃으로 동일한 세개의 컬럼을 가지지만 화면크기가 576px 이하가 되면 상하로 배치가 변경 됩니다. 하나의 row 에 모든 컬럼을 배치하려면 구성 컬럼 크기의 합이 반드시 12컬럼 이하여야 하며 초과될 경우 다음 row 로 넘어가게 됩니다.</p>
<div class="row">
  <div class="col-sm-3">.col-sm-3</div>
  <div class="col-sm-3">.col-sm-3</div>
  <div class="col-sm-3">.col-sm-3</div>
  <div class="col-sm-3">.col-sm-3</div>
</div>

<p>하나의 row 에서 임의로 컬럼을 다음 라인으로 옮기기 위해서는(column break) 중간에 .w-100 클래스를 가지는 <div>를 추가 합니다.</p>
<div class="container">
  <div class="row">
    <div class="col">col</div>
    <div class="col">col</div>
    <div class="w-100"></div>
    <div class="col">col</div>
    <div class="col">col</div>
  </div>
</div>


<p>03: BS 컴포넌트
컴포넌트는 부트스트랩에서 정의한 UI 요소로 버튼, 경고창, 네비게이션바 와 같이 화면 구성에 필요한 요소들을 정의해둔 클래스 집합 입니다.</p>
<p>컴포넌트는 클래스만 사용해도 동작하는 유형과 특정 태그와 함께 사용해야 하는 유형이 있습니다. 각각의 컴포넌트 문서와 사용예를 보고 적용하면 됩니다.</p>
<p>다음은 BS의 기본 컴포넌트 목록 입니다.</p>
<p>컴포넌트    설명    비고
Alerts    텍스트 메시지를 포함하는 알림 박스    유형에 따라 5가지 컬러스키마로 구성 가능
Badge    버튼과 유사한 모양으로 텍스트와 숫자뱃지로 구성    스마트폰 아이콘에 숫자 뱃지와 유사
Breadcrumb    웹사이트에서 현재 페이지의 위치 정보를 표기    /home / board / 자유게시판 형식
Buttons    다양한 색상과 디자인의 버튼을 지원.    이벤트 처리는 별도 JS 처리가 필요
Button group    버튼을 그룹으로 묶어 메뉴형태로 사용가능    수직 버튼 그룹 구성도 가능함
Card    카드와 같이 세로 형태의 박스에 사진, 텍스트 등으로 콘텐츠 구성    제목과 내용을 버튼, 링크등으로 구성 가능
Carousel    이미지 슬라이드 컴포넌트    Next, Prev 버튼, 인디케이터, 자동슬라이드쇼 가능
Collaps    일부 콘텐츠를 숨기거나 보여줄수 있는 컴포넌트    Accordion 형태의 사용도 가능
Dropdown    <select>와 같은 선택 목록 컴포넌트    Button, Button group과 결합해 사용 가능
Forms    HTML form 요소와 함께사용    form-group 및 다양한 레이아웃 요소들을 포함하고 있음.
Input groupd    입력양식들을 그룹으로 묶어주는 컴포넌트    크기지정, 버튼, 체크박스, 드롭다운 등과 결합 가능
Jumbotron    큰 텍스트를 가지는 반응형 컴포넌트로 보통 메인 화면에 사용    제목과 내용으로 구성
List group    <ul>,<li>로 구성된 목록을 박스형태로 묶어서 표현    버튼, 링크, 수평배치 등도 지원
Media object    이미지와 텍스트로 구성되는 블로그, SNS, 댓글 유형    댓글의 댓글형식과 같이 들여쓰기 목록 구성 가능
Modal    현재 화면에 포함된 독립 윈도우로 JS Alert 대체가능    제목과 내용, 버튼등으로 구성되며, 닫기 기능 제공
Navs    메뉴 시스템(네비게이션) 구성을 위한 컴포넌트    버튼, 탭, 드롭다운과 결합해 구성 가능
Navbar    여러 컴포넌트를 묶어 구성한 네비게이션 바 컴포넌트    일반적으로 쓸수 있는 여러 유형의 네비게이션바 제공
Pagination    게시판 목록 페이지 이동을 위한 링크 구성    다양한 크기와 정렬 옵션이 있음
Popovers    버튼등을 클릭하면 주면에 나타나는 조그만 알림창    위치 지정과 닫기 기능 제공
Progress    진행률을 표시하는 바 형태의 UI컴포넌트    HTML <progress> 태그 대체 사용
Scrollspy    네비게이션바의 메뉴와 스크롤되는 콘텐츠의 위치 표시를 자동으로 연계해 줌    List group, Navbar 등과 결합해서 사용
Spinners    진행률을 표시하는 움직이는 원형태의 UI컴포넌트    여러 컬러와 정렬 옵션이 있음
Toasts    Push notification 형태의 알림창    위치 지정과 스택형태로 쌓기 가능
Tooltips    마우스가 올라가면 동작하는 도움말 풍선    위치 지정 가능
각각의 컴포넌트 사용법은 <a href="https://getbootstrap.com/docs/4.3/components/alerts/">https://getbootstrap.com/docs/4.3/components/alerts/</a> 을 참고하기 바랍니다.</p>
<p>컴포넌트 사용법
BS 컴포넌트는 적절한 태그와 클래스의 조합으로 이루어져 있습니다. 예를들어 Badge 를 사용하는 경우 다음과 같이 기본 Badge 를 만들수 있습니다. 버튼과 마찬가지로 success, info, primary 등의 컬러 스키마를 적용할 수 있습니다.</p>
<h1><span class="badge badge-secondary">New Item</span></h1>
숫자로 된 카운터 Badge 를 버튼에 추가하려면 다음과 같이 버튼을 만든다음 <span> 으로 Badge 를 추가 합니다.

<button type="button" class="btn btn-primary">
  New Item <span class="badge badge-light">4</span>
</button>
실행결과는 다음과 같습니다. 

<p>다음은 좀 더 복잡한 컴포넌트인 Navbar 를 한번 살펴보도록 하겠습니다. 네이게이션바는 navbar, navbar-nav, nav-item 으로 구성 됩니다. 네비게이션바의 메인 컨테이너는 <div> 태그 혹은 <nav> 태그를 사용할 수 있습니다.</p>
<p>네비게이션바에 들어가는 아이템들은 <ul>, <li>로 구성되며 각각 navbar-nav, nav-item 클래스를 사용합니다.</p>
<nav class="navbar">
  <ul class="navbar-nav">
    <li class="nav-item">
      <a class="nav-link" href="#">Active</a>
    </li>
  </ul>
</nav>
여기에 컬러 스키마와 크기옵션 등을 추가하면 다음과 같이 됩니다.

<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
  <ul class="navbar-nav">
    <li class="nav-item active">
      <a class="nav-link" href="#">Active</a>
    </li>
    <li class="nav-item">
      <a class="nav-link" href="#">Link1</a>
    </li>
    <li class="nav-item">
      <a class="nav-link" href="#">Link2</a>
    </li>
    <li class="nav-item">
      <a class="nav-link disabled" href="#">Disabled</a>
    </li>
  </ul>
</nav>
실행결과는 다음과 같습니다.



<p>04: BS 유틸리티
유틸리티 클래스를 잘 사용하면 추가적인 CSS 속성정의 없이 편하게 원하는 결과물을 쉽게 만들 수 있습니다.</p>
<p>부트스트랩을 사용하는데 있어 margin, padding, color, position, size 등 다양한 CSS 속성들을 사용하기 편하도록 미리 정의해 둔 클래스들로 기본 컴포넌트 클래스들과 결합해 사용합니다.</p>
<p>여기서는 중요한 유틸리티 클래스를 중심으로 알아 봅니다.</p>
<p>각각의 유틸리티 사용법은 <a href="https://getbootstrap.com/docs/4.3/utilities/">https://getbootstrap.com/docs/4.3/utilities/</a> 을 참고하기 바랍니다.</p>
<p>1) color
기본적으로 primary, secondary, success, danger, warning, info, light, dark, white로 스키마가 정의되어 있으며 배경, 텍스트, 버튼등에 결합되어 사용 합니다.</p>
<p>부트스트랩을 사용하는 페이지들이 모두 비슷한 느낌을 주는 이유는 바로 정해진 컬러 스키마를 주로 사용하기 때문입니다. 물론 다양한 컬러를 정의해서 사용하는 것도 가능하지만 사용용도에 따른 컬러 스키마를 사용하는 것이 좋습니다. 기본 컬러가 마음에 들지 않으면 테마를 정의해서 바꿔 사용해도 되기 때문에 개별적인 컬러값을 사용하기 보다는 스키마에 정의된 클래스들을 사용하길 권장 합니다.</p>
<p>다음은 컬러를 배경과 텍스트에 적용한 예 입니다.</p>
<div class="p-3 mb-2 bg-primary text-white">.bg-primary</div>
<div class="p-3 mb-2 bg-secondary text-white">.bg-secondary</div>
<div class="p-3 mb-2 bg-success text-white">.bg-success</div>
<div class="p-3 mb-2 bg-danger text-white">.bg-danger</div>
<div class="p-3 mb-2 bg-warning text-dark">.bg-warning</div>
<div class="p-3 mb-2 bg-info text-white">.bg-info</div>
<div class="p-3 mb-2 bg-light text-dark">.bg-light</div>
<div class="p-3 mb-2 bg-dark text-white">.bg-dark</div>
<div class="p-3 mb-2 bg-white text-dark">.bg-white</div>
 2) size
width, height 속성으로 크기 지정이 필요한 경우 사용할 수 있는 유틸리티 클래스 입니다.

<p>자유롭게 크기를 지정할 수 있는 것은 아니며 정해진 크기 비율을 사용할 수 있으며 viewport 를 기준으로 하는 상대적인 크기 지정도 가능합니다.</p>
<p>w-<em>, h-*형식으로 width, height 를 지정하고 25%, 50%, 75%, 100%, auto 중에서 선택해 사용.
mw-</em>, mh-<em>는 max-width, max-height 를 지정.
vw-</em>, vh-<em>, min-vw-</em>, min-vh-* viewport 를 기준으로 하는 상태 크기 지정.</p>
<div class="w-25 p-3 bg-info">Width 25%</div>
<div class="w-50 p-3 bg-info">Width 50%</div>
<div class="w-75 p-3 bg-info">Width 75%</div>
<div class="w-100 p-3 bg-info">Width 100%</div>
<div class="w-auto p-3 bg-info">Width auto</div> 
 3) spacing
박스모델에 필요한 margin, padding 을 지정하기 위한 유틸리티 클래스 입니다.

<p>기본 사용법은 {property}{sides}-{size} 형식이며 xs 스크린 사이즈를 기준으로 합니다. 그외 스크린 사이즈에 따른 지정은 {property}{sides}-{breakpoint}-{size} 형식을 사용합니다.</p>
<p>property
m: margin
p: padding
sides
상하좌우 각각 영문 첫글자를 사용합니다. 비워둘경우 4방향 모두를 지정합니다.</p>
<p>top(t),bottom(b), left(l), right(r)
x, y
size
0~5, auto 를 사용합니다. 3을 기준으로 부트스트랩의 기본 설정값의 0.25, 0.5, 1.5, 3 배율을 크기를 가지게 됩니다.</p>
<p>다음은 BS size 유틸리티를 사용한 예 입니다.</p>
<div class="pt-4 bg-warning">pt-4 (1.5rem = 24px)</div>
<div class="p-5 bg-success">p-5 (3rem = 48px)</div>
<div class="m-5 pb-5 bg-info">m-5 (3rem = 48px), pb-5 (3rem = 48px)</div>
첫번째 박스는 윗쪽 padding 만 지정
두번째 박스는 전체 padding 을 동일하게 지정
세번째 박스는 전체 margin 과 아랫쪽 padding을 지정
 4) shadow
그림자 효과를 부여하는 클래스로 입체감있는 박스 컨테이너를 만들때 효과적입니다.

<p>기본적으로 shadow-* 형식으로 크기와 함께 사용하게 됩니다.</p>
<div class="shadow-none p-3 mb-5 bg-light rounded">No shadow</div>
<div class="shadow-sm p-3 mb-5 bg-white rounded">Small shadow</div>
<div class="shadow p-3 mb-5 bg-white rounded">Regular shadow</div>
<div class="shadow-lg p-3 mb-5 bg-white rounded">Larger shadow</div> ]]></description>
        </item>
        <item>
            <title><![CDATA[Django Model]]></title>
            <link>https://velog.io/@ysj_log/Django-Model</link>
            <guid>https://velog.io/@ysj_log/Django-Model</guid>
            <pubDate>Mon, 19 Aug 2024 00:19:02 GMT</pubDate>
            <description><![CDATA[<h1 id="django-model">Django Model</h1>
<p> 
앞서 언급한 것처럼 장고의 모델은 DB 테이블을 결정짓는다.
즉, 모델에는 데이터가 저장될 때 어떤 필드에 저장될 것인지, 이 데이터가 저장될 때 어떤 동작을 할 것인지 등이 포함된다.
 </p>
<p>기초</p>
<p>각 모델은 django.db.models.Model의 서브클래스다
모델의 각 속성(attribute)는 DB의 필드(Field)를 의미한다
모델을 생성하면 Django는 자동으로 생성된 DB엑세스 API(save(), delete() 등)를 제공한다</p>
<p> 
모델 생성 및 사용
python# app/models.py</p>
<p>from django.db import models</p>
<p>class Person(models.Model):
    class Meta:
        db_table = &quot;person&quot;</p>
<pre><code>name = models.CharField(max_length=30)
email = models.EmailField()
birth = models.DateField()복사</code></pre><p>위와 같은 형태로 클래스를 정의해 모델을 정의할 수 있다
테이블의 이름을 정해주지 않으면 sqlite DB에 app_person형태로 테이블이 자동으로 만들어지지만, 메타데이터 서브클래스 Meta를 오버라이딩해서 db_table매개변수를 다시 정의해주면 person 등으로 테이블 이름으로 바꿔줄 수 있다
 
클래스의 각 속성은 위에 말한 것처럼 DB의 필드를 의미하는 것이며 속성 이름 = models.필드타입(옵션=옵션) 형태로 정의할 수 있다.
 
모델을 사용하기 위해서는 우선 장고가 우리가 만든 앱을 인식할 수 있도록 settings.py에 등록해주어야 한다.
그렇지 않으면 우리가 아무리 모델을 변경해주고 makemigrations 명령어로 migration을 만들어 주려고 해도 아래와 같이 감지하지 못한다
 
settings.py에 앱을 등록하지 않았을 경우</p>
<p> 
아래와 같이 등록하면 된다
 
python# mysite/settings.py</p>
<p>INSTALLED_APPS = [
    # ...
    &quot;app&quot;,
    # ...
]복사
app은 당연히 본인이 생성한 앱 이름으로 바꿔주어야 한다
 </p>
<p>필드(Fields)
모델을 구성하는 가장 중요한 부분이자 유일한 부분이다.
장고에서 DB의 필드는 파이썬의 클래스 속성으로 정의된다.
필드의 이름을 선택할 때 clean이나 save, delete와 같이 models API에 미리 정의되어 있는 이름과 겹치지 않도록 해야한다.
 </p>
<p>필드 타입(Field Type)
 </p>
<p>AutoField</p>
<p>자동으로 값이 증가하는 IntegerField.
PK값이 자동적으로 추가되므로 일반적으로 직접 사용할 일은 잘 없다
 
하지만 자동으로 생성되는 id라는 이름이 정 마음에 들지 않는다면 아래와 같이 변경해줄 수 있다.
 
python# app/models.py</p>
<p>from django.db import models</p>
<p>class User(models.Model):
    class Meta:
        db_table = &quot;user&quot;</p>
<pre><code>superduper_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=50)복사</code></pre><p>위와 같이 AutoField(primary_key=True)로 superduper_id라는 필드를 만들어 주었다
migrate를 하고 결과물을 보면 다음과 같다
id를 superduper_id로 바꿨다</p>
<p>테이블의 PK필드 이름이 잘 바뀐 것을 볼 수 있다.테이블의 PK는 단 하나만 존재해야 하므로 primary_key속성을 True로 설정하지 않으면 오류가 난다
 
 </p>
<p>IntegerField</p>
<p>정수 필드.
MinValueValidator와 MaxValueValidator를 이용해 값을 검증한다
-2147483648 ~ 2147483647까지 모든 DB에서 안전하게 사용할 수 있다
 
이말을 듣고 궁금해져서 테스트 해보았다
부호있는 4byte의 최댓값 +1</p>
<p>부호있는 4byte 최댓값 양수에 1을 더해줬을 때 오류없이 잘된다.
여러번 테스트를 한 끝에 결과적으로 9,223,372,036,854,775,808에서 아래와 같은 오류가 발생했다.
OverflowError: Python int too large to convert to SQLite INTEGER
즉, &#39;python에서는 문제없는데 SQLite에서 너무 큰 값은 처리 못해요&#39;다
원인은 현재 사용하고 있는 SQLite의 정수가 부호있는 8byte 값이기 때문이다.
따라서 2^64bit = 18,446,744,073,709,551,616의 절반까지의 양수까지 처리할 수 있다.
SQLite가 아닌 다른 DB는 다른 정수값 체계가 있을 수 있으므로 안전하게 사용하자
 
추가적으로 값을 검증하는 Min/MaxValueValidator를 이용해서 다음과 같이 활용할 수 있다
 
python# app/models.py</p>
<p>from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator</p>
<p>class User(models.Model):
    class Meta:
        db_table = &quot;user&quot;</p>
<pre><code>superduper_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=50)
age = models.IntegerField(validators=[MinValueValidator(18), MaxValueValidator(250)])복사</code></pre><p>만약 성인들만 이용할 수 있는 사이트를 만들고자 할 때 만18세 미만의 청소년들은 가입을 금지시킨다고 하자
그럴 때 위와 같이 django.core.validators의 Min/MaxValueValidator클래스를 이용해 값을 제한할 수 있다
결과는 다음과 같다
Age에 15세를 입력했을 때</p>
<p> </p>
<p>FloatField</p>
<p>파이썬의 float자료형과 대응되는 실수 필드.
이도 역시 위의 Min/MaxValueValidator클래스를 이용해 값을 제한할 수 있다
 
 </p>
<p>DecimalField(max_digits=None, decimal_places=None)</p>
<p>파이썬의 decimal자료형과 대응되는 실수 필드.
숫자의 최대 자릿수를 표현하는 max_digits와 소수부를 지정하는 decimal_places를 필수 인자로 가진다.
부동소수점인 Float에서 발생하는 무한소수 문제를 해결할 수 있지만 메모리를 많이 잡아먹는다
 
 </p>
<p>BooleanField</p>
<p>True/False로 구성된 필드. 
null=True 옵션을 적용하고 default옵션을 적용하지 않으면 기본값은 Null이 된다
Unknown, Yes, No 세가지 형태가 존재할 수 있다</p>
<p> 
 
 </p>
<p>CharField(max_length=<int>)</p>
<p>문자열 필드. 최대길이를 지정하는 max_length를 필수적으로 가져야 한다
 
 </p>
<p>TextField</p>
<p>긴 텍스트 필드. max_length가 필요없지만 만약 지정한다면 자동적으로 생성되는 form field에는 영향을 준다.
하지만 model이나 DB에는 영향을 주지 못한다.
max_length=20으로 적용했을 때 Introduce</p>
<p>위의 그림과 같이 max_length=20 옵션을 주면 20자 이상 텍스트를 작성할 수 없다
 
django shell로 Nancy의 introduce필드값을 변경</p>
<p>변경된 텍스트</p>
<p>하지만 위와 같이 DB에 직접 수정을 하면 max_length로 제한한 길이가 무색하게 잘 수정된다.
 
 </p>
<p>DateField / DateTimeField(auto_now=False, auto_now_add=False)</p>
<p>각각 파이썬의 datetime.date, datetime.datetime 객체로 표시되는 필드
 
 </p>
<p>TimeField(auto_now=False, auto_now_add=False)</p>
<p>파이썬의 datetime.time객체로 표시되는 필드.
 
 </p>
<p>EmailField</p>
<p>EmailValidator를 이용해 이메일의 유효성을 검증하는 CharField
 
 </p>
<p>FileField(upload_to=&quot;&quot;, storage=None, max_length=<int>)</p>
<p>파일필드. PK로 지정할 수 없다</p>
<p>upload_to : MEDIA_ROOT의 서브디렉토리를 결정하기 위한 옵션. settings.py에 MEDIA_ROOT=&#39;/media/&#39;를 설정하고 upload_to=&quot;photos/%Y/%m/%d&quot;를 설정했다면 파일은 home/media/photos/2023/04/19/file.jpg 형태로 저장된다.
storage : 다양한 환경에 따라 서로 다른 storage를 선택해야 할 때 사용하는 옵션. 자세한 내용은 여기</p>
<p> 
 </p>
<p>ImageField(upload_to=None, height_field=None, width_field=None, max_length=100)</p>
<p>업로드된 파일이 유효한 이미지인지를 검사하는 FileField
 
 
 </p>
<p>필드 옵션(Field Options)
모든 필드 타입에 사용가능한 옵션들이다
 </p>
<p>null</p>
<p>기본값은 False. True라면 DB에 비어있는 값을 NULL로 저장한다.
문자열 기반 필드에서 no data(데이터가 없음)을 의미하는 값이 NULL과 빈 문자열 두가지가 혼용될 수 있으므로 CharField나 TextField에는 사용하면 안된다. 
문자열 기반 필드에서 사용할 수 있는 한가지 예외는 unique=True옵션과 blank=True옵션이 함께 사용됐을 때다
이때는 빈값이 여러개 생성될 수 있으므로 unique=True옵션에 걸리지 않기 위해 null=True를 설정할 수 있다.
 
 </p>
<p>blank</p>
<p>기본값은 False. True라면 빈 문자열을 허용한다
null이 DB에 관계된(database-related) 이슈라면 blank는 유효성 검사와 관련(validation-related)된다.
blank=False라면 이 필드는 값이 필수다.
 
 </p>
<p>unique</p>
<p>unique=True라면 테이블 전체에서 값들이 유일한 값이어야 한다
ManyToManyField와 OneToOneField를 제외한 모든 필드 타입에서 사용할 수 있다
 
 </p>
<p>default</p>
<p>필드의 기본값을 설정한다.
어떤 value 혹은 callable한 객체가 들어갈 수 있다.(list, set같이 mutable한 객체는 불가)
만약 callable한 객체가 들어간다면 새로운 객체가 생성될 때마다 불릴 것이다
 
 </p>
<p>editable</p>
<p>editable=False라면 admin페이지나 ModelForm에서 보이지 않는다. 또한 모델 유효성 검사에서도 제외된다.
 
 
 </p>
<p>db_column</p>
<p>필드의 이름을 별도로 설정한다. 이 옵션을 따로 사용하지 않는다면 기본적인 필드 이름이 적용된다.
 
 
 </p>
<p>db_comment</p>
<p>Django 코드를 보지 않고 DB를 이용하는 사람들에게 각 칼럼의 comment를 달아줄 수 있다
 
 
 </p>
<p>choices</p>
<p>각 필드 값에 사람이 읽을 수 있는 값을 별도로 설정해줄 수 있다
[(A, B), (A, B), ...]형식으로 구성되고 A는 실제 DB에 저장되는 값, B는 사람이 읽을 수 있는 값이다
 
 
 </p>
<p>관계 필드(Relationship Fields)
각 Table의 관계를 나타내는 필드
 </p>
<p>ForeignKey(to, on_delete)</p>
<p>Many-to-One 관계.
현재 모델에 관련된 모델의 클래스(to)와 그 클래스의 row가 삭제됐을 때 현재 모델이 어떻게 행동할 지에 관한 on_delete옵션을 설정해주어야 한다.
모델 간의 관계를 설정할 때 상대 모델이 코드 상 뒤에 있어 NameError가 발생할 때, 문자열로 된 상대 모델의 이름으로 대체할 수 있다.(lazy relationship)
 
python# app/models.py</p>
<p>from django.db import models</p>
<p>class Car(models.Model):
    manufacturer = models.ForeignKey(
        &quot;Manufacturer&quot;,
        on_delete=models.CASCADE,
    )
    # ...</p>
<p>class Manufacturer(models.Model):
    # ...
    pass복사
 
위와 같은 경우 테이블의 필드에는 manufacturer_id라는 _id가 붙은 이름으로 저장된다.
만약 이 이름이 싫다면 db_column옵션으로 다른 이름을 지정해주면 된다
 
인수(Arguments)</p>
<p>on_delete : ForeignKey로 참조하는 객체가 삭제되었을 때 SQL의 행동을 결정한다(아래 옵션들은 django.db.models에 존재한다)</p>
<p>CASCADE : 자신이 참조하고 있는 테이블의 데이터가 삭제되면 자동으로 자신의 데이터도 삭제
PROTECT : ProtectedError를 발생시켜 참조된 데이터의 삭제를 방지한다
RESTRICT : RestrictedError를 발생시켜 참조된 데이터의 삭제를 방지한다. PROTECT와의 차이는 일부 특수한 상황에서 데이터의 삭제를 허용한다
SET_NULL : 자신이 참조하고 있는 테이블의 데이터가 삭제되면 NULL값으로 대체한다. null=True옵션일 때만 사용가능하다
SET_DEFAULT : default값으로 대체한다. ForeignKey에 default값이 미리 설정되어 있어야 한다
SET() : 어떤 호출된 결과로 대체한다
DO_NOTHING : 아무것도 하지 않는다</p>
<p>related_name : 참조된 객체로부터의 관계를 위한 이름. 역참조를 위한 이름이라고 생각하면 편하다.</p>
<p> </p>
<p>ManyToManyField(to)</p>
<p>many-to-many관계. 
 
 
 </p>
<p>OneToOneField(to, on_delete, parent_link=False)</p>
<p>one-to-one관계.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA["GET /static/css/style.css HTTP/1.1" 404 에러]]></title>
            <link>https://velog.io/@ysj_log/GET-staticcssstyle.css-HTTP1.1-404-%EC%97%90%EB%9F%AC</link>
            <guid>https://velog.io/@ysj_log/GET-staticcssstyle.css-HTTP1.1-404-%EC%97%90%EB%9F%AC</guid>
            <pubDate>Thu, 15 Aug 2024 23:45:08 GMT</pubDate>
            <description><![CDATA[<p>css스타일이 적용이 되지않아 찾아보니 이런 오류가 발생했다.</p>
<p><img src="https://velog.velcdn.com/images/ysj_log/post/6c3447e0-05c6-4c06-8a4e-76dcb81ff520/image.png" alt=""></p>
<p>도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?도대체 왜 이런 오류가 발생할까?</p>
<p>시력테스트
다음중 잘못된 부분을 찾으시오.
<img src="https://velog.velcdn.com/images/ysj_log/post/fbbbe453-0e92-4b84-804b-0d873fc10298/image.png" alt=""></p>
<p>정답은 STATICFILES_DIRS가 아니라 STATICFILES__DIRS라고 적었기 때문이다.
<img src="https://velog.velcdn.com/images/ysj_log/post/75ef81da-503b-4700-98fd-2ad71c6d31f9/image.png" alt="">
정상적으로 작동하는 것을 볼 수 있다.
하지만 나의 머리는 오류찾기로 데미지를 입어 정상적으로 작동하지 않는것도 볼 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹의 암호화 방식]]></title>
            <link>https://velog.io/@ysj_log/%EC%9B%B9%EC%9D%98-%EC%95%94%ED%98%B8%ED%99%94-%EB%B0%A9%EC%8B%9D</link>
            <guid>https://velog.io/@ysj_log/%EC%9B%B9%EC%9D%98-%EC%95%94%ED%98%B8%ED%99%94-%EB%B0%A9%EC%8B%9D</guid>
            <pubDate>Wed, 14 Aug 2024 00:40:31 GMT</pubDate>
            <description><![CDATA[<p>웹에서는 내가 원하는 정보를 열람하는 것뿐만 아니라, 내가 입력한 정보를 웹 사이트를 운영하는 회사의 시스템으로 전달하는 경우도 많습니다. 예를 들어, 포털 사이트에 내 계정 정보를 입력하고 로그인하거나, 은행 사이트에 접속하여 계좌 정보를 조회해 이체하는 경우가 이에 해당합니다. 만약 누군가가 이러한 개인 정보를 몰래 보거나, 이를 다시 악용한다면 더 이상 안전한 웹 서핑은 불가능할 것입니다.</p>
<p>이때 웹에서 정보를 보호하기 위한 가장 기본적인 기술이 HTTPS라고 할 수 있습니다. 이번 글에서는 HTTPS가 어떤 보안 기술로 브라우저와 웹 서버 사이의 통신을 지킬 수 있는지 알아보겠습니다.</p>
<p>HTTPS는 무엇인가?</p>
<p>HTTPS를 통한 암호화 통신 &lt;출처: 작가&gt;</p>
<p>웹은 안전한 통신을 위해 정보를 암호화합니다. 암호화란 일반적인 평문을 알아볼 수 없도록 암호화하여 암호문으로 만드는 과정입니다. 개인 정보가 담긴 평문을 암호화하고, 이렇게 만들어진 암호문을 상대방에게 전달하면, 상대방은 이를 다시 복호화 하여 원래의 평문으로 열람할 수 있습니다.</p>
<p>이와 같은 과정을 웹 브라우저와 웹 서버에 사용하는 대표적인 기술이 바로 HTTPS(Hypertext Transfer Protocol Secure)입니다. 인터넷 콘텐츠를 전달하는 TCP 프로토콜의 일종인 HTTP에 S(Secure) 기능을 더한 것이죠.</p>
<p>HTTPS의 원천 기술로는 SSL(Secure Socket Layer)과 TLS(Transport Layer Security) 전송 기술이 있습니다. 단어에서 알 수 있듯이 안전한 계층(layer)을 웹 통신에 추가하는 방식입니다. 이 기술을 수행하기 위해 웹 서버에 설치하는 것이 SSL/TLS 인증서입니다. TLS는 SSL의 개선 버전으로, 최신 인증서는 대부분 TLS를 사용하지만, 편의적으로 SSL 인증서라고 말합니다. 웹 브라우저는 공신력 있는 인증서의 정보를 브라우저 내부에 보관하고 있으며, 접속하는 웹 사이트에 믿을만한 인증서가 설치되어 있는지 확인합니다.</p>
<p>HTTPS는 안전한 데이터의 전달이 브라우저와 웹 서버 사이의 전달 구간에서 이루어지기 때문에, 보안 채널(secure channel), 전송 보안(secure transit)이라고 부르기도 합니다. </p>
<p>SSL 인증서와 SSL 핸드셰이크에 탑재된 기술
SSL 인증서 관련 프로세스에는 아래와 같은 보안 기술이 탑재되어 있습니다.</p>
<p>대칭키 암호화 방식
비대칭키 암호화 방식
통신 대상을 서로가 확인하는 신분 확인
믿을 수 있는 SSL 인증서를 위한 디지털 서명
디지털 서명을 해주는 인증 기관의 확인
공개키를 안전하게 전달하고 공유하기 위한 프로토콜
암호화된 메시지의 변조 여부를 확인하는 메시지 무결성 알고리즘</p>
<p>SSL에 사용된 보안 기술은 암호화, 인증, 서명, 공개키, 무결성 확인 등 매우 다양하기에 이것만 잘 이해하고 있어도, 웬만한 IT 보안 기술에 대한 기본은 이해할 수 있습니다. 이 중에서 대표적인 암호화 방식 두 개를 살펴보겠습니다.</p>
<p>대칭키 암호화 방식, 공개키 암호화 방식
대칭키와 공개키 암호화 방식의 차이 &lt;출처: 작가&gt;</p>
<p>1) 대칭키 암호화 방식
대칭키 암호화 방식이란 하나의 암호화키(key)로 평문을 암호화하고, 다시 암호문을 원해의 평문으로 복호화할 때 사용하는 방식입니다. 대문을 잠그는 자물쇠를 떠올려보면, 자물쇠를 잠근 열쇠만이 그 자물쇠를 다시 열 수 있습니다. 즉 잠그고 여는 것 모두가 하나의 열쇠를 사용합니다. 그러나 만약 이 열쇠를 잃어버렸고, 내 집 주소를 아는 사람이 열쇠를 주웠다면 어떤 상황이 될까요? 이렇듯 대칭키 암호화 방식은 키를 단 하나만 사용하는 간편함이 있지만, 키를 분실하거나 도난을 당한다면 내 암호문을 누군가가 복호화하여 볼 수 있다는 치명적인 단점이 있습니다.</p>
<p>2) 공개키 암호화 방식
공개키 암호화 방식은 공개키, 개인키 이렇게 두 개의 키를 한 쌍(키페어: key pair)으로 각각 암호화/복호화에 사용합니다. 일반적으로 공개키로 암호화한 것을 개인키로 복호화합니다. 개인키를 먼저 만들고, 여기서 공개키를 파생하여 한 쌍의 키를 만들기 때문에 키페어라고 부릅니다. 만약 같은 쌍이 아닌 다른 키를 사용하려 한다면 암호화/복호화가 불가능합니다.</p>
<p>공개키 방식은 대칭키 방식에 비해 안전하지만, 계산 과정이 복잡하고 연산 도중 컴퓨터의 자원이 많이 사용합니다. 그래서 실제 IT 시스템에서는 공개키 방식과 대칭키 방식을 적절히 혼합하여 사용합니다.</p>
<p>SSL 핸드셰이크 과정
SSL 핸드셰이크 과정
SSL 핸드셰이크 과정 &lt;출처: 작가&gt;</p>
<p>핸드셰이크(handshake)란 악수를 의미하는데요. 브라우저와 웹 서버가 서로 암호화 통신을 시작할 수 있도록 신분을 확인하고, 필요한 정보를 클라이언트와 서버가 주거니 받거니 하는 과정이 악수와 비슷하여 붙여진 이름입니다. 각 단계의 과정을 순서대로 알아보겠습니다.</p>
<p>클라이언트: ① 클라이언트에 해당하는 브라우저가 먼저 웹 서버에 접속합니다. (Client Hello)
웹 사이트 접속에 HTTPS를 사용하는 브라우저는 다음 정보를 Client Hello 단계에서 보냅니다.</p>
<p>브라우저가 사용하는 SSL 혹은 TLS 버전 정보
브라우저가 지원하는 암호화 방식 모음(cipher suite)
브라우저가 순간적으로 생성한 임의의 난수(숫자)
만약 이전에 SSL 핸드 셰이크가 완료된 상태라면, 그때 생성된 세션 아이디(Session ID)
기타 정보</p>
<p>cipher suite는보안의 궁극적 목표를 달성하기 위해 사용하는 방식을 패키지의 형태로 묶어 놓은 것을 의미합니다. 여기서 보안의 목표는 다음과 같습니다.</p>
<p>안전한 키 교환
전달 대상 인증
암호화 알고리즘
메시지 무결성 확인 알고리즘</p>
<p>서버: ② 웹 서버는 ①번에 응답하면서 아래 정보를 클라이언트에 제공합니다. (Server Hello)
브라우저의 암호화 방식 정보 중에서 서버가 지원하고 선택한 암호화 방식(cipher suite)
서버의 공개키가 담긴 SSL 인증서. 인증서는 CA의 비밀키로 암호화되어 발급된 상태입니다.
서버가 순간적으로 생성한 임의의 난수(숫자)
클라이언트 인증서 요청(선택사항)</p>
<p>클라이언트: ③ 브라우저는 서버의 SSL 인증서가 올바른지 확인합니다.
대부분 브라우저에는 공신력 있는 CA들의 정보와 CA가 만든 공개키가 이미 설치되어 있습니다. 서버가 보낸 SSL 인증서가 정말 CA가 만든 것인지를 확인하기 위해, 내장된 CA 공개키로 암호화된 인증서를 복호화합니다. 정상적으로 복호화되었다면 CA가 발급한 것이 증명되는 셈입니다. 만약 등록된 CA가 아니거나, 등록된 CA가 만든 인증서처럼 꾸몄다면 이 과정에서 발각이 되며 브라우저 경고를 보냅니다.</p>
<p>클라이언트: ④ 브라우저는 자신이 생성한 난수와 서버의 난수를 사용하여 premaster secret을 만듭니다.
웹 서버 인증서에 딸려 온 웹 사이트의 공개키로 이것을 암호화하여 서버로 전송합니다.</p>
<p>서버: ⑤ 서버는 사이트의 비밀키로, 브라우저가 보낸 premaster secret 값을 복호화합니다.
복호화한 값을 master secret 값으로 저장합니다. 이것을 사용하여 방금 브라우저와 만들어진 연결에 고유한 값을 부여하기 위한 세션키를 생성합니다. 세션키는 대칭키 암호화에 사용할 키입니다. 이것으로 브라우저와 서버 사이에 주고받는 데이터를 암호화하고 복호화합니다.</p>
<p>서버/클라이언트: ⑥ SSL 핸드셰이크를 종료하고 HTTPS 통신을 시작합니다.
브라우저와 서버는 SSL 핸드셰이크가 정상적으로 완료되었습니다. 이제는 웹상에서 데이터를 세션키를 사용해 암호화/복호화하며, HTTPS 프로토콜을 통해 주고받을 수 있습니다. HTTPS 통신이 완료되는 시점에서 서로에게 공유된 세션키를 폐기합니다. 만약 세션이 여전히 유지되고 있다면 브라우저는 SSL 핸드셰이크 요청이 아닌 세션 ID만 서버에게 알려주면 됩니다. 이 부분은 ①에서 언급했습니다.</p>
<p>SSL 핸드셰이크 과정은 구현체마다 조금씩 다른 옵션을 가지고 있지만, 대부분의 원리는 위의 내용에서 크게 벗어나지 않습니다. SSL 인증서에는 대칭키 방식과 공개키 방식 두 개 모두 사용하며, 모든 웹 콘텐츠의 전달을 공개키 방식으로 한다면 웹 서버와 브라우저에 많은 부담이 됩니다. 그래서 SSL 핸드셰이크 단계까지는 공개키 방식, 그 이후의 HTTPS 통신은 대칭키 방식을 사용합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Django 사용법 흐름]]></title>
            <link>https://velog.io/@ysj_log/Django-%EC%82%AC%EC%9A%A9%EB%B2%95-%ED%9D%90%EB%A6%84</link>
            <guid>https://velog.io/@ysj_log/Django-%EC%82%AC%EC%9A%A9%EB%B2%95-%ED%9D%90%EB%A6%84</guid>
            <pubDate>Mon, 12 Aug 2024 00:09:56 GMT</pubDate>
            <description><![CDATA[<p>장고를 설치했다고 가정하에 설명하겠다.</p>
<p><code>django-admin startproject &lt;프로잭트명&gt;</code>: 장고 프로잭트 생성</p>
<p><code>django startapp &lt;앱이름&gt;</code>: 장고 앱 생성</p>
<p>base templates폴더 만든 후 기본 html 파일 생성</p>
<p>{% block %}을 이용해 기본 틀 마련 후 settings에 templates부분 BASE DIR / templates로 경로 설정</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[정보 은닉]]></title>
            <link>https://velog.io/@ysj_log/%EC%A0%95%EB%B3%B4-%EC%9D%80%EB%8B%89</link>
            <guid>https://velog.io/@ysj_log/%EC%A0%95%EB%B3%B4-%EC%9D%80%EB%8B%89</guid>
            <pubDate>Fri, 09 Aug 2024 01:08:04 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-python">class Person:
    def __init__(self, name, age, adress=None):
        self.__name = name
        self.__age = age
        self.__adress = adress

    def set_name(self, name):
        if len(name) &gt;= 2:
            self.__name = name
        else:
            print(&quot;이름은 두 글자 이상 넣어주세요.&quot;)

    def get_name(self):
        return self.__name


    def set_age(self, age):
        if age &gt; 0:
            self.__age = age
        else:
            print(&quot;나이는 0보다 큰 값이여야합니다.&quot;)

    def get_age(self):
        return self.__age

    name = property(get_name, set_name)
    age = property(get_age, set_age)



p = Person(&#39;유지민&#39;, 22, &#39;수원&#39;) ##private(_Person4__age)에 해당 값이 들어감

print(dir(p)) ##_Person__age(private)와 __age(거짓정보)라는 두개의 인스턴스가 생성된것을 확인할 수 있다.
print(p.__dict__) ##Person의 private 값을 딕셔너리로 출력

p._Person__age = 25 ##_Person__age(private)에 해당 값을 할당
# print(p.__age) ##_age(거짓정보)는 없으므로 에러 발생

p.__name = &#39;손흥민&#39; ##__name(거짓정보)에 해당 값을 할당
p.set_name(&#39;김범수&#39;) ##_Person__name(private)에 해당 값을 할당

p.__age = 30 ##__age(거짓정보)에 해당 값을 할당
p.set_age(40) ##_Person__age(private)에 해당 값을 할당

print(p.get_age()) ##__age의 private 값을 딕셔너리로 출력
print(p.get_name()) ##__name의 private 값을 딕셔너리로 출력

p = Person(&#39;손흥민&#39;, 30, &#39;부산&#39;)
p.name = &quot;김범수&quot; ##property에 의해 setter 부분의 메소드인 set_name의 매개변수에 할당됨
print(p.name) ##private(_Person_name)의 값을 출력

p.age = 40 ##property에 의해 setter 부분의 메소드인 set_age의 private(_Person_age)에 할당됨
print(p.age) ##private(_Person_age)의 값을 출력</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Django 사용하기]]></title>
            <link>https://velog.io/@ysj_log/Django-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ysj_log/Django-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 08 Aug 2024 00:21:38 GMT</pubDate>
            <description><![CDATA[<h1 id="django-설정">Django 설정</h1>
<ul>
<li><p><code>$ pip install django</code> : 장고 설치</p>
</li>
<li><p><code>$ django-admin startproject my_project</code> : my_project 디렉토리 및 관련 파일 설치</p>
</li>
<li><p><code>$ cd my_project</code> : my_project디렉토리로 이동</p>
</li>
<li><p><code>$ python manage.py migrate</code> : migrate를 해주면 Sqlite3파일이 생성</p>
</li>
<li><p><code>$ python manage.py runserver</code> : 장고 프로젝트 실행하기</p>
</li>
<li><p><code>$ python manage.py startapp main</code> : main페이지 만들기</p>
</li>
<li><pre><code class="language-python">INSTALLED_APPS = [
  &#39;django.contrib.admin&#39;,
  &#39;django.contrib.auth&#39;,
  &#39;django.contrib.contenttypes&#39;,
  &#39;django.contrib.sessions&#39;,
  &#39;django.contrib.messages&#39;,
  &#39;django.contrib.staticfiles&#39;,
  &#39;main&#39;,
]
</code></pre>
</li>
</ul>
<p><code>my_project/settings.py</code> 에 <code>INSTALLED_APPS</code> 에 위 코드를 추가
<code>my_project/main/templates/main</code> 폴더를 만든 후 index.html파일 만들기</p>
<ul>
<li><pre><code class="language-python">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;title&gt;Title&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;/body&gt;
&lt;/html&gt;

</code></pre>
</li>
</ul>
<p>main/views.py에 다음 코드를 추가하여 인코딩</p>
<pre><code class="language-python">from django.shortcuts import render</code></pre>
<h1 id="view-만들기">View 만들기</h1>
<pre><code class="language-python">def index(request):
    return render(request,&#39;main/index.html&#39;)</code></pre>
<p>main/urls.py파일을 만들어 아래의 코드를 추가하여 view와 url을 연결</p>
<pre><code class="language-python">from django.urls import path

from . import views


urlpatterns = [
    path(&#39;&#39;, views.index, name=&#39;index&#39;),
]</code></pre>
<p>my_project/urls.py에서 아래와 같이 변경 후 앱의 url과 프로젝트의 url을 연결</p>
<pre><code class="language-python">from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path(&#39;admin/&#39;, admin.site.urls),
    path(&#39;&#39;, include(&#39;main.urls&#39;)),
]</code></pre>
<p><code>$ python manage.py runserver</code> : 페이지를 호스팅</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TCP/IP 4계층]]></title>
            <link>https://velog.io/@ysj_log/TCPIP-4%EA%B3%84%EC%B8%B5</link>
            <guid>https://velog.io/@ysj_log/TCPIP-4%EA%B3%84%EC%B8%B5</guid>
            <pubDate>Wed, 07 Aug 2024 00:34:55 GMT</pubDate>
            <description><![CDATA[<p>컴퓨터 간 100110110과 같은 데이터를 주고 받을때는 여러 문제점이 생기게 된다.
먼저 해당 데이터를 전기신호로 바꾸어 주어야 컴퓨터간의 데이터 교환을 할 수 있게 된다. 즉 디지털 신호를 아날로그 신호로 바꾸어야한다.
하지만 문제가 발생하게 되는데 <span style=color:red>100110110</span>다음 <span style=color:skyblue>1011011101</span>의 데이터를 주고 받을때는 두 데이터가 겹처지게 되고 이는 전혀 다른 데이터인 <span style=color:red>100110110</span><span style=color:skyblue>1011011101</span> 이 되게 된다. 이때 데이터끼리 시작과 끝을 구분지어 주게 된다.
또한 해당 데이터가 어떤 컴퓨터로 와야하는지를 알려주어야 한다. 만약 내가 집에서 컴퓨터와 스마트폰을 쓰고 있다고 한다. 내가 친구한테 메세지를 폰으로 받으려고 하는데, 해당 메세지 데이터는 어떤 기기로 가야할 지에 대한 정보가 없다. 이에 대한 정보를 패킷에 만들어주는 역할이 1계층에서 진행된다.</p>
<p>또한, 컴퓨터가 여러대 있다고 생각해보자. 그러면 해당 데이터는 어떤 컴퓨터로 데이터를 주고 받을지 구분이 되어있지 않다. 따라서 어떤 ip주소 혹은 라우터로 보낼지에 대한 정보를 추가해주는게 2계층의 역할이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[synchronous(동기)와 asynchronous(비동기)]]></title>
            <link>https://velog.io/@ysj_log/synchronous%EB%8F%99%EA%B8%B0%EC%99%80-asynchronous%EB%B9%84%EB%8F%99%EA%B8%B0</link>
            <guid>https://velog.io/@ysj_log/synchronous%EB%8F%99%EA%B8%B0%EC%99%80-asynchronous%EB%B9%84%EB%8F%99%EA%B8%B0</guid>
            <pubDate>Mon, 05 Aug 2024 23:57:25 GMT</pubDate>
            <description><![CDATA[<h3 id="동기와-비동기">동기와 비동기</h3>
<ul>
<li><p><strong>동기(synchronous)</strong>는 어떤 작업을 진행할 때 순차적으로 진행하는 방식이다. 여러 작업을 수행해야 할 때 순차적으로 진행하는 방식이다. 한 작업이 끝난 후 다음작업을 진행하게된다.</p>
</li>
<li><p><strong>비동기(asynchronous)</strong>는 어떤 작업을 진행할때 그 작업이 완료되지 않더라도 다음 코드를 실행하는 방식이다. 한 작업이 진행중임에도 다른 작업을 진행하게 된다. 즉, 병렬처리가 가능하다. 
비동기 프로그래밍은 일반적으로 이벤트 기반(event-driven)이나 콜백(callback) 기반으로 구현된다. 
비동기 프로그래밍은 주로 I/O 작업이 많은 경우나 여러 작업을 동시에 처리해야 하는 경우에 특히 유용합니다. 네트워크 통신, 웹 개발, 데이터베이스 액세스, 파일 입출력 등의 작업은 대부분 I/O 작업이므로 비동기 방식으로 처리하는 것이 효과적입니다.</p>
</li>
</ul>
<h3 id="비동기를-사용하는-이유">비동기를 사용하는 이유</h3>
<ul>
<li><p>응답성(Responsiveness): 병렬처리를 통해 여러 작업을 동시에 수행함으로, 사용자가 작업요청 후 응답을 기다리는 불필요한 시간을 줄여준다.</p>
</li>
<li><p>확장성(Scalability): 여러 작업을 동시에 실행하므로 웹 서버, 네트워크 서비스, 데이터 파이프라인 등과 같은 시스템의 확장성을 향상시키는 데 도움이 된다</p>
</li>
<li><p>자원 효율성(Resource Efficiency): 놀고있는 CPU나 메모리의 공간을 활용할 수 있다.</p>
</li>
<li><p>병렬성(Concurrency): 여러 작업이 동시에 실행될 수 있으며, 이는 멀티코어 프로세서를 활용하여 작업을 분산 처리할 수 있다.</p>
</li>
</ul>
<h3 id="파이썬에서의-비동기-구동">파이썬에서의 비동기 구동</h3>
<ul>
<li><strong>일반적인 방식</strong></li>
</ul>
<p>다음은 비동기를 사용하기 전 sum()함수를 사용하여 결과값을 출력하는 함수이다.</p>
<pre><code class="language-python">import time


def sleep():
    time.sleep(1)


def sum(name, numbers):
    start = time.time()
    total = 0
    for number in numbers:
        sleep()
        total += number
        print(f&#39;작업중={name}, number={number}, total={total}&#39;)
    end = time.time()
    print(f&#39;작업명={name}, 걸린시간={end-start}&#39;)
    return total


def main():
    start = time.time()

    result1 = sum(&quot;A&quot;, [1, 2])
    result2 = sum(&quot;B&quot;, [1, 2, 3])

    end = time.time()
    print(f&#39;총합={result1+result2}, 총시간={end-start}&#39;)


if __name__ == &quot;__main__&quot;:
    main()</code></pre>
<p>sum()함수에 의해 numbers의 요소를 더할 때 마다 1초씩 걸리며, 결과는 다음과 같다.</p>
<pre><code>작업중=A, number=1, total=1
작업중=A, number=2, total=3
작업명=A, 걸린시간=2.000162124633789
작업중=B, number=1, total=1
작업중=B, number=2, total=3
작업중=B, number=3, total=6
작업명=B, 걸린시간=3.0002427101135254
총합=9, 총시간=5.0004048347473145</code></pre><ul>
<li><strong>비동기 적용</strong></li>
</ul>
<p>다음은 위 코드에 async를 적용한 것이다.</p>
<pre><code class="language-python">import asyncio
import time


async def sleep():
    await asyncio.sleep(1)


async def sum(name, numbers):
    start = time.time()
    total = 0
    for number in numbers:
        await sleep()
        total += number
        print(f&#39;작업중={name}, number={number}, total={total}&#39;)
    end = time.time()
    print(f&#39;작업명={name}, 걸린시간={end-start}&#39;)
    return total


async def main():
    start = time.time()

    task1 = asyncio.create_task(sum(&quot;A&quot;, [1, 2]))
    task2 = asyncio.create_task(sum(&quot;B&quot;, [1, 2, 3]))

    await task1
    await task2

    result1 = task1.result()
    result2 = task2.result()

    end = time.time()
    print(f&#39;총합={result1+result2}, 총시간={end-start}&#39;)


if __name__ == &quot;__main__&quot;:
    asyncio.run(main())</code></pre>
<p>async를 적용한 비동기 함수를 코루틴이라 하며, async는 def앞에 await은 호출한 함수 앞에 붙여 사용한다.
코루틴 진행중 await을 만나면 await로 호출한 코루틴이 종료될 때까지 기다리지 않고 제어권을 메인 스레드나 다른 코루틴으로 넘긴다.</p>
<p>이때 sleep함수에서 <code>time.sleep(1)</code>이 아닌 <code>async.sleep(1)</code>을 사용해서 비동기 출력이 가능하다.</p>
<p><code>asyncio.create_task()</code>는 수행할 코루틴 작업(태스크)을 생성한다. 여기서는 작업을 생성할 뿐이지 실제로 코루틴이 수행되는 것은 아니다. 실제 코루틴 실행은 await 태스크가 담당한다.</p>
<pre><code>작업중=A, number=1, total=1
작업중=B, number=1, total=1
작업중=A, number=2, total=3
작업명=A, 걸린시간=2.000617742538452
작업중=B, number=2, total=3
작업중=B, number=3, total=6
작업명=B, 걸린시간=3.000927209854126
총합=9, 총시간=3.000927209854126</code></pre><p>제어권이 await에 의해 계속 바뀌게 되어 A작업과 B작업을 번갈아가며 수행한다.
B작업의 수행시간이 5.x에서 3.x로 줄어든 것을 확인할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Django 사용]]></title>
            <link>https://velog.io/@ysj_log/Django-%EC%82%AC%EC%9A%A9</link>
            <guid>https://velog.io/@ysj_log/Django-%EC%82%AC%EC%9A%A9</guid>
            <pubDate>Mon, 05 Aug 2024 00:14:14 GMT</pubDate>
            <description><![CDATA[<ol>
<li>Django 설치
설치 전에 장고란 무엇인가 간단히 살펴보겠습니다.</li>
</ol>
<p>Django(/dʒæŋɡoʊ/ jang-goh/쟁고/장고)는 파이썬으로 만들어진 무료 오픈소스 웹 애플리케이션 프레임워크(web application framework)입니다. 쉽고 빠르게 웹사이트를 개발할 수 있도록 돕는 구성요소로 이루어진 웹 프레임워크입니다.</p>
<p>웹사이트를 구축할 때, 비슷한 유형의 요소들이 항상 필요합니다. 회원가입, 로그인, 로그아웃과 같이 사용자 인증을 다루는 방법이나 웹사이트의 관리자 패널, 폼, 파일 업로드와 같은 것들이 있습니다.</p>
<p>그래서 많은 사람들이 바로 사용할 수 있는 구성요소들을 갖춘 여러 프레임워크를 만들습니다. 장고도 그 중 하나입니다.</p>
<p>비유를 하자면, 편지(request, 요청)가 도착했는지 확인해주는 메일박스(port, 포트)가 있고 이 것은 웹서버가 해주는 일입니다. 웹 서버는 받은 편지를 읽고 웹 페이지와 함께 답장을 준니다. 그런데 무언가를 주고 싶을 때는 그 안에 내용이 있어야 하는데, 장고는 그 특정 콘텐츠를 만들 수 있는 역할을 합니다.</p>
<p>아래 명령어로 장고를 설치합니다.</p>
<p>pip install django
Django 프로젝트
이번장에서는 Django 기본 프로젝트를 생성하고, 생성한 프로젝트로 서버를 실행한 후 브라우저를 통해 접속하는 과정을 알아보겠습니다. Django는 node.js의 express 모듈처럼 간단한 명령어로 기본 프로젝트를 생성할 수 있으며 관리자 기능까지 제공합니다.</p>
<p>manage.py는 사이트 관리를 도와주는 유틸리티입니다. </p>
<p>settings.py는 웹사이트 설정이 있는 파일입니다.</p>
<p>urls.py파일은 urlresolver가 사용하는 패턴 목록을 포함하고 있습니다.</p>
<p>가. Django 프로젝트 생성
프로젝트를 생성하기 위해 wsl에 접속하여 프로젝트를 생성할 디렉토리로 이동합니다. 본 문서에서는 /mnt/d/django 아래에 생성하겠습니다. /mnt/d/django 디렉토리에서 아래와 같이 명령어를 입력합니다.</p>
<p>mkdir /mnt/d/django
cd /mnt/d/django
django-admin startproject mysite
그러면 mysite라는 디렉토리가 하나 생성되고, 디렉토리 내부에는 manage.py 파일과 함께 프로젝트이름과 동일한 디렉토리가 하나 더 생성되어 있는것을 확인할 수 있습니다. 아래와 같은 디렉토리와 파일이 생성됩니다.</p>
<p>mysite
├───manage.py
└───mysite
        settings.py
        urls.py
        wsgi.py
        <strong>init</strong>.py
settings.py 파일을 열어 한국시간과 한글로 설정을 변경합니다. 기본은 UTC와 영어(en_us)로 되어 있습니다.</p>
<p>timezone 설정 : TIME_ZONE = &#39;Asia/Seoul&#39;
언어설정 : LANGUAGE_CODE = &#39;ko&#39;  </p>
<p>Database 설정 확인 : 기본적으로 sqlite DB를 사용하는데 DB명 등을 변경할 수 있습니다.</p>
<p>DATABASES = {
    &#39;default&#39;: {
        &#39;ENGINE&#39;: &#39;django.db.backends.sqlite3&#39;,
        &#39;NAME&#39;: BASE_DIR / &#39;db.sqlite3&#39;,
    }
}</p>
<p>나. 데이터베이스 생성
데이터베이스를 생성하기 위해서 콘솔 창에서 아래 코드를 실행합니다. 위에서 생성한 /mnt/d/django/mysite 디렉토리에서 </p>
<p>python3 manage.py migrate 명령어를 실행합니다. 데이터베이스와 함께 테이블들을 생성합니다.</p>
<p>/mnt/d/django/mysite$ python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK</p>
<p>다. Django 웹서버 실행
이제 /mnt/d/django/mysite디렉토리에서 아래 명령어를 입력하여 웹서버를 실행합니다.</p>
<p>python3 manage.py runserver</p>
<p>/mnt/d/django/mysite$ python3 manage.py runserver
Watching for file changes with StatReloader
Performing system checks...</p>
<p>System check identified no issues (0 silenced).
February 09, 2022 - 21:25:47
Django version 4.0.2, using settings &#39;mysite.settings&#39;
Starting development server at <a href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a>
Quit the server with CONTROL-C.</p>
<p>라. 브라우저로 접속 테스트
브라우저를 열고 주소창에 <a href="http://127.0.0.1:8000">http://127.0.0.1:8000</a> 을 입력합니다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[패키지 사용법]]></title>
            <link>https://velog.io/@ysj_log/%ED%8C%A8%ED%82%A4%EC%A7%80-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@ysj_log/%ED%8C%A8%ED%82%A4%EC%A7%80-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Fri, 02 Aug 2024 00:30:07 GMT</pubDate>
            <description><![CDATA[<p>다음은 패키지의 가능한 구조이다.</p>
<pre><code>sound/                          #Top-level package
      __init__.py               #Initialize the sound package
      formats/                  #Subpackage for file format conversions
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  #Subpackage for sound effects
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  #Subpackage for filters
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...</code></pre><p>sys.path패키지를 가져올 때, Python은 패키지 하위 디렉터리를 찾기 위해 디렉터리를 검색합니다.</p>
<p>이 <strong>init</strong>.py파일은 Python이 파일을 포함하는 디렉토리를 패키지로 취급하도록 하는 데 필요합니다(최근 버전에서는 <strong>init</strong>.py를 사용하지 않아도 알아서 구분하기때문에 사용자에 취향에 따라 사용할지 결정). 이렇게 하면 와 같은 일반적인 이름을 가진 디렉토리가 모듈 검색 경로에서 나중에 발생하는 유효한 모듈을 의도치 않게 숨기는 것을 방지할 수 있습니다.</p>
<p>패키지 사용자는 다음과 같이 패키지에서 개별 모듈을 가져올 수 있습니다.</p>
<p><code>import sound.effects.echo</code>
이것은 하위 모듈을 로드합니다 sound.effects.echo. 전체 이름으로 참조해야 합니다.</p>
<p><code>ound.effects.echo.echofilter(input, output, delay=0.7, atten=4)</code>
하위 모듈을 가져오는 또 다른 방법은 다음과 같습니다.</p>
<p><code>from sound.effects import echo</code>
이렇게 하면 하위 모듈이 로드 echo되고 패키지 접두사 없이 사용할 수 있으므로 다음과 같이 사용할 수 있습니다.</p>
<p><code>echo.echofilter(input, output, delay=0.7, atten=4)</code>
또 다른 변형은 원하는 함수나 변수를 직접 가져오는 것입니다.</p>
<p><code>from sound.effects.echo import echofilter</code>
다시 말해서, 이렇게 하면 하위 모듈이 로드되지만 echo해당 기능을 echofilter()직접 사용할 수 있습니다.</p>
<p><code>echofilter(input, output, delay=0.7, atten=4)</code>
를 사용할 때, 항목은 패키지의 하위 모듈(또는 하위 패키지)이거나, 함수, 클래스 또는 변수와 같이 패키지에 정의된 다른 이름일 수 있습니다. 명령문은 먼저 항목이 패키지에 정의되어 있는지 테스트합니다. 정의되어 있지 않으면 모듈이라고 가정하고 로드를 시도합니다. 찾지 못하면 예외가 발생합니다.<code>from package import itemimportImportError</code></p>
<p>반대로, 와 같은 구문을 사용할 때 마지막 항목을 제외한 각 항목은 패키지여야 합니다. 마지막 항목은 모듈이나 패키지가 될 수 있지만 이전 항목에서 정의된 클래스, 함수 또는 변수가 될 수 없습니다.<code>import item.subitem.subsubitem</code></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CPU의 구조]]></title>
            <link>https://velog.io/@ysj_log/CPU%EC%9D%98-%EA%B5%AC%EC%A1%B0</link>
            <guid>https://velog.io/@ysj_log/CPU%EC%9D%98-%EA%B5%AC%EC%A1%B0</guid>
            <pubDate>Wed, 31 Jul 2024 06:44:51 GMT</pubDate>
            <description><![CDATA[<h1 id="개요">개요</h1>
<p> CPU(Central Processing Unit)은 주 기억장치인 메모리에서 명령어를 읽고 해석하여 수행하는 작업을 한다. CPU의 주요 구성 요소로는 <span style=color:skyblue>산술 및 논리 연산</span> 을 수행하는 ALU(Arithmetic[산수] Logic), 명령어의 순서와 수행을 <span style=color:skyblue>제어</span>하는 제어유닛(Control Unit),그리고 중간 결과와 작업 상태를 <span style=color:skyblue>저장</span>하는 Register가 있다.</p>
<hr>
<h2 id="alu">ALU</h2>
<p> ALU는 산술 및 논리 연산을 처리한다. </p>
<ul>
<li><p>산술연산: 사칙연산</p>
</li>
<li><p>논리연산: AND, OR, NOT 과 같은 비트 논리 연산, 비트 시프트 연산</p>
<p><img src="https://velog.velcdn.com/images/ysj_log/post/c99ddedc-7f41-45cc-8869-19008593e19c/image.png" alt=""></p>
<p>위 그림은 ALU의 구조이며, 레지스터를 통해 입력받은 피연산자(Integer Operand)와 제어 유닛으로 부터 받은 명령 코드(opcode)를 통해 연산을 수행하며 결과값(Integer Result)을 다시 레지스터로 반환한다.</p>
<p>또한 ALU의 연산 결과를 플래그 레지스터에 저장함으로써, 추가적인 상태 정보(플래그)를 제공할 수 있다. 이는 연산 결과가 양수 또는 음수인지, 오버플로우(연산 결과가 레지스터의 용량을 초과한 경우)가 발생했는지 등의 정보를 나타낸다.</p>
<h3 id="flag-register">Flag register</h3>
<p>Flag register는 CPU 내부 기구중 하나로 산술 연산 결과의 상태를 보여주는 flag bit들이 모인 레지스터이다.
산술 연산시 CPU에 의해 자동적으로 세팅되며, 프로세서의 현재 상태를 결정한다.
상태레지스터라고 불리고 기종에 따라 condition register라고 불리기도한다.</p>
<p>1) 상태 플래그 (Status Flag)</p>
<table>
<thead>
<tr>
<th>Flag</th>
<th>기능</th>
</tr>
</thead>
<tbody><tr>
<td>Carry Flag (CF)</td>
<td>Unsigned overflow가 발생할 때 1로 세팅된다.</td>
</tr>
<tr>
<td>Parity Flag (PF)</td>
<td>연산결과에 1인 bit의 개수가 짝수개이면 1 , 홀수개이면 0으로 세팅된다.</td>
</tr>
<tr>
<td>Auxiliary Flag (AF)</td>
<td>연산결과 하위 4bit에 Unsigned overflow가 발생했을때 1로 세팅된다.</td>
</tr>
<tr>
<td>Zero Flag (ZF)</td>
<td>연산결과가 0일 때 1로 세팅된다.</td>
</tr>
<tr>
<td>Sign Flag (SF)</td>
<td>부호를 나타내는 flag로 연산결과의 MSB(Most Significant Bit)와 같다. 연산결과가 양수이면 0 , 음수이면 1로 세팅된다.</td>
</tr>
<tr>
<td>Overflow Flag (OF)</td>
<td>Signed overflow가 발생할 때 1로 세팅된다.</td>
</tr>
</tbody></table>
<p>2) 컨트롤 플래그 (Control flag) : CPU의 동작상태를 제어하는 flag</p>
<table>
<thead>
<tr>
<th>Flag</th>
<th>기능</th>
</tr>
</thead>
<tbody><tr>
<td>Trap Flag (TF)</td>
<td>Trap flag가 1로 세팅되면 명령어를 한개 수행하고 , 0x01 inturrupt (the debug interrupt)를 발생시키게 되는데 0x01 inturrupt가 발생하면 디버거가 해당 프로세스를 attach 할 수 있는 상태가 된다.</td>
</tr>
<tr>
<td>Interrupt enable Flag (IF)</td>
<td>Interrupt enable Flag가 1로 세팅되면 외부 인터럽트 요구는 무시되고 , 0으로 세팅되면 외부 인터럽트요구를 받아들인다.</td>
</tr>
<tr>
<td>Direction Flag (DF)</td>
<td>데이터를 다른 메모리에 복사할때 방향을 결정하는 flag이다. Direction flag가 0으로 세팅되있을동안 데이터 주소를 가르키는 레지스터가 증가하고 , 1로 세팅되있을동안 데이터 주소를 가르키는 레지스터가 감소한다.</td>
</tr>
</tbody></table>
<ul>
<li><p>연산에 따른 Flag Bit</p>
<ol>
<li>Signed</li>
</ol>
<p>|      | CF | ZF | SF | OF</p>
</li>
<li><p>---|----|----|----|----|----
ADD|    X&gt;0 , Y&gt;0 , X+Y&lt;RANGE|    0|    0|    0|    0
ADD|    X&gt;0 , Y&gt;0 , X+Y&gt;RANGE|    0|    0|    1|    1
SUB|    X&gt;0 , Y&gt;0 , X&gt;Y| 0|    0| 0| 0
SUB|    X&gt;0 , Y&gt;0 , X&lt;Y|    1|    0|    1|    0
SUB|    X&gt;0 , Y&gt;0 , X=Y|    0|    1|    0|    0</p>
<ol start="2">
<li><p>Unsigned</p>
<p>|   | CF | ZF | SF | OF</p>
</li>
</ol>
</li>
<li><p>---|----|----|----|----|----
ADD|    X&gt;0 , Y&gt;0 , X+Y&lt;RANGE    |0    |0    |0    |0
ADD|    X&gt;0 , Y&gt;0 , X+Y&gt;RANGE    |1    |0    |1    |0
SUB|    X&gt;0 , Y&gt;0 , X&gt;Y    |0    |0    |0    |0
SUB|    X&gt;0 , Y&gt;0 , X&lt;Y    |1    |0    |1    |0
SUB|    X&gt;0 , Y&gt;0 , X=Y    |0    |1    |0    |0</p>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="control-unit">Control Unit</h2>
<p><img src="https://velog.velcdn.com/images/ysj_log/post/ef369031-d36e-4c75-8d6f-603547f4dce7/image.png" alt=""></p>
<ol>
<li><p>CU는 Clock에서 신호를 받는다. 이때 클럭은 특정 주기로 반복되는 신호로서 제어장치가 타이밍을 맞추어 다른 장치들과 동기화를 하는데 중요한 역할을 한다.</p>
</li>
<li><p>명령 레지스터와 Flag 레지스터로 부터 명령어와 Flag를 받아 제어신호를 발생시킴</p>
</li>
<li><p>Cpu 내부 혹은 Control Bus로 신호를 보내고(출력), 받아들인다.(입력)</p>
</li>
</ol>
<hr>
<h2 id="register">Register</h2>
<ol>
<li>Program Counter, PC: 메모리에서 읽어 들일 명령어의 주소를 저장</li>
<li>Command Register, Instruction Register, IR: 현재 CPU가 해석하고 있는 명령어를 저장</li>
<li>Memory Address Register, MAR: 메모리의 주소를 저장</li>
<li>Memory Buffer Register, MBR: 메모리와 주고받을 데이터와 명령어를 저장</li>
<li>General Purpose Register: 다양하고 일반적인 상황에서 자유롭게 사용</li>
<li>Flag Register: CPU가 수행한 최근 연산에 대한 정보, 그리고 CPU의 현재 상태를 나타내는 여러 플래그를 저장</li>
<li>Stack pointer: 스택의 Top을 가리키는 레지스터</li>
<li>Base-register: 기준 주소를 나타내는 레지스터</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[빅데이터와 인공지능]]></title>
            <link>https://velog.io/@ysj_log/%EB%B9%85%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%99%80-%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5</link>
            <guid>https://velog.io/@ysj_log/%EB%B9%85%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%99%80-%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5</guid>
            <pubDate>Wed, 31 Jul 2024 00:33:01 GMT</pubDate>
            <description><![CDATA[<h2 id="빅데이터">빅데이터</h2>
<ul>
<li><p>데이터 종류</p>
<ul>
<li>정형 데이터<ul>
<li>정량적이고 수치로 확인할 수 있거나 구조를 가지고 있는 데이터     </li>
<li>예시: 시간, 시계열 데이터, 금융 데이터, ID/PW, 온도, 카드번호, 수강생 기록 등등</li>
</ul>
</li>
<li>비정형 데이터<ul>
<li>수치적으로 확인할 수 없거나 구조를 띄지 않는 데이터</li>
<li>예시: 그림, 소리, 영상 등등</li>
</ul>
</li>
<li>반정형 데이터<ul>
<li>정형데이터와 비정형데이터의 성격을 두개 다 가지는 데이터<ul>
<li>예시<ul>
<li>DICOM 파일(의료용 디지털 영상 및 통신 표준) 그림과 환자 정보가 함께 있음</li>
<li>JSON(python에서 튜플형식의 키와 값으로 데이터를 저장함)</li>
<li>XML(태그를 통해 데이터 요소를 저장함)</li>
<li>스마트폰에서 위치 값을 함께 저장하는 사진</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>데이터 전처리</p>
<ul>
<li>데이터를 AI에게 학습시키기 전이나 분석하기 전에 적합한 형태로 가공하는 작업</li>
<li>데이터 전처리를 하는 이유<ul>
<li>데이터를 이용한 결과물에 대한 품질을 향상시키기 위해 꼭 필요한 작업입니다.</li>
</ul>
</li>
<li>데이터 전처리 종류<ul>
<li>데이터 정제: 필요한 데이터만 남도록 필터링 하는 과정<ul>
<li>데이터 통합: 일관된 데이터로 만드는 과정입니다</li>
<li>데이터 변화: 크기가 벗어났거나 인코딩이 맞지 않는 데이터를 옳바르게 바꿔줍니다</li>
<li>데이터 분할: 전체 데이터를 훈련 데이터 셋과 시험 데이터 셋으로 분할합니다</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>빅데이터</p>
<ul>
<li><p>빅데이터는 단순히 많은 양의 데이터를 의미하는것이 아니고 3가지의 필수적인 특성을 가진다.</p>
<ul>
<li>규모: 굉장히 방대한 양의 유의미한 데이터</li>
<li>속도: 데이터의 생성 및 처리 속도가 매우 빠릅니다.</li>
<li>다양성: 데이터의 종류 뿐만 아니라 형식이 다양합니다.</li>
</ul>
</li>
<li><p>데이터 수집 계획</p>
<ul>
<li>데이터 식별 및 선택 → 데이터 수집/저장 방법 결정 → 데이터 수집 → 데이터 저장 → 데이터 정제 → 데이터 구조화 → 데이터 전처리 → 빅데이터 구성</li>
</ul>
</li>
<li><p>빅데이터를 활용하기 위한 기술 및 도구</p>
<ul>
<li>데이터 저장: Hadoop, HDFS, Amazon S3</li>
<li>데이터 처리: Apache Spark, Apache Flink, Apache Storm</li>
<li>데이터 분석: R, Python (pandas, NumPy, SciPy), SAS, SPSS</li>
<li>데이터 시각화: Tableau, Power BI, D3.js</li>
<li>데이터베이스: NoSQL 데이터베이스 (MongoDB, Cassandra, HBase), NewSQL 데이터베이스 (Google Spanner, CockroachDB)</li>
</ul>
</li>
</ul>
</li>
<li><p>꼭 알아야하는 개념!</p>
<ul>
<li>메타데이터
다른 정보에 대한 정보를 의미합니다. 보통 어떤 정보의 근원에 대한 정보를 담고 있습니다.</li>
<li>회귀분석: 두 개 이상의 변수 간의 관계를 분석하는 방법<pre><code>  - 단순 회귀 분석: 하나의 독립 변수와 하나의 종속 변수 간의 관계를 분석합니다
  - 다중 회귀 분석: 두 개 이상의 독립 변수와 하나의 종속 변수 간의 관계를 분석합니다
  - 다항 회귀 분석: 독립 변수와 종속 변수 간의 비선형 관계를 분석합니다
  - 로지스틱 회귀 분석: 종속 변수가 이진형(두 가지 범주)일 때 사용하는 회귀 분석 방법입니다.</code></pre></li>
<li>군집분석: 데이터를 유사한 특성을 가진 군집으로 나누기 위한 분석 방법입니다.</li>
<li>IoT(Internet of Things): 인터넷을 통해 다양한 물리적 장치들이 서로 연결되어 데이터를 주고받으며 상호작용하는 시스템을 의미<ul>
<li>최근에는 다양한 가전제품들에도 사물인터넷을 적용하여 사용자의 행동 패턴을 분석하고 니즈를 확보하는 일에도 사용</li>
</ul>
</li>
<li>로드밸런싱: 부하가 집중되는것을 방지하기 위해 여러 서버에 네트워크 트래픽을 분산시키는 기술</li>
<li>데이터 레이크: 원시 데이터를 그대로 저장하는 시스템  ex) hadoop</li>
<li>데이터 거버넌스: 데이터의 신뢰성, 사용성, 보안성을 보장하기 위해 관리하는 모든 작업</li>
<li>데이터 웨어하우스: 대량의 데이터를 통합, 저장하여 분석하는 시스템</li>
</ul>
</li>
</ul>
<h2 id="인공지능">인공지능</h2>
<ul>
<li><p>Deep learning(딥러닝, 줄여서 DL이라고 합니다)</p>
<ul>
<li>인공지능을 학습시키거나 문제를 해결하기 위한 핵심 알고리즘을 의미합니다.<ul>
<li>Neuron(뉴런): 신경망의 기본 단위로 입력을 받아 가중치를 적용하고 활성화 함수를 통해 출력을 생성</li>
<li>Layer(층): 뉴런들이 모여있는 층으로 보통 입력층(Input Layer), 은닉층(Hidden Layer), 출력층(Output Layer)으로 구성됩니다.</li>
<li>Weight(가중치): 뉴런에서 다음 뉴런으로 넘길 때 중요도(가중치)를 적용하기 위한 매개변수입니다.<ul>
<li>이 가중치가 왜 중요하냐면 가중치에 따라 결과가 달라짐. 옳바른 학습을 많이 시킬수록 더 정교한 가중치가 만들어진다.</li>
</ul>
</li>
<li>Model(모델): 보통 인공지능 분야에서 모델이라고 하면 어떤 AI나 신경망 등 대상체를 의미해요.
단어 사용 예시: 수강생 딥러닝 모델, 수강생 숙제 시키는 인공지능 모델</li>
<li>ANN(Artificial Neural Network, 인공신경망): 여러 뉴런으로 이루어진 인공 신경망을 의미합니다.</li>
<li>DNN(Deep Neural Network, 심층신경망): 기존의 ANN의 단점을 해결하기 위해 은닉층을 통해 더 깊은 신경망 구조를 갖는 신경망</li>
<li>CNN(Convolution Neural Network**, 합성곱신경망): 특징을 추출하고 패턴을 파악하는데 우수한 신경망</li>
<li>RNN(Recurrent Neural Network, 순회신경망): 시간적인 특성을 함께 학습하고 적용하기 위한 신경망</li>
<li>다층 퍼셉트론 (Multilayer Perceptron, MLP): 층이 여러개가 이루어진 신경망을 의미해요.</li>
<li>역전파 알고리즘 (Backpropagation): 신경망의 가중치를 업데이트하여 오차를 최소화하는 방법이예요.</li>
<li>생성적 적대 신경망 (Generative Adversarial Networks, GAN): 새로운 데이터를 생성하기 위한 신경망이예요.</li>
</ul>
</li>
</ul>
</li>
<li><p>Machine learning(기계학습, 줄여서 ML이라고 합니다.)</p>
<ul>
<li><p>인공지능을 학습 시키는 것을 의미합니다.</p>
</li>
<li><p>꼭 알아야하는 개념!</p>
<ul>
<li><p>지도 학습
입력 데이터와 정답을 함께 주며 학습시키는 방식
응용분야: 이미지 분류, 스팸 이메일 탐지, 주식 가격 예측, 코인 가격 예측</p>
</li>
<li><p>비지도 학습
입력 데이터만 주어지고, 정답이 없는 상태에서 데이터의 패턴이나 구조를 찾는 방식
응용분야: 구매 패턴에 따른 고객 세분화, 이상 탐지, 차원 축소</p>
</li>
<li><p>강화 학습
시행착오를 통해 보상을 최대화하기 위해 학습하는 방식</p>
<ul>
<li><p>응용분야</p>
<p>  게임 AI, 로봇 제어, 자율 주행 차량</p>
</li>
</ul>
</li>
<li><p>반지도 학습
일부 데이터에 대해서는 분류와 정답이 있지만 나머지 일부는 없는 상태로 학습.
응용분야: 데이터 라벨링 (대학원생이 하던 고생을 대신 시킬 수 있어요!)</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p>Artificial Intelligence(인공지능, 줄여서 AI라고 합니다.)</p>
<ul>
<li>딥러닝 알고리즘을 통해 머신러닝이된 프로그램을 인공지능이라합니다.</li>
<li>꼭 알아야하는 개념!<ul>
<li>약인공지능 (Narrow AI or Weak AI)
특정 작업이나 문제를 해결하는 데 특화된 AI. 일반 지능이 아닌 특정 분야에서만 능력을 발휘하는 인공지능 모델을 의미해요.
(그렇다고 성능이 안좋은 것은 아니예요! 특정 작업은 빠르게 수행도 가능하고
학습도 용이한편입니다!)</li>
<li>강인공지능 (General AI or Strong AI)
인간과 유사한 수준의 지능을 가지고 다양한 작업을 수행할 수 있는 인공지능 모델을 의미해요.</li>
<li>대형 언어 모델 (Large Language Model, LLM)
많은 양의 텍스트 데이터를 학습하여 언어 이해와 생성 능력을 갖춘 인공지능 모델<ul>
<li>어떤 것들이 있을까요?<ul>
<li>ChatGPT(<strong>GPT-3</strong>, <strong>GPT-4</strong>)</li>
<li><strong>BERT</strong></li>
<li><strong>T5</strong></li>
<li><strong>Turing-NLG</strong></li>
<li><strong>LLaMA</strong></li>
<li>위 예시 말고도 굉장히 많이 있어요!</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>더 깊게 깊게!</p>
<ul>
<li>초인공지능 (Superintelligent AI)
인간의 지능을 초월하는 AI. 상상 속의 개념으로, 아직은 이론적인 단계에 있어요.
(’터미네이터’라는 영화에 나오는 ‘스카이넷’같은 인공지능이 여기에 속해요.)</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 1027 고층건물]]></title>
            <link>https://velog.io/@ysj_log/%EB%B0%B1%EC%A4%80-1027-%EA%B3%A0%EC%B8%B5%EA%B1%B4%EB%AC%BC-e3wfnnt6</link>
            <guid>https://velog.io/@ysj_log/%EB%B0%B1%EC%A4%80-1027-%EA%B3%A0%EC%B8%B5%EA%B1%B4%EB%AC%BC-e3wfnnt6</guid>
            <pubDate>Tue, 30 Jul 2024 00:04:59 GMT</pubDate>
            <description><![CDATA[<p>def count_left(now):
    min = float(&#39;inf&#39;) 
    cnt = 0 
    for idx in range(now-1, -1, -1):
        inc = (buildings[now] - buildings[idx]) / (now - idx) 
        if min &gt; inc: 
            min = inc
            cnt += 1
    return cnt</p>
<p>def count_right(now):
    max = -float(&#39;inf&#39;) 
    cnt = 0
    for idx in range(now+1, N):
        inc = (buildings[now] - buildings[idx]) / (now - idx)
        if max &lt; inc:
            max = inc
            cnt += 1
    return cnt</p>
<p>N = int(input())
buildings = list(map(int, input().split()))
ret = 0
for i in range(N):
    left = count_left(i)
    right = count_right(i)
    ret = max(ret, left + right)</p>
<p>print(ret)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[BFS를 이용한 미로 탈출]]></title>
            <link>https://velog.io/@ysj_log/BFS%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%AF%B8%EB%A1%9C-%ED%83%88%EC%B6%9C</link>
            <guid>https://velog.io/@ysj_log/BFS%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%AF%B8%EB%A1%9C-%ED%83%88%EC%B6%9C</guid>
            <pubDate>Sun, 28 Jul 2024 16:59:23 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-python">from collections import deque

T = int(input())

for test_case in range(1, T + 1):
    N = int(input())
    maze=[list(map(int,input())) for _ in range(N)]
    ds=[[1,-1,0,0],[0,0,1,-1]]
    goal=0

    for i in range(N):
        for j in range(N):
            if maze[i][j] == 3:
                x, y = j, i
                break

    queue=deque([])
    queue.append([x,y,0])

    while maze[y][x] != 2:
        a = queue.popleft()
        xx, yy = a[0], a[1]
        cnt = a[2]
        maze[yy][xx]=1

        for _ in range(4):
            dx = xx+ds[0][_]
            dy = yy+ds[1][_]
            if 0&lt;=dx&lt;N and 0&lt;=dy&lt;N and maze[dy][dx]==0:
                dcnt=cnt+1
                queue.append([dx,dy,dcnt])
            elif 0&lt;=dx&lt;N and 0&lt;=dy&lt;N and maze[dy][dx]==2:
                goal=cnt
                x=dx
                y=dy
                break

        if not queue:
            break

    print(f&#39;#{test_case} {goal}&#39;)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Stack을 활용해 계산기 만들기]]></title>
            <link>https://velog.io/@ysj_log/Stack%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%B4-%EA%B3%84%EC%82%B0%EA%B8%B0-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@ysj_log/Stack%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%B4-%EA%B3%84%EC%82%B0%EA%B8%B0-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Thu, 25 Jul 2024 15:38:05 GMT</pubDate>
            <description><![CDATA[<p>문자열로 된 입력받은 중위표기법계산식을 stack을 활용해 후위표기법계산식으로 변경 후 계산하는 최적화 방식이다.</p>
<table>
<thead>
<tr>
<th><center>부호</th>
<th><center>isp(중위표기법 내부 우선순위)</th>
<th><center>icp(스택 내부 우선순위)</th>
</tr>
</thead>
<tbody><tr>
<td><center>)</td>
<td><center>-</td>
<td><center>-</td>
</tr>
<tr>
<td><center>*, /</td>
<td><center>2</td>
<td><center>2</td>
</tr>
<tr>
<td><center>+, -</td>
<td><center>1</td>
<td><center>1</td>
</tr>
<tr>
<td><center>(</td>
<td><center>0</td>
<td><center>3</td>
</tr>
</tbody></table>
<p>해당하는 우선순위를 비교하며 중위표기법내부의 부호들을 스택에 쌓으며, 우선순위보다 낮거나 같은 부호를 스택에 쌓게될경우 스택 가장위에 있는 부호들의 우선순위와 비교하여 높은것을을 스택에서 빼며 출력하고 다시 비교하여 쌓도록 한다.</p>
<p>위와같은 규칙을 따라하면 후위표기법이 만들어진다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Hash Table]]></title>
            <link>https://velog.io/@ysj_log/Hash-Table</link>
            <guid>https://velog.io/@ysj_log/Hash-Table</guid>
            <pubDate>Sun, 21 Jul 2024 23:45:12 GMT</pubDate>
            <description><![CDATA[<h2 id="1해시테이블hashtable-시간복잡도">1.해시테이블(HashTable) 시간복잡도</h2>
<p> 해시테이블의 Key값은 해시함수에 의해 고유한 index를 가지게 되어 바로 접근할 수 있으므로 평균 O(1)의 시간복잡도로 데이터를 조회할 수 있다. 하지만 데이터의 충돌이 발생한 경우 Chaining에 연결된 리스트들까지 검색을 해야 하므로 O(N)까지 시간복잡도가 증가할 수 있다.
충돌을 방지하는 방법들은 데이터의 규칙성(클러스터링)을 방지하기 위한 방식이지만 공간을 많이 사용한다는 치명적인 단점이 있다.
만약 테이블이 꽉 차있는 경우라면 테이블을 확장해주어야 하는데, 이는 매우 심각한 성능의 저하를 불러오기 때문에 가급적이면 확장을 하지 않도록 테이블을 설계해주어야 한다.
(통계적으로 해시 테이블의 공간 사용률이 70% ~ 80%정도가 되면 해시의 충돌이 빈번하게 발생하여 성능이 저하되기 시작한다고 한다.)                </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[DFS,BFS 그리고 DP(Tabulation,Memoization)에 대한 고찰]]></title>
            <link>https://velog.io/@ysj_log/DFSBFS-%EA%B7%B8%EB%A6%AC%EA%B3%A0-DPTabulationMemoization%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B3%A0%EC%B0%B0</link>
            <guid>https://velog.io/@ysj_log/DFSBFS-%EA%B7%B8%EB%A6%AC%EA%B3%A0-DPTabulationMemoization%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B3%A0%EC%B0%B0</guid>
            <pubDate>Fri, 19 Jul 2024 10:42:15 GMT</pubDate>
            <description><![CDATA[<p>결론부터 말하자면 둘은 다른 개념이다.
DFS와 BFS는 탐색하는 방법에 대한 개념이다.
또 DP는 결과값을 얻는 방법을 최적화하는 개념이다.
Tabulation,Memoization은 결과값이 다음 결과값에 영향을 주는 방식인 것이다.
팩토리얼을 예로 들어보자</p>
<pre><code class="language-py">def factorial(n):
    if n==0: return 1

    ret = n*factorial(n-1)
    return ret</code></pre>
<p>팩토리얼를 구하는 과정에 대한 함수는 다음과 같다.
위 함수에서 6!을 구한다고 생각했을 때 6!을 구하기위해 5!로 가고 5!을 구하기 위해 4!로 간다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Que]]></title>
            <link>https://velog.io/@ysj_log/Que</link>
            <guid>https://velog.io/@ysj_log/Que</guid>
            <pubDate>Thu, 18 Jul 2024 01:47:50 GMT</pubDate>
            <description><![CDATA[<h2 id="que의-구조">Que의 구조</h2>
<pre><code class="language-py">class Queue:
    def __init__(self):
        self.front = None

    def push(self, value):
        if not self.front:
            self.front = Node(value)
            return

        node = self.front
        while node.next:
            node = node.next
        node.next = Node(value)

    def pop(self):
        if not self.front:
            return None

        node = self.front
        self.front = self.front.next
        return node.val

    def is_empty(self):
        return self.front is None</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[스택]]></title>
            <link>https://velog.io/@ysj_log/%EC%8A%A4%ED%83%9D</link>
            <guid>https://velog.io/@ysj_log/%EC%8A%A4%ED%83%9D</guid>
            <pubDate>Thu, 18 Jul 2024 01:46:04 GMT</pubDate>
            <description><![CDATA[<h2 id="스택을-사용하는-이유">스택을 사용하는 이유</h2>
<p>스택은 선입후출의 모델이다. 
쌓은 데이터에서 가장 최근에 쌓은 데이터를 꺼내어 접근하는 방식으로 사용한다.</p>
<h2 id="스택의-구조">스택의 구조</h2>
<pre><code class="language-py">class Node:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next


class Stack:
    def __init__(self):
        self.top = None

    def push(self, value):
        self.top = Node(value, self.top)

    def pop(self):
        if self.top is None:
            return None

        node = self.top
        self.top = self.top.next

        return node.val

    def is_empty(self):
        return self.top is None</code></pre>
<p>위는 스택의 구조 예시이다.
연결리스트의 구조이고, push시 노드의 .top에 value를 집어넣는다. 
이때 .next값은 self.top을 갖게 되는것이 핵심이다. </p>
]]></description>
        </item>
    </channel>
</rss>