<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>baekjim.log</title>
        <link>https://velog.io/</link>
        <description>도전을 좋아하는 개발자</description>
        <lastBuildDate>Sat, 15 Mar 2025 04:25:05 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>baekjim.log</title>
            <url>https://velog.velcdn.com/images/b_jim/profile/145f5891-f67c-4a99-9a76-ad7123c460e6/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. baekjim.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/b_jim" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[node.js 기본 문법 정리]]></title>
            <link>https://velog.io/@b_jim/node.js-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@b_jim/node.js-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Sat, 15 Mar 2025 04:25:05 GMT</pubDate>
            <description><![CDATA[<h2 id="변수">변수</h2>
<p>Node.js(JavaScript)의 변수는 두 가지 키워드로 선언 가능합니다.</p>
<ul>
<li><code>const</code>: 변경 불가능한 변수 (immutable, read-only)</li>
<li><code>let</code>: 변경 가능한 변수 (mutable)</li>
</ul>
<pre><code class="language-javascript">const name = &quot;node.js&quot;;
let age = 30;</code></pre>
<p>JavaScript는 타입 추론이 가능하여 타입을 명시하지 않아도 됩니다.</p>
<pre><code class="language-javascript">const name = &quot;node.js&quot;;
let age = 30;</code></pre>
<h2 id="데이터-타입">데이터 타입</h2>
<p>JavaScript에서 사용하는 주요 기본 타입</p>
<ul>
<li><code>number</code></li>
<li><code>boolean</code></li>
<li><code>string</code></li>
<li><code>object</code></li>
<li><code>undefined</code></li>
<li><code>null</code></li>
</ul>
<h2 id="문자열과-변수">문자열과 변수</h2>
<p>JavaScript에서 문자열에 변수 표현식은 아래와 같이 사용됩니다.</p>
<pre><code class="language-javascript">const name = &quot;node.js&quot;;
console.log(`Hello, ${name}!`); // Hello, node.js!
console.log(`1 + 1 = ${1 + 1}`); // 1 + 1 = 2</code></pre>
<h2 id="조건문">조건문</h2>
<p>if문 기본 사용법</p>
<pre><code class="language-javascript">// 기본 사용법
if (condition) {

} else if (condition) {

} else {

}

// 좀 더 간결하게 사용하기
const a = 1;
const b = 2;
const max = a &gt; b ? &quot;틀렸어!&quot; : &quot;정답!&quot;;</code></pre>
<p>조건이 복잡하거나 많을 경우 더 간결하게 switch문을 사용할 수 있습니다.</p>
<pre><code class="language-javascript">const number = 0;
let result;

switch (true) {
    case number &gt; 0:
        result = &quot;양수&quot;;
        break;
    case number === 0:
        result = &quot;0&quot;;
        break;
    default:
        result = &quot;음수&quot;;
}</code></pre>
<h2 id="반복문">반복문</h2>
<p>일반적인 반복문 사용법</p>
<pre><code class="language-javascript">for (let i = 1; i &lt;= 5; i++) { // 1~5

}

for (let i = 1; i &lt;= 10; i += 2) { // 2씩 증가

}

for (let i = 10; i &gt;= 1; i--) { // 10~1까지 감소

}

for (let i = 1; i &lt; 5; i++) { // 1~4까지 5는 생략

}</code></pre>
<p>배열이나 리스트</p>
<pre><code class="language-javascript">const fruits = [&quot;사과&quot;, &quot;바나나&quot;, &quot;귤&quot;];

for (const fruit of fruits) {
    console.log(fruit);
}</code></pre>
<h2 id="함수">함수</h2>
<pre><code class="language-javascript">function greet(name) {
    return `Hello, ${name}!`;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Docker 세팅에서 Xdebug 사용하기]]></title>
            <link>https://velog.io/@b_jim/Docker-%EC%84%B8%ED%8C%85%EC%97%90%EC%84%9C-Xdebug-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@b_jim/Docker-%EC%84%B8%ED%8C%85%EC%97%90%EC%84%9C-Xdebug-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 17 Feb 2025 05:03:55 GMT</pubDate>
            <description><![CDATA[<p>Xdebug 버전 확인</p>
<p><img src="https://velog.velcdn.com/images/b_jim/post/8befea74-0241-4292-9464-66c88b16bb68/image.png" alt=""></p>
<p><a href="https://www.php.net/supported-versions.php">https://www.php.net/supported-versions.php</a></p>
<h3 id="docker에서-xdebug-다운받기">Docker에서 Xdebug 다운받기</h3>
<pre><code># Dockerfile.php82 -&gt; 현재 사용중인 docker 기준으로 작성

# php8.2 Xdebug 설치
RUN pecl install xdebug-3.2.1 &amp;&amp; docker-php-ext-enable xdebug</code></pre><h3 id="phpstorm에서-설정하기">PhpStorm에서 설정하기</h3>
<p><em>Settings -&gt; PHP</em></p>
<p><img src="https://velog.velcdn.com/images/b_jim/post/2001425f-106b-4ed6-b256-2732ece91dbe/image.png" alt=""></p>
<ol>
<li>… 버튼을 클릭하여 CLI Interpreters를 생성</li>
<li>&quot;+&quot; 버튼을 눌러서 From Docker, Vargrent … 클릭
<img src="https://velog.velcdn.com/images/b_jim/post/fe36ea10-8809-4146-b520-757f92b473a4/image.png" alt=""></li>
<li>Image name에 docker 이미지를 선택하고 확인 버튼
<img src="https://velog.velcdn.com/images/b_jim/post/3069f9df-c3e1-4a44-96d0-7dbc6c55e3de/image.png" alt=""></li>
<li>사용하는 버전이 맞는지 체크하고 Apply
<img src="https://velog.velcdn.com/images/b_jim/post/4a9c24ef-5749-4488-b82a-30f0229f68cb/image.png" alt=""></li>
<li>CLI Interpreter에 위에서 생성한 duse-admin을 선택</li>
<li>바로 아래에 Path mappings 오른쪽 폴더 버튼을 클릭 후 Local Path에 local project path를 적고 Remote Path에 docker path를 적어줌</li>
<li>또 바로 아래 Docker container도 오른쪽 폴더 버튼을 클릭 후 Host Path에 local project path를 적고 Container path에 docker path를 적어줌</li>
<li>Apply</li>
</ol>
<hr>
<p><em>Settings -&gt; PHP -&gt; Servers</em>
<img src="https://velog.velcdn.com/images/b_jim/post/dd1cc39c-cb89-4439-9e6b-c0045559f4b9/image.png" alt=""></p>
<ol>
<li><ul>
<li>버튼으로 클릭</li>
</ul>
</li>
<li>Name에 사용할 이름을 입력</li>
<li>Host에 현재 docker에 설정된 Host를 입력</li>
<li>Port에 현재 docker에 설정된 Port를 입력</li>
<li>Use path mappings … 체크박스 선택</li>
<li>File/Directory에 현재 local에서 사용중인 Project Path를 입력</li>
<li>Absolute path on the server에 docker 컨테이너 내부에 설치되어 있는 Project Path를 입력</li>
</ol>
<hr>
<p><em>Settings -&gt; PHP -&gt; Debug</em>
<img src="https://velog.velcdn.com/images/b_jim/post/88849133-d6f3-44c0-94c7-2640661973ab/image.png" alt=""></p>
<ol>
<li>Xdebug 라인에 Can accept external connections 체크박스 선택</li>
<li>Debug port가 9003이 되어있는지 확인</li>
</ol>
<hr>
<ol>
<li>command + shift + A 로 액션 검색 (config) 검색후 &#39;Edit ConfigUrations...&#39; 선택
<img src="https://velog.velcdn.com/images/b_jim/post/4e6733ac-2793-408e-891c-bf5f831b293b/image.png" alt=""></li>
<li>앞서 만든 Interpreter로 설정한 후 Apply
<img src="https://velog.velcdn.com/images/b_jim/post/bcf00974-8d8c-4f3e-a2b1-26fda479ad27/image.png" alt=""></li>
<li>이제 PhpStorm 우측 상단에 phpunit.xml로 선택 후 Run 버튼으로 테스트 시작
<img src="https://velog.velcdn.com/images/b_jim/post/70631113-549a-4901-aeb0-a55b7bc9ad3b/image.png" alt=""></li>
<li>완료</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[python 기본 문법 정리]]></title>
            <link>https://velog.io/@b_jim/python-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@b_jim/python-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Tue, 21 Jan 2025 06:40:44 GMT</pubDate>
            <description><![CDATA[<h1 id="python-개요-및-문법-정보">Python 개요 및 문법 정보</h1>
<h2 id="프리평을-위한-python-기본-문법">프리평을 위한 Python 기본 문법</h2>
<hr>
<h3 id="1-변수"><strong>1. 변수</strong></h3>
<p>Python은 동적 타입을 지원합니다. 변수 선언 시 자료형을 명시하지 않아도 됩니다.</p>
<pre><code class="language-python"># 숫자 생성
age = 25
height = 180.5

# 문자열
name = &quot;Alice&quot;

# 불리언
is_active = True</code></pre>
<hr>
<h3 id="2-함수"><strong>2. 함수</strong></h3>
<p>Python은 <code>def</code> 키워드를 통해 함수를 정의합니다.</p>
<pre><code class="language-python"># 기본 함수

def greet(name):
    return f&quot;Hello, {name}!&quot;

print(greet(&quot;Python&quot;))  # Hello, Python!</code></pre>
<hr>
<h3 id="3-조건문"><strong>3. 조건문</strong></h3>
<p>Python의 조건문은 다양한 조건을 처리할 수 있도록 지원합니다.</p>
<pre><code class="language-python">age = 18

if age &lt; 20:
    print(&quot;미성년자&quot;)
elif age &lt; 60:
    print(&quot;성인&quot;)
else:
    print(&quot;노인&quot;)</code></pre>
<hr>
<h3 id="4-반복문"><strong>4. 반복문</strong></h3>
<p>Python은 <code>for</code> 키워드 및 <code>while</code> 반복을 지원합니다.</p>
<pre><code class="language-python"># for 반복문
for i in range(5):  # 0~4
    print(i)

# while 반복문
count = 0
while count &lt; 3:
    print(count)
    count += 1</code></pre>
<hr>
<h3 id="5-리스트"><strong>5. 리스트</strong></h3>
<p>리스트는 데이터를 순서대로 저장하고 조작할 수 있는 구조입니다.</p>
<pre><code class="language-python">fruits = [&quot;사과&quot;, &quot;바나나&quot;, &quot;체리&quot;]

# 접근
print(fruits[0])  # 사과

# 추가
fruits.append(&quot;방울토마토&quot;)

# 삭제
fruits.remove(&quot;바나나&quot;)

# 반복
for fruit in fruits:
    print(fruit)</code></pre>
<hr>
<h3 id="6-딕셔너리"><strong>6. 딕셔너리</strong></h3>
<p>딕셔너리는 키-값 쌍으로 이루어진 데이터 구조입니다.</p>
<pre><code class="language-python">person = {&quot;name&quot;: &quot;Alice&quot;, &quot;age&quot;: 25}

# 접근
print(person[&quot;name&quot;])  # Alice

# 추가
person[&quot;city&quot;] = &quot;Seoul&quot;

# 삭제
del person[&quot;age&quot;]

# 반복
for key, value in person.items():
    print(f&quot;{key}: {value}&quot;)</code></pre>
<hr>
<h3 id="7-클래스와-객체"><strong>7. 클래스와 객체</strong></h3>
<p>Python에서 클래스는 <code>class</code> 키워드를 통해 정의합니다.</p>
<pre><code class="language-python">class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def introduce(self):
        return f&quot;My name is {self.name}, and I&#39;m {self.age} years old.&quot;

# 객체 생성
alice = Person(&quot;Alice&quot;, 25)
print(alice.introduce())</code></pre>
<hr>
<h3 id="8-상속"><strong>8. 상속</strong></h3>
<p>Python에서 상속은 클래스 정의 시 괄호 안에 부모 클래스를 지정합니다.</p>
<pre><code class="language-python">class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return &quot;Woof!&quot;

class Cat(Animal):
    def speak(self):
        return &quot;Meow!&quot;

dog = Dog()
cat = Cat()

print(dog.speak())  # Woof!
print(cat.speak())  # Meow!</code></pre>
<hr>
<h3 id="9-클래스-간-di-dependency-injection"><strong>9. 클래스 간 DI (Dependency Injection)</strong></h3>
<p>Python에서 의존성 주입은 생성자를 통해 구현할 수 있습니다.</p>
<pre><code class="language-python">class Engine:
    def start(self):
        return &quot;Engine started&quot;

class Car:
    def __init__(self, engine: Engine):
        self.engine = engine

    def drive(self):
        return self.engine.start()

# DI 사용
engine = Engine()
car = Car(engine)

print(car.drive())  # Engine started</code></pre>
<hr>
<h3 id="10-자주-쓰는-자료구조"><strong>10. 자주 쓰는 자료구조</strong></h3>
<h4 id="리스트"><strong>리스트</strong></h4>
<pre><code class="language-python">numbers = [1, 2, 3, 4, 5]
numbers.append(6)
numbers.remove(2)</code></pre>
<h4 id="딕셔너리"><strong>딕셔너리</strong></h4>
<pre><code class="language-python">person = {&quot;name&quot;: &quot;John&quot;, &quot;age&quot;: 30}</code></pre>
<h4 id="셋"><strong>셋</strong></h4>
<pre><code class="language-python">unique_numbers = {1, 2, 3, 3, 2}
print(unique_numbers)  # {1, 2, 3}</code></pre>
<h4 id="큐-queue"><strong>큐 (Queue)</strong></h4>
<pre><code class="language-python">from collections import deque

queue = deque([1, 2, 3])
queue.append(4)
queue.popleft()  # 1 제거</code></pre>
<h4 id="스택-stack"><strong>스택 (Stack)</strong></h4>
<pre><code class="language-python">stack = []
stack.append(1)
stack.append(2)
stack.pop()  # 2 제거</code></pre>
<h4 id="우선순위-큐"><strong>우선순위 큐</strong></h4>
<pre><code class="language-python">import heapq

heap = []
heapq.heappush(heap, 10)
heapq.heappush(heap, 5)
heapq.heappush(heap, 20)

print(heapq.heappop(heap))  # 5</code></pre>
<hr>
<h3 id="11-파일-입출력"><strong>11. 파일 입출력</strong></h3>
<p>Python에서 파일 입출력은 간단합니다.</p>
<pre><code class="language-python"># 파일 쓰기
with open(&quot;example.txt&quot;, &quot;w&quot;) as f:
    f.write(&quot;Hello, Python!&quot;)

# 파일 읽기
with open(&quot;example.txt&quot;, &quot;r&quot;) as f:
    print(f.read())</code></pre>
<hr>
<h3 id="12-예외-처리"><strong>12. 예외 처리</strong></h3>
<p>Python에서 예외 처리는 <code>try-except</code> 블록을 사용합니다.</p>
<pre><code class="language-python">try:
    x = 1 / 0
except ZeroDivisionError:
    print(&quot;Cannot divide by zero&quot;)
finally:
    print(&quot;Execution complete&quot;)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[kotlin 기본 문법 정리]]></title>
            <link>https://velog.io/@b_jim/kotlin-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@b_jim/kotlin-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Fri, 13 Dec 2024 15:16:39 GMT</pubDate>
            <description><![CDATA[<h2 id="변수">변수</h2>
<p>코틀린의 변수는 두 가지 키워드로 선언 가능합니다.</p>
<ul>
<li>val: 변경 불가능한 변수 (immutable, read-olny)</li>
<li>var: 변경 가능한 변수 (mutable)<pre><code class="language-kotlin">val name: String = &quot;kotlin&quot;
var age: Int = 30 </code></pre>
코틀린은 타입 추론 덕분에 타입을 명시하지 않아도 됩니다.<pre><code class="language-kotlin">val name = &quot;kotlin&quot;
var age = 30</code></pre>
</li>
</ul>
<h2 id="데이터-타입">데이터 타입</h2>
<p>코틀린에서 사용하는 주요 기본 타입</p>
<ul>
<li>int</li>
<li>double</li>
<li>boolean</li>
<li>char</li>
<li>string</li>
</ul>
<h2 id="문자열과-변수">문자열과 변수</h2>
<p>코틀린에서 문자열에 변수 표현식은 아래와 같이 사용됩니다.</p>
<pre><code class="language-kotlin">val name: String = &quot;kotlin&quot;
println(&quot;Hello, $name!&quot;) // Hello, kotlin!
println(&quot;1 + 1 = ${1 + 1}&quot;) // 1 + 1 = 2</code></pre>
<h2 id="조건문">조건문</h2>
<p>if문 기본 사용법</p>
<pre><code class="language-kotlin">// 기본 사용법
if () {

} else if () {

} else {

}

// 좀 더 간결하게 사용하기
val a = 1
val b = 2
val max = if (a &gt; b) &quot;틀렸어!&quot; else &quot;정답!&quot;</code></pre>
<p>조건이 복잡하거나 많을 경우 더 간결하게 when문을 사용할 수 있습니다.</p>
<pre><code class="language-kotlin">val number: Int = 0

val result = when {
    number &gt; 0 -&gt; &quot;양수&quot;
    number == 0 -&gt; &quot;0&quot;
    else -&gt; &quot;음수&quot;
}</code></pre>
<h2 id="반복문">반복문</h2>
<p>일반적인 반복문 사용법</p>
<pre><code class="language-kotlin">for (i in 1..5) { // 1~5

}

for (i in 1..10 step 2) { // 2씩 증가

}

for (i in 10 downTo 1) { // 10~1까지 감소

}

for (i in 1 until 5) { // 1~4까지 5는 생략

}</code></pre>
<p>배열이나 리스트</p>
<pre><code class="language-kotlin">val fruits = listOf(&quot;사과&quot;, &quot;바나나&quot;, &quot;귤&quot;)

for (fulit in fulits) {
    println(fulit)
}</code></pre>
<h2 id="함수">함수</h2>
<pre><code class="language-kotlin">fun greet (name: String): String {
    return &quot;Hello, $name!&quot;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[php8.0 주요 문법 변화 ]]></title>
            <link>https://velog.io/@b_jim/php8.0-%EC%A3%BC%EC%9A%94-%EB%B3%80%ED%99%94-%EB%AC%B8%EB%B2%95</link>
            <guid>https://velog.io/@b_jim/php8.0-%EC%A3%BC%EC%9A%94-%EB%B3%80%ED%99%94-%EB%AC%B8%EB%B2%95</guid>
            <pubDate>Mon, 05 Aug 2024 06:58:56 GMT</pubDate>
            <description><![CDATA[<p>php 8.0 이후 주요 문법 변화에 대해 설명한다.</p>
<h2 id="named-params">Named Params</h2>
<p>기존엔 중간 파라미터 값을 사용하지 않기 위해 default나 Null로 처리하던 것들을 Named Params를 이용해 쉽게 처리가 가능해젔다.</p>
<h3 id="before">Before</h3>
<pre><code class="language-php">function getUser(string $name, string $type = null, string $address)
{

};

getUser(&#39;테스트&#39;, null, &#39;서울특별시 강남구&#39;);
</code></pre>
<h3 id="after">After</h3>
<pre><code class="language-php">function getUser(string $name, string $type = null, string $address)
{

};

getUser(name: &#39;테스트&#39;, address: &#39;서울특별시 강남구&#39;);
</code></pre>
<h2 id="nullsafe-operator">Nullsafe Operator</h2>
<p>null인 객체를 참조할 때 방어코드로 작성할 수 있다.</p>
<pre><code class="language-php">$user = new User();
$user?-&gt;name;</code></pre>
<h2 id="match">Match</h2>
<p>swith문을 대신해 더 간략하게 인라인으로 작성이 가능해젔다.</p>
<h3 id="before-1">Before</h3>
<pre><code class="language-php">switch ($type) {
    case &#39;business&#39;:
        $result = &quot;기업유저&quot;;
        break;
    default :
          $result = &quot;일반유저&quot;;
        break;
}</code></pre>
<h3 id="after-1">After</h3>
<pre><code class="language-php">$result =. match ($type) {
    &#39;business&#39; =&gt; &quot;기업유저&quot;,
     default =&gt; &quot;일반유저&quot;,
};</code></pre>
<h2 id="constructor-property-promotion">Constructor property promotion</h2>
<p>생성자 문법을 좀 더 간략하게 사용이 가능해젔다. 또한 psr-12 생성자 마지막에 &#39;,&#39; 처리가 가능해젔다.</p>
<h3 id="before-2">Before</h3>
<pre><code class="language-php">private $handler;
public function __construct(
    Handler $handler
)
{
    parent::__construct();
    $this-&gt;handler = $handler;
}</code></pre>
<h3 id="after-2">After</h3>
<pre><code class="language-php">public function __construct(
    private readonly $handle,
) {}
</code></pre>
<h2 id="return-type-mixed">Return Type Mixed</h2>
<p>문서에만 존재하던 Mixed가 실제로 사용이 가능해젔다.</p>
<pre><code class="language-php">class A
{
    public function bar(): mixed
}

class B extends A
{
    public function bar(): int
}</code></pre>
<h2 id="union-types">Union Types</h2>
<pre><code class="language-php">interface AInterface
{
    public function foo(): string|int
}

class B implements AInterface
{
    public function foo(): string|int
    {

    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[IDE 라이브 템플릿 생성법]]></title>
            <link>https://velog.io/@b_jim/IDE-%EB%A7%A4%ED%81%AC%EB%A1%9C-%EC%83%9D%EC%84%B1%EB%B2%95</link>
            <guid>https://velog.io/@b_jim/IDE-%EB%A7%A4%ED%81%AC%EB%A1%9C-%EC%83%9D%EC%84%B1%EB%B2%95</guid>
            <pubDate>Tue, 22 Aug 2023 01:56:37 GMT</pubDate>
            <description><![CDATA[<p>작업을 하다보면 자주 사용하는 패턴을 단축키로 등록하고 싶을 때가 있습니다. IDE의 기능을 사용하여 해당 기능 구현이 가능합니다.</p>
<h3 id="단축키-등록하기">단축키 등록하기</h3>
<ol>
<li><p>Setting -&gt; Editor -&gt; LiveTemplate -&gt; php
<img src="https://velog.velcdn.com/images/b_jim/post/8b133649-3087-4ce3-b2a5-1dacb879febc/image.png" alt=""></p>
</li>
<li><p>+버튼으로 라이브 템플릿을 생성하고 변경을 클릭하여 php로 변경 후 약어와 템플릿 텍스트를 설정합니다.
<img src="https://velog.velcdn.com/images/b_jim/post/782a8b99-4054-41f0-9541-9befab2a4cf6/image.png" alt=""></p>
</li>
<li><p>에디터로 가서 pubfc를 입력 후 Tap키를 눌러서 설정한 템플릿 텍스트가 잘 나오는지 확인합니다.</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[IDE와 JIRA 연동해서 이슈 관리하기]]></title>
            <link>https://velog.io/@b_jim/IDE%EC%99%80-JIRA-%EC%97%B0%EB%8F%99%ED%95%B4%EC%84%9C-%EC%9D%B4%EC%8A%88-%EA%B4%80%EB%A6%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@b_jim/IDE%EC%99%80-JIRA-%EC%97%B0%EB%8F%99%ED%95%B4%EC%84%9C-%EC%9D%B4%EC%8A%88-%EA%B4%80%EB%A6%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 22 Aug 2023 01:45:56 GMT</pubDate>
            <description><![CDATA[<p>JIRA와 IDE를 연동하는 방법을 들었는데 유용한거 같아서 한번 사용해보기로 했습니다.</p>
<h3 id="jira-tocken-얻기">JIRA TOCKEN 얻기</h3>
<ol>
<li>JIRA에 로그인 후 우측 프로필 옆 설정모양 이모티콘 클릭 후 Atlassian 계정 설정으로 들어가 줍니다.</li>
<li>보안탭에 들어가서 API 토큰 만들기 및 관리를 클릭합니다.
<img src="https://velog.velcdn.com/images/b_jim/post/dd83b396-7555-46fe-bc33-581beb443641/image.png" alt=""></li>
<li>API 토큰 만들기를 클릭하고 새로운 토큰을 생성하고 키를 복사합니다.</li>
</ol>
<h3 id="ide-설정하기">IDE 설정하기</h3>
<ol>
<li>Preferences -&gt; Tools-&gt; Tasks -&gt; Services에 들어갑니다. (한글버전: 설정 -&gt; 도구 -&gt; 작업 -&gt; 서버)</li>
<li>+버튼으로 JIRA를 생성하고 위에서 생성한 토큰을 넣어주면 끝납니다.
<img src="https://velog.velcdn.com/images/b_jim/post/5fda91ad-477b-4507-bcae-815bc99b291a/image.png" alt=""></li>
</ol>
<h3 id="나에게-할당된-이슈-불러오기">나에게 할당된 이슈 불러오기</h3>
<p>저는 Mac을 사용중이고 Mac 기준으로 oprtion + shift + n 키로 현재 나에게 할당된 이슈 목록을 불러올 수 있습니다. 목록을 불러오면 자동으로 해당 이슈ID로 브랜치가 새로 생성됩니다.</p>
<p>브랜치 생성 옵션은 설정에서 변경 가능합니다.
Preferences -&gt; Tools-&gt; Tasks
<img src="https://velog.velcdn.com/images/b_jim/post/f8a54292-292b-4627-9694-a8791df757db/image.png" alt=""></p>
<p>참고
<a href="https://wani-coding.tistory.com/135">https://wani-coding.tistory.com/135</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Repository Pattern(3)]]></title>
            <link>https://velog.io/@b_jim/Repository-Pattern3</link>
            <guid>https://velog.io/@b_jim/Repository-Pattern3</guid>
            <pubDate>Thu, 08 Jun 2023 12:08:36 GMT</pubDate>
            <description><![CDATA[<p>이전에 각 계층간의 공통으로 사용해야 되는 법을 알아봤으니 이제 유저를 조회하는 쿼리는 어디에 어떤 식으로
작성하는지를 알아보려 한다.</p>
<p>파일 경로는 아래와 같이 생성했다.</p>
<pre><code>app
 ㄴ Http
      ㄴ Controllers
       ㄴ User
         ㄴ UserController.php
 ㄴ Models
     ㄴ User
       ㄴ User.php
 ㄴ Services
     ㄴ User
       ㄴ UserService.php
 ㄴ Repositoies
     ㄴ User
       ㄴ UserRepository.php
     ㄴ BaseRepository.php
 ㄴ Interfaces
     ㄴ User
       ㄴ UserInterface.php
     ㄴ BaseInterface.php</code></pre><p>작업은 가장 먼저 UserInterface를 만들 예정이다.</p>
<h2 id="userinterface">UserInterface</h2>
<p>BaseInterface를 상속받고 있으므로 처음 추상화 시켰던 매서드들은 그대로 사용할 수 있다.
그러므로 만약 전체를 조회하는 쿼리만 사용한다면 UserInterface 안에는 따로 작성하지 않아도 된다.
하지만 BaseInterface에서 선언한 매서드 외에 특정 조건의 쿼리를 추가로 사용한다면 아래와 같이 추가해주자.
예를 들어 권한이 Admin인 회원들을 찾아오는 쿼리를 작성해보자.</p>
<p><em>app/Interfaces/User/UserInterface.php</em></p>
<pre><code class="language-php">&lt;?php

namespace App\Interfaces\User;

use App\Interfaces\BaseInterface;

interface UserInterface extends BaseInterface
{
    /**
     * @return LengthAwarePaginator
     */
    public function getAdmin(): \Illuminate\Database\Eloquent\Collection
}
</code></pre>
<p>인터페이스를 다 작성했으면 구현 클래스를 작성해야 한다.</p>
<h2 id="userrepository">UserRepository</h2>
<p><em>app/Repositories/User/UserRepository.php</em></p>
<pre><code class="language-php">&lt;?php

namespace App\Repositories\User;

use App\Models\User;
use App\Repositories\BaseRepository;
use App\Interfaces\User\UserInterface;
use Illuminate\Database\Eloquent\Collection;

class UserRepository extends BaseRepository implements UserInterface
{
    protected $model;
    public function __construct(User $model)
    {
        parent::__construct($model);
        $this-&gt;model = $model;
    }

    /**
     * @return Collection
     */
    public function getAdmin(): Collection
    {
        return $this-&gt;model-&gt;where(&#39;qualification&#39;, &#39;admin&#39;)-&gt;get();
    }


}
</code></pre>
<p>BaseRepostory를 extends하고 있어서 다른 매서드들은 그대로 사용할 수 있지만 UserInterface는 implements이기 때문에 선언해놓은 매서드들을 반드시 override해야 한다.</p>
<h2 id="userservice">UserService</h2>
<p>다음은 간단한 쿼리를 가지고 오는 비즈니스 로직이다.
앞에 Repository에 작성한 매서드를과는 달리 좀 더 비즈니스적인 작명을 해준다.</p>
<p><em>app/Service/UserService.php</em></p>
<pre><code class="language-php">&lt;?php

namespace App\Services\User;

use App\Interfaces\Users\UserInterface;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;

class UserService
{
    private $repository;
    public function __construct(UserInterface $repository)
    {
        $this-&gt;repository = $repository;
    }

    /**
     * @return Collection
     */
    public function getUserList(): Collection
    {
        return $this-&gt;repository-&gt;all();
    }

    /**
     * @return Model
     */
    public function getUser($id): Model
    {
        return $this-&gt;repository-&gt;findId($id);
    }

    /**
     * @return Collection
     */
    public function getAdminUsers(): Collection
    {
        return $this-&gt;repository-&gt;getAdmin();
    }
}
</code></pre>
<h2 id="usercontroller">UserController</h2>
<p><em>app/http/Controller/User/UserController.php</em></p>
<pre><code class="language-php">&lt;?php

namespace App\Http\User\Controllers;

use App\Interfaces\User\UserInterface;
use App\Services\User\UserService;
use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;

class UserController extends Controller
{
    private $userService;
    public function __construct(UserService $userService){
        $this-&gt;userService = $userService;
    }

    /**
     * @return Collection
     */
    public function list(): Collection
    {
        return $this-&gt;userService-&gt;getUserList();
    }

    public function find($id): Model
    {
        return $this-&gt;userService-&gt;findId($id);
    }

    public function findAdmin(): Collection
    {
        return $this-&gt;userService-&gt;getAdminUsers();
    }

}</code></pre>
<p>마지막으로 컨트롤러에서 Service에 있는 비즈니스 로직을 가져오면 작업이 마무리된다.
컨트롤러에서 return은 예시일뿐 실제로는 Response등등으로 대체된다.</p>
<p>이상 Repository Pattern 포스팅을 마친다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Repository Pattern(2)]]></title>
            <link>https://velog.io/@b_jim/Repository-Pattern2</link>
            <guid>https://velog.io/@b_jim/Repository-Pattern2</guid>
            <pubDate>Mon, 05 Jun 2023 08:45:54 GMT</pubDate>
            <description><![CDATA[<p>본격적으로 Laravel을 이용하여 각 계층을 어떤 식으로 사용하는지 실습해보려 한다.
기본적인 예제만 다룰 예정이므로 회원 정보를 조회하는 로직을 예제로 사용한다.</p>
<p>필자는 아래와 같은 방법으로 사용했다.
(파일명과 파일경로는 자유이므로 꼭 필자의 경로와 같이 사용하지 않아도 무방하다.)</p>
<pre><code>app
 ㄴ Http
      ㄴ Controllers
 ㄴ Models
 ㄴ Services
 ㄴ Repositoies
 ㄴ Interfaces</code></pre><p>작업은 가장 먼저 제일 많이 사용되는 매서드 들을 추상화 시킬 예정이다.</p>
<h2 id="interface">Interface</h2>
<p><em>app/Interfaces/BaseInterface.php</em></p>
<pre><code class="language-php">&lt;?php

namespace App\Interfaces\Interfaces;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;

interface BaseInterface
{
    /**
     * @return Collection
     */
    public function all(): Collection;

    /**
     * @param int $id
     * @return Model
     */
    public function findId(int $id): Model;

    /**
     * @param array $data
     * @return Model
     */
    public function create(array $data = []): Model;

    /**
     * @param array $data
     * @return bool
     */
    public function update(array $data = []): bool;

    /**
     * @param array $data
     * @return bool
     */
    public function delete(array $data = []): bool;

}
</code></pre>
<p>해당 내용은 가장 기본적으로 사용되는 <code>ORM</code>의 매서드를 추상화 시키는 과정이다.
해당 패턴에 관련해서는 디자인 패턴(Factory Method Pattern)을 공부하는 걸 추천한다.</p>
<p>다음은 구현 클래스를 작성할 차례다.</p>
<h2 id="repositoty">Repositoty</h2>
<p><em>app/Repositories/BaseRepository.php</em></p>
<pre><code class="language-php">&lt;?php

namespace App\Repositories;

use App\Interfaces\BaseInterface;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;

class BaseRepository implements BaseInterface
{
    private Model $model;
    public function __construct(Model $model)
    {
        $this-&gt;model = $model;
    }

    /**
     * @param array $columns
     * @param array $relations
     * @return : Collection
     */
    public function all(array $columns = [&#39;*&#39;], array $relations = []): Collection
    {
        return $this-&gt;model-&gt;get($columns);
    }

    /**
     * @param int $id
     * @param array $columns
     * @return Model
     */
    public function findId(int $id, array $columns = [&#39;*&#39;], array $relations = []): Model
    {
        return $this-&gt;model-&gt;find($id, $columns);
    }

    /**
     * @param array $data
     * @return Model
     */
    public function create(array $data = []): Model
    {
        return $this-&gt;model-&gt;create($data);
    }

    /**
     * @param array $data
     * @return bool
     */
    public function update(array $data = []): bool
    {
        return $this-&gt;model-&gt;update($data);
    }

    /**
     * @param array $data
     * @return bool
     */
    public function delete(array $data = []): bool
    {
        return $this-&gt;model-&gt;delete($data);
    }

}</code></pre>
<p>해당 BaseRepository는 BaseInterface를 <strong>다중 상속(implements)</strong> 하고 있다.
이러한 경우 추상화되어있는 부모의 메소드를 반드시 <strong>재정의(Override)</strong> 해야 한다.</p>
<h2 id="의존성-주입dependency-injection">의존성 주입(Dependency Injection)</h2>
<p>구현체에 매서드를 사용하기 위해서는 인터페이스를 바인딩 해야 한다. Laravel의 컨테이너를 이용하면 인터페이스와 구현체를 쉽게 인스턴스화 할 수 있다.
필자는 관리 중인 Repository를 한 파일에서 관리하기 위해 따로 파일을 생성할 예정이다.</p>
<pre><code class="language-php">php artisan make:provider RepositoryServiceProvider</code></pre>
<p><em>Config/app.php</em></p>
<pre><code class="language-php">&#39;providers&#39; =&gt; [
    App\Providers\RepositoryServiceProvider::class,
]</code></pre>
<p>까지 등록을 해준다. 그리고 생성된 파일에 인터페이스를 바인딩 한다.
<em>app/Providers/RepositoryServiceProvider.php</em></p>
<pre><code class="language-php">&lt;?php

namespace App\Providers;

use App\Repositories\Eloquent\BaseRepository;
use App\Repositories\Interfaces\BaseInterface;
use Illuminate\Support\ServiceProvider;

class RepositoryServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        $this-&gt;app-&gt;bind(BaseInterface::class, BaseRepository::class);
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}
</code></pre>
<p>기본적인 추상화 과정은 끝났다. 다음 포스팅에서는 해당 매서드들과 추가적인 매서드를 통해서 회원 조회를 하는 로직을 완성해보자.</p>
<p>참고 자료
<a href="https://vuxy.tistory.com/entry/Laravel-8-%EC%97%90%EC%84%9C-Repository-%ED%8C%A8%ED%84%B4-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0">https://vuxy.tistory.com/entry/Laravel-8-%EC%97%90%EC%84%9C-Repository-%ED%8C%A8%ED%84%B4-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</a>
<a href="https://blog.decorus.io/php/2018/07/04/laravel-dependency-injection-container.html">https://blog.decorus.io/php/2018/07/04/laravel-dependency-injection-container.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Repository Pattern(1)]]></title>
            <link>https://velog.io/@b_jim/Repository-Pattern</link>
            <guid>https://velog.io/@b_jim/Repository-Pattern</guid>
            <pubDate>Mon, 05 Jun 2023 07:00:23 GMT</pubDate>
            <description><![CDATA[<p>MVC 패턴을 사용하여 개발하다 보면 비즈니스 로직을 담고 있는 파일들이 점점 커지는 것을 느낄 것이다. 
서비스가 커질수록 비즈니스 로직이 복잡해지기 시작했고 유지보수가 점점 힘들어진다고 느꼈다.</p>
<h2 id="문제점">문제점</h2>
<p>&quot;Controller는 최대한 가볍게&quot;라는 원칙에 따라 개발했다면 Model에서 비즈니스 로직을 작성하는 경우가 심심치 않게 생길 것이다. 이를 좀 더 보완하기 위해 Service계층을 따로 작성하여 Model에 작성한 비지니스 로직을 Service에서 작성하기 시작했다. 하지만 하나의 계층이 나뉘었을 뿐 여전히 비즈니스 로직에 대한 유지보수는 쉽지 않았다.</p>
<p>비즈니스 로직이 복잡해질수록 오류가 났을 때 오류를 해결하기 위해서 내가 작성한 비즈니스 로직에서 문제점을 계속 찾아야 했고 이로 인해서 유지보수가 점점 복잡해지기 시작했다고 느꼈다. 이를 해결하기 위해 계층을 좀 더 세분화 시킬 필요가 있었다.</p>
<h2 id="전략">전략</h2>
<p>각각의 계층을 나누고 각 계층에서는 주어진 역할만 수행할 수 있게끔 로직을 작성하여 유지보수의 효율성을 높인다.</p>
<p><strong><em>Model</em></strong> : 데이터 베이스와의 연결 계층으로 사용한다.
<strong><em>Controller</em></strong> : Model과 View를 연결하는 계층으로 사용한다.
<strong><em>Service</em></strong> : 비즈니스 로직을 작성하는 계층으로 사용한다.
<strong><em>Repository</em></strong> : 비즈니스 로직에 필요한 쿼리를 작성하는 계층으로 사용한다.
<strong><em>Interface</em></strong> : 사용할 함수를 정의해 놓는 계층으로 사용한다.</p>
<h2 id="장점">장점</h2>
<ol>
<li>비지니스 로직과 DB 접근 로직 간의 결합 도가 낮아진다.</li>
<li>각 계층 간의 수정이 가능해진다.</li>
<li>결합 도가 낮아져서 테스트 코드를 작성하기 유리해진다.</li>
<li>추상화 적 요소를 가지고 있어서 객체의 공통적인 속성과 기능을 정의하는 것이 가능해진다.</li>
</ol>
<h2 id="단점">단점</h2>
<ol>
<li>모든 객체지향의 단점이겠지만 개발 속도가 느리다.</li>
<li>관리해야 할 파일이 많아진다.</li>
</ol>
<h2 id="마치며">마치며</h2>
<p>다음 포스팅에서는 실제로 해당 계층들이 어떻게 사용되는지를 알아보자.
실습에선 Laravel을 사용할 예정이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[도전을 좋아하는 개발자 백지민 입니다.]]></title>
            <link>https://velog.io/@b_jim/intro</link>
            <guid>https://velog.io/@b_jim/intro</guid>
            <pubDate>Thu, 01 Jun 2023 14:03:26 GMT</pubDate>
            <description><![CDATA[<hr>
<p>👨🏻‍💻 백지민
✉️ <a href="mailto:wmlals0002@gmail.com">wmlals0002@gmail.com</a>
🧷 <a href="https://github.com/jmlog" target="_blank"> https://github.com/jmlog</a>
🇰🇷 South Korea</p>
<hr>
<h2 id="introduce">Introduce.</h2>
<p>안녕하세요 도전을 좋아하는 개발자 백지민 입니다.
새로운 환경이나 새로운 것에 도전하는 것을 좋아합니다. 
디자인부터 시작하여 퍼블리셔, 그리고 백엔드 개발자가 되기까지 끊임없는 노력과 도전을 해왔습니다.</p>
<p>스타트업의 스타팅 개발자로 입사하여 누적투자 235억 원, 규모 80명의 회사로 성장할 때까지 웹/앱 기능개발, 배포, 운영 등 핵심 개발을 담당한 경험이 있습니다. 
또한 업무 초반 급급하게 개발하던 환경을 체계적으로 개선하기 위해 팀별 업무 내용 공유, 일정 공유, 업무환경 개선 등 더 나은 환경을 주도하고 개선한 경험이 있습니다.</p>
<p>믿고 의지할 수 있는 동료들과 함께 일했습니다.
저의 동료들은 서로가 서로에게 힘이 돼주었고, 혼자서는 해낼 수 없는 일도 항상 옆에서 같이해주며 앞으로 달려 나가는 길에 큰 힘이 되어주었습니다.
믿을 수 있고 의지할 수 있는 동료를 만들어서 어떠한 일이든 함께 이끌어 나아가는 게 제가 생각하는 업무의 핵심 가치입니다.</p>
<p>앞으로도 미래를 향해 끝없이 도전하고 성장하는 개발자가 되고 싶습니다.</p>
<hr>
<h2 id="experience">Experience.</h2>
<h3 id="피터팬의-좋은방-구하기">피터팬의 좋은방 구하기</h3>
<p>2023.07 ~ 재직중
개발팀 / 매니저</p>
<p>[담당업무]
피터핀의 좋은방 구하기의 사용자 웹 / 중개사 관리자 페이지 / API서버 등 신규 기능개발 및 유지보수를 전담하였습니다.</p>
<p>[기술 스택]
    - PHP
    - Laravel Framework / docker
    - Mssql
    - GitHub
    - DockerCompose
    - Aws
    - PostMan
    - Jira</p>
<p>[주요업무]
    - 아파트 신규사업 개발
    - 알림톡 전송서버 개발</p>
<h3 id="패션플러스">패션플러스</h3>
<p>2022.10 ~ 2023.07
개발팀 / 프리랜서</p>
<p>[담당업무]
패션플러스의 CS관리자 / 입점 업주 관리자 페이지의 신규기능 개발 및 유지보수를 전담하였습니다.</p>
<p>[기술 스택]
    - PHP
    - Laravel Framework / valet
    - Mssql
    - GitHub</p>
<h3 id="에이치엠씨네트웍스">에이치엠씨네트웍스</h3>
<p>2020.03 ~ 2022.08
개발팀 / 선임연구원</p>
<p>[담당업무]
케어네이션 초기부터 앱을 구축 하였고, 주로 사용자 앱의 신규 기능개발, 유지보수, 사용자 앱 RESTful API 제작을 주로 담당하였습니다. 
그 외 최고 관리자, CS 관리자를 구축하고 신규 기능개발, 장애 대응, 유지보수를 전담하였습니다.</p>
<p>[기술 스택]
    - PHP
    - Laravel Framework / valet
    - Mysql
    - Ajax
    - Git lab
    - Aws
    - PostMan</p>
<p>[주요업무]
    - 보호자 앱 1.0/2.0 기능개발 및 유지보수
    - 간병인 앱 1.0 기능개발 및 유지보수
    - 최고관리자, CS관리자 기능개발 및 유지보수
    - RESTful API
    - Git을 활용한 지속적인 소스 통합
    - 테스트서버 배포</p>
<p>[상세업무]
일정 관리/복약 서비스 기능 개발 및 기능 개선 작업
    - 기획서를 리뷰하며 커뮤니케이션을 통해 이슈 해결
    - 기획/개발 의도에 맞게 DB 설계 및 수정
    - 간병인의 간병 일정 관리 효율 향상
    - 간병인의 환자 복약 편의성 증가
    - 일정 등록, 수정, 삭제 속도 개선 5.32s =&gt; 0.22s</p>
<p>공공데이터를 활용한 병원, 약국, 상조/장례 시설 찾기 기능 개발 및 개선
    - 공공데이터 API 사전 조사 및 데이터 마이그레이션
    - 네이버 지도, 카카오맵 등 지도 시설 찾기 관련 앱 사전 조사
    - 간병인 가까운 병원에 일감찾기 기대
    - 공공데이터 API 스로틀링 제한 우회 및 데이터 커스텀
    - 시설 찾기 속도 개선 2.23s =&gt; 0.32s</p>
<p>커뮤니티 댓글/대댓글 기능 개선
    - 계층형 구조로 DB구조 변경
    - N+1 쿼리 문제 해결
    - 쿼리 속도 개선 1.62s =&gt; 0.11s</p>
<p>데이터 암/복호화
    - Request Data AES암/복호화
    - 민감한 데이터 RSA암/복호화
    - Request Data 위변조 체크 SHA-256 암호화
    - Middleware 복호화 과정에 문제/위변조가 생기면 로그 전송
    - 데이터의 무결성 보장
    - 개인, 기업, 금융정보등 민감한 데이터 보호</p>
<p>삼성화재 보험 가입 API를 이용한 간병인 배상책임 보험 가입 기능 개발
    - 삼성화재 API 문서 개선 요청
    - CS팀 보험 관련 인바운드 콜수 개선
    - 운영팀 보험 관련 업무 효율 향상
    - 매달 수기로 작성하던 보험 가입을 자동화</p>
<p>지원한 간병인의 업무능력 평가 기능 개발
    - 보호자 간병인 선택률 증가 기대
    - 간병인 면접 제안 콜수 개선
    - 간병인 공고 매칭률 약 30% 증가</p>
<p>간병인 대신 공고 지원기능 개발
    - 간병인 공고 매칭률 약 50% 증가
    - 지원 관련 CS 아웃바운도 콜수 개선</p>
<p>관리자 결제 취소/취소 예상 금액 계산기 기능 개발
    - 수기로 계산해서 하던 업무를 자동화
    - 취소 실수율 약 80% 이상 개선
    - CS/운영팀 업무 효율 향상</p>
<p>일일 부가세/정산 데이터 생성 및 엑셀 다운로드 기능 개발
    - Schedule을 활용하여 일일 부가세/정산 데이터 생성
    - 데이터 정확도 약 95% 이상 증가
    - 회계팀 업무 반 자동화</p>
<p>[그 외]
    - 간병인 유동 인구 데이터 통계 및 웹사이트(DataLap)로 제작 -&gt; 후속 투자유치 
      성공
    - 결제 실패시 슬랙으로 Log 전송 기능 개발 -&gt; 긴급 장애를 빠르게 대처
    - ORM을 활용하여 데이터베이스 연동 단순화 및 개발 생산성 향상
    - Collection method를 활용하여 데이터 가공 -&gt; 코드의 가시성 증가 및 유지보 
      수 향상
    - Query Scope를 활용하여 특정 조건 쿼리 -&gt; 코드의 재활용성 증가
    - Query Builder를 활용하여 보다 복잡한 쿼리 작성 -&gt; 코드의 생산성, 재활용성 
      증가
    - Transaction과 Observer를 활용하여 데이터의 정합성 유지
    - PostMan을 활용한 API 명세서 작성 -&gt; Front와, 외주, 새로운 멤버들과의 협업 
      증대</p>
<p>[성과]
    - 케어네이션 앱 출시
    - 동종 업계 1위 달성
    - 연매출 0원 -&gt; 80억으로 증가
    - 누적 투자금 235억 유치
    - 앱 다운로드 수 10만+
    - 누적회원 10만
    - MAU 3.5만</p>
<br />

<h3 id="rescue-pat">RESCUE PAT</h3>
<p>2023.03 ~ 진행중</p>
<p>[프로젝트 소개]
평소 관심 있던 분야를 개발하고자 만든 사이드 프로젝트 겸, 새로운 기술들을 적용해보기 위한 토이 프로젝트입니다.</p>
<p>[기술 스택]
    - PHP
    - Laravel Framework / sail
    - Mysql 
    - GitHub / GitHub Action
    - Aws (ec2, rds, s3, code deploy)
    - CI/CD</p>
<p>[주요업무]
Github Action과 Aws Code Deploy를 활용한 CI/CD 구축
    - 코드의 변경 사항을 지속해서 통합
    - 테스트 코드에서의 에러를 빠르게 발견 및 대응
    - pull request / push 등 동작 한 번으로 배포가 가능
    - 짧은 주기로 변경 사항을 테스트하고 배포가 가능</p>
<p>TDD(테스트 주도 개발) 도입
    - 코드를 작성해 나가며 예외 처리 후 메인 로직에 작성하여 코드 품질 향상
    - 테스트를 검증하기 때문에 버그를 조속히 발견 및 대응 가능
    - 문서화 기능 대처 가능</p>
<p><a href="https://velog.io/@b_jim/Repository-Pattern">Repository Pattern 도입</a>
    - 코드의 재활용성 증가
    - 각 계층 간의 결합도를 낮춰서 변경이 필요할 시 해당 계층만 수정이 가능
    - 데이터 엑세스 로직을 캡슐화하여 여러 곳에서 재활용 가능
    - 시스템의 유연성과 확장성 증대
    - 객체 지향적 설계</p>
<br />

<h3 id="인조이웍스">인조이웍스</h3>
<p>2019.02 ~ 2020.02
개발팀 / 사원</p>
<p>[회사소개]
매년 10개 이상의 프로젝트를 개발하는 SI 업체</p>
<p>[기술 스택]
    - PHP
    - Laravel Framework / valet
    - Mysql
    - Ajax
    - Git lab
    - Aws</p>
<p>[주요업무]
    - 관리자 페이지 개발
    - 앱 기능 개발
    - Scss를 활용한 관리자 UI 개발
    - BootStarp을 활용한 관리자 UI 개발
    - Git을 활용한 지속적인 소스 통합</p>
<p>[상세업무]
휴넷 합격마법사 홈페이지
    - 문제풀이 기능 개발
    - 문제풀이 해설 기능 개발
    - 자주 틀리는 문제 및 약점 공유 기능 개발
    - 과목별 문제등록 기능 개발
    - 과목별 통계페이지 개발</p>
<p>스타플레이
    - 생방송 전 원하는 아이돌에게 투표기능 개발
    - 좋아하는 아이돌 홍보 게시판 기능 개발
    - 리워드 기능 개발</p>
<p>폴릭
    - Kakao Map Api를 활용한 마커 작업
    - 사진기자 등록 기능 개발
    - 나에게 가까운 사진기자 찾기 기능 개발
    - 사진기자와 소비자 매칭기능 개발</p>
<hr>
<h2 id="skills">Skills.</h2>
<ul>
<li>Front-End : Html5/Css3, jQuery, JavaScript, Sass</li>
<li>Back-End : Php, Laravel, Java, Spring Boot</li>
<li>Data : Mysql</li>
<li>Infra : Aws(EC2, RDS, CodeDeploy, S3 등), Docker</li>
</ul>
<hr>
<h2 id="education">Education.</h2>
<p>2011.03 ~ 2015.02 인덕대학교 디자인 멀티미디어 전공</p>
<hr>
]]></description>
        </item>
    </channel>
</rss>