<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>s_chuli.log</title>
        <link>https://velog.io/</link>
        <description>👨🏻‍💻 #developer#일상#공부#기록 </description>
        <lastBuildDate>Sat, 27 May 2023 15:04:16 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>s_chuli.log</title>
            <url>https://images.velog.io/images/s_chuli/profile/1fdc7cfb-174b-4cce-b017-bb98b213b8b3/KakaoTalk_Photo_2021-02-27-01-11-05.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. s_chuli.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/s_chuli" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[String, StringBuffer, StringBuilder 차이와 장단점]]></title>
            <link>https://velog.io/@s_chuli/String-StringBuffer-StringBuilder-%EC%B0%A8%EC%9D%B4%EC%99%80-%EC%9E%A5%EB%8B%A8%EC%A0%90</link>
            <guid>https://velog.io/@s_chuli/String-StringBuffer-StringBuilder-%EC%B0%A8%EC%9D%B4%EC%99%80-%EC%9E%A5%EB%8B%A8%EC%A0%90</guid>
            <pubDate>Sat, 27 May 2023 15:04:16 GMT</pubDate>
            <description><![CDATA[<p>String, StringBuffer, StringBuilder는 Java에서 문자열을 처리하는 클래스입니다. 이들 클래스는 문자열을 표현하고 조작하는 다양한 메서드를 제공하지만, 몇 가지 차이점이 있습니다. 각 클래스의 차이점과 장단점을 살펴보겠습니다.</p>
<h3 id="1-string">1. String</h3>
<p><strong>String</strong>은 객체이며, 한 번 생성되면 변경할 수 없는 <strong>불변(Immutable)성</strong>을 가진 <strong>불변 객체</strong>입니다.</p>
<p>String 객체에 새로운 문자열을 합치게 되면 기존 생성한 String 객체에 문자열을 이어 붙이는 것이 아니라 기존 문자열과 이어 붙인 문자열을 담은 <strong>새로운 String 객체</strong>를 생성하게 됩니다. </p>
<p>String 객체는 JVM 메모리 구조의 <strong>Heap 메모리 영역</strong>에 생성되며, 한 번 생성된 String 객체의 내용은 불변성 특징때문에 변경할 수 없습니다!</p>
<p>기존에 사용하지 않는 String 객체들은 GC(가비지 컬렉션)에 의해서 <strong>회수</strong>되기는 하지만, 문자열 연결 작업이 많은 경우 성능 측면에서 <strong>비효율적</strong>일 수 있으며, 많은 메모리가 사용될 수 있기 때문에 신중히 사용 할 필요가 있습니다.</p>
<hr>
<h3 id="2-stringbuffer--stringbuilder">2. StringBuffer / StringBuilder</h3>
<p><strong>StringBuffer</strong>와 <strong>StringBuilder</strong>의 공통점은 <strong>AbstractStringBuilder</strong> 추상 클래스를 상속받고 있다는 점입니다. 그렇다는 것은 StringBuffer와 StringBuilder는 <strong>공통의 API</strong>를 제공한다는 의미입니다.</p>
<p>문자열 연결 작업이 자주 발생하고 있다면 String 객체를 + 연산자로 연결하는 것이 아니라, StringBuffer와 StringBuilder 객체를 사용하는 것이 좋습니다.</p>
<p>StringBuffer와 StringBuilder의 <strong>차이점</strong>은 바로 <strong>스레드 안전성(Thread safe)</strong>입니다. </p>
<p>StringBuffer는 <strong>동기화(synchronized)</strong>되어 여러 스레드(Thread)에서 안전하게 사용할 수 있습니다. 즉, <strong>멀티스레드 환경</strong>에서 동시에 접근하더라도 <strong>데이터 일관성</strong>을 보장한다는 것입니다.</p>
<p>반면, StringBuilder는 <strong>동기화(synchronized)되지 않아</strong> 멀티스레드 환경에서의 안정성을 보장하지 않습니다. 따라서 <strong>단일 스레드 환경</strong>에서 문자열 조작이 필요한 경우에는 StringBuilder를 사용하는 것이 더 효율적입니다!</p>
<hr>
<h3 id="3-메모리-효율성">3. 메모리 효율성</h3>
<p>메모리 효율성 측면에서는 <strong>String</strong>, <strong>StringBuffer</strong>, <strong>StringBuilder</strong> 순서로 메모리를 사용합니다. String은 <strong>불변</strong>이기 때문에 문자열 조작 시마다 새로운 객체를 생성하기 때문에 이후에 <strong>메모리 낭비</strong>를 초래할 수 있습니다!</p>
<p>StringBuffer와 StringBuilder는 <strong>가변</strong>이기 때문에 내부적으로 <strong>버퍼</strong>를 사용하여 문자열을 조작합니다. 문자열 조작이 빈번한 경우에는 <strong>StringBuffer</strong>와 <strong>StringBuilder</strong>가 메모리 효율성 측면에서 더 좋은 선택일 수 있습니다.</p>
<p>따라서 정리하자면 !!
문자열을 변경하지 않고 <strong>읽기만 하는 경우</strong>에는 <strong>String</strong> 객체를 사용한다!
문자열 연결 작업이 자주 발생하고 <strong>단일 스레드 환경</strong>이다? <strong>StringBuilder</strong>를 사용!
StringBuilder와 같지만, <strong>멀티 스레드 환경</strong>에서 사용한다! 그렇다면 <strong>StringBuffer</strong>를 사용하도록 합시다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CheckedException과 UnCheckedException의 차이]]></title>
            <link>https://velog.io/@s_chuli/CheckedException%EA%B3%BC-UnCheckedException%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@s_chuli/CheckedException%EA%B3%BC-UnCheckedException%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Wed, 05 Apr 2023 16:05:59 GMT</pubDate>
            <description><![CDATA[<p>자바에서 예외(Exception)는 Checked Exception과 Unchecked Exception 두 가지로 나눌 수 있습니다. 이번 글에서는 Checked Exception과 Unchecked Exception의 차이점을 알아보겠습니다.</p>
<h4 id="checked-exception">Checked Exception</h4>
<p>Checked Exception은 예외 처리가 강제되는 예외입니다. 즉, 예외가 발생한 메서드에서 예외를 처리하거나, 해당 메서드를 호출한 상위 메서드에서 예외를 처리해야 합니다. Checked Exception은 일반적으로 입출력, 네트워크, 데이터베이스 연결과 같은 외부 자원을 사용하는 메서드에서 발생합니다. Checked Exception을 사용하는 이유는, 이러한 자원을 사용하는 경우 예기치 못한 상황이 발생할 수 있기 때문에 예외 처리를 강제함으로써 프로그래머가 예외 상황을 놓치지 않도록 하기 위함입니다.</p>
<p>Checked Exception 예시 코드를 보겠습니다.</p>
<pre><code class="language-java">import java.io.FileInputStream;
import java.io.IOException;

public class Example {

    public static void main(String[] args) {
        try {
            FileInputStream fileInputStream = new FileInputStream(&quot;example.txt&quot;);
            // 파일에서 데이터를 읽는 로직
            fileInputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}</code></pre>
<p>위 코드에서 FileInputStream 생성자는 FileNotFoundException이 발생할 수 있는 메서드입니다. 따라서 IOException 예외를 처리하기 위해 try-catch 구문을 사용하여 예외를 처리하였습니다.</p>
<h4 id="unchecked-exception">Unchecked Exception</h4>
<p>Unchecked Exception은 예외 처리가 강제되지 않는 예외입니다. 즉, 예외가 발생해도 상위 메서드에서 예외 처리를 강제하지 않습니다. Unchecked Exception은 주로 프로그래밍 오류와 관련된 예외입니다. 예를 들어, 배열 인덱스 범위를 벗어나거나, 널 포인터 참조 등의 경우에 Unchecked Exception이 발생합니다.</p>
<p>Unchecked Exception 예시 코드를 보겠습니다.</p>
<pre><code class="language-java">public class Example {

    public static void main(String[] args) {
        int[] arr = new int[5];
        arr[6] = 10;
    }
}</code></pre>
<p>위 코드에서 arr 배열의 인덱스를 벗어나 arr[6]에 10을 할당하려고 하면 ArrayIndexOutOfBoundsException이 발생합니다. 이 예외는 Checked Exception이 아니므로, 예외 처리를 강제하지 않습니다.</p>
<h4 id="checked-exception와-unchecked-exception-차이점">Checked Exception와 Unchecked Exception 차이점</h4>
<p>Checked Exception과 Unchecked Exception의 가장 큰 차이점은 예외 처리가 강제되는지 여부입니다. Checked Exception은 예외 처리가 강제되므로, 예외 처리를 강제하지 않으면 컴파일 오류가 발생합니다. 반면에, Unchecked Exception은 예외 처리를 강제하지 않으므로, 예외 처리를 강제하지 않아도 코드 컴파일은 가능합니다. 따라서, Checked Exception은 반드시 예외 처리를 해야 하는 외부 자원을 다루는 코드에서 사용되며, Unchecked Exception은 주로 프로그램 자체의 버그나 오류를 나타내는 예외로 사용됩니다.</p>
<p>또한, Checked Exception은 throws 키워드를 사용하여 예외를 호출한 메서드로 던져야 합니다. 이를 통해 예외를 처리하지 않고 호출한 메서드로 예외를 전달할 수 있습니다. 반면에, Unchecked Exception은 throws 키워드를 사용하지 않아도 예외를 던질 수 있습니다.</p>
<h4 id="checked-exception-class-종류">Checked Exception Class 종류</h4>
<ul>
<li>IOException</li>
<li>SQLException</li>
<li>ClassNotFoundException</li>
<li>InterruptedException</li>
<li>...</li>
</ul>
<h4 id="unchecked-exception-class-종류">Unchecked Exception Class 종류</h4>
<ul>
<li>RuntimeException</li>
<li>NullPointerException</li>
<li>ArrayIndexOutOfBoundsException</li>
<li>IllegalArgumentException
...</li>
</ul>
<p>따라서, 예외 처리가 강제되는지 여부에 따라 Checked Exception과 Unchecked Exception을 선택하여 사용하면 됩니다. 외부 자원을 다루는 코드에서는 Checked Exception을, 프로그램 자체의 버그나 오류를 나타내는 예외에서는 Unchecked Exception을 사용하는 것이 일반적입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[컴파일러(compiler)와 인터프리터(interpreter)의 차이]]></title>
            <link>https://velog.io/@s_chuli/%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%ACcompiler%EC%99%80-%EC%9D%B8%ED%84%B0%ED%94%84%EB%A6%AC%ED%84%B0interpreter%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@s_chuli/%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%ACcompiler%EC%99%80-%EC%9D%B8%ED%84%B0%ED%94%84%EB%A6%AC%ED%84%B0interpreter%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Mon, 20 Mar 2023 15:03:54 GMT</pubDate>
            <description><![CDATA[<h3 id="java의-컴파일러compiler와-인터프리터interpreter에-대해-알아보자">Java의 컴파일러(compiler)와 인터프리터(Interpreter)에 대해 알아보자.</h3>
<p>프로그래밍(java, c, c++ 등..) 언어들은 인간친화적 언어이다. 인간이 알아볼 수 있도록 작성할 수 있고 그것을 해독할 수 있다. 하지만 컴퓨터는 다르다. 컴퓨터는 0아니면 1로 이루어진 기계어 신호만 알아듣기 때문에 우리가 작성한 프로그래밍 언어는 이해할 수 없다. 그렇기 때문에 컴퓨터를 통해 언어를 실행시키기 위해서는 기계어로 번역해줘야 한다. 번역을 하는 과정이 compile(컴파일)이고 번역 역할을 도와주는 녀석이 compiler(컴파일러)이다. 대표적인 컴파일러 언어는 c와 c++가 있다.</p>
<h3 id="인터프리터interpreter">인터프리터(interpreter)</h3>
<p>컴파일러와 달리 소스 작성 후 번역 작업을 한 번에 처리하는 것이 아니라, 실행 할 때마다  interpreter라는 프로그램이 컴퓨터에게 코드를 기계어로 변역해준다. 대표적인 언어로는 Javascript, Python, Ruby 등이 있다.</p>
<h3 id="java의-컴파일러compiler와-인터프리터interpreter">Java의 컴파일러(compiler)와 인터프리터(interpreter)</h3>
<p>자바는 컴파일러 언어이기도 하고 인터프리터 언어이기도 하다. 자바는 다른 컴파일러 언어들이 작동하듯이 자바 컴파일러를 이용해 전체 코드를 한번에 번역한다. 이 과정은 컴파일러 언어와 동일하지만 자바 컴파일러는 코드를 바로 기계어로 번역해주는 것이 아니라, 자방 가상 머신(JVM)이 실행시킬 수 있는 자바 바이트코드(class)로 번역한다. 보통 자바를 컴파일하고나면 .java 파일들이 .class 파일로 변환된 것을 확인할 수 있는데 class 파일은 바이트코드로 이루어져 있다.</p>
<p>**  java compiler의 역할**</p>
<ul>
<li>.java file → javac (java compiler) → .class file 변환</li>
</ul>
<p><strong>java interpreter 역할</strong>    </p>
<ul>
<li>java compiler에 의해 변환된 .class 파일 내의 바이트 코드를 특정 환경의(OS) 기계에서 실행될 수 있도록 바이트 코드를 한 줄씩 읽어 기계어(2진 코드)로 변환한다.</li>
</ul>
<p><strong>JIT 컴파일러(compiler)</strong></p>
<ul>
<li>인터프리터 효율을 높이기 위해, 인터프리터가 반복되는 코드를 발견하면 JIT 컴파일러로 반복되는 코드를 모두 네이티브 코드로 바꿔둔다. 그 다음부터 인터프리터는 네이트브 코드로 컴파일된 코드를 바로 사용한다.</li>
</ul>
<hr>
<h4 id="정리--java의-컴파일러와-인터프리터에-대해-설명하세요">[정리]  Java의 컴파일러와 인터프리터에 대해 설명하세요.</h4>
<p>먼저, compiler는 인간이 작성한 프로그래밍 언어를 컴퓨터가 이해할 수 있는 기계어로 번역하는 역할을 하는 프로그램입니다. 대표적인 컴파일러 언어로는 c와 c++가 있습니다.</p>
<p>반면, interpreter는 소스 코드를 한 번에 번역하지 않고 실행할 때마다 프로그램이 소스 코드를 기계어로 변역하는 역할을 하는 프로그램입니다. 대표적인 인터프리터 언어로는 Javascript, Python, Ruby 등이 있습니다.</p>
<p>Java는 컴파일러 언어이기도 하고 인터프리터 언어이기도 합니다. Java는 자바 컴파일러를 이용해 전체 코드를 한 번에 번역하지만, 번역된 코드는 기계어가 아닌 JVM이 실행시킬 수 있는 자바 바이트코드로 번역됩니다. JVM은 자바 바이트코드를 한 줄씩 읽어 기계어로 변환하여 실행합니다.</p>
<p>또한, JIT 컴파일러는 인터프리터의 효율을 높이기 위해, 인터프리터가 반복되는 코드를 발견하면 해당 코드를 네이티브 코드로 바꿉니다. 그러면 이후에는 인터프리터가 바로 네이티브 코드를 사용하여 실행할 수 있으므로 성능이 향상됩니다.</p>
<p>따라서, 컴파일러와 인터프리터는 프로그래밍 언어를 실행하는 방식에서 차이가 있으며, Java는 컴파일러와 인터프리터를 모두 사용합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring Batch란 무엇인지 알아보자]]></title>
            <link>https://velog.io/@s_chuli/Spring-Batch%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EC%A7%80-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@s_chuli/Spring-Batch%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EC%A7%80-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Thu, 11 Aug 2022 16:14:30 GMT</pubDate>
            <description><![CDATA[<h3 id="💁🏻♂️-spring-batch란">💁🏻‍♂️ Spring Batch란?</h3>
<p>batch는 일괄 처리라는 뜻을 가지고 있습니다.</p>
<p>일괄처리라는 것은 어떠한 내용들을 묶어서 한 번에 처리하는 것을 말합니다. 어떠한 내용들은 데이터가 될 것입니다. 
즉, 대용량 데이터를 처리하는 경우에 Spring Batch를 사용합니다.
ex) 정산, 거래명세서, 회원 정리, 알림톡</p>
<p>또 다른 이유는 효과적인 로깅, 통계 처리, 트랜잭션 관리 등 재사용에 가능한 필수 기능을 지원합니다.
예외가 발생할 경우에도 방어할 기능이 존재합니다. </p>
<hr>
<h3 id="💁🏻♂️-spring-batch-구조">💁🏻‍♂️ Spring Batch 구조</h3>
<ul>
<li><p><strong>Batch 구조 (Batch Application Style)</strong>
<img src="https://velog.velcdn.com/images/s_chuli/post/34b91e50-3788-4dc6-b9ab-a17650de7990/image.png" alt=""></p>
</li>
<li><p><strong>실행 구조 (Run Tier)</strong>
  Application의 상호 의존적 스케줄링을 허용하고 병렬 처리 기능을 합니다.</p>
</li>
<li><p><strong>작업 구조 (Job Tier)</strong>
  전체적인 Job의 수행을 책임지고 Job내의 각 Step을 정책에 따라 순차적으로 수행합니다.</p>
</li>
<li><p><strong>응용프로그램 구조 (Application Tier)</strong>
  Job을 수행하는데 필요한 Component</p>
</li>
<li><p>데이터 구조 (Data Tier)
  DB, 파일 또는 대기열을 포함할 수 있는 물리적 데이터 원본과의 통합을 제공합니다.</p>
</li>
</ul>
<hr>
<h3 id="💁🏻♂️-spring-batch-메타데이터-테이블-구조">💁🏻‍♂️ Spring Batch 메타데이터 테이블 구조</h3>
<p><img src="https://velog.velcdn.com/images/s_chuli/post/e4768d49-a872-409d-9da9-c3ad809f0c5a/image.png" alt=""></p>
<h4 id="spring-batch-에서-제공하는-메타-데이터-스키마는-총-6개의-테이블로-이루어져-있습니다-순서는-다음과-같습니다">Spring Batch 에서 제공하는 메타 데이터 스키마는 총 6개의 테이블로 이루어져 있습니다. 순서는 다음과 같습니다.</h4>
<ul>
<li><p><strong>BATCH_JOB_INSTANCE - JOB의 생성 정보를 담는 테이블</strong></p>
<ul>
<li>JOB_INSTANCE_ID : JOB 고유 ID</li>
<li>VERSION : 버전정보</li>
<li>JOB_NAME : JOB 빌드 시 생성하는 이름</li>
<li>JOB_KEY : JOB 고유 키</li>
</ul>
</li>
<li><p><strong>BATCH_JOB_EXECUTION - JOB의 실행정보를 담는 테이블</strong></p>
<ul>
<li>JOB_EXECUTION_ID : JOB 실행 고유 ID</li>
<li>VERSION : 버전정보</li>
<li>JOB_INSTANCE_ID : JOB 고유 ID</li>
<li>CREATE_TIME : 생성 시간</li>
<li>START_TIME : 시작 시간</li>
<li>END_TIME : 종료 시간</li>
<li>STATUS : 실행 상태</li>
<li>EXIT_CODE : 종료 코드</li>
<li>EXIT_MESSAGE : JOB 수행 실패시 메세지</li>
<li>LAST_UPDATED : 최종 업데이트 시간</li>
<li>JOB_CONFIGURATION_LOCATION : JOB Config 설정 위치</li>
</ul>
</li>
<li><p><strong>BATCH_JOB_EXECUTION_PARAM - JOB에서 사용되는 파라미터 값 들을 담는 테이블</strong></p>
<ul>
<li>JOB_EXECUTION_ID : JOB 실행 고유 ID</li>
<li>TYPE_CD : 저장된 값의 Type (string, date, long, double)</li>
<li>KEY_NAME : 키</li>
<li>STRING_VAL : String 값</li>
<li>DATE_VAL : date 값</li>
<li>LONG_VAL : long 값</li>
<li>DOUBLE_VAL : double 값</li>
<li>IDENTIFYING : job instance 생성 시 관여 여부 플래그</li>
</ul>
</li>
<li><p><strong>BATCH_JOB_EXECUTION_CONTEXT - 작업 중 사용되는 모든 정보가 기록되는 Context를 저장하기 위한 테이블</strong></p>
<ul>
<li>JOB_EXECUTION_ID : JOB 실행 고유 ID</li>
<li>SHORT_CONTEXT : String 형태의 Conext</li>
<li>SERIALIZED_CONTEXT : serialized 된 context</li>
</ul>
</li>
<li><p><strong>BATCH_STEP_EXECUTION - Step의 실행 정보를 담는 테이블</strong></p>
<ul>
<li>STEP_EXECUTION_ID : Step 실행 고유 ID</li>
<li>VERSION : 버전정보</li>
<li>STEP_NAME : Step 이름</li>
<li>JOB_EXECUTION_ID : Job 실행 고유 ID</li>
<li>START_TIME : 시작시간</li>
<li>END_TIME : 종료시간</li>
<li>STATUS : 실행 상태</li>
<li>COMMIT_COUNT : 트랜잭션당 커밋 수</li>
<li>READ_COUNT : 조회한 아이템 수</li>
<li>FILTER_COUNT : 필터링 된 아이템 수</li>
<li>WRITE_COUNT : 저장된 아이템 수</li>
<li>READ_SKIP_COUNT : 조회 스킵한 아이템 수</li>
<li>WRITE_SKIP_COUNT : 저장 스킵한 아이템 수</li>
<li>PROCESS_SKIP_COUNT : 스킵 된 아이템 수</li>
<li>ROLLBACK_COUNT : 롤백 발생 횟 수</li>
<li>EXIT_CODE : 종료 코드</li>
<li>EXIT_MESSAGE : Step 수행 실패시 메세지</li>
<li>LAST_UPDATED : 최종 업데이트 시간</li>
</ul>
</li>
<li><p><strong>BATCH_STEP_EXECUTION_CONTEXT - Step에서 사용되는 모든 정보가 기록되는 Context를 저장하기 위한 테이블</strong></p>
<ul>
<li>STEP_EXECUTION_ID : Step 실행 고유 ID</li>
<li>SHORT_CONTEXT : String 형태의 Context</li>
<li>SERIALIZED_CONTEXT : Serializied된 전체 Context</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring의 IoC와 DI 정리 ]]></title>
            <link>https://velog.io/@s_chuli/Spring%EC%9D%98-IoC%EC%99%80-DI-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@s_chuli/Spring%EC%9D%98-IoC%EC%99%80-DI-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Tue, 09 Aug 2022 13:42:46 GMT</pubDate>
            <description><![CDATA[<h3 id="ioc-inversion-of-control">IoC (Inversion of Control)</h3>
<p>IoC는 Inversion of Control의 약어로 제어의 역전이라는 뜻을 가지고 있습니다. 다시 말해 객체를 제어한다는 이야기입니다. </p>
<p>그럼 이러한 <strong>객체의 제어</strong>를 누가 하느냐? 개발자가 직접적으로 객체의 생명주기와 객체와 객체들 간의 제어를 수행하는 것이 아니라 <strong>IoC 컨테이너</strong>가 이를 수행하는 것 입니다.</p>
<p>Ioc가 객체들을 관리해줌으로써 객체 간의 결합도를 줄일수 있고, 중복 코드를 줄이고 코드의 가독성을 높일 수 있습니다. </p>
<p>그래서 Spring의 IoC 컨테이너의 객체는 어떤 객체를 말하는 걸까요?
바로 <strong>Spring Container</strong>에 생성된 <strong>Bean</strong>들을 말하는 것입니다. Spring의 Bean을 생성하는 방법은 객체에 어노테이션을 붙여서 생성할 수 있습니다.</p>
<h4 id="1-componentscan">1. @ComponentScan</h4>
<p>Spring 프로젝트를 생성하게 되면 최상위 클래스에 @SpringBootApplication을 보셨을 겁니다.
@SpringBootApplication 어노테이션을 타고 들어가게되면 수 많은 어노테이션 중에 @ComponentScan이 존재하는데요. <strong>@ComponentScan의 역할</strong>은 IoC 컨테이너의 등록될 <strong>Bean들을 탐색</strong>하는 역할을 합니다.</p>
<p>@ComponentScan의 탐색 범위는 @SpringBootApplication의 <strong>최상위부터 가장 최하위에 위치한 class들을 탐색</strong>하여 <strong>Bean</strong>을 등록하게 됩니다.</p>
<p>그렇다면 @ComponentScan이 탐색하는 대상은 어떠한 Class들 일까요?
개발하다보면 가장 많이 볼 수 있는 <strong>@Component, @Controller, @Service, @Repository</strong> 등 <strong>Stereotype</strong>으로 지정하는 모든 어노테이션이 대상입니다. Sterepotype의 어노테이션들은 @Component를 포함하고 있는데, 추가적으로 Bean을 등록할 객체가 있으면 @Component를 붙여서 사용하면 됩니다.</p>
<h4 id="2-configuration">2. @Configuration</h4>
<p>@Configuration을 붙힌 Class를 생성하여 Bean들을 정의할 수 있습니다.
다시 말해 @Controller, @Service처럼 하나의 Class를 Bean으로 생성할 수 있지만 @Configuration이 붙은 Class에서는 여러개의 객체를 Bean으로 등록할 수 있습니다. </p>
<p>예를 들어 특정 객체들을 Bean으로 생성하여 IoC 컨테이너에서 Singleton 객체로 사용하고 싶은 경우를 보겠습니다.</p>
<pre><code class="language-java">@Configuration
public class SpringConfig {

    @Bean
    public ObjectMapper objectMapper() {
        return new ObjectMapper();    
    }

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

}</code></pre>
<p>위와 같이 개발자가 특정 객체를 Bean으로 지정해서 사용할 수 있습니다.</p>
<hr>
<h3 id="di-dependency-injection">DI (Dependency Injection)</h3>
<p>DI는 의존성 주입이라는 뜻 입니다. 위에서 IoC에 등록한 Bean에게 또 다른 Bean을 주입 받아 사용하는 것을 의미 합니다. 의존성을 주입하는 방법에는 3가지 방법이 있습니다.</p>
<h4 id="1-생성자-주입">1. 생성자 주입</h4>
<p>생성자 주입은 말 그대로 생성자를 통해서 의존성을 주입 받는 것입니다. 주입 받을 객체를 IoC로부터 Parameter로 전달 받아서 의존성을 부여 받을 객체에게 주입하는 방식입니다.</p>
<pre><code class="language-java">@Controller
public class SpringController {
    private final SpringService springService;

    public SpringController(SpringService springService) {
        this.springService = springService;
    }
}</code></pre>
<p>생성자 주입은 Spring Reference에서 가장 권장하는 방법입니다. 앞에 final 타입을 붙이는 이유는 객체의 불변성을 뜻하고 Class 내부에서 의존성 주입받은 객체를 수정하는 문제를 방지할 수 있습니다.</p>
<p>생성자 주입을 할 경우, 객체와 객체간의 순환 참조를 방지할 수 있습니다. SpringService에서도 SpringController를 의존성 주입을 하게되면 컴파일시 오류를 발견하게 되고 Server가 실행되지 않습니다.</p>
<h4 id="2-autowired-주입">2. @Autowired 주입</h4>
<p>@Autowired 주입은 어노테이션을 이용하여 쉽게 의존성을 주입하는 방법입니다. </p>
<pre><code class="language-java">@Controller
public class SpringController {

    @Autowired
    private SpringService springService;

}</code></pre>
<p>@Autowired 주입은 생성자 주입보다는 소스 코드도 줄어들고 어노테이션만 붙이면 의존성을 주입받을 수 있습니다. </p>
<p>하지만 위에서 생성자 주입시 말한 final 레퍼런스타입을 지정하지 못하여 불변성이 깨지게 되고,
순환 참조가 발생되어도 컴파일시 오류를 발견하지 않은 채로 서버가 실행되는 단점이 있습니다.</p>
<h4 id="2-setter-주입">2. Setter 주입</h4>
<p>Setter주입은 객체의 생성자 호출 또는 팩토리 메서드를 호출을 통해서 객체의 의존성을 주입하는 방법입니다.</p>
<pre><code class="language-java">@Controller
public class SpringController {

    private SpringService springService;    

    public void setSpringController(SpringService springService) {
        this.springService = springService;
    }

}</code></pre>
<p>Setter 주입같은 경우는 특정 상황에 따라 사용하기 좋을 것 같습니다. 단점으로는 setter를 통해 주입하지 않아도 Controller 객체가 생성되기 때문에 주입하려는 대상이 setter로 인해 주입되지 않은 상태라면 Service 호출 시 NullpointException이 발생합니다. </p>
<p>그래서 Setter는 사용하려는 모든 시점에 Null 검사를 하여 사용해야 하는 번거로움이 있습니다. </p>
<hr>
<h4 id="정리하자면-di의-3가지-의존성-주입-방법-중-spring-reference에서도-권장하고-있는-생성자-주입을-사용하는-것이-가장-바람직하고-코드-품질이나-유지보수-면에서도-좋은-방법이-될-것-같네요">정리하자면 DI의 3가지 의존성 주입 방법 중 Spring Reference에서도 권장하고 있는 생성자 주입을 사용하는 것이 가장 바람직하고 코드 품질이나 유지보수 면에서도 좋은 방법이 될 것 같네요!</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring bean의 Scope]]></title>
            <link>https://velog.io/@s_chuli/Spring-bean%EC%9D%98-Scope</link>
            <guid>https://velog.io/@s_chuli/Spring-bean%EC%9D%98-Scope</guid>
            <pubDate>Mon, 08 Aug 2022 14:37:59 GMT</pubDate>
            <description><![CDATA[<h3 id="1-spring-bean-이란">1. Spring Bean 이란?</h3>
<blockquote>
<p>스프링 IoC(Inversion of Control) Container에 의해서 객체가 관리되고 애플리케이션의 핵심을 이루는 객체들을 Spring Bean이라고 한다. Bean은 Spring Container에 의해서 인스턴스화되어 조립되고 관리된다.</p>
</blockquote>
<hr>
<h3 id="2-bean-scope-이란">2. Bean Scope 이란?</h3>
<blockquote>
<p>Scope의 뜻대로 빈이 존재할 수 있는 범위를 말한다. 스프링 Bean은 기본 Scope으로 Singleton Scope가 적용된다.</p>
</blockquote>
<hr>
<h3 id="3-spring-scope의-종류">3. Spring Scope의 종류</h3>
<ul>
<li>singleton<ul>
<li>IoC 컨테이너에 하나의 객체만 생성되어 공유하는 디자인 패턴</li>
<li>해당 bean에 대한 요청이 있으면 생성된 하나의 인스턴스를 반환한다.</li>
<li>컨테이너가 종료되면 bean도 제거된다.</li>
</ul>
</li>
<li>prototype<ul>
<li>prototype 범위가 있는 bean은 컨테이너에서 요청할 때마다 다른 인스턴스를 반환한다. bean 정의에서 값 prototype을 “@Scope(prototype)” 어노테이션을 설정하여 정의한다.</li>
</ul>
</li>
<li>request<ul>
<li>HTTP 요청이 들어오고 나갈 때 까지 유지되는 scope, 각 HTTP 요청마다 인스턴스를 생성한다.</li>
</ul>
</li>
<li>session<ul>
<li>session이 생성되고 종료될 때 까지 유지되는 scope</li>
</ul>
</li>
<li>application<ul>
<li>web의 servlet context와 같은 범위로 유지되는 scope</li>
</ul>
</li>
</ul>
<hr>
<h3 id="singleton-scope-사용-시-주의할-점">Singleton Scope 사용 시 주의할 점.</h3>
<p>Spring Scope 경우 defualt로 singleton 전략을 사용하기 때문에 해당 Bean에 대한 요청을 하나의 인스턴스로 공유하는 부분을 항상 생각하며, 절대로 bean 자체에 필드를 생성하여 데이터를 공유하거나 요청마다의 값을 지정하는 행위는 하지 않아야 한다. 각 Thread 마다의 데이터 공유가 필요시에는 ThreadLocal또는 Parameter을 사용하여 값을 반환하도록 하는 것이 올바르게 Singleton 패턴을 사용하는 것이라고 생각한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 가운데 글자 가져오기]]></title>
            <link>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B0%80%EC%9A%B4%EB%8D%B0-%EA%B8%80%EC%9E%90-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0</link>
            <guid>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B0%80%EC%9A%B4%EB%8D%B0-%EA%B8%80%EC%9E%90-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0</guid>
            <pubDate>Tue, 09 Mar 2021 13:07:18 GMT</pubDate>
            <description><![CDATA[<p><strong>문제설명</strong>
단어 s의 가운데 글자를 반환하는 함수, solution을 만들어 보세요. 단어의 길이가 짝수라면 가운데 두글자를 반환하면 됩니다.</p>
<p><strong>재한사항</strong></p>
<ul>
<li>s는 길이가 1 이상, 100이하인 스트링입니다.</li>
</ul>
<p><strong>작성 코드</strong></p>
<pre><code class="language-javascript">const solution = (s) =&gt; {    
  const mok = s.length / 2;  
  return s.length % 2 === 0 ? s.substring(mok+1, mok-1) : s.substring(mok, mok+1);       
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TypeScript] TypeScript로 블록체인 만들기 - 노마드 코더]]></title>
            <link>https://velog.io/@s_chuli/TypeScript-TypeScript%EB%A1%9C-%EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EB%85%B8%EB%A7%88%EB%93%9C-%EC%BD%94%EB%8D%94</link>
            <guid>https://velog.io/@s_chuli/TypeScript-TypeScript%EB%A1%9C-%EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EB%85%B8%EB%A7%88%EB%93%9C-%EC%BD%94%EB%8D%94</guid>
            <pubDate>Fri, 26 Feb 2021 16:01:52 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>노마드 코더의 니꼴라스 강좌를 따라하며 TypeScript를 활용해 간단한 블록체인 구현하기. 나의 강의 목적은 TypeScript 사용 해보는 것.
블록체인의 개념은 깊게 이해하지 못 함.</p>
</blockquote>
<p><strong>🌙 프로젝트 설정</strong></p>
<ol>
<li>프로젝트 생성 아래 명령으로 프로젝트 셋팅하기.</li>
<li>TypeScript 설치하기.</li>
</ol>
<blockquote>
<ul>
<li>yarn init  </li>
</ul>
</blockquote>
<ul>
<li>yarn global add typescript</li>
</ul>
<p><strong>Config 파일 설정</strong></p>
<ol>
<li>tsconfig.json : 프로젝트 생성 후 tsconfig.json 타입스크립트 설정파일을 생성한다.
타입 스크립트 컴파일 옵션을 설정해서 자동으로 컴파일 되게 설정했다.<pre><code class="language-javascript">{
 &quot;compilerOptions&quot;: {
     &quot;module&quot;: &quot;commonjs&quot;,
     &quot;target&quot;: &quot;ES6&quot;,
     &quot;sourceMap&quot;: true,
     &quot;outDir&quot;: &quot;dist&quot;
 },
 &quot;include&quot;: [&quot;src/**/*&quot;],
 &quot;exclude&quot;: [&quot;node_modules&quot;]
} </code></pre>
</li>
<li>package.json : 타입스크립트.ts 파일을 컴파일 하게 되면 자바스크립트 파일이 자동으로 생성되는데 start를 지정해 컴파일이 성공 했을 때 자바스크립트 파일이 생성되는 위치를 지정해준다.<pre><code class="language-javascript">&quot;scripts&quot;: {
 &quot;start&quot;: &quot;tsc-watch --onSuccess \&quot; node dist/index.js \&quot; &quot;
}</code></pre>
</li>
</ol>
<p><strong>🤌🏼 코드를 작상하기 전..</strong></p>
<blockquote>
<ul>
<li>블록의 Hash 값을 생성하기 위해  &quot;crypto-js&quot; 라이브러리를 설치한다.
crypto-js 라이브러리는 문자들을 결합시켜준다.</li>
</ul>
</blockquote>
<ul>
<li>블록체인은 말 그대로 블록들을 체인으로 연결하여 여러개의 블록을 가진 구조를 말하는 것이다. 이 프로젝트에서는 하나의 블록을 Default로 생성 하여 그 블록을 중심으로 여러개의 블록을 생성하여 연결 짓는 것이 목적이다.</li>
</ul>
<p><strong>index.ts</strong></p>
<pre><code class="language-typescript">import * as CryptoJS from &#39;crypto-js&#39;; 

class Block {
    static calculateBlockHash = (index: number, previousHash:string, data: string, timestamp: number):string =&gt; {
      /* 
          CryptoJS 라이브러리는 문자들을 결합해 하나의 문자열로 만든다.          
      */
        return CryptoJS.SHA256(index + previousHash + data + timestamp).toString();
    }

    static validateStructure = (aBlock : Block) =&gt;
        typeof aBlock.index === &quot;number&quot; &amp;&amp;
        typeof aBlock.hash === &quot;string&quot; &amp;&amp;
        typeof aBlock.previousHash === &quot;string&quot; &amp;&amp;
        typeof aBlock.data === &quot;string&quot; &amp;&amp;
        typeof aBlock.timestamp === &quot;number&quot;;          

    public index : number;
    public hash : string;
    public previousHash : string;
    public data : string;
    public timestamp : number;    

    constructor(index: number, hash: string, previousHash: string, data: string, timestamp: number) {
        this.index = index;
        this.hash = hash;
        this.previousHash = previousHash;
        this.data = data;
        this.timestamp = timestamp;
    }
}

/* Default 블록 생성. */
const genesisBlock : Block = new Block(0, &quot;20202020&quot;, &quot;&quot;, &quot;Hello&quot;, 123456);

/* 전체 블록들을 담을 배열. */
let blockchain : Block[] = [genesisBlock];

/* 현재 생성된 블록들을 가져오는 함수 */
const getBlockchain = () :Block[] =&gt; blockchain;
/* 현재 블록들 중에 가장 최근에 생성된 블록 가져오는 함수 */
const getLatestBlock = () : Block =&gt; blockchain[blockchain.length - 1];
/* 새로운 블록 생성시간 만들기 함수. */
const getNewTimeStamp = () : number =&gt; Math.round(new Date().getTime() / 1000);

/* 
    - 블록을 생성하는 함수.
    - Block 클래스의 내장 함수인 calculateBlockHash를 사용하여
    새로운 블록을 생성할 수 있게 Param을 전달한다. 
    - 생성된 Block을 기존 블록들을 담는 List에 Push

*/
const createNewBlock = (data: string): Block =&gt; {
    const previousBlock: Block = getLatestBlock();
    const newIndex: number = previousBlock.index + 1;
    const newTimeStamp: number = getNewTimeStamp();
    const newHash: string = Block.calculateBlockHash(
        newIndex, 
        previousBlock.hash, 
        data, 
        newTimeStamp
    );
    const newBlock: Block = new Block(
        newIndex,
        newHash,
        previousBlock.hash,
        data,
        newTimeStamp
    );

    addBlock(newBlock);
    return newBlock;
}

/*
    생성된 블록을 받아 해쉬를 생성한다.
*/
const getHashForBlock = (aBlock: Block) : string =&gt; 
    Block.calculateBlockHash(aBlock.index, aBlock.previousHash, aBlock.data, aBlock.timestamp);

/*
    생성된 블록과 최근의 블록 유효성 검사.
*/
const isBlockValid = (candidateBlock : Block, previousBlock : Block) : boolean =&gt; {
      /* 생성된 블록이 Block 클래스의 타입과 일치하지 않을 경우 */
    if(!Block.validateStructure(candidateBlock)) {
        return false;
    }
      /* 최근의 블록의 index와 생성된 블럭의 index + 1 값과 생성된 index 값이 같지 않을 경우 */
    else if(previousBlock.index + 1 !== candidateBlock.index) {
        return false;
    }
  /* 
      최근의 블록의 해쉬값과 생성된 이전의 해쉬값이 일치 하지 않은 경우.
  */
    else if(previousBlock.hash !== candidateBlock.previousHash) {
        return false;
    }
  /*
      생성된 해쉬 값이 일치하지 않은 경우
  */
    else if(getHashForBlock(candidateBlock) !== candidateBlock.hash) {
        return false;
    } else {
        return true;
    }
}

/* 유효성 검사 결과가 True일 경우 block 리스트에 추가. */
const addBlock = (candidateBlock: Block) : void =&gt; {
    if(isBlockValid(candidateBlock, getLatestBlock())) {
        blockchain.push(candidateBlock);
    }
}

createNewBlock(&quot;second block&quot;);
createNewBlock(&quot;third block&quot;);
createNewBlock(&quot;fourth block&quot;);

console.log(getBlockchain());

export {};</code></pre>
<p>함수 또는 객체, 요소 하나하나의 Type을 지정해주기 때문에 결과의 Type을 미리 예측할 수 있다는 점이 아주 매력적인 TypeScript이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React-Native] 에러일기 - main.jsbundle ]]></title>
            <link>https://velog.io/@s_chuli/React-Native-%EC%97%90%EB%9F%AC%EC%9D%BC%EA%B8%B0-main.jsbundle</link>
            <guid>https://velog.io/@s_chuli/React-Native-%EC%97%90%EB%9F%AC%EC%9D%BC%EA%B8%B0-main.jsbundle</guid>
            <pubDate>Wed, 24 Feb 2021 05:35:26 GMT</pubDate>
            <description><![CDATA[<p>React Native 프로젝트를 생성 후 Xcode로 프로젝트를 열었을 때 main.jsbundle 파일이 없어서 프로젝트 실행이 안 되는 경우가 종종 발생한다..</p>
<p>처음에 개발했을 때 이 문제로 정말 고생했던 기억이 있다..</p>
<p><strong>해결방법</strong>
우선 package.json 파일을 열고 sciprts 부분에 작성한다.</p>
<blockquote>
<p>&quot;build:ios&quot;: &quot;react-native bundle --entry-file=&#39;index.js&#39; --bundle-output=&#39;./ios/main.jsbundle&#39; --dev=false --platform=&#39;ios&#39;&quot;,</p>
</blockquote>
<p>그 후</p>
<blockquote>
<p>yarn build:ios 또는 npm run build:ios</p>
</blockquote>
<p>보통 이 에러가 났을 때 보면 Main.jsbundle 파일이 없어서 나는 에러였다.. 그러니 Xcode를 열어서 파일이 빨간색인지 확인하자
<img src="https://images.velog.io/images/s_chuli/post/02bf9bd3-ff39-4497-9e38-2ec93e1d94d7/image.png" alt=""></p>
<p>🤘🏼 추가로 2021년 이후로 프로젝트를 실행해도 계속 오류가 날 경우엔 Podfile를 수정.</p>
<p><img src="https://images.velog.io/images/s_chuli/post/e25c21d8-2665-4ec9-870a-8653791cfff8/image.png" alt=""></p>
<p>이 부분을 주석 걸거나 =&gt;  ({&#39;Flipper&#39; =&gt; &#39;0.74.0&#39;}) 이 부분을 수정하면 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 같은 숫자는 싫어]]></title>
            <link>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B0%99%EC%9D%80-%EC%88%AB%EC%9E%90%EB%8A%94-%EC%8B%AB%EC%96%B4</link>
            <guid>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B0%99%EC%9D%80-%EC%88%AB%EC%9E%90%EB%8A%94-%EC%8B%AB%EC%96%B4</guid>
            <pubDate>Tue, 23 Feb 2021 15:01:54 GMT</pubDate>
            <description><![CDATA[<p><strong>문제 설명</strong></p>
<p>배열 arr가 주어집니다. 배열 arr의 각 원소는 숫자 0부터 9까지로 이루어져 있습니다. 이때, 배열 arr에서 연속적으로 나타나는 숫자는 하나만 남기고 전부 제거하려고 합니다. 단, 제거된 후 남은 수들을 반환할 때는 배열 arr의 원소들의 순서를 유지해야 합니다. 예를 들면,</p>
<p>arr = [1, 1, 3, 3, 0, 1, 1] 이면 [1, 3, 0, 1] 을 return 합니다.
arr = [4, 4, 4, 3, 3] 이면 [4, 3] 을 return 합니다.
배열 arr에서 연속적으로 나타나는 숫자는 제거하고 남은 수들을 return 하는 solution 함수를 완성해 주세요.</p>
<p><strong>제한 사항</strong></p>
<ul>
<li>배열 arr의 크기 : 1,000,000 이하의 자연수</li>
<li>배열 arr의 원소의 크기 : 0보다 크거나 같고 9보다 작거나 같은 정수</li>
</ul>
<p><strong>작성 코드</strong></p>
<pre><code class="language-javascript">const solution = (arr) =&gt; {

    const result = arr.filter((item, index) =&gt; {
        return item !== arr[index-1]
    });

    return result;    
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 2016년]]></title>
            <link>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-2016%EB%85%84</link>
            <guid>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-2016%EB%85%84</guid>
            <pubDate>Tue, 23 Feb 2021 14:27:36 GMT</pubDate>
            <description><![CDATA[<p><strong>문제 설명</strong>
2016년 1월 1일은 금요일입니다. 2016년 a월 b일은 무슨 요일일까요? 두 수 a ,b를 입력받아 2016년 a월 b일이 무슨 요일인지 리턴하는 함수, solution을 완성하세요. 요일의 이름은 일요일부터 토요일까지 각각 SUN,MON,TUE,WED,THU,FRI,SAT</p>
<p>입니다. 예를 들어 a=5, b=24라면 5월 24일은 화요일이므로 문자열 TUE를 반환하세요.</p>
<p><strong>제한 조건</strong></p>
<ul>
<li>2016년은 윤년입니다.</li>
<li>2016년 a월 b일은 실제로 있는 날입니다. (13월 26일이나 2월 45일같은 날짜는 주어지지 않습니다)</li>
</ul>
<p><strong>작성 코드</strong></p>
<pre><code class="language-javascript">const solution =(a, b) =&gt; {
    const weekend = [&quot;SUN&quot;, &quot;MON&quot;, &quot;TUE&quot;, &quot;WED&quot;, &quot;THU&quot;, &quot;FRI&quot;, &quot;SAT&quot;];    

    const date = &quot;2016&quot;+ &quot;-&quot; + a + &quot;-&quot; + b;

    const today = new Date(date).getDay();
    const result = weekend[today];

    return result;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] K번째 수]]></title>
            <link>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-K%EB%B2%88%EC%A7%B8-%EC%88%98</link>
            <guid>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-K%EB%B2%88%EC%A7%B8-%EC%88%98</guid>
            <pubDate>Sat, 20 Feb 2021 14:40:39 GMT</pubDate>
            <description><![CDATA[<p><strong>문제설명</strong>
배열 array의 i번째 숫자부터 j번째 숫자까지 자르고 정렬했을 때, k번째에 있는 수를 구하려 합니다.</p>
<p>예를 들어 array가 [1, 5, 2, 6, 3, 7, 4], i = 2, j = 5, k = 3이라면</p>
<pre><code> 1. array의 2번째부터 5번째까지 자르면 [5, 2, 6, 3]입니다.
 2. 1에서 나온 배열을 정렬하면 [2, 3, 5, 6]입니다.
 3. 2에서 나온 배열의 3번째 숫자는 5입니다.</code></pre><p>배열 array, [i, j, k]를 원소로 가진 2차원 배열 commands가 매개변수로 주어질 때, commands의 모든 원소에 대해 앞서 설명한 연산을 적용했을 때 나온 결과를 배열에 담아 return 하도록 solution 함수를 작성해주세요.</p>
<p><strong>제한사항</strong></p>
<ul>
<li>array의 길이는 1 이상 100 이하입니다.</li>
<li>array의 각 원소는 1 이상 100 이하입니다.</li>
<li>commands의 길이는 1 이상 50 이하입니다.</li>
<li>commands의 각 원소는 길이가 3입니다.</li>
</ul>
<p><strong>입출력 예</strong>
<img src="https://images.velog.io/images/s_chuli/post/416a4868-c4ac-472a-931a-b258ae398a0b/image.png" alt=""></p>
<p><strong>작성 코드</strong></p>
<pre><code class="language-javascript">/*
    [1, 5, 2, 6, 3, 7, 4], i = 2, j = 5, k = 3

    i = 시작
    j = 끝
    k = 원소 위치

    3개의 array[i,j,k] (리스트)를 제공.

    return [5, 6, 3] 총 3개의 원소 값을 구하는 거임.

    ex)
    1단계 : 2에서 5번째까지 배열을 자른다. [5, 2, 6, 3]
    2단계 : 1단계에서 자른 배열을 정렬한다. [2, 3, 5, 6]
    3단계 : 2단계에서 나온 배열의 3번째 요소를 저장한다.
*/


const solution = (array, commands) =&gt; {
    const result = [];    

    for(const idx of commands) {
        const i = idx[0] - 1;
        const j = idx[1]; 
        const k = idx[2] - 1;

        /* 1단계 */
        const sliceList = array.slice(i, j);

        /* 2단계 */
        sliceList.sort((a, b) =&gt; {
            return a - b;
        });

        /* 3단계 */
        result.push(sliceList[k]);        
    }

    return result;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 체육복 ]]></title>
            <link>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%B2%B4%EC%9C%A1%EB%B3%B5</link>
            <guid>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%B2%B4%EC%9C%A1%EB%B3%B5</guid>
            <pubDate>Wed, 17 Feb 2021 15:48:48 GMT</pubDate>
            <description><![CDATA[<p><strong>문제 설명</strong>
점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번호의 학생이나 바로 뒷번호의 학생에게만 체육복을 빌려줄 수 있습니다. 예를 들어, 4번 학생은 3번 학생이나 5번 학생에게만 체육복을 빌려줄 수 있습니다. 체육복이 없으면 수업을 들을 수 없기 때문에 체육복을 적절히 빌려 최대한 많은 학생이 체육수업을 들어야 합니다.</p>
<p>전체 학생의 수 n, 체육복을 도난당한 학생들의 번호가 담긴 배열 lost, 여벌의 체육복을 가져온 학생들의 번호가 담긴 배열 reserve가 매개변수로 주어질 때, 체육수업을 들을 수 있는 학생의 최댓값을 return 하도록 solution 함수를 작성해주세요.</p>
<p><strong>제한 사항</strong></p>
<ul>
<li>전체 학생의 수는 2명 이상 30명 이하입니다.</li>
<li>체육복을 도난당한 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.</li>
<li>여벌의 체육복을 가져온 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.</li>
<li>여벌 체육복이 있는 학생만 다른 학생에게 체육복을 빌려줄 수 있습니다. </li>
<li>여벌 체육복을 가져온 학생이 체육복을 도난당했을 수 있습니다. 이때 이 학생은 체육복을 하나만 도난당했다고 가정하며, 남은 체육복이 하나이기에 다른 학생에게는 체육복을 빌려줄 수 없습니다.</li>
</ul>
<p><strong>입출력 예</strong>
 <img src="https://images.velog.io/images/s_chuli/post/9c131bc6-a391-447a-bc51-b23c2a34f0cc/image.png" alt=""></p>
<p> <strong>작성 코드</strong></p>
<pre><code class="language-javascript">const solution = (n, lost, reserve) =&gt; {        

    const filterLost = lost.filter((item) =&gt; {
        if(!reserve.includes(item)) {
            return item;
        }
    });
    const filterReserve = reserve.filter((item) =&gt; {
        if(!lost.includes(item)) {
            return item;
        }
    });    

    for(const l of filterReserve) {
        const first = l - 1;
        const last = l + 1;        

        if(filterLost.includes(first)) {
            const index = filterLost.indexOf(first);
            filterLost.splice(index, 1);
        }
        else if(filterLost.includes(last)) {
            const index = filterLost.indexOf(last);
            filterLost.splice(index, 1);
        }              
    }
    n = n - filterLost.length;

    return n;
}</code></pre>
<p><strong>정리</strong>
주의해야 할 점은 제한사항에 보면 여벌을 가지고 있는 학생이 도난을 당할 수 있다고 했다. 그리고 그 학생은 여벌을 빌려줄 수 없다고 되어 있어서 이 학생은 여벌이 있는 학생이었지만 도난을 당했기 때문에 lost 배열에도 포함되어 있다.
그래서 첫번 째로 lost배열과 reserve 배열에 중복되는 값을 제거 filter 함수로 걸러냈다.</p>
<p>두번 째로 여벌이 있는 학생들의 앞 번호와 뒷 번호를 구해서 그 번호가 체육복이 없는 학생들이 포함되는 번호이면은 그 lost 학생에게 체육복을 주는 방식으로 문제를 해결했다.</p>
<p>체육복이 없는 학생들 중 앞 번호에 해당하는 학생일 경우 그 학생의 index를 찾아서 splice()를 써서 그 index에 해당하는 요소를 삭제시켰다.
뒷 번호도 마찬가지이다.
splice()를 사용하면 그 삭제된 요소를 제외한 나머지 요소들이 반환된다.</p>
<p>세번 째로는 도난 당한 친구들이 담긴 lost 배열의 길이를 구해 전체 학생 수 에서 빼주었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 신규 아이디 추천]]></title>
            <link>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%8B%A0%EA%B7%9C-%EC%95%84%EC%9D%B4%EB%94%94-%EC%B6%94%EC%B2%9C</link>
            <guid>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%8B%A0%EA%B7%9C-%EC%95%84%EC%9D%B4%EB%94%94-%EC%B6%94%EC%B2%9C</guid>
            <pubDate>Mon, 15 Feb 2021 14:47:11 GMT</pubDate>
            <description><![CDATA[<p><strong>문제설명</strong>
신규 유저가 입력한 아이디를 나타내는 new_id가 매개변수로 주어질 때, 네오가 설계한 7단계의 처리 과정을 거친 후의 추천 아이디를 return 하도록 solution 함수를 완성해 주세요.</p>
<p><strong>제한사항</strong>
new_id는 길이 1 이상 1,000 이하인 문자열입니다.
new_id는 알파벳 대문자, 알파벳 소문자, 숫자, 특수문자로 구성되어 있습니다.
new_id에 나타날 수 있는 특수문자는 -_.~!@#$%^&amp;*()=+[{]}:?,&lt;&gt;/ 로 한정됩니다.</p>
<p><strong>입출력 예</strong>
<img src="https://images.velog.io/images/s_chuli/post/f8a5e6c5-70b2-419f-9135-7475b3bcc32e/image.png" alt=""></p>
<p><strong>문제 조건</strong>
1단계 new id의 모든 대문자를 대응되는 소문자로 치환합니다.
2단계 new id에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거합니다.
3단계 new id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.
4단계 new id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.
5단계 new id가 빈 문자열이라면, new_id에 &quot;a&quot;를 대입합니다.
6단계 new id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다.
     만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.
7단계 new_id의 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다</p>
<p><strong>작성 코드</strong></p>
<pre><code class="language-javascript">function solution(new_id) {   

    let id_validation = new_id.toLowerCase()
                    .replace(/[^\a-z0-9-_.]/g,&#39;&#39;)
                    .replace(/\.+/g, &#39;.&#39;)
                    .replace(/^\.+|\.$/g, &#39;&#39;);

    if(id_validation.length === 0) {
        id_validation = &quot;a&quot;;
    }

    if(id_validation.length &gt; 15) {
        id_validation = id_validation.substring(0, 15).replace(/\.$/g, &#39;&#39;);
    }    

    let lastString = id_validation.substring(id_validation.length - 1);
    if(id_validation.length &lt;= 2) {
        for(let i=id_validation.length; i &lt; 3; i++) {
            id_validation = id_validation + lastString;
        }
    }

    return id_validation;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 모의고사]]></title>
            <link>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%AA%A8%EC%9D%98%EA%B3%A0%EC%82%AC</link>
            <guid>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%AA%A8%EC%9D%98%EA%B3%A0%EC%82%AC</guid>
            <pubDate>Thu, 11 Feb 2021 08:09:33 GMT</pubDate>
            <description><![CDATA[<p><strong>문제 설명</strong>
수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 1번 문제부터 마지막 문제까지 다음과 같이 찍습니다.</p>
<p>1번 수포자가 찍는 방식: 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ...
2번 수포자가 찍는 방식: 2, 1, 2, 3, 2, 4, 2, 5, 2, 1, 2, 3, 2, 4, 2, 5, ...
3번 수포자가 찍는 방식: 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, ...</p>
<p>1번 문제부터 마지막 문제까지의 정답이 순서대로 들은 배열 answers가 주어졌을 때, 가장 많은 문제를 맞힌 사람이 누구인지 배열에 담아 return 하도록 solution 함수를 작성해주세요.</p>
<p><strong>제한 조건</strong></p>
<ul>
<li>시험은 최대 10,000 문제로 구성되어있습니다. </li>
<li>문제의 정답은 1, 2, 3, 4, 5중 하나입니다.</li>
<li>가장 높은 점수를 받은 사람이 여럿일 경우, return하는 값을 오름차순 정렬해주세요.</li>
</ul>
<p><strong>입출력 예</strong>
<img src="https://images.velog.io/images/s_chuli/post/5713d9e2-ad25-433e-a637-4d564a376f00/image.png" alt=""></p>
<p><strong>작성 코드</strong></p>
<pre><code class="language-javascript">const solution = (answers) =&gt; {
    const losers = [
        [1, 2, 3, 4, 5],
        [2, 1, 2, 3, 2, 4, 2, 5],
        [3, 3, 1, 1, 2, 2, 4, 4, 5, 5]
    ];
    const maxNumbers = []; /* 루저들의(수포자) 문제 맞힌 수*/

    /* 맞힌 문제 카운트하기 */
    for(const loser of losers) {
        maxNumbers.push(answers.reduce((acc, cur, idx) =&gt; {
            cur === loser[idx % loser.length] ? acc++ : acc;
            return acc;
        }, 0));
    }       

    /* 제일 많이 맞힌 루저 찾기 */            
    const result = maxNumbers.reduce((acc, cur, idx) =&gt; {           
        cur === Math.max(...maxNumbers) ? acc.push(idx+1) : acc; 
        return acc;
    }, []); 

    return result;
}</code></pre>
<p><strong>정리</strong>
reduce(accumulator, currentValue, index, array)</p>
<p>accumulator - 배열의 누적 값
currentValue - 현재 값
index - 현재 배열의 인덱스
array - 배열 원본</p>
<p>reduce는 두 번째로 인자로 현재 인덱스에 해당하는 객체를 반환해주기 때문에 정답들의 순서대로 반환되는 수포자들의 값들과 비교하여 accumulator에 카운트하게 했다.</p>
<p><strong>loser[idx % loser.length]</strong> ..?
수포자1의 길이가 5이고 정답 리스트의 인덱스를 0이라고 해보자 그러면 나머지로 0이 나온다. 0 % 5 = 0 이니까..
그럼 정답의 개수가 20개일 경우 20번 반복인데.. 수포자1의 길이는 고정이니까
0<del>19 % 5 = 0</del>4..  </p>
<p>수포자1의 객체가 [1,2,3,4,5] 이므로
1,2,3,4,5를 총 4번 반복해서 정답과 비교할거임</p>
<p>이걸 하고 나면 가장 많이 맞힌 수포자를 구하는건 쉽다.
카운트된 수포자들을 reduce 함수로 가장 많이 맞힌 수포자를 찾고
첫 번째 파라미터를 list타입으로 현재 수포자의 index + 1해서 return만 해주면 끝. </p>
<p>일하면서 reduce 써보려 해도 어렵고 귀찮아서 안 쓸려했는데 이렇게 쓸줄은 몰랐다,, filter 안 쓰고 reduce로 다 커버 가능할 듯 싶다 ㅎㅎ 개꿀띵🤪</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 두 개 뽑아서 더하기]]></title>
            <link>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%91%90-%EA%B0%9C-%EB%BD%91%EC%95%84%EC%84%9C-%EB%8D%94%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%91%90-%EA%B0%9C-%EB%BD%91%EC%95%84%EC%84%9C-%EB%8D%94%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 11 Feb 2021 05:49:51 GMT</pubDate>
            <description><![CDATA[<p><strong>문제 설명</strong>
정수 배열 numbers가 주어집니다. numbers에서 서로 다른 인덱스에 있는 두 개의 수를 뽑아 더해서 만들 수 있는 모든 수를 배열에 오름차순으로 담아 return 하도록 solution 함수를 완성해주세요.</p>
<p><strong>제한 사항</strong></p>
<ul>
<li>numbers의 길이는 2 이상 100 이하입니다.<ul>
<li>numbers의 모든 수는 0 이상 100 이하입니다.</li>
</ul>
</li>
</ul>
<p><strong>입출력 예</strong>
<img src="https://images.velog.io/images/s_chuli/post/abc05295-0200-4be9-88db-82f4ea2937a2/image.png" alt=""></p>
<p><strong>작성 코드</strong></p>
<pre><code class="language-javascript">const solution = (numbers) =&gt;  {
    let result = [];

    for(let i=0; i &lt; numbers.length; i++) {
        for(let j=i+1; j &lt; numbers.length; j++) {
            const number = numbers[i] + numbers[j];

            result.push(number);
        }     
    }
    const uniqueNumbers = [...new Set(result)];

    uniqueNumbers.sort((a, b) =&gt; {
        return a-b;
    })

    return uniqueNumbers;    
}</code></pre>
<p><strong>정리</strong>
result 배열의 중복체크를 indexOf를 사용할 수도 있지만 ...new Set() 함수를 사용하여 현재 배열의 중복된 값을 제거 후 새로운 배열을 반환받도록 했다. 코드가 2줄이나 줄었음 ㅎㅎ 개꿀</p>
<p>sort 정렬은 자바스크립트 MDN 문서를 참고했다. 내림차순일 경우 a, b 인자의 순서를 바꾸어서 리턴하면 됨. ex) return b-a</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 완주하지 못한 선수]]></title>
            <link>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%99%84%EC%A3%BC%ED%95%98%EC%A7%80-%EB%AA%BB%ED%95%9C-%EC%84%A0%EC%88%98</link>
            <guid>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%99%84%EC%A3%BC%ED%95%98%EC%A7%80-%EB%AA%BB%ED%95%9C-%EC%84%A0%EC%88%98</guid>
            <pubDate>Tue, 09 Feb 2021 15:11:33 GMT</pubDate>
            <description><![CDATA[<p><strong>문제설명</strong></p>
<p>수많은 마라톤 선수들이 마라톤에 참여하였습니다. 단 한 명의 선수를 제외하고는 모든 선수가 마라톤을 완주하였습니다.
마라톤에 참여한 선수들의 이름이 담긴 배열 participant와 완주한 선수들의 이름이 담긴 배열 completion이 주어질 때, 완주하지 못한 선수의 이름을 return 하도록 solution 함수를 작성해주세요.</p>
<p><strong>제한사항</strong></p>
<ul>
<li>마라톤 경기에 참여한 선수의 수는 1명 이상 100,000명 이하입니다.</li>
<li>completion의 길이는 participant의 길이보다 1 작습니다.</li>
<li>참가자의 이름은 1개 이상 20개 이하의 알파벳 소문자로 이루어져 있습니다.</li>
<li>참가자 중에는 동명이인이 있을 수 있습니다.</li>
</ul>
<p><strong>입출력 예</strong>
participant : [&quot;leo&quot;, &quot;kiki&quot;, &quot;eden&quot;]
completion : [&quot;marina&quot;, &quot;josipa&quot;, &quot;nikola&quot;, &quot;vinko&quot;, &quot;filipa&quot;]</p>
<p><strong>코드 예</strong></p>
<pre><code class="language-javascript">function solution(participant, completion) {    

    participant.sort();
    completion.sort();

    for(const idx in participant) {
        if(participant[idx] !== completion[idx]) {
            /* 
            조건이 단 한명의 선수를 제외하고 모두 완주이기 때문에
            한명이라도 걸리면 return해서 끝내자
            */
            return participant[idx];            
        }
    }


/*
    map : key, value로 이루어진 객체 반환.

    완주한 선수의 중복을 체크. 
*/

const solution = (participant,completion) =&gt; { 
  completion.map(name =&gt; completion[name] = (completion[name]|0)+1);

  return participant.find((name) =&gt; !completion[name]--); 
}; </code></pre>
<blockquote>
</blockquote>
<p><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/for...in">자바스크립트 for문 관련 공식 문서 &lt;&lt;</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 크레인 인형뽑기]]></title>
            <link>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%81%AC%EB%A0%88%EC%9D%B8-%EC%9D%B8%ED%98%95%EB%BD%91%EA%B8%B0</link>
            <guid>https://velog.io/@s_chuli/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%81%AC%EB%A0%88%EC%9D%B8-%EC%9D%B8%ED%98%95%EB%BD%91%EA%B8%B0</guid>
            <pubDate>Mon, 08 Feb 2021 14:56:55 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-javascript">function solution(board, moves) {
    let result = 0; //터트린 아이템 갯수.
    let box = [];  //아이템을 담을 바구니.        


    for(const move of moves) {
        for(let i=0; i &lt; board.length; i++) { /* board의 길이만큼 반복.. */
            /* 값이 0이 아닌 경우만 담자.. */
            if(board[i][move-1] !== 0) {                
                const selectItem = board[i][move-1];  //선택한 아이템..

                if(selectItem === box[box.length-1]) { //선택한 아이템과 바구니의 마지막으로 담긴 아이템이 같으면 파괴.
                    box.pop();                    
                    result += 2; //선택한 아이템과 파괴한 아이템 카운트 하기                     
                } else {
                    box.push(selectItem);
                }
                board[i][move-1] = 0; // 빈 배열로 초기화.
                break;                
            }
        }       
    }
    return result;
}</code></pre>
<p>pop() : 배열에서 마지막 요소를 제거하고 반환해준다.</p>
]]></description>
        </item>
    </channel>
</rss>