<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>성장하는 개발자</title>
    <link>https://khsung0.tistory.com/</link>
    <description>웹 개발자로 취업하여 경험하고 공부한 내용들을 정리할 블로그입니다.
부족한 부분은 날카롭게 지적해주시면 감사하겠습니다!!</description>
    <language>ko</language>
    <pubDate>Wed, 15 Apr 2026 01:05:38 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>코딩독학하기</managingEditor>
    <image>
      <title>성장하는 개발자</title>
      <url>https://tistory1.daumcdn.net/tistory/5058731/attach/75ed0e6e090c49b1866d5924092b6ded</url>
      <link>https://khsung0.tistory.com</link>
    </image>
    <item>
      <title>[BOJ] Python 백준 2447번 별 찍기-10 골드5</title>
      <link>https://khsung0.tistory.com/85</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://www.acmicpc.net/problem/2447&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/2447&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;문제 풀이&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해당 문제는 처음 반복문을 접할 때 풀어보는 별 찍기의 재귀버전이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3X3 크기의 한 패턴이 정해져 있고 크기가 증가할수록 같은 패턴이 반복되는 형태인데 처음엔 직관적으로 간단하게 생각해서 9 부분으로 나눠 각 Position에 대해 번호를 파라미터로 넘기고 해당 Position에 따라 별, 공백, 별 줄 바꿈 출력을 생각했으나 뜻대로 되지 않았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3X3 패턴이 출력되는 만큼 줄 바꿈도 같이 출력이 되었고 일정한 패턴의 확장이 아니라 그냥 패턴의 연속된 출력이었기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 접근 방식을 다시 생각해봤다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일단 3X3 패턴을 하나의 원소로 가정하고 3배씩 증가할 때마다 행과 열을 복사하는 방식이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;화면 캡처 2024-12-22 201214.png&quot; data-origin-width=&quot;430&quot; data-origin-height=&quot;123&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRW6S6/btsLrN2d0yP/LpBpObR0btrcf5gkCJlULK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRW6S6/btsLrN2d0yP/LpBpObR0btrcf5gkCJlULK/img.png&quot; data-alt=&quot;패턴 복사 방법&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRW6S6/btsLrN2d0yP/LpBpObR0btrcf5gkCJlULK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRW6S6%2FbtsLrN2d0yP%2FLpBpObR0btrcf5gkCJlULK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; alt=&quot;패턴 복사 방법&quot; loading=&quot;lazy&quot; width=&quot;430&quot; height=&quot;123&quot; data-filename=&quot;화면 캡처 2024-12-22 201214.png&quot; data-origin-width=&quot;430&quot; data-origin-height=&quot;123&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;패턴 복사 방법&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위 사진처럼 직전의 패턴에 대해 증가할때마다 행을 3배로 복사하고 1,3번째 행은 열을 3배로, 2번째 행은 패턴의 길이만큼 공백을 넣어주면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파이썬은 리스트나 문자열의 복사가 상당히 쉬운 편이기 때문에 다행인 것 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;직전의 패턴에서 한 줄씩 문자열로 치환을 하면 나머진 구현에 어려움이 있을 것 같진 않다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1734866649787&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;N=int(input())
# 하나의 별표에서 시작한다 가정
res=[&quot;*&quot;]
def func(n):
    global res
    if n&amp;gt;3:
        func(n//3)
    # 행 X3
    res=res*3

    # 열 X3
    for i in range(len(res)//3):
        res[i]=res[i]*3
    # 열 + 공백 + 열
    for i in range(len(res)//3,len(res)*2//3):
        res[i]=res[i]+&quot; &quot;*len(res[i])+res[i]
    # 열 X3
    for i in range(len(res)*2//3,len(res)):
        res[i]=res[i]*3

func(N)
for i in range(len(res)):
    print(res[i])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;재귀를 타면서 문자열 리스트를 공유해야 하기 때문에 결과 리스트를 전역변수로 공유하는 global을 사용했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;필자는 이게 직관적이기에 사용했는데 각자 파라미터로 직접 데이터를 보내는 방식과 비교하여 본인이 편한 방식대로 구현하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문제에서 입력 조건이 3 이상이기 때문에 조건문에 3 초과인 경우 재귀를 타도록 구현하였는데 제출하고 생각해 보니 애초에 res 리스트는 빈 리스트로 초기화하고 n == 1인 경우에 res 리스트를 별표 문자열 하나로 초기화 하는 방식이 다소 깔끔하지 않을까 생각이 든다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;화면 캡처 2024-12-22 201214.png&quot; data-origin-width=&quot;1037&quot; data-origin-height=&quot;71&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bncKzq/btsLsCMDrRu/uR6rtLGLENkBfjMFDdfB5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bncKzq/btsLsCMDrRu/uR6rtLGLENkBfjMFDdfB5k/img.png&quot; data-alt=&quot;결과 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bncKzq/btsLsCMDrRu/uR6rtLGLENkBfjMFDdfB5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbncKzq%2FbtsLsCMDrRu%2FuR6rtLGLENkBfjMFDdfB5k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1037&quot; height=&quot;71&quot; data-filename=&quot;화면 캡처 2024-12-22 201214.png&quot; data-origin-width=&quot;1037&quot; data-origin-height=&quot;71&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;결과 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문제를 맞긴 했지만 처음에 다소 접근 방식에서 헤맸던 문제이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;함수를 실행시켰을 때와 재귀를 타고 다시 실행했을 때의 실행결과를 고려하다 보니 스스로 발목을 잡는 것처럼 복잡하고 헷갈려서 재귀 문제는 최대한 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;같은 부분을 단순화&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시켜서&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;함수 그 자체가 실행하는 과정에 집중&lt;/b&gt;&lt;/span&gt;하는 연습과 경험이 필요한 것 같다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>알고리즘/알고리즘 문제 풀이</category>
      <category>Python</category>
      <category>백준</category>
      <category>알고리즘</category>
      <category>재귀</category>
      <category>파이썬</category>
      <author>코딩독학하기</author>
      <guid isPermaLink="true">https://khsung0.tistory.com/85</guid>
      <comments>https://khsung0.tistory.com/85#entry85comment</comments>
      <pubDate>Sun, 22 Dec 2024 16:47:41 +0900</pubDate>
    </item>
    <item>
      <title>데이터 전처리를 위한 파이썬 Pandas 사용하기</title>
      <link>https://khsung0.tistory.com/84</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 분석을 하기 위해선 수집된 데이터(Raw Data)를 목적에 맞게끔 가공하는 작업이 필요하다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;순금을 뽑기 위해 불순물을 제거하는 것처럼 분석하고자 하는 목적에 맞는 데이터를 추출해야 보다 정확한 분석이 가능하기 때문이다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Raw Data를 분석에 적합한 형태로 가공하는 작업을 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;전처리 작업&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이라고 하는데 이 전처리 작업에 유용한 라이브러리인 Pandas에 대해 데이터 분석과 시각화 관련된 공부를 하는 김에 정리하려고 한다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Pandas란&lt;/span&gt;&lt;/h2&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot;&gt;&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Pandas는 데이터 조작과 분석을 위한 Python의 라이브러리이다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 구조는 Series와 DataFrame으로 구성되어 있다.&lt;/span&gt;&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;시리즈(Series):&lt;/b&gt;&lt;span style=&quot;background-color: #FFFFFF;&quot;&gt; 시리즈는 1차원 배열과 같은 데이터 구조로, 각각의 데이터에 인덱스가 부여되어 있다.&lt;br&gt;예를 들어, 날씨 정보를 담은 시리즈에서는 날짜가 인덱스로 사용되고, 각 날짜에 해당하는 온도가 시리즈의 값으로 들어갈 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;b&gt;데이터프레임(DataFrame):&lt;/b&gt;&lt;span style=&quot;background-color: #FFFFFF;&quot;&gt; 데이터프레임은 연속된 여러 시리즈로 엑셀과 같은 표 형식의 2차원 배열 데이터 구조다.&lt;br&gt;예를 들어, 여러 날짜에 대한 온도, 습도, 강수량 정보를 담은 여러 시리즈를 합쳐서 데이터프레임으로 만들 수 있다.&lt;/span&gt; &lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Pandas를 이용하여 Data를 쉽게 로딩하고 정리, 분석, 시각화할 수 있으며 DB와 유사한 연산을 지원하기 때문에 Data를 편리하게 처리할 수 있다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;따라서 Pandas는 데이터 분석, 머신러닝, 통계 등 다양한 분야에서 사용된다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Pandas 사용하기&lt;/span&gt;&lt;/h2&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot;&gt;&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Pandas를 설치하는 명령어는 다음과 같다.&lt;/span&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;pip install pandas&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;675&quot; data-origin-height=&quot;39&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biyFEv/btsEFcTQpYi/shMLjWkh9cAk4cSKyNQSB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biyFEv/btsEFcTQpYi/shMLjWkh9cAk4cSKyNQSB0/img.png&quot; data-alt=&quot;설치 완료 메시지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biyFEv/btsEFcTQpYi/shMLjWkh9cAk4cSKyNQSB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiyFEv%2FbtsEFcTQpYi%2FshMLjWkh9cAk4cSKyNQSB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; alt=&quot;설치 완료 메시지&quot; loading=&quot;lazy&quot; width=&quot;675&quot; height=&quot;39&quot; data-origin-width=&quot;675&quot; data-origin-height=&quot;39&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;설치 완료 메시지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위 사진처럼 뜬다면 설치가 완료된 것이다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 함수를 사용한 결과를 보면서 어떤 상황엔 어떤 함수를 써야 하는지 알아보자.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 데이터 읽어오기&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;크게 엑셀에서 읽어오거나 직접 데이터를 입력하는 두 가지 방법이 있다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;217&quot; data-origin-height=&quot;112&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMLBvG/btsE8B1DwDH/KCcKrfzgf3QlSrJgcI2UF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMLBvG/btsE8B1DwDH/KCcKrfzgf3QlSrJgcI2UF0/img.png&quot; data-alt=&quot;user_data.xlsx&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMLBvG/btsE8B1DwDH/KCcKrfzgf3QlSrJgcI2UF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMLBvG%2FbtsE8B1DwDH%2FKCcKrfzgf3QlSrJgcI2UF0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; alt=&quot;user_data.xlsx&quot; loading=&quot;lazy&quot; width=&quot;217&quot; height=&quot;112&quot; data-origin-width=&quot;217&quot; data-origin-height=&quot;112&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;user_data.xlsx&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위 사진과 같은 데이터가 있을 때 Pandas에서 사용하는 코드와 출력 결과는 다음과 같다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;import pandas as pd

# 엑셀 파일에서 데이터 읽어오기
excel_file_path = 'user_data.xlsx'

# csv파일일 경우
# df = pd.read_csv(excel_file_path, encoding='utf-8-sig')

# excel파일일 경우
df = pd.read_excel(excel_file_path)

# 읽어온 데이터 출력
print(df)

# 직접 데이터 입력
data = {'이름': ['홍길동', '김철수', '이영희','고길동'],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'나이': [25, 30, 22, None],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'직업': ['학생', None, '디자이너','개발자']}

# 데이터프레임 생성
df = pd.DataFrame(data)

# 생성한 데이터프레임 출력
print(df)

# 데이터 일부 확인
print(&quot;df.head(2)&quot;)
print(df.head(2))
print(&quot;df.tail(1)&quot;)
print(df.tail(1))&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;142&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IaSaV/btsFb84R01F/NmRzZfPBc5UB2TXgX6IjK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IaSaV/btsFb84R01F/NmRzZfPBc5UB2TXgX6IjK1/img.png&quot; data-alt=&quot;전체 데이터, 상단 2행, 하단 1행&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IaSaV/btsFb84R01F/NmRzZfPBc5UB2TXgX6IjK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIaSaV%2FbtsFb84R01F%2FNmRzZfPBc5UB2TXgX6IjK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; alt=&quot;전체 데이터, 상단 2행, 하단 1행&quot; loading=&quot;lazy&quot; width=&quot;677&quot; height=&quot;111&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;142&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;전체 데이터, 상단 2행, 하단 1행&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;출력 결과를 보면 알 수 있듯이 엑셀처럼 2차원 배열 형태를 확인할 수 있고 첫 번째 행이 컬럼 명, 두 번째 행부터는 자동으로 인덱스가 붙어있다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;직접 데이터를 넣을 경우엔 딕셔너리의 키를 컬럼 명으로, 값을 데이터 리스트로 만든 후 DataFrame 함수의 파라미터로 넣으면 된다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;또한 데이터가 많을 경우 전체 출력을 하기 어렵기 때문에 데이터 구조나 예시 데이터를 확인하기 위해 head(), tail() 함수를 사용하면 된다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Default는 5줄이고 파라미터에 넣은 숫자만큼의 행을 가져오기 때문에 SQL의 LIMIT과 같은 기능이다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;print(&quot;컬럼 명&quot;)
print(df.columns)

print(&quot;행, 열 크기&quot;)
print(df.shape)

print(&quot;데이터 정보 확인&quot;)
print(df.info())

print(&quot;요약 통계 확인&quot;)
print(df.describe())&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각각의 출력 결과는 다음과 같다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3SdwX/btsFhqZV033/fLVPZZNkKCiO46U3GOoMB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3SdwX/btsFhqZV033/fLVPZZNkKCiO46U3GOoMB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3SdwX/btsFhqZV033/fLVPZZNkKCiO46U3GOoMB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3SdwX%2FbtsFhqZV033%2FfLVPZZNkKCiO46U3GOoMB1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; alt=&quot;출력 결과&quot; loading=&quot;lazy&quot; width=&quot;850&quot; height=&quot;208&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;158&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컬럼명과 행열의 크기, 데이터들의 대략적인 요약, 숫자 데이터들의 통계를 확인할 수 있다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이를 이용해 행렬의 크기와 non-null의 Count를 비교해서 데이터가 없는(Null 값인) 부분이 있다면 차후에 계측값 제거를 통해 가공해야겠다는 생각을 할 수 있다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Data Frame에서 특정 컬럼을 선택하여 Series를 추출할 수 있는데 컬럼 하나를 추출할 때와 여러 개를 추출할 때의 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;파라미터 값을 잘 확인&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해야 한다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;print(&quot;열 선택&quot;)
selected_column = df['나이']
print(selected_column.head())
print(selected_column.size, selected_column.count())
selected_columns = df[['이름', '나이']]
print(selected_columns.head())
print(selected_columns.size)
print(selected_columns.count())
print(selected_columns.value_counts())&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;189&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QUqcG/btsFmewVY09/v0fcjOP6nPmH1iOBtTiNGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QUqcG/btsFmewVY09/v0fcjOP6nPmH1iOBtTiNGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QUqcG/btsFmewVY09/v0fcjOP6nPmH1iOBtTiNGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQUqcG%2FbtsFmewVY09%2Fv0fcjOP6nPmH1iOBtTiNGk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; alt=&quot;출력 결과&quot; loading=&quot;lazy&quot; width=&quot;702&quot; height=&quot;189&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;189&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단일 컬럼 선택 시 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;문자열 하나&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;만 들어가지만 복수 컬럼 선택 시 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;리스트 형태의 컬럼명&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을 파라미터로 보내며 Count 관련 함수는 Null 값이 들어간 행을 제외하고 세기 때문에 Law Data에서 자신에게 필요한 데이터만 추출하면 유용하게 사용할 수 있다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;print('조건식을 이용한 열 선택')
selected_column = df[df['이름'] == &quot;홍길동&quot;]
print(selected_column.head())&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;167&quot; data-origin-height=&quot;53&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Vd66W/btsFg5IuesO/koPCuqFklbmizKCl4XMT01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Vd66W/btsFg5IuesO/koPCuqFklbmizKCl4XMT01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Vd66W/btsFg5IuesO/koPCuqFklbmizKCl4XMT01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVd66W%2FbtsFg5IuesO%2FkoPCuqFklbmizKCl4XMT01%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; alt=&quot;출력 결과&quot; loading=&quot;lazy&quot; width=&quot;217&quot; height=&quot;69&quot; data-origin-width=&quot;167&quot; data-origin-height=&quot;53&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특히 특정 조건에 해당하는 데이터를 추출하려면 컬럼 선택 값으로 추출하고자 하는 조건식을 사용하면 된다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이를 이용하면 특정 나이대, 특정 지역에 해당하는 데이터를 추출할 수 있다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;print(&quot;Null 값이 있는 데이터 갯수&quot;)
print(df.isnull().sum())
print(&quot;Null값을 제거한 데이터&quot;)
print(df.dropna())
print(&quot;직업의 Null값을 제거한 데이터&quot;)
print(df.dropna(subset=['직업']))&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;139&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N16jI/btsFm1qz52G/FOI3tuMemT4kRFajonL5h0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N16jI/btsFm1qz52G/FOI3tuMemT4kRFajonL5h0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N16jI/btsFm1qz52G/FOI3tuMemT4kRFajonL5h0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN16jI%2FbtsFm1qz52G%2FFOI3tuMemT4kRFajonL5h0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; alt=&quot;출력 결과&quot; loading=&quot;lazy&quot; width=&quot;865&quot; height=&quot;139&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;139&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;isnull() 함수는 데이터가 Null인 경우 True를 반환하는데 Sum()을 통해 합계를 구함으로써 Null값을 카운트하는 효과를 낼 수 있다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;또한 dropna()는 데이터가 Null인 행을 제거한 데이터를 반환하며 파라미터로 특정 컬럼의 Null 값만 제거할 수 있기 때문에 항상 Law Data를 다루기 전 dropna()를 사용하여 빈 값이 있으면 안 되는 컬럼의 데이터를 제거하는 게 좋을 것 같다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;print(&quot;Null값 채우기&quot;)
print(df.fillna({'나이' : 0 , '직업' : '없음'}))&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;182&quot; data-origin-height=&quot;104&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/chkEe2/btsFgqe43y2/knV573khrbBHL7JsZymmkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/chkEe2/btsFgqe43y2/knV573khrbBHL7JsZymmkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/chkEe2/btsFgqe43y2/knV573khrbBHL7JsZymmkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FchkEe2%2FbtsFgqe43y2%2FknV573khrbBHL7JsZymmkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; alt=&quot;출력 결과&quot; loading=&quot;lazy&quot; width=&quot;222&quot; height=&quot;127&quot; data-origin-width=&quot;182&quot; data-origin-height=&quot;104&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;반대로 Null 값을 일괄적으로 채워야 할 때가 있는데 fillna() 함수를 사용하면 된다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;한 가지 값으로 채울 수 있다면 해당 값만 파라미터로 보내면 되지만 컬럼마다 초기화해야 하는 값이 다르다면 딕셔너리 형태로 Key는 컬럼명, Value는 Data 값으로 설정하면 위 사진처럼 채워진다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>취업 후 학습</category>
      <category>pandas</category>
      <category>Python</category>
      <category>데이터</category>
      <category>파이썬</category>
      <author>코딩독학하기</author>
      <guid isPermaLink="true">https://khsung0.tistory.com/84</guid>
      <comments>https://khsung0.tistory.com/84#entry84comment</comments>
      <pubDate>Thu, 8 Feb 2024 11:51:32 +0900</pubDate>
    </item>
    <item>
      <title>MSSQL 테이블 변수, 임시 테이블 사용하기</title>
      <link>https://khsung0.tistory.com/83</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실무에서 파트너사 알림톡 발송을 위해 대량의 데이터를 반복 Insert 할 일이 생겼는데 초기에 생각보다 시간이 너무 오래 걸려 효율적인 방법을 찾던 중 테이블 변수와 임시 테이블에 대해 알게 되어 정리할 겸 작성하기로 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Join으로 조회한 데이터들을 While문을 통해 Row 접근으로 Update, Insert를 반복하는 작업인데 &lt;span style=&quot;text-align: start;&quot;&gt; 테이블 변수와 임시 테이블을&amp;nbsp;모르고 비효율적인 쿼리로 실행했을 땐&amp;nbsp;&lt;/span&gt;필요한 Data를 While문 안에서 계속 Join 하며 Select 했더니 아래 표처럼 기하급수적으로 시간이 늘어났다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 63.7209%; height: 221px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignCenter&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;발송 Data Row 수&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;톡 발송 완료시간&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;50개&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;18초&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;100개&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1분 10초&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;200개&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4분 10초&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;300개&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;9분 20초&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;600개&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;37분 40초&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시작한 직후엔 1초당 3개씩 발송하더니 시간이 갈수록 1초에 1개, 2초에 1개.... 이런 식으로 점점 딜레이가 됐었다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;운영계 DB에 불필요한 테이블을 만들지 않으려다 보니 이러한 결과가 나왔는데 테이블 변수나 임시 테이블을 사용하니 시간은 획기적으로 줄어들었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여담이지만 필요한 데이터를 파이썬으로 생성했더니 참 편한 것 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;테이블 변수&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;테이블 변수는 조회한 테이블 형태의 값들을 변수에 저장하는 것을 뜻한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;변수이기 때문에 일반 변수와 동일하게 DECLARE로 &quot;@&quot;를 붙여 선언하고 메모리에 생성되기 때문에 쿼리가 실행되는 함수, 프로시저 안에서만 일시적으로 유효하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1701675387314&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;-- 테이블 변수 선언
DECLARE @TEMP_TABLE_NAME TABLE(
    -- 컬럼 선언
    COL1 VARCHAR(10),
    COL2 INT
)

-- 기존 테이블 전체 테이블 변수로 복사
INSERT INTO @TEMP_TABLE_NAME
SELECT * FROM ORIGIN_TABLE;

-- Join한 결과에서 특정 컬럼만 테이블 변수로 복사
INSERT INTO @TEMP_TABLE_NAME
SELECT A.COL1, A.COL2, B.COL1, B.COL2 FROM ORIGIN_TABLE_1 AS A
INNER JOIN ORIGIN_TABLE_2 AS B
ON A.COL1 = B.COL1;

-- 조회 예시
SELECT * FROM @TEMP_TABLE_NAME;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;장점&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt; 임시 테이블보다 빠르게 작동하며, 디스크 I/O를 줄일 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt; &lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;트랜잭션 로그에 기록되지 않으므로 롤백이 필요하지 않다.&lt;/span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt; &lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;저장 프로시저, 함수, 트리거 등에서 사용할 수 있다.&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt; &lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;컴파일 시점에 결정되므로, 재컴파일을 유발하지 않는다.&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #374151;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;단점&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt; 통계를 생성하지 않아, 쿼리 최적화에 영향을 줄 수 있다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt; &lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;인덱스를 생성할 수 없으므로, 대량의 데이터를 처리하는 데는 부적합하다. (100건 이상의 데이터 사용 시 성능 저하)&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt; &lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;세션 간에 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;공유할 수 없다.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt; &lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;ALTER TABLE 명령을 사용하여 구조를 변경할 수 없다.&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;임시 테이블&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;임시 테이블은 일시적으로 데이터를 저장하고 조작하는 데 사용하는 테이블이며 시스템 DB인 tempdb에 저장된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;테이블이기 때문에 CREATE을 사용하고 &quot;#&quot;을 붙여 임시 테이블을 선언한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이때 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&quot;#&quot;&lt;/b&gt;&lt;/span&gt;은 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;지역 임시 테이블&lt;/b&gt;&lt;/span&gt;을 뜻하고 테이블 변수와는 다르게 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&quot;##&quot;&lt;/b&gt;&lt;/span&gt;을 통한 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;전역 임시 테이블&lt;/b&gt;&lt;/span&gt; 선언이 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;즉, 전역 선언을 통해 사용자 본인의 다른 Session에서도 접근이 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;명시적으로 삭제하지 않더라도 DB와 연결된 Session이 종료되면 자동으로 삭제되며 전역 임시 테이블의 경우 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;마지막 Session이 종료&lt;/b&gt;&lt;/span&gt;되면 삭제되기 때문에 실무에서 테이블 조작하기 편하게 해주는 것 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주로 복잡한 쿼리를 단순화하거나 중간 결과를 저장하고 여러 프로시저에서 결과를 공유하는 용도로 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1701677126443&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;-- 지역 임시 테이블 선언 ('#' 한 개)
CREATE TABLE #TEMP_TABLE_NAME (
    -- 컬럼 선언
    COL1 VARCHAR(10),
    COL2 INT
)

-- 전역 임시 테이블 선언 ('#' 두 개)
CREATE TABLE ##TEMP_TABLE_NAME (
    -- 컬럼 선언
    COL1 VARCHAR(10),
    COL2 INT
)
-- 기존 테이블 전체 테이블 변수로 복사
INSERT INTO #TEMP_TABLE_NAME
SELECT * FROM ORIGIN_TABLE;

-- Join한 결과에서 특정 컬럼만 테이블 변수로 복사
INSERT INTO #TEMP_TABLE_NAME
SELECT A.COL1, A.COL2, B.COL1, B.COL2 FROM ORIGIN_TABLE_1 AS A
INNER JOIN ORIGIN_TABLE_2 AS B
ON A.COL1 = B.COL1;

-- 조회 예시
SELECT * FROM #TEMP_TABLE_NAME;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;장점&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt; 복잡한 쿼리를 단순화하고, 중간 결과를 저장하여 데이터 처리를 더 효율적으로 만들 수 있다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt; 큰 데이터 세트를 작은 부분으로 분할하여 처리하면 성능이 향상될 수 있다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt; 쿼리의 중간 결과를 확인하고 문제를 디버깅하는 데 도움이 된다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt; 사용자 세션별로 생성되므로 다른 사용자가 접근할 수 없어 보안에 좋다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;단점&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt; 트랜잭션 로그에 기록되므로, 많은 양의 데이터를 처리하면 로그 크기가 커질 수 있다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt; &lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;디스크 I/O 작업에 대한 &lt;/span&gt;Overhead가 존재한다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #374151;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;저장 프로시저 내부에서 실행할 때마다 재 컴파일이 발생한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #374151;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;적은 데이터(100건 이하)는 테이블 변수가 더 빠를 수 있지만 많은 데이터(100건 이상)는 임시 테이블이 성능적으로 유리하다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #374151;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;필자는 애초에 비효율적인 쿼리였기 때문에 저장 프로시저 수정, 임시 테이블 적용, Update 필요 없는 행 로직 수행 제외 등 여러 차례에 걸쳐 튜닝한 결과 상당한 시간 단축을 이루었다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #374151;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;다음은 데이터 1000건 기준의 테이블 변수와 임시 테이블 적용 후 알림톡 발송 실행 시간이다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1.png&quot; data-origin-width=&quot;389&quot; data-origin-height=&quot;45&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/txTqU/btsBof1g4GY/buZeFgEoDe15xl0D5FgRWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/txTqU/btsBof1g4GY/buZeFgEoDe15xl0D5FgRWk/img.png&quot; data-alt=&quot;테이블 변수 실행 시간 (24초)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/txTqU/btsBof1g4GY/buZeFgEoDe15xl0D5FgRWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtxTqU%2FbtsBof1g4GY%2FbuZeFgEoDe15xl0D5FgRWk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; alt=&quot;테이블 변수 실행 시간&quot; loading=&quot;lazy&quot; width=&quot;424&quot; height=&quot;49&quot; data-filename=&quot;1.png&quot; data-origin-width=&quot;389&quot; data-origin-height=&quot;45&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;테이블 변수 실행 시간 (24초)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2.png&quot; data-origin-width=&quot;386&quot; data-origin-height=&quot;41&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXmntH/btsBl7oUmfb/bsAgOZ9ark0kJY9bY72w11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXmntH/btsBl7oUmfb/bsAgOZ9ark0kJY9bY72w11/img.png&quot; data-alt=&quot;임시 테이블 실행 시간 (18초)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXmntH/btsBl7oUmfb/bsAgOZ9ark0kJY9bY72w11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXmntH%2FbtsBl7oUmfb%2FbsAgOZ9ark0kJY9bY72w11%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; alt=&quot;임시 테이블 실행 시간&quot; loading=&quot;lazy&quot; width=&quot;425&quot; height=&quot;45&quot; data-filename=&quot;2.png&quot; data-origin-width=&quot;386&quot; data-origin-height=&quot;41&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;임시 테이블 실행 시간 (18초)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단일 Insert로는 최대 1000행이 가능하기 때문에 1000행을 기준으로 잡았으며 임시 테이블이 테이블 변수보다 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;25%가량 시간 단축&lt;/b&gt;&lt;/span&gt; 된 것을 확인할 수 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여태까진 쿼리에 대한 큰 고민을 하지 않은 것 같아 이번 경험을 계기로 끊임없이 고민하고 개선시키려 노력해야겠다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>취업 후 학습</category>
      <category>db</category>
      <category>MSSQL</category>
      <author>코딩독학하기</author>
      <guid isPermaLink="true">https://khsung0.tistory.com/83</guid>
      <comments>https://khsung0.tistory.com/83#entry83comment</comments>
      <pubDate>Mon, 4 Dec 2023 17:49:36 +0900</pubDate>
    </item>
    <item>
      <title>[PDF 전자책] 파이썬을 이용한  업무 자동화 프로그램 만들기</title>
      <link>https://khsung0.tistory.com/82</link>
      <description>&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;488&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dW5Mlo/btsr4KDXBoO/DPHrR34f175b82XzvFCV30/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dW5Mlo/btsr4KDXBoO/DPHrR34f175b82XzvFCV30/img.jpg&quot; data-alt=&quot;Thumbnail&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dW5Mlo/btsr4KDXBoO/DPHrR34f175b82XzvFCV30/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdW5Mlo%2Fbtsr4KDXBoO%2FDPHrR34f175b82XzvFCV30%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; alt=&quot;파이썬을 이용한 업무 자동화&quot; loading=&quot;lazy&quot; width=&quot;652&quot; height=&quot;488&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;488&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Thumbnail&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot; style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일을 하다 보면 생각보다 자주 단순 반복작업을 하게 되는 경우가 있습니다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;때에 따라서 많은 데이터를 수집해야 할 수도 있고 주기적으로 메일을 보낸다거나 엑셀 파일의 수많은 데이터를 수정해야 할 수도 있습니다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사람이 동시에 할 수 있는 일의 양과 그에 따른 시간은 한정적이기 때문에 단순 반복 작업을 자동화시킨다면 그만큼 낭비되는 시간을 아껴 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;업무 효율화&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 추구할 수 있습니다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마치 공장에서 일련의 프로세스들을 자동화 기계를 통해 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;비용과 시간 대비 생산량을 극대화&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시키듯&lt;b&gt;,&lt;/b&gt; &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;정해진 패턴&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 있고 비교적 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;많은 시간을 요구&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하는 작업이라면 컴퓨터를 통해 빠르고 효과적으로 처리할 수 있습니다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;물론 기본적으로 특정 기능을 하는 프로그램이 아니라 직접 프로그래밍을 통해 자신이 원하는 기능을 구현하는 것이기 때문에 Python 혹은 최소한 하나의 프로그래밍 언어에 익숙하고 자신의 생각을 코드로 나타낼 수 있는 역량이 필요합니다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;만약 코드를 직접 구현할 자신이 없다면 언어와 관련된 학습은 구글링을 통해 쉽게 집약된 자료를 찾을 수 있고 자신의 생각을 코드로 나타내는 부분은 알고리즘 연습을 통해 충분히 독학 가능하다고 생각합니다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;u&gt;&lt;span style=&quot;color: #006DD7;&quot;&gt;https://kmong.com/knowhow/gig/290286&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;전문가가 필요한 순간, 프리랜서 마켓 No.1 크몽&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;마케팅·디자인·IT프로그래밍·영상 등 다양한 비즈니스 분야의 전문가를 만나보세요!&quot; data-og-host=&quot;kmong.com&quot; data-og-source-url=&quot;https://kmong.com/knowhow/gig/290286&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cgpR7Y/hyTPDhvajE/mXKf3eGaSPysIJyrb4MVC0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ezM76r/hyTMfo21yj/BpyptRRL0HxQUYkD7vXr70/img.png?width=652&amp;amp;height=929&amp;amp;face=0_0_652_929,https://scrap.kakaocdn.net/dn/b35X7p/hyTPzMVN8d/p6XKc6QGnlCm2a1x6Wvlzk/img.png?width=652&amp;amp;height=929&amp;amp;face=0_0_652_929&quot; data-og-url=&quot;https://kmong.com/knowhow/gig/290286&quot;&gt;&lt;a href=&quot;https://kmong.com/knowhow/gig/290286&quot; target=&quot;_blank&quot; data-source-url=&quot;https://kmong.com/knowhow/gig/290286&quot;&gt;&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cgpR7Y/hyTPDhvajE/mXKf3eGaSPysIJyrb4MVC0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ezM76r/hyTMfo21yj/BpyptRRL0HxQUYkD7vXr70/img.png?width=652&amp;amp;height=929&amp;amp;face=0_0_652_929,https://scrap.kakaocdn.net/dn/b35X7p/hyTPzMVN8d/p6XKc6QGnlCm2a1x6Wvlzk/img.png?width=652&amp;amp;height=929&amp;amp;face=0_0_652_929')&quot;&gt; &lt;/div&gt;&lt;div class=&quot;og-text&quot;&gt;&lt;p class=&quot;og-title&quot;&gt;전문가가 필요한 순간, 프리랜서 마켓 No.1 크몽&lt;/p&gt;&lt;p class=&quot;og-desc&quot;&gt;마케팅·디자인·IT프로그래밍·영상 등 다양한 비즈니스 분야의 전문가를 만나보세요!&lt;/p&gt;&lt;p class=&quot;og-host&quot;&gt;kmong.com&lt;/p&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;&lt;p data-ke-size=&quot;size18&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;알고리즘 같은 경우, 집약된 자료를 찾기 힘들어 정리할 겸 과외 경험을 살려 최대한 이해하기 쉽게 작성했으며 반응도 좋았기에 충분히 도움 될 것이라 생각합니다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자동화 프로그램을 작성하는데 자신의 상황에 맞게 로직을 구성하고 해당 논리를 그대로 코드로 구현할 수준이면 되기 때문에 굳이 어려운 알고리즘을 학습할 필요가 없어 부담 갖지 않으셔도 됩니다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이를 통해 기본적인 프로그래밍에 대한 역량을 갖췄다면 이젠 실 생활에 적용하여 소위 말하는 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;&quot;일잘러&quot;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로 거듭나는 일만 남았습니다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제로 저도 취준생 때 재밌을 것 같아 직접 구현해 보고 이를 프로젝트에 적용하여 팀원들에게 좋은 평가를 받았었고 면접에서도 강점으로 어필하였으며 실무에서도 효율적인 업무가 가능했습니다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;또한 전자책을 완성한 직후 평가를 위해 지인과 직장 선배들에게 공유했었는데 일관되게 긍정적인 피드백을 받았습니다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아무래도 소비자분들께 판매를 하는 전자책이기 때문에 저 스스로가 완벽하다고 생각하지 않으면 서비스를 올려두지 않습니다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;관심 있으신 분들은 아래 링크를 통해 어떤 내용들이 있는지 확인해 보고 고민해 보시는 것을 추천드립니다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;u&gt;&lt;span style=&quot;color: #006DD7;&quot;&gt;https://kmong.com/knowhow/gig/490311&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;전문가가 필요한 순간, 프리랜서 마켓 No.1 크몽&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;마케팅·디자인·IT프로그래밍·영상 등 다양한 비즈니스 분야의 전문가를 만나보세요!&quot; data-og-host=&quot;kmong.com&quot; data-og-source-url=&quot;https://kmong.com/knowhow/gig/490311&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/burBLG/hyTIPYea64/eGDG0221nj2Hw3hmECK60k/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/gVPyO/hyTMaGnVRe/50I8iDjlHIlBkyJPi8heL1/img.jpg?width=652&amp;amp;height=488&amp;amp;face=0_0_652_488,https://scrap.kakaocdn.net/dn/btnUBg/hyTL4sDncp/MTyo6yvU8Ee7Z2UGTNzJvk/img.jpg?width=652&amp;amp;height=488&amp;amp;face=0_0_652_488&quot; data-og-url=&quot;https://kmong.com/knowhow/gig/490311&quot;&gt;&lt;a href=&quot;https://kmong.com/knowhow/gig/490311&quot; target=&quot;_blank&quot; data-source-url=&quot;https://kmong.com/knowhow/gig/490311&quot;&gt;&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/burBLG/hyTIPYea64/eGDG0221nj2Hw3hmECK60k/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/gVPyO/hyTMaGnVRe/50I8iDjlHIlBkyJPi8heL1/img.jpg?width=652&amp;amp;height=488&amp;amp;face=0_0_652_488,https://scrap.kakaocdn.net/dn/btnUBg/hyTL4sDncp/MTyo6yvU8Ee7Z2UGTNzJvk/img.jpg?width=652&amp;amp;height=488&amp;amp;face=0_0_652_488')&quot;&gt; &lt;/div&gt;&lt;div class=&quot;og-text&quot;&gt;&lt;p class=&quot;og-title&quot;&gt;전문가가 필요한 순간, 프리랜서 마켓 No.1 크몽&lt;/p&gt;&lt;p class=&quot;og-desc&quot;&gt;마케팅·디자인·IT프로그래밍·영상 등 다양한 비즈니스 분야의 전문가를 만나보세요!&lt;/p&gt;&lt;p class=&quot;og-host&quot;&gt;kmong.com&lt;/p&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;&lt;p data-ke-size=&quot;size18&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;만약 구매하신 분들 중에서 날카로운 피드백을 크몽을 통해서나 블로그 댓글로 남겨주신다면 적극 수용, 반영하고 수정된 내용들을 다시 드리도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>알고리즘/자료구조 알고리즘 강의</category>
      <category>Python</category>
      <category>업무</category>
      <category>자동화</category>
      <category>전자책</category>
      <category>파이썬</category>
      <category>프로그램</category>
      <author>코딩독학하기</author>
      <guid isPermaLink="true">https://khsung0.tistory.com/82</guid>
      <comments>https://khsung0.tistory.com/82#entry82comment</comments>
      <pubDate>Fri, 25 Aug 2023 11:45:08 +0900</pubDate>
    </item>
    <item>
      <title>스프링 Annotation(어노테이션) 정리</title>
      <link>https://khsung0.tistory.com/81</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;업무를 하면서 다양하고 많은 Annotation에 대한 이해가 부족해 정리하고자 작성하기로 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Lombok Annotation&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Setter&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Class의 모든 필드에 해당하는 Setter 메서드 생성&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Getter&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Class의 모든 필드에 해당하는 Getter 메서드 생성&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@ToString&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Class의 모든 필드에 해당하는 ToString 메서드 생성&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@NoArgsConstructor&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Class의 기본 생성자 추가&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@RequiredArgsConstructor&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Final이나 @NonNull인 필드만 파라미터로 받는 생성자 추가&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@AllArgsConstructor&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Class의 모든 필드 값을 파라미터로 받는 생성자 추가&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@EqualsAndHashCode&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Equals와 HashCode 메서드를 오버라이딩 하는 어노테이션&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Data&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Setter, @Getter, @ToString, @NoArgsConstructor 등 Lombok에서 제공하는 필드와 관련된 모든 코드 추가 (모든 기능 사용 가능하므로 Risk 존재해서 사용하지 않는 게 좋음)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;JPA Annotation&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Entity&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 DB 테이블과 매핑될 Class&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Table(name = &quot;&quot;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 DB의 name에 해당하는 테이블과 매핑(생략할 경우 Class명과 테이블명 매핑)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Id&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해당 테이블의 PK 필드&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Column(name = &quot;&quot;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;name에 해당하는 컬럼과 매핑(생략할 경우 필드명과 컬럼명 매핑)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spring Annotation&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Controller&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해당 Class는 Controller란 것을 명시하고 Spring에서 Bean으로 등록 (&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Bean&lt;/b&gt;&lt;/span&gt;이란 Spring에서 관리하는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;자바 객체&lt;/b&gt;&lt;/span&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Service&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해당 Class는 비즈니스 로직을 수행하는 Service란 것을 명시하고 Spring에서 Bean으로 등록&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Repository&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해당 Class는 DAO인 것을 명시하고 Spring에서 Bean으로 등록 (Spring에서 지원하지 않는 Exception을 Spring Exception으로 전환)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Component&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해당 Class는 Component란 것을 명시하고 Spring에서 Bean으로 등록 (@Controller, @Service, @Repository의 상위 어노테이션이므로 3가지 전부 @Component으로 대체 가능)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Bean&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;개발자가 제어 불가능한 외부 라이브러리 등을 Bean으로 등록&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@ComponentScan&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Component, @Controller, @Service, @Repository 가 부여된 Class 들을 검색해서 Bean으로 등록&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@RequestMapping(value = &quot;&quot;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;URI의 요청이 value와 일치할 경우 해당 클래스나 메서드 실행&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@RequestParam(value = &quot;&quot;, required = false)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메서드 파라미터 앞에 쓰며 Http 요청의 파라미터 값(value)을 메서드 파라미터로 받음&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;required 옵션의 Default는 true이며 true일 경우 해당 파라미터가 없을 때 400 에러 발생&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@RequestBody&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메서드 파라미터 앞에 쓰며 Http 요청의 Body를 자바 객체로 변환해서 매핑된 메서드 파라미터로 전달&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@RequestHeader(value = &quot;&quot;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메서드 파라미터 앞에 쓰며 Request의 Header값을 메서드의 파라미터로 받는 어노테이션&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@ResponseBody&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자바 객체를 Http 요청의 Body로 변환(content-type을 application/json으로 설정 필요)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@RestController&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Controller와 @ResponseBody를 합친 어노테이션&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@ModelAttribute&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;View단에서 전달하는 파라미터를 메서드의 파라미터로 변환해 주는 어노테이션(태그의 name과 클래스의 멤버 변수명, Set 메서드명 일치)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 Get, Post, Put, Delete, Patch 요청에 대한 Annotation&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Valid&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파라미터 객체 앞에 쓰며 유효한 객체인지 검사&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@CookieValue(value = &quot;&quot;, required = false)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;쿠키의 value 값을 받아오며 required의 Default는 true&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;required = false를 사용하지 않은 상태에서 해당 쿠키값이 존재하지 않다면 500 에러를 발생시키고 사용하면 존재하지 않을 때 null로 받음&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Lazy&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Class가 실제 사용될 때 Spring에서 Bean등록을 하게 되는 지연 로딩&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Autowired&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Field, Setter, Constructor 3가지에 사용하며 Type에 따라 Bean을 주입&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Qualifier(&quot;id&quot;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Autowired와 같이 쓰며 같은 타입의 Bean 객체가 있을 경우 명시된 ID로 원하는 Bean을 주입하는 어노테이션&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@PathVariable&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메서드 파라미터 앞에 쓰며 URI에서 특정 값을 메서드 파라미터로 받아오는 어노테이션&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특정 값은 URI에서 {}로 감싸고 파라미터 명과 같음&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Transactional&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메서드 내부의 DB 트랜잭션 설정하는 어노테이션&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Scheduled(cron = &quot;&quot;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Cron 표현식에 의한 정해진 시간에 메서드를 실행시키는 어노테이션&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Test&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Junit에서 테스트할 대상으로 지정&lt;/span&gt;&lt;/p&gt;</description>
      <category>취업 후 학습</category>
      <category>annotation</category>
      <category>Spring</category>
      <category>spring boot</category>
      <author>코딩독학하기</author>
      <guid isPermaLink="true">https://khsung0.tistory.com/81</guid>
      <comments>https://khsung0.tistory.com/81#entry81comment</comments>
      <pubDate>Wed, 28 Jun 2023 16:01:04 +0900</pubDate>
    </item>
    <item>
      <title>스프링이란? 스프링과 스프링 부트의 차이점은?</title>
      <link>https://khsung0.tistory.com/80</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이미 Spring Boot를 이용한 웹 업무를 하고 있지만 유지보수 수준이기 때문에 구체적인 이해가 부족한 듯싶어 처음부터 정리할 겸 작성하기로 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spring 이란?&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spring은 Java 개발을 편하게 해주는 프레임워크이며 웹 MVC 모듈을 제공하여 동적인 웹을 효과적으로 제작할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;또한 ORM(JPA, Mybatis)과 같은 모듈들을 보다 편하게 사용할 수 있다는 장점이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이때 ORM은 Object Relational Mapping의 약자로 객체와 관계형 데이터 베이스의 데이터를 자동으로 Mapping 해주는 것을 뜻한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;추가적으로 &lt;u&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://start.spring.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://start.spring.io/&lt;/a&gt;&lt;/span&gt;&lt;/u&gt; 해당 사이트에서 초기 프로젝트를 생성하는 서비스를 제공하기도 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spring은 자바 객체의 생명 주기를 관리하기 때문에 사용자는 컨테이너에서 필요한 객체를 가져와 사용만 하면 된다는 편리함이 있으며 대표적인 특징으로는 DI, IOC가 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DI는 Dependency Injection(의존성 주입)의 약자로 어떤 객체를 사용하는 주체가 객체를 직접 생성하는 것이 아니라 Spring에서 생성한 객체를 주체에게 주입시켜 주는 방식을 뜻한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;객체를 직접 생성하게 되면 수정 사항이 생길 때마다 수정할 부분이 많아지는데(의존성이 높아지는데) Spring에서 생성하게 되면 Interface를 기반으로 관리하기 때문에 수정할 부분이 줄어든다(의존성이 낮아진다).&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이때 Interface를 사용하는 이유는 Controller 단에서 직접 Service를 바라보는 게 아닌 Interface를 바라보고 있는데 Interface에 대한 실제 구현체가 Service단에 있으므로 Runtime 직전까지는 실제 구현체를 알지 못한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;따라서&amp;nbsp; Controller 단에서는 실제 비즈니스 로직에 대해 알 필요가 없고 Interface의 메서드로만 로직을 구성하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;반대로 Service 단에서는 Interface의 규칙만 잘 지킨다면 언제든 로직 변경이 가능하고 새로운 클래스로 대체도 가능하기 때문에 의존성이 낮아져 확장성이 높다는 장점이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IOC는 Inversion Of Control(제어의 역전)의 약자로 간단하게 말하자면 사용자의 제어권을 Spring에게 넘기는 것을 뜻한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일반적인 Java Programming의 흐름은 사용자가 직접 객체를 생성하고 메서드를 호출하는 방식이었지만 Spring에서는 Spring이 객체를 생성하고 주입하여 객체의 메서드를 호출하는 방식이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;따라서 Spring이 실행될 때 모든 의존성 객체를 생성하고 필요한 곳에 주입해 준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spring과 Spring Boot의 차이점&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;결론부터 말하자면 Spring Boot는 Spring의 복잡성을 줄인 업그레이드 버전이라고 생각하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Spring은 Dependency 설정을 위해&amp;nbsp;&lt;u&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://mvnrepository.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://mvnrepository.com/&lt;/a&gt;&lt;/span&gt;&lt;/u&gt; 같은 곳에서 일일이 찾아야 하고 버전 관리도 직접 해야 해서 번거롭고 복잡하지만 Spring Boot는 spring-boot-starter를 통해 자동으로 설정할 수 있어 훨씬 더 짧은 시간에 비교적 간단하게 실행할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;또한 Spring은 주로 maven 기반의 Java Application을 만드는 데 사용하지만 Spring Boot는 Gradle 기반의 REST API 개발에 사용하며 톰캣 같은 WAS가 내장되어 있어 쉽게 Web Application 구동이 가능하며 실행 가능한 JAR 파일 생성도 가능하여 자바 옵션만으로 쉽게 배포가 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정리하자면 Spring은 프레임워크를 보다 세밀하게 제어하는 경우, Spring Boot는 빠르게 간단하게 Application 개발을 하는 경우에 적합하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>취업 후 학습</category>
      <category>Spring</category>
      <category>spring boot</category>
      <author>코딩독학하기</author>
      <guid isPermaLink="true">https://khsung0.tistory.com/80</guid>
      <comments>https://khsung0.tistory.com/80#entry80comment</comments>
      <pubDate>Tue, 20 Jun 2023 14:26:52 +0900</pubDate>
    </item>
    <item>
      <title>리액트 data.map is not a function 에러 해결</title>
      <link>https://khsung0.tistory.com/79</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;리액트에서는 return 문에서 JSX를 사용하기 때문에 직접적으로 for문과 같은 반복문을 사용하지 못한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;굳이 사용하자면 JSX를 반환하는 함수를 선언하고 그 안에 반복문을 사용할 순 있겠지만 코드가 짧아질수록 편의성이 증가하므로 주로 map을 쓰는 편이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;캡처.png&quot; data-origin-width=&quot;416&quot; data-origin-height=&quot;182&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dsFwB2/btsdH16laJU/3JtsfKpSbTsytfc0FA2RD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dsFwB2/btsdH16laJU/3JtsfKpSbTsytfc0FA2RD0/img.png&quot; data-alt=&quot;map 함수 에러&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dsFwB2/btsdH16laJU/3JtsfKpSbTsytfc0FA2RD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdsFwB2%2FbtsdH16laJU%2F3JtsfKpSbTsytfc0FA2RD0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; alt=&quot;map 함수 에러&quot; loading=&quot;lazy&quot; width=&quot;416&quot; height=&quot;182&quot; data-filename=&quot;캡처.png&quot; data-origin-width=&quot;416&quot; data-origin-height=&quot;182&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;map 함수 에러&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하지만 종종 위와 같이 map is not a function 에러가 나타나는 경우가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문제는 두 가지 경우로 나눌 수 있는데 첫 번째는 data 부분이 배열이 아닌 경우고, 두 번째는 data 변수가 배열로 데이터를 받기 전 렌더링이 되었을 경우다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;map 함수는 배열에 접근하기 위한 자바스크립트의 내장 함수이기 때문에 배열이 아닌 데이터(특히 객체)에 map을 사용할 경우 문제가 발생한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;따라서 콘솔에 해당 변수를 찍어보면 배열이 아닌 경우가 대다수일 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하지만 간혹 가다 분명히 배열이 맞는데 위와 같은 에러가 나오는 경우가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이것은 두 번째 케이스인 변수가 배열의 데이터를 받기 전에 렌더링 되었을 경우다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;물론 useState([])처럼 빈 배열로 초기화하면 되지만 상황에 따라 불가능한 경우도 있을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그럴 땐 데이터를 받아왔을 때만 컴포넌트를 렌더링 하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;즉, 문제 되는 변수가 data 라면 {data &amp;amp;&amp;amp; data.map()}처럼 data 변수에 값을 받아왔을 때만 map 함수를 실행시키도록 변경하면 문제는 해결된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이때 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;중괄호({})&lt;/b&gt;&lt;/span&gt;로 감싸주는 것을 잊으면 안 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=====&amp;nbsp; 리액트를 처음으로 접해서 공부할 겸 정리한 것이라 적극적인 피드백 환영합니다!! =====&lt;/span&gt;&lt;/p&gt;</description>
      <category>취업 후 학습</category>
      <category>리액트</category>
      <author>코딩독학하기</author>
      <guid isPermaLink="true">https://khsung0.tistory.com/79</guid>
      <comments>https://khsung0.tistory.com/79#entry79comment</comments>
      <pubDate>Wed, 3 May 2023 10:49:38 +0900</pubDate>
    </item>
    <item>
      <title>파이썬 Pyautogui로 매크로 만들기</title>
      <link>https://khsung0.tistory.com/78</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파이썬은 인터프리터 언어라 컴파일 언어에 비해 비록 느리지만 사용자 친화적으로 쉬운 구문과 광범위한 응용 프로그램에 사용할 수 있단 장점이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특히 강력한 라이브러리로 데이터 분석, AI, 자동화 등에 강점을 보이는데 이번에는 자동화(매크로)에 자주 쓰이는 Pyautogui에 대해 알아보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시작 전에 처음 들어봤거나 확실하게 알지 못하는 사람들을 위해 매크로가 무엇인지 알아보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 매크로란 컴퓨터 과학 분야에서 정해진 순서에 따라 특정한 입력 시퀀스가 출력 시퀀스를 정의하는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;규칙이나 패턴&lt;/b&gt;&lt;/span&gt;을 말한다. (출처 : 위키백과)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;즉, 쉽게 풀어서 말하자면 정해진 반복 작업을 컴퓨터가 수행하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특히 게임이나 티켓팅, 수강신청 등에서 매크로란 단어를 많이 접했을 텐데 이들의 공통점이 정해진 위치를 반복적으로 이동, 클릭, 입력한다는 점이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로직만 잘 구성한다면 불필요한 반복 작업을 컴퓨터에게 대신시킬 수 있기 때문에 아주 유용한 스킬이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Pyautogui 사용하기&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그럼 Pyautogui를 설치해 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;필자는 윈도우 환경이며 Visual Studio Code를 사용하기 때문에 터미널에 바로 입력하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;337&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/R9ReR/btr0RPKliP2/FDx7biGzlcUuPoLo0SGqv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/R9ReR/btr0RPKliP2/FDx7biGzlcUuPoLo0SGqv0/img.png&quot; data-alt=&quot;Pyautogui 설치 로그&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/R9ReR/btr0RPKliP2/FDx7biGzlcUuPoLo0SGqv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FR9ReR%2Fbtr0RPKliP2%2FFDx7biGzlcUuPoLo0SGqv0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; alt=&quot;Pyautogui 설치 로그&quot; loading=&quot;lazy&quot; width=&quot;529&quot; height=&quot;296&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;337&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Pyautogui 설치 로그&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;명령어는 pip install pyautogui이고 위 사진처럼 Successfully installed 로그가 찍힌다면 설치가 완료된 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이제 Pyautogui를 설치했으니 관련 함수들을 알아보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;함수들은 크게 마우스, 키보드, 이미지 관련 함수로 나눌 수 있는데 상당히 함수가 많기 때문에 그중에서도 자주 쓰일만한 함수들만 정리했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특히 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;빨간 표시는&lt;/b&gt; &lt;b&gt;생략 가능한 옵션&lt;/b&gt;&lt;/span&gt;을 뜻한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 660px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 24px;&quot;&gt;
&lt;td style=&quot;width: 99.8837%; height: 20px;&quot; colspan=&quot;2&quot; width=&quot;601&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;마우스 관련 함수&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;position()&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;마우스의 현재 위치 좌표 출력&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;mouseInfo()&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;마우스의 죄표, RGB Color 등 관련 정보&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;moveTo(x, y, &lt;span style=&quot;color: #ee2323;&quot;&gt;n&lt;/span&gt;)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;좌표 (x, y)로 &lt;span style=&quot;color: #ee2323;&quot;&gt;n 초 동안&lt;/span&gt; 이동&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;dragTo(x, y, &lt;span style=&quot;color: #ee2323;&quot;&gt;n&lt;/span&gt;)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;좌표 (x, y)로 &lt;span style=&quot;color: #ee2323;&quot;&gt;n 초 동안&lt;/span&gt; 드래그&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;click(&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;button=&amp;rsquo;right&amp;rsquo;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;왼쪽 클릭&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;오른쪽 클릭&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;click(&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;clicks=n, interval=t&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;왼쪽 클릭&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;(t&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;초 간격으로&lt;span&gt; n&lt;/span&gt;번 클릭&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;doubleClick()&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;왼쪽 더블 클릭&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;scroll(x)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;x만큼 스크롤 이동(양수면 위, 음수면 아래)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 24px;&quot;&gt;
&lt;td style=&quot;width: 99.8837%; height: 20px;&quot; colspan=&quot;2&quot; width=&quot;601&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&amp;nbsp;키보드 관련 함수&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;write(&amp;lsquo;String&amp;rsquo;,&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;interval=n&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;영어 문자열을&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;초 마다 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;입력 (한글 지원 X)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;keyDown(&amp;lsquo;key&amp;rsquo;)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;key에 해당하는 키를 누름&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;keyUp(&amp;lsquo;key&amp;rsquo;)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;key&lt;/span&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에 해당하는 키를 뗌&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;press(&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;lsquo;key&amp;rsquo;&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;]&lt;/span&gt;, &lt;span style=&quot;color: #ff0000;&quot;&gt;presses=n, interval=t&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;nbsp;리스트에 있는 &lt;/span&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;키를&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;초에&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;한 번씩 &lt;span&gt;n&lt;/span&gt;번&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;입력&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;hotkey(&amp;lsquo;key1&amp;rsquo;, &amp;rsquo; key2&amp;rsquo;)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;key1, key2 입력&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;KEYBOARD_KEYS&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;입력 가능한 키 리스트&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 24px;&quot;&gt;
&lt;td style=&quot;width: 99.8837%; height: 20px;&quot; colspan=&quot;2&quot; width=&quot;601&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&amp;nbsp;이미지 관련 함수&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 40px;&quot; width=&quot;274&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;screenshot(&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;lsquo;test.png&amp;rsquo;&lt;/span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;region=(x1, y1, x2, y2)&lt;span style=&quot;color: #000000;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 40px;&quot; width=&quot;327&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;스크린샷 이미지 객체 반환&lt;/span&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;test.png &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;명으로 파일 저장&lt;span&gt;, (x1, y1) &lt;/span&gt;부터&amp;nbsp; &lt;span&gt;(x2, y2)&lt;/span&gt;까지의 영역&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;locateOnScreen(&amp;lsquo;test.png&amp;rsquo;)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;test.png 와 일치하는 영역 반환(left, top, width, height)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;locateAllOnScreen(&amp;lsquo;test.png&amp;rsquo;)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;test.png 와 일치하는 모든 영역 반환(left, top, width, height)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;locateCenterOnScreen(&amp;lsquo;test.png&amp;rsquo;)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;test.png 와 일치하는 영역의 중앙 좌표 반환&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 99.8837%; height: 20px;&quot; colspan=&quot;2&quot; width=&quot;601&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&amp;nbsp;기타 함수&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;size()&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;주 모니터 크기 반환(width, height)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;countdown(n)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;n초 동안 카운트 다운하며 각 숫자를 출력&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 44.3024%; height: 20px;&quot; width=&quot;274&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;PAUSE = t&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 55.5813%; height: 20px;&quot; width=&quot;327&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;각 함수별 t초 딜레이(Default = 0.1초)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특히 매크로는 정해진 좌표를 반복 클릭하기 때문에 구현 단계에서 좌표를 얻을 수 있는 mouseInfo()가 상당히 유용한 함수다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주의해야 할 점은 키보드 관련 함수에서 알파벳키를 입력하고 실제 입력 상황에서 한글로 되어 있다면 상관없지만 write로 직접 한글 입력은 지원하지 않기 때문에 한글 입력을 위해선 편법을 위한 추가 사항이 조금 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;바로 pyperclip을 설치해서 클립보드에 한글을 복사 후 붙여 넣기 하는 방식이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;명령어는 pip install pyperclip이며 pyautogui를 설치할 때처럼 동일하게 하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1677405127455&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pyperclip, pyautogui

# 클립보드에 한글 문자열 복사
pyperclip.copy('한글 입력 테스트')

# ctrl + v 로 붙여넣기
pyautogui.hotkey('ctrl', 'v')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설치 후 위 코드처럼 작성하면 한글을 입력하는 듯한 효과를 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 함수를 사용한 예제를 보기엔 너무 방대하므로 간단하게 특정 위치를 반복 클릭하는 매크로와 임시 비밀번호를 생성해서 저장하는 예제를 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;반복 클릭 매크로&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1677407488028&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pyautogui

# 첫 시작 위치로 이동
pyautogui.moveTo(334, 351)

# 시작 위치에서 마우스가 벗어나면 반복 중지
while pyautogui.position().x == 334 and pyautogui.position().y == 351:
    pyautogui.click()
    pyautogui.moveTo(320, 446)
    pyautogui.click()
    pyautogui.moveTo(334, 351)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위 코드는 특정 위치를 무한 반복 클릭하는 코드다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이때 주의해야 할 점은 마우스를 다루기 때문에 딜레이나 무한 루프를 탈출할 조건을 사용하지 않을 경우 이도저도 못하는 난감한 상황이 발생할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해당 예제에서는 시작 위치를 정하고 마우스가 위치를 벗어날 경우 프로그램을 종료하도록 작성했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위와 같은 로직으로 미리 mouseInfo() 함수를 이용해서 좌표 정보를 얻고 작성하면 빠르게 반복 클릭할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;임시 비밀번호 생성 후 저장&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1677408496865&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pyautogui, random, time

# 길이가 8인 소문자 임시 비밀번호 생성
def temp_pw():
    pw = ''
    for i in range(8):
        pw += chr(random.randrange(97,123))
    return pw

# 메모장 위치
pyautogui.moveTo(496, 423)
pyautogui.doubleClick()

# 메모장이 켜질때까지 대기
time.sleep(1)

# 메모장에 커서 생성
pyautogui.moveTo(604, 713)
pyautogui.click()

# 5개의 임시 비밀번호 생성
for i in range(5):
    pyautogui.write(temp_pw()+'\n')

# 저장
pyautogui.hotkey('ctrl', 's')

# 메모장 종료
pyautogui.hotkey('alt', 'f4')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;필자는 임시 비밀번호를 저장하기 위한 메모장을 생성했었고 해당 위치 좌표로 이동 후 더블 클릭으로 켰다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;너무 속도가 빨라 엉뚱한 곳을 클릭하는 것을 방지하기 위해 메모장이 켜질 때까지 대기하려 time.sleep(1)을 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메모장이 켜지면 커서를 생성하기 위해 한번 클릭을 했고 소문자로 이루어진 8자리 임시 비밀번호를 저장 후 종료하는 로직이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이처럼 파이썬의 자동화 도구를 잘 사용하면 불필요한 반복 작업을 컴퓨터에게 시킬 수 있어 상당히 편리하고 개인에게 강력한 무기가 될 수 있다고 생각한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;필자도 종종 필요한 경우 자동화 코드를 작성해서 편리했고 이를 본 주위 사람들이 신기해했던 경험이 있기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;차후에 단순한 마우스, 키보드 자동화 말고도 엑셀 파일처럼 업무 자동화에 대해서도 가능한 자세히 포스팅하도록 하겠다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>취업 후 학습</category>
      <category>pyautogui</category>
      <category>Python</category>
      <category>매크로</category>
      <category>자동화</category>
      <category>파이썬</category>
      <author>코딩독학하기</author>
      <guid isPermaLink="true">https://khsung0.tistory.com/78</guid>
      <comments>https://khsung0.tistory.com/78#entry78comment</comments>
      <pubDate>Sun, 26 Feb 2023 18:54:18 +0900</pubDate>
    </item>
    <item>
      <title>안드로이드 스튜디오 딜레이(Delay) 구현</title>
      <link>https://khsung0.tistory.com/77</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;앱을 구현하다 보면 병렬 처리가 필요할 경우 스레드를 사용하면 되지만 상황에 따라서 일정시간 뒤에 전체 로직을 수행해야 할 경우가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;필자 같은 경우 현재 구현하고 있는 카드 뒤집기 게임에서 일정시간 전체 카드를 보여주고 다시 뒤집는 로직을 수행하거나 두 번째 오픈한 카드가 일치하지 않을 때 일정시간 이후 다시 뒤집어야 되는데 여기서 딜레이가 필요했기 때문에 정리하기로 마음먹었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;결론부터 말하자면 Handler의 postDelayed 메서드를 사용하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1673235150731&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;new Handler().postDelayed(new Runnable(){
        @Override
        public void run(){
            //구현하고 싶은 코드
        }
    }, 5000);	//5초&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Handler의 postDelayed 메서드에 Runnable 인터페이스를 파라미터로 주고 run을 실행시키는 형태이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이때 두 번째 파라미터는 딜레이하고 싶은 시간인데 기준이 ms(미리 세컨드)이므로 1초당 1000ms로 계산해서 넣으면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1673235336596&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;new Handler().postDelayed(new Runnable(){
        @Override
        public void run(){
            for (int i = 0; i &amp;lt; idIndex; i++){
                animator = ObjectAnimator.ofFloat(findViewById(i),&quot;rotationY&quot;,0,180);
                animator.start();
            }
            clickControl(true);
            if(player == 1){
                stt = new SoloTimerThread();
                t = new Thread(stt);
            }else{
                dtt = new DuoTimerThread();
                t = new Thread(dtt);
            }
            t.start();
        }
    }, 5000);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위 코드는 5초의 딜레이를 주고 모든 카드들을 y축을 기준으로 180도 뒤집은 다음, 모드에 따라 해당하는 스레드를 실행시키는 예제이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;의외로 스레드만큼 딜레이는 유용하므로 코드를 참고하여 적절히 사용하면 좋을 것 같다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>취업 후 학습/안드로이드</category>
      <category>delay</category>
      <category>딜레이</category>
      <category>안드로이드 스튜디오</category>
      <author>코딩독학하기</author>
      <guid isPermaLink="true">https://khsung0.tistory.com/77</guid>
      <comments>https://khsung0.tistory.com/77#entry77comment</comments>
      <pubDate>Mon, 9 Jan 2023 12:40:52 +0900</pubDate>
    </item>
    <item>
      <title>안드로이드 스튜디오 스레드(Thread) 구현하기</title>
      <link>https://khsung0.tistory.com/76</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;카드 맞추기 앱을 구현하면서 타이머 때문에 스레드를 다루게 되어&amp;nbsp;정리할 겸 포스팅하기로 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하나의 동작하는 프로그램을 프로세스(Process)라고 하며 하나의 프로세스는 한 가지 일밖에 하지 못한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하지만 프로세스 안에 있는 스레드를 이용한다면 두 가지 이상의 일을 동시에 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;물론 보다 정확히 말하자면 동시에 하는 것처럼 보이게 할 수 있는 것이다.(스레드에 대해 자세한 정리는 기회가 되면 포스팅하겠다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이를 병렬 처리라 하며 안드로이드의 자바 코드로 스레드를 구현하는 방법은 두 가지가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;첫 번째는 Thread 클래스를 상속받는 방법이고 두 번째는 Runnable 인터페이스를 구현하여 Thread 객체에 전달하는 방법이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Thread 클래스&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1673235980918&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class MyThread extends Thread {
    // run() 메소드를 오버라이드
    public void run() {
    	// 수행할 로직
        System.out.println(&quot;Hello from a thread!&quot;);
    }

    public static void main(String[] args) {
        // MyThread 객체를 생성한 후, start() 메소드를 호출하여 실행
        MyThread thread = new MyThread();
        thread.start();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위 내용은 스레드를 상속받아 사용하는 코드이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;start() 메서드를 실행하면 Thread 클래스 내부에서 run() 메서드를 실행하기 때문에 꼭 thread.run()이 아닌 thread.start()로 하는 것을 잊으면 안 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Runnable 인터페이스&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Thread는 Class를 상속(Extends) 받기 때문에 Java의 단일상속에 의해 다른 Class를 상속받을 수 없어 유용하지 않은 편이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;또한 Thread를 상속받을 경우 Thread Class에 구현된 모든 코드들이 동작하기 때문에 자원을 많이 잡아먹어 효율적이지 못하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이를 해결하기 위해 Runnable 인터페이스를 구현(Implements)하고 Thread 객체에 전달하면 대부분의 구현을 할 수가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1677228756065&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class MyRunnable implements Runnable {
    // run() 메소드를 오버라이드
    public void run() {
    	// 수행할 로직
        System.out.println(&quot;Hello from a thread!&quot;);
    }

    public static void main(String[] args) {
        // MyRunnable 객체를 생성한 후, 이를 Thread 생성자에 전달
        MyRunnable runnable = new MyRunnable();
        Thread thread = new Thread(runnable);
        thread.start();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위 내용은 Runnable 객체를 생성한 후 Thread 생성자에 전달해서 Thread를 생성하고 실행한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이때 생성한 Runnable 객체는 다른 클래스에서도 사용할 수 있기 때문에 유연한 코드 작성이 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Thread는 상속이고 Runnable은 Interface이기 때문에 다중 상속이 불가능한 Java에서 Runnable 객체는 아주 유용한 작성방법이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Runnable 인터페이스를 이용한 Thread 수행 시에도 내부적으로 Run() 메서드를 오버라이드 하기 때문에 thread.run()이 아닌 thread.start()를 해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Thread를 사용하는 대표적인 예시가 타이머이기 때문에 마지막으로 Runnable Interface를 이용한 타이머를 예제로 설명하겠다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1677229311342&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class MyRunnable implements Runnable {
    // run() 메소드를 오버라이드
    public void run() {
    	// 스레드가 실행할 로직 구현
        int second = 0;
        System.out.println(&quot;===== 타이머 실행 =====&quot;);
        // 타이머에 자주 쓰는 코드
        while (true){
            System.out.println(&quot;실행시간 : &quot; + second);
            try {
                Thread.sleep(1000); 	// 1초 딜레이
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
            second++;
        }
        System.out.println(&quot;===== 타이머 종료 =====&quot;);
    }

    public static void main(String[] args) {
        // MyRunnable 객체를 생성한 후, 이를 Thread 생성자에 전달
        MyRunnable runnable = new MyRunnable();
        Thread thread = new Thread(runnable);
        thread.start();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위 예제는 While문을 통해 무한 루프를 돌면서 Thread.sleep으로 1초간 딜레이를 주는 타이머다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이때 종료하고 싶은 시점에서 thread.stop()이나 thread.interrupt()를 호출하면 Run() 메서드 내부에서 Catch문에 걸려 종료할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;thread.stop()은 불완전한 메서드이기 때문에 thread.interrupt()를 추천한다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>취업 후 학습/안드로이드</category>
      <category>쓰레드</category>
      <category>안드로이드 스튜디오</category>
      <author>코딩독학하기</author>
      <guid isPermaLink="true">https://khsung0.tistory.com/76</guid>
      <comments>https://khsung0.tistory.com/76#entry76comment</comments>
      <pubDate>Tue, 3 Jan 2023 12:44:24 +0900</pubDate>
    </item>
  </channel>
</rss>