<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>기록의 습작</title>
        <link>https://velog.io/</link>
        <description>GyUL의 Backend 개발일기</description>
        <lastBuildDate>Mon, 15 May 2023 11:53:44 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>기록의 습작</title>
            <url>https://velog.velcdn.com/images/k-gn/profile/b46da911-e5f5-4588-ac6e-82b5c857230e/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. 기록의 습작. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/k-gn" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Github Action Gradle CI Issue (feat. Git Submodule)]]></title>
            <link>https://velog.io/@k-gn/Github-Action-CI-Issue-feat.-Git-Submodule</link>
            <guid>https://velog.io/@k-gn/Github-Action-CI-Issue-feat.-Git-Submodule</guid>
            <pubDate>Mon, 15 May 2023 11:53:44 GMT</pubDate>
            <description><![CDATA[<p>사이드 프로젝트 진행 중 만난 Github Action CI 이슈...</p>
<p>작성한 테스트 코드를 PR 에서 돌리고, 결과 리포트를 보여주기 위한 간단한 CI 였는데 이게 나를  괴롭힐 줄은 상상도 못했다.</p>
<p>다신 똑같은 이슈로 시간 보내지 않도록 처음부터 하나하나 정리해보자.</p>
<hr>
<ol>
<li>Gradlew Issue
<img src="https://velog.velcdn.com/images/k-gn/post/6aa12c79-9050-4751-b91c-ada6d7bde32d/image.png" alt=""></li>
</ol>
<p>처음으로 나를 당황시켰던 이슈였다.</p>
<pre><code>./gradlew clean test</code></pre><p>이 명령어가 그냥 동작 자체를 하지 않는 것이다.
하지만 이 문제는 크게 오래 걸리지 않았다. 
gradle-wrapper 관련 파일들에 무슨 문제가 있나 싶어 새로 갈아끼웠더니 바로 해결되었다.</p>
<hr>
<ol start="2">
<li>Test Failed
<img src="https://velog.velcdn.com/images/k-gn/post/4eb14c6f-c492-4585-9f0e-eeca9b1a7120/image.png" alt=""></li>
</ol>
<p>그 다음 나온 이슈는 ApiApplicationTests 클래스의 contextLoads() 가 계속 실패하였다.
단순히 저렇게만 나오니 뭐가 문젠지 모르겠어서</p>
<pre><code>./gradlew clean test -i</code></pre><p><strong>-i</strong> 옵션을 통해 로그를 같이 확인해보았다.</p>
<pre><code>Caused by:
        org.springframework.beans.factory.BeanCreationException: Error creating bean with name &#39;s3Config&#39;: Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder &#39;cloud.aws.credentials.accessKey&#39; in value &quot;${cloud.aws.credentials.accessKey}&quot;</code></pre><p>갑자기 등장한 S3Config 를 보고 멍하니 뇌정지가 찾아왔다...
전혀 예상하지 못한 친구의 등장으로 당황하긴 했지만 흠.. 설정 정보를 가지고 오지 못하는 것 같다.
Yml 에는 잘 설정되어 있구, Profile 설정도 잘 되어있는데 왜 설정 정보를 못가지고 오는걸까?</p>
<hr>
<ol start="3">
<li>Git Submodule</li>
</ol>
<p>현재 사이드 프로젝트에선 설정파일 관리를 Git Submodule 를 통해 하고 있다.
빌드과정에서 Git Submodule 의 Yml 파일들을 가져와 프로젝트를 실행시킨다.
로컬에선 분명 잘 가져오던 파일들이 CI가 돌 때 못 가져 오는건가? 싶어서 Git Submodule CI 와 관련된 내용들을 리서치 해보니 private repo를 clone 할 수 있는 GitHub Key를 추가해야 제대로 가져올 수 있다는 내용을 발견했다.</p>
<pre><code>- name: Checkout repo
  uses: actions/checkout@v3
    with:
      token: ${{ secrets.GITHUB_TOKEN }}
      submodules: true</code></pre><p>해당 설정을 추가해주니...
<img src="https://velog.velcdn.com/images/k-gn/post/583a7ba6-c02e-4fad-a080-29106f6c5ec1/image.png" alt=""></p>
<p>드디어 CI가 잘 동작하는 걸 확인할 수 있었다..!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[오브젝트]]></title>
            <link>https://velog.io/@k-gn/%EC%98%A4%EB%B8%8C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@k-gn/%EC%98%A4%EB%B8%8C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Sun, 02 Apr 2023 05:52:16 GMT</pubDate>
            <description><![CDATA[<p>최근에 조영호님의 객체지향의 사실과 오해라는 책을 너무 재미있게 읽어서 그 다음으로 읽을 책을 찾아보고 있었는데, 조영호님의 오브젝트라는 책을 주변에서 너무너무 추천해주길래 궁금해서 바로 구매해버렸다..!</p>
<p>책을 읽고 중요한 개념들만 간단히 정리해보려고 한다.</p>
<hr>
<ol>
<li><p><strong>실행중에 제대로 동작하더라도, 변경이 용이해야 하고, 이해하기 쉬워야 한다.</strong></p>
<ul>
<li>변경이 용이하지 못하면 한 객체의 수정이 다른 객체의 수정으로 영향을 끼치게 되어 코드가 일시에 흔들리게 된다는 것 (최소한의 의존성, 낮은 결합도)</li>
<li>이해하기 쉬워야 한다는 것은 우리의 예상에서 크게 벗어나지 않아야 한다는 것과 한 메소드가 많은 세부사항을 다루고 있으면 부담이 된다는 것</li>
</ul>
</li>
</ol>
<ol start="2">
<li><p><strong>객체를 자율적인 존재로 만들자.</strong></p>
<ul>
<li>자신의 일은 자신이 하자. (자신의 데이터를 책임진다.)</li>
<li>다른 객체의 세부사항을 굳이 알 필요 없다. (캡슐화)
즉, 다른 객체의 인터페이스에만 의존하며, 구현을 알 필요가 없다.</li>
</ul>
</li>
</ol>
<ol start="3">
<li><p><strong>외부 간섭을 최대한 배제하고, 메시지를 통해 협력하자.</strong></p>
<ul>
<li>데이터와 프로세스가 동일한 모듈 내부에 위치해야 한다.</li>
</ul>
</li>
<li><p><strong>어느정도 트레이드오프의 시점이 존재한다.</strong></p>
<ul>
<li>훌륭한 설계는 적절한 트레이드오프의 결과물이다.</li>
</ul>
</li>
</ol>
<ol start="5">
<li><strong>객체지향 패러다임의 핵심 -&gt; 역할, 책임, 협력</strong><ul>
<li>객체지향의 본질은 협력하는 객체들의 공동체 창조</li>
<li>어떤 협력이 필요하고 협력을 위해 어떤 역할과 책임이 필요한지 고민하지 않은 채 구현에 초점을 맞춘다면, 변경하기 어렵고 유연하지 못한 코드를 낳는다.</li>
<li>협력 : 애플리케이션 기능을 구현하기 위해 수행되는  상호작용</li>
<li>책임 : 객체가 협력에 참여하기 위해 수행하는 로직</li>
<li>역할 : 협력 안에서 수행하는 책임들이 모여 객체가 수행하는 역할을 구성</li>
</ul>
</li>
</ol>
<ol start="6">
<li><p><strong>협력</strong></p>
<ul>
<li><p>객체지향 세계에서 기능을 구현할 수 있는 방법이다.</p>
</li>
<li><p>객체 사이의 메시지 전송을 통해 협력을 한다. (즉, 한 객체가 다른 객체에게 무엇인가를 요청하는 것이다.)</p>
</li>
<li><p>객체는 다른 객체의 내부 구현에 직접 접근할 수 없기 때문에 오직 메시지 전송을 통해서만 요청할 수 있다.</p>
</li>
<li><p>메시지를 수신한 객체는 메서드를 실행해 요청에 응답한다.</p>
</li>
<li><p>외부 객체는 오직 메시지만 전송하고, 메시지를 어떻게 처리할지는 수신한 객체가 자율적으로 결정한다.</p>
</li>
<li><p>자신이 할 수 없는 일을 외부 객체에게 위임하면, 전체적인 자율성을 향상시킨다.</p>
</li>
<li><p>객체의 상태와 행동을 결정하는 것은 객체가 참여하는 협력이다.</p>
<ul>
<li>협력을 통해 결정된 행동으로 상태를 결정한다. (협력이 제일 상위)</li>
</ul>
</li>
<li><p>협력이 설계를 위한 책임 결정 문맥을 제공한다. (ex. 영화 예매 협력에서의 Movie 객체)</p>
</li>
</ul>
</li>
</ol>
<ol start="7">
<li><strong>책임</strong><ul>
<li>협력에 참여하기 위해 객체가 수행하는 행동 (응집도 있는 행위의 집합)</li>
<li>&#39;아는 것&#39; + &#39;하는 것&#39;<ul>
<li>아는 것 : 사적인 정보, 관련된 객체, 자신이 유도하거나 계산할 수 있는 것 등</li>
<li>하는 것 : 객체 생성 및 계산 수행, 다른 객체의 행동 시작, 다른 객체의 활동 제어 등</li>
</ul>
</li>
<li>책임은 협력안에서 객체의 외부 인터페이스와 내부 속성을 결정한다.</li>
<li>적절한 협력은 적절한 책임을 제공하고, 적절한 책임은 적절한 객체에게 할당된다.</li>
<li>객체에게 얼마나 적절한 책임을 할당하냐가 설계 전체 품질을 결정한다. (책임 주도 설계)</li>
<li>책임 할당 시 고려해야하는 요소<ul>
<li>메시지가 객체를 결정 : 책임을 할당할 메시지를 먼저 식별하고 메시지를 처리할 객체를 선택한다. 이렇게 하는 이유는 다음과 같다.<ul>
<li>최소한의 인터페이스를 가지게 된다. (꼭 필요한 크기의 인터페이스)</li>
<li>추상 인터페이스를 가질 수 있게 된다. (객체의 인터페이스는 무엇을 하는지 표현해야 하지만 어떻게 수행하는지 노출해선 안된다. 메시지는 외부 객체가 요청하는 무언가를 의미하기 때문에 메시지를 먼저 식별하면 무엇을 수행할지 초점을 맞추는 인터페이스를 얻을 수 있다.</li>
</ul>
</li>
<li>행동이 상태를 결정 : 객체가 협력에 적합한지 결정하는 것은 객체의 상태가 아닌 행동이다. 따라서 상태에 초점을 맞추면 안된다. 협력이 객체의 행동을 결정하고, 행동이 상태를 결정하며, 그 행동이 책임이 된다.</li>
</ul>
</li>
</ul>
</li>
</ol>
<ol start="8">
<li><strong>역할</strong><ul>
<li>객체가 어떤 특정한 협력 안에서 수행하는 책임의 집합</li>
<li>역할을 통해 유연하고 재사용 가능한 협력을 얻을 수 있다. (추상화)</li>
<li>일반적으로 추상클래스와 인터페이스를 사용하여 역할을 정의한다.</li>
</ul>
</li>
</ol>
<p>오늘은 조영호님의 오브젝트 2장 객체지향 프로그래밍을 읽고 배운점을 정리해보려고 한다.</p>
<ol start="9">
<li><strong>클래스의 내부와 외부를 구분하자.</strong><ul>
<li>경계의 명확성이 객체의 자율성을 보장</li>
<li>프로그래머에게 구현의 자유를 제공</li>
</ul>
</li>
</ol>
<ol start="10">
<li><strong>객체지향의 핵심은 객체를 자율적인 존재로 만드는 것이다.</strong><ul>
<li>스스로 상태를 관리하고, 판단하고, 행동하는 공동체를 구성하는 것</li>
<li>외부의 간섭을 최소화</li>
<li>객체 스스로 최선의 방법을 결정해야 한다.</li>
<li>인터페이스와 구현의 분리</li>
<li>내부 구현 은닉</li>
<li>변경에 대한 혼란을 최소화 시킬 수 있다.</li>
</ul>
</li>
</ol>
<ol start="11">
<li><strong>하나의 인스턴스 변수만 포함하더라도 명시적인 개념을 표현하기 위해 객체를 생성해도 좋다.</strong><ul>
<li>명시적이고 분명할 뿐만 아니라, 전체적인 설계의 명확성과 유연성을 높인다.</li>
</ul>
</li>
</ol>
<ol start="12">
<li><strong>협력의 관점에서 어떤 객체가 필요한지 결정하고, 공통 상태와 행위를 구현하기 위해 클래스를 작성한다.</strong></li>
</ol>
<ol start="13">
<li><strong>메시지 전송과 수신을 통해 객체는 다른 객체와 상호작용한다.</strong><ul>
<li>객체는 메서드를 통해 자신만의 방법으로 메시지를 처리한다.</li>
</ul>
</li>
</ol>
<ol start="14">
<li><strong>상속과 다형성을 통해 코드를 유연하게 만들 수 있다.</strong><ul>
<li>설계가 유연해질수록 코드를 이해하고 디벙깅하기는 점점 더 어려워진다.</li>
<li>유연성을 억제할 수록 재사용성과 확장 가능성은 낮아진다.</li>
<li>다형성은 컴파일 시간 의존성과 실행 시간 의존성을 다르게 만들 수 있다.</li>
<li>상속이 오로지 코드의 재사용을 위해서 사용된다면, 변경에 취약한 코드를 낳게 할 확률이 높다.</li>
<li>내부 구현을 공유할 필요가 없고 순수 인터페이스만 공유해야 한다면, 추상 클래스가 아닌 인터페이스를 사용하면 된다.</li>
</ul>
</li>
</ol>
<ol start="15">
<li><strong>추상화</strong> <ul>
<li>추상화 계층만 따로 떼어 놓고 보면 요구사항의 정책을 높은 수준에서 서술할 수 있다.</li>
<li>즉, 세부 내용은 무시한 채 쉽고 간단하게 표현할 수 있다. (표현 수준을 조정)</li>
<li>기존 구조를 수정하지 않고도 새로운 기능을 쉽게 추가 및 확장할 수 있어 설계가 더욱 유연해진다.</li>
</ul>
</li>
</ol>
<ol start="16">
<li>*<em>책임의 위치를 결정하기 위해 조건문을 쓰는 것은 좋지 않다. (예외 케이스를 최소화하고 일관성을 유지하자.) *</em></li>
</ol>
<ol start="17">
<li><p><strong>상속과 합성을 적절하게 함께 사용하자</strong></p>
<ul>
<li><p>상속은 캡슐화를 위반하고, 설계를 유연하지 못하게 한다.</p>
<ul>
<li>캡슐화 위반 : 부모 클래스의 내부 구조를 잘 알고 있어야 한다. 왜냐하면 부모 클래스를 기반으로 자식 클래스의 코드를 구현해야 하기 때문이다. 자식 클래스에서 super를 이용해 부모 클래스의 메소드를 호출하는 상황이라면 부모 클래스의 구현은 자식 클래스에게 노출되어 캡슐화가 약해지고, 자식 클래스와 부모 클래스는 강하게 결합되어 부모 클래스를 변경할 때 자식 클래스도 함께 변경될 가능성이 높아진다.</li>
<li>유연하지 않은 설계 : 실행 시점에 객체의 종류를 변경하는 것이 불가능하다. </li>
</ul>
</li>
<li><p>합성은 이러한 상속의 두가지 문제점을 모두 해결한다.</p>
</li>
<li><p>그렇다고 상속을 쓰지말라는 것이 아니다! 함께 사용하면 된다!</p>
<ul>
<li>변경에 대한 유연함과 코드의 재사용 + 다형성을 통한 인터페이스 재사용이 가능해진다.</li>
</ul>
</li>
</ul>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ubuntu 20.04에 Jenkins를 설치해보기]]></title>
            <link>https://velog.io/@k-gn/Ubuntu-20.04%EC%97%90-Jenkins%EB%A5%BC-%EC%84%A4%EC%B9%98%ED%95%B4%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@k-gn/Ubuntu-20.04%EC%97%90-Jenkins%EB%A5%BC-%EC%84%A4%EC%B9%98%ED%95%B4%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Thu, 30 Mar 2023 12:19:01 GMT</pubDate>
            <description><![CDATA[<p>저번에 Ubuntu 20.04에 도커와 도커 컴포즈를 설치한 글에 이어서 이번에는 Jenkins 설치를 정리해보려구 한다.</p>
<p>도커와 도커 컴포즈를 설치했던 것 보다 훨씬 쉽게 설치할 수 있다.</p>
<hr>
<h4 id="jenkins를-설치하려면-자바를-먼저-설치해주어야-한다">Jenkins를 설치하려면 자바를 먼저 설치해주어야 한다.</h4>
<pre><code>$ sudo apt update
$ sudo apt install openjdk-11-jre
$ java -version</code></pre><h4 id="자바-설치가-완료되었다면-아래-명령어를-통해-바로-jenkins를-설치할-수-있다">자바 설치가 완료되었다면, 아래 명령어를 통해 바로 Jenkins를 설치할 수 있다.</h4>
<pre><code>curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee \
  /usr/share/keyrings/jenkins-keyring.asc &gt; /dev/null
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
  https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
  /etc/apt/sources.list.d/jenkins.list &gt; /dev/null
sudo apt-get update
sudo apt-get install jenkins</code></pre><hr>
<h3 id="참고">참고</h3>
<p><a href="https://www.jenkins.io/doc/book/installing/linux/">https://www.jenkins.io/doc/book/installing/linux/</a> (공식문서)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Github action 을 활용하여 자동으로 Reviewers, Assignees 할당해주기 ]]></title>
            <link>https://velog.io/@k-gn/Github-action-%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-%EC%9E%90%EB%8F%99%EC%9C%BC%EB%A1%9C-Reviewers-Assignees-%ED%95%A0%EB%8B%B9%ED%95%B4%EC%A3%BC%EA%B8%B0</link>
            <guid>https://velog.io/@k-gn/Github-action-%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-%EC%9E%90%EB%8F%99%EC%9C%BC%EB%A1%9C-Reviewers-Assignees-%ED%95%A0%EB%8B%B9%ED%95%B4%EC%A3%BC%EA%B8%B0</guid>
            <pubDate>Wed, 29 Mar 2023 01:09:56 GMT</pubDate>
            <description><![CDATA[<p>Github action 을 활용하여 자동으로 PR에 Reviewers, Assignees를 할당해볼거다!
적용하기도 쉽고 사소한 작업이지만, 매번 PR을 생성할 때 추가해주는 것이 귀찮기도 하고 이런 사소한 작업 하나하나 찾아보면서 자동화 하는 과정이 너무 재미있어서 바로 적용해보려구 한다..!</p>
<hr>
<p>먼저 &#39;레파지토리&#39;/.github/auto_assign.yml 를 생성하여 아래와 같이 작성해주었다.</p>
<pre><code>addReviewers: true


addAssignees: author


reviewers:
  - name1
  - name2
  - name3

numberOfReviewers: 3</code></pre><p>이 후 PR 생성 시 돌아갈 workflow를 작성해주었다.</p>
<pre><code>name: Auto Assign Action
on:
  - pull_request_target

jobs:
  add-reviews:
    runs-on: ubuntu-latest
    steps:
      - uses: kentaro-m/auto-assign-action@v1.2.4
        with:
          configuration-path: &quot;.github/auto_assign.yml&quot;</code></pre><hr>
<p>설정은 이게 전부이며, 정말 간단하다.
이제 PR을 생성할 경우 자동으로 Reviewers, Assignees가 할당되는 마법을 볼 수 있다.</p>
<p>** 이슈 및 주의사항 **
merge 할 곳에 해당 파일이 존재해야지 동작했다.
PR을 작성할 때는 보이지 않고, 작성 후 request를 올리면 그때 CI가 돌면서 뜬다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ubuntu 20.04 에 Docker / Docker-compose 설치하기]]></title>
            <link>https://velog.io/@k-gn/Ubuntu-20.04-%EC%97%90-Docker-Docker-compose-Jenkins-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@k-gn/Ubuntu-20.04-%EC%97%90-Docker-Docker-compose-Jenkins-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 28 Mar 2023 15:05:21 GMT</pubDate>
            <description><![CDATA[<p>오늘은 우분투 20.04 버전에 도커와 도커컴포즈를 설치해보려한다.</p>
<h4 id="docker-및-docker-compose-설치에-필요한-유틸-다운">docker 및 docker-compose 설치에 필요한 유틸 다운</h4>
<pre><code>sudo apt-get update
sudo apt-get install -y ca-certificates \ 
    curl \
    software-properties-common \
    apt-transport-https \
    gnupg \
    lsb-release</code></pre><h4 id="이전에-docker-를-설치했다면-제거">이전에 docker 를 설치했다면 제거</h4>
<pre><code>sudo apt remove docker docker-engine docker.io containerd runc
</code></pre><h5 id="docker-리포지토리-설정">docker 리포지토리 설정</h5>
<pre><code>sudo apt-get update &amp;&amp; upgrade
sudo apt-get install ca-certificates curl gnupg lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo &quot;deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable&quot; | sudo tee /etc/apt/sources.list.d/docker.list &gt; /dev/nul</code></pre><h4 id="추가한-repository-업데이트">추가한 repository 업데이트</h4>
<pre><code>sudo apt-get update
</code></pre><h4 id="docker-설치">docker 설치</h4>
<pre><code>sudo apt-get install docker-ce docker-ce-cli containerd.io
</code></pre><h4 id="sudo-없이-docker-쓰기">sudo 없이 docker 쓰기</h4>
<pre><code>sudo usermod -aG docker ${USER}
</code></pre><h3 id="도커-컴포즈docker-compose-설치">도커 컴포즈(docker-compose) 설치</h3>
<pre><code>sudo curl -L &quot;https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-$(uname -s)-$(uname -m)&quot; -o /usr/local/bin/docker-compose
-o /usr/local/bin/docker-compose</code></pre><p>최신 버전을 설치하고 싶다면 위 명령어에 보이는 1.28.5 라는 버전 숫자를 바꿔주면 된다!</p>
<pre><code>sudo chmod +x /usr/local/bin/docker-compose  # chmod 를 통해서 실행이 가능하게 세팅
</code></pre><hr>
<h5 id="docker-설치-후-varrundockersock의-permission-denied-발생하는-경우varrundockersock-파일의-권한을-666으로-변경하여-그룹-내-다른-사용자도-접근-가능하게-변경">docker 설치 후 /var/run/docker.sock의 permission denied 발생하는 경우/var/run/docker.sock 파일의 권한을 666으로 변경하여 그룹 내 다른 사용자도 접근 가능하게 변경</h5>
<pre><code>sudo chmod 666 /var/run/docker.sock
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[AWS 를 활용하여 HTTPS 설정하는 방법]]></title>
            <link>https://velog.io/@k-gn/AWS-%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-HTTPS-%EC%84%A4%EC%A0%95%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@k-gn/AWS-%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-HTTPS-%EC%84%A4%EC%A0%95%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Tue, 21 Mar 2023 12:08:29 GMT</pubDate>
            <description><![CDATA[<p>오늘은 웹사이트에 HTTPS (Hypertext Transfer Protocol Secure)를 설정해보려한다! 로컬 환경이라면 크게 상관 없겠지만 누구나 접근할 수 있는 배포된 환경이라면 필수로 적용해야 하는 것이 바로 HTTPS 설정을 해볼것이다..!</p>
<h1 id="https-를-적용해야-하는-이유">HTTPS 를 적용해야 하는 이유?</h1>
<p><strong>설정하기에 앞서 우리는 왜 HTTPS 설정을 해야 할까요?</strong></p>
<p>기존의 서버와 클라이언트가 데이터를 주고 받기 위한 프로토콜인 <strong>HTTP 는</strong>  암호화가 
되지 않은 평문 데이터를 전송하기 때문에 제 3자가 해당 데이터를 조회할 수 있습니다.</p>
<p>따라서 누구든 마음만 먹으면 네트워크단에서 소중한 데이터를 확인할 수 있어서 
<strong>보안</strong>에 매우 <strong>취약</strong> 하다는 이슈가 존재한다.</p>
<p>이러한 문제를 해결하기 위해 네트워크 상에서 제 3자가 정보를 볼 수 없도록 암호화를 지원하는 <strong>HTTPS</strong> 프로토콜이 등장 했다.</p>
<h3 id="https-가-적용된-웹사이트의-장점"><strong>HTTPS 가 적용된 웹사이트의 장점</strong></h3>
<ol>
<li>웹사이트에서 주고받는 정보를 암호화한다. </li>
<li>공인된 민간기업 CA(Certificate Authority) 의 인증을 받기 때문에 신뢰하고 사용할 수 있다.</li>
<li>HTTPS 사용 시 검색엔진 최적화(SEO) 혜택을 볼 수 있다.<ol>
<li>구글에서는 HTTPS 를 적용 하고 있는지를 검색 순위의 결정 요소에 포함(가산점)하고 있다.</li>
</ol>
</li>
<li>크롬이나 파이어폭스 등 일부 브라우저에서는 안전하지 않은 사이트의 접속을 막는 추세이다.</li>
<li>과거엔 HTTP 에 비해 속도가 느렸지만, 하드웨어의 발전과 HTTPS/2 업그레이드로 속도차이가 차이를 못느낄 정도로 개선되었다.</li>
</ol>
<p>이러한 장점들 때문에 대부분의 웹사이트는 현재 HTTPS 를 적용하고 있다.</p>
<p>어떻게보면 모든 웹사이트 보안의 가장 중요한 <strong>핵심 요소</strong> 라고도 할 수 있다...!</p>
<hr>
<p>HTTPS 설정을 할 수 있는 방법은 여러가지 있지만, AWS를 사용하고 있는김에 ACM 인증서를 발급받아 적용해볼 것이다!</p>
<h3 id="acm-인증서-발급받기">ACM 인증서 발급받기</h3>
<p>AWS 에서 AWS Certificate Manager 에 들어가 인증서를 먼저 요청해야한다.</p>
<p>해당 인증서는 HTTPS 설정을 하기 위한 <strong>SSL 인증서다.</strong></p>
<p>꼭 AWS 인증서가 아닌 외부 SSL 인증서가 있다면 프라이빗 인증서 요청을 통해 사용할 수도 있다.</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/731cd252-68d4-4de7-add7-b74c995b00d8/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/8f125c4e-4bab-44c2-9be0-d88af8cb544f/image.png" alt=""></p>
<ol>
<li><strong>먼저 사용할 도메인 이름을 적어준다.</strong></li>
</ol>
<p>이 때 추가로 서브도메인을 여러개 사용할 예정이라면, [이 인증서에 다른 이름 추가] 를 눌러서 추가해줄 수 있고, 위 사진처럼 * 키워드를 사용하여 한번에 서브도메인을 받아줄 수도 있다!</p>
<pre><code>(이미지 속 도메인 주소는 임의로 적은 도메인 주소입니다.)</code></pre><ol>
<li><strong>보통은 도메인을 구매 후 DNS 검증을 통해 해당 도메인의 소유권을 검증한다.</strong></li>
</ol>
<p><strong>이제 인증서를 생성을 누르면…</strong></p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/23da01c3-c7b9-456b-831c-426c89a11fca/image.png" alt=""></p>
<p>비어있던 인증서란에 이렇게 인증서가 등장..! 
하지만 아직 검증 전이기 때문에 <strong>사용할 수 없는 상태로 존재한다</strong>.</p>
<p>DNS 검증을 설정해주었는데 아무리 기다려도 활성화가 안되는데.. 이유가 뭐지?</p>
<p>바로 도메인과 AWS <strong>네임서버</strong>가 연결되어 있지 않기 때문!</p>
<p><strong>네임서버</strong>는 IP 주소와 도메인 주소를 연결해주는 역할을 해주는 중요한 친구다!</p>
<p>그럼 네임서버를 빨리 연결해주러 가보자!</p>
<hr>
<h3 id="route-53-설정-후-acm-검증하기">Route 53 설정 후 ACM 검증하기</h3>
<p>먼저 네임서버를 받으려면 <strong>Route53</strong> 이란 호스팅 영역을 생성해주어야 한다.</p>
<aside>
💡 **Route53** ??

<p>Route53 이란 AWS 에서 제공하는 DNS.
도메인을 IP 로 변환하여 네트워크 통신을 통해 목적지를 찾아가게 해준다.</p>
</aside>

<p>생성하는건 크게 어렵지 않다!</p>
<p>도메인 이름만 명시해준 후 생성해주는 것이 전부!</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/bf067512-bcfc-4efc-be1c-e76da04c6e3f/image.png" alt=""></p>
<p>이렇게 호스팅 영역을 생성하게 되면</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/87c81721-1bab-4650-816d-ffec9f474e0a/image.png" alt=""></p>
<p>저렇게 <strong>4개의 네임서버 주소</strong>가 생성되고, <strong>4개의 주소를 도메인을 구매한 사이트에 가서 연결</strong>해준다.</p>
<p>(ex. 가비아에서 구매한 도메인일 경우 가비아 홈페이지에 들어가서 설정!)</p>
<p>이제 다시 ACM 으로 넘어가서 내 인증서를 들어가보면</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/f63d5de5-d8ee-4d2c-9536-c67f611ea46e/image.png" alt=""></p>
<p>도메인 항목에 검증 대기중인 CNAME 레코드가 하나 있는데 이 레코드를 Route 53 에 생성해주면 된다.</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/b961da07-2391-4e6e-a3a2-0f3b026dcef3/image.png" alt=""></p>
<p>그럼 내 Route 53 에 해당 CNAME 레코드가 생성된다.</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/aeb95bc7-aaed-4ca5-b613-4016184461d5/image.png" alt=""></p>
<p><strong>이제 짧으면 5분 내로, 길면 1시간 정도까지 기다리면 내 인증서의 상태가 발급됨으로 초록불이 번쩍!!</strong></p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/00e04b39-3450-4041-a891-a6698eb04235/image.png" alt=""></p>
<p>이제 HTTP 도메인을 HTTPS 로 만들어주는 마법의 AWS SSL 인증서를 발급받았다.</p>
<hr>
<h3 id="elb로-https-리스너-설정하기">ELB로 HTTPS 리스너 설정하기</h3>
<p>사실 처음에는 로드밸런서가 어디있는지 찾는거부터 오래 걸렸다..</p>
<p>검색을 해도 AWS 에선 뜨질 않는다..</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/87a40058-b0d3-4128-b089-1185f9d6826c/image.png" alt=""></p>
<p>로드 밸런서는 EC2 서비스에 들어가서 왼쪽 카테고리를 내리다보면 로드밸런싱 안에 꽁꽁(?) 숨겨져 있다.</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/3ef90618-3186-4308-879f-c9cda7d63575/image.png" alt=""></p>
<hr>
<p>로드밸런서에 들어가보면 지금은 텅 비어있다.</p>
<p>너무 허전하니 얼른 로드밸런서를 하나 생성해보자!</p>
<p>로드밸런서 생성 버튼 클릭!</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/1048efaf-42bc-47e9-a3ec-bc99f1701d67/image.png" alt=""></p>
<p>3개의 로드밸런서 중 HTTPS 설정을 하려면 <strong>Application Load Balancer (ALB)</strong> 를 사용하면 된다.</p>
<p>ALB 를 생성해주고 ALB 의 <strong>리스너 규칙과 인증서 적용</strong>만 해주면 쉽게 HTTPS 를 설정해줄 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/15ff18f3-66a5-4dc1-8d7b-9419ada4e599/image.png" alt=""></p>
<p><strong>이제 직접 ALB 설정을 해보자!</strong></p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/0e66fd41-e06c-4eba-a5f1-af5b2a12d8d1/image.png" alt=""></p>
<ul>
<li><strong>Basic configuration</strong><ul>
<li>여기선 말 그대로 기본적인 설정을 해주면 된다.<ul>
<li>로드밸런서 이름을 설정해주기</li>
<li>로드밸런서 스키마 정하기<ul>
<li>internet-facing : 외부 트래픽을 분산시키는 로드밸런스</li>
<li>internal : 내부 트래픽을 분산시키는 로드밸런스</li>
</ul>
</li>
<li>IP 타입 정하기</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/k-gn/post/3c26238d-bf2b-458e-85d2-12f0c11e1543/image.png" alt=""></p>
<ul>
<li><p><strong>Network mapping</strong></p>
<ul>
<li><p>본인이 설정한 VPC 가 있다면 해당 VPC 와 알맞은 가용영역을 체크해주시면 된다.</p>
</li>
<li><p>설정한 VPC 가 없다면 기본 VPC 가 자동으로 골라져 있을 것이다.</p>
<ul>
<li><p>기본 VPC 는 아래 4개 전부 체크해주시면 된다.</p>
<p>(가용영역 및 네트워크 개념은 해당 글에서 다루지 않겠다.)</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/k-gn/post/faf4f6e1-4b43-4fed-8c84-c95dd9cd2f87/image.png" alt=""></p>
<ul>
<li><strong>Security groups</strong><ul>
<li>직접 생성한 보안그룹이 있다면 선택한다. (없으면 default 보안그룹 사용)</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/k-gn/post/be4e3b8b-7fdb-4915-b1e8-6fe208dc7182/image.png" alt=""></p>
<ul>
<li><strong>Listeners and routing</strong> (제일 중요한 부분!)<ul>
<li>들어오는 정보를 해석하여 어떤 타겟으로 보낼지 설정해주는 곳이다.</li>
<li>외부 클라이언트와 ALB 사이에 프로토콜과 포트를 지정한다.</li>
</ul>
</li>
</ul>
<p>여기서 우리는 기다리고 기다리던 <strong>HTTP → HTTPS</strong> 설정을 해줄 수 있다.</p>
<p>위 사진에 프로토콜을 HTTP 에서 HTTPS 로 변경하게 되면 인증서를 등록할 수 있는</p>
<p>[Secure listener settings] 창이 생기고 여기서 아까 만든 ACM 인증서를 등록한다.</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/a9822258-ae1d-4d1e-a573-9a0513b75eec/image.png" alt=""></p>
<p>HTTPS 로 들어온 요청을 이제 어디로 보낼지 타겟을 지정해주어야 한다.</p>
<p>[Create target group] 으로 들어가 목적지 타겟을 만들어 준다.</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/bf0391c6-43f1-40f2-9380-b22c1e75d55b/image.png" alt=""></p>
<p>타겟 타입은 본인이 보낼 타겟 타입을 지정해주면 된다.(저는 인스턴스로 보낼 거라 인스턴스 타입!)</p>
<p>Target group name 에 타겟의 이름을 작성해준다.</p>
<p>이제 해당 타겟의 프로토콜과 포트번호를 적어준다. (저는 인스턴스 내부로 HTTP:80 요청을 보낸다.)</p>
<p>이 후 따로 설정한 VPC 나 프로토콜, Healthy check 경로가 있다면 추가로 작성한다.</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/ea78a0ce-722c-41bf-8c45-d43b593a8f9f/image.png" alt=""></p>
<p>여기선 실제로 어떤 인스턴스로 보낼지와 포트번호를 입력한다.</p>
<p>보낼 인스턴스를 체크한 후 [Include as pending below] 를 눌러주면 아래 Review targets 로 이동하면서 
등록이 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/4a18e6ee-b877-4b28-bb72-ea4d6ff0ac9c/image.png" alt=""></p>
<p>타겟 그룹까지 이제 생성이 완료되었습니다!</p>
<p>위에 타겟그룹란을 한번 새로고침하면 방금 만든 타겟이 뜰텐데 선택해준 후 로드밸런서 설정이 끝난다.</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/23a524c9-9297-4839-9d53-ffe6237b3b94/image.png" alt=""></p>
<p>아까 텅 비어있던 로드밸런서 창에 이제 내가 만든 로드밸런서가 생겼다!</p>
<p>밑에 리스너도 잘 등록되어 있는걸 확인하실 수 있다.</p>
<p>이제 로드밸런서 설정까지 마무리를 해보았는데 <strong>Route 53 호스팅 영역에 생성한 도메인 레코드를
방금 만든 ALB 와 연결해주는 작업</strong>을 해야한다!</p>
<p>그래야 해당 도메인 주소로 들어오는 요청을 ALB 가 받아줄 수 있다!! </p>
<hr>
<h3 id="route-53-레코드와-alb-연결하기">Route 53 레코드와 ALB 연결하기</h3>
<p>다시 Route 53 호스팅 영역으로 돌아와 주황색 레코드 생성 버튼을 눌러 ALB 와 연결될 A 레코드를 하나 생성한다.</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/e35167c0-b5a0-40ab-9725-d793553b0480/image.png" alt=""></p>
<p>처음에 들어갈 땐 별칭이 체크되어 있지 않을 텐데 별칭을 체크해주면 트래픽 라우팅 대상을 정해줄 수 있다.</p>
<p>라우팅 대상은 만든 로드밸런서에 대한 별칭을 선택하고, 선택한 Region 을 고른 후 ALB 를 연결해준다.</p>
<p>이렇게 레코드를 하나 만드는 것으로 ALB 와의 연결이 끝났다. </p>
<p>이제부터 저 도메인으로 들어온 요청들은 모두 ALB 를 통해 들어온다.</p>
<p><strong>ALB 리스너 설정으로 원하는 HTTPS 도 잘 적용이 되었다!</strong> </p>
<hr>
<h3 id="추가-리스너-작업">추가 리스너 작업</h3>
<p>근데 뭔가 이상한점이 하나 있다.</p>
<p>보통 사이트들은 HTTP 로 요청이 갈 때 HTTPS 로 바꿔서 요청을 보내주는데 지금 설정한 사이트는 그냥 그대로 HTTP 요청을 보내고, HTTPS 로 바꿔주지 않고 있는 상태다.</p>
<p>그럼 어떻게 바꿔줄 수 있을까??</p>
<p>→ <strong>바로 방금 작업했던 리스너 설정을 추가로 해주면 요청을 바꿔줄 수 있다!</strong></p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/7bc3ff0a-3d94-4f95-93de-532d008dd84d/image.png" alt=""></p>
<p>로드밸런서 창 아래에 리스너 추가로 필요한 리스너를 추가한다.</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/2902e430-f03b-49fc-944c-8c674b8565ab/image.png" alt=""></p>
<p>아래 셀렉트 박스를 보시면 눈에 띄는 키워드가 하나 보인다.</p>
<p><strong>Redirect Redirect Redirect Redirect Redirect Redirect Redirect</strong></p>
<p>이미 안봐도 끝났다.</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/ce5ec237-60e2-46c4-babc-ad8fd391cde6/image.png" alt=""></p>
<p>HTTP:80 으로 들어오는 모든 요청을 HTTPS:443 으로 리다이렉트 시켜주는 리스너를 추가해준다.</p>
<p>이렇게 추가로 리스너 설정까지 해주면 사이트로 오는 모든 요청에 HTTPS 를 적용해줄 수 있다. </p>
<hr>
<p>이상 간단한 것 같으면서도 나름 복잡한 AWS를 활용한 HTTPS 설정이였다..!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CheckStyle로 코드 컨벤션 지키기]]></title>
            <link>https://velog.io/@k-gn/CheckStyle%EB%A1%9C-%EC%BD%94%EB%93%9C-%EC%BB%A8%EB%B2%A4%EC%85%98-%EC%A7%80%ED%82%A4%EA%B8%B0-9gt42p6u</link>
            <guid>https://velog.io/@k-gn/CheckStyle%EB%A1%9C-%EC%BD%94%EB%93%9C-%EC%BB%A8%EB%B2%A4%EC%85%98-%EC%A7%80%ED%82%A4%EA%B8%B0-9gt42p6u</guid>
            <pubDate>Sun, 19 Mar 2023 12:32:24 GMT</pubDate>
            <description><![CDATA[<p>어느날 우릐 프론트엔드팀에서</p>
<p>Javascript 의 <strong>husky</strong> 를 사용해서 커밋 시 코드 냄새를 잡아 </p>
<p>이슈가 있다면 커밋을 못하게 만드는 </p>
<p>아주 그냥 기개맥히는 기술을 도입하였다..!</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/118b583b-b16a-4948-b95f-0f56baa7f474/image.png" alt=""></p>
<p>그분들이 husky를 사용하는 모습을 보고 경악을 금치못한 나는 </p>
<p>인텔리제이나 Gradle 에도 husky 같은 기술이 있는지 리서치하였고….</p>
<p><strong>드디어!! (두둥)</strong></p>
<p><strong>Checkstyle</strong> 이란 기특한 놈을 찾아버렸다..!</p>
<blockquote>
<p>CheckStyle은 코드 컨벤션을 맞추는데 도움을 주는 플러그인이다.</p>
</blockquote>
<p>요놈을 잘 활용하면 commit을 하기 전에 (pre-commit) 컨벤션을 잘 지켰는지 확인하고, 잘 지키지 않았을 경우 수정하라는 메시지와 함께 commit이 되지 않도록 제한을 걸어줄 수 있다. </p>
<p>이제 한번 <strong>인텔리제이와 Git hook</strong> 을 사용해 해당 기능을 적용해보자!!</p>
<hr>
<p><strong>먼저 인텔리제이 Plugin 에서 다운로드를 받자 (참고로 이클립스에도 존재한다)</strong></p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/d7214113-64d1-464b-bd39-4b7f64638071/image.png" alt=""></p>
<p><strong>잘 설치가 되었다면 Settings → Tools 에 Checkstyle 가 생겼을 것이다!</strong></p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/e0891112-19a6-41de-bcbb-deb25fffa76f/image.png" alt=""></p>
<p><strong>CheckStyle 설치 후 formatter.xml 과 직접 규칙들을 정의한 checks.xml 파일 두개를 프로젝트 루트경로에 추가해준다!</strong></p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/c57245a3-7ad4-4a2a-ac40-5dc335dd1d82/image.png" alt=""></p>
<p><strong>인텔리제이에서 Settings를 통해 formatter.xml을 적용해줍니다.</strong></p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/87deb713-66e4-431f-a956-158c76c02a5e/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/5a1b6e0a-da82-423a-abe9-09efb55fed87/image.png" alt=""></p>
<p><strong>추가로 checks.xml도 적용해줍니다.</strong></p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/80f60510-a88a-4575-abfa-a359d07b40e8/image.png" alt=""></p>
<p><strong>이제 git hook 도 설정을 해줘야하는데</strong></p>
<p>프로젝트 워크스페이스를 확인해보면 깃 연동이 되었을 경우 <strong>.git</strong> 폴더가 있을 것이다!!</p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/323d7e68-3b33-42c1-af78-3509e5a19030/image.png" alt=""></p>
<p><strong>여길 들어가보면</strong></p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/f9f5699a-acf7-43c9-8581-5f96d5683f2c/image.png" alt=""></p>
<p><strong>hooks 라는 폴더가 있는데 여기서 git hook 설정을 해줄 수 있드아!</strong></p>
<p><strong>먼저 위에 checkstyle.jar 파일을 해당 hooks 폴더 안에 추가해주어야 한다. (아래 경로에서 다운로드 가능)</strong></p>
<p><a href="https://github.com/checkstyle/checkstyle/releases/">Releases · checkstyle/checkstyle</a></p>
<p><img src="https://velog.velcdn.com/images/k-gn/post/036a717b-bdee-4308-9945-4332b94961aa/image.png" alt=""></p>
<p><strong>이제 커밋 전 checkstyle 을 통해 내 코드를 검사할 목적이였기 때문에!</strong></p>
<p><strong>pre-commit.sample → pre-commit 으로 변경 후 해당 파일을 수정해주면 된다! (아래 코드는 내가 사용하고 있는 pre-commit file 이다)</strong></p>
<pre><code class="language-perl">#!/usr/bin/perl
#
# Pre-commit hook for running checkstyle on changed Java sources
#
# To use this you need:
# 1. checkstyle&#39;s jar file somewhere
# 2. a checkstyle XML check file somewhere
# 3. To configure git:
#   * git config --add checkstyle.jar &lt;location of jar&gt;
#   * git config --add checkstyle.checkfile &lt;location of checkfile&gt;
#   * git config --add java.command &lt;path to java executale&gt; [optional
#     defaults to assuming it&#39;s in your path]
# 4. Put this in your .git/hooks directory as pre-commit
#
# Now, when you commit, you will be disallowed from doing so
# until you pass your checkstyle checks.

$command = &quot;git-diff-index --cached HEAD 2&gt;&amp;1 | sed &#39;s/^:.*     //&#39; | uniq&quot;;
open (FILES,$command . &quot;|&quot;) || die &quot;Cannot run &#39;$command&#39;: $!\n&quot;;

$CONFIG_CHECK_FILE = &quot;checkstyle.checkfile&quot;;
$CONFIG_JAR = &quot;checkstyle.jar&quot;;
$CONFIG_JAVA = &quot;java.command&quot;;

$check_file = `git config --get $CONFIG_CHECK_FILE`;
$checkstyle_jar = `git config --get $CONFIG_JAR`;
$java_command = `git config --get $CONFIG_JAVA`;

if (!$check_file || !$checkstyle_jar)
{
   die &quot;You must configure checkstyle in your git config:\n&quot;
   . &quot;\t$CONFIG_CHECK_FILE - path to your checkstyle.xml file\n&quot;
   . &quot;\t$CONFIG_JAR - path to your checkstyle jar file\n&quot;
   . &quot;\t$CONFIG_JAVA - path to your java executable (optional)\n&quot;
   ;
}

$java_command = &quot;java&quot; if (!$java_command);

chomp $check_file;
chomp $checkstyle_jar;
chomp $java_command;

$command = &quot;$java_command -jar $checkstyle_jar -c $check_file&quot;;

@java_files = ();
@words = ();

foreach (&lt;FILES&gt;)
{
   chomp;
   @words = split(/ /, $_);
   $type = substr(@words[-1], 0, 1);

   if($type eq &quot;D&quot;) {
      print &quot;$type - delete \n&quot;;
   }else {
      print &quot;$type - add or modify \n&quot;;
      next if (!(/\.java$/));
      push @java_files, $_;
      $command .= &quot; &quot;;
      $command .= $_;
   }
}
if ($#java_files &gt;= 0)
{
   if (&amp;run_and_log_system ($command))
   {
       print STDERR &quot;Commit aborted.\n&quot;;
       exit -1;
   }
}

exit 0;

sub run_and_log_system
{
   ($cmd) = @_;

   system $cmd;
}</code></pre>
<p><strong>여기까지 왔다면 이제 거의 끝났다!!</strong></p>
<p><strong>해당 프로젝트 위치에서 터미널 (git bash) 를 열어서 아래 명령어를 두개 치면 진짜 끝!</strong></p>
<pre><code class="language-bash">git config --add checkstyle.jar {파일경로}/checkstyle-{버전}-all.jar
git config --add checkstyle.checkfile {파일경로}/custom_checks.xml</code></pre>
<hr>
<p><a href="https://checkstyle.sourceforge.io/">https://checkstyle.sourceforge.io/</a></p>
<ul>
<li>Checkstyle site</li>
<li>여기서 다양한 규칙들을 확인할 수 있다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[객체 지향의 사실과 오해]]></title>
            <link>https://velog.io/@k-gn/%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5%EC%9D%98-%EC%82%AC%EC%8B%A4%EA%B3%BC-%EC%98%A4%ED%95%B4%EB%A5%BC-%EC%9D%BD%EA%B3%A0</link>
            <guid>https://velog.io/@k-gn/%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5%EC%9D%98-%EC%82%AC%EC%8B%A4%EA%B3%BC-%EC%98%A4%ED%95%B4%EB%A5%BC-%EC%9D%BD%EA%B3%A0</guid>
            <pubDate>Sat, 18 Mar 2023 12:42:17 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/k-gn/post/0a3adeca-b3c8-43c1-a0d6-28ecc2d89f13/image.jpeg" alt=""></p>
<p>드디어 조영호님의 객체지향의 사실과 오해 책을 매일 읽겠다고 마음만 먹고 묵혀두었다가 더는 미루면 안될것 같아 일주일동안 열심히 읽고 완독해버렸다!!</p>
<h3 id="책을-읽으면서">책을 읽으면서</h3>
<p>생각보다 난이도가 높은 책이라는 생각이 들었다.
나는 책을 읽는 속도가 좀 빨라서 원래는 하루면 완독할 수 있을 거라 생각했지만, 책을 이해하고 생각하는 시간이 많이 들어 넉넉하게 일주일을 잡고 책을 읽었다.</p>
<p><em>이 책의 내용을 완전히 나의 것으로 만들려면 2번은 더 읽어야 할 것 같다.</em></p>
<h3 id="리뷰">리뷰</h3>
<p>객체지향 세계를 이상한 나라의 엘리스 이야기의 내용을 가져와 설명해주는 특이하면서도 흥미로운 책이였다.</p>
<p>내가 이해한 내용을 요약하자면 아래와 같다.</p>
<ol>
<li>객체지향은 현실세계의 모방이 아닌 소프트웨어 세계에서의 <strong>재창조</strong>이다.</li>
<li>객체는 <strong>상태</strong>와 <strong>행위</strong>를 지닌 <strong>자율적인</strong> 존재이다. (자율적인 객체란 <strong>캡슐화</strong>가 잘 적용된 객체)</li>
<li>객체는 다른 객체가 무엇을 수행하는지 알 수 있지만, 어떻게 수행하는지 알 수 없다.</li>
<li>복잡성을 단순화하는 <strong>타입과 추상화</strong></li>
<li>객체는 협력과 행동을 고려하면서 설계를 해야한다. (상태를 먼저 설계하지 말자)</li>
<li><strong>역할/협력/책임</strong> 이 3가지를 항상 고려해야한다.</li>
<li>객체의 책임 수행은 공개된 인터페이스에게 <strong>메시지</strong>를 전송하여 이뤄진다. (여기서 <strong>다형성</strong>이 적용된다)</li>
</ol>
<p>하나하나 생각하면서 읽는 과정이 너무 어려웠지만 그만큼 많은 가르침을 준 책이였다.
이 책 다음으로 읽을 조영호님의 &quot;오브젝트&quot; 라는 책도 굉장히 기대가 되었다.</p>
]]></description>
        </item>
    </channel>
</rss>