<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>j-_-.log</title>
        <link>https://velog.io/</link>
        <description>juny</description>
        <lastBuildDate>Sat, 23 Apr 2022 14:35:24 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. j-_-.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/j-_-" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[python 시간 중복 계산 (feat. set)]]></title>
            <link>https://velog.io/@j-_-/python-%EC%8B%9C%EA%B0%84-%EC%A4%91%EB%B3%B5-%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@j-_-/python-%EC%8B%9C%EA%B0%84-%EC%A4%91%EB%B3%B5-%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Sat, 23 Apr 2022 14:35:24 GMT</pubDate>
            <description><![CDATA[<h1 id="python-시간-중복-계산">python 시간 중복 계산</h1>
<h2 id="문제">문제</h2>
<p>A 직원은 09:00 출근 14:00 퇴근
B 직원은 12:00 출근 20:00 퇴근</p>
<p>점심 시간은 12:00-13:00</p>
<p>점심시간을 제외하고 A직원이나 B직원이 가게에 있었던 시간은 몇분인지 구하시오.</p>
<h2 id="접근-방식">접근 방식</h2>
<p>자료구조 중 SET은 중복이 존재하지 않는다는 특징이 있습니다.</p>
<blockquote>
<p>중복제거((A의 근무 시간 목록) + (B의 근무 시간 목록)) - (점심시간)</p>
</blockquote>
<p>중복 제거 후 결과의 길이를 구하면 중복 제거된 시간을 찾아낼 수 있습니다.</p>
<pre><code class="language-python">def get_work_time(start, end):

    work_min_list = []
    work_range = []
    bgng_dt = datetime.datetime.strptime(start, &quot;%Y%m%d%H%M&quot;)
    end_dt = datetime.datetime.strptime(end, &quot;%Y%m%d%H%M&quot;)

    if bgng_dt == end_dt:
        return work_min_list
    else:
        work_range = daterange_min(bgng_dt, end_dt - datetime.timedelta(minutes=1))


    for dt in work_range:
        work_min_list.append(dt)

    return work_min_list


def daterange_min(bgng_dt, end_dt):
    for n in range(int((end_dt - bgng_dt).seconds / 60) + 1):
        yield bgng_dt + datetime.timedelta(minutes=n)


A_work_list = get_work_time(&quot;202204230900&quot;, &quot;202204231400&quot;)
B_work_list = get_work_time(&quot;202204231200&quot;, &quot;202204232000&quot;)
launch_list = get_work_time(&quot;202204231200&quot;, &quot;202204231300&quot;)

print(&quot;결과:&quot;, len(list(set(A_work_list + B_work_list) - set(launch_list))))

결과 : 600</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Django app 자동 추가 전략]]></title>
            <link>https://velog.io/@j-_-/Django-app-%EC%9E%90%EB%8F%99-%EC%B6%94%EA%B0%80-%EC%A0%84%EB%9E%B5</link>
            <guid>https://velog.io/@j-_-/Django-app-%EC%9E%90%EB%8F%99-%EC%B6%94%EA%B0%80-%EC%A0%84%EB%9E%B5</guid>
            <pubDate>Wed, 20 Apr 2022 17:22:52 GMT</pubDate>
            <description><![CDATA[<h1 id="django-app-자동-추가">django app 자동 추가</h1>
<p>Django로 개발을 진행하다보면 자연스럽게 생성한 app을 settings.py 하위에 INSTALLED_APPS 안에 등록하게 됩니다.</p>
<p>등록되는 앱의 수가 적다면 하나씩 등록해도 되지만 앱 개수가 많아진다면 어떤 앱이 등록되었는지 어떤 앱이 등록되지 않았는지 정리가 힘들게 됩니다.</p>
<p>이 문제를 해결하기 위해 프로젝트에 등록되는 앱들을 하나의 폴더에 넣고 해당 폴더 안의 모든 앱들을 자동으로 INSTALLED_APPS에 등록되도록 합니다. </p>
<h2 id="프로젝트-생성-및-구조">프로젝트 생성 및 구조</h2>
<blockquote>
<p>Django-admin startproject auto_app_test</p>
</blockquote>
<p>기본적으로 프로젝트 명으로 메인 폴더가 생성되고 하위에 settings.py가 존재합니다.
<img src="https://velog.velcdn.com/images/j-_-/post/9d390b5d-fef8-41fc-b2a3-8ef9cc095d00/image.png" alt=""></p>
<h2 id="기본-app-생성-및-추가">기본 app 생성 및 추가</h2>
<blockquote>
<p>cd auto_app_test
python manage.py startapp test1</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/j-_-/post/94d2d0b7-5dde-4023-aeda-297f9c9c3d64/image.png" alt=""></p>
<p>manage.py를 이용하여 새로운 app을 생성하면 settings.py에 생성된 app 폴더의 apps.py 클래스의 name값을 등록해야 한다.</p>
<p><img src="https://velog.velcdn.com/images/j-_-/post/20a59c64-b6fa-41dc-acdc-3466359eccbf/image.png" alt=""><img src="https://velog.velcdn.com/images/j-_-/post/8103cbc9-3dd9-49f7-bbf6-2508eca222d1/image.png" alt=""></p>
<h3 id="기본-설정-서버-실행-확인">기본 설정 서버 실행 확인</h3>
<blockquote>
<p>python manage.py runserver
서버를 실행시켜 에러가 나지 않고 정상적으로 실행되는 것을 체크한다.</p>
</blockquote>
<h2 id="자동-app추가를-위해-폴더-구조-변경">자동 app추가를 위해 폴더 구조 변경</h2>
<blockquote>
<p>mkdir app</p>
</blockquote>
<h3 id="app폴더-이동-및-실행-테스트">app폴더 이동 및 실행 테스트</h3>
<p><img src="https://velog.velcdn.com/images/j-_-/post/e916ca9d-2373-49f5-b831-bc37de2dffad/image.png" alt=""></p>
<p>‘app’ 폴더를 생성한 후 앞서 생성했던 test1  폴더를 app폴더 하위로 이동시킨다.
이대로 서버를 실행하면 ‘ModuleNotFoundError: No module named &#39;test1&#39;‘ 에러가 발생한다.</p>
<p>이것을 해결하기 위해선 2가지를 ‘app.test1’로 수정해야 한다.</p>
<ol>
<li>app/test1/apps.py 클래스 name값</li>
<li><ol start="2">
<li>settings.py INSTALLED_APPS </li>
</ol>
</li>
</ol>
<h3 id="기본-설정-서버-실행-확인-1">기본 설정 서버 실행 확인</h3>
<blockquote>
<p>python manage.py runserver</p>
</blockquote>
<p>정상적으로 실행된다.</p>
<h2 id="앱-자동추가-로직-생성">앱 자동추가 로직 생성</h2>
<blockquote>
<p>settings.py</p>
</blockquote>
<p>Python은 인터프리터 언어이기 때문에 위에서 아래로 순차적으로 해석한다. 즉, settings.py의 INSTALLED_APPS 배열 상단에서 자동화 로직을 추가 가능하다.</p>
<pre><code class="language-python">
# settings.py
# api/하위폴더에 apps.py를 소유한 폴더라면 app으로 인식하고 등록합니다.
def get_app_list():
    app_list = []
    app_dir = os.path.join(BASE_DIR, &#39;app&#39;)
    for file in os.listdir(app_dir):
        file_path = os.path.join(app_dir, file)
        if os.path.isdir(file_path):
            if os.path.exists(os.path.join(file_path, &#39;apps.py&#39;)):
                app_list.append(file)

    app_list = list(map(lambda x: f&quot;app.{x}&quot;, app_list))
    return app_list


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;,
                 ] + get_app_list()</code></pre>
<h3 id="자동-앱-추가-실행-확인">자동 앱 추가 실행 확인</h3>
<blockquote>
<p>python manage.py runserver</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/j-_-/post/00c1791e-bcac-4586-8f20-878401a90c65/image.png" alt=""></p>
<p>정상적으로 실행된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[python  개발을 위한 가상 환경 세팅 (feat. pip)]]></title>
            <link>https://velog.io/@j-_-/python-%EA%B0%9C%EB%B0%9C%EC%9D%84-%EC%9C%84%ED%95%9C-%EA%B0%80%EC%83%81-%ED%99%98%EA%B2%BD-%EC%84%B8%ED%8C%85-feat.-pip</link>
            <guid>https://velog.io/@j-_-/python-%EA%B0%9C%EB%B0%9C%EC%9D%84-%EC%9C%84%ED%95%9C-%EA%B0%80%EC%83%81-%ED%99%98%EA%B2%BD-%EC%84%B8%ED%8C%85-feat.-pip</guid>
            <pubDate>Tue, 19 Apr 2022 17:14:27 GMT</pubDate>
            <description><![CDATA[<h1 id="django-개발을-위한-가상-환경-세팅">django 개발을 위한 가상 환경 세팅</h1>
<p>python3을 이용하여 한 가지 프로젝트만 진행한다면 전역에 패키지를 설치해도 무방하지만 프로젝트별로 사용하는 패키지 버전이나 종류가 달라지는 경우가 흔합니다.
각 프로젝트 별 가상환경을 생성하여 프로젝트별 불필요한 패키지가 설치 되지 않도록 합니다.</p>
<p><strong>가상 환경을 생성하는 base python은 프로젝트별로 버전이 같아야 하므로 명시해주는 것이 좋습니다.</strong></p>
<h2 id="가상환경-생성">가상환경 생성</h2>
<blockquote>
<p>python3 -m venv &lt;가상환경 이름&gt;</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/j-_-/post/acfc1d5a-cc82-45c7-9309-0302bb3d6cf9/image.png" alt=""></p>
<p>저는 맥OS를 사용중이라 python2, python3가 기본적으로 모두 설치되어 있어서 python3로 입력하였습니다.
생성되는 가상환경은 운영체제 별로 달라서 window에서 생성한 가상환경이 mac에서 호환되지 않는 경우도 있습니다.</p>
<h2 id="가상환경-실행">가상환경 실행</h2>
<p><strong>*Mac</strong></p>
<blockquote>
<p>source ./&lt;가상환경 이름&gt;/bin/activate </p>
</blockquote>
<p><strong>*Window</strong></p>
<blockquote>
<p>./&lt;가상환경 이름&gt;/Scripts/activate.bat</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/j-_-/post/c2868a4b-a28a-4b25-8f9b-4d9dbf544e3d/image.png" alt=""></p>
<p>가상환경이 실행되면 프롬프트 앞쪽에 (가상환경 이름)이 붙게됩니다.</p>
<h2 id="django-설치">django 설치</h2>
<blockquote>
<p>pip install django
pip list</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/j-_-/post/e4b5c608-8cfc-49e3-965d-306e8752ce15/image.png" alt=""></p>
<h3 id="전역에-설치된-패키지들">전역에 설치된 패키지들</h3>
<p><img src="https://velog.velcdn.com/images/j-_-/post/dab22f38-9890-4f1f-866a-8a5e3f68f714/image.png" alt=""></p>
<h2 id="설치된-패키지-목록-관리하기">설치된 패키지 목록 관리하기</h2>
<p>git이나 svn에서 코드를 관리할 때 바이너리 모듈을 저장하지 않고 spring에선 pom.xml, JS -&gt; package.json처럼 해당 프로젝트에 필요한 라이브러리들에 대한 정보만 관리합니다.</p>
<p>python은 보편적으로 pip freeze명령을 통해 출력된 목록을 사용합니다.</p>
<blockquote>
<p>pip freeze &gt; requirements.txt</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/j-_-/post/46858b2b-1c7d-42bd-8568-21c2be79b717/image.png" alt=""></p>
<p>저장된 requirements.txt 파일을 통해 다시 패키지를 설치할 수 있습니다.</p>
<blockquote>
<p>pip uninstall django
pip install -r requirements.txt</p>
</blockquote>
<p>-r 옵션은 requirements 파일을 활용하여 패키지를 다운로드 하는 옵션입니다.</p>
<p><img src="https://velog.velcdn.com/images/j-_-/post/c373c0da-e658-4bfa-8e4a-cef3460bc0ad/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <link>https://velog.io/@j-_-/tjsody1w</link>
            <guid>https://velog.io/@j-_-/tjsody1w</guid>
            <pubDate>Mon, 18 Apr 2022 14:10:53 GMT</pubDate>
            <description><![CDATA[<h1 id="민첩한-개발을-위한-django-마이그레이션-전략">민첩한 개발을 위한 Django 마이그레이션 전략</h1>
<p><img src="https://velog.velcdn.com/images/j-_-/post/c1bc1862-e492-46c9-97ef-3b9e2305d7a5/image.jpg" alt="">
<img src="https://velog.velcdn.com/images/j-_-/post/72c4d654-81ea-4988-9658-6550c3a0c379/image.jpg" alt=""></p>
<h2 id="진행-배경">진행 배경</h2>
<p>기존에 스프링 + mybatis 조합으로 웹 개발을 배운 상태로 새롭게 진행하는 프로젝트에서는 장고를 사용해야 했습니다. 장고의 orm과 마이그레이션 기능은 넘어야 할 산으로 다가왔습니다. 아직 JPA를 접하지 못한 상황에서 django ORM을 먼저 접했기 때문에 빠른 개발을 위해 복잡한 마이그레이션을 포기하고 설계 시 몇 가지 선택을 했습니다.</p>
<p>기존에 개발을 진행했던 단계는 <strong>요구사항 분석 -&gt; 데이터베이스 설계 -&gt; 코드개발 -&gt; 테스트 -&gt; 배포</strong> 순으로 진행 하였는데  django를 처음보고 느낀 것은 <strong>코드개발 -&gt; 데이터 베이스 설계</strong>로 기존 개발 스텝이 꼬이는 느낌을 받았습니다.</p>
<p>아직 기존 개발단계를 버리지 못한 단계에서 갑자기 순서를 바꿔 진행 할 수 없었기 때문에 
기존처럼 DB설계 후 개발 하는 순서로 진행하였습니다.</p>
<h2 id="마이그레이션migration이란">마이그레이션(Migration)이란?</h2>
<p>장고는 migrate 명령을 통해 app 안의 모델들을 자동으로 데이터베이스 스키마를 생성 혹은 관리 해줍니다.</p>
<p>단독으로 개발을 할 경우에 마이그레이션을 이용하여 개발을 진행하면 보다 빠르고 편하게 개발을 진행할 수 있지만 여러명이 하나의 데이터베이스를 바라보고 개발을 진행 할 경우 종종 마이그레이션이 꼬이거나 다른 사람이 수정한 마이그레이션 때문에 프로젝트가 실행이 되지 않는 경우가 발생하기도 합니다.</p>
<p>기존 스프링으로 웹 개발을 진행하고 장고에 익숙치 않은 상태에서 빠른 개발과 꼬임 방지를 위해 몇 가지 전략적 선택을 하였고 이 경험을 공유하고자 합니다.</p>
<h2 id="마이그레이션을-포기하고-선택한-것">마이그레이션을 포기하고 선택한 것</h2>
<h3 id="초기-migration-최초-1회">초기 migration (최초 1회)</h3>
<blockquote>
<p>python manage.py migrate</p>
</blockquote>
<p>장고에선 필수적으로 생성 되어야하는 테이블이 존재합니다. 최초 한번은 migration을 진행하여 장고에서 내부적으로 사용하는 테이블을 생성시킬 필요성이 있습니다.</p>
<h3 id="inspectedb-활용">inspectedb 활용</h3>
<blockquote>
<p>python manage.py inspectie &gt; models.py</p>
</blockquote>
<p>장고에는 <strong>inspectdb</strong>라는 기능이 있습니다. <strong>기존 단계대로 모든 DB설계를 마친 후 데이터 베이스를 생성</strong>하고 inspectdb 명령으로 연결된 데이터베이스의 모든 테이블 정보를 기준으로 생성된 모델 class들이 자동으로 생성됩니다.
생성된 모델을 VO처럼 사용하여 개발을 진행합니다.</p>
<p><strong>*마이그레이션을 하지 않아도 해당 모델로 db에 접근하는 것이 가능합니다.</strong></p>
<h3 id="git-커밋">git 커밋</h3>
<p>마이그레이션을 진행하고 나면 app폴더 하위에 migrations폴더가 생성됩니다.
해당 폴더를 git으로 관리하지 않도록 하여 다른 사람이 영향을 받지 않도록 합니다.</p>
<h2 id="장고-마이그레이션을-보고-느낀-점">장고 마이그레이션을 보고 느낀 점</h2>
<p>기존 설계방식은 데이터베이스가 1순위로 설계되는 느낌이었는데 Django ORM에서는 데이터베이스보다 WAS의 기능에 중심을 맞춰서 설계가 되는 느낌이였습니다. 막상 개발을 진행하며 여러 라이브러리들을 보니 Model 자체도 순수 VO처럼 사용되는 것이 아니라 각자 객체로써 역할을 수행하는 것 같았습니다. 처음 설계 시 조금 더 경험이 있었다면 보다 django의 패러다임에 맞춘 개발을 진행 할 수 있지 않았을까 생각됩니다.</p>
]]></description>
        </item>
    </channel>
</rss>