<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>dongc.log</title>
        <link>https://velog.io/</link>
        <description>세상에 기여하는 사람이 되고 싶습니다.</description>
        <lastBuildDate>Sun, 14 Jan 2024 06:18:14 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>dongc.log</title>
            <url>https://velog.velcdn.com/images/_dongd9173/profile/211515fc-e73b-4cf3-8043-c65d9c1e10fb/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. dongc.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/_dongd9173" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[JPA Entity에 기본 생성자를 만들어야 하는 이유]]></title>
            <link>https://velog.io/@_dongd9173/JPA-%EA%B8%B0%EB%B3%B8-%EC%83%9D%EC%84%B1%EC%9E%90%EB%A5%BC-%EB%A7%8C%EB%93%A4%EC%96%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</link>
            <guid>https://velog.io/@_dongd9173/JPA-%EA%B8%B0%EB%B3%B8-%EC%83%9D%EC%84%B1%EC%9E%90%EB%A5%BC-%EB%A7%8C%EB%93%A4%EC%96%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</guid>
            <pubDate>Sun, 14 Jan 2024 06:18:14 GMT</pubDate>
            <description><![CDATA[<p>JPA 관련 프로젝트를 하던 중, 이런 에러를 만났다.
<img src="https://velog.velcdn.com/images/_dongd9173/post/447502cc-fca8-4243-91c9-7cd7beb8e295/image.png" alt=""></p>
<p>기본 생성자가 엔티티에 존재하지 않다는 내용이다.
구글링하여 찾아보니, DB와 엔티티가 매핑되려면 기본 생성자를 만들어줘야 한다는 것이다.</p>
<p><strong>&#39;왜 기본생성자를 만들어 줘야할까?&#39;</strong> 하는 궁금증이 생겼다.</p>
<h3 id="jpa에서-기본-생성자-만들어줘야-하는-이유">JPA에서 기본 생성자 만들어줘야 하는 이유</h3>
<p>DB에 존재하는 데이터를 엔티티에 매핑하는 과정은 JPA에서 빈번하다. 
JPA는 DB 데이터를 객체 필드에 주입할 때 기본 생성자로 객체를 만들고 Reflection API를 통해 값을 매핑하게 된다.</p>
<p>🔘 <strong>Reflection API</strong>?
  정확한 클래스 타입을 알지 못해도 그 클래스의 정보들(타입, 필드, 메서드 등)에 접근할 수 있게 해주는 API이다. </p>
<p>그러나 Reflection API는 <strong>생성자의 매개변수 정보</strong>를 알 수 없다.
그렇기 때문에 기본 생성자를 만들어줘야 Reflection API가 객체를 생성할 수 있고, 생성된 객체로 필드 값을 매핑할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[첫 테스트 코드 적용기]]></title>
            <link>https://velog.io/@_dongd9173/%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%BD%94%EB%93%9C%EB%A5%BC-%EC%9E%91%EC%84%B1%ED%95%98%EB%A9%B4%EC%84%9C-%EB%8A%90%EB%82%80%EC%A0%90</link>
            <guid>https://velog.io/@_dongd9173/%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%BD%94%EB%93%9C%EB%A5%BC-%EC%9E%91%EC%84%B1%ED%95%98%EB%A9%B4%EC%84%9C-%EB%8A%90%EB%82%80%EC%A0%90</guid>
            <pubDate>Tue, 12 Sep 2023 11:50:42 GMT</pubDate>
            <description><![CDATA[<p>인프런에서 <a href="https://www.inflearn.com/course/practical-testing-%EC%8B%A4%EC%9A%A9%EC%A0%81%EC%9D%B8-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B0%80%EC%9D%B4%EB%93%9C/dashboard">테스트 코드 관련 강의</a>를 듣고 &#39;테스트가 이런것이구나&#39; 를 <strong>간접적으로 체험</strong>했지만 <strong>직접적인 체험</strong>을 원했던 저는, 현재 진행중인 프로젝트의 일부 도메인에 테스트를 적용 해봤습니다.</p>
<h3 id="기존의-개발방식">기존의 개발방식</h3>
<p>백엔드에서 DB 로직을 작성하고, 서비스 로직, 컨트롤러 로직 순으로 작성하고 나면 하나의 API가 만들어집니다. </p>
<blockquote>
<p>DB -&gt; 서비스 -&gt; 컨트롤러 =&gt; API 완성!</p>
</blockquote>
<p>위와 같이 한번에 원큐로 완성되면 정말 좋겠지만, 저같은 경우는 그렇지 않더군요.</p>
<blockquote>
<p>DB -&gt; 서비스(어라? 파라미터 뭔가 모자른데?) -&gt; DB -&gt; 서비스 -&gt; 컨트롤러(파라미터 또 모자란다..) -&gt; 서비스 ...(반복)</p>
</blockquote>
<h3 id="테스트를-도입한-개발방식">테스트를 도입한 개발방식</h3>
<blockquote>
<p>DB <strong>테스트</strong> 작성 -&gt; DB 로직 작성 -&gt; 서비스 <strong>테스트</strong> 작성 -&gt; 서비스 로직 작성 -&gt; 컨트롤러 <strong>테스트</strong> 작성 -&gt; 컨트롤러 로직 작성</p>
</blockquote>
<p>본 로직을 작성하기 전에 테스트(단위 및 통합) 코드를 작성하는 패턴으로 개발했습니다.
테스트는 또 아래 3단계를 거치곤 합니다</p>
<blockquote>
<ol>
<li>Red: 빨간불을 뜨게 하라. 테스트 작성 전, 어떤걸 개발할 것인지 생각하는 단계</li>
<li>Green: 초록불을 뜨게하라. 어떻게 개발할 것인지 생각하고 작성하는 단계</li>
<li>Refactor: 개선하라. 작성한 코드를 개선하는 단계</li>
</ol>
</blockquote>
<p>테스트를 도입한 개발방식에서는 효과적인 테스트 코드를 작성하기 위해서 로직에 대해 다시한번 생각하게 됩니다. 그래서 기존의 개발방식과는 다르게 실수를 많이 줄일 수 있었죠.</p>
<h3 id="테스트의-장점">테스트의 장점</h3>
<p>테스트를 작성하는건 코드를 작성하는데에 실수를 바로잡는 역할을 하기도 합니다. 또한, 언급은 안했지만 전체적인 테스트 코드를 실행하고 나면, 혹여나 변경된 로직으로 영향을 끼친 코드가 있는지 테스트 코드로 확인할 수 있는 장점이 있습니다.</p>
<h3 id="테스트의-단점">테스트의 단점</h3>
<p>테스트를 도입한 개발방식이 기존 개발방식보다 시간적으로 더 느릴수도 있습니다.
위에서 봤던 <strong>테스트를 도입한 개발방식</strong>에서는 비즈니스 로직을 작성하기 전에 테스트를 먼저 작성하는 TDD 방식을 따랐습니다. 테스트를 추가적으로 작성해준다는 것 자체가 시간을 더 쓰게 만들수도 있는것이죠.</p>
<h3 id="어떤상황에서-테스트를-추천-혹은-비추천-할까요">어떤상황에서 테스트를 추천 혹은 비추천 할까요?</h3>
<blockquote>
<p>추천: 프로젝트의 문서화 작성, 유지보수가 편한 프로젝트를 위함
비추천: MVP를 만들어야 하는 프로젝트, 빠른 시간안에 완료해야 하는 프로젝트</p>
</blockquote>
<h3 id="마무리">마무리</h3>
<p>이렇게 &#39;테스트 코드를 작성하면서 느낀점&#39;을 간략히 작성해봤습니다. 감사합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Java validation @Max @Min이 적용에 관하여]]></title>
            <link>https://velog.io/@_dongd9173/Java-validation-Max-Min%EC%9D%B4-%EC%A0%81%EC%9A%A9%EC%97%90-%EA%B4%80%ED%95%98%EC%97%AC</link>
            <guid>https://velog.io/@_dongd9173/Java-validation-Max-Min%EC%9D%B4-%EC%A0%81%EC%9A%A9%EC%97%90-%EA%B4%80%ED%95%98%EC%97%AC</guid>
            <pubDate>Wed, 06 Sep 2023 08:07:39 GMT</pubDate>
            <description><![CDATA[<p>Spring 에서 @Valid로 RequestBody를 체크 과정중, 
String 타입에 @Min(글자 길이 검증) 하려 했는데 안되는 현상이 일어났다.</p>
<pre><code class="language-java">public class CommentCreateRequest {

    @NotBlank(message = &quot;내용을 입력해주세요.&quot;)
    @Min(value= 10, message = &quot;내용은 10자리 이상 입력해주세요.&quot;) // Not working
    private String content;

}</code></pre>
<p>알아보니 @Max @Min은 숫자 필드에만 적용되는 사실을 알았다.</p>
<p>문자열 필드엔 @Size를 적용해야 한다.</p>
<pre><code class="language-java">public class CommentCreateRequest {

    @NotBlank(message = &quot;내용을 입력해주세요.&quot;)
    @Size(min = 10, message = &quot;내용은 10자리 이상 입력해주세요.&quot;)
//    @Size(min = 10, max = 255, message = &quot;내용은 10자리 이상, 255자리 이하로 입력해주세요.&quot;)
    private String content;

}</code></pre>
<p>@Size는 필드의 범위를 나타내는데 에도 효과적으로 보인다.
참고로 @Size는 String 외에도 Collection, Map, Array 필드를 지원한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[orElse, orElseGet, orElseThrow 에 대해서]]></title>
            <link>https://velog.io/@_dongd9173/orElse-orElseGet-orElseThrow</link>
            <guid>https://velog.io/@_dongd9173/orElse-orElseGet-orElseThrow</guid>
            <pubDate>Mon, 04 Sep 2023 09:37:06 GMT</pubDate>
            <description><![CDATA[<p>Java8에서 지원하는 Optional에서 orElse, orElseGet, orElseThrow를 쓰다보면 비슷한 점이 많아 햇갈릴 때가 많다. 이번기회에 간략히 정리해보자</p>
<h2 id="optional의-orelse">Optional의 orElse</h2>
<pre><code class="language-java">public T orElse(T other) {
    return value != null ? value : other;
}</code></pre>
<p>**  Optinal의 value값이 null이 아니라면 그대로 value 반환하고, 그렇지 않으면 other(값)를 반환한다.**</p>
<h2 id="optional의-orelseget">Optional의 orElseGet</h2>
<pre><code class="language-java">public T orElseGet(Supplier&lt;? extends T&gt; supplier) {
    return value != null ? value : supplier.get();
}</code></pre>
<p>Optinal value 값이 null이 아니면 value를 반환해주는건 orElse와 같다.
<strong>다만, orElseGet은 null일때 함수로 넘어가는 점이 다르다. (supplier.get)</strong></p>
<h2 id="optional의-orelsethrow">Optional의 orElseThrow</h2>
<p>두개가 있는걸 이제 알았다.</p>
<pre><code class="language-java">// 첫번째
public T orElseThrow() {
    if (value == null) {
        throw new NoSuchElementException(&quot;No value present&quot;);
    }
    return value;
}</code></pre>
<p>첫번째 orElseThrow는 Optional의 value가 없다면 NoSuchElementException 예외를 발생시킨다. 
<strong>값이나 함수로 넘어가지 않고 예외를 발생시키는 점이 다르다.</strong></p>
<pre><code class="language-java">// 두번째
public &lt;X extends Throwable&gt; T orElseThrow(Supplier&lt;? extends X&gt; exceptionSupplier) throws X {
    if (value != null) {
        return value;
    } else {
        throw exceptionSupplier.get();
    }
}</code></pre>
<p>두번째 orElseThrow는 Optional의 value가 없다면 <strong>&#39;내가 넘긴 파라미터 예외로&#39;</strong> 예외를 발생시킨다. 
이 예외는 함수로 호출한다.
<strong>함수로 넘어가되, 사용자 지정 예외(?)로 예외를 발생시킨다.</strong></p>
<p>틀린 부분이 있다면 피드백 부탁드립니다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[인프콘 2023 행사 세션들에 대한 간단 후기]]></title>
            <link>https://velog.io/@_dongd9173/%EC%9D%B8%ED%94%84%EC%BD%98-2023-%ED%96%89%EC%82%AC-%EC%84%B8%EC%85%98%EB%93%A4%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B0%84%EB%8B%A8-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@_dongd9173/%EC%9D%B8%ED%94%84%EC%BD%98-2023-%ED%96%89%EC%82%AC-%EC%84%B8%EC%85%98%EB%93%A4%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B0%84%EB%8B%A8-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Sat, 26 Aug 2023 06:41:09 GMT</pubDate>
            <description><![CDATA[<p align="center">
    <img src="https://velog.velcdn.com/images/_dongd9173/post/5f508f80-5cfb-45dc-9170-c97ea2fbd94e/image.jpeg" width="300">
</p>

<p>인프런에서 주최한 인프콘2023을 가서 들었던 세션들에 대해 후기를 남기고 싶어서 글을 적게 됐다.
내가 들은 세션들은 아래와 같다.</p>
<h2 id="들었던-세션들">들었던 세션들</h2>
<p>10:00 오프닝 | 인프랩의 미래 - 교육을 넘어 라이프타임 커리어 플랫폼으로 이형주, 이동욱,홍연의
11:40 ~ 12:20 출시 3일 만에 앱스토어 2위를 달성한 사이드 프로젝트 - 김현준, 김아인
12:40 ~ 13:00 왜 내가 만든 서비스는 아무도 안쓰지? - 이동훈
14:00 ~ 14:40 어느날 고민 많은 주니어 개발자가 찾아왔다 2탄 - 김영한
15:40 ~ 16:20 스프링과 함께 더 나은 개발자 되기</p>
<p>!! <strong><em>지금부터는 세션마다 제 개인적인 후기를 적은 것임을 알려드립니다.</em></strong> !!</p>
<h3 id="1000-오프닝">10:00 오프닝</h3>
<p>처음엔 인프랩 CEO 이형주 님이 나오셔서 인프랩 비전, 목표, 미래에 대해 간략히 말씀해 주셨고,
두 번째 인프랩 CTO 이동욱 님은 22/23년에 했던 것을 회고하고, 나아가 23/24년에 출시될 기능까지 미리 알려주셔서 참가자들의 감탄을 자아냈다.
마지막으로 홍연의 님은 인프콘 즐기는 방법을 간략하게 알려주셨다. </p>
<p>특히 이동욱 님의 발표를 더 보자면, 2022/2023년에 개편사항에서 인프런 수강자 입장의 나는, 편의성을 다시 한번 느끼며 감동하지 않을 수 없었다. 
또한 2023/2024년 출시될 기능 모두 인프런, 랠릿을 사용하는 사람들에게 득이 될 것으로 보여서 기대가 된다.</p>
<h3 id="1140--1220-출시-3일-만에-앱스토어-2위를-달성한-사이드-프로젝트---김현준-김아인">11:40 ~ 12:20 출시 3일 만에 앱스토어 2위를 달성한 사이드 프로젝트 - 김현준, 김아인</h3>
<p align="center">
    <img src="https://velog.velcdn.com/images/_dongd9173/post/87f3c620-0d2d-4511-8d2f-601bffeb4bf8/image.jpeg" width="300">
</p>

<p>이 세션은 2명의 강연자가 나와서 발표하는 자리였다. 20분은 김현준 기획자 및 마케터가 강연하셨고, 나머지 20분은 김아인 개발자(iOS와 flask서버)가 강연하셨다. (<del>두 분 다 고3이였다</del>)
이 앱의 이름은 <a href="https://skrr.app/">skrr(스컬)</a> 이다.</p>
<p>김현준 님은 기획자 및 마케터로서 </p>
<ol>
<li>스컬이란 앱이 어떻게 시작 그리고 과정</li>
<li>마케팅 방식</li>
<li>팀장이라는 위치에서 회고 </li>
</ol>
<p>등을 말했다.</p>
<p>김아인 님은 개발자로서 </p>
<ol>
<li>프로젝트 아키텍처에 대한 설명</li>
<li>운영하며 생기던 여러 가지 이슈</li>
<li>개발자다운 회고</li>
</ol>
<p>등을 말했다.</p>
<p>이 사이드 프로젝트인 스컬을 만든 스컬팀의 행동력이 대단했다고 판단했다.
특히, 아키텍처를 완벽히 따지지 않고 일단 해보자는 실행력에 인상 깊이 봤다. 현재 가지고 있는 한정적인 자원으로 어떤 것을 할 수 있을까를 고민하고 행동한 실행력이었다.</p>
<h3 id="1240--1300-왜-내가-만든-서비스는-아무도-안쓰지---이동훈">12:40 ~ 13:00 왜 내가 만든 서비스는 아무도 안쓰지? - 이동훈</h3>
<p align="center">
    <img src="https://velog.velcdn.com/images/_dongd9173/post/0b1be4da-a06e-4a1b-acb7-776ac5091ed9/image.jpeg" width="300">
</p>

<p>이번 세션도 사이드 프로젝트(이하 사.프)에 대한 발표였다. 이동훈 개발자님은 많은 사.프를 만들었고, 코로나맵을 만드신 분이었다.</p>
<p>개발자는 문제를 찾는 사람 이란걸 강조하셨다.
문제를 찾아야 한다는건 알고 있었는데 어떻게 찾아야 할까? 에 대한 세션이었다.</p>
<ol>
<li>내가 원하는것 말고, 상대방이 무엇이 불편해서 문제가 생기는질 관찰하라. 
 내가 원하는걸 사.프로 개발하면, 고객 니즈를 내 프로젝트에 끼워 맞추게 되는 문제점이 발견된다.</li>
<li>내가 원하되, 고객의 입장이 되어보자. 고객의 입장이 되어본다면 무엇이 불편한지 접근할 수 있다.</li>
</ol>
<h3 id="1400--1440-어느날-고민-많은-주니어-개발자가-찾아왔다-2탄---김영한">14:00 ~ 14:40 어느날 고민 많은 주니어 개발자가 찾아왔다 2탄 - 김영한</h3>
<p align="center">
    <img src="https://velog.velcdn.com/images/_dongd9173/post/768a36e5-1520-499e-9fe1-37420d5968c2/image.jpeg" width="300">
</p>

<p>이 세션은 김영한 지식공유자님의 발표였다. 1탄은 유튜브로 보고 2탄을 참가했다. 세션 참여자들이 정말 많았다. 그래서 더 기대되는 세션이었다.</p>
<p>처음엔 지식공유자로 업을 변경한 이유를 간략히 설명해 주셨다. 과거에도 교육을 해보셨던 분이라는 걸 이때 알았다. 실무중심의 개발자 강의를 만들고 싶어 하시는 야망을 느꼈다.</p>
<p>전체적인 내용은 <strong>꾸준히 열심히 하라</strong>는 내용이었지만, 강의 때와 같이 실무적인 예시를 많이 들어주셔서 이해가 더 잘됐다. </p>
<h3 id="1540--1620-스프링과-함께-더-나은-개발자-되기---이일민토비">15:40 ~ 16:20 스프링과 함께 더 나은 개발자 되기 - 이일민(토비)</h3>
<p align="center">
    <img src="https://velog.velcdn.com/images/_dongd9173/post/d77730b9-289c-49de-b5ac-64ead0d220d1/image.jpeg" width="300">
</p>

<p>전체적인 내용은 스프링은 역사와 철학이 있고, 그렇기 때문에 &#39;스프링을 그냥 쓰지말자&#39; 라는 내용이였다. </p>
<p>컨트롤러 서비스 레포지토리 레이어를 나눠서 디비 연결하고 등등, 기계적으로 쓰지말고 좀 더 깊숙히 탐구해보자는 말과 그렇게 하면 스프링이 성장한 것 처럼 당신도 같이 성장 해 있을 것이라는 말도 해주셨다.</p>
<p>블로그에 대한 견해도 말씀하셨다. 블로그를 하는건 좋지만, <strong>나만의 글</strong>로 쓰도록 하라는 점, 내 것을 만들려면 내 생각을 써야한다는 점 등 블로그를 시작하는 나에게 큰 용기가 됐다.</p>
<p>마지막으로 <strong>본인이 열심히 기여하여 커뮤니티가 되어보세요.</strong> 라고 말씀하신게 나에게 큰 울림이 됐다.</p>
<h2 id="마무리">마무리</h2>
<p>처음 인프콘 행사에 참여하게 됐는데, 인프런에서 강의에서만 봤던 지식공유자 님들과 커뮤니티에서 사진으로만 봤던 분들을 오프라인에서 직접 마주보니 감회가 새로웠다.
그리고 강연을 모두 듣고 난 후, 강연을 듣는 이유가 무엇일까를 다시한번 고민해 보는 시간도 됐다.</p>
<p>크게 두가지 라고 보았다.</p>
<ol>
<li>내가 몰랐던 부분을 강연자의 경험을 통해 들을 수 있게 되는 점</li>
<li>내 기억 깊숙이 자리잡고 있는 앎을 다시한번 일깨워주는 점</li>
</ol>
<p>한 가지 아쉬운 점이 네트워킹 이였는데, 혼자 행사를 가서 그런지 네트워킹이 너무 뻘쭘해서 어떻게 할지 몰라 했었다. (결국 간식만 받고 바로 집으로 왔다..) 네트워킹까지는 참여 하지 못했지만, 다음엔 꼭 참여해서 여러 사람들과 대화를 나눠보고 싶다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring bean validation 에서 햇갈리는 3가지(@NotNull, @NotEmpty, @NotBlank) 정리하기]]></title>
            <link>https://velog.io/@_dongd9173/Spring-bean-validation-%EC%97%90%EC%84%9C-%ED%96%87%EA%B0%88%EB%A6%AC%EB%8A%94-3%EA%B0%80%EC%A7%80NotNull-NotEmpty-NotBlank-%EC%A0%95%EB%A6%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@_dongd9173/Spring-bean-validation-%EC%97%90%EC%84%9C-%ED%96%87%EA%B0%88%EB%A6%AC%EB%8A%94-3%EA%B0%80%EC%A7%80NotNull-NotEmpty-NotBlank-%EC%A0%95%EB%A6%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 18 Aug 2023 05:40:49 GMT</pubDate>
            <description><![CDATA[<p>개인적으로 Controller 에서 @Valid를 설정할때 마다 햇갈리는 3가지 validation이 있는데, 바로 <strong>@NotNull, @NotEmpty, @NotBlank</strong> 이다. 
오래 기억에 남기 위해 나만의 언어로 정리해보려고 한다.</p>
<p>우선 validation을 사용하려면 spring 프로젝트에서 build.gradle 파일의 dependencies 를 추가해줘야 한다.</p>
<pre><code class="language-java">implementation &#39;org.springframework.boot:spring-boot-starter-validation&#39;</code></pre>
<p>예시는 Controller에서 책(Book)을 추가하기 위해 Request Body에 책 이름을 받는 클래스를 만들어 주도록 하겠다.</p>
<pre><code class="language-java">public class BookCreateRequest {

//      어떤걸 써야할까?
//    @NotNull
//    @NotEmpty
//    @NotBlank
    private String title;
}</code></pre>
<h3 id="notnull">@NotNull</h3>
<p><strong>null을 허용하지 않는</strong> validation. 
단, <strong>빈칸(&quot;&quot;, &quot; &quot;)을 허용</strong> 한다.</p>
<h3 id="notempty">@NotEmpty</h3>
<p>여기서는 <strong>null과 비어있는 문자열(&quot;&quot;)을 허용하지 않는</strong> validation.
단, <strong>공백(&quot; &quot;)을 허용</strong>한다.</p>
<h3 id="notblank">@NotBlank</h3>
<p><strong>null과 빈칸(&quot;&quot;, &quot; &quot;) 모두를 허용하지 않는</strong> validation.
<br/>
3가지가 이해됐다면, 요구사항에 맞게 validation을 고르자.</p>
<pre><code class="language-java">public class BookCreateRequest {

    @NotBlank // null과 빈칸(&quot;&quot;, &quot; &quot;) 모두 허용하지 않기에, @NotBlank를 사용한다.
    private String title;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[@NoArgsConstructor(access = AccessLevel.PROTECTED) 의미]]></title>
            <link>https://velog.io/@_dongd9173/NoArgsConstructoraccess-AccessLevel.PROTECTED-%EC%9D%98%EB%AF%B8</link>
            <guid>https://velog.io/@_dongd9173/NoArgsConstructoraccess-AccessLevel.PROTECTED-%EC%9D%98%EB%AF%B8</guid>
            <pubDate>Wed, 16 Aug 2023 01:54:50 GMT</pubDate>
            <description><![CDATA[<p>무의식적으로 계속 쓰던 코드 중 하나는, 롬복에서 지원하는 NoArgsConstructor 어노테이션이였다. 그 중, @NoArgsConstructor(access = AccessLevel.PROTECTED) 는 어떤 의미를 말해주는 코드인지를 간략하게 내 글로 적고 넘어가 보려 한다.</p>
<ul>
<li><strong>lombok 라이브러리가 필요합니다!</strong></li>
</ul>
<p>기본적으로 자바는 클래스 생성 시, 기본 생성자를 통해 객체를 만들 수 있게 된다.</p>
<pre><code class="language-java">public class OrderMatching {

    private String title;

}

OrderMatching orderMatching = new OrderMatching(); // ok
</code></pre>
<p>다만, 자바의 이러한 기본적인 부분이 객체를 생성해 개발할때, 오해를 불러일으킬 수 있는 코드가 될 수 있다.</p>
<p>&#39;난 title 파라미터를 받는 <strong>생성자만 사용해서 객체를 생성</strong>할꺼야&#39; 라고 했을때를 가정해보자.</p>
<pre><code class="language-java">public class OrderMatching {

    private String title;

    public OrderMatching(String title) {
        this.title = title;
    }
}

OrderMatching orderMatching1 = new OrderMatching(&quot;테스트1&quot;); // ok
OrderMatching orderMatching2 = new OrderMatching(); // 의도하지 않음</code></pre>
<p>우리가 의도한 객체 생성자는 orderMatching1 이였지만, orderMatching2 방식으로 할 수 있는걸 볼 수 있다. orderMatching2 방식은 쓰지 않으니 명시적으로 막아두는게 좋을 수 있다.</p>
<pre><code class="language-java">public class OrderMatching {

    private String title;

    protected OrderMatching() { }

    public OrderMatching(String title) {
        this.title = title;
    }
}

OrderMatching orderMatching1 = new OrderMatching(&quot;테스트1&quot;); // ok
OrderMatching orderMatching2 = new OrderMatching(); // 컴파일 에러</code></pre>
<p>이걸 롬복 어노테이션을 통해 의미를 상단에 명시해줄 수 있다. </p>
<pre><code class="language-java">@NoArgsConstructor(access = AccessLevel.PROTECTED) // 추가
public class OrderMatching {

    private String title;

    // protected OrderMatching() { } // 삭제

    public OrderMatching(String title) {
        this.title = title;
    }
}

OrderMatching orderMatching1 = new OrderMatching(&quot;테스트1&quot;); // ok
OrderMatching orderMatching2 = new OrderMatching(); // 컴파일 에러</code></pre>
<h2 id="느낀점">느낀점</h2>
<p>코드라는건 말하는 것, 글을 쓰는 것과 같다고 생각한다. 그렇기 때문에 무의식적으로 코드를 써내려가기 보다, 그 의미를 곱씹으면서 써 내려가는것이 좋겠다. 다른 사람들이 봤을때, 이 코드의 의도를 알 수 있게끔.</p>
<p><strong>이상한점이 있다면 꼭 알려주세요!</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Toy project] 카페 쿠폰적립 애플리케이션 시작]]></title>
            <link>https://velog.io/@_dongd9173/Toy-project-%EC%B9%B4%ED%8E%98-%EC%BF%A0%ED%8F%B0%EC%A0%81%EB%A6%BD-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98</link>
            <guid>https://velog.io/@_dongd9173/Toy-project-%EC%B9%B4%ED%8E%98-%EC%BF%A0%ED%8F%B0%EC%A0%81%EB%A6%BD-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98</guid>
            <pubDate>Wed, 10 May 2023 21:03:01 GMT</pubDate>
            <description><![CDATA[<p>velog의 첫 글을 어떤걸 쓸까 하다가 진행 중인 토이 프로젝트인 <strong>카페 쿠폰적립 애플리케이션</strong>에 대해 작성해 보려고 한다. 과정과 설계까지만 기록하려 한다. </p>
<h2 id="시작하게-된-계기">시작하게 된 계기</h2>
<p>커피를 먹고 싶을 때 자주 찾는 아담한 카페가 집 앞 3분 거리에 있다. 쿠폰 적립을 종이로 하는 카페다. 이 카페는 쿠폰 적립 종이를 가게에 보관해 주고 있다. 그래서 쿠폰이 많아짐에 따라 보관할 수 있는 &#39;보관함&#39;이 늘어나는 걸 확인할 수 있었다. 내가 이 부분을 해결해 줄 수 있을 것으로 보였다.</p>
<h2 id="유사-서비스">유사 서비스</h2>
<p>비슷한 서비스가 있었다. 바로 <strong>도도 포인트</strong> 라는 서비스였다. 내가 구현하려는 애플리케이션 의도와 주요 기능[핸드폰 번호를 입력하면 쿠폰이 적립된다.]이 같고, 심지어 브랜드 마케팅 효과에 도움을 주는 기능들도 여럿 있었다. 가격은 2023년 5월 11일 기준으로 3년 약정 월 2만 원 정도 하는 서비스다. 
카페 사장님에게 이 서비스를 제안 해봤지만, <strong>가격이 부담돼 못할 것 같다고 하셨다</strong>. 그만큼 작은 카페였다.</p>
<p>순간적으로 이 문제를 해결한 몇 가지가 떠올랐다. </p>
<ul>
<li>집에서 뒹굴던 안드로이드 샤오미 태블릿</li>
<li>Typescript 학습 의지</li>
<li>Next.js를 Typescript로 구현해 보고 싶다는 다짐</li>
</ul>
<p>이후로 간단한 설계에 들어갔다.</p>
<h2 id="간단한-구조-설계">간단한 구조 설계</h2>
<ul>
<li>프론트엔드 및 백엔드: Typescript 기반의 Next.js(react.js)</li>
<li>데이터베이스: Firebase Realtime Database Or Cloud Firestore</li>
<li>배포: Vercel</li>
</ul>
<p>이 설계는 MVP(Minimum Viable Product)로 개발해서 간단히 배포하는 데에 초점을 뒀다. </p>
<h2 id="이-토이프로젝트가-끝나면-얻어갈-것들">이 토이프로젝트가 끝나면 얻어갈 것들</h2>
<p>토이 프로젝트나 사이드 프로젝트는 끝나고 나면 나에게 남는 게 있어야 한다 는 이 원칙을 고수하는 편이다.</p>
<ul>
<li>Typescript
  자바 백엔드 개발자 이지만 자바스크립트를 좋아해서 배워보고 싶었다.</li>
<li>Next.js 13 버전
  Next.js 12 버전의 앱은 개발을 해봤기 때문에 13버전으로 해보고 싶은 마음이 컸다.</li>
<li>Firebase Realtime Database에 대해서</li>
<li>개인정보 처리 방침에 대해서</li>
<li>기타 등등</li>
</ul>
<h2 id="마무리">마무리</h2>
<p>간단한 구조 설계를 만든 후, 구현 중에 중요하고 생각하거나 이슈가 있는 부분을 여기에 기록 해두려고 한다. 내가 개발 블로그를 시작하다니, 감회가 새롭다.</p>
<p>사실 이 프로젝트는 안 해도 되는 프로젝트다. 
이유는 도도 포인트라는 서비스가 있기 때문인 점도 있고, 무엇보다 <strong>가게에서 쿠폰 종이를 보관하지 않으면 되는 문제</strong>기 때문이다. </p>
<p>문제를 애플리케이션 개발 없이 해결된다면, 최고의 해결책이 아닐까 라는 생각을 문득 해본다.</p>
]]></description>
        </item>
    </channel>
</rss>