<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>hyeo_ni__.log</title>
        <link>https://velog.io/</link>
        <description>개발자로 성장 중 입니다.</description>
        <lastBuildDate>Tue, 22 Oct 2024 07:32:12 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>hyeo_ni__.log</title>
            <url>https://velog.velcdn.com/images/hyeo_ni__/profile/a63e9c7f-8d0c-459a-a49d-f604251e0481/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. hyeo_ni__.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hyeo_ni__" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[우테코 프리코스] 1주차 회고록]]></title>
            <link>https://velog.io/@hyeo_ni__/%EC%9A%B0%ED%85%8C%EC%BD%94-%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-1%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0%EB%A1%9D</link>
            <guid>https://velog.io/@hyeo_ni__/%EC%9A%B0%ED%85%8C%EC%BD%94-%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-1%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0%EB%A1%9D</guid>
            <pubDate>Tue, 22 Oct 2024 07:32:12 GMT</pubDate>
            <description><![CDATA[<h2 id="우테코-프리코스를-시작하게된-계기">우테코 프리코스를 시작하게된 계기</h2>
<h2 id="프리코스-진행-방식">프리코스: 진행 방식</h2>
<h3 id="🟡-과제-제출-전-체크-리스트">🟡 과제 제출 전 체크 리스트</h3>
<ul>
<li>터미널에서 <strong><code>java -version</code>을 실행하여 Java 버전이 21인지 확인</strong>한다. Eclipse 또는 IntelliJ IDEA와 같은 IDE에서 Java 21로 실행되는지 확인한다.</li>
<li>터미널에서 <strong>Mac 또는 Linux 사용자의 경우 ./gradlew clean test 명령을 실행</strong>하고, <strong>Windows 사용자의 경우 <code>gradlew.bat clean test</code> 또는 <code>./gradlew.bat clean test</code> 명령을 실행</strong>할 때 모든 테스트가 아래와 같이 통과하는지 확인한다.</br>

</li>
</ul>
<hr>
<h2 id="프리코스-1주차-과제">프리코스: 1주차 과제</h2>
<h3 id="과제-진행-요구-사항">과제 진행 요구 사항</h3>
<ul>
<li>미션은 문자열 <a href="https://github.com/woowacourse-precourse/java-calculator-7">덧셈 계산기</a> 저장소를 포크하고 클론하는 것으로 시작</li>
<li>기능을 구현하기 전 README.md에 구현할 기능 목록을 정리해 추가</li>
<li>Git의 커밋 단위는 앞 단계에서 README.md에 정리한 기능 목록 단위로 추가
→ <a href="https://gist.github.com/stephenparish/9941e89d80e2bc58a153">AngularJS Git Commit Message Conventions</a>을 참고해 커밋 메시지를 작성한다.</li>
<li>자세한 과제 진행 방법은 프리코스 진행 가이드 문서를 참고</li>
</ul>
<h3 id="기능-요구-사항">기능 요구 사항</h3>
<ul>
<li><p>쉼표(,) 또는 콜론(:)을 구분자로 가지는 문자열을 전달하는 경우 구분자를 기준으로 각 숫자의 합을 반환
⇒ ex) &quot;&quot; =&gt; 0, &quot;1,2&quot; =&gt; 3, &quot;1,2,3&quot; =&gt; 6, &quot;1,2:3&quot; =&gt; 6</p>
<pre><code class="language-java">// text가 공백일 경우 0 반환
if (text == null) {}
if (text.isEmpty()) {}
// 구분자를 기준으로 문자열을 나누어 저장
String[] numbers = text.split(&quot;,|;&quot;);</code></pre>
</li>
<li><p>기본 구분자(쉼표, 콜론) 외에 커스텀 구분자를 지정
→ 문자열 앞부분의 &quot;//&quot;와 &quot;\n&quot; 사이에 위치하는 문자를 커스텀 구분자로 사용</p>
<pre><code class="language-java">if (text == null) {}
if (text.isEmpty()) {}
String[] numbers = text.split(&quot;,&quot;);</code></pre>
<blockquote>
<p>출력
java.util.regex.Matcher[pattern=//(.)\n(.*) region=0,7 lastmatch=]</p>
</blockquote>
</li>
<li><p>사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시킨 후 애플리케이션은 종료</p>
</li>
</ul>
<h4 id="입출력-요구-사항-및-실행-결과-예시">입출력 요구 사항 및 실행 결과 예시</h4>
<h3 id="입력">입력</h3>
<ul>
<li>구분자와 양수로 구성된 문자</li>
</ul>
<h3 id="출력">출력</h3>
<ul>
<li>덧셈 결과<pre><code>결과: 6</code></pre></li>
</ul>
<h3 id="실행-결과-예시">실행 결과 예시</h3>
<pre><code>덧셈할 문자열을 입력해 주세요.
1,2:3
결과: 6</code></pre><hr>
<h2 id="프로그래밍-요구-사항">프로그래밍 요구 사항</h2>
</br>

<hr>
<h2 id="✏️-배운점">✏️ 배운점</h2>
<h4 id="커스텀-구분자">커스텀 구분자</h4>
<blockquote>
<p>자바에서 정규 표현식 전문적으로 다루는 클래스인 java.util.regex 패키지를 사용,
패키지 안의 클래스중 주로 Pattern 클래스와 Matcher 클래스가 사용된다.</p>
</blockquote>
<p>정규식 클래스의 장점은 정규식을 Pattern 객체로 미리 컴파일 해둘수 있어,
처리 속도 빠르고, 매칭된 데이터들을 좀더 상세히 다룰 수 있다.</p>
<pre><code class="language-java">Pattern pattern = Pattern.compile(&quot;//(.)\n(.*)&quot;);

String text = &quot;//;\n1;2;3&quot;;
Matcher m = pattern.matcher(text);</code></pre>
</br>

<h4 id="illegalargumentexception이란">IllegalArgumentException이란?</h4>
<blockquote>
<p>호출자가 인수로 부적절한 값을 넘길 때 던지는 예외로,
간단히 설명하면 사용자가 값을 잘못 입력한 경우에 발생하는 예외이다.</p>
</blockquote>
<pre><code class="language-java">public void setMonth(int month) {
    if (month &gt; 12) {
            throw new IllegalArgumentException(&quot;달은 12월까지 입니다.&quot;)
        }
    this.month = month;
}</code></pre>
</br>
그러나 IllegalArgumentException 예외 말고도, 다른 예외 처리 방법이 있다.
그 처리 방법들 중 두 가지를 가져와봤다.
내용은 아래와 같다.

<h5 id="illegalstateexception">IllegalStateException</h5>
<blockquote>
<p>대상 객체의 상태가 호출된 메서드를 수행하기에 적절하지 않을 때 발생시킬 수 있는 예외로,
간단히 설명하면 체스 게임을 진행하는데, 체스판이 생성되지 않은 경우 발생하는 예외이다.</p>
</blockquote>
<pre><code class="language-java">public void start() {
    if(this.board == null) {
    thorow new IllegalStateException(&quot;보드판이 준비되지 않았습니다.&quot;)
}</code></pre>
<h5 id="nullpointerexception">NullPointerException</h5>
<blockquote>
<p>null 값을 허용하지 않는 메서드에 null을 건낼 때 발생시킬 수 있는 예외로,
IllegalArgumentException를 발생시킬 수 있으나 관례상 null을 건낼 경우
NullPointerException 예외를 발생시킨다.</p>
</blockquote>
<pre><code class="language-java">public void setMonth(int month) {
    if (month == null) {
        throw new NullPointerException(&quot;달은 1월부터 12월까지 입니다.&quot;)
    }    
    if (month &gt; 12){
        throw new IllegalArgumentException(&quot;달은 12월까지 입니다.&quot;)
    }
    this.month = month;
}</code></pre>
<hr>
<h2 id="소감문">소감문</h2>
<p>한 주 동안 리팩토링 방법이나 TDD 등 프로젝트에 접목해보지 못한 것 들을 알 수 있는
소중한 시간들이었던 것 같다.</p>
<p>리팩토링 방법이나 TDD를 좀 더 응용해서 2주차를 진행하고,
공통 피드백을 받아 부족한 부분을 한 단계 더 보완해낼 예정이다.</p>
<p>정신없이 지나간 1주일이었지만 정말 소중한 시간이었으며,
예상보다 더 많은 것들을 배울 수 있어 좋았다.
특히나 부족하게 여겨졌던 기초를 한 번 더 다질 수 있었고,
사람들과 디스코드에서 대화하며 다양한 정보를 얻을 수 있어 좋았던 것 같다.</p>
<p>이를 토대로 2주차도 나아가볼 예정이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TDD란? 테스트 코드를 만들어보자!]]></title>
            <link>https://velog.io/@hyeo_ni__/TDD%EB%9E%80-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%BD%94%EB%93%9C%EB%A5%BC-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@hyeo_ni__/TDD%EB%9E%80-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%BD%94%EB%93%9C%EB%A5%BC-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Sat, 19 Oct 2024 07:17:50 GMT</pubDate>
            <description><![CDATA[<h2 id="📝-tdd란">📝 TDD란?</h2>
<blockquote>
<p>Test Driven Development의 약자로 선 테스트 후 개발 방식의 프로그래밍 방법이다.
과거 개발 방식 초기에는 Test First Development (테스트 우선 개발)로 불렸었다.</p>
</blockquote>
<h4 id="tdd의-개발주기">TDD의 개발주기</h4>
<p>TDD의 개발 주기가 존재하는데 Red, Green, Yellow 단계로 나뉜다.</p>
<ul>
<li>Red 단계: <strong>실패하는 테스트 코드</strong>를 먼저 작성
→ 실패하는 테스트 코드를 작성할 때까지 실제 코드 미작성<h5 id="✍-예제-코드">✍ 예제 코드</h5>
<pre><code class="language-java">@Test
public void testSum(){
   Calculator calculator = new Calculator();
   assertEquals(5, calculator.sum(2, 3));
}</code></pre>
</li>
<li>Green 단계: <strong>테스트 코드를 성공시키기 위한 실제 코드</strong>를 작성한다.
→ 실패하는 테스트를 통과할 정도의 최소한으로 실제 코드를 작성<h5 id="✍-예제-코드-1">✍ 예제 코드</h5>
<pre><code class="language-java">public class Calculator {
  public int add(int a, int b) {
      return a + b;
  }
}</code></pre>
</li>
<li>Yellow 단계에서는 <strong>중복 코드 제거, 일반화</strong> 등의 <strong>리팩토링을 수행</strong>한다.</li>
</ul>
<h4 id="💭-일반적인-개발-방식">💭 일반적인 개발 방식</h4>
<blockquote>
<p><strong>요구사항 분석 → 설계 → 개발 → 테스트 → 배포</strong>의 형태로 개발 주기를 갖는다.</p>
</blockquote>
<p>일반적인 개발 방식의 단점은 아래와 같이 가지고 있다.</p>
<ol>
<li>소비자의 요구 사항이 처음부터 명확하지 않을 수 있음.</li>
<li>처음부터 완벽한 설계가 어려움.</li>
<li>자체적으로 버그 검출 능력 저하 혹은 소스코드의 품질이 저하될 수 있음.</li>
<li>자체 테스트 비용이 증가할 수 있음.</li>
</ol>
<p>❗ 재사용 및 관리가 어려워 유지 보수를 어렵게 만든다.</p>
<h4 id="tdd의-장점">TDD의 장점</h4>
<ul>
<li><p>TDD만의 반복적인 단계가 진행되며, 자연스럽게 코드의 버그가 줄고, 소스코드는 간결해진다.</p>
</li>
<li><p>명확한 요구사항을 기반으로 코드를 작성
: 테스트가 곧 코드의 명세서 역할을 할 수 있다.
: 테스트는 유연성, 유지보수성, 재사용성을 제공</p>
</li>
<li><p>추가 구현의 용이함
: 자동화된 유닛 테스팅을 전제하므로 테스트 기간을 획기적으로 단축</p>
</li>
</ul>
<h4 id="tdd의-단점">TDD의 단점</h4>
<ul>
<li><p>생산성의 저하
: 처음부터 2개의 코드를 짜야하고, 중간중간 테스트를 하며 고쳐나가야 하기 때문</p>
</li>
<li><p>테스트 관리의 복잡성
: 프로젝트가 커질수록 테스트 코드도 많아지기에 유지 보수하는데에도 추가적인 노력 필요</p>
</li>
</ul>
<h4 id="tdd의-대표적인-tool---junit">TDD의 대표적인 Tool - JUnit</h4>
<blockquote>
<p>자바의 단위 테스팅 프레임 워크로, JUnit만 존재하는 것은 아니다.
다른 언어들도 프레임워크가 존재하며 , 보통 이름을 xUnit이라 지칭한다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Django]Apscheduler]]></title>
            <link>https://velog.io/@hyeo_ni__/DjangoApscheduler</link>
            <guid>https://velog.io/@hyeo_ni__/DjangoApscheduler</guid>
            <pubDate>Fri, 23 Feb 2024 14:16:44 GMT</pubDate>
            <description><![CDATA[<h2 id="📚-apscheduler">📚 <a href="https://pypi.org/project/django-apscheduler/">Apscheduler</a></h2>
<blockquote>
<p>일정 주기 마다 실행</p>
</blockquote>
<h3 id="✍-코드"><strong>✍ 코드</strong></h3>
<pre><code class="language-bash">pip install django-apscheduler</code></pre>
<p>스케쥴러를 사용하기 위해 우선 라이브러리를 받아준다.
이후 settings.py에 세팅 해준다.</p>
<h3 id="✍-코드-1"><strong>✍ 코드</strong></h3>
<pre><code class="language-python"># settings.py
INSTALLED_APPS = [
    &#39;django_apscheduler&#39;,
]</code></pre>
<h3 id="✍-코드-2"><strong>✍ 코드</strong></h3>
<pre><code class="language-python"># views.py

from datetime import datetime
from apscheduler.schedulers.background import BackgroundScheduler

def Scheduler():
    Now = datetime.now()
    print(&quot;실행 후 5초가 지났습니다. 현재 시각 :&quot;, Now.time())

# 스케줄러 설정
scheduler = BackgroundScheduler()
scheduler.add_job(Scheduler, &#39;interval&#39;, seconds = 5)
# 스케줄러 시작
scheduler.start()</code></pre>
<p>필요한 라이브러리들을 import해준다.
datetime은 시각을 확인해주기 위해 import해주었다.</p>
<table>
<thead>
<tr>
<th>옵션</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>interval</td>
<td>N초, N분 등 일정 주기 마다 실행</td>
</tr>
<tr>
<td>cron</td>
<td>매 시간, 매 분과 같이 정해진 시간 혹은 날짜에 실행</td>
</tr>
<tr>
<td></br></td>
<td></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>명령어</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>year</td>
<td>연도 4자리</td>
</tr>
<tr>
<td>month</td>
<td>월 1 ~ 12</td>
</tr>
<tr>
<td>day</td>
<td>일자 1 ~ 31</td>
</tr>
<tr>
<td>week</td>
<td>주차 수 1 ~ 53</td>
</tr>
<tr>
<td>day_of_week</td>
<td>요일 0 ~ 6(Mon, Tue, Wed, Thu, Fri, Sat, Sun)</td>
</tr>
<tr>
<td>hour</td>
<td>시간 0 ~ 23</td>
</tr>
<tr>
<td>minute</td>
<td>분 0 ~ 59</td>
</tr>
<tr>
<td>second</td>
<td>초 0 ~ 59</td>
</tr>
<tr>
<td>timezone</td>
<td>사용할 timezone 설정</td>
</tr>
</tbody></table>
<h3 id="💻-출력"><strong>💻 출력</strong></h3>
<pre><code class="language-bash">실행 후 5초가 지났습니다. 현재 시각 : 14:32:29.601103
실행 후 5초가 지났습니다. 현재 시각 : 14:32:34.593561
실행 후 5초가 지났습니다. 현재 시각 : 14:32:39.599084
실행 후 5초가 지났습니다. 현재 시각 : 14:32:44.597033
실행 후 5초가 지났습니다. 현재 시각 : 14:32:49.590092</code></pre>
<h3 id="📢-터미널-실행창">📢 터미널 실행창</h3>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/ee574f55-7537-4209-9697-97dd04df1b45/image.png" alt=""></p>
<p>이와 같이 실행되는 것을 확인해 볼 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Django]Simple-Jwt 로그인]]></title>
            <link>https://velog.io/@hyeo_ni__/DjangoSimple-Jwt-%EB%A1%9C%EA%B7%B8%EC%9D%B8</link>
            <guid>https://velog.io/@hyeo_ni__/DjangoSimple-Jwt-%EB%A1%9C%EA%B7%B8%EC%9D%B8</guid>
            <pubDate>Tue, 13 Feb 2024 06:16:30 GMT</pubDate>
            <description><![CDATA[<h2 id="📝-simple-jwt">📝 <a href="https://django-rest-framework-simplejwt.readthedocs.io/en/latest/">Simple-Jwt</a></h2>
<blockquote>
<p>Simple JWT는 Django REST Framework에 대한 JSON <strong>웹 토큰 인증 백엔드</strong>를 제공한다.</p>
</blockquote>
<p>사용하는 라이브러리는 아래와 같다.</p>
<h3 id="✍-코드"><strong>✍ 코드</strong></h3>
<pre><code class="language-bash">pip install djangorestframework-simplejwt</code></pre>
</br>
</br>

<hr>
<h2 id="📚-simple_jwt-세팅">📚 simple_jwt 세팅</h2>
<h3 id="✍-코드-1"><strong>✍ 코드</strong></h3>
<pre><code class="language-python"># settings.py

from datetime import timedelta

INSTALLED_APPS = [
    …
    # simple-jwt 추가해주기 
    &#39;rest_framework_simplejwt&#39;,
]

SIMPLE_JWT = {
    &#39;ACCESS_TOKEN_LIFETIME&#39;: timedelta(minutes=60),
    &#39;REFRESH_TOKEN_LIFETIME&#39;: timedelta(days=1),
    &#39;ROTATE_REFRESH_TOKENS&#39;: True,
}</code></pre>
<p>simple_jwt기본 설정을 해준다.
Access ToKen과 Refresh Token의 생명주기를 60분으로 설정한다.
Rotate Token 회전시킬지 여부를 지정하는데, 보안상 권장하는 편이다.
</br>
</br></p>
<hr>
<h2 id="📚-로그인">📚 로그인</h2>
<h3 id="✍-코드-2"><strong>✍ 코드</strong></h3>
<pre><code class="language-python"># views.py

from django.contrib.auth.hashers import check_password
from rest_framework_simplejwt.tokens import RefreshToken

@api_view([&#39;POST&#39;])
def user_login(request):
    if request.method == &#39;POST&#39;:
        username = request.data.get(&#39;username&#39;)
        password = request.data.get(&#39;password&#39;)

        user = AuthUser.objects.filter(username=username).first()
        if user and check_password(password, user.password):
            # 인증 성공시 바로 로그인
            login(request, user)
            refresh = RefreshToken.for_user(user)
            access_token = str(refresh.access_token)
            refresh_token = str(refresh)

            # Users에서 nickname 가져오기
            try:
                user_info = UserProfile.objects.get(username=user.username)
                nickname = user_info.nickname
            except UserProfile.DoesNotExist:
                nickname = None

            return Response(
                {
                    &#39;status&#39;: &#39;success&#39;,
                    &#39;username&#39;: user.username,
                    &#39;nickname&#39;: nickname,
                    &#39;access_token&#39;: access_token,
                    &#39;refresh_token&#39;: refresh_token,
                    &#39;message&#39;: &#39;로그인이 완료되었습니다.&#39;
                },
                status=status.HTTP_200_OK
            )
        else:
            # 인증 실패
            logger = logging.getLogger(__name__)
            logger.error(f&#39;Failed login attempt for username: {username}&#39;)
            return Response(
                {
                    &#39;status&#39;: &#39;fail&#39;,
                    &#39;message&#39;: &#39;로그인에 실패했습니다.&#39;
                },
                status=status.HTTP_401_UNAUTHORIZED
            )</code></pre>
<p><strong>check_password</strong>는 두 password를 비교하여 boolean값을 리턴한다.
이후 패스워드 및 username이 일치할 경우 자동으로 로그인이 되며, access토큰과 refresh토큰을 발급해준다.</p>
<blockquote>
<ul>
<li>Access Token
: 로그인시 발급되며, 사용자 인증 정보를 담고 있음</li>
</ul>
</blockquote>
<ul>
<li>Refresh Token
: Access토큰을 재발급 받는 용도로 유효기간이 더 길다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Django]SMS인증 - Naver Cloud]]></title>
            <link>https://velog.io/@hyeo_ni__/DjangoSMS%EC%9D%B8%EC%A6%9D-Naver-Cloud</link>
            <guid>https://velog.io/@hyeo_ni__/DjangoSMS%EC%9D%B8%EC%A6%9D-Naver-Cloud</guid>
            <pubDate>Mon, 29 Jan 2024 02:17:44 GMT</pubDate>
            <description><![CDATA[<h2 id="📚-naver-cloud-platform">📚 <a href="https://www.ncloud.com/">Naver Cloud Platform</a></h2>
<p>우선 SMS 인증을 위해 <strong>Naver Cloud Platform</strong>에 가입을 해야한다.</p>
<p>물론 Naver 말고도 SMS 인증을 도와주는 다른 플랫폼도 많다.
하지만 해당 플랫폼을 선택한 이유는 <strong>10만 크레딧</strong>을 무료로 제공해주기 때문이다.</p>
<p>회원가입을 완료했으면 <a href="https://www.ncloud.com/product/applicationService/sens">Simple &amp; Easy Notification Service</a>를 이용신청하면 된다.
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/60b0b59f-1630-4ae7-ba6f-1a02440820a2/image.png" alt="">
이후에 프로젝트를 생성해준다.
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/d9cf8275-c71a-4996-9001-73d2d51fca17/image.png" alt="">
각 서비스 타입 및 이름은 각자 작성해준다.</p>
<p>생성 후 발신번호를 꼭 등록해주어야 하는데, 본인 소유의 발신번호일 경우 간단하게 신청이 된다.</p>
<p>여기까지 기본 설정이 끝났으면 인증키를 발급받아야한다.</br></br></p>
<hr>
<h2 id="📚-api-인증키-및-기타-인증키">📚 API 인증키 및 기타 인증키</h2>
<ul>
<li><p>OPEN API Key
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/ebc4c8dd-1e7e-4e59-bfca-5c47ea1019d6/image.png" alt="">
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/0d2b9fa6-458f-4ec1-aa09-930359aacc1e/image.png" alt="">
project 생성시 발급 가능하다. (</p>
</li>
<li><p>Access Key / Secret Key
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/6fb6069a-0042-4add-ac5c-33152d9a724f/image.png" alt="">
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/be6f9f31-5a86-4f9e-bbac-625e07931c95/image.png" alt="">
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/a1d8c34f-055b-46f0-bc71-ca587056c344/image.png" alt="">
마이페이지 - 인증키 관리에서 발급 받을 수 있다.</br></br></p>
</li>
</ul>
<hr>
<h2 id="📚-sms-인증">📚 SMS 인증</h2>
<h3 id="✍-코드"><strong>✍ 코드</strong></h3>
<pre><code class="language-sql">create table sms(
    id int auto_increment primary key,
    phone_number varchar(15),
    auth_number varchar(6)
);</code></pre>
<pre><code class="language-python"># models.py

class Sms(models.Model):
    phone_number = models.CharField(max_length=15, blank=True, null=True)
    auth_number = models.CharField(max_length=6, blank=True, null=True)

    class Meta:
        managed = False
        db_table = &#39;sms&#39;

    @classmethod
    def create_sms(cls, phone_number, auth_number):
        sms = cls(phone_number=phone_number, auth_number=auth_number)
        sms.save()</code></pre>
<p>우선 위와 같이 테이블을 만들어준다.
테이블 생성 및 수정, 삭제시 반드시 해줘야하는 &#39;<strong>python manage.py migrate</strong>&#39;를 해준다.</p>
<p>저장 메서드를 추가하여 SMS를 저장할 때 사용한다. </p>
<h3 id="✍-코드-1"><strong>✍ 코드</strong></h3>
<pre><code class="language-bash">pip install requests</code></pre>
<p>필요한 라이브러리인 requests를 설치해준다.</p>
<h3 id="✍-코드-2"><strong>✍ 코드</strong></h3>
<pre><code class="language-python"># sms.py

import json
import requests
import time
import base64
import hashlib
import hmac

def make_signature(url, access_key, secret_key):
    timestamp = str(int(time.time() * 1000))
    method = &quot;POST&quot;
    message = method + &quot; &quot; + url + &quot;\n&quot; + timestamp + &quot;\n&quot; + access_key
    message = bytes(message, &#39;UTF-8&#39;)
    secret_key = bytes(secret_key, &#39;UTF-8&#39;)
    signingkey = base64.b64encode(hmac.new(secret_key, message, digestmod=hashlib.sha256).digest())
    return signingkey

def send_sms(phone_number, content):
    user_access_key = &quot;access key 입력&quot;
    user_secret_key = &quot;secret key 입력&quot;
    sms_service_id = &quot;OPEN API Key(서비스 ID)&quot;
    url = &quot;/sms/v2/services/&quot; + sms_service_id + &quot;/messages&quot;
    api_url = &#39;https://sens.apigw.ntruss.com&#39; + url

    headers = {
        &#39;Content-Type&#39;: &#39;application/json; charset=utf-8&#39;,
        &#39;x-ncp-apigw-timestamp&#39;: str(int(time.time() * 1000)),
        &#39;x-ncp-iam-access-key&#39;: user_access_key,
        &#39;x-ncp-apigw-signature-v2&#39;: make_signature(url, user_access_key, user_secret_key)
    }

    body = {
        &quot;type&quot;: &quot;SMS&quot;,
        &quot;contentType&quot;: &quot;COMM&quot;,
        &quot;countryCode&quot;: &quot;82&quot;,
        &quot;from&quot;: &quot;등록한 연락처&quot;,
        &quot;content&quot;: content,
        &quot;messages&quot;: [
            {
                &quot;to&quot;: phone_number,
            }
        ]
    }

    body_result = json.dumps(body)

    response = requests.post(api_url, headers=headers, data=body_result)
    response.raise_for_status()
    response_result = response.json()

    send_result = response_result.get(&#39;statusCode&#39;)

    if send_result == &quot;202&quot;:
        return True
    else:
        return False</code></pre>
<ul>
<li><p>기본정보
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/6e75afa2-818b-4da3-9228-7e485774dfdc/image.png" alt=""></p>
</li>
<li><p>메시지 발송
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/cd129d07-f007-4fe3-82c0-1276336ff88f/image.png" alt="">
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/77f8c7b6-0964-4afd-af39-111a7f18d33b/image.png" alt="">
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/9b84091d-c0bd-487c-ac5d-b04b2c2fecb0/image.png" alt=""></p>
</li>
</ul>
<p>위 표를 참고하여 sms.py코드를 작성하였다.
자세한건 <a href="https://api.ncloud-docs.com/docs/ai-application-service-sens-smsv2">SMS API</a>사이트에서 확인할 수 있다.</p>
<h3 id="✍-코드-3"><strong>✍ 코드</strong></h3>
<pre><code class="language-python"># views.py
import random
from .sms import send_sms

@api_view([&#39;POST&#39;])
def SMS(request):
    if request.method == &#39;POST&#39;:
        phone_number = request.data.get(&#39;phone_number&#39;)
        auth_number = str(random.randint(100000, 999999))
        sms_content = f&quot;[TEST]\n인증 코드는 {auth_number} 입니다.&quot;
        send_result = send_sms(phone_number, sms_content)

        if send_result:
            # SMS를 데이터베이스에 저장
            Sms.create_sms(phone_number, auth_number)
            return Response({&#39;message&#39;: &#39;인증 문자 전송이 완료되었습니다.&#39;}, status=status.HTTP_201_CREATED)
        else:
            return Response({&#39;message&#39;: &#39;인증 문자 전송에 실패했습니다.&#39;}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
</code></pre>
<p><strong>Sms.create_sms(phone_number, auth_number)</strong>위에서 만든 메소드를 사용하여 저장한다.</p>
<p>이후 데이터를 전송하면 아래와 같이 인증 코드가 온 것을 확인해 볼 수 있다.
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/9ec14779-9ef0-424c-9e73-eb7fcef12652/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Django]회원가입 및 로그인]]></title>
            <link>https://velog.io/@hyeo_ni__/Django%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%EB%B0%8F-%EB%A1%9C%EA%B7%B8%EC%9D%B8</link>
            <guid>https://velog.io/@hyeo_ni__/Django%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%EB%B0%8F-%EB%A1%9C%EA%B7%B8%EC%9D%B8</guid>
            <pubDate>Tue, 23 Jan 2024 04:25:28 GMT</pubDate>
            <description><![CDATA[<h2 id="📚-회원가입">📚 회원가입</h2>
<p>장고에서는 DB 연동시 자동으로 회원가입에 사용할 수 있는 <strong>Auth_User</strong>테이블이 생성된다.</p>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/5653b207-0bf2-4e7a-b733-83abf4538147/image.png" alt=""></p>
<p>models.py에 AuthUser를 가져온 후 사용하기 위해 간단히 설정을 해줘야한다.</p>
<h3 id="✍-코드"><strong>✍ 코드</strong></h3>
<pre><code class="language-python"># models.py
class AuthUser(models.Model):
    password = models.CharField(max_length=128)
    last_login = models.DateTimeField(blank=True, null=True)
    is_superuser = models.IntegerField(default=False) # default 설정
    username = models.CharField(unique=True, max_length=150)
    first_name = models.CharField(max_length=150)
    last_name = models.CharField(max_length=150)
    email = models.CharField(max_length=254)
    is_staff = models.IntegerField(default=0) # default 설정
    is_active = models.IntegerField(default=0) # default 설정
    date_joined = models.DateTimeField(auto_now_add = True) # 날짜 자동 입력

    class Meta:
        managed = False
        db_table = &#39;auth_user&#39;</code></pre>
<p>바로 기본값(default) 설정이다.
기본값을 설정하지 않을 경우 Null값이 허용되지 않은 열들이 있어 에러가 발생한다.
<strong>is_superuser, is_staff, is_active</strong> 값을 default로 0 혹은 False로 설정한다.
이후 <strong>date_joined</strong>는 auto_now_add를 True로 주어 데이터 입력시 값이 자동으로 입력되게 해준다.</p>
<h3 id="✍-코드-1"><strong>✍ 코드</strong></h3>
<pre><code class="language-python"># serializers.py

class AuthUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = AuthUser
        fields = (&#39;id&#39;, &#39;username&#39;, &#39;password&#39;)

# views.py
@api_view([&#39;POST&#39;])
def signup(request):
    if request.method == &#39;POST&#39;:
        serializer = AuthUserSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()

            return Response({&#39;message&#39;: &#39;회원 가입이 완료되었습니다.&#39;}, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)</code></pre>
<p>간단히 POST를 받아와 회원가입을 할 수 있다.
이후 JSON형식으로 username과 password를 설정한다.</p>
<h3 id="✍-코드-2"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">{
    &quot;username&quot;:&quot;username&quot;,
    &quot;password&quot;:&quot;password&quot;
}</code></pre>
<p>MySQL에서 DB를 확인해보면 아래와 같이 입력되어 있는 것을 볼 수 있다.
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/6baf97ac-3ab9-4caa-be86-44f12a83668f/image.png" alt="">
하지만 보안을 위해 password는 암호화하여 DB에 저장할 수 있도록 해주는 것이 좋다.</br></br></p>
<hr>
<h2 id="📚-password-암호화">📚 PASSWORD 암호화</h2>
<blockquote>
<p><strong>make_password</strong>
: Django에서 제공하는 함수로 문자열을 암호화 시킨다.</p>
</blockquote>
<h3 id="✍-코드-3"><strong>✍ 코드</strong></h3>
<pre><code class="language-python"># models.py

from django.contrib.auth.hashers import make_password

@api_view([&#39;POST&#39;])
def signup(request):
    if request.method == &#39;POST&#39;:
        serializer = AuthUserSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
             # Serializer에서 입력받은 원시 비밀번호를 가져온다.
            raw_password = serializer.validated_data.get(&#39;password&#39;)

            # make_password 함수를 사용하여 비밀번호를 해시화하고 저장한다.
            hashed_password = make_password(raw_password)
            serializer.save(password=hashed_password)

            return Response({&#39;message&#39;: &#39;회원 가입이 완료되었습니다.&#39;}, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)</code></pre>
<p>위와 같이 코드를 수정 후 저장하면 비밀번호가 암호화 되어 들어간 것을 확인할 수 있다.
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/8681d63a-7aa9-4b5b-bde3-e7f1c7dda5dd/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Django]Query_Params]]></title>
            <link>https://velog.io/@hyeo_ni__/DjangoQueryParams</link>
            <guid>https://velog.io/@hyeo_ni__/DjangoQueryParams</guid>
            <pubDate>Tue, 16 Jan 2024 06:02:02 GMT</pubDate>
            <description><![CDATA[<h2 id="📝-query-parameter란">📝 query parameter란?</h2>
<blockquote>
<p>URL의 쿼리 매개변수에 대한 접근을 제공한다.</br></p>
</blockquote>
<p></br></br></p>
<hr>
<h2 id="📚-query_params">📚 query_params</h2>
<blockquote>
<p>전통적인 Django는 request.GET을 사용하여 쿼리 매개변수에 접근한다.
하지만 DRF에서는 request.query_params를 권장한다.</p>
</blockquote>
<p>이를 통해 내가 원하는 데이터만 검색을 할 수 있다.
우선 코드를 작성하기 이전 어떤 데이터가 있는지 확인을 해야한다.</p>
<h3 id="📢-postman-실행창">📢 Postman 실행창</h3>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/f5f8ffc4-5547-45f2-95cc-7436c1adc5c0/image.png" alt="">
기존 테이블에 임의로 데이터를 추가하였다.</p>
<h3 id="✍-코드"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">@api_view([&#39;GET&#39;, &#39;POST&#39;, &#39;PUT&#39;, &#39;DELETE&#39;])
def TestAPI(request, id=None):
    queryset = Testapi.objects.all()
    if request.method == &#39;GET&#39;:
        title = request.query_params.get(&#39;title&#39;)
        if title:
            queryset = queryset.filter(title__contains=title)
        serializer = TestAPISerializer(queryset, many=True)
        return Response(serializer.data)</code></pre>
<h3 id="✍-status-상태-코드"><strong>✍ status 상태 코드</strong></h3>
<table>
<thead>
<tr>
<th>코드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>request.query_params.get(&#39;title&#39;)</td>
<td>요청의 쿼리 매개변수에서 &#39;title&#39; 매개변수를 가져온다.</td>
</tr>
<tr>
<td>title__contains=title</td>
<td>Django의 ORM에서 사용되는 검색 필드 조회 연산자로 특정 문자열이 포함된 레코드를 검색</td>
</tr>
<tr>
<td>queryset.filter()</td>
<td>매개변수 값을 포함하는 레코드로 QuerySet을 필터링</td>
</tr>
</tbody></table>
<p>URL입력시 <strong>?title=안녕</strong>이라고 입력 후 조회시 title에 &#39;안녕&#39;이라는 글자가 들어가는 모든 데이터를 조회할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/e4573fd4-4ac0-410c-8c00-2133e5336c13/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Django]API POST, PUT, DELETE]]></title>
            <link>https://velog.io/@hyeo_ni__/DjangoAPI-POST-PUT-DELETE</link>
            <guid>https://velog.io/@hyeo_ni__/DjangoAPI-POST-PUT-DELETE</guid>
            <pubDate>Tue, 09 Jan 2024 10:38:49 GMT</pubDate>
            <description><![CDATA[<h2 id="📚-post">📚 POST</h2>
<blockquote>
<p>데이터 입력시 POST를 사용한다.</p>
</blockquote>
<h3 id="✍-코드"><strong>✍ 코드</strong></h3>
<pre><code class="language-python"># api/views.py
from rest_framework import status

@api_view([&#39;POST&#39;])
def postTestAPI(request):
    serializer = TestAPISerializer(data=request.data)
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


# api/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path(&#39;getapi/&#39;, views.getTestAPI),
    path(&#39;postapi/&#39;, views.postTestAPI) # 추가
]</code></pre>
</br>

<table>
<thead>
<tr>
<th>코드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>@api_view([&#39;POST&#39;])</td>
<td>API 뷰를 정의, HTTP 중 POST 요청을 처리한다.</td>
</tr>
<tr>
<td>TestAPISerializer(data=request.data)</td>
<td>받아온 데이터(request.data)를 TestAPISerializer를 사용하여 직렬화</td>
</tr>
<tr>
<td>serializer.is_valid()</td>
<td>렬화된 데이터가 유효한지 확인</td>
</tr>
<tr>
<td>Response</td>
<td>상태 코드 및 데이터 혹은 오류 메시지 반환</td>
</tr>
<tr>
<td>status</td>
<td>HTTP 응답 상태 코드를 정의하는 데 사용되는 모듈</td>
</tr>
<tr>
<td></br></td>
<td></td>
</tr>
</tbody></table>
<h3 id="✍-status-상태-코드"><strong>✍ status 상태 코드</strong></h3>
<table>
<thead>
<tr>
<th>상태 코드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>HTTP_200_OK</td>
<td>요청 성공, 클라이언트에 데이터 제공</td>
</tr>
<tr>
<td>HTTP_201_CREATED</td>
<td>요청 성공, 새로운 리소스가 생성</td>
</tr>
<tr>
<td>HTTP_204_NO_CONTENT</td>
<td>요청 성공, 별도의 데이터 미제공(주고 DELETE에서 사용)</td>
</tr>
<tr>
<td>HTTP_400_BAD_REQUEST</td>
<td>잘못된 요청으로 서버에서 처리할 수 없음</td>
</tr>
<tr>
<td>HTTP_401_UNAUTHORIZED</td>
<td>인증이 필요한 리소스에 접근하려고 할 때 사용, 클라이언트 미인증</td>
</tr>
<tr>
<td>HTTP_404_NOT_FOUND</td>
<td>요청한 리소스를 찾을 수 없음</td>
</tr>
<tr>
<td>HTTP_500_INTERNAL_SERVER_ERROR</td>
<td>서버 측에서 오류 발생</td>
</tr>
</tbody></table>
<p>코드를 저장 후 서버를 실행해 준다.
주소창에 <strong>localhost:8000/api/postapi/</strong>를 입력하면 아래와 같은 창이 뜨게 된다.</p>
<h3 id="📢-chrome-실행창">📢 Chrome 실행창</h3>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/7c53a6d1-30a0-455b-9b15-e46e5710d044/image.png" alt=""></p>
<h3 id="✍-코드-1"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">{
    &quot;title&quot;: &quot;POST API&quot;,
    &quot;content&quot;: &quot;post 되었습니다.&quot;
}</code></pre>
<p>JSON형식의 데이터를 입력 후 POST버튼을 눌러준다.</p>
<h3 id="📢-postman-실행창">📢 Postman 실행창</h3>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/2fddc132-a8f9-4be6-9208-e7f557c6b8c2/image.png" alt="">
Postman같은 경우 왼쪽 <strong>GET을 POST로 변경 후 raw-JSON에 입력</strong>해야한다.
입력 후 <strong>send버튼</strong>을 누를 경우 위 이미지와 같이 보여진다.</p>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/9fe128ff-04df-4c83-bf3e-2925900d60e4/image.png" alt=""></p>
<p>다시 GET으로 확인해볼경우 정상적으로 데이터가 들어간 것을 확인할 수 있다.</br></br></p>
<hr>
<h2 id="📚-put">📚 PUT</h2>
<blockquote>
<p>데이터 수정시 PUT을 사용한다.</p>
</blockquote>
<h3 id="✍-코드-2"><strong>✍ 코드</strong></h3>
<pre><code class="language-python"># api/views.py

@api_view([&#39;PUT&#39;])
def putTestAPI(request, id):
    try:
        data = Testapi.objects.get(id=id)
    except Testapi.DoesNotExist:
        return Response({&#39;message&#39;: &#39;해당 ID를 가진 데이터를 찾을 수 없습니다.&#39;}, status=status.HTTP_404_NOT_FOUND)

    serializer = TestAPISerializer(data, data=request.data)

    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data)

    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


# api/urls.py

urlpatterns = [
    path(&#39;getapi/&#39;, views.getTestAPI),
    path(&#39;postapi/&#39;, views.postTestAPI),
    path(&#39;putapi/&#39;, views.putTestAPI), # 추가
    path(&#39;putapi/&lt;int:id&gt;/&#39;, views.putTestAPI), # 추가
]</code></pre>
</br>

<table>
<thead>
<tr>
<th>코드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>@api_view([&#39;PUT&#39;])</td>
<td>API 뷰를 정의, HTTP 중 PUT 요청을 처리한다.</td>
</tr>
<tr>
<td>try•except</td>
<td>예외 처리시 사용</td>
</tr>
<tr>
<td>Testapi.objects.get(id=id)</td>
<td>ID를 사용하여 데이터베이스에서 해당 레코드를 가져오기</td>
</tr>
<tr>
<td>Testapi.DoesNotExist</td>
<td>Django 모델에서 발생하는 예외 중 DB에서 모델 객체를 찾지 못할 때 발생</td>
</tr>
</tbody></table>
<p>코드를 저장 후 서버를 실행해 준다.
주소창에 <strong>localhost:8000/api/putapi/1/</strong>를 입력 후 수정할 내용을 작성해준다.</p>
<h3 id="📢-postman-실행창-1">📢 Postman 실행창</h3>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/b453ead4-399f-4dc2-a52b-7062e08315c6/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/5562e28f-9404-4222-8f32-40d6087a1b9d/image.png" alt=""></p>
<p>Postman같은 경우 왼쪽 <strong>GET을 PUT으로 변경 후 raw-JSON에 입력</strong>해야한다.
입력 후 <strong>send버튼</strong>을 누를 경우 위 이미지와 같이 보여진다.</br></br></p>
<hr>
<h2 id="📚-delete">📚 DELETE</h2>
<blockquote>
<p>데이터 삭제시 DELETE를 사용한다.</p>
</blockquote>
<h3 id="✍-코드-3"><strong>✍ 코드</strong></h3>
<pre><code class="language-python"># api/views.py

@api_view([&#39;DELETE&#39;])
def deleteTestAPI(request, id):
    try:
        Testapi_instance = Testapi.objects.get(id=id)
    except Testapi.DoesNotExist:
        return Response({&#39;message&#39;: &#39;해당 ID를 가진 데이터를 찾을 수 없습니다.&#39;}, status=status.HTTP_404_NOT_FOUND)
    Testapi_instance.delete()
    return Response(status=status.HTTP_204_NO_CONTENT)


# api/urls.py

urlpatterns = [
    path(&#39;getapi/&#39;, views.getTestAPI),
    path(&#39;postapi/&#39;, views.postTestAPI),
    path(&#39;putapi/&lt;int:id&gt;/&#39;, views.putTestAPI),
    path(&#39;deleteapi/&lt;int:id&gt;/&#39;, views.deleteTestAPI), # 추가
]</code></pre>
</br>

<table>
<thead>
<tr>
<th>코드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>@api_view([&#39;DELETE&#39;])</td>
<td>API 뷰를 정의, HTTP 중 PUT 요청을 처리한다.</td>
</tr>
<tr>
<td>Testapi_instance.delete()</td>
<td>Django 모델에서 데이터베이스에서 특정 레코드를 삭제하는 메서드</td>
</tr>
</tbody></table>
<p>코드를 저장 후 서버를 실행해 준다.
주소창에 <strong>localhost:8000/api/deleteapi/2/</strong>를 입력 후 send버튼을 누른다.</p>
<h3 id="📢-postman-실행창-2">📢 Postman 실행창</h3>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/867036f6-f188-4c8e-8af4-97f5857cf07f/image.png" alt=""></p>
<p>Postman같은 경우 왼쪽 <strong>GET을 DELETE 변경 후 **send버튼</strong>을 누를 경우 삭제된다.
이후 다시 확인하면 id 2가 사라진 것을 볼 수 있다.</br></br></p>
<hr>
<h2 id="📚-url하나로-get-post-put-delete하기">📚 URL하나로 GET, POST, PUT, DELETE하기</h2>
<blockquote>
<p>하나의 url로 GET, POST, PUT, DELETE를 처리할 수 있다.</p>
</blockquote>
<h3 id="✍-코드-4"><strong>✍ 코드</strong></h3>
<pre><code class="language-python"># app/views.py
@api_view([&#39;GET&#39;, &#39;POST&#39;, &#39;PUT&#39;, &#39;DELETE&#39;])
def TestAPI(request, id=None):
    if request.method == &#39;GET&#39;:
        data = Testapi.objects.all()
        serializer = TestAPISerializer(data, many=True)
        return Response(serializer.data)

    elif request.method == &#39;POST&#39;:
        serializer = TestAPISerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == &#39;PUT&#39;:
        try:
            data = Testapi.objects.get(id=id)
        except Testapi.DoesNotExist:
            return Response({&#39;message&#39;: &#39;해당 ID를 가진 데이터를 찾을 수 없습니다.&#39;}, status=status.HTTP_404_NOT_FOUND)

        serializer = TestAPISerializer(data, data=request.data)

        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == &#39;DELETE&#39;:
        try:
            Testapi_instance = Testapi.objects.get(id=id)
        except Testapi.DoesNotExist:
            return Response({&#39;message&#39;: &#39;해당 ID를 가진 데이터를 찾을 수 없습니다.&#39;}, status=status.HTTP_404_NOT_FOUND)
        Testapi_instance.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

# app/views.py
from django.urls import path
from . import views

urlpatterns = [
    path(&#39;testapi/&#39;, views.TestAPI),
    path(&#39;testapi/&lt;int:id&gt;/&#39;, views.TestAPI),
]</code></pre>
<p>데코레이터에 GET, POST, PUT, DELETE를 넣고 elif문으로 어떤 요청인지 받아와 해당 코드를 실행할 수 있다.</p>
<h3 id="📢-chrome-실행창-1">📢 Chrome 실행창</h3>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/6c81efcd-0a26-453c-8538-9b7e4691d7fe/image.png" alt=""></p>
<h3 id="📢-postman-실행창-3">📢 Postman 실행창</h3>
<blockquote>
<p>POST
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/8251a528-e05a-4356-971c-8f2b0ec71390/image.png" alt=""></p>
</blockquote>
<blockquote>
<p>PUT
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/eef3d952-2c1a-45e9-aad9-2337231c9628/image.png" alt=""></p>
</blockquote>
<blockquote>
<p>DELETE 및 GET
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/ed58e372-9ea2-453d-8c6f-7a12e91b0042/image.png" alt=""></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Django]API생성하기]]></title>
            <link>https://velog.io/@hyeo_ni__/DjangoAPI%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@hyeo_ni__/DjangoAPI%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 01 Jan 2024 13:54:54 GMT</pubDate>
            <description><![CDATA[<h2 id="📝-drfdjango-rest-framework란">📝 DRF(Django-REST-Framework)란?</h2>
<blockquote>
<p>Django 안에서 RESTful API 서버를 쉽게 만들게 도와주는 라이브러리다.</p>
</blockquote>
<h2 id="📚-필요-라이브러리">📚 필요 라이브러리</h2>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/413545d2-e214-4e2d-9598-1dc7d236974e/image.png" alt=""></p>
<h3 id="✍-코드"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">$ pip install djangorestframework</code></pre>
<p>Django REST Framework는 API를 구축할 수 있게 만들어 주기 때문에 꼭 필요하다.</br></br></p>
<hr>
<h2 id="📚-settingspy-설정">📚 settings.py 설정</h2>
<h3 id="✍-코드-1"><strong>✍ 코드</strong></h3>
<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;api&#39;, # 생성한 앱 이름
    &#39;rest_framework&#39;,
]</code></pre>
<p>INSTALLED_APPS에 생성한 앱을 등록해야 사용할 수 있다.</br></br></p>
<hr>
<h2 id="📚-serializerspy-생성">📚 serializers.py 생성</h2>
<h3 id="✍-코드-2"><strong>✍ 코드</strong></h3>
<pre><code class="language-python"># api/serializers.py

from rest_framework.serializers import ModelSerializer
from .models import Testapi

class TestDataSerializer(ModelSerializer):
    class Meta:
        model = Testapi        # 테이블 명
        fields = &#39;__all__&#39;    # 사용할 필드(열)</code></pre>
<p>serializer는 <strong>직렬화</strong>를 의미한다.
django에 저장되어 있는 모델 인스턴스를 REST API에서 사용하는 JSON형태로 바꿔주는 역할을 한다.</br></br></p>
<hr>
<h2 id="📚-viewspy-수정">📚 views.py 수정</h2>
<h3 id="✍-코드-3"><strong>✍ 코드</strong></h3>
<pre><code class="language-python"># api/views.py

#  HTTP 응답을 생성하고 반환
from rest_framework.response import Response
# 해당 함수가 특정 HTTP 요청 메서드를 처리
from rest_framework.decorators import api_view
from .models import Testapi
from .serializers import TestAPISerializer

@api_view([&#39;GET&#39;])
def getTestAPI(request):
    data = Testapi.objects.all()
    serializer = TestAPISerializer(data, many=True)
    return Response(serializer.data)</code></pre>
<table>
<thead>
<tr>
<th>코드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>@api_view([&#39;GET&#39;])</td>
<td>API 뷰를 정의, HTTP 중 GET 요청을 처리한다.</td>
</tr>
<tr>
<td>Testapi.objects.all()</td>
<td>Testapi 모델에서 모든 데이터를 가져와 저장</td>
</tr>
<tr>
<td>TestAPISerializer(data, many=True)</td>
<td>데이터를 JSON형식으로 변환하여 직렬화</td>
</tr>
<tr>
<td>many=True</td>
<td>여러 객체를 직렬화할 때 사용</td>
</tr>
<tr>
<td>many=False</td>
<td>단일 객체를 직렬화할 때 사용</td>
</tr>
<tr>
<td>return Response(serializer.data)</td>
<td>직렬화된 데이터를 HTTP 응답으로 반환</td>
</tr>
<tr>
<td></br></br></td>
<td></td>
</tr>
</tbody></table>
<hr>
<h2 id="📚-urlspy-수정-및-생성">📚 urls.py 수정 및 생성</h2>
<h3 id="✍-코드-4"><strong>✍ 코드</strong></h3>
<pre><code class="language-python"># project/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path(&#39;admin/&#39;, admin.site.urls),
    path(&#39;api/&#39;, include(&#39;api.urls&#39;))
]</code></pre>
<p>include를 사용하여 Django 애플리케이션을 모듈화하고 다른 애플리케이션에서 정의된 URL 패턴을 현재 애플리케이션에 재사용할 수 있다. 
이를 통해 url을 별로 관리할 수 있도록 도와준다.</p>
<h3 id="✍-코드-5"><strong>✍ 코드</strong></h3>
<pre><code class="language-python"># api/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path(&#39;getapi/&#39;, views.getTestAPI)
]</code></pre>
<p><strong>&#39;testapi/&#39;</strong> 경로로 들어오는 요청은 <strong>&#39;views.getTestAPI&#39;</strong> 함수를 호출한다.</br></br></p>
<hr>
<h2 id="📚-실행">📚 실행</h2>
<p>이제 서버를 실행시킨 후 주소창에 <strong>localhost:8000/api/testapi/</strong>를 입력하면 실행되는 창을 볼 수 있다.</p>
<h3 id="📢-chrome-실행창">📢 Chrome 실행창</h3>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/96e603fd-7604-4e35-accb-71747bb0ca5e/image.png" alt=""></p>
<h3 id="📢-postman-실행창">📢 Postman 실행창</h3>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/ccdc3f85-3089-4bf8-8638-d45ff954fbce/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Django]DB 테이블 가져오기 및 오류 수정]]></title>
            <link>https://velog.io/@hyeo_ni__/DjangoDB-%ED%85%8C%EC%9D%B4%EB%B8%94-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0-%EB%B0%8F-%EC%98%A4%EB%A5%98-%EC%88%98%EC%A0%95</link>
            <guid>https://velog.io/@hyeo_ni__/DjangoDB-%ED%85%8C%EC%9D%B4%EB%B8%94-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0-%EB%B0%8F-%EC%98%A4%EB%A5%98-%EC%88%98%EC%A0%95</guid>
            <pubDate>Mon, 18 Dec 2023 02:43:17 GMT</pubDate>
            <description><![CDATA[<h2 id="📚-db-테이블-가져오기">📚 DB 테이블 가져오기</h2>
<h3 id="✍-코드"><strong>✍ 코드</strong></h3>
<pre><code class="language-bash">$ python manage.py inspectdb &gt; models.py</code></pre>
<ul>
<li>python manage.py inspectdb &gt; models.py
: 기존에 연동되어 있는 DB 테이블을 models.py로 생성 및 저장해준다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/ef55f025-e179-42af-8209-c0e95fb7f812/image.png" alt=""></p>
<h3 id="✍-코드-1"><strong>✍ 코드</strong></h3>
<pre><code class="language-bash">$ python manage.py migrate
$ python manage.py runserver</code></pre>
<p>DB를 수정 혹은 생성할 때 마다 migrate를 입력해줘야한다.</br></br></p>
<hr>
<h2 id="📚-필요한-테이블만-가져오기">📚 필요한 테이블만 가져오기</h2>
<p>inspectdb로 가져온 models.py를 사용하기 위해선 app폴더에 있는 models.py로 가져와야한다.</p>
<p>현재는 testapi만 필요하니 testapi만 옮겨줄 예정이다.</p>
<p>이후 필요없는 models.py는 지워는게 좋다.</p>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/0a73ff77-81f0-4348-baeb-b961fb87fe5d/image.png" alt=""></p>
<p>물론 대부분의 테이블이 필요하다면 파일자체를 덮어쓰기해도 된다.
</br></br></p>
<hr>
<h2 id="📚-에러발생">📚 에러발생</h2>
<h3 id="🔨-에러-코드"><strong>🔨 에러 코드</strong></h3>
<pre><code class="language-bash">ValueError: source code string cannot contain null bytes</code></pre>
<p>간혹 모델을 생성한 후 위와 같이 에러가 발생하는 것을 볼 수 있다.</p>
<p>굉장히 간단히 해결할 수 있는 문제이다.
생성된 모델이 다음과 같이 <strong>UTF-8</strong>로 Encoding되지 않아 발생하는 문제이다.
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/eb16f542-c77e-4aad-bddf-01a4c091cea7/image.png" alt="">
vscode에서 인코딩부분을 누른 후 <strong>Save with Encoding</strong>으로 들어가 <strong>UTF-8</strong>로 변경해주면 쉽게 해결될 문제이다.
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/460d14cf-c74b-4f03-b141-d3a1a7a97950/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/0d91b259-e945-4558-991d-4dd70e265e1f/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Django]MySQL 연동하기]]></title>
            <link>https://velog.io/@hyeo_ni__/DjangoMySQL-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@hyeo_ni__/DjangoMySQL-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 11 Dec 2023 08:37:07 GMT</pubDate>
            <description><![CDATA[<h2 id="📚-mysql-테이블-생성">📚 MySQL 테이블 생성</h2>
<h3 id="✍-코드"><strong>✍ 코드</strong></h3>
<pre><code class="language-sql">create database test;
use test;

create table testapi(
    id int auto_increment primary key,
    title varchar(100),
    content longtext
);

  INSERT INTO testapi(title, content) 
  VALUES(&#39;안녕!&#39;, &#39;testapi야!&#39;);

select * from testapi;</code></pre>
<p>MySQL에 연동하기 이전에 테이블에 생성 후 확인을 해준다.
(물론 연동한 후 해도 상관은 없지만 미리 생성해두었다.)</br></br></p>
<hr>
<h2 id="📚-필요-라이브러리">📚 필요 라이브러리</h2>
<h3 id="✍-코드-1"><strong>✍ 코드</strong></h3>
<pre><code class="language-bash">$ pip install mysqlclient</code></pre>
<p>Python에서 MySQL서버와 통신을 할 수 있게 해주는 커넥터같은 역할을 해준다.</br></br></p>
<hr>
<h2 id="📚-settingspy-설정">📚 settings.py 설정</h2>
<h3 id="✍-코드-2"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">DATABASES = {
    &#39;default&#39;: {
        &#39;ENGINE&#39;: &#39;django.db.backends.mysql&#39;,
        &#39;NAME&#39;: &#39;test&#39;, # 사용할 DataBase 이름
        &#39;USER&#39;: &#39;root&#39;, # DB 사용자명
        &#39;PASSWORD&#39;: &#39;1234&#39;, # DB 사용자 암호
        &#39;HOST&#39;: &#39;localhost&#39;,
        &#39;PORT&#39;: &#39;3306&#39;,
    }
}</code></pre>
<p>위와 같이 Database의 정보를 입력한 후 저장한다.
서버를 실행하는 명령어를 사용하여 제대로 연결되었는지 확인할 수 있다.</br></br></p>
<p><strong>서버 실행 명령어</strong></p>
<h3 id="✍-코드-3"><strong>✍ 코드</strong></h3>
<pre><code class="language-bash">python manage.py runserver</code></pre>
</br>

<hr>
<h2 id="📚-데이터베이스-테이블-연동">📚 데이터베이스 테이블 연동</h2>
<h3 id="✍-코드-4"><strong>✍ 코드</strong></h3>
<pre><code class="language-bash">python manage.py makemigrations
python manage.py migrate</code></pre>
<ul>
<li>python manage.py makemigrations
: 모델(models.py)의 변경 내역을 스키마에 적용시키는 방법</li>
<li>python manage.py migrate
: 실제 DB에 변경사항을 적용하는 명령어</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/217e7fe9-ef15-4b7e-9543-910fda8d64e1/image.png" alt=""></p>
<p>정상적으로 적용 후 MySQL을 확인해보면 장고와 관련된 테이블들이 추가된 것을 확인해 볼 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[MySQL]MySQL 기본 쿼리문]]></title>
            <link>https://velog.io/@hyeo_ni__/MySQLMySQL-%EA%B8%B0%EB%B3%B8-%EC%BF%BC%EB%A6%AC%EB%AC%B8</link>
            <guid>https://velog.io/@hyeo_ni__/MySQLMySQL-%EA%B8%B0%EB%B3%B8-%EC%BF%BC%EB%A6%AC%EB%AC%B8</guid>
            <pubDate>Mon, 04 Dec 2023 07:35:53 GMT</pubDate>
            <description><![CDATA[<h2 id="📝-데이터베이스database">📝 데이터베이스(Database)</h2>
<blockquote>
<p>데이터의 집합(저장소)</p>
</blockquote>
<h2 id="📚-생성-선택-삭제">📚 생성, 선택, 삭제</h2>
<h3 id="✍-코드"><strong>✍ 코드</strong></h3>
<pre><code class="language-sql">CREATE DATABASE database_name;
USE database_name;
DROP DATABASE database_name;</code></pre>
<hr>
<h2 id="📝-테이블table">📝 테이블(Table)</h2>
<h2 id="📚-생성-및-기본키pk">📚 생성 및 기본키(PK)</h2>
<h3 id="✍-코드-1"><strong>✍ 코드</strong></h3>
<pre><code class="language-sql">CREATE TABLE table_name (
    column1 datatype primary key,
    column2 datatype,
    ...
);</code></pre>
<p>컬럼에 따른 데이터 타입을 지정한다.
이때 <strong>Primary Key</strong>는 기본키로 중복 및 NULL값을 비허용한다.
보통 primary key는 id로 많이 지정한다.</p>
<h3 id="✍-코드-2"><strong>✍ 코드</strong></h3>
<pre><code class="language-sql">CREATE TABLE user (
    user_id int auto_increment primary key,
    name varchar(10)
);</code></pre>
<p>위와 같이 입력을 할 경우 id에 자동으로 +1씩 하여 입력이 된다.
name과 같은 경우 최대 10글자까지 입력할 수 있으며 NULL값이 허용된다.</br></br></p>
<h2 id="📚-외래키fk">📚 외래키(FK)</h2>
<h3 id="✍-코드-3"><strong>✍ 코드</strong></h3>
<pre><code class="language-sql">CREATE TABLE info (
    info_id int auto_increment primary key,
    user_id int,
    phone_number varchar(11)
    FOREIGN KEY (user_id) REFERENCES user(user_id)
);</code></pre>
<p>외래키(Foreign key)는 한 테이블의 열(또는 여러 열)이 다른 테이블의 기본 키나 후보 키에 대한 참조(링크)를 나타내는 열이나 열의 집합</p>
<p>외래 키 설정을 통해 데이터 무결성을 유지하고 관련 테이블 간의 관계를 명확하게 정의할 수 있다.</br></br></p>
<h2 id="📚-열-추가add-column">📚 열 추가(ADD COLUMN)</h2>
<h3 id="✍-코드-4"><strong>✍ 코드</strong></h3>
<pre><code class="language-sql">ALTER TABLE table_name
ADD column_name data_type;</code></pre>
<p>기존 테이블에 새로운 열을 추가한다.</br></br></p>
<h2 id="📚-열-수정modify-column">📚 열 수정(MODIFY COLUMN)</h2>
<h3 id="✍-코드-5"><strong>✍ 코드</strong></h3>
<pre><code class="language-sql">ALTER TABLE table_name
MODIFY column_name new_data_type;</code></pre>
<p>기존 열의 데이터 타입을 변경한다.</br></br></p>
<h2 id="📚-열-삭제drop-column">📚 열 삭제(DROP COLUMN)</h2>
<h3 id="✍-코드-6"><strong>✍ 코드</strong></h3>
<pre><code class="language-sql">ALTER TABLE table_name
DROP column_name;</code></pre>
<p>테이블에서 기존 열을 삭제한다.</br></br></p>
<h2 id="📚-외래-키-추가-add-foreign-key">📚 외래 키 추가 (ADD FOREIGN KEY)</h2>
<h3 id="✍-코드-7"><strong>✍ 코드</strong></h3>
<pre><code class="language-sql">ALTER TABLE child_table
ADD CONSTRAINT fk_name
FOREIGN KEY (child_column)
REFERENCES parent_table (parent_column);</code></pre>
<p>외래 키를 추가하여 테이블 간의 관계를 정의한다.</br></br></p>
<h2 id="📚-테이블-이름-변경-rename-table">📚 테이블 이름 변경 (RENAME TABLE)</h2>
<h3 id="✍-코드-8"><strong>✍ 코드</strong></h3>
<pre><code class="language-sql">ALTER TABLE old_table_name
RENAME TO new_table_name;</code></pre>
<p>기존 테이블의 이름을 변경한다.</br></br></p>
<h2 id="📚-기본-키-추가-add-primary-key">📚 기본 키 추가 (ADD PRIMARY KEY)</h2>
<h3 id="✍-코드-9"><strong>✍ 코드</strong></h3>
<pre><code class="language-sql">ALTER TABLE table_name
ADD PRIMARY KEY (column_name);</code></pre>
<p>테이블에 새로운 기본 키를 추가한다.</br></br></p>
<hr>
<h2 id="📝-데이터">📝 데이터</h2>
<h2 id="📚-조회select">📚 조회(SELECT)</h2>
<h3 id="✍-코드-10"><strong>✍ 코드</strong></h3>
<pre><code class="language-sql">SELECT * FROM table_name;</code></pre>
<blockquote>
<p>해당 테이블의 모든 데이터를 조회</p>
</blockquote>
<h3 id="✍-코드-11"><strong>✍ 코드</strong></h3>
<pre><code class="language-sql">SELECT column1, column2 FROM table_name;</code></pre>
<blockquote>
<p>해당 테이블의 특정 열을 선택해서 조회</p>
</blockquote>
<h3 id="✍-코드-12"><strong>✍ 코드</strong></h3>
<pre><code class="language-sql">SELECT * FROM table_name WHERE condition;</code></pre>
<blockquote>
<p>조건에 따라 데이터를 선택해서 조회</p>
</blockquote>
</br>

<h2 id="📚-추가-입력insert">📚 추가, 입력(INSERT)</h2>
<pre><code class="language-sql">INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...);</code></pre>
<p>테이블 중 입력할 열(column)에 값을 넣는다.
</br></p>
<h2 id="📚-업데이트update">📚 업데이트(UPDATE)</h2>
<pre><code class="language-sql">UPDATE table_name SET column1 = value1, column2 = value2 WHERE condition;
</code></pre>
<p>조건(condition)에 맞는 열(column)에 값을 수정한다.</p>
</br>

<h2 id="📚-삭제delete">📚 삭제(DELETE)</h2>
<pre><code class="language-sql">DELETE FROM table_name WHERE condition;</code></pre>
<p>조건(condition)에 맞는 열(column)을 삭제한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Django]장고 프로젝트 및 앱 생성]]></title>
            <link>https://velog.io/@hyeo_ni__/Django%EC%9E%A5%EA%B3%A0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%B0%8F-%EC%95%B1-%EC%83%9D%EC%84%B1</link>
            <guid>https://velog.io/@hyeo_ni__/Django%EC%9E%A5%EA%B3%A0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%B0%8F-%EC%95%B1-%EC%83%9D%EC%84%B1</guid>
            <pubDate>Tue, 28 Nov 2023 13:55:04 GMT</pubDate>
            <description><![CDATA[<h2 id="📝-프로젝트란">📝 프로젝트란?</h2>
<blockquote>
<p>하나의 웹 사이트로 프로젝트 안에는 여러 개의 앱이 존재한다.</p>
</blockquote>
<hr>
<h2 id="📚-프로젝트-생성하기">📚 프로젝트 생성하기</h2>
<h3 id="✍-코드"><strong>✍ 코드</strong></h3>
<pre><code class="language-bash">django-admin startproject &#39;프로젝트명&#39; .</code></pre>
<p>프로젝트명 다음에 오는 점 &#39;<strong>.</strong>&#39;은 현재 디렉터리를 의미한다.
즉, 현재 디렉터리를 기준으로 프로젝트를 생성한다.
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/9aea2411-b423-4fc8-986c-10c734b6a58a/image.png" alt="">
기본적으로 <strong>project</strong>파일과 <strong>manage.py</strong>가 생긴 것을 확인해 볼 수 있다.</br></br></p>
<hr>
<h2 id="📚-프로젝트-구조">📚 프로젝트 구조</h2>
<p>위 이미지에 있는 프로젝트 구조를 한 눈에 보기 쉽게 나타내어 봤다.</p>
<pre><code>Django/
├─ manage.py
└─ project/
    ├─ __init__.py
    ├─ asgi.py
    ├─ settings.py
    ├─ urls.py
    └─ wsgi.py</code></pre><table>
  <tr>
    <td rowspan="1">Django</td>
    <td>사용자가 생성한 폴더</td>
  </tr>
  <tr>
    <td rowspan="1">project</td>
    <td>사용자가 생성한 django 프로젝트 폴더</td>
  </tr>
  <tr>
    <td rowspan="2">manage.py</td>
    <td>웹 서버 실행 및 프로젝트 관리 도구로, 다양한 명령어를 실행 가능</td>
    <tr>
        <td>명령어 : $ python manage.py (command) [options]</td>
      </tr>
  </tr>
  <tr>
    <td rowspan="1">__init__.py</td>
    <td>현재 폴더가 Python 패키지로 인식하기 위한 파일</td>
  </tr>
  <tr>
    <td rowspan="2">asgi.py</td>
    <td>Asynchronous Server Gateway Interface</td>
    <tr>
        <td>Django 애플리케이션이 비동기식 웹서버와 연결/소통하는 것을 도움</td>
      </tr>
  </tr>
  <tr>
    <td rowspan="1">settings.py</td>
    <td>Django 프로젝트 설정을 관리</td>
  </tr>
  <tr>
    <td rowspan="1">urls.py</td>
    <td>Django 프로젝트의 URL 패턴을 정의 (경로 및 요청별 기능 등)</td>
  </tr>
  <tr>
    <td rowspan="2">wsgi.py</td>
    <td>Web Server Gateway Interface</td>
    <tr>
        <td>Django 애플리케이션이 웹서버와 연결 및 소통하는 것을 도움</td>
      </tr>
</table>
</br>

<hr>
<h2 id="📚-앱-생성하기">📚 앱 생성하기</h2>
<h3 id="✍-코드-1"><strong>✍ 코드</strong></h3>
<pre><code class="language-bash">django-admin startapp &#39;앱 명&#39; .</code></pre>
<p>프로젝트 단독으로는 아무런 것도 만들 수 없다.
프로젝트에 기능을 추가하기 위해 앱을 생성해야한다.
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/e2f94f8d-7969-419f-aeef-939896d378c6/image.png" alt="">
기본적으로 <strong>api</strong>파일이 생긴 것을 확인해 볼 수 있다.</br></br></p>
<hr>
<h2 id="📚-프로젝트-구조-1">📚 프로젝트 구조</h2>
<p>위 이미지에 있는 앱 구조를 한 눈에 보기 쉽게 나타내어 봤다.</p>
<pre><code>Django/
├─ project/
├─ db.sqlite3
├─ manage.py
└─ api/
    ├─ __init__.py
    ├─ admin.py
    ├─ apps.py
    ├─ models.py
    ├─ tests.py
    ├─ views.py
    └─ migrations/</code></pre><table>
  <tr>
    <td rowspan="1">__init__.py</td>
    <td>현재 폴더가 Python 패키지로 인식하기 위한 파일</td>
  </tr>
  <tr>
    <td rowspan="1">admin.py</td>
    <td>관리자용 페이지 설정</td>
  </tr>
  <tr>
    <td rowspan="1">apps.py</td>
    <td>앱의 정보</td>
  </tr>
  <tr>
    <td rowspan="1">models.py</td>
    <td>애플리케이션에서 사용하는 Model을 정의 (Data Base)</td>
  </tr>
  <tr>
    <td rowspan="1">tests.py</td>
    <td>프로젝트의 테스트 코드를 작성하는 곳</td>
  </tr>
  <tr>
    <td rowspan="1">views.py</td>
    <td>앱의 기능, 로직을 작성</td>
  </tr>
</table>
</br>

<hr>
<h2 id="📚-로컬-서버-구동">📚 로컬 서버 구동</h2>
<p>기본적인 프로젝트와 앱을 생성하였으면 아래 코드를 통해 서버를 실행할 수 있다.</p>
<h3 id="✍-코드-2"><strong>✍ 코드</strong></h3>
<pre><code class="language-bash">python manage.py runserver</code></pre>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/30cc781a-41f0-4194-8a4d-60201e7cb0e8/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Django]가상 환경 및 장고 개발 환경]]></title>
            <link>https://velog.io/@hyeo_ni__/Django%EA%B0%80%EC%83%81-%ED%99%98%EA%B2%BD-%EB%B0%8F-%EC%9E%A5%EA%B3%A0-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD</link>
            <guid>https://velog.io/@hyeo_ni__/Django%EA%B0%80%EC%83%81-%ED%99%98%EA%B2%BD-%EB%B0%8F-%EC%9E%A5%EA%B3%A0-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD</guid>
            <pubDate>Mon, 20 Nov 2023 06:55:10 GMT</pubDate>
            <description><![CDATA[<h2 id="📝-가상-환경이란">📝 가상 환경이란?</h2>
<blockquote>
<p><strong>독립된 공간</strong>을 만들어주는 기능</p>
</blockquote>
<p>다양한 프로젝트를 진행하며, <strong>서로 다른 버전</strong>의 장고나 패키지들을 사용해야 하는 문제들이 발생할 수 있다.
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/2acc0c65-c124-43a8-a844-99f43ad807e1/image.png" alt=""></p>
<p>이러한 문제를 해결하기 위해 가상 환경을 사용하는데, 하나의 PC안에 독립된 공간을 여러개 만들어 사용할 수 있다.
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/2b17cad5-5482-4b9c-b3f6-c6ea1aa3b81c/image.png" alt="">
</br></br></p>
<hr>
<h2 id="📚-가상-환경-구축-방법">📚 가상 환경 구축 방법</h2>
<h3 id="✍-코드"><strong>✍ 코드</strong></h3>
<pre><code class="language-bash">C:\&gt; mkdir venv
C:\&gt; cd venv
C:\venv\&gt; python -m venv project</code></pre>
<ul>
<li><strong>python -m</strong> : 라이브러리 모듈을 스크립트로 실행 </li>
</ul>
<p>venv파일에 &#39;project&#39;라는 이름의 가상 환경을 생성했다면 이제 사용하기 위해 가상 환경에 진입해야한다.</p>
<p>가상 환경에 진입하기 위해 생성한 가상 환경에 있는 <strong>Scripts</strong>디렉터리의 activate 명령을 실행해야 한다.</p>
<h3 id="✍-코드-1"><strong>✍ 코드</strong></h3>
<pre><code class="language-bash">C:\venv\&gt; cd C:\venv\project\Scripts
C:\venv\project\Scripts&gt; activate</code></pre>
<p>이렇게 실행을 하면 C:\ 왼쪽에 (project)가 생긴 것을 확인할 수 있다.
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/96071243-f0c7-4567-81bc-273fc708f0d6/image.png" alt=""></p>
<p>만약 activate로 실행이 안될 경우 <strong>.\activate</strong>로 실행할 수도 있다.</p>
<p>현재 가상 환경에서 벗어나고 싶을 경우 <strong>deactivate</strong>명령어를 실행하면 된다.</p>
<h2 id="📚-맥mac에서-가상-환경-진입">📚 맥(mac)에서 가상 환경 진입</h2>
<p>mac은 가상 환경 진입하는 방법이 window와 다르다.
가상 환경을 생성하는 명령어 까진 같다.</p>
<h3 id="✍-코드-2"><strong>✍ 코드</strong></h3>
<pre><code class="language-bash">maehyong@mymac venvs % cd project/bin
maehyong@mymac bin % source activate
(project) maehyong@mymac bin %</code></pre>
<p>window는 <strong>Scripts</strong>폴더가 생성되며, Linux나 Mac과 같은 경우 <strong>bin</strong>폴더가 생성된다.
</br></br></p>
<hr>
<h2 id="📚-장고-설치">📚 장고 설치</h2>
<p>장고를 설치하기 이전 가상 환경에 들어가 있는지 꼭 확인 후 설치하는 것이 좋다.</p>
<p>그 이유는 위에서 설명 하였으니 위를 참고하면 될 것 같다.</p>
<h3 id="✍-코드-3"><strong>✍ 코드</strong></h3>
<pre><code class="language-bash">(project) C:\venv\project\Scripts&gt; pip install django</code></pre>
<ul>
<li><strong>pip</strong> : 파이썬 라이브러리를 설치 및 관리</li>
</ul>
<p>장고를 설치해줄 때 <strong>django==버전</strong>을 입력할 경우 해당 버전이 설치가 된다.
<img src="https://velog.velcdn.com/images/hyeo_ni__/post/a7d00e0f-8f13-40ad-9b6f-e516296a2847/image.png" alt="">
위와 같은 화면이 나올 경우 장고가 제대로 설치된 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Django]Django란?]]></title>
            <link>https://velog.io/@hyeo_ni__/Django%EB%9E%80</link>
            <guid>https://velog.io/@hyeo_ni__/Django%EB%9E%80</guid>
            <pubDate>Wed, 15 Nov 2023 08:43:26 GMT</pubDate>
            <description><![CDATA[<h2 id="📝-django란">📝 Django란?</h2>
<blockquote>
<p><strong>Python</strong>기반의 풀스택 웹 프레임워크
오픈 소스로 웹을 만드는데 필요한 대부분의 기능을 가지고 있다.</p>
</blockquote>
<p>여기서 웹 프레임워크를 간단히 설명하면 &quot;<strong>웹 프로그램을 만들기 위한 스타터 키트</strong>&quot;라고 생각하면 쉽다.</br></br></p>
<hr>
<h2 id="📚-django의-장점">📚 Django의 장점</h2>
<blockquote>
<ul>
<li>빠르다.
웹 개발시 번거로움을 배부분 처리해주어, 개발자가 애플리케이션의 개념부터 완성까지 단 시간 안에 진행할 수 있습니다.</br>
</li>
</ul>
</blockquote>
<ul>
<li>보안성이 좋다.
보안을 중요하게 생각하여 개발을 하며 쉽게 발생할 수 있는 실수들을 막아줍니다.</br></li>
<li>확장성이 뛰어나다.
가장 많은 트래픽 수요를 충족시키기 위해 빠르고 유연하게 확장할 수 있습니다.</li>
</ul>
<p>크게 3가지의 장점을 가지고 있는 장고는 <a href="https://www.djangoproject.com/">Django</a> 공식 사이트에 들어가 보면 위쪽 상단에 &#39;<strong>The web framework for perfectionists with deadlines.</strong>&#39;라고 적혀 있는 것을 확인해 볼 수 있다.
해석 해보면 &#39;마감에 쫓기는 완벽주의자를 위한 웹 프레임워크&#39;이다.</p>
<p>Django는 개발에 있어 정말 필요한 기능이 모여있다는 것을 알 수 있다.
</br></p>
<hr>
<h2 id="📚-django를-사용-중인-곳">📚 Django를 사용 중인 곳</h2>
<blockquote>
<ul>
<li>instargram</li>
</ul>
</blockquote>
<ul>
<li>toss</li>
<li>번개장터</li>
<li>화해</li>
<li>기타 등등..</li>
</ul>
<p>대표적인 4곳을 가져와봤는데, 이외에도 많은 곳에서 Django를 사용하여 웹사이트를 구축했다.</p>
<p>그중 <strong>instargram</strong>에서는 세계에서 제일 큰 규모의 장고 웹사이트이며, toss는 사내 서비스 개발에 사용되었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python]기본 문법(메소드, 상속, 추상메소드, 추상 클래스)]]></title>
            <link>https://velog.io/@hyeo_ni__/Python%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95%EB%A9%94%EC%86%8C%EB%93%9C-%EC%83%81%EC%86%8D-%EC%B6%94%EC%83%81%EB%A9%94%EC%86%8C%EB%93%9C-%EC%B6%94%EC%83%81-%ED%81%B4%EB%9E%98%EC%8A%A4</link>
            <guid>https://velog.io/@hyeo_ni__/Python%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95%EB%A9%94%EC%86%8C%EB%93%9C-%EC%83%81%EC%86%8D-%EC%B6%94%EC%83%81%EB%A9%94%EC%86%8C%EB%93%9C-%EC%B6%94%EC%83%81-%ED%81%B4%EB%9E%98%EC%8A%A4</guid>
            <pubDate>Mon, 13 Nov 2023 07:50:46 GMT</pubDate>
            <description><![CDATA[<h2 id="📝-메소드">📝 메소드</h2>
<blockquote>
<p><img src="https://velog.velcdn.com/images/hyeo_ni__/post/713b0bbc-7219-4173-8f29-cf3b81912303/image.png" alt=""></p>
</blockquote>
<hr>
<h2 id="📝-상속">📝 상속</h2>
<blockquote>
<p>부모 class의 내용을 자식 class가 물려받는 것</p>
</blockquote>
<p></br><strong>항목 순서는 의미가 없으며, 키는 중복될 수 없다.</strong>
또한, 키는 수정될 수 없지만, 값은 수정될 수 있다.</p>
<h3 id="✍-코드"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">class 부모:
    ...내용...

class 자식(부모):
    ...내용...</code></pre>
<h3 id="✍-코드-1"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">class Country:
    name = &#39;국가명&#39;
    population = &#39;인구&#39;
    capital = &#39;수도&#39;

    def show(self):
        print(&#39;국가 클래스의 메소드입니다.&#39;)

class Korea(Country):
    def __init__(self, name):
        print(&#39;__init__&#39;)
        self.name = name

    def show_name(self):
        print(&#39;국가 이름은 : &#39;, self.name)</code></pre>
<p></br>위 코드를 실행시 Korea는 Country Class를 상속받게 된다.</p>
<h3 id="✍-코드-2"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">a = Korea(&#39;대한민국&#39;)
a.show()
a.show_name()
a.capital
a.name</code></pre>
<h3 id="💻-출력"><strong>💻 출력</strong></h3>
<pre><code class="language-python">__init__
국가 클래스의 메소드입니다.
국가 이름은 :  대한민국
수도
대한민국</code></pre>
<ul>
<li>a = Korea(&#39;대한민국&#39;)
객체가 생성되며 name은 대한민국으로 변환된다.</li>
<li>a.show(), a.capital, a.name
Country를 상속 받았기 때문에 각각의 함수 및 변수가 실행되어 출력된다.</br></br></li>
</ul>
<hr>
<h2 id="📝-추상-메소드">📝 추상 메소드</h2>
<blockquote>
<p>아직 구현이 종료되지 않은 미완성 메소드</p>
</blockquote>
<p>추상 클래스를 지원하는 모듈 abc(Abstract Base Class)를 가져오기 위해 import를 해야한다.</p>
<ul>
<li>정의되는 클래스의 괄호 안에 <strong>metaclass = abc.ABCMeta</strong>를 지정</li>
<li>추상 메소드 머리 위에 데코레이터 <strong>@abc.abstractmethod</strong>를 넣어 메소드가 추상이라는 것을 지정<h3 id="✍-코드-3"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">from abc import *
class Polygon(metaclass = MBCMeta):
  @abstractmethod
  def area(self):
      pass</code></pre>
</br></br></li>
</ul>
<hr>
<h2 id="📝-추상-클래스abstract-class">📝 추상 클래스(abstract class)</h2>
<blockquote>
<p>미완성인 추상 메소드를 적어도 하나 이상 갖는 클래스로 부모인 추상 클래스는 자신만을 객체 인스턴스로 생성 불가능</p>
</blockquote>
<p>이때 추상 메소드는 자식 클래스에서 반드시 구현해야한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python]기본 문법(리스트, 튜플, 딕셔너리) ]]></title>
            <link>https://velog.io/@hyeo_ni__/Python%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95%EB%A6%AC%EC%8A%A4%ED%8A%B8-%ED%8A%9C%ED%94%8C-%EB%94%95%EC%85%94%EB%84%88%EB%A6%AC</link>
            <guid>https://velog.io/@hyeo_ni__/Python%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95%EB%A6%AC%EC%8A%A4%ED%8A%B8-%ED%8A%9C%ED%94%8C-%EB%94%95%EC%85%94%EB%84%88%EB%A6%AC</guid>
            <pubDate>Wed, 08 Nov 2023 11:50:53 GMT</pubDate>
            <description><![CDATA[<h2 id="📝-리스트list">📝 리스트(list)</h2>
<blockquote>
<p>항목의 순서나 내용을 수정할 수 있는 항목의 나열</p>
</blockquote>
<h4 id="--콜론으로-구분된-항목을-표현합니다"><strong>[]</strong> : 콜론으로 구분된 항목을 표현합니다.</h4>
<h3 id="✍-코드"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">A = []</code></pre>
<p></br>비어있는 리스트를 생성하는 방법입니다.</br></br></p>
<hr>
<h2 id="📝-튜플tuple">📝 튜플(Tuple)</h2>
<blockquote>
<p>항목의 순서나 내용을 수정할 수 없는 항목의 나열</p>
</blockquote>
<h4 id="--콤마로-구분된-항목을-표현합니다"><strong>()</strong> : 콤마로 구분된 항목을 표현합니다.</h4>
<p></br> 기타 내용</p>
<h3 id="✍-코드-1"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">A = ()</code></pre>
<p></br>비어있는 튜플을 생성하는 방법입니다.</br></br></p>
<hr>
<h2 id="📝-딕셔너리dict">📝 딕셔너리(Dict)</h2>
<blockquote>
<p>키와 값의 쌍인 항목을 나열한 시퀀스입니다.</p>
</blockquote>
<h4 id="keyvalue--일련의-키와-값을-쌍으로-리스트-형식과-튜플-형식을-모두-사용합니다"><strong>{&#39;key&#39;:&#39;value&#39;}</strong> : 일련의 키와 값을 쌍으로 리스트 형식과 튜플 형식을 모두 사용합니다.</h4>
<p></br><strong>항목 순서는 의미가 없으며, 키는 중복될 수 없습니다.</strong>
또한, 키는 수정될 수 없지만, 값은 수정될 수 있습니다.</p>
<h3 id="✍-코드-2"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">dict = {&#39;사과&#39;:&#39;apple&#39;, &#39;곰&#39;:&#39;bear&#39;}
print(dict)</code></pre>
<h3 id="💻-출력"><strong>💻 출력</strong></h3>
<pre><code class="language-python">{&#39;사과&#39;: &#39;apple&#39;, &#39;곰&#39;: &#39;bear&#39;}</code></pre>
<p></br>키가 단순 문자열이면 간단히 월=’Monday’처럼 키 = 값 항목 나열로도 지정 가능합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python]기본 문법(반복문, break, continue)]]></title>
            <link>https://velog.io/@hyeo_ni__/Python%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95%EB%B0%98%EB%B3%B5%EB%AC%B8-break-continue</link>
            <guid>https://velog.io/@hyeo_ni__/Python%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95%EB%B0%98%EB%B3%B5%EB%AC%B8-break-continue</guid>
            <pubDate>Mon, 06 Nov 2023 05:00:11 GMT</pubDate>
            <description><![CDATA[<h2 id="📝-반복문이란">📝 반복문이란?</h2>
<blockquote>
<p>프로그램 내에서 똑같은 명령을 일정 횟수만큼 반복하여 수행하도록 제어하는 명령문</br>
반복문에는 <strong>for문</strong>과 <strong>while문</strong>이 있다.</p>
</blockquote>
<hr>
<h2 id="📚-for문">📚 for문</h2>
<blockquote>
<p>정해져 있는 시퀀스의 항목 값으로 반복을 실행</p>
</blockquote>
<p></br>만약 여러 개의 값을 갖는 시퀀스에서 변수에 하나의 값을 순서대로 할당하며, 할당된 변수값을 갖고 블록의 문장들을 순차적으로 실행한다.</p>
<h3 id="✍-코드"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">for 변수 in 시퀀스:
    문장1
    문장2</code></pre>
<h3 id="✍-코드-1"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">for A in range(3):
  print(&#39;반복문&#39;)</code></pre>
<h3 id="💻-출력"><strong>💻 출력</strong></h3>
<pre><code class="language-python">반복문
반복문
반복문</code></pre>
<p></br>정해진 횟수만큼 실행 후 종료된다.</br></br></p>
<hr>
<h2 id="📚-while문">📚 while문</h2>
<blockquote>
<p>논리 표현식이 True인 동안 while문에 속한 문장들이 반복해서 수행</p>
</blockquote>
<h3 id="✍-코드-2"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">while 논리 표현식:
    문장1
    문장2</code></pre>
<h3 id="✍-코드-3"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">A = 0
while A &lt; 3:
  print(&#39;반복 횟수는 {}번입니다.&#39;.format(A + 1))
  A += 1</code></pre>
<h3 id="💻-출력-1"><strong>💻 출력</strong></h3>
<pre><code class="language-python">반복 횟수는 1번입니다.
반복 횟수는 2번입니다.
반복 횟수는 3번입니다.</code></pre>
<p></br>반복문을 실행하다가 False일 경우 실행이 종료된다.</br></br></p>
<hr>
<h2 id="📚-break">📚 break</h2>
<blockquote>
<p>break문 이후에 있는 문장들을 실행하지 않고 반복문을 종료하고 빠져나간다.</p>
</blockquote>
<h3 id="✍-코드-4"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">A = 0
while True:
  if A &gt;= 3:
      break
  print(&#39;반복 횟수는 {}번입니다.&#39;.format(A + 1))
  A += 1</code></pre>
<h3 id="💻-출력-2"><strong>💻 출력</strong></h3>
<pre><code class="language-python">반복 횟수는 1번입니다.
반복 횟수는 2번입니다.
반복 횟수는 3번입니다.</code></pre>
<p></br></br></p>
<hr>
<h2 id="📚-continue">📚 continue</h2>
<blockquote>
<p>continue문 이후의 문장은 실행하지 않고 다시 논리 표현식을 검사</p>
</blockquote>
<h3 id="✍-코드-5"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">for A in range(1, 11):
  if A % 2 == 0:
    print(&#39;2의 배수인 {}입니다.&#39;.format(A))
  continue
  print(&#39;저는 출력이 안됩니다.&#39;)</code></pre>
<h3 id="💻-출력-3"><strong>💻 출력</strong></h3>
<pre><code class="language-python">2의 배수인 2입니다.
2의 배수인 4입니다.
2의 배수인 6입니다.
2의 배수인 8입니다.
2의 배수인 10입니다.</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python]기본 문법(내장함수)]]></title>
            <link>https://velog.io/@hyeo_ni__/Python%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95%EB%82%B4%EC%9E%A5%ED%95%A8%EC%88%98-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%8B%A4%EC%9D%8C-%EC%97%85%EB%A1%9C%EB%93%9C</link>
            <guid>https://velog.io/@hyeo_ni__/Python%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95%EB%82%B4%EC%9E%A5%ED%95%A8%EC%88%98-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%8B%A4%EC%9D%8C-%EC%97%85%EB%A1%9C%EB%93%9C</guid>
            <pubDate>Fri, 03 Nov 2023 05:48:20 GMT</pubDate>
            <description><![CDATA[<h2 id="📝-내장함수란">📝 내장함수란?</h2>
<blockquote>
<p>파이썬 라이브러리로 인터프리터에서 아무런 설정 없이 바로 사용할 수 있는 함수들</p>
</blockquote>
<p></br>다양한 함수들 중 많이 사용하는 함수 몇가지를 정리해봤다.</br></br></p>
<hr>
<h2 id="📚-min">📚 min()</h2>
<blockquote>
<p>문자열을 구성하는 문자에서 코드 값으로 구분하여 <strong>최소값</strong>을 반환</p>
</blockquote>
<h3 id="✍-코드"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">A = [3, 5, 8, 2, 1, 7]
print(min(A))</code></pre>
<h3 id="💻-출력"><strong>💻 출력</strong></h3>
<pre><code class="language-python">1</code></pre>
<p></br></br></p>
<hr>
<h2 id="📚-max">📚 max()</h2>
<blockquote>
<p>문자열을 구성하는 문자에서 코드 값으로 구분하여 <strong>최대값</strong>을 반환</p>
</blockquote>
<h3 id="✍-코드-1"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">A = [3, 5, 8, 2, 1, 7]
print(max(A))</code></pre>
<h3 id="💻-출력-1"><strong>💻 출력</strong></h3>
<pre><code class="language-python">8</code></pre>
<p></br></br></p>
<hr>
<h2 id="📚-range">📚 range()</h2>
<blockquote>
<p>0부터 n-1까지 n개의 항목인 정수로 구성되는 시퀀스이다.</p>
</blockquote>
<p></br>기본적으로 <strong>range(start, stop, step)</strong>형식으로 이루어져 있으며, step을 생략할 경우 기본적으로 1이 들어간다.</p>
<h3 id="✍-코드-2"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">for A in range(0, 11, 2):
  print(A)</code></pre>
<h3 id="💻-출력-2"><strong>💻 출력</strong></h3>
<pre><code class="language-python">0
2
4
6
8
10</code></pre>
<p></br><strong>0부터 10까지 2씩 증가</strong>하는 값을 출력한다.</br></br></p>
<hr>
<h2 id="📚-sorted">📚 sorted()</h2>
<blockquote>
<p>리스트 항목의 순서를 정렬한 리스트를 반환하는 내장함수</p>
</blockquote>
<h3 id="✍-코드-3"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">A = [3, 5, 8, 2, 1, 7]
print(sorted(A))</code></pre>
<h3 id="💻-출력-3"><strong>💻 출력</strong></h3>
<pre><code class="language-python">[1, 2, 3, 5, 7, 8]</code></pre>
<p></br>기본적으로 <strong>오름차순</strong>으로 정렬해준다.</br></br></p>
<hr>
<h2 id="📚-zip">📚 zip()</h2>
<blockquote>
<p>몇 개의 리스트나 튜플의 항목으로 조합된 튜플을 생성</p>
</blockquote>
<p></br>동일한 수로 이뤄진 여러 개의 튜플 항목 시퀀스를 각각의 <strong>리스트</strong>로 묶어 주는 역할이다.</p>
<h3 id="✍-코드-4"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">upper = [&#39;A&#39;, &#39;B&#39;, &#39;C&#39;]
lower = [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;]
for A in zip(upper, lower):
  print(A)</code></pre>
<h3 id="💻-출력-4"><strong>💻 출력</strong></h3>
<pre><code class="language-python">(&#39;A&#39;, &#39;a&#39;)
(&#39;B&#39;, &#39;b&#39;)
(&#39;C&#39;, &#39;c&#39;)</code></pre>
<p></br>이렇게 리스트로 묶어준 튜플은 자료형 zip이 되며, 간단히 리스트나 튜플로 변환한다.</br></br></p>
<hr>
<h2 id="📚-lambda">📚 lambda</h2>
<blockquote>
<p>작고 이름이 없는(익명, Anonymous) 함수로 사용자 정의 함수와 비슷한 역할
이러한 람다 함수는 여러 개의 인자를 취할 수 있지만 표현식은 하나만 가능하다는 단점이 있다.</p>
</blockquote>
<h4 id="lambda-매개변수--표현식expression"><strong>lambda 매개변수 : 표현식(expression)</strong></h4>
<p></br>사용자 정의 함수를 사용하게 된다면 아래와 같이 코드가 길어지게 된다.
이런 간단한 코드를 간추리기 위해 lambda 함수를 사용한다.</p>
<h3 id="✍-코드-5"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">def hap(x, y):
    return x + y
x, y = map(int, input().split())
hap(x, y)</code></pre>
<h3 id="💻-출력-5"><strong>💻 출력</strong></h3>
<pre><code class="language-python">2 3
5</code></pre>
<p></br>이런 간단한 코드를 간추리기 위해 lambda 함수를 사용한다.
위 코드를 람다식으로 표현해보면 아래와 같다.</p>
<h3 id="✍-코드-6"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">(lambda x,y: x + y)(2, 3)</code></pre>
<h3 id="💻-출력-6"><strong>💻 출력</strong></h3>
<pre><code class="language-python">5</code></pre>
<p></br>위와 같이 간단하게 정리된 코드를 볼 수 있다.</br></br></p>
<hr>
<h2 id="📚-map">📚 map</h2>
<blockquote>
<p>여러 개의 데이터를 한 번에 다른 형태로 변환하기 위해 사용되며, 여러 개의 데이터를 담고 있는 list나 tuple을 대상으로 주로 사용하는 함수
<strong>map(변환 함수, 순회 가능한 데이터)</strong></p>
</blockquote>
<h3 id="✍-코드-7"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">x, y = map(int, input().split())
print(x)
print(y)</code></pre>
<h3 id="💻-출력-7"><strong>💻 출력</strong></h3>
<pre><code class="language-python">3 5
3
5</code></pre>
<p></br>띄어쓰기를 기준으로 구분하여 리스트로 변환시켜 각 변수 x와 y에 값을 저장할 수 있다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python]기본 문법(사용자 정의 함수)]]></title>
            <link>https://velog.io/@hyeo_ni__/Python%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%A0%95%EC%9D%98-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@hyeo_ni__/Python%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%A0%95%EC%9D%98-%ED%95%A8%EC%88%98</guid>
            <pubDate>Wed, 01 Nov 2023 01:39:29 GMT</pubDate>
            <description><![CDATA[<h2 id="📝-사용자-정의-함수란">📝 사용자 정의 함수란?</h2>
<blockquote>
<p>사용자가 <strong>직접</strong> 생성하여 사용할 수 있는 함수</p>
</blockquote>
<hr>
<h2 id="📝-def">📝 def</h2>
<blockquote>
<p>함수 정의 키워드</p>
</blockquote>
<h4 id="def-함수이름-인자1-인자2-"><strong>def 함수이름 (인자1, 인자2, …)</strong></h4>
<h3 id="✍-코드"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">def 함수이름 (인자1, 인자2, …)
    문장1
    문장2
    return 반환값1, 반환값2, … </code></pre>
<h3 id="✍-코드-1"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">def hello(name):
    print(&#39;안녕하세요. {}님 반갑워요! :)&#39;.format(name))
hello(&#39;velog&#39;)</code></pre>
<h3 id="💻-출력"><strong>💻 출력</strong></h3>
<pre><code class="language-python">안녕하세요. velog님 반갑워요! :)</code></pre>
<p></br>return값이 꼭 없어도 된다.</p>
<h3 id="✍-코드-2"><strong>✍ 코드</strong></h3>
<pre><code class="language-python">def Calculate(x, y, c):
  if c == &#39;+&#39;:
    return &#39;결과는 {}입니다!&#39;.format(x + y)
  elif c == &#39;-&#39;:
    return &#39;결과는 {}입니다!&#39;.format(x - y)
  elif c == &#39;*&#39;:
    return &#39;결과는 {}입니다!&#39;.format(x * y)
  elif c == &#39;//&#39;:
    return &#39;결과는 {}입니다!&#39;.format(x // y)
Calculate(10, 5, &#39;+&#39;)</code></pre>
<h3 id="💻-출력-1"><strong>💻 출력</strong></h3>
<pre><code class="language-python">결과는 15입니다!</code></pre>
<p></br>return문으로 함수 기능을 수행한 후 반환 값을 전달한다.</p>
]]></description>
        </item>
    </channel>
</rss>