<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>sunggil-5125.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Wed, 14 Jun 2023 03:09:16 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>sunggil-5125.log</title>
            <url>https://velog.velcdn.com/images/sunggil-5125/profile/2a03f111-be12-46c1-acc9-cb56252c4ad8/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. sunggil-5125.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/sunggil-5125" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[SaaS와 B2B란?]]></title>
            <link>https://velog.io/@sunggil-5125/SaaS%EC%99%80-B2B%EB%9E%80</link>
            <guid>https://velog.io/@sunggil-5125/SaaS%EC%99%80-B2B%EB%9E%80</guid>
            <pubDate>Wed, 14 Jun 2023 03:09:16 GMT</pubDate>
            <description><![CDATA[<h2 id="🤔-saassoftware-as-a-service">🤔 SaaS(SoftWare as a Service)?</h2>
<p>클라우드 컴퓨팅이 도입되면서 생긴 용어로 어플리케이션을 조직이나 개인에게 제공하는 it 서비스 방식을 말한다.
SaaS는 일반적으로 구독 방식으로 구매하며, 소프트웨어는 제공사의 클라우드에서 운영된다.</p>
<h3 id="saas의-장점">SaaS의 장점</h3>
<ol>
<li>구독 시스템으로 초기 설치에 대한 비용이 적음
처음엔 작은 비용을 들여서 사용해보고, 유용하다고 생각이 든다면 장기적으로 사용할 수 있다.</li>
<li>유지보수 비용이 따로 들지 않음
소프트웨어를 클라우드를 통해 서비스 제공사에서 제공 해주기 때문에 구독비만 내고 따로 유지보수 비용이 들지 않는다.</li>
<li>고성능 하드웨어가 따로 필요하지 않음
서비스를 설치해서 사용하지 않고, 서비스 제공사에서 클라우드를 제공해 사용자는 인터넷을 통해 접속하기 때문이다.</li>
</ol>
<h3 id="saas의-단점">SaaS의 단점</h3>
<ol>
<li>SaaS 서비스에 대한 의존
구독하고 있는 SaaS 서비스가 장애가 생겨 문제가 생긴다면, 대처가 불가능하다.</li>
<li>데이터 보안에 대한 위험
데이터를 SaaS 서비스의 내부 데이터 저장소에 보관하는게 아니라, 공급사의 클라우드를 통해 저장하기 때문에 보안이 완벽하지 않을 수도 있다.</li>
</ol>
<h2 id="🤔-b2b">🤔 B2B?</h2>
<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/d37f3aa7-3a97-455e-bbf1-2b5f99f11587/image.png" alt=""></p>
<p>위의 사진과 같이 B2B는 기업을 타겟으로 한 거래 방식으로, 다른 기업에 제품이나 서비스를 공급하는 기업이 수익을 창출하는 방식이다.</p>
<h3 id="b2b의-장점">B2B의 장점</h3>
<ul>
<li><ol>
<li>장기적인 협력 관계
B2B는 일시적으로 거래하기 보다는 장기적으로 하기 때문에
장기적으로 협력 관계를 만들 수 있다.</li>
</ol>
</li>
<li><ol start="2">
<li>높은 수익 마진
B2B의 고객 수는 적더라도, 고객 단가가 높아 개별 고객별 수익 마진이 크다. (이건 B2B를 제공해주는 서비스마다 다를거 같다.)</li>
</ol>
</li>
</ul>
<h3 id="b2b의-단점">B2B의 단점</h3>
<ul>
<li><ol>
<li>적은 고객수
일반적인 개인을 대상을 타겟으로 삼는(B2C) 보다는 기업을 대상으로 삼기 때문에 B2C와 비교해서는 고객수가 적다.</li>
</ol>
</li>
<li><ol start="2">
<li>긴 판매 기간
위의 단점과 같이 기업을 대상으로 삼기 때문에 중간에 의사 결정자가 많다. 그래서 판매 시간이 길다.</li>
</ol>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[@Transactional의 동작 원리]]></title>
            <link>https://velog.io/@sunggil-5125/Transactional%EC%9D%98-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC</link>
            <guid>https://velog.io/@sunggil-5125/Transactional%EC%9D%98-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC</guid>
            <pubDate>Sat, 27 May 2023 13:17:38 GMT</pubDate>
            <description><![CDATA[<h2 id="🤔-개요">🤔 개요</h2>
<p>면접관님: AOP에 대해 설명해주세요.
나: 관점지향 프로그래밍으로써, 공통적인 부분을 객체를 만들어 중복 코드를 없애주는 것 입니다.
면접관님: AOP를 써본 예시에 대해서 설명해주세요.
나: AOP는 사용해본적 없습니다!</p>
<p>실제로 지난주 목요일 내가 면접을 봤을때 실제로 대답한 말이다.
지금 생각해보니 이불킥을 당장이라도 차고 싶을 만큼 개 뚱단지 같은 소리라고 생각한다.
다시는 이런 상황이 생기지 않게 글로 정리해 공부해볼려고 한다!</p>
<h2 id="💻-aop란">💻 AOP란?</h2>
<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/d546905b-aa99-4b70-aa26-a708033cad35/image.png" alt=""></p>
<p>위 사진을 보면 노란색의 로직은 Class A, Class B, Class C에서 모두 중복된 로직들이다. 
하지만 요구사항이 들어와 노란색 로직을 바꾼다고 가정해보자, 그럼 우린 Class A, Class B, Class C 모든 클래스마다 공통적이게 수정을 해야할것이다.
이렇게 <strong>어떤 로직을 기준으로 별도의 객체를 만들어 분리하는 기술을 AOP</strong>라 한다.</p>
<h3 id="spring-aop의-특징">Spring AOP의 특징</h3>
<ul>
<li>Bean에만 AOP 기술 적용 가능하다.</li>
<li>Proxy 방식으로 AOP가 동작한다.</li>
</ul>
<h2 id="🤔-transactional의-동작-과정은">🤔 @Transactional의 동작 과정은?</h2>
<p>@Transactional는 Spring AOP를 기반으로 동작한다. 
그래서 위에 특징으로 설명한것과 같이 Proxy 방식을 통해 동작한다.</p>
<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/81ad7213-799a-4392-8d0a-4834b34308c6/image.png" alt=""></p>
<p>위의 사진 처럼 대상 객체(Transaction을 적용할 로직)를 감싸는 Proxy 객체를 만들어 대상 객체의 결과에 따라 commit, rollback 한다. 위 사진을 코드로 바꾼다면 아래 코드 처럼 바뀔것이다.</p>
<pre><code class="language-java">public class TransactionProxy{
    private final TransactonManager manager = TransactionManager.getInstance();
        ...

    public void transactionLogic() {
        try {
            // 트랜잭션 전처리(트랜잭션 시작, autoCommit(false) 등)
            manager.begin();

            // 다음 처리 로직(타겟 비스니스 로직, 다른 부가 기능 처리 등)
            target.logic();

            // 트랜잭션 후처리(트랜잭션 커밋 등)
            manager.commit();
        } catch ( Exception e ) {
            // 트랜잭션 오류 발생 시 롤백
            manager.rollback();
        }
    }
</code></pre>
<h3 id="💻-proxy-객체를-만드는-방법은">💻 Proxy 객체를 만드는 방법은?</h3>
<p>Proxy 객체를 만드는 방식으로는 2가지가 있다.</p>
<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/87b2e027-c8ae-45f5-abcf-be28d497ae0f/image.png" alt=""></p>
<ul>
<li><p>JDK Proxy 방식
Spring에서 사용하는 방식으로 Target 클래스의 인터페이스를 상속하여 Proxy 객체를 만든다. 
하지만 Target 클래스의 인터페이스가 존재하지 않는다면 JDK 방식에서는 Exception을 던져준다.</p>
</li>
<li><p>CGLip Proxy
JDK 방식과는 달리 인터페이스가 없어도 Target 클래스를 상속하여 Proxy 객체를 만든다.
Target 클래스의 바이트 코드를 조작하여 Proxy 객체를 만들기 때문에 리플렉션 방식의 JDK Proxy보다 성능이 좋아 Spring Boot에서 사용한다.</p>
</li>
</ul>
<h2 id="🚨-transactional의-주의점">🚨 @Transactional의 주의점</h2>
<ol>
<li><p>Target 메서드에 private 사용 불가
프록시 객체는 Target 객체, 인터페이스를 상속 받아 객체를 만들기 때문에 private로 되어있으면 상속 받을 수 없기 때문에 트랜잭션 관리가 되지 않는다.</p>
</li>
<li><p>Target 메서드에 내부적인 메서드를 사용하지 말자
트랜잭션이 아닌 메소드에서 트랜잭션이 선언된 내부의 메소드를 호출하면 프록시 객체가 아닌 대상 객체의 메소드를 호출하기 때문에 트랜잭션이 적용되지 않는다.</p>
</li>
</ol>
<pre><code class="language-java">@Service
@RequiredArgsConstructor
public class PostService {
    private final PostRepository postRepository;

    public void savePostList(List&lt;PostDto&gt; postListDto) {
          postListDto.forEach(postDto -&gt; addBook(postDto));
    }

    @Transactional
    public void savePost(PostDto postDto) {
        Post post = postDto.toEntity();
        postRepository.save(post);
    }

}
</code></pre>
<p><del>구린 코드이지만 설명을 위해서..</del>
위에 코드 처럼 @Transaction 어노테이션을 내부 메서드에 선언하면 프록시 객체가 savePost를 타겟 메서드로 삼기 때문에 이것을 주의하여 @Transactional을 선언하여야 한다.</p>
<h2 id="😁-마무리">😁 마무리</h2>
<p>스프링 공부하면서 무조건 쓰게 되는게 @Transactional 어노테이션인데 어떻게 돌아가는지도 모르고 썼었던 과거의 나에게 한대 때리고 싶고, 앞으로도 내가 쓰는 기술들의 동작 과정에 대해서 공부해볼려고 한다!</p>
<h2 id="🙇♂️-참고">🙇‍♂️ 참고</h2>
<p><a href="https://velog.io/@ann0905/AOP%EC%99%80-Transactional%EC%9D%98-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC#-contents">https://velog.io/@ann0905/AOP%EC%99%80-Transactional%EC%9D%98-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC#-contents</a>
<a href="https://velog.io/@pond1029/transactional">https://velog.io/@pond1029/transactional</a>
<a href="https://mommoo.tistory.com/92">https://mommoo.tistory.com/92</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[😁 DIP 정리]]></title>
            <link>https://velog.io/@sunggil-5125/DIP-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@sunggil-5125/DIP-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 13 Apr 2023 07:18:25 GMT</pubDate>
            <description><![CDATA[<p>DDD 책을 읽다가 DIP에 대한 내용이 나와 정리해볼려고 한다.</p>
<h2 id="dip란">DIP란?</h2>
<p>Dependency Inversion Principle의 줄임말로 의존 역전 원칙이라는 뜻이다.
이 원칙은 고수준 모듈이 저수준 모듈을 의존하게 아니라 저수준 모듈이 고수준 모듈을 의존 하게 하는 원칙이다.</p>
<blockquote>
<p>고수준 모듈: 어떤 의미 있는 단일 기능을 제공하는 모듈
  저수준 모듈: 고수준 모듈의 기능을 구현하기 위해서 필요한 기능의 구현</p>
</blockquote>
<h2 id="왜-고수준-모듈이-저수준-모듈을-의존하면-안되는데">왜 고수준 모듈이 저수준 모듈을 의존하면 안되는데?</h2>
<p>바로 객체간 의존성이 높아지기 때문이다. 고수준 모듈이 저수준 모듈을 의존해 기능을 개발해나가게 되면 저수준 모듈을 교체해야할 상황이 와 저수준 모듈을 변경 했는데 고수준 모듈까지 구현을 바꿔야 할 상황이 오기 때문이다.</p>
<pre><code class="language-kotlin">@Service
class SendMoneyService(
    private val samsungPayService: SamsungPayService
) {

    fun execute(account: String) {
        samsungPayService.execute(account, &quot;korea&quot;)
    }

}</code></pre>
<p>위에 예시 코드를 보면 <del>(더럽게 못썻다..)</del> SendMoneyService 고수준 모듈이 <code>SamsungPayService</code> 저수준 모듈 클래스에 의존하고 있다.</p>
<p>이는 필자가 위에서 말한 고수준 모듈이 저수준 모듈을 의존하고 있는것이다.</p>
<p><code>SamsungPayService</code>를 <code>KakaoPayService</code>로 바꿔보자. 그렇게 된다면 <code>SendPayService</code>의 코드를 모두 수정해야할 상황이 생기게 된다. 이렇게 되면 객체의 유연성도 떨어질 뿐만 아니라 SRP도 위반하게 되는것이다.</p>
<h2 id="인터페이스로-추상화">인터페이스로 추상화</h2>
<p>위에서 발생한 상황은 인터페이스를 사용해 추상화 하면 해결이 가능하다.</p>
<pre><code class="language-kotlin">@Service
class SendMoneyService(
    private val payService: PayService
) {

    fun execute(account: String) {
        payService.execute(account, &quot;korea&quot;)
    }

}</code></pre>
<pre><code class="language-kotlin">interface PayService {

    fun execute(account: String, world: String)

}</code></pre>
<pre><code class="language-kotlin">@Service
class PayServiceImpl(
    private val samsungPay: SamsungPay
): PayService {

    fun execute(account: String, world: String) {
        ~~~ 어쩌고 저쩌고
    }

}</code></pre>
<p>이렇게 되면 <code>PayService</code> 인터페이스도 의미 있는 단일 기능을 제공하기 때문에 고수준 모듈이 된다. <code>SendMoneyService(고수준)</code>이 <code>PayService(고수준)</code>을 의존하고, <code>PayServiceImpl(저수준)</code>이 <code>PayService(고수준)</code>을 의존하기 때문에 인터페이스를 만들어 DIP 원칙을 적용할 수 있다!</p>
<p>뿐만 아니라 인터페이스를 사용하게 된다면 객체를 모킹해서 단위 테스트 코드를 작성하기도 편리해진다</p>
<h2 id="인터페이스를-쓰면-다-되는건가">인터페이스를 쓰면 다 되는건가?</h2>
<p>인터페이스를 쓰면 다 DIP가 적용 되는건 아니다.</p>
<pre><code class="language-kotlin">@Service
class SendMoneyService(
    private val samsungPayService: SamsungPayService
) {

    fun execute(account: String) {
        samsungPayService.execute(account, &quot;korea&quot;)
    }

}</code></pre>
<pre><code class="language-kotlin">interface SamsungPayService {

    fun execute(account: String, world: String)

}</code></pre>
<pre><code class="language-kotlin">@Service
class SamsungPayServiceImpl(
    private val samsungPay: SamsungPay
): SamsungPayService {

    fun execute(account: String, world: String) {
        ~~~ 어쩌고 저쩌고
    }

}</code></pre>
<p>위에 코드를 보면 인터페이스를 만들었지만 SendMoneyService가 SamsungPayService를 의존하고있다. 즉 고수준 모듈이 저수쥰 모듈을 의존하고 있는 것이다. 이렇게 인터페이스를 쓰면 DIP가 다 적용되는것은 아니다. 이를 유의하자</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[🤔 kotlin에서 Entity를 Data Class로 지정하면 안되는 이유]]></title>
            <link>https://velog.io/@sunggil-5125/kotlin%EC%97%90%EC%84%9C-Entity%EB%A5%BC-data-class%EB%A1%9C-%EC%A7%80%EC%A0%95%ED%95%98%EB%A9%B4-%EC%95%88%EB%90%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</link>
            <guid>https://velog.io/@sunggil-5125/kotlin%EC%97%90%EC%84%9C-Entity%EB%A5%BC-data-class%EB%A1%9C-%EC%A7%80%EC%A0%95%ED%95%98%EB%A9%B4-%EC%95%88%EB%90%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</guid>
            <pubDate>Tue, 11 Apr 2023 11:03:20 GMT</pubDate>
            <description><![CDATA[<p>프로젝트를 개발하면서 Entity에 흔히 DTO에 쓰는 Data Class 사용해도 될까라는 의문이 들었다. Data Class는 데이터를 담을 때 사용하고, 유요한 copy(), equal(), toString() 같은 메서드들을 지원해주니까 사용해도 되겠지! 라는 생각이 들었지만 결론은 붙히면 안되는것을 깨닳았다.</p>
<h2 id="data-class">Data Class</h2>
<p>일단 첫번째로 data class가 무엇인지 알아보자.</p>
<p>Data Class는 일반 클래스와 달리, 위에서 말했다 싶이 데이터 보관 목적으로 만든 클래스이고, 다양한 메서드를 자동 생성해주는 클래스이다. </p>
<p>Data Class 생성시 만들어지는 메서드로는</p>
<ul>
<li>hashCode()</li>
<li>copy()</li>
<li>equal()</li>
<li>toString()</li>
<li>componentsN()</li>
</ul>
<p>이렇게 있고, 또한 여러개의 특징을 가지고 있다.</p>
<ul>
<li>기본 생성자에 1개 이상의 val, var를 붙힌 파라미터가 있어야한다.</li>
<li>다른 클래스를 상속할 수 없다. (sealed 클래스 상속 가능, 인터페이스 구현 가능)</li>
<li>abstract, open, sealed, inner 등의 키워드를 붙힐 수 없다.</li>
<li>자동으로 생성한 메서드를 오버라이딩 할 경우, 오버라이드 된 메서드를 사용한다.</li>
</ul>
<h2 id="entity-dirty-check">Entity Dirty Check</h2>
<p>Dirty Check은 Entity를 스냅샷을 찍어 변경된 부분이 있으면 말 그대로 변경된것이 있으면 알아서 데이터를 수정해주는것을 의미한다.</p>
<p>Entity를 Data Class로 지정해서 클래스를 만들면 <code>hashCode()</code>, <code>equal()</code> 메서드가 Hibernate의 Dirty Check 검사 메커니즘의 요구와 호환되지 않아 Dirty Check가 불가능 하다.</p>
<p>또한 <code>equal()</code> 메서드는 객체의 모든 필드 속성이 동일한지 비교하지만 Hibernate는 기본 키 필드만 비교한다. 이렇게 모든 필드의 속성이 동일한지 확인할 수 있으므로 성능 문제가 발생 할 수 있다.</p>
<h2 id="지연-로딩">지연 로딩</h2>
<p>지연 로딩은 객체를 필요한 시점에 연관된 객체의 데이터를 불러오는것이다. 지연로딩의 반대는 즉시 로딩으로 데이터를 조회할때 연관된 객체의 데이터를 한번에 불려오는것이다. 즉시 로딩으로 연관된 객체를 불러오면 속도는 빠르겠지만 불러놓고 쓰지 않으면 메모리만 소비 된다는 단점이 있다.</p>
<pre><code class="language-kotlin">@Entity
public class Member {

    @Id
    @Column(name = &quot;member_id&quot;)
    private String id;

    private String name;

    private int age;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = &quot;team_id&quot;)
    private Team team;
}


// 지연 로딩 실행 코드
Member member = em.find(Member.class, &quot;member1&quot;);
Team team = member.getTeam(); // 객체 그래프 탐색
team.getName(); // 팀 객체 실제 사용</code></pre>
<p>위의 지연 로딩을 사용한 코드를 예로 보자면 Entity Manger를 이용해서 member를 조회 할때 member1만 조회하고 team은 조회하지 않는다. 대신에 객체를 상속을 이용해서 proxy 객체를 만들어 조회한다.</p>
<p>위에서 말했다 싶이 Data Class는 상속이 불가능하다! 상속을 하기 위해서 open 키워드를 붙힐 수도 없다! </p>
<p>이 때문에 Entity에 Data Class를 사용한다면 지연로딩이 불가능하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[🤔 얕은 복사와 깊은 복사]]></title>
            <link>https://velog.io/@sunggil-5125/%EA%B9%8A%EC%9D%80-%EB%B3%B5%EC%82%AC%EC%99%80-%EC%96%95%EC%9D%80-%EB%B3%B5%EC%82%AC</link>
            <guid>https://velog.io/@sunggil-5125/%EA%B9%8A%EC%9D%80-%EB%B3%B5%EC%82%AC%EC%99%80-%EC%96%95%EC%9D%80-%EB%B3%B5%EC%82%AC</guid>
            <pubDate>Thu, 06 Apr 2023 10:49:34 GMT</pubDate>
            <description><![CDATA[<p>코프링으로 프로젝트를 진행하면서 data 클래스의 copy()라는 메서드를 사용해 보았는데, 뭔지 정확히 알고 쓰면 좋겠어서 블로그를 작성하게 되었다.</p>
<h2 id="얕은-복사">얕은 복사</h2>
<p>얕은 복사는 객체 인스턴스의 주소값을 복사하는 것이다. 그래서 원복 객체를 수정하면 복사한 객체도 수정이 된다. 동일성과 동등성이 보장된다.</p>
<blockquote>
<p>동일성: 두 객체가 할당된 메모리 주소가 같다. ex) ==
동등성: 두 객체의 내용이 같다. ex) equals</p>
</blockquote>
<pre><code class="language-kotlin">val num1 = 1
val num2 = num1

printlin(num1 == num2) // true</code></pre>
<h2 id="깊은-복사">깊은 복사</h2>
<p>깊은 복사는 실제 값을 새로운 메모리 공간에 복사하는 것이다. 따라서 원본 객체를 수정하면 복사한 객체가 수정이 되지 않는다.</p>
<blockquote>
<p>코틀린의 copy() 메서드는 깊은 복사라고 한다.</p>
</blockquote>
<pre><code class="language-kotlin">val person1 = Person(name = &quot;김성길&quot;, age = 19)
val person2 = person1.copy()

println(person1 == person2) // false</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[🤔 JPA에 대해 알아보자]]></title>
            <link>https://velog.io/@sunggil-5125/JPA%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@sunggil-5125/JPA%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Tue, 04 Apr 2023 13:16:49 GMT</pubDate>
            <description><![CDATA[<h2 id="jpa란">JPA란?</h2>
<p>JPA는 Java Persistence API의 약자로 자바 ORM 기술에 대한 API 표준 명세를 뜻한다. 대표적으로 패러다임 불일치 문제를 해결해주고, 영속성 컨텍스트를 제공해준다.</p>
<blockquote>
<p>ORM 이란?
Object Relational Mappaing의 약자로 객체와 관계형 데이터 베이스를 매핑해주는 기술이다. 객체는 객체대로, 관계형 데이터베이스는 관계형 데이터베이스대로 설계하고, ORM 프레임 워크가 중간에서 매칭을 해주는 역할을 한다.</p>
</blockquote>
<p>JPA는 인터페이스의 모음이다. 단순한 명세이기 때문에 구현체가 없다. 근데 우리는 어떻게 JPA라는걸 사용할 수 있을까?</p>
<h2 id="hibernate">Hibernate</h2>
<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/2c763db0-cd8b-4909-8b6d-3a0c4e04c45e/image.png" alt=""></p>
<p>우리는 Hibernate가 JPA를 구현한 구현체이기 때문에 JPA를 쓸 수 있는것이다!
개발한지 10년이 넘었고, 대중적으로 많이 이용하는 유명한 JPA의 구현체 중 하나이다.
Hibernamte는 내부적으로 JDBC를 이용해 관계형 데이터베이스와 커넥션을 맺고 상호작용한다.</p>
<p>JPA를 구현하는 다른 구현체들로는 EclipseLink나 DataNuclenus 등이 있다고 한다.</p>
<p>만약 JPA를 구현하는 구현체들이 프로젝트에서 맞지 않거나 마음에 들지 않는 경우 개발자가 직접 JPA 구현체를 만들어 사용할 수 있다고 한다.</p>
<h2 id="영속성-컨텍스트">영속성 컨텍스트</h2>
<p>JPA가 뭔지 알았으니 JPA의 내부 구조가 어떻게 돌아가는지 알아보자. 그러기 위해서는 영속성 구조에 대해서 이해해야 한다.</p>
<p>애플리케이션을 개발하면 EntityManagerFactory를 통해서 클라이언트 요청이 들어올때 마다 EntityManager를 생성한다. 또 EntityManager를 통해서 내부적으로 DB 커넥션을 해 DB를 사용하게 되는것이다.</p>
<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/8c9415ee-369c-4914-92db-8dc08b738df8/image.png" alt=""></p>
<p>위에 사진을 통해서 persist() 메서드가 어떻게 돌아가는지 알아보자.</p>
<h4 id="1-개발자가-userrepositorysaveusera-요청을-한다">1. 개발자가 userRepository.save(userA) 요청을 한다.</h4>
<p>개발자가 Entity를 DB에 저장하기 위해서 save 요청을 하면 EntityManager를 통해 persist()를 호출하게 된다. </p>
<pre><code class="language-java">SimpleJpaRepository.java

/*
 * (non-Javadoc)
 * @see org.springframework.data.repository.CrudRepository#save(java.lang.Object)
 */
@Transactional
@Override
public &lt;S extends T&gt; S save(S entity) {

    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}</code></pre>
<p>왜냐하면 위에 <code>save()</code> 메서드를 까보면 새로운 entity라면 <code>persist()</code> 메서드를 호출하게 개발이 되어 있기 때문이다. 새로운 entity가 아니라면 <code>merge()</code> 메서드를 호출하는데 <code>merge()</code> 메서드는 말그대로 병합 해주는 역할을 한다.</p>
<h4 id="2-영속성-컨텍스트-진입">2. 영속성 컨텍스트 진입</h4>
<p><code>persist()</code> 호출시 userA라는 객체는 영속성 컨텍스트 영역에 진입하게 된다. 이 영역에 진입시 Entity 단위로 변환되어 진입한다. 이렇게 영속성 컨텍스트 영역에 진입한 entity는 key-value로 1차 캐시 라는 영역에 또 저장된다. 이때 key는 @Id 어노테이션이 붙은 필드이고, value는 entity로 저장된다.
또한 동시에 userA entity를 DB에 저장하기 위한 insert 쿼리가 쓰기지연 SQL 저장소에 저장된다.</p>
<h4 id="3-트랜젝션-커밋시-쿼리문-db에-전송">3. 트랜젝션 커밋시 쿼리문 DB에 전송</h4>
<p>JPA는 한 트랜잭션 단위를 기반으로 DB에 작업을 처리한다. 트랜잭션 단위에 있는 비지니스 로직을 모두 처리한 후 commit() 메서드를 호출하면 쓰기지연 SQL 저장소에 저장되었었던 모든 쿼리문이 DB에 날라간다.
일차적으로는 그렇게 보일 수도 있지만 commit() 메서드가 flush() 메서드를 호출해 쿼리문이 DB에 날라가는것이다.</p>
<hr>
<h2 id="entity의-생명주기">Entity의 생명주기</h2>
<p>Entity의 생명주기는 4가지로 나뉜다.</p>
<blockquote>
</blockquote>
<ul>
<li>영속 상태</li>
<li>비영속 상태</li>
<li>준영속 상태</li>
<li>삭제 상태</li>
</ul>
<pre><code class="language-java">User user = new User();
user.setId(1L);
user.setName(&quot;JPA!&quot;); // 여기까지는 비영속 상태

em.persist(user); // 영속 상태 (영속성 컨텍스트에 의해 관리된다)
// =&gt; But, 아직 DB 에 저장되진 않았다. 즉 SQL 쿼리가 아직 안날라감

em.detach(user); // 준영속 상태
// =&gt; user 를 영속성 컨텍스트에서 분리한다. Dirty Checking.. 등 기능들을 사용하지 못함

em.remove(user); // 실제 DB에 영구 저장된 상태인 user 객체를 지우겠다는 요청</code></pre>
<hr>
<h2 id="변경-감지dirty-checking">변경 감지(Dirty Checking)</h2>
<p>JPA는 수정과 관련된 메소드가 존재하지 않는다. 변경감지는 데이터를 수정 할 수 있게 해주는 기능으로써, 
트랜잭션 커밋시 영속화된 entity에서 가지고 있던 스냅샷(최소 정보)와 바뀐 entity 정보를 비교해서 바뀐 부분을 수정 해주는 기능이다. </p>
<pre><code class="language-java">memberA.setNamge(10); // 영속 Entity 데이터 수정
// =&gt; 더티 체킹으로 인해, persist() 를 호출하지 않아도 자동으로 데이터가 수정된다.

transaction.commit(); // 트랜잭션 커밋</code></pre>
<p>위 코드 처럼 데이터가 바뀌면 스냅샷과 비교해 바뀌면 update 쿼리를 날린다.</p>
<hr>
<h2 id="🙇♂️-출처-🙇♂️">🙇‍♂️ 출처 🙇‍♂️</h2>
<p><a href="https://velog.io/@msung99/JPA-Persist-Context-%EB%A5%BC-%ED%86%B5%ED%95%9C-%EC%98%81%EC%86%8D%EC%84%B1-Entity-%EA%B4%80%EB%A6%AC-%EB%A9%94%EC%BB%A4%EB%8B%88%EC%A6%98">https://velog.io/@msung99/JPA-Persist-Context-%EB%A5%BC-%ED%86%B5%ED%95%9C-%EC%98%81%EC%86%8D%EC%84%B1-Entity-%EA%B4%80%EB%A6%AC-%EB%A9%94%EC%BB%A4%EB%8B%88%EC%A6%98</a></p>
<p><a href="https://bravenamme.github.io/2020/09/09/jpa_2/">https://bravenamme.github.io/2020/09/09/jpa_2/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[🤔 IoC 컨테이너란?]]></title>
            <link>https://velog.io/@sunggil-5125/IoC-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EB%9E%80</link>
            <guid>https://velog.io/@sunggil-5125/IoC-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EB%9E%80</guid>
            <pubDate>Fri, 31 Mar 2023 07:05:39 GMT</pubDate>
            <description><![CDATA[<p>IoC 컨테이너란 자바 객체의 라이프 사이클을 책임지고 의존성을 관리해주는 컨테이너 이다.</p>
<h3 id="왜-사용하는데">왜 사용하는데?</h3>
<p>IoC 컨테이너를 사용하지 않는다면 개발자가 필요한 객체가 있을때마다 New 키워드로 생성을 할것인데, IoC 컨테이너를 사용한다면 개발자가 필요한 객체를 IoC 컨테이너가 제공을 해줘 개발자는 비지니스 로직에 집중 할 수 있다. 객체 생성 코드도 없으므로 TDD에도 용이하다.</p>
<h3 id="bean-factory-application-context">Bean Factory, Application Context</h3>
<p>스프링 컨테이너는 두가지가 있다. Bean Factory와 Bean Factory를 상속하는 Application Context이다.</p>
<ol>
<li>Bean Factory</li>
</ol>
<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/5c5b3c94-2e67-4f24-a1d1-6e60035440cd/image.png" alt=""></p>
<ul>
<li>스프링 컨테이너의 최상위 인터페이스이다.</li>
<li>팩토리 디자인을 구현한 것으로, Bean을 관리, 생성, 조회 역할을 한다.</li>
<li>getBean() 메서드를 제공한다.</li>
<li>컨테이너가 구동될 때 Bean을 생성하는게 아닌 필요할때 요청에 의해서 사용 시점에 Bean이 생성되는 지연로딩(Lazy Loading) 방식을 사용한다.</li>
</ul>
<ol start="2">
<li>Application Context</li>
</ol>
<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/6a09a01f-bce6-48ba-8796-c723228eae86/image.png" alt=""></p>
<ul>
<li>Bean Factory의 기능을 모두 상속 받아서 제공한다.</li>
<li>Bean Factory와 달리 컨테이너가 구동될때 Bean을 생성하는 사전로딩(Pre Loading) 방식이 사용된다.</li>
<li>Bean Factory보다 더 다양한 기능을 제공한다.</li>
<li>MessageSource 메세지 소스를 활용한 국제화 기능 -&gt; 한국에서 들어오면 한국어, 영어로 들어오면 영어로 번역해준다.</li>
<li>EnvironmentCapable 환경변수 -&gt; 로컬, 개발, 운영 환경변수들을 구분해서 처리 한다.</li>
<li>ApplicationEventPublisher 어플리케이션 이벤트 -&gt; 이벤트를 발행하고 구독하는 모델을 편리하게 지원한다.</li>
<li>ResourceLoader 편리한 리소그 조회 -&gt; 파일, 클래스 패스, 외부 등에서 리소스를 편리하게 조회 한다.</li>
<li>요즘은 Bean Factory를 직접 사용하지 않고, 부과 기능이 추가된 Application Context를 사용한다고 한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[🤔 Bean 이란?]]></title>
            <link>https://velog.io/@sunggil-5125/Bean-%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@sunggil-5125/Bean-%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Wed, 29 Mar 2023 11:51:26 GMT</pubDate>
            <description><![CDATA[<p>Bean이란 IoC 컨테이너에서 관리되고, 애플리케이션에서 핵심을 이루는 자바 객체를 의미한다. IoC 컨테이너에서 관리된다는 점을 빼면 그냥 순수 자바 객체와 다름 없다. Bean은 디폴트로 싱글톤으로 생성된다.</p>
<h3 id="singleton싱글톤이란">Singleton(싱글톤)이란?</h3>
<p>애플리케이션 전영에서 인스턴스가 하나만 생성되게 보장하는 디자인 패턴이다.</p>
<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/921b0720-574b-450b-a799-c1f1c75cbf9f/image.png" alt=""></p>
<p>위에 그림을 보면 클라이언트가 memberService Bean을 요청했을때 IoC(DI) 컨테이너가 동일한 객체 인스턴스를 반환해주는것을 볼 수 있다.</p>
<blockquote>
<p>🚨 싱글톤 패턴의 주의점 🚨</p>
</blockquote>
<ul>
<li>하나의 인스턴스를 생성해서 공유하는것이기 때문에 객체의 상태를 유지하게 설계하면 안된다.</li>
<li>특정 클라이언트에 의존적이거나 값을 변경할 수 있는 필드가 있으면 안된다.</li>
<li>가급적 읽기만 가능해야 한다.</li>
<li>필드 대신 공유되지 않은 지역변수, 매개변수, TreadLocal을 사용하자.</li>
</ul>
<h3 id="bean-등록-방법은">Bean 등록 방법은?</h3>
<p>첫번째 방법으로는 @Component 어노테이션을 사용하는 것이다.
직접 클래스위에 @Compoenent 어노테이션을 사용해도 되고, stereotype인 @Service, @Controller, @Repository를 사용해서 Bean을 등록할 수 있다. stereotype인 어노테이션들도 까보면 @Component 어노테이션을 포함하기 때문에 가능한 것이다.</p>
<p>두번째 방법으로는 @Configuration 어노테이션과 @Bean 어노테이션을 사용하는 것이다. @Configuration 어노테이션은 해당 클래스에 Bean이 있으니 scan해라! 라는 어노테이션이다. @Bean 어노테이션은 해당 메서드를 Bean으로 등록하는것이다. @Bean을 사용해 등록 할 경우 메서드의 이름으로 Bean 이름이 된다.</p>
<h3 id="bean을-어떻게-등록하는데">Bean을 어떻게 등록하는데?</h3>
<p>~Application에 있는 @ComponenteScan 어노테이션 덕분에 ~Application 하위 패키지에 있는 Bean들을 스캔해 IoC 컨테이너에 Bean을 등록할 수 있다.
여기서 주의할 점은 ~Application이 속해있는 패키지 보다 Bean 스캔 대상이 상위 패키지에 있다면 ComponentScan이 되지 않는다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[🤔 JVM 이란?]]></title>
            <link>https://velog.io/@sunggil-5125/JVM-%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@sunggil-5125/JVM-%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Mon, 27 Mar 2023 10:55:44 GMT</pubDate>
            <description><![CDATA[<p>Java Virtual Machine, 자바 가상 머신의 줄임말으로, OS에 규약 받지 않고 Java 코드를 컴퓨터가 알아 먹을 수 있도록 컴파일 해주는 역할을 한다.
JVM이 있기에 우리는 리눅스, 윈도우, 맥 다양한 OS 환경에서 java코드를 실행 시킬 수 있는 것이다.</p>
<blockquote>
<p>JVM 덕분에 Write Once, Run Anywhere 을 가능하게 한다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/8356418c-4c3c-4cf5-be45-e07bfa41c9b4/image.png" alt=""></p>
<h3 id="compile">Compile</h3>
<p>1) 개발자가 자바 소스 파일(.java)를 작성한다.
2) 자바 컴파일러를 이용하여 자바 소스 파일을 컴파일 한다. 이때 나오는 파일은 바이트 코드로, 아직 JVM이 이해할 수 없다. java 코드와 이진 코드의 중간 지점이라 생각하면 된다.</p>
<h3 id="runtime">Runtime</h3>
<p>1) 바이트 코드를 클래스 로더에게 전달한다.
2) 클래스 로더는 동적 로딩을 통해 필요한 클래스들을 로딩 및 체크 하여 런타임 데이터 영역(Runtime-DateAreas), 즉 JVM의 메모리에 올린다.
3) 실행 엔진(Excution Engine)은 JVM 메모리에 올라온 바이트 코드들을 JVM 내부에서 실행 할 수 있도록 언어를 변경한다. 변경하는 방법은 두가지가 있다.</p>
<ul>
<li><p>인터프리터(Java Interpreter): 자바 바이트 코드들을 한줄씩 읽어서 기계어로 바꿔준다. 한줄씩 기계어로 바꾸는건 빠르지만 전체적인 실행 속도는 느리다는 단점이 있다.</p>
<br>
</li>
<li><p>JIT 컴파일러(Just-In-Time Compiler): 인터프리터의 단점을 보완하기 위해서 도입된 방식으로 바이트 코드 전체를 기계어로 바꾸는 방식이다. 그래서 빌드 시에 컴파일러 속도는 더 느리다. 하지만 그 이후에는 더 이상 인터프리팅 하지 않고 캐싱해 기계어로 변경한다. 즉 하나씩 인터프리팅 하는것이 아니라 만들어 둔 실행 파일을 읽기 때문에 실행 속도는 더 빠르다.</p>
</li>
</ul>
<h2 id="jvm-구성-요소">JVM 구성 요소</h2>
<h4 id="1-class-loder">1. class loder</h4>
<p>자바는 동적으로 코드들을 읽으므로, JVM이 동작하다가 클래스 파일을 참조하는 순간 동적으로 읽어서 JVM에 링크 된다. 자바 클래스 로더는 동적으로 메모리에 로딩 시켜주는 역할을 한다.</p>
<h4 id="2-runtime-dataareas">2. Runtime DataAreas</h4>
<p>JVM이 프로그램을 실행 시키기 위해 OS로 부터 별도로 할당받은 메모리 공간이다.
크게 5가지로 나뉜다.</p>
<ul>
<li><p>PC Register: 스레드가 시작될때 생성되며 스레드마다 하나씩 존재한다. 스레드가 어떤 부분을 어떤 명령으로 실행해야할지에 대한 기록을 하는 부분으로 현재 수행 중인 JVM의 명령의 주소를 나타낸다.</p>
</li>
<li><p>JVM Stack: 프로그램 실행 과정에서 임시로 할당 되었다가 메서드를 빠져 나가면 바로 소멸되는 특성의 데이터를 데이터를 저장하기 위한 영역이다. 메서드와 메서드 정보(메서드의 매개변수, 지역변수, 임시변수, 메소드 호출 주소)를 스택에 쌓는다. 메서드를 호출 할 때마다 각각의 스택 프레임(메서드를 위한 공간)이 생성된다. 메서드가 끝나면 프레임 별로 삭제한다.</p>
</li>
<li><p>Native Method Stack: 자바 외의 언어로 작성된 native 코드들을 위한 stack이다. 예로 Java Native Interface를 통해 호출되는 c/c++ 등의 코드를 수행한다. Natice Method를 호출하게 되면 Native Method Stack에 새로운 스택 프레임을 생성하여 푸시 한다. 이는 JVM 내부에 영향을 주지 않기 위함이다.</p>
</li>
<li><p>Method Area: 클래스 정보를 처음 메모리 공간에 올릴 때 초기화 되는 대상을 저장하기 위한 메모리 공간이다. 모든 쓰레드가 공유하는 메모리 영역이다. 클래스, 인터페이스, 메소드, 필드, static 등의 바이트 코드를 보관한다.</p>
</li>
<li><p>Heap: 프로그램 상에서 동적으로 할당하여 사용하는 영역이다. 클래스를 이용해 객체를 생성하면 힙에 저장된다. 공유 되는 자원이다.</p>
</li>
</ul>
<h4 id="3-garbage-collection">3. Garbage Collection</h4>
<p>가비지 컬렉션은 자바의 메모리 관리 방법 중의 하나로 JVM의 Heap 영역에서 동적으로 할당했던 메모리 영역 중 필요 없게 된 메모리 영역을 주기적으로 삭제하는 프로세스이다.</p>
<h2 id="jdk와-jre">JDK와 JRE</h2>
<h4 id="jre">JRE</h4>
<p>JRE는 자바 실행 환경(Java Runtime Environment)의 약자로 자바로 만들어진 프로그램을 실행 시키기 위해 필요한 라이브러리들과 각종 API, JVM이 포함되어 있다. </p>
<h4 id="jdk">JDK</h4>
<p>JDK는 자바 개발도구(Java Development Kit)의 약자로 JRE + 개발을 위해 필요한 도구 (javac, java등)들을 포함한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[🤔 스프링과 스프링 부트란?]]></title>
            <link>https://velog.io/@sunggil-5125/%EC%8A%A4%ED%94%84%EB%A7%81%EA%B3%BC-%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8%EB%9E%80</link>
            <guid>https://velog.io/@sunggil-5125/%EC%8A%A4%ED%94%84%EB%A7%81%EA%B3%BC-%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8%EB%9E%80</guid>
            <pubDate>Wed, 22 Mar 2023 14:12:30 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/560d1bf2-e1f0-48b9-8058-5b8a3ab35179/image.png" alt=""></p>
<h2 id="spring-framework">Spring Framework</h2>
<p>자바 EE 어플리케이션을 빌드 할 수 있는 오픈 소스 경량 프레임워크이다.
동적인 웹 사이트를 개발하기 위해(Jsp, Hibernate.. 등) 기술을 제공한다.</p>
<h2 id="spring의-특징">Spring의 특징</h2>
<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/f79cce4a-83b5-4a6e-b784-34f4f7fbb7b7/image.png" alt=""></p>
<h3 id="1-pojo-프로그래밍-지향">1. POJO 프로그래밍 지향</h3>
<p>스프링의 가장 큰 특징은 POJO 프로그래밍을 지향한다는 것이다.</p>
<blockquote>
<p>POJO란? Plain Old Java Object, 순수 Java만을 통해서 생성된 객체를 의미한다.</p>
</blockquote>
<p>순수 Java만을 사용한다는 것은 외부의 라이브러리와 외부의 모듈을 사용하지 않고
Java의 스펙에 정의된 기술만을 사용한다는 의미이다.</p>
<pre><code class="language-java">public class Person {

    String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}</code></pre>
<p>위에 코드는 필드와 getter, setter가 존재하는 기본적인 POJO의 예시이다.</p>
<h4 id="pojo는-이해했는데-왜-spring-프레임워크에서-지향하는-것일까">POJO는 이해했는데 왜 Spring 프레임워크에서 지향하는 것일까?</h4>
<p>바로 외부 기술에 얽매이지 않고 보다 유연하게 변화와 확장을 사용하기 위해서다. 만약 Person 객체가 사용하고 있는 외부 기술을 더 이상 사용할 수 없게 되거나, 개선된 신 기술이 등장한다면 Person 객체를 모두 뜯어 고쳐야하는 불상사가 생기기 때문에 Spring 프레임 워크는 POJO를 지향한다.</p>
<h3 id="2-di-ioc-컨테이너">2. DI, IoC 컨테이너</h3>
<p>Java는 객체지향 언어로써 객체간의 관계를 맺어주는것이 중요하다.
Spring이 객체간의 관계를 맺을때 도움을 주는것이 <code>DI(Dependency Injection)</code>이다.
<strong>DI는 객체를 직접 생성하는 방법이 아닌 외부에서 생성한 후에 주입 시켜주는 방식이다.</strong></p>
<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/bf95fbb3-e26f-4295-b31b-f071ecb328b7/image.png" alt=""></p>
<p>위 그림과 같이 DI를 사용해 객체간의 의존성을 만들어주게 되면 객체간의 결합도를 낮추게 되고, 객체의 유연성을 높일 수 있다.</p>
<p><strong>Ioc(Inversion of Control)는 객체의 생명주기를 책임지고, 의존성을 관리해주는 컨테이너이다.</strong>
위에서 외부에서 객체를 생성해준다고 했는데 생성해주는 대상이 IoC 컨테이너이다.
예시로 우리가 코드를 작성할때 생각해보면 Controller, Service 같은 객체들을 만들기는 하지만 어느 시점에 호출되고 의존성을 주입해주는지 따로 관리하지 않는다.
하지만 그런데도 의존성 주입이 잘 되고 코드가 잘 돌아간다! 이것은 IoC 컨테이너가 해당 역할을 해주기 때문이다.</p>
<h3 id="3-aop">3. AOP</h3>
<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/c88d8258-f90c-4f80-b63f-1251247e1368/image.png" alt=""></p>
<p>위 사진과 같이 객체 A, B, C에서 나타나는 블록 색깔은 중복적인 코드들이다.
이때 A 객체의 노란 블록 코드를 수정하게 된다면 B, C 객체들의 코드들도 일일히 찾아서 수정해야할것이다. 
이러한 문제점을 해결하기 위해 별도의 객체로 만들어 분리하는 기술을 <code>AOP</code>라고 한다.</p>
<h3 id="4-psa">4. PSA</h3>
<p>스프링은 백엔드 개발에 있어 핵심적인 프레임 워크이며, 백엔드 개발에서 데이터 베이스를 때어놓고 말하기는 어렵다.
만약 MySQL로 개발을 끝낸 상황인데 MariaDB로 데이터 베이스를 바꿔야 한다고 
한다고 가정해보자, 그러면 데이터 베이스에 관련된 모든 코드들을 수정해야할것이다.</p>
<p>하지만 우리는 개발하면서 한번도 그런적이 없다! <del>(그랬을 수도..)</del></p>
<p>스프링이 데이터베이스를 추상화 한 인터페이스를 제공해주기 때문이다! 스프링은 데이터 베이스에 접근하는 방법을 규정한 인터페이스를 제공하고 있으며, 이를 <code>JDBC(Java DataBase Connectivity)</code>라고 한다.</p>
<p>이렇게 특정 기술들을 부품처럼 쉽게 끼고 뺄 수 있게 서비스를 추상화 하여 일관된 방식으로 사용할 수 있는 것을<code>PSA(Portable Service Abstraction)</code>이라고 한다.</p>
<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/cc7b612f-e80d-4df6-a2d3-de34b3736ed6/image.webp" alt=""></p>
<h2 id="spring-boot">Spring Boot</h2>
<p>스프링은 앞서 설명한 만큼 기능들이 엄청나게 많다. 그래서 환경 설정이 엄청나게 복잡한데, 이러한 문제점을 해결한것이 Spring Boot이다. 스프링 부트는 스프링 프레임 워크를 간편하게 사용하기 위해서 도와준다.</p>
<h2 id="spring과-spring-boot의-차이점">Spring과 Spring Boot의 차이점</h2>
<ol>
<li>Spring Boot에는 Tomcat이 내장되어 있어 Tomcat을 설치하거나 버전 변경등 수고로운 부분을 덜어준다.</li>
<li>Spring 프레임워크는 각각의 dependency들의 호환 되는 부분들을 일일히 맞춰줘야 되서 하나의 버전을 올리면 다 올려야하는 불상사가 생기는데 Spring Boot는 starter가 모든 문제들을 다 해결해준다.</li>
<li>XML 설정을 따로 안해줘도 된다. </li>
<li>jar 파일을 이용해 손쉽게 배포가 가능하다.</li>
</ol>
<h2 id="🙇♂️-출처">🙇‍♂️ 출처</h2>
<p><a href="https://www.codestates.com/blog/content/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8">스프링과 스프링부트(Spring Boot)ㅣ정의, 특징, 사용 이유, 생성 방법 | 코드인사이트</a></p>
<p><a href="https://velog.io/@courage331/Spring-%EA%B3%BC-Spring-Boot-%EC%B0%A8%EC%9D%B4">Spring 과 Spring Boot 차이 | velog</a></p>
<p><a href="https://code-lab1.tistory.com/193">[Spring] AOP(Aspect Oriented Programming)란? 스프링 AOP란? | tistory</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[spring boot + aws로 첫 배포 후기]]></title>
            <link>https://velog.io/@sunggil-5125/spring-boot-aws%EB%A1%9C-%EC%B2%AB-%EB%B0%B0%ED%8F%AC-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@sunggil-5125/spring-boot-aws%EB%A1%9C-%EC%B2%AB-%EB%B0%B0%ED%8F%AC-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Thu, 14 Jul 2022 08:36:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>링크 <a href="https://dev-log.kr">https://dev-log.kr</a></p>
</blockquote>
<h2 id="프로젝트를-시작하게-된-계기">프로젝트를 시작하게 된 계기</h2>
<p>Nest.js에서 Spring Boot로 프레임 워크를 바꿨을 당시 프로젝트를 해서 실력을 향상 시키고 싶었는데, 마침 같은 반 프론트를 공부하는 친구가 개인 프로젝트로 블로그를 만들길래 꼽 껴서 시작하게 되었다.</p>
<hr>
<h2 id="배포-과정">배포 과정</h2>
<h3 id="ec2">ec2</h3>
<p>일단 배포는 처음이라 aws 프리티어 계정을 만들고 ec2 인스턴스를 만들었다.</p>
<h3 id="build">build</h3>
<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/159da0c6-fe01-4af7-b3fa-2dd58c78157c/image.png" alt=""></p>
<p>Gradle -&gt; build 한 후</p>
<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/c134db39-6eae-43a7-8163-eb02efabbb76/image.png" alt=""></p>
<p><strong>FileZilla</strong>로 내 <strong>build</strong> 파일을 옮긴 다음에 window powershell로 ec2에 접속을 하고 서버를 키니...!</p>
<h3 id="오류">오류</h3>
<p><img src="https://velog.velcdn.com/images/sunggil-5125/post/c20d10ed-9fc4-44b5-8852-08f1ddeff2b8/image.png" alt=""></p>
<p>두둥.. 이런 오류가 떴었다...</p>
<p>친구가 말해주길 MySQL 외부 접근 허용이 안되어 있어서 그런거 같다고 해서 
내 계정에 외부 접속 권한을 허용하게도 만들고, 계정을 새로 만들어 보았는데.. 결국 안됐었다..
rds를 쓸려고 했지만 돈이 엄청 깨진다는 소리를 듣고 ec2에서 MySQL을 깔아서 ec2 퍼블릭 ipv4 주소로 Workbench test connection을 하니 <strong>성공</strong>..!
그 후 gabia에서 도메인을 사고 ssl 인증서 까지 발급 후 도메인으로 접속을 하니까 배포 성공!!</p>
<hr>
<h2 id="아쉬운-점">아쉬운 점</h2>
<p>screen을 따서 배포 후 ssh 접속이 꺼지면 다시 접속이 안되는것이다..! 내가 잘 못 한건지 모르겠지만
이 부분으로 무중단 배포가 중단 배포가 되어버려 계속 ec2 인스턴스를 껏다가 켜야 한다..
이 문제의 해결 방법을 아시는 분은 연락 부탁드립니다.. 😢 </p>
<blockquote>
<p>discord : 성길#0091</p>
</blockquote>
<h2 id="개발-기한">개발 기한</h2>
<p><code>4월 16일 ~ 7월 4일</code></p>
<hr>
<h2 id="깃허브-링크">깃허브 링크</h2>
<blockquote>
<p>Back-End(나) : <a href="https://github.com/SungGil-5125/Blog">https://github.com/SungGil-5125/Blog</a>
Front-End(환빈) : <a href="https://github.com/HWANBINYOO/React-project/tree/main/vlog">https://github.com/HWANBINYOO/React-project/tree/main/vlog</a></p>
</blockquote>
<h2 id="글을-마치며">글을 마치며</h2>
<p>이 프로젝트를 시작 할 당시는 김영한님의 무료 강의를 다 보고 개발을 들어가서
내가 폐를 안끼치고 개발을 할 수 있을까?!?! 하는 걱정도 있었지만,
부족한 코딩 실력에 맞추면서 함께 프로젝트를 진행해준 프론트 개발자 환빈이한테 너무 고맙다👍</p>
<p><code>ps. spring security 얼마 안썼는데 정보보안 애들이 못뚫음..ㅋㅋㅋ</code></p>
]]></description>
        </item>
    </channel>
</rss>