<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ameri-kano</title>
        <link>https://velog.io/</link>
        <description>똑똑한 사람이 되게 해주세요</description>
        <lastBuildDate>Sun, 04 Aug 2024 14:52:03 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>ameri-kano</title>
            <url>https://velog.velcdn.com/images/ameri-kano/profile/bbc80eef-7db2-4755-8e85-291b2580b6c4/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ameri-kano. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ameri-kano" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[네이버 부스트캠프 챌린지] 3주차 개인 회고]]></title>
            <link>https://velog.io/@ameri-kano/%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%B6%80%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%94%84-%EC%B1%8C%EB%A6%B0%EC%A7%80-3%EC%A3%BC%EC%B0%A8-%EA%B0%9C%EC%9D%B8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@ameri-kano/%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%B6%80%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%94%84-%EC%B1%8C%EB%A6%B0%EC%A7%80-3%EC%A3%BC%EC%B0%A8-%EA%B0%9C%EC%9D%B8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Sun, 04 Aug 2024 14:52:03 GMT</pubDate>
            <description><![CDATA[<p>3주차가 끝났고, 4주차만을 남겨두고 있다.
이번주는 개인적으로 마음을 다시 먹고 조금 더 적극적으로 활동에 참여하려 해본 주간이었다.
어떤 것들을 했냐면,</p>
<h2 id="피어세션을-주도하다">피어세션을 주도하다</h2>
<p>팀원들과 함께 해결 과정을 발표하고 질문이나 피드백, 또는 사담을 주고받을 수도 있는 피어세션 시간이 매일 주어진다. 이번 주는 이 피어세션에서 딱히 누가 시키지는 않았지만 진행을 주도해보았다. 각자 최대한으로 설명을 할 수 있도록 분량을 조율해보려 하고, 또는 대화 주제를 던지고 이야기를 주고받는 것을 적극적으로 도우려고 했다.
아주 완벽한 진행이었는지는 잘 모르겠지만, 그래도 금요일에 이번 주 팀원들과 마무리로 팀 회고를 하면서 잘 이끌어주셔서 고맙다는 말을 듣고 이번 주는 미션 해결 이외에도 더 유익한 한 주를 보낸 것 같아 뿌듯했다.</p>
<h2 id="함께-개발-진행하기">함께 개발 진행하기</h2>
<p>사실 지난 주에 짝과 함께 미션을 해결하는 시간이 있었으나 예비군 때문에 경험하지 못했던 게 좀 아쉬웠다. 그래서 이번 주가 짝과 함께 해결하는 첫 시간이었기 때문에 혹시나 내가 부족하지는 않을까 조금의 걱정도 했었다. 그렇게 짝과 개발을 진행했는데, 가장 재미있었던 부분은 서로를 이해시키는 시간이었다.
결국 같은 과제를 두고 개발을 진행하려면 두 명이 이해한 내용, 그리고 해결하기 위해 학습한 지식, 그리고 해결하는 방향성을 조율하는 것이 가장 중요했다. 개인으로 해결할 때에는 내 자신이 어떻게 해결했는지 설명하고, 내 자신이 생각한 대로 질문에 답변하면 됐다. 그러나 함께 해결하기 위해서는 서로가 미션의 내용이나 학습한 내용을 서로 주고받고, 주고받는 과정에서 상대를 이해시키고 조율하여 해결의 방향성을 맞춰나가야 했다. 
그리고 이 과정이 실시간으로 이루어져 즉각적으로 질문이나 피드백을 나눌 수 있었다. 미션을 해결해 나가기 위한 시간은 더 걸렸고 결과도 아주 뛰어나진 않았지만 이 과정이 너무 뜻깊었다.
개인적으로 남을 이해시키기 위한 설명을 하기 위해 꽤 노력한다고 생각했는데도 아직은 부족했던 것 같지만, 조금이라도 늘은 것 같아서 다행인 것 같다. 개발 문제 해결 능력이 발전해 나가고 있다는 것이니까.</p>
<h2 id="학습-설계-구현-의-루틴-지키기">학습-설계-구현 의 루틴 지키기</h2>
<p>미션은 가볍게 훑어 보고, 해결을 위한 학습에 먼저 집중했다. 그리고 학습의 시간을 고정하려 노력했다. 예를 들어 10시에 시작했다면, 학습을 12시까지 끝마치고 점심을 먹은 뒤, 1시부터 해결을 시작하는 루틴을 지키려 노력했다. 결과적으로 반은 성공했고 반은 실패했다. 학습을 12시 내에 마쳤을 때도 있고, 내용이 많아 제 시간에 못 끝내기도 했기 때문이다. 그렇지만 제한 시간을 두니 조금 더 집중력이 상승한 것 같아서, 집중을 늘리고 싶다는 목표를 달성하게 된 것 같아서 좋았다. 학습의 예를 들어보면, </p>
<ul>
<li>미션이 프로 야구 선수들의 데이터를 뽑아 리포트를 만드는 것이라고 하자. (실제 미션 내용과 무관하다.)</li>
<li>그렇다면 각 데이터(타율, 타점, 평균자책점 등)의 의미를 먼저 학습한다.</li>
<li>그 다음 리포트를 작성하기 위해 통계를 내는 방법(평균, 중앙값, 분산)을 학습한다.</li>
<li>그리고 리포트를 작성하는 순서와 방법을 학습한다.</li>
</ul>
<p>이런 느낌으로 학습을 진행하니, 읽어보면서 이해가 되지 않았던 부분도 어떻게 해결해야 할지 방향성을 조금 더 쉽게 잡을 수 있었다.</p>
<h2 id="이대로-잘-마무리하자">이대로 잘 마무리하자</h2>
<p>해낸 것들이 저번보다 늘어서 그래도 발전했구나를 느꼈다. 이제 정말 1주일 밖에 남지 않았는데, 조금 더 집중을 늘리고 더 적극적으로 참여하여 남은 1주일을 마무리하고 싶다. 적어도 후회는 남지 않도록.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[디자인 패턴에 대하여]]></title>
            <link>https://velog.io/@ameri-kano/design-pattern</link>
            <guid>https://velog.io/@ameri-kano/design-pattern</guid>
            <pubDate>Tue, 16 Jan 2024 07:43:07 GMT</pubDate>
            <description><![CDATA[<h2 id="들어가기-전에">들어가기 전에</h2>
<p>얘기는 안했지만 작년 12월 초에 입사하여 열심히 교육받고 공부 중이다. 개발에 필요한 지식을 여러 가지 습득 중에 있는데, 그 중에 면접에서도 질문받았으면서 생각보다 다양하고 복잡하고 중요하다 생각이 드는 디자인 패턴에 대해 전반적인 내용을 정리해봤다. 각각 패턴에 대해서도 하나씩 정리해볼 예정이다.</p>
<hr>
<h2 id="디자인-패턴이란">디자인 패턴이란?</h2>
<p>디자인 패턴은 소프트웨어 디자인 과정에서 자주 발생하는 문제들에 대한 전형적인 해결책이다. 코드에서 반복되는 디자인 문제를 해결하기 위한 청사진과 같다. 청사진이라는 의미는 구체적인 구현은 개발자가 직접 해야 한다는 의미이다.</p>
<p>라이브러리나 함수 코드는 복사해서 사용할 수 있지만 패턴은 그렇게 사용할 수는 없다. 위에서 말한 것 처럼 구현된 코드가 아니라, 문제를 해결할 수 있는 일반적인 개념이기 때문이다.</p>
<h2 id="디자인-패턴이-왜-필요한가">디자인 패턴이 왜 필요한가?</h2>
<p>그렇다면 디자인 패턴은 왜 필요할까? 디자인 패턴은 일반적인 소프트웨어 디자인 문제들에 대해 시도되었으며 검증된 해결책들을 모은 것이다. 꼭 다루지 않더라도 패턴을 알고 있다면 객체 지향 디자인 원칙들로 많은 종류의 문제를 해결하는 방법을 배울 수 있기 때문이다.</p>
<p>그리고, 개발자들끼리 서로 효율적으로 소통할 수 있는 공통 표준/언어 를 디자인 패턴으로 정의한다. 예를 들어 “이 문제를 해결하기 위해 해당 인스턴스를 <strong>애플리케이션 전역적으로 하나만 정의하고 어디에서든 접근할 수 있도록 구현</strong>하였습니다.” 라고 말해도 되겠지만 이 말은 결국 “해당 인스턴스를 <strong>싱글톤(singleton) 패턴을 이용해 구현</strong>하였습니다.” 라고 말해도 의미가 통할 것이다. 싱글톤 패턴에 대해서 알고 있는 개발자라면 상세하게 설명할 필요도 없어질 것이다.</p>
<h2 id="디자인-패턴의-한계점">디자인 패턴의 한계점</h2>
<p>그렇지만 디자인 패턴에는 명확한 한계점도 존재한다.</p>
<h3 id="약한-프로그래밍-언어에서-야매-해결책이-되어버릴-수-있다">약한 프로그래밍 언어에서 야매(?) 해결책이 되어버릴 수 있다.</h3>
<blockquote>
<p>💡 두 가지 짚고 넘어가야 할 부분이 있는데, <strong>약한 프로그래밍 언어</strong>란 변수나 데이터 타입을 명시적으로 선언하지 않으며, 컴파일러나 인터프리터가 알아서 타입 변환을 수행하는 언어를 말한다. 예를 들어 자바스크립트 같은 언어를 의미한다. 자바스크립트에서 <code>var a = “Hello”</code> 처럼 변수를 선언하면 알아서 문자열로 인식하게 된다.
’야매’ 는 참고한 글의 원문에서는 <strong>클루지</strong>(Kludge, 그냥 빨리 날림으로 그 문제만을 해결하기 위해 만든 허술하고 조잡한 코드) 라고 나와있었지만 바로 이해하는 데에는 야매 라는 단어가 더 편할 것 같아서 임의로 고쳤다.</p>
</blockquote>
<p>일반적으로 패턴은 개발자가 추상화 수준이 부족한 프로그래밍 언어나 기술을 선택했을 때 발생한다. 이런 경우 패턴은 결국 어디에나 다 들어가 버릴 수 있는 초능력을 가진 야매 해결책이 되어버린다. 예를 들어 <strong>전략(Strategy) 패턴</strong>은 대부분의 최신 프로그래밍 언어에서 간단한 익명(람다) 함수로 구현 가능한데 패턴만을 적용하면 나중에 문제가 발생할 수도 있지 않을까?</p>
<h3 id="비효율적인-해결책이-될-수도-있다">비효율적인 해결책이 될 수도 있다.</h3>
<p>패턴은 널리 사용되는 문제 해결 방식을 체계화한 것이다. 이렇게 통합된 패턴들을 프로젝트의 맥락에 따라 적용하지 않고 그대로 사용하여 구현해버리면 오히려 비효율적인 방법이 될 수도 있다.</p>
<h3 id="불필요한-부분에서-사용할-수도-있다">불필요한 부분에서 사용할 수도 있다.</h3>
<p>패턴을 처음 배운 사람이 패턴을 배운 후, 굳이 패턴이 필요하지 않은 간단한 문제도 억지로 패턴을 적용하려 할 수도 있다. 분명 좋은 해결 방법일 수는 있지만 상황에 맞게 적절히 적용하는 것이 중요하다고 할 수 있겠다.</p>
<h2 id="패턴의-분류">패턴의 분류</h2>
<p>디자인 패턴은 복잡성, 상세도, 적용 범위에 따라 분류할 수 있다.</p>
<p>가장 기본적인 하위 설계 패턴을 <strong>이디엄(idiom)</strong> 이라고 한다. 일반적으로 단일 프로그래밍 언어에 적용할 수 있다. </p>
<p><strong>아키텍처(architecture)</strong> 패턴은 상위 설계 패턴으로 가장 보편적으로 사용된다. 거의 모든 언어로 아키텍처 패턴을 구현할 수 있으며 다른 패턴들과 달리 어플리케이션 전체 구조(아키텍처)를 설계하는 데 사용할 수 있다.</p>
<p>그리고 모든 패턴은 패턴의 의도나 목적에 따라 분류할 수 있다.</p>
<ul>
<li><strong>생성 패턴(Creational patterns)</strong></li>
<li><strong>구조 패턴(Structural patterns)</strong></li>
<li><strong>행동 패턴(Behavioral patterns)</strong></li>
</ul>
<h2 id="생성-패턴">생성 패턴</h2>
<p>생성 패턴은 <strong>기존 코드의 재활용과 유연성을 증가시키는 객체 생성 매커니즘들을 제공</strong>한다. 생성 패턴에는 <strong>팩토리 메서드(factory method), 추상 팩토리(abstract factory), 빌더(builder), 프로토타입(prototype), 싱글톤(singleton)</strong> 등이 있다.</p>
<h2 id="구조-패턴">구조 패턴</h2>
<p>구조 패턴은 <strong>구조를 유연하고 효율적으로 유지하면서 객체와 클래스를 더 큰 구조로 조합하는 방법을 설명</strong>한다. 구조 패턴에는 <strong>어댑터(adapter), 브릿지(bridge), 컴포지트(composite), 데코레이터(decorator), 퍼사드(facade), 플라이웨이트(flyweight), 프록시(proxy)</strong> 등이 있다.</p>
<h2 id="행동-패턴">행동 패턴</h2>
<p>행동 패턴은 <strong>객체 간의 효과적인 의사소통과 책임 할당을 처리</strong>한다. 행동 패턴에는 <strong>책임 연쇄(Chain of Responsibility), 커맨드(command), 반복자(iterator), 중재자(mediator), 메멘토(memento), 옵저버(observer), 상태(state), 전략(strategy), 템플릿 메서드(template method), 비지터(visitor)</strong> 등이 있다.</p>
<hr>
<h2 id="참고-자료">참고 자료</h2>
<p><a href="https://refactoring.guru/ko/design-patterns">디자인 패턴들</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[면접 대비/프로그래밍] 객체 지향 설계의 SOLID 원칙]]></title>
            <link>https://velog.io/@ameri-kano/%EB%A9%B4%EC%A0%91-%EB%8C%80%EB%B9%84-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%EC%84%A4%EA%B3%84%EC%9D%98-SOLID-%EC%9B%90%EC%B9%99</link>
            <guid>https://velog.io/@ameri-kano/%EB%A9%B4%EC%A0%91-%EB%8C%80%EB%B9%84-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%EC%84%A4%EA%B3%84%EC%9D%98-SOLID-%EC%9B%90%EC%B9%99</guid>
            <pubDate>Sun, 12 Nov 2023 04:12:42 GMT</pubDate>
            <description><![CDATA[<h3 id="시작하며">시작하며</h3>
<p>이번 주제는 객체지향 프로그래밍에서 한번 쯤 들어보고, 실현하면 정말 이상적이라고 하지만 정말 실전에서 적용하기는 많은 노력이 필요한 것 같은 SOLID 원칙에 대해 정리해 봤다.
(자바 코딩 인터뷰 완벽 가이드 라는 책을 참고했다)</p>
<hr>
<h3 id="solid-원칙">SOLID 원칙</h3>
<p>SOLID란 프로그래머의 바이블이라 할 수 있는 클린 코드의 저자이기도 한 로버트 C. 마틴이 발표한 5가지의 객체지향 설계 원칙의 첫 글자를 순서대로 가져온 것이다.</p>
<h3 id="s---단일-책임-원칙">S - 단일 책임 원칙</h3>
<p>단일 책임 원칙(Single responsibility principle)은 <strong>하나의 클래스는 단 하나의 책임만 져야 한다</strong>는 의미를 뜻한다. 하나의 목표만을 위해 클래스를 작성한다면 유지보수 및 가시성을 높게 유지할 수 있게 된다.</p>
<h3 id="o---개방-폐쇄-원칙">O - 개방 폐쇄 원칙</h3>
<p>개방 폐쇄 원칙(Open-closed principle)은 <strong>소프트웨어 컴포넌트는 확장에 관해 열려 있고 수정에 관해 닫혀 있어야 한다</strong>는 의미이다. 다른 개발자가 단순히 클래스를 확장하기만 해도 클래스의 동작을 수정할 수 있도록 클래스를 설계하고 작성해야 한다는 의미이다. 즉 수정이 필요한 제약 사향을 클래스에 포함해서는 안 되며, 다른 개발자가 이 클래스를 확장하기만 하면 원하는 작업이 가능하도록 만들어야 한다.</p>
<h3 id="l---리스코프-치환-원칙">L - 리스코프 치환 원칙</h3>
<p>리스코프 치환 원칙(Liskov substitution principle)은 미국의 컴퓨터 과학자 바바라 리스코프가 발표한 원칙으로, <strong>파생 타입은 반드시 기본 타입을 완벽하게 대체할 수 있어야 한다</strong>는 의미이다. 즉, 모든 자식 클래스의 객체가 부모 클래스의 객체와 반드시 같은 방식으로 동작해야 한다. 이렇게 구현하면 타입 변환 후에 뒤따라오는 런타임 타입 식별에 유용하다.</p>
<h3 id="i---인터페이스-분리-원칙">I - 인터페이스 분리 원칙</h3>
<p>인터페이스 분리 원칙(Interface segregation principle)은 <strong>클라이언트가 사용하지 않을 불필요한 메서드를 강제로 구현하게 해서는 안된다</strong>는 의미이다. 클라이언트가 사용하지 않을 메서드를 강제로 구현해야 하는 일이 없을 때까지 하나의 인터페이스를 2개 이상의 인터페이스로 분할해야 한다는 의미이다.</p>
<h3 id="d---의존관계-역전-원칙">D - 의존관계 역전 원칙</h3>
<p>의존관계 역전 원칙은 <strong>구체화가 아닌 추상화에 의존해야 한다</strong>는 의미이다. 구상된 모듈에 의존하는 새로운 구상 모듈 대신, 구상 모듈을 결합하기 위해 추상 계층에 의존해야 한다는 것이다. 이를 위해 모든 구상 모듈은 추상적인 내용만 노출해야 하며, 이를 통해 구상 모듈들은 분리된 상태를 유지하면서 다른 구상 모듈에 대해 확장할 수 있다.</p>
<h3 id="예상-질문">예상 질문</h3>
<blockquote>
<p>구체화가 아닌 추상화에 의존해야 한다고 했는데, 그렇다면 객체지향에서 추상화의 개념은 무엇인가?</p>
</blockquote>
<p>추상화란 객체지향 프로그래밍의 중요 개념 중 하나로, 객체지향 프로그래밍의 객체는 사용자에게 높은 수준의 작업 집합만 노출하고 이 작업의 내부 구현 내용은 숨겨야 합니다. 추상화하여 구현하면 사용자는 어플리케이션이 일을 수행하는 방법이 아닌 수행하는 일 자체에 집중할 수 있게 됩니다. 중요한 내용만 노출하여 복잡성을 줄이고 보안을 유지하게 되는 것입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[면접 대비/DB] 동시성 제어(Concurrency Control)]]></title>
            <link>https://velog.io/@ameri-kano/%EB%A9%B4%EC%A0%91-%EB%8C%80%EB%B9%84-DB-%EB%8F%99%EC%8B%9C%EC%84%B1-%EC%A0%9C%EC%96%B4</link>
            <guid>https://velog.io/@ameri-kano/%EB%A9%B4%EC%A0%91-%EB%8C%80%EB%B9%84-DB-%EB%8F%99%EC%8B%9C%EC%84%B1-%EC%A0%9C%EC%96%B4</guid>
            <pubDate>Sun, 05 Nov 2023 05:19:10 GMT</pubDate>
            <description><![CDATA[<h3 id="시작하며">시작하며</h3>
<p>이번 주제는 DB의 트랜잭션 (transaction) 에서 중요하게 생각하는 동시성 제어 (Concurrency Control) 이다.</p>
<hr>
<h3 id="동시성-제어concurrency-control">동시성 제어(Concurrency Control)</h3>
<blockquote>
<p>동시성 제어(Concurrency Control)란 동시에 실행되는 여러 개의 트랜잭션이 작업을 성공적으로 마칠 수 있도록 트랜잭션의 실행 순서를 제어하는 기법이다.</p>
</blockquote>
<h3 id="동시성-제어의-정의">동시성 제어의 정의</h3>
<p>다중 사용자 환경을 지원하는 데이터 베이스 시스템에서 여러 트랜잭션들이 성공적으로 동시에 실행될 수 있도록 지원하는 기능이다. 다중 사용자 환경을 지원하는 DB system의 경우 필수적으로 지원해야 하는 기능으로 병행제어 라고도 한다. 동시성 제어를 통해 트랜잭션의 직렬화 수행(여러 작업이 동시에 일어나지 않고 일정한 순서를 지키며 한 번에 하나의 트랜잭션을 수행하는 것)을 보장할 수 있게 된다.</p>
<h3 id="동시성-제어의-목적">동시성 제어의 목적</h3>
<ul>
<li>트랜잭션의 직렬성 보장</li>
<li>공유도 최대, 응답 시간 최소, 시스템 활동의 최대 보장</li>
<li>데이터의 무결성 및 일관성 보장</li>
</ul>
<h3 id="동시성-제어를-하지-않을-경우-발생하는-문제">동시성 제어를 하지 않을 경우 발생하는 문제</h3>
<h4 id="갱신-손실-lost-update">갱신 손실 (Lost Update)</h4>
<ul>
<li>하나의 트랜잭션이 갱신한 내용을 다른 트랜잭션이 덮어씀으로써 갱신이 무효화가 되는 것을 의미</li>
<li>두 개이상 트랜잭션이 한 개의 데이터를 동시에 갱신(Update)할 때 발생</li>
</ul>
<h4 id="현황파악오류-dirty-read">현황파악오류 (Dirty Read)</h4>
<ul>
<li>읽기 작업을 하는 트랜잭션 1이 쓰기 작업을 하는 트랜잭션 2가 작업한 중간 데이터를 읽기 때문에 발생하는 문제</li>
<li>작업중인 트랜잭션 2가 작업을 Rollback한 경우 트랜잭션 1은 무효가 된 데이터를 읽게 되고 잘못된 결과를 도출한다.</li>
</ul>
<h4 id="모순성-inconsistency">모순성 (Inconsistency)</h4>
<ul>
<li>다른 트랜잭션들이 해당 항목 값을 갱신하는 동안 한 트랜잭션이 두 개의 항목 값 중 어떤 것은 갱신되기 전의 값을 읽고 다른 것은 갱신된 후의 값을 읽게 되어 데이터의 불일치가 발생하는 상황</li>
</ul>
<h4 id="연쇄복귀-cascading-rollback">연쇄복귀 (Cascading Rollback)</h4>
<ul>
<li>두 트랜잭션이 동일한 데이터 내용을 접근할 때 발생</li>
<li>한 트랜잭션이 데이터를 갱신한 다음 실패하여 Rollback 연산을 수행하는 과정에서, 갱신과 Rollback 연산을 실행하고 있는 사이에 해당 데이터를 읽어서 사용할 때 발생할 수 있는 문제</li>
</ul>
<h3 id="예상질문">예상질문</h3>
<blockquote>
<p>동시성을 제어할 수 있는 기법에는 어떤 것들이 있나요?</p>
</blockquote>
<p>트랜잭션이 데이터에 락을 거는 락킹(locking) 기법, 시스템에서 생성하는 고유 시간 번호인 타임스탬프를 트랜잭션에 부여하여 접근 순서를 보장하는 타임스탬프(timestamp) 기법, 트랜잭션을 수행하고 종료할 때 적합성을 검증하여 최종 반영하는 적합성 검증(validation) 이 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[스터디/알고리즘] BFS]]></title>
            <link>https://velog.io/@ameri-kano/BFS</link>
            <guid>https://velog.io/@ameri-kano/BFS</guid>
            <pubDate>Thu, 02 Nov 2023 09:46:11 GMT</pubDate>
            <description><![CDATA[<h3 id="시작하며">시작하며</h3>
<p>저번 주는 DFS였다면 BFS가 안 나오면 섭하다. 둘 다 그래프 탐색의 방법이지만 확실한 구현 방법과 용도의 차이가 있는 만큼 정리해 볼 필요가 있다고 생각한다.</p>
<hr>
<h2 id="bfsbreadth-first-search">BFS(Breadth First Search)</h2>
<p><code>BFS(Breadth First Search, 너비 우선 탐색)</code> 는 <code>DFS</code>와 마찬가지로 그래프 탐색 방법 중 하나이다. 최대한 깊숙히 들어가서 노드를 방문하던 DFS와 달리 인접한 노드들을 우선해서 방문하며, 그렇게 전체를 방문할 수 있도록 넓게(너비를 우선으로) 뻗어나가며 탐색한다. 이를 위해 <code>큐</code> 자료구조를 이용하며, 자세한 과정은 다음과 같다.</p>
<ol>
<li>탐색을 시작하는 노드(시작점)을 큐에 삽입(enqueue) 하고 방문 처리한다.</li>
<li>큐에서 노드를 꺼내(dequeue), 해당 노드 중에 방문 처리하지 않은 노드들을 전부 큐에 삽입하고 방문 처리한다.</li>
<li>이 과정을 모두 끝날 때 까지 반복한다.</li>
</ol>
<p>각각을 활용하여 해결할 수 있는 문제의 유형도 많이 다르다. 
문제를 해결했던 경험 상으로는, 여러 개의 각각의 그래프가 나뉘어져 있으면 DFS를 사용했고(막힌 곳 까지 먼저 갔다 돌아와야 나뉘어진 그래프의 개수를 파악하기 더 쉽다), 미로에서 탈출하는 유형의 문제에선 미로를 그래프로 표현해 BFS를 이용했었다. 미로를 탈출하려면 도착점까지 모든 경우를 생각하여 도달해야 하기 때문이라고 생각하면서 문제를 해결했던 기억이 난다.</p>
<h2 id="구현-예시">구현 예시</h2>
<p>DFS에서 이용했던 그래프와 같은 그래프를 가져왔다. (결과의 차이를 비교하기 쉽게 하기 위함이다)
<img src="https://velog.velcdn.com/images/ameri-kano/post/46cf113f-5683-4a80-911f-af2f7c6b6f96/image.png" alt=""></p>
<p>BFS를 수행하는 Java 코드와 결과는 다음과 같다.</p>
<h3 id="코드">코드</h3>
<pre><code class="language-java">package algorithm;

import java.util.ArrayDeque;
import java.util.HashMap;
import java.util.List;

public class GraphSearch {

  static void initGraph(HashMap&lt;Integer, List&lt;Integer&gt;&gt; graph) {
    for(int i=1; i&lt;=8; i++) {
      graph.put(i, List.of());
    }

    graph.put(1, List.of(2, 3, 4));
    graph.put(2, List.of(7));
    graph.put(4, List.of(5, 6));
    graph.put(5, List.of(6));
    graph.put(7, List.of(8));
  }

  static void BFS(int start, HashMap&lt;Integer, List&lt;Integer&gt;&gt; graph,
      boolean[] visited) {
    ArrayDeque&lt;Integer&gt; queue = new ArrayDeque&lt;&gt;();
    visited[start] = true;
    queue.add(start);

    while (!queue.isEmpty()) {
      int current = queue.pollFirst();
      System.out.print(current + &quot; &quot;);

      for (int v: graph.get(current)) {
        if (!visited[v]) {
          queue.add(v);
          visited[v] = true;
        }
      }
    }
  }

  public static void main(String[] args) {
    HashMap&lt;Integer, List&lt;Integer&gt;&gt; graph = new HashMap&lt;&gt;();
    boolean[] visited = new boolean[9];

    initGraph(graph);
    BFS(1, graph, visited);
  }
}</code></pre>
<h3 id="결과">결과</h3>
<pre><code class="language-java">1 2 3 4 7 5 6 8</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[면접 대비/OS] 교착 상태(deadlock)]]></title>
            <link>https://velog.io/@ameri-kano/%EB%A9%B4%EC%A0%91-%EB%8C%80%EB%B9%84-OS-%EA%B5%90%EC%B0%A9-%EC%83%81%ED%83%9C</link>
            <guid>https://velog.io/@ameri-kano/%EB%A9%B4%EC%A0%91-%EB%8C%80%EB%B9%84-OS-%EA%B5%90%EC%B0%A9-%EC%83%81%ED%83%9C</guid>
            <pubDate>Sun, 29 Oct 2023 05:09:39 GMT</pubDate>
            <description><![CDATA[<h3 id="시작하며">시작하며</h3>
<p>이번 주제는 OS(운영체제)이다. 워낙 중요하고 내용이 많은 것 같아서 그 중 어떤 걸 정리해 볼까 고민이 많았는데, 그 중에 나에게 가장 익숙한 단어였으나 생각보다 알아야 할 게 많았던 교착 상태(deadlock)로 정했다.</p>
<hr>
<h3 id="경쟁-상태와-임계-영역">경쟁 상태와 임계 영역</h3>
<p>여러 프로세스 또는 스레드에서 하나의 공유 자원에 접근하는 경우가 있는데, 이 때 이 접근 순서에 따라 결과가 달라질 수 있다. 이런 현상을 동시에 접근해 경쟁하는 상태라고 하여 <strong>경쟁 상태</strong>라고 하고, 위에서 말한 접근 순서에 따라 결과가 달라지는 코드 영역을 <strong>임계 영역</strong>이라고 한다. 임계 영역에 여러 접근이 동시에 발생하는 것을 방지하려면 다음 3가지 조건을 충족해야 한다.</p>
<ul>
<li>상호배제 기법(mutual exclusive) : 어떤 프로세스가 임계 영역을 실행 중일 때 다른 프로세스가 임계 영역에 접근할 수 없다. 상호배제 기법으로는 뮤텍스와 세마포어가 있다.</li>
<li>진행 : 임계 영역을 실행중인 프로세스가 없을 때 다른 프로세스가 임계 영역을 실행한다.</li>
<li>한정된 대기 : 임계 영역에 접근을 요청할 때 무한한 시간을 기다리지 않는다.</li>
</ul>
<h3 id="뮤텍스mutex">뮤텍스(mutex)</h3>
<p>상호배제(<strong>mut</strong>ual <strong>ex</strong>clusive) 에서 단어를 가져온 기법으로, 락(lock)을 가진 프로세스만이 공유 자원에 접근할 수 있게 하는 방법이다. 임계 영역에 먼저 접근한 프로세스가 임계 영역에 락을 걸면 다른 프로세스들은 해당 프로세스가 락을 해제하기 전까지 기다려야 한다.
임계 영역에 접근하지 못한 프로세스는 락을 얻기 위해 기다리면서 락이 풀렸는지 반복문을 돌면서 확인한다. 이를 바쁜 대기의 한 종류인 스핀락(spinlock)이라고 한다. 프로세스가 반복문을 돌면서 계속 자원의 사용 가능 여부를 확인하므로 프로세스가 빠르게 교체될 수 있다.</p>
<blockquote>
<p>바쁜 대기(busy waiting)란, 프로세스가 공유 자원에 접근할 수 있는 권한을 얻을 때 까지 확인하는 과정을 말한다.</p>
</blockquote>
<h3 id="교착-상태deadlock">교착 상태(deadlock)</h3>
<p>상호배제 기법 때문에 <strong>2개 이상의 프로세스가 각각 자원을 가지고 있으면서 서로의 자원을 요구하며 기다리는 상태를 교착 상태</strong>(deadlock)라고 한다. 교착 상태가 발생하는 필요충분조건(프로세스들이 각각의 조건을 모두 가지거나 모두 아니어야 한다.) 4가지는 다음과 같다.</p>
<ul>
<li>상호배제 : 하나의 공유 자원에 하나의 프로세스만 접근할 수 있다.</li>
<li>점유와 대기 : 프로세스가 최소 하나의 자원을 점유하고 있는 상태에서 추가로 다른 프로세스에서 사용 중인 자원을 점유하기 위해 대기한다.</li>
<li>비선점 : 다른 프로세스에 할당된 자원을 뺏을 수 없다.</li>
<li>원형 대기 : 프로세스가 자신의 자원을 점유하면서 앞이나 뒤의 프로세스의 자원을 요구한다.</li>
</ul>
<h3 id="예상-질문">예상 질문</h3>
<blockquote>
<p>상호배제 기법에 뮤텍스와 세마포어가 있는데, 각각에 대해 설명해 보세요.</p>
</blockquote>
<p>뮤텍스는 락을 가진 프로세스만 공유 자원에 접근할 수 있습니다. 임계 영역에 접근할 수 있는 프로세스는 하나뿐이며, 다른 프로세스는 임계 영역에 접근한 프로세스가 락을 해제할 때까지 기다려야 합니다. 반면 세마포어는 공유 자원에 접근할 수 있는 프로세스의 수를 정해 접근을 제어하는 방법입니다. 임계 영역에 접근할 수 있는 키 n개(2개 이상, 1개라면 뮤텍스와 차이점이 없음)를 지정하고 이 키를 가진 프로세스만이 임계 영역에 접근하게 하는 방식입니다.</p>
<blockquote>
<p>교착 상태를 예방할 수 있는 방법을 설명해 보세요.</p>
</blockquote>
<p>교착 상태를 막으려면 교착 상태가 발생하는 4가지 조건 중 하나를 제거하면 됩니다. 즉 여러 프로세스가 동시에 하나의 공유 자원을 사용하게 하거나(상호배제 제거), 프로세스가 실행되기 전에 필요한 모든 자원을 할당하여 프로세스 대기를 없애고 프로세스가 자원을 점유하지 않은 상태에만 자원을 요구하게 하거나(점유/대기 제거), 자원을 점유한 프로세스가 다른 자원을 요구 할 때 현재 점유한 자원을 반환하게 하거나(비선점 제거), 자원을 선형으로 정렬하고 방향을 정해 한 쪽 방향으로만 자원을 요구하게 하면(원형 대기 제거) 교착 상태를 예방할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[스터디/알고리즘] DFS]]></title>
            <link>https://velog.io/@ameri-kano/DFS</link>
            <guid>https://velog.io/@ameri-kano/DFS</guid>
            <pubDate>Thu, 26 Oct 2023 11:31:38 GMT</pubDate>
            <description><![CDATA[<h3 id="시작하며">시작하며</h3>
<p>이번 주 스터디에서 준비해서 발표할 알고리즘은 DFS이다. 어떤 알고리즘인지 알고 있지만 다시 공부한다 생각하고 정리해 본다.</p>
<hr>
<h2 id="dfsdepth-first-search">DFS(Depth First Search)</h2>
<p><code>DFS(Depth First Search, 깊이 우선 탐색)</code> 는 그래프 탐색 방법 중 하나이다. 깊이 우선 탐색이라는 말 그대로 그래프에서 가장 깊은 부분을 우선적으로 탐색하는 알고리즘이다.</p>
<p>최대한 깊숙히 들어가면서 노드를 방문한 후, 다시 돌아가서 다른 경로를 탐색하는 것이 DFS의 동작 과정이며, 이를 위해 <code>스택</code> 자료구조를 이용한다. 자세한 과정은 다음과 같다.</p>
<ol>
<li>탐색을 시작하는 노드(시작점)을 스택에 삽입(push) 하고 방문 처리한다. (방문 처리를 하는 이유는 이미 탐색한 노드를 다시 스택에 삽입하지 않게 하기 위함이다.)</li>
<li>스택의 가장 위 노드를 꺼내면서(pop), 그 노드에 방문하지 않은 인접 노드가 있다면 그 인접 노드를 스택에 젛고 방문 처리한다. 그러한 인접 노드가 없다면 다시 스택에서 가장 위 노드를 꺼낸다.</li>
<li>이 과정을 모두 끝날 때 까지 반복한다.</li>
</ol>
<p>위처럼 스택을 이용해서 구현할 수도 있고, 재귀함수(재귀함수의 호출도 스택 영역에서 이루어지며, 같은 과정을 가진다.)를 이용해서 구현할 수도 있다.</p>
<h2 id="구현-예시">구현 예시</h2>
<p>예를 들어, 아래와 같은 모양의 그래프가 있다.
<img src="https://velog.velcdn.com/images/ameri-kano/post/46cf113f-5683-4a80-911f-af2f7c6b6f96/image.png" alt=""></p>
<p>위 그래프에서 DFS를 수행하는 코드와 결과는 다음과 같다. (그래프는 인접 리스트 형태로 재귀함수를 이용해 구현하였다.)</p>
<h3 id="코드">코드</h3>
<pre><code class="language-java">package algorithm;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class GraphSearch {

  static void initGraph(HashMap&lt;Integer, List&lt;Integer&gt;&gt; graph) {
    for (int i=1; i&lt;=8; i++) {
      graph.put(i, new ArrayList&lt;&gt;());
    }

    graph.get(1).add(2);
    graph.get(1).add(3);
    graph.get(1).add(4);

    graph.get(2).add(7);

    graph.get(4).add(5);
    graph.get(4).add(6);

    graph.get(5).add(6);

    graph.get(7).add(8);
  }

  static void DFS(int vertex, HashMap&lt;Integer, List&lt;Integer&gt;&gt; graph,
      boolean[] visited) {
    visited[vertex] = true;
    System.out.print(vertex + &quot; &quot;);

    for (int v: graph.get(vertex)) {
      if (!visited[v]) {
        DFS(v, graph, visited);
      }
    }
  }

  public static void main(String[] args) {
    HashMap&lt;Integer, List&lt;Integer&gt;&gt; graph = new HashMap&lt;&gt;();
    boolean[] visited = new boolean[9];

    initGraph(graph);
    DFS(1, graph, visited);
  }
}
</code></pre>
<h3 id="결과">결과</h3>
<pre><code class="language-java">1 2 7 8 3 4 5 6</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[면접 대비/네트워크] TCP와 UDP]]></title>
            <link>https://velog.io/@ameri-kano/%EB%A9%B4%EC%A0%91-%EB%8C%80%EB%B9%84-TCP%EC%99%80-UDP</link>
            <guid>https://velog.io/@ameri-kano/%EB%A9%B4%EC%A0%91-%EB%8C%80%EB%B9%84-TCP%EC%99%80-UDP</guid>
            <pubDate>Sun, 22 Oct 2023 04:46:22 GMT</pubDate>
            <description><![CDATA[<h2 id="시작하며">시작하며</h2>
<p>부트캠프를 수료하고 슬슬 지원하던 중, 감사하게도 생각보다 빨리 면접을 보게 됐다. 잠시 소홀하고 있던 CS 지식을 다시 공부하면서 간단하게 정리해 보고, 예상 질문도 한번 생각해 봤다. 
우선, 가장 취약하다고 생각하는 네트워크에서부터(대학에서 전공으로 듣지 못했었다) 정리해볼까 한다.</p>
<h2 id="tcp와-udp">TCP와 UDP</h2>
<blockquote>
<p>TCP와 UDP는 전송 계층(OSI 7계층 중 4계층)에서 사용하는 대표적인 프로토콜이다.</p>
</blockquote>
<h3 id="tcp">TCP</h3>
<p>연결형 서비스를 지원하고 데이터의 신뢰성을 보장한다. 전반적으로 다음과 같은 특징이 있다.</p>
<ul>
<li>송신부와 수신부의 연결을 확인하는 연결형 서비스다.</li>
<li>패킷 교환 방식은 패킷이 전달되는 회선이 정해져 있는 가상 회선 방식이다.</li>
<li>패킷의 전송 순서가 보장된다.</li>
<li>패킷의 수신 여부를 확인한다.</li>
<li>송신부와 수신부는 1:1 통신을 한다.</li>
<li>데이터 손실이 없음을 보장하므로 신뢰성이 높다.</li>
<li>데이터의 송수신 속도가 느리다.</li>
</ul>
<p>이외에, TCP는 연결형 서비스를 지원하기 위해 송신부와 수신부를 연결하는 과정을 거치는데 <strong>연결을 시작할 때</strong>(세션을 수립할 때)에는 <strong>3-way handshaking</strong>(핸드셰이킹, 요청과 응답을 총 3번 주고받음)을, <strong>종료할 때에는 4-way handshaking</strong>을 한다.</p>
<h4 id="tcp-제어-방법">TCP 제어 방법</h4>
<p>TCP의 데이터 신뢰성을 보장하기 위한 제어 방법으로는 흐름 제어, 혼잡 제어, 오류 제어가 있다.</p>
<ul>
<li>흐름 제어 : 데이터 송신부와 수신부에서 데이터 처리 속도의 차이 때문에 생기는 데이터 손실을 방지하는 방법으로, <strong>정지-대기</strong> 와 <strong>슬라이딩 윈도우</strong> 방식이 있다.</li>
<li>혼잡 제어 : 송신부의 데이터 전달 속도와 네트워크 속도 차이로 데이터 손실이 발생하는 것을 방지하기 위한 방법으로 <strong>AIMD</strong>, <strong>느린 시작</strong> 방식이 있다.<blockquote>
<p>AIMD 는 <strong>합 증가 곱 감소</strong> 방식으로, 윈도우의 크기를 증가시킬 때에는 더하며 증가시키지만 데이터 손실이 발생하면 1/2 배와 같이 배수 단위로 줄이는 방식을 말한다.</p>
</blockquote>
</li>
<li>오류 제어 : 통신 중 데이터에 오류 또는 유실이 발생할 때 데이터의 신뢰성을 보장하기 위해 오류를 제어하는 방식으로, <strong>정지-대기</strong>(수신 확인 메세지(ACK) 를 일정 시간 동안 받지 못해 타임아웃이 발생하면 해당 패킷을 다시 보내는 방식), <strong>GO-Back-N ARQ</strong>(송신부에서 연속적으로 데이터를 보냈는데 누락된 데이터가 있다면 송신부에서 해당 데이터부터 재전송하는 방식) 방식 등이 있다.</li>
</ul>
<h3 id="udp">UDP</h3>
<p>송신부와 수신부 간 연결을 지원하지 않고 데이터그램 형태의 통신을 지원한다. 따로 연결 과정 없이 패킷을 바로 송수신하게 되며, 신뢰성이 낮지만 속도가 빠르다는 장점이 있다. 전반적인 특징은 다음과 같다.</p>
<ul>
<li>송신부와 수신부의 연결이 보장되지 않는 비연결형 서비스다.</li>
<li>패킷이 서로 다른 회선으로 교환될 수 있는 데이터그램 패킷 교환 방식이다.</li>
<li>송신부에서 전달한 패킷 순서와 수신부에서 받은 패킷 순서가 다를 수 있다.</li>
<li>패킷의 수신 여부를 확인하지 않는다.</li>
<li>1:1, 1:N, N:N 통신 모두 가능하다.</li>
<li>데이터의 신뢰성이 낮다.</li>
<li>데이터의 전송 속도가 빠르다.</li>
</ul>
<h4 id="체크섬">체크섬</h4>
<p>UDP는 신뢰성이 낮지만, 최소한의 신뢰성을 보장하기 위해 checksum(체크섬) 방식으로 오류를 검출한다. 체크섬은 데이터의 무결성을 보장하는 간단한 방법으로, 체크섬을 만들기 위한 데이터를 모두 더한 뒤 오버플로되는 자릿수를 떼어 데이터에 다시 더한 후 1의 보수를 취해서 만든다. 이를 송신부에 넣어 수신부로 보내 수신부에서 송신부와 동일한 체크섬 값이 나오는지 확인하는 방식이다. 그러나 이 방법으로 100% 오류를 검출할 수 있는 것은 아니며, UDP의 체크섬은 선택 사항이므로 보내지 않을 수도 있다.</p>
<h2 id="예상-질문">예상 질문</h2>
<blockquote>
<p>TCP 방식과 UDP 방식을 각각 사용할 수 있는 서비스는 어떤 것이 있을까요?</p>
</blockquote>
<p>TCP 방식은 연결 과정이 필요하며, 순서가 보장되고 신뢰성이 높다. 그러므로 파일 전송(FTP) 등 보내는 내용의 신뢰성이 중요한 서비스에서 사용할 수 있다.
UDP 방식은 연결 과정이 필요 없고, TCP 방식에 비해 신뢰성을 확인하는 과정이 필요 없으므로 네트워크의 부하가 적고 속도가 빠르다. 그러므로 신뢰성보다는 데이터가 끊기지 않는 연속성을 더 중요하게 고려해야 하는 스트리밍(음악, 영상 등) 서비스에서 사용할 수 있다.</p>
<blockquote>
<p>TCP와 UDP에서 패킷을 교환하는 방식에 대해 각각 설명하세요.</p>
</blockquote>
<p>TCP 방식에서는 가상 회선 방식을 사용한다. 가상 회선 방식은 데이터를 주고받기 전에 패킷을 전송할 가상 회선 경로를 설정하여 모든 패킷을 하나의 경로로 전송한다. 이를 통해 패킷의 전송 순서를 보장할 수 있다.
UDP 방식에서는 데이터그램 방식을 사용한다. 데이터그램 방식은 패킷마다 최적의 경로로 전송되는 방식으로, 전송 속도가 더 빨라질 수 있지만 송신부의 패킷 순서와 수신부의 패킷 순서가 다를 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[programmers/JAVA] 피보나치 수]]></title>
            <link>https://velog.io/@ameri-kano/programmersJAVA-%ED%94%BC%EB%B3%B4%EB%82%98%EC%B9%98-%EC%88%98</link>
            <guid>https://velog.io/@ameri-kano/programmersJAVA-%ED%94%BC%EB%B3%B4%EB%82%98%EC%B9%98-%EC%88%98</guid>
            <pubDate>Fri, 13 Oct 2023 06:10:07 GMT</pubDate>
            <description><![CDATA[<hr>
<h3 id="문제-a-hrefhttpsschoolprogrammerscokrlearncourses30lessons12945-target_blank링크a">문제 <a href="https://school.programmers.co.kr/learn/courses/30/lessons/12945" target="_blank">링크</a></h3>
<p>피보나치 수는 F(0) = 0, F(1) = 1일 때, 1 이상의 <code>n</code>에 대하여 <code>F(n) = F(n-1) + F(n-2)</code> 가 적용되는 수 입니다.</p>
<p>예를들어</p>
<ul>
<li>F(2) = F(0) + F(1) = 0 + 1 = 1</li>
<li>F(3) = F(1) + F(2) = 1 + 1 = 2</li>
<li>F(4) = F(2) + F(3) = 1 + 2 = 3</li>
<li>F(5) = F(3) + F(4) = 2 + 3 = 5
와 같이 이어집니다.</li>
</ul>
<p>2 이상의 <code>n</code>이 입력되었을 때, <code>n</code>번째 피보나치 수를 1234567으로 나눈 나머지를 리턴하는 함수, solution을 완성해 주세요.</p>
<h4 id="제한-사항">제한 사항</h4>
<p><code>n</code> 은 2 이상 100,000 이하인 자연수입니다.</p>
<hr>
<h3 id="접근-방법">접근 방법</h3>
<p>문제 자체는 단순하게 <code>n</code>번째 피보나치 수를 반환하는 문제인데, 나머지를 반환해야한다는 점이 다르다. 단순 피보나치 수는 dp를 이용하여 점화식을 세워 구하면 되는데, 매번 나머지를 계산해줘야 하므로 이전에도 이를 이용해 해결해본 적이 있는 모듈러 연산의 덧셈법칙을 활용해야 한다. 
모듈러 연산의 덧셈법칙을 다시 정리해보면 다음과 같다.</p>
<pre><code class="language-java">(A + B) mod C = (A mod C + B mod C) mod C</code></pre>
<h3 id="소스-코드">소스 코드</h3>
<pre><code class="language-java">class Solution {    
    public int solution(int n) {
        int[] fibonacci = new int[n+1];
        fibonacci[0] = 0; fibonacci[1] = 1;

        for(int i=2; i&lt;=n; i++) {
            fibonacci[i] = fibonacci[i-2] % 1234567 + fibonacci[i-1] % 1234567;
            fibonacci[i] %= 1234567;
        }

        return fibonacci[n];
    }
}</code></pre>
<h3 id="제출-결과">제출 결과</h3>
<p><img src="https://velog.velcdn.com/images/ameri-kano/post/cb35ae6f-59cf-45e7-96c6-2d4291367e0e/image.png" alt=""></p>
<hr>
<h3 id="마무리하며">마무리하며</h3>
<p>문제 자체는 단순하지만 생각보다 적용해야 될 부분이 있어서 생각해보기에 좋은 문제였다. 
스쿨을 수료하고 여유가 생겨 다시 블로그 기록을 스터디 겸 시작한다. 다시 꾸준히 잘 정리하고 기억해야지.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[스프링 부트 핵심 가이드] 정리 8주차]]></title>
            <link>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-8%EC%A3%BC%EC%B0%A8</link>
            <guid>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-8%EC%A3%BC%EC%B0%A8</guid>
            <pubDate>Sun, 09 Jul 2023 13:22:10 GMT</pubDate>
            <description><![CDATA[<h4 id="a-hrefhttpssearchshoppingnavercombookcatalog33005838635cat_id50010881pbokproec8aa4ed9484eba781ebb680ed8ab8ed95b5ec8baceab080ec9db4eb939cct3dlhspxgfk7cci3d13eccc862d5fa22bceca9182890803bd5ab9d6d27ctr3dboknx7csn3d956947chk3df4c134224127a865acb42b606b5f05d69ddaad0f-targetblank책-링크a"><a href="https://search.shopping.naver.com/book/catalog/33005838635?cat_id=50010881&frm=PBOKPRO&query=%EC%8A%A4%ED%94%84%EB%A7%81+%EB%B6%80%ED%8A%B8+%ED%95%B5%EC%8B%AC+%EA%B0%80%EC%9D%B4%EB%93%9C&NaPm=ct%3Dlhspxgfk%7Cci%3D13eccc862d5fa22bceca9182890803bd5ab9d6d2%7Ctr%3Dboknx%7Csn%3D95694%7Chk%3Df4c134224127a865acb42b606b5f05d69ddaad0f" target=blank>책 링크</a></h4>
<p>매주 <strong>스프링 부트 핵심 가이드</strong> 를 읽으며 이전에 궁금했거나, 새롭게 알게 된 내용들을 정리했다.
(이번 주는 13장을 읽었다.)</p>
<hr>
<h3 id="스프링-시큐리티">스프링 시큐리티</h3>
<p><img src="https://velog.velcdn.com/images/ameri-kano/post/1803f1fe-91df-4a4a-94c0-8acb90cb689e/image.png" alt=""></p>
<blockquote>
<p>위 그림은 스프링 시큐리티의 보안 필터체인 중 기본값인 <code>UsernamePasswordAuthenticationFilter</code> 를 통한 인증 과정이다. 위 필터는 접근 권한을 확인하고 인증이 실패하면 로그인 폼을 보내는 역할을 수행한다. 화면이 없는 어플리케이션의 경우 다른 필터에서 인증 및 인가 처리를 수행해야 하는데, 그러한 인증 방법으로 JWT 토큰을 활용한 방법이 있다.</p>
</blockquote>
<h4 id="jwt-토큰을-이용한-필터-구현-순서">JWT 토큰을 이용한 필터 구현 순서</h4>
<p>토큰을 생성하고 정보를 해석해 인증을 수행하는 클래스 -&gt; 이 클래스를 활용한 필터</p>
<h4 id="securityconfiguration-구현">SecurityConfiguration 구현</h4>
<p>위에서 구현한 필터는 스프링 시큐리티를 적용하기 위한 컴포넌트이다. 다음은 <code>WebSecurityConfigureAdapter</code> 를 상속받는 <code>Configuration</code> 클래스를 구현하는 것이다. <code>configure()</code> 메소드에 작성될 수 있는 설정 코드는 다음과 같다. 모든 설정은 전달받은 <code>HttpSecurity</code> 에 설정하게 된다.</p>
<ul>
<li><p><code>httpBasic.disable()</code>
UI를 사용하는 기본값을 가진 시큐리티 설정을 비활성화한다.</p>
</li>
<li><p><code>csrf.disable()</code>
CSRF(사이트 간 요청 위조, 웹 어플리케이션의 취약점 중 하나로 특정 페이지의 보안을 취약하게 하는 방법이다.) 보안을 비활성화한다. 브라우저 사용 환경이 아니라면 비활성화해도 문제가 되지 않는다. </p>
</li>
<li><p><code>sessionManagement().sessionCreationPolicy(SessionCreationPolicy)</code>
REST API 기반 어플리케이션의 동작 방식을 설정한다. <code>SessionCreationPolicy</code> 에는 세션을 사용함에 따라 결정한다.</p>
</li>
<li><p><code>authorizeRequest()</code>
어플리케이션에 들어오는 요청에 대한 권한을 체크한다. <code>antMatcher()</code> 는 <code>antPattern</code> 을 통해 권한을 설정한다. <code>permitAll()</code>, <code>antMatchers(HttpMethod.GET, &quot;/api/**).permitAll()&quot;</code>, <code>.anyRequest().hasRole(&quot;ADMIN&quot;)</code> 등 요청별, 링크별 다양한 권한 설정이 가능하다. </p>
</li>
<li><p><code>exceptionHandling().accessDeniedHandler()</code>
권한을 확인하는 과정에서 통과하지 못하는 예외가 발생하면 예외를 전달한다.</p>
</li>
<li><p><code>exceptionHandling().authenticationEntryPoint()</code>
인증 과정에서 예외가 발생하면 예외를 전달한다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[스프링 부트 핵심 가이드] 정리 7주차]]></title>
            <link>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-7%EC%A3%BC%EC%B0%A8</link>
            <guid>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-7%EC%A3%BC%EC%B0%A8</guid>
            <pubDate>Fri, 30 Jun 2023 01:34:17 GMT</pubDate>
            <description><![CDATA[<h4 id="a-hrefhttpssearchshoppingnavercombookcatalog33005838635cat_id50010881pbokproec8aa4ed9484eba781ebb680ed8ab8ed95b5ec8baceab080ec9db4eb939cct3dlhspxgfk7cci3d13eccc862d5fa22bceca9182890803bd5ab9d6d27ctr3dboknx7csn3d956947chk3df4c134224127a865acb42b606b5f05d69ddaad0f-targetblank책-링크a"><a href="https://search.shopping.naver.com/book/catalog/33005838635?cat_id=50010881&frm=PBOKPRO&query=%EC%8A%A4%ED%94%84%EB%A7%81+%EB%B6%80%ED%8A%B8+%ED%95%B5%EC%8B%AC+%EA%B0%80%EC%9D%B4%EB%93%9C&NaPm=ct%3Dlhspxgfk%7Cci%3D13eccc862d5fa22bceca9182890803bd5ab9d6d2%7Ctr%3Dboknx%7Csn%3D95694%7Chk%3Df4c134224127a865acb42b606b5f05d69ddaad0f" target=blank>책 링크</a></h4>
<p>매주 <strong>스프링 부트 핵심 가이드</strong> 를 읽으며 이전에 궁금했거나, 새롭게 알게 된 내용들을 정리할 예정이다.
(이번 주는 11~12장을 읽었다.)</p>
<hr>
<h3 id="액추에이터actuator">액추에이터(Actuator)</h3>
<p>어플리케이션을 개발하고 운영하는 단계에 접어들면 정상적으로 동작하는지 모니터링하는 환경이 매우 중요해진다. 스프링 부트에서는 엔드포인트나 JMX(Java Management eXtensions, 실행중인 어플리케이션의 상태를 모니터링하고 설정을 변경할 수 있게 해준다. JMX를 통해 관리를 하려면 Managed Beans를 생성해야 한다.)를 통해 어플리케이션을 모니터링하고 관리할 수 있는 기능을 제공한다.</p>
<p>액추에이터 의존성을 추가하고, <code>application.properties</code> 파일에 다양한 속성을 추가하여 설정이 가능하다. 엔드포인트(모니터링을 사용하는 경로)는 활성화와 노출 여부를 설정 가능하다. 예시는 다음과 같다.</p>
<pre><code class="language-properties">## shutdown 활성화, caches 비활성화
management.endpoint.shutdown.enabled=true
management.endpoint.caches.enabled=false</code></pre>
<pre><code>## Endpoint 노출 설정
## 모든 기능을 노출하나 threaddump와 heapdump 제외
## HTTP 설정
management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=threaddump, heapdump

## JMX 설정
management.endpoints.jmx.exposure.include=*
management.endpoints.jmx.exposure.exclude=threaddump, heapdump</code></pre><p>이러한 엔드포인트들은 어플리케이션에 관한 민감한 정보를 포함하고 있으므로 노출 설정을 신중하게 고려할 필요가 있다.</p>
<h3 id="액추에이터-기능-요약">액추에이터 기능 요약</h3>
<h4 id="기본-정보info">기본 정보(/info)</h4>
<p>가동 중인 어플리케이션의 정보를 볼 수 있다. 제공하는 정보는 어플리케이션에서 몇 가지 방법을 거칠 수 있으나 <code>application.properties</code> 파일에 <code>info.</code> 로 시작하는 속성 값들을 정의하는 것이 가장 쉬운 방법이다. 값을 정의한 뒤 <code>서버주소/actuator/info</code> URL에 접근하면 정의한 속성 값을 바탕으로 생성된 정보가 <code>JSON</code> 형태로 제공된다.</p>
<h4 id="상태health">상태(/health)</h4>
<p>어플리케이션의 상태를 확인할 수 있으며, 주로 네트워크 계층에서 L4 레벨(Loadbalancing, 전송 계층에서의 부하 분산) 에서 상태를 확인하기 위해 사용된다.</p>
<h4 id="빈-정보beans">빈 정보(/beans)</h4>
<p>스프링 컨테이너에 등록된 빈의 전체 목록을 JSON 형식으로 보여준다. 그러나 워낙 많은 빈이 자동으로 등록되기 때문에 한 눈에 내용을 파악하기는 어렵다.</p>
<h4 id="스프링-부트의-자동설정-내역conditions">스프링 부트의 자동설정 내역(/conditions)</h4>
<p>자동설정(AutoConfiguration) 내역을 확인한다. 크게 <code>positiveMatches</code> 와 <code>negativeMatches</code> 로 구분되며 자동설정의 <code>@Conditional</code> 에 따라 평가된 내용을 표시한다.</p>
<h4 id="스프링-환경변수-정보env">스프링 환경변수 정보(/env)</h4>
<p>스프링의 환경 변수 정보를 확인한다. 기본적으로 <code>application.properties</code> 파일의 변수들이 표시되며 OS, JVM 의 환경변수도 함께 표시된다.</p>
<h4 id="로깅-레벨-확인loggers">로깅 레벨 확인(/loggers)</h4>
<p>어플리케이션의 로깅 레벨 수준의 설정을 확인한다. <code>GET</code> 메소드로 호출하면 확인이 가능하며 <code>POST</code> 메소드로 호출하면 로깅 레벨을 변경할 수도 있다.</p>
<h4 id="커스텀-액추에이터">커스텀 액추에이터</h4>
<p>기존 기능에 내용을 추가하거나, 새로운 엔드포인트를 개발하는 방식으로 구현하며,<code>@Endpoint</code> 가 명시된 클래스를 이용하여 구현할 수 있다.</p>
<h3 id="서버-간-통신resttemplate">서버 간 통신(RestTemplate)</h3>
<blockquote>
<p>MSA(MicroService Architecture) 는 한 서버에 하나의 주요 기능을 담으므로, 다른 서버의 기능을 사용하고 싶은 경우가 발생한다. 이럴 때 다른 서버에서 결과를 받아야하는 경우도 있는데, 이때 사용하는 것이 RestTemplate이다.</p>
</blockquote>
<h4 id="get-형식의-resttemplate">GET 형식의 RestTemplate</h4>
<p>다양한 방법이 있으나 가장 보편적인 방법은 <code>UriComponentsBuilder</code> 를 사용하는 방법이다.</p>
<pre><code class="language-java">// 경로 변수 방식
URI uri = UriComponentsBuilder
        .fromUriString(&quot;http://localhost:8080&quot;)
        .path(&quot;/api/{name}&quot;)
        .encode()
        .build()
        .expand(&quot;MyName&quot;)
        .toUri();

// 쿼리 파라미터 방식
URI uri2 = UriComponentsBuilder
        .fromUriString(&quot;http://localhost:8080&quot;)
        .path(&quot;/api/param&quot;)
        .queryParam(&quot;name&quot;, &quot;myName&quot;)
        .encode()
        .build()
        .toUri();

RestTemplate restTemplate = new RestTemplate();
ResponseEntity&lt;String&gt; response = restTemplate.getForEntity(uri, String.class);

return responseEntity.getBody();
</code></pre>
<h4 id="post-형식의-resttemplate">POST 형식의 RestTemplate</h4>
<p>GET 방식과 유사하지만 Request 헤더와 바디가 필요한 경우 다음과 같이 작성한다.</p>
<pre><code class="language-java">RequestEntity&lt;PersonDto&gt; request = RequestEntity
    .post(uri)
    .header(&quot;HEADER&quot;, &quot;my header&quot;)
    .body(personDto);

RestTemplate restTemplate = new RestTemplate();
ResponseEntity&lt;PersonDto&gt; response = restTemplate.exchange(requestEntity, PersonDto.class);
</code></pre>
<h3 id="webclient">WebClient</h3>
<blockquote>
<p>실제 운영환경의 어플리케이션은 정식 스프링 부트의 버전보다 낮은 경우가 많아 RestTemplate을 많이 사용하지만, 최신 버전에서는 RestTemplate이 지원 중단되어 WebClient를 사용할 것을 권고한다. 이러한 흐름에 맞춰 둘 다 알고 있는 것이 좋겠다.</p>
</blockquote>
<p>WebClient를 생성하는 방법에는 크게 두가지가 있다.</p>
<ul>
<li><code>create()</code> 메소드를 통한 생성</li>
<li><code>builder()</code> 를 이용한 생성</li>
</ul>
<p>WebClient는 우선 객체를 생성한 후 요청을 전달하는 방식으로 동작한다. <code>builder()</code> 를 통해 <code>baseUrl()</code> 메소드에서 기본 URL을 설정하고 <code>defaultHeader()</code> 메소드로 헤더의 값을 설정한다. 일반적으로 <code>WebClient</code> 객체를 이용할 때 객체를 생성하고 재사용하는 방법으로 구현하는 것이 좋다. 한번 빌드된 <code>WebClient</code> 는 변경할 수 없으나 <code>Webclient.mutate()</code> 메소드를 사용하면 복제 가능하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[스프링 부트 핵심 가이드] 정리 6주차(2)]]></title>
            <link>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-6%EC%A3%BC%EC%B0%A82</link>
            <guid>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-6%EC%A3%BC%EC%B0%A82</guid>
            <pubDate>Mon, 19 Jun 2023 06:45:54 GMT</pubDate>
            <description><![CDATA[<p>이번주 정리 내용이 좀 길어져서 분리했다.
<a href="https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-6%EC%A3%BC%EC%B0%A81" target=blank> 이전 글 링크 </a></p>
<hr>
<h3 id="스프링-부트에서의-예외-처리">스프링 부트에서의 예외 처리</h3>
<blockquote>
<p>웹 서비스 어플리케이션에서는 외부에서 들어오는 요청에 담긴 데이터를 처리하는 경우가 많다. 그 과정에서 예외가 발생하면 예외를 복구하여 정상으로 처리하기보다는 요청을 보낸 클라이언트에 어떤 문제가 발생했는지를 전달하는 경우가 더 많다.</p>
</blockquote>
<p>예외가 발생했을 때 클라이언트에 오류를 전달하려면 결국 컨트롤러로 전달해야 한다. 스프링 부트에서는 크게 두 가지의 방식으로 처리한다.</p>
<ul>
<li><code>@RestControllerAdvice</code> 와 <code>@ExceptionHandler</code> 을 이용해 모든 컨트롤러의 예외 처리</li>
<li><code>@ExceptionHandler</code> 을 이용해 특정 컨트롤러의 예외 처리</li>
</ul>
<pre><code class="language-java">@RestControllerAdvice
public class CustomExceptionHandler {
    ...
    @ExceptionHandler(value = RuntimeException.class)
    public ResponseEntity&lt;?&gt; handleException(RuntimeException e, HttpServletRequest request) {
        ...
    }
    ...
}</code></pre>
<p>위처럼 클래스에 <code>@RestControllerAdvice</code> 를 지정해주면 <code>@Controller</code> 나 <code>@RestController</code> 에서 발생하는 예외를 한 곳에서 관리하고 처리 가능하며, 패키지를 지정해서 예외를 관제하는 범위를 지정할 수도 있다. 그리고 <code>@ExceptionHandler</code> 에 처리하고 싶은 예외를 <code>value</code> 로 지정해주면 지정한 예외를 처리하는 메서드가 정의된다.
이렇게 구현하면 지정한 예외가 발생했을 때 응답으로 예외 처리 메소드를 실행하여 얻은 결과를 전달한다. 특정 컨트롤러에서만 예외를 처리하고 싶다면 <code>@ExceptionHandler</code> 가 달려 있는 메소드를 그 컨트롤러에 정의하면 된다.</p>
<h4 id="예외-처리의-우선순위">예외 처리의 우선순위</h4>
<p>동일하게 핸들러 메소드가 선언된 상태라면 조금 더 구체적인 예외 클래스가 선언된 쪽이 더 높은 우선순위를 갖게 된다. 다른 경우로는 글로벌 예외 처리와 컨트롤러 내의 예외 처리가 있을텐데, 이 경우에는 범위가 좁은 컨트롤러의 핸들러 메소드가 우선순위를 가진다.</p>
<h4 id="커스텀-예외-처리">커스텀 예외 처리</h4>
<p>예외를 상속받고 별도의 메세지를 지정해주는 방식으로 커스텀 예외를 정의하여 사용할 수 있다. 예를 들으면 다음과 같다.</p>
<pre><code class="language-java">public class CustomException extends RuntimeException {

    private HttpStatus httpStatus;
    private ErrorCode errorCode;
    private String description;

    public CustomException(ErrorCode errorCode) {
        this.errorCode = errorCode;
        this.httpStatus = errorCode.httpStatus;
        this.description = errorCode.description;
    }
}

public enum ErrorCode {

    NOT_ENOUGH_MONEY(HttpStatus.BAD_REQUEST, &quot;잔액이 부족합니다.&quot;);
    // 이외에 다양한 에러들을 정의하여 사용

    private HttpStatus httpStatus;
    private String description;
}</code></pre>
<p>다른 기본 구현된 예외를 던지는 것과 같은 방법으로 예외 처리하고 싶은 부분에 <code>throw new CustomException()</code> 을 작성해주면 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[스프링 부트 핵심 가이드] 정리 6주차(1)]]></title>
            <link>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-6%EC%A3%BC%EC%B0%A81</link>
            <guid>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-6%EC%A3%BC%EC%B0%A81</guid>
            <pubDate>Mon, 19 Jun 2023 06:16:19 GMT</pubDate>
            <description><![CDATA[<h4 id="a-hrefhttpssearchshoppingnavercombookcatalog33005838635cat_id50010881pbokproec8aa4ed9484eba781ebb680ed8ab8ed95b5ec8baceab080ec9db4eb939cct3dlhspxgfk7cci3d13eccc862d5fa22bceca9182890803bd5ab9d6d27ctr3dboknx7csn3d956947chk3df4c134224127a865acb42b606b5f05d69ddaad0f-targetblank책-링크a"><a href="https://search.shopping.naver.com/book/catalog/33005838635?cat_id=50010881&frm=PBOKPRO&query=%EC%8A%A4%ED%94%84%EB%A7%81+%EB%B6%80%ED%8A%B8+%ED%95%B5%EC%8B%AC+%EA%B0%80%EC%9D%B4%EB%93%9C&NaPm=ct%3Dlhspxgfk%7Cci%3D13eccc862d5fa22bceca9182890803bd5ab9d6d2%7Ctr%3Dboknx%7Csn%3D95694%7Chk%3Df4c134224127a865acb42b606b5f05d69ddaad0f" target=blank>책 링크</a></h4>
<p>매주 <strong>스프링 부트 핵심 가이드</strong> 를 읽으며 이전에 궁금했거나, 새롭게 알게 된 내용들을 정리할 예정이다.
(이번 주는 10장을 읽었다.)</p>
<hr>
<h3 id="스프링-부트의-유효성-검사">스프링 부트의 유효성 검사</h3>
<blockquote>
<p>어플리케이션의 비즈니스 로직이 올바르게 동작하려면 데이터를 사전 검증하는 작업이 필요한데, 이를 유효성 검사 또는 데이터 검증이라 부른다. 의도한 형식으로 값이 들어오는지 체크하는 과정이 예시라고 할 수 있다.</p>
</blockquote>
<pre><code class="language-java">public class ValidRequestDto {

    @NotBlank
    String name;

    @Email
    String email;

    @Pattern(regexp = &quot;정규식&quot;)
    String phoneNumber;

    @Min(value = 20) 
    @Max(value = 40)
    int age;

    @Size(min = 0, max = 40)
    String description;

    @Positive
    int count;

    @AssertTrue
    boolean booleanCheck;
}</code></pre>
<p>위와 같은 DTO 클래스가 있다. 각 필드에 어노태이션을 선언함으로써 유효성 검사를 위한 조건을 설정한다. 대표적인 어노태이션은 다음과 같다.</p>
<h4 id="문자열-검증">문자열 검증</h4>
<ul>
<li><code>@Null</code> : <code>null</code> 만 허용한다.</li>
<li><code>@NotNull</code> : <code>null</code> 을 허용하지 않는다. <code>&quot;&quot;</code>, <code>&quot; &quot;</code>는 허용한다.</li>
<li><code>@NotEmpty</code> : <code>&quot;&quot;</code>을 허용하지 않고 <code>&quot; &quot;</code>는 허용한다.</li>
<li><code>@NotBlank</code> : <code>&quot;&quot;</code>, <code>&quot; &quot;</code> 둘 다 허용하지 않는다.</li>
</ul>
<h4 id="최대최솟값-검증">최대/최솟값 검증</h4>
<ul>
<li><code>@Min/Max(value = $number),</code>: <code>$number</code> 이상/이하의 값을 허용한다.</li>
</ul>
<h4 id="값의-범위-검증">값의 범위 검증</h4>
<ul>
<li><code>@Positive/Negative</code> : 양수/음수 를 허용한다.</li>
<li><code>@PositiveOrZero/NegativeOrZero</code> : 0을 포함한 양수/음수 를 허용한다.</li>
</ul>
<h4 id="시간에-대한-검증">시간에 대한 검증</h4>
<ul>
<li><code>@Future/Past</code> : 현재보다 미래/과거 의 날짜를 허용한다.</li>
<li><code>@FutureOrPresent/PastOrPresent</code> : 현재를 포함한 미래/과거 의 날짜를 허용한다.</li>
</ul>
<h4 id="이메일-검증">이메일 검증</h4>
<ul>
<li><code>@Email</code> : 이메일 형식이 올바른지 검사하며 <code>&quot;&quot;</code> 을 허용한다.</li>
</ul>
<h4 id="boolean-검증">Boolean 검증</h4>
<ul>
<li><code>@AssertTrue/AssertFalse</code> : <code>true</code>/<code>false</code> 인지 체크하며 <code>null</code> 값은 체크하지 않는다.</li>
</ul>
<h4 id="문자열-길이-검증">문자열 길이 검증</h4>
<ul>
<li><code>@Size(min = $number1, max = $number2)</code> : <code>$number1</code> 이상 <code>$number2</code> 이하의 범위를 허용한다.</li>
</ul>
<h4 id="정규식-검증">정규식 검증</h4>
<ul>
<li><code>@Pattern(regexp = &quot;정규식&quot;)</code> : 정규식을 검사한다. <code>java.util.regex.Pattern</code> 패키지의 컨벤션을 따른다.</li>
</ul>
<p>위처럼 DTO 객체를 선언해준 후 컨트롤러의 <code>@RequestBody</code> 앞에 <code>@Valid</code> 를 달아줘야 설정한 유효성 검사를 수행한다.</p>
<pre><code class="language-java">@PostMapping(&quot;/valid&quot;)
public ResponseEntity&lt;String&gt; checkValidation(
    @Valid @RequestBody ValidRequestDto validRequestDto) {
    ...
}</code></pre>
<p>규칙에 맞게 요청하면 http 응답으로 <code>200 OK</code> 메세지가 뜨고, 아닌 경우 <code>400 bad request</code> 가 뜨며 로그에서 문제가 있는 부분을 확인할 수 있다.</p>
<h4 id="validated-활용">@Validated 활용</h4>
<p>방금까지 유효성 검사를 위해 <code>@Valid</code>  를 사용했다. 스프링에서는 <code>@Validated</code> 을 지원하며, <code>@Valid</code>  의 기능을 포함하고 있기 때문에 변경 가능하다. 유효성 검사를 그룹으로 묶어 대상을 특정 가능하다. 그룹은 코드가 없는 인터페이스의 형태로 생성한다.  </p>
<pre><code class="language-java">public interface ValidationGroup { 
}</code></pre>
<p>그룹을 설정하는 법은 DTO 객체의 어노태이션에 그룹을 명시해주면 된다.</p>
<pre><code class="language-java">// ValidRequestDto
...
@Min(value = 20, groups = ValidationGroup.class) 
@Max(value = 40, groups = ValidationGroup.class)
int age;
...</code></pre>
<p>컨트롤러에서 활용하는 법은 <code>@Valid</code> 를 사용한 것과 똑같이 같은 자리에 그룹 클래스를 포함해 설정해주면 된다.</p>
<pre><code class="language-java">@PostMapping(&quot;/validated/group&quot;)
public ResponseEntity&lt;String&gt; checkValidation2(
    @Validated(ValidationGroup.class) @RequestBody ValidRequestDto validRequestDto) {
    ...
}</code></pre>
<p>이렇게 그룹을 명시하여 실행하면 <strong>그룹에 포함된 필드만</strong> 유효성 검사를 실시한다. 반대로 그룹을 지정하지 않으면 <code>groups</code> <strong>를 설정하지 않은 필드에 대해서</strong> 유효성 검사를 실시한다.</p>
<h4 id="커스텀-validation">커스텀 Validation</h4>
<p>인터페이스 <code>ConstraintValidator</code> 를 구현하는 클래스를 생성하는 방식으로 구현한다. 그리고 이 클래스를 커스텀 어노태이션에 <code>@Constraint(validatedBy = Validator.Class)</code> 어노태이션을 지정해주면 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[스프링 부트 핵심 가이드] 정리 5주차]]></title>
            <link>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-5%EC%A3%BC%EC%B0%A8</link>
            <guid>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-5%EC%A3%BC%EC%B0%A8</guid>
            <pubDate>Fri, 16 Jun 2023 07:49:35 GMT</pubDate>
            <description><![CDATA[<h3 id="a-hrefhttpssearchshoppingnavercombookcatalog33005838635cat_id50010881pbokproec8aa4ed9484eba781ebb680ed8ab8ed95b5ec8baceab080ec9db4eb939cct3dlhspxgfk7cci3d13eccc862d5fa22bceca9182890803bd5ab9d6d27ctr3dboknx7csn3d956947chk3df4c134224127a865acb42b606b5f05d69ddaad0f-targetblank책-링크a"><a href="https://search.shopping.naver.com/book/catalog/33005838635?cat_id=50010881&frm=PBOKPRO&query=%EC%8A%A4%ED%94%84%EB%A7%81+%EB%B6%80%ED%8A%B8+%ED%95%B5%EC%8B%AC+%EA%B0%80%EC%9D%B4%EB%93%9C&NaPm=ct%3Dlhspxgfk%7Cci%3D13eccc862d5fa22bceca9182890803bd5ab9d6d2%7Ctr%3Dboknx%7Csn%3D95694%7Chk%3Df4c134224127a865acb42b606b5f05d69ddaad0f" target=blank>책 링크</a></h3>
<p>매주 <strong>스프링 부트 핵심 가이드</strong> 를 읽으며 이전에 궁금했거나, 새롭게 알게 된 내용들을 정리할 예정이다.
(이번 주는 9장을 읽었다.)</p>
<hr>
<h3 id="연관관계-매핑">연관관계 매핑</h3>
<p>두 엔티티 간의 연관관계는 다음과 같다.</p>
<ul>
<li>One to One: 일대일</li>
<li>One to Many: 일대다</li>
<li>Many to One:  다대일</li>
<li>Many to Many: 다대다</li>
</ul>
<p>어떤 엔티티를 중심으로 연관된 엔티티를 보느냐에 따라 연관관계가 달라진다. (예를 들어, 상품과 그 상품을 생산하는 업체가 있다 했을 때, 업체 입장에서는 한 업체가 여러 개의 상품을 가지므로 일대다, 반대로 상품은 여러 종류의 상품이 한 업체에서 만들어지므로 다대일이라고 할 수 있다.)
일반적으로 데이터베이스에서는 연관관계를 설정하면 외래 키를 통해 테이블을 조인하는 방식으로 생성되나 JPA에서는 엔티티 사이의 참조 방향을 설정할 수 있다. 이는 양방향으로 설정해도 무관하나 단방향으로만 설정해도 해결되는 경우가 많다. 일반적으로 외래키를 가지는 테이블이 관계의 주인이 되며, 주인은 외래키를 사용할 수 있으나 상대는 읽기만 수행할 수 있다.</p>
<h3 id="일대일-매핑">일대일 매핑</h3>
<p>연관관계를 가지는 다른 엔티티 객체에 어노태이션을 달아준다.</p>
<pre><code class="language-java">// 자동으로 이름을 매핑하지만 의도한 컬럼이 들어가지 않을 수도 있으므로
// @JoinColumn 을 사용하여 이름을 지정해준다.
// @OneToOne optional : false인 경우 null을 허용하지 않는다.
@OneToOne(optional = false)
@JoinColumn(name = &quot;column_name&quot;)
private Product product;</code></pre>
<blockquote>
<p>다른 연관관계의 경우에도 그렇지만, 실행하여 생성되는 SQL을 확인해보면 자동으로 테이블 조인이 수행되는 것을 확인할 수 있다.
(위의 <code>optional</code>이 기본값 <code>true</code>인 경우 조인은 outer join 이 실행되고, <code>false</code>인 경우 inner join이 실행된다. 객체의 설정에 따라 JPA는 최적의 쿼리를 생성한다는 것을 알 수 있다.)</p>
</blockquote>
<p>양방향 매핑은 각각 객체에 <code>@OneToOne</code> 을 달아주면 되는데, 이 경우 주인을 명시하지 않으면 조인이 두 번 실행돼 속도 면에서 손해가 발생할 수 있다. 그러므로 <code>mappedBy</code> 설정 값을 추가하여 주인을 표시한다.</p>
<pre><code class="language-java">@OneToOne(mappedBy = &quot;product&quot;)
@Tostring.Exclude
private ProductDetail productDetail;</code></pre>
<p>위와 같이 작성하면, <code>ProductDetail</code> 엔티티가 <code>Product</code> 엔티티의 주인이 된다. 이렇게 양방향으로 관계를 설정하면  <code>toString</code> 을 실행할 때 순환참조가 발생하여 에러가 발생한다. 그러므로 필요한 경우가 아니라면 단방향으로 연관관계를 설정하거나 양방향이 필요하다면 위처럼 제외 설정하는 것이 좋다.</p>
<h3 id="일대다-다대일-매핑">일대다, 다대일 매핑</h3>
<p>일대일 매핑과 유사하게, <code>@ManyToOne</code> 또는 <code>@OneToMany</code> 를 객체에 달아주면 된다. 다만 주의할 점은 일대다의 경우 여러 상대 엔티티가 포함될 수 있으므로 컬렉션의의 형식으로(대표적인 컬렉션으로 <code>List, Map</code> 이 있다.) 선언한다.</p>
<pre><code class="language-java">@OneToMany(mappedBy = &quot;producer&quot;, fetch = FetchType.EAGER)
@Tostring.Exclude
private List&lt;Product&gt; productList = new ArrayList&lt;&gt;();</code></pre>
<p>위에서 처럼 fetch 타입을 설정해주는 이유는 일대다의 기본 fetch 전략이 지연 로딩(Lazy) 이기 때문이다.</p>
<blockquote>
<p>지연로딩(Lazy loading)과 즉시로딩(Eager loading) 은 중요한 개념이다. 엔티티 객체의 개념으로 데이터베이스를 구현했으므로 연관관계가 있는 객체가 필드에 존재하게 되는데, 이 연관관계와 상관없이 즉시 해당 엔티티의 값만 조회하고 싶거나, 연관관계를 가진 테이블의 값도 조회하고 싶은 경우 등의 조건을 만족하기 위해 등장한 개념이 지연로딩과 즉시로딩이다.</p>
</blockquote>
<h3 id="다대다-매핑">다대다 매핑</h3>
<p>다대다 연관관계는 실무에서 거의 사용되지 않는 관계 구성이다. 각 엔티티에서 서로를 리스트로 가지는 구조가 만들어지는데, 이 경우에는 중간 엔티티 테이블을 생성해 다대다를 일대다 또는 다대일로 해소하여 처리한다.</p>
<h3 id="영속성-전이cascade">영속성 전이(cascade)</h3>
<p>특정 엔티티의 영속성 상태를 변경할 때 그 엔티티와 연관된 엔티티의 영속성에도 영향을 미쳐 상태를 변경하는 것을 의미한다. 각 연관관계의 어노태이션에 <code>cascade</code> 라는 속성으로 포함되어 있다.</p>
<h4 id="cascade의-종류">cascade의 종류</h4>
<ul>
<li><code>ALL</code> : 모든 변경에 대해 적용</li>
<li><code>PERSIST</code> : 엔티티가 영속화할 때 연관된 엔티티도 함께 영속화</li>
<li><code>MERGE</code> : 엔티티를 영속성 컨텍스트에 병합할 때 연관된 엔티티도 병합</li>
<li><code>REMOVE</code> : 엔티티를 제거할 때 연관된 엔티티도 제거</li>
<li><code>REFRESH</code> : 엔티티를 새로고침할 때 연관된 엔티티도 새로고침</li>
<li><code>DETACH</code> : 엔티티를 영속성 컨텍스트에서 제외하면 연관된 엔티티도 제외</li>
</ul>
<p>타입의 종류에서 알 수 있듯 엔티티 생명주기와 연관이 있다. 상태 변경이 일어나면 매핑으로 연관된 엔티티에도 동일한 동작이 일어나도록 전이를 발생시키는 것이다.</p>
<h4 id="고아-객체orphan">고아 객체(orphan)</h4>
<p>고아 객체란 부모 엔티티와 연관관계가 끊어진 엔티티를 의미한다. JPA 에는 이러한 고아 객체를 자동으로 제거하는 기능이 있으며, 자식 엔티티가 다른 엔티티와 연관관계를 가지고 있다면 사용하지 않는 것이 좋다. 연관관계 어노태이션에 <code>orphanRemoval = true</code> 속성을 추가하는 방식으로 기능을 추가한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[스프링 부트 핵심 가이드] 정리 4주차]]></title>
            <link>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-4%EC%A3%BC%EC%B0%A8</link>
            <guid>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-4%EC%A3%BC%EC%B0%A8</guid>
            <pubDate>Sat, 10 Jun 2023 11:18:17 GMT</pubDate>
            <description><![CDATA[<h3 id="a-hrefhttpssearchshoppingnavercombookcatalog33005838635cat_id50010881pbokproec8aa4ed9484eba781ebb680ed8ab8ed95b5ec8baceab080ec9db4eb939cct3dlhspxgfk7cci3d13eccc862d5fa22bceca9182890803bd5ab9d6d27ctr3dboknx7csn3d956947chk3df4c134224127a865acb42b606b5f05d69ddaad0f-targetblank책-링크a"><a href="https://search.shopping.naver.com/book/catalog/33005838635?cat_id=50010881&frm=PBOKPRO&query=%EC%8A%A4%ED%94%84%EB%A7%81+%EB%B6%80%ED%8A%B8+%ED%95%B5%EC%8B%AC+%EA%B0%80%EC%9D%B4%EB%93%9C&NaPm=ct%3Dlhspxgfk%7Cci%3D13eccc862d5fa22bceca9182890803bd5ab9d6d2%7Ctr%3Dboknx%7Csn%3D95694%7Chk%3Df4c134224127a865acb42b606b5f05d69ddaad0f" target=blank>책 링크</a></h3>
<p>매주 <strong>스프링 부트 핵심 가이드</strong> 를 읽으며 이전에 궁금했거나, 새롭게 알게 된 내용들을 정리할 예정이다.
(이번 주는 8장을 읽었다.)</p>
<hr>
<h3 id="jpa-쿼리-메서드상세">JPA 쿼리 메서드(상세)</h3>
<h4 id="쿼리의-주제-키워드">쿼리의 주제 키워드</h4>
<ul>
<li><p><strong>find...By</strong>
조회하는 기능을 수행한다. 이외에 query...By, search...By, stream...By(스트림으로 반환) 등의 키워드로 사용 가능하다.</p>
</li>
<li><p><strong>exists...By</strong>
특정한 데이터가 존재하는지 확인한다.</p>
</li>
<li><p><strong>count...By</strong>
조회를 수행하고 나온 결과의 레코드의 개수를 반환한다.</p>
</li>
<li><p><strong>delete...By, remove...By</strong>
삭제를 수행한다.</p>
</li>
<li><p><strong>...First{number}..., Top{number}</strong>
조회된 결과의 개수를 제한한다. (<code>LIMIT ...</code> 과 유사한 역할)</p>
</li>
</ul>
<h4 id="쿼리의-조건자-키워드">쿼리의 조건자 키워드</h4>
<ul>
<li><p><strong>is, (is)Not</strong>
값의 일치나 불일치를 조건으로 사용한다.</p>
</li>
<li><p><strong>(is)Null, (is)NotNull</strong>
값이 null인지 아닌지를 확인한다</p>
</li>
<li><p>*<em>(is)True, (is)False *</em>
<code>boolean</code> 형태의 값을 확인한다.</p>
</li>
<li><p><strong>And, Or</strong>
여러 조건을 묶을 때 사용한다.</p>
</li>
<li><p><strong>(is)GreaterThan, (is)LessThan, (is)Between</strong>
숫자나 <code>datetime</code> 을 대상으로 비교하는 데에 사용한다. 경계값을 포함하려면(이상, 이하) 뒤에 <code>Equal</code> 을 추가한다.</p>
</li>
<li><p><strong>(is)StartingWith(==StartsWith), (is)EndingWith(==EndsWith),(is)Containing(==Contains), 
(is)Like</strong>
컬럼의 값의 일부가 일치하는지 확인한다. SQL에서의 <code>%</code>와 동일한 역할을 하는데 <code>Like</code>를 사용할 때에는 파라미터에 <code>%</code> 를 포함하여 전달해야 한다.</p>
</li>
</ul>
<h3 id="정렬과-페이징">정렬과 페이징</h3>
<h4 id="정렬">정렬</h4>
<pre><code class="language-java">OrderBy{column}{Asc(오름차순)/Desc(내림차순)}</code></pre>
<p>위와 같이 사용하면 된다. 여러 개의 컬럼을 기준으로 정렬하려면 먼저 정렬하고 싶은 컬럼과 기준을 순서대로 적어주되, <code>And</code> 와 <code>Or</code> 를 사용하지 않는다.</p>
<p>위의 방법으로도 가능하지만 JPA 라이브러리의 <code>Sort</code> 객체를 활용하여 정렬할 수도 있다. 예시는 다음과 같다.</p>
<pre><code class="language-java">// 이름이 &quot;Kim&quot; 인 사람을 성적순으로 오름차순 정렬
entityRepository.findByName(&quot;Kim&quot;, Sort.by(Order.asc(&quot;Grade&quot;)));
// 이름이 &quot;Kim&quot; 인 사람을 성적순으로 오름차순 정렬 후 나이순으로 내림차순 정렬
entityRepository.findByName(&quot;Kim&quot;, Sort.by(Order.asc(&quot;Grade&quot;), Order.desc(&quot;age&quot;)));</code></pre>
<p>이래도 길어보인다면 <code>Sort</code> 객체를 변수나 메소드화하여 사용할 수도 있다.</p>
<h4 id="페이징">페이징</h4>
<pre><code class="language-java">Page&lt;Person&gt; findByName(String name, Pageable pageable);</code></pre>
<p>데이터베이스의 레코드를 개수별로 나눠 페이지를 구분할 수 있다. <code>Page&lt;T&gt;</code> 형태의 객체를 받아야 하며 두번째 파라미터인 <code>Pagable</code> 은 구현체인 <code>PageRequest</code> 를 사용한다. <code>of</code> 메소드는 페이지 번호, 페이지 당 개수, 혹은 정렬에 사용한 <code>Sort</code> 객체를 이용하여 <code>Page</code> 를 생성한다. 이렇게 객체를 생성한 뒤 값을 확인하려면 <code>getContent()</code> 메소드를 사용한다.</p>
<h3 id="query-어노태이션">@Query 어노태이션</h3>
<blockquote>
<p>메소드의 키워드를 적절히 조합하여 메소드를 구현할 수도 있으나 직접 SQL을 작성하여 레포지토리의 메소드를 구현할 수도 있다. </p>
</blockquote>
<p><code>@Query(&quot;SQL 문장&quot;)</code> 의 방식으로 구현 가능하며, 파라미터를 바인딩하는 방식으로도 가능하다. 예시는 아래와 같다.</p>
<pre><code class="language-java">@Query(&quot;Select p FROM Person p WHERE p.name = :name&quot;)
List&lt;Person&gt; findByNameParam(@Param(&quot;name&quot;) String name);</code></pre>
<p>그리고 @Query 를 사용하면 엔티티 전체가 아니라 <code>SELECT</code> 를 사용하듯이 원하는 컬럼만 가져올 수도 있다. 그러나 이에 대한 엔티티 타입은 지정되어 있지 않으므로 <code>Object</code> 형태의 객체로 가져와야 한다.</p>
<h3 id="querydsl">QueryDSL</h3>
<p>QueryDSL은 정적(static) 타입을 이용해 쿼리를 생성할 수 있도록 해주는 프레임워크이다. 이 역시 Spring Data JPA처럼 코드를 이용하여 쿼리를 생성하므로 자동완성, 가독성 향상 등 다양한 장점을 가질 수 있다. </p>
<p>Spring data JPA와 비슷하게 레포지토리에 빌더(Builder) 형식으로 각 요소들(select, where, from 등) 을 지정해주면 알맞은 결과를 반환해준다. 결과를 받기 위해선 <code>fetch()</code> 메소드를 사용한다.</p>
<h3 id="jpa-auditing">Jpa Auditing</h3>
<p>엔티티의 생성 일자, 변경 일자, 생성자, 변경자 등을 감시(Audit) 하여 자동으로 값을 넣어주는 기능이다.</p>
<p>스프링 부트 어플리케이션에 <code>@EnableJpaAuditing</code> 어노태이션을 위에 달아주면 된다. 이런 요소가 들어가는 공통 엔티티(BaseEntity) 클래스를 생성하고, 각각 <code>@CreatedDate, @LastModifiedDate</code> 을 달아주면 된다. 예시는 다음과 같다.</p>
<pre><code class="language-java">// 엔티티가 상속받을 경우 자식에게 정보를 전달한다.
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {

    @CreateDate
    private LocalDateTime createdAt;

    @LastModifiedDate
    private LocalDateTime updatedAt;
}</code></pre>
<p>이렇게 한 <code>BaseEntity</code> 를 상속받는 엔티티는 따로 <code>LocalDateTime.now()</code> 등으로 시간을 정해주지 않아도 자동으로 값이 생성되고 변경된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[스프링 부트 핵심 가이드] 정리 3주차]]></title>
            <link>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-3%EC%A3%BC%EC%B0%A8</link>
            <guid>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-3%EC%A3%BC%EC%B0%A8</guid>
            <pubDate>Sun, 04 Jun 2023 07:20:59 GMT</pubDate>
            <description><![CDATA[<h3 id="a-hrefhttpssearchshoppingnavercombookcatalog33005838635cat_id50010881pbokproec8aa4ed9484eba781ebb680ed8ab8ed95b5ec8baceab080ec9db4eb939cct3dlhspxgfk7cci3d13eccc862d5fa22bceca9182890803bd5ab9d6d27ctr3dboknx7csn3d956947chk3df4c134224127a865acb42b606b5f05d69ddaad0f-targetblank책-링크a"><a href="https://search.shopping.naver.com/book/catalog/33005838635?cat_id=50010881&frm=PBOKPRO&query=%EC%8A%A4%ED%94%84%EB%A7%81+%EB%B6%80%ED%8A%B8+%ED%95%B5%EC%8B%AC+%EA%B0%80%EC%9D%B4%EB%93%9C&NaPm=ct%3Dlhspxgfk%7Cci%3D13eccc862d5fa22bceca9182890803bd5ab9d6d2%7Ctr%3Dboknx%7Csn%3D95694%7Chk%3Df4c134224127a865acb42b606b5f05d69ddaad0f" target=blank>책 링크</a></h3>
<p>매주 <strong>스프링 부트 핵심 가이드</strong> 를 읽으며 이전에 궁금했거나, 새롭게 알게 된 내용들을 정리할 예정이다.
(이번 주는 6장을 읽었다.)</p>
<hr>
<h3 id="orm과-jpa">ORM과 JPA</h3>
<h4 id="orm이란">ORM이란?</h4>
<blockquote>
<p>ORM은 Object Relational Mapping의 줄임말로, 자바와 같은 객체지향 언어에서의 객체와 RDB(Relational Database, 관계형 데이터베이스)의 테이블을 자동으로 매핑하는 방법이다.</p>
</blockquote>
<p>ORM을 이용하면 쿼리문을 작성이 아닌 코드로 데이터를 조작할 수 있다.</p>
<h4 id="orm의-장점">ORM의 장점</h4>
<ul>
<li>쿼리를 객체지향적으로 조작할 수 있다.</li>
<li>쿼리문을 작성하는 양이 아주 많이 줄어든다.</li>
<li>즉, 재사용 및 유지보수가 편리하다. (객체지향을 따르므로)</li>
<li>데이터베이스에 대한 종속성이 줄어든다. (예를 들어, MySQL을 사용하던 데이터베이스를 MariaDB로 교체한다고 했을 때, 약간 바뀌는 모든 쿼리문을 교체할 필요도 없고 그만큼 에러가 발생할 위험도 줄어든다.)</li>
</ul>
<h4 id="orm의-단점">ORM의 단점</h4>
<ul>
<li>복잡한 쿼리를 요구하는 경우 코드로 구현하기 어려우며 성능 문제가 발생할 수 있다.</li>
<li>객체의 관점과 데이터베이스의 관계의 관점에는 차이가 있어서 혼동이 발생할 수 있다.</li>
</ul>
<h4 id="jpa">JPA</h4>
<blockquote>
<p>JPA는 Java Persistence API를 의미하며, 자바의 ORM 기술 표준으로 채택된 인터페이스이다. ORM이 개념이라면 JPA는 조금 더 구체적인 명세라고 생각하면 되겠다.</p>
</blockquote>
<p>JPA는 내부적으로 JDBC를 사용하는데, 개발자가 JDBC를 활용하여 구현하면 SQL에 의존하게 되어 효율이 떨어진다. JPA는 이 문제점을 보완하여 개발자 대신 요구하는 기능에 맞는 SQL을 생성하고 데이터베이스를 조작하여 객체와 데이터베이스를 이어준다. 이를 기반으로 구현한 것 중 가장 많이 사용되는 것이 하이버네이트(Hibernate) 이고, 스프링 부트에서는 이 하이버네이트의 기능을 더욱 편하게 사용하도록 구현된 Spring Data JPA를 활용할 수 있다.</p>
<h3 id="엔티티">엔티티</h3>
<blockquote>
<p>데이터베이스의 테이블에 대응하는 클래스이다. 데이터베이스의 테이블과 컬럼을 정의할 수 있으며, 어노테이션을 사용하여 다양한 관계를 정의할 수 있다.</p>
</blockquote>
<h4 id="엔티티-관련-어노테이션">엔티티 관련 어노테이션</h4>
<ul>
<li><p><code>@Entity</code>
해당 클래스가 엔티티임을 명시하기 위한 어노테이션이다.</p>
</li>
<li><p><code>@Table</code>
테이블 이름과 클래스 이름을 다르게 지정해야 할 때 사용한다. 명시하지 않으면 둘의 이름이 같다는 의미이며, 다른 이름을 쓰려면 <code>@Table(name= 이름)</code> 의 형태로 테이블명을 명시해야 한다.</p>
</li>
<li><p><code>@Id</code>
테이블의 기본 값으로 사용되며, 모든 엔티티는 이 <code>@Id</code> 어노테이션이 필요하다.</p>
</li>
<li><p><code>@GeneratedValue</code>
일반적으로 <code>@Id</code> 와 함께 사용되며, 어떤 방식으로 자동 생성할지를 결정한다. 흔히 데이터베이스에 위임하는 <code>IDENTITY</code> 를 많이 사용하며, 이 방식은 데이터베이스의 <code>AUTO_INCREMENT</code> 를 사용해 기본값을 생성한다.</p>
</li>
<li><p><code>@Column</code>
엔티티 클래스의 멤버는 자동으로 컬럼으로 매핑되지만, 몇 가지 설정이 필요한 경우 사용한다.(컬럼의 이름, 값이 <code>null</code>이 될 수 있는지, 데이터 길이, 유니크 컬럼 등)</p>
</li>
</ul>
<h3 id="레포지토리">레포지토리</h3>
<blockquote>
<p>레포지토리는 Spring Data JPA가 제공하는 인터페이스이다. JpaRepository 를 상속받는 인터페이스를 생성하여 엔티티가 생성한 데이터베이스에 접근하는 데 사용된다.</p>
</blockquote>
<h4 id="기본-예시">기본 예시</h4>
<pre><code class="language-java">// 엔티티와 엔티티의 기본값(@id) 타입으로 지정
public interface PersonRepository extends JpaRepository&lt;Person, Long&gt; {
}</code></pre>
<h4 id="메소드-생성-규칙">메소드 생성 규칙</h4>
<p>기본적인 메소드는 생성이 되어있지만 규칙에 따라 커스텀 메서드도 생성할 수 있다. 이를 통해 CRUD(Create, Read, Update, Delete)를 모두 구현 가능하다.</p>
<ul>
<li>findBy: 일치하는 값을 가지는 컬럼을 조회한다. SQL의 where의 역할을 한다.</li>
<li>StartsWith/StartingWith - EndsWith/EndingWith : 특정 키워드로 시작하거나 끝나는 조건을 설정한다.</li>
<li>Before/After: 시간을 기준으로 검색한다.</li>
<li>Between: 두 값 사이의 데이터를 검색한다.</li>
</ul>
<h3 id="컨트롤러와-서비스">컨트롤러와 서비스</h3>
<p>컨트롤러 클래스에 API를 구현하고, 여기에서 어떠한 요청을 받으면 데이터베이스는 서비스 클래스에서 핵심 기능을 제공한다. 데이터베이스와 밀접한 관련이 있는 객체는 <code>엔티티 또는 DAO(Data Access Object)</code>를 사용하고, 클라이언트와 가까워지는 서비스 등의 레이어에서는 데이터를 주고받을 때 <code>DTO(Data Transfer Object)</code> 객체 를 사용하는 것이 일반적이다.
<img src="https://velog.velcdn.com/images/ameri-kano/post/755e2395-d063-4469-a683-b28463e7a08f/image.png" alt=""></p>
<h4 id="jpa-에서-값을-변경할-때">JPA 에서 값을 변경할 때</h4>
<p>조회, 추가, 삭제 의 메소드와는 다른 점이 있다. update 라는 키워드를 따로 사용하지 않으며, 값을 <code>find()</code> 를 통해 가져오면 객체가 영속성 컨텍스트에 추가된다. 컨텍스트가 유지되는 상황에서 코드에서 객체의 값을 변경하고 다시 <code>save()</code> 를 실행하면 변경 감지를 수행하여 값을 변경해준다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[스프링 부트 핵심 가이드] 정리 2주차]]></title>
            <link>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-2%EC%A3%BC%EC%B0%A8</link>
            <guid>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-2%EC%A3%BC%EC%B0%A8</guid>
            <pubDate>Sat, 27 May 2023 13:47:13 GMT</pubDate>
            <description><![CDATA[<h3 id="a-hrefhttpssearchshoppingnavercombookcatalog33005838635cat_id50010881pbokproec8aa4ed9484eba781ebb680ed8ab8ed95b5ec8baceab080ec9db4eb939cct3dlhspxgfk7cci3d13eccc862d5fa22bceca9182890803bd5ab9d6d27ctr3dboknx7csn3d956947chk3df4c134224127a865acb42b606b5f05d69ddaad0f-targetblank책-링크a"><a href="https://search.shopping.naver.com/book/catalog/33005838635?cat_id=50010881&frm=PBOKPRO&query=%EC%8A%A4%ED%94%84%EB%A7%81+%EB%B6%80%ED%8A%B8+%ED%95%B5%EC%8B%AC+%EA%B0%80%EC%9D%B4%EB%93%9C&NaPm=ct%3Dlhspxgfk%7Cci%3D13eccc862d5fa22bceca9182890803bd5ab9d6d2%7Ctr%3Dboknx%7Csn%3D95694%7Chk%3Df4c134224127a865acb42b606b5f05d69ddaad0f" target=blank>책 링크</a></h3>
<p>매주 <strong>스프링 부트 핵심 가이드</strong> 를 읽으며 이전에 궁금했거나, 새롭게 알게 된 내용들을 정리할 예정이다.
(이번 주는 4~5장을 읽었다.)</p>
<hr>
<h3 id="메이븐의-생명주기">메이븐의 생명주기</h3>
<blockquote>
<p>maven은 자바 기반 프로젝트를 빌드하고 관리하는 데 사용하는 도구이다. <code>pom.xml</code> 파일에 라이브러리를 추가하면 그 라이브러리와 해당 라이브러리에 필요한 라이브러리까지 전부 내려받아 관리가 가능하다. 현재는 그래들(gradle) 로 전환되는 추세이긴 하지만 아직은 메이븐을 활용한 프로젝트가 많다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ameri-kano/post/e97bd276-9ce4-4076-84f9-67f3d52d3efc/image.png" alt="">
메이븐의 생명주기는 크게 기본(Default), 클린(Clean), 사이트(Site) 생명주기의 3가지로 구분된다. 각 생명주기에는 단계가 존재하고 특정 단계를 수행하기 위해서는 이전 단계를 마쳐야 한다.</p>
<h3 id="api-개발">API 개발</h3>
<p>기본적으로 컨트롤러 클래스를 만들고 클래스 위에 <code>@RestController</code> 어노태이션을 붙여줘 컨트롤러임을 스프링에게 알려준다. 그 다음 클래스에 <code>@RequestMapping</code> 을 붙여주면 내부 메소드에서 사용할 공통 URL을 설정할 수 있다. </p>
<h4 id="requestmapping으로-구현하기">@RequestMapping으로 구현하기</h4>
<p>메소드에 <code>@RequestMapping</code> 어노태이션을 다른 설정 없이 선언하면 모든 HTTP 요청을 받을 수 있으나, 특정 요청만 받으려면 별도 설정이 필요하다. 스프링의 버전이 업데이트되면서 <code>@GetMapping, @PostMapping, @PutMapping, @DeleteMapping</code> 등 이름에서부터 명시된 어노태이션을 사용하므로 특별히 활용해야 하는 경우가 아니라면 <code>@RequestMapping</code> 은 사용하지 않는다.</p>
<h3 id="get-메소드">GET 메소드</h3>
<blockquote>
<p>GET 메소드에 매개 변수를 전달하는 방법은 크게 URL 자체에 값을 담거나 쿼리 문자열을 명시하는 방법이 있다. 각각 메소드에 <code>@PathVariable</code> 을 포함하거나 <code>@RequestParam</code> 을 포함하는 방식으로 구현이 가능하다.</p>
</blockquote>
<h4 id="pathvariable을-활용한-get-메소드">@PathVariable을 활용한 GET 메소드</h4>
<pre><code class="language-java">// 일반적인 방법
@GetMapping(&quot;/api/{value}&quot;)
public String getValue(@PathVariable String value) {
    return value;
}

// URL 매핑과 메소드 매개변수의 이름이 다른 경우
@GetMapping(&quot;/api/{value}&quot;)
public String getValue(@PathVariable(&quot;value&quot;) String val) {
    return val;
}</code></pre>
<h4 id="requestparam을-활용한-get-메소드">@RequestParam을 활용한 GET 메소드</h4>
<pre><code class="language-java">// http://localhost:8080/request?value1=Hello&amp;value2=World
@GetMapping(&quot;/request&quot;)
public String getRequest(@RequestParam String value1, @RequestParam String value2) {
    return &quot;value1: &quot; + value1 + &quot;value2: &quot; + value2;
}

// 값이 정해져 있지 않다면 Map 객체 활용 가능
@GetMapping(&quot;/request&quot;)
public String getValue(@RequestParam Map&lt;String, String&gt; parameterMap) {
    ...
}</code></pre>
<h3 id="post-메소드">POST 메소드</h3>
<blockquote>
<p>POST 메소드에서는 저장하고자 하는 값이나 리소스를 HTTP 바디(body) 에 담아 전달한다.
바디는 다수의 환경에서 JSON 형식으로 전달해준다.</p>
</blockquote>
<h4 id="requestbody를-활용한-post-메소드">@RequestBody를 활용한 POST 메소드</h4>
<pre><code class="language-java">// 바디에 어떤 값이 들어올지 특정하기 어려울 경우 Map 객체 사용
@PostMapping(&quot;/request&quot;)
public String postRequest(@RequestBody Map&lt;String, Object&gt; requestBody) {
    ...
}

// DTO(Data Transfer Object) 가 있다면 DTO 활용 가능
// DTO의 멤버 변수를 바디의 키와 매핑
@PostMapping(&quot;/request&quot;)
public String postRequest(@RequestBody PersonDto personDto) {
    ...
}</code></pre>
<p>이외에 PUT, DELETE 도 유사한 구조를 가지고 있으며 각각 수정과 삭제의 기능을 한다는 점이 차이가 있다.</p>
<h3 id="requestentity와-responseentity">RequestEntity와 ResponseEntity</h3>
<p>각각 요청과 응답 객체를 더욱 편하게 생성해줄 수 있는 객체이다. 모든 HTTP 메소드에서 사용 가능하며, 헤더와 바디 이외에 HTTP 응답 코드도 지정해 줄 수 있다.</p>
<pre><code class="language-java">// DTO를 활용
@DeleteMapping(&quot;/request&quot;)
public ResponseEntity&lt;PersonDto&gt; postRequest(@RequestBody PersonDto personDto) {
    return ResponseEntity
        .status(HttpStatus.OK)
        .body(personDto);
}</code></pre>
<h3 id="swagger">Swagger</h3>
<p>API 명세 문서를 만들어주는 라이브러리이다. 컨트롤러에 있는 메소드에 추가적으로 어노태이션을 달아주면 Swagger가 자동으로 문서를 만들어주는데, Spring 버전별로(2.x.x 이거나 3.x.x) 어노태이션에 차이가 있으므로 유의해야 한다.</p>
<h3 id="logback">Logback</h3>
<p>서버에서 발생하는 로그를 파일로 저장할 때 사용하는 라이브러리이다. 에러, 경고, 디버그 등 다양한 로그 레벨을 설정하여 종류별로 관리할 수 있으며, 자체적으로 로그 파일 압축, 로그 파일 보관 기간 설정 등 다양한 기능을 지원한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[스프링 부트 핵심 가이드] 정리 1주차]]></title>
            <link>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-1%EC%A3%BC%EC%B0%A8</link>
            <guid>https://velog.io/@ameri-kano/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-%ED%95%B5%EC%8B%AC-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%A0%95%EB%A6%AC-1%EC%A3%BC%EC%B0%A8</guid>
            <pubDate>Thu, 18 May 2023 06:42:32 GMT</pubDate>
            <description><![CDATA[<h3 id="a-hrefhttpssearchshoppingnavercombookcatalog33005838635cat_id50010881pbokproec8aa4ed9484eba781ebb680ed8ab8ed95b5ec8baceab080ec9db4eb939cct3dlhspxgfk7cci3d13eccc862d5fa22bceca9182890803bd5ab9d6d27ctr3dboknx7csn3d956947chk3df4c134224127a865acb42b606b5f05d69ddaad0f-targetblank책-링크a"><a href="https://search.shopping.naver.com/book/catalog/33005838635?cat_id=50010881&frm=PBOKPRO&query=%EC%8A%A4%ED%94%84%EB%A7%81+%EB%B6%80%ED%8A%B8+%ED%95%B5%EC%8B%AC+%EA%B0%80%EC%9D%B4%EB%93%9C&NaPm=ct%3Dlhspxgfk%7Cci%3D13eccc862d5fa22bceca9182890803bd5ab9d6d2%7Ctr%3Dboknx%7Csn%3D95694%7Chk%3Df4c134224127a865acb42b606b5f05d69ddaad0f" target=blank>책 링크</a></h3>
<p>매주 <strong>스프링 부트 핵심 가이드</strong> 를 읽으며 이전에 궁금했거나, 새롭게 알게 된 내용들을 정리할 예정이다.</p>
<hr>
<h3 id="레이어드-아키택쳐">레이어드 아키택쳐</h3>
<p>레이어드 아키택쳐(Layered Architecture)란, 어플리케이션의 컴포넌트를 유사 관심사를 기준으로 레이어로 묶어 수평적으로 구성한 구조를 의미한다. 일반적으로 프레젠테이션 계층, 비즈니스 계층, 데이터 접근 계층의 3계층으로 이루어져 있으며, 이를 스프링과 스프링 MVC(Model-View-Controller)에 적용하면 View와 Controller는 프레젠테이션 계층, Model은 비즈니스 와 데이터 접근 계층으로 구분할 수 있다. 다만 Model을 세분화하여 비즈니스 계층에 서비스, 데이터 접근 계층에 DAO를 배치하여 도메인을 관리한다. 자세하게 설명하면 다음과 같다.</p>
<p><strong>프레젠테이션 계층</strong></p>
<ul>
<li>유저 인터페이스(UI, User Interface) 계층이라고도 한다.</li>
<li>클라이언트와 가장 가깝게 맞닿아 있다.</li>
<li>클라이언트로부터 데이터와 요청을 받고 API의 결과를 응답으로 전달한다.</li>
</ul>
<p><strong>비즈니스 계층</strong></p>
<ul>
<li>서비스(Service) 계층이라고도 한다.</li>
<li>핵심 비즈니스 로직을 구현한다.</li>
<li>트랜잭션이나 유효성 검사 등의 작업도 수행한다.</li>
</ul>
<p><strong>데이터 접근 계층</strong></p>
<ul>
<li>영속(Persistence) 계층이라고도 한다.</li>
<li>데이터베이스에 접근하는 작업을 수행한다.</li>
<li>일반적으로 DAO(Data Access Object, 데이터 접근 객체)를 이용한다고 표현하지만, Spring Data JPA(Java Persistence API)에서는 리포지토리(Repository)가 DAO의 역할을 수행한다.</li>
</ul>
<h3 id="rest-api">REST API</h3>
<blockquote>
<p>REST API, RESTful하게, 이런 말을 많이 들어는 봤는데 이에 대해 자세하게 알지는 못했었다. 이번 기회에 확실하게 알아보고 정리하려 한다.</p>
</blockquote>
<h4 id="rest란">REST란?</h4>
<p><strong>Representional State Transfer</strong>의 약자로, WWW(월드 와이드 웹)과 같은 시스템 아키택쳐의 형식이다. 같은 주고받는 자원에 이름을 규정하고 URI에 명시해 HTTP 메소드(GET, POST, PUT, DELETE)를 통해 해당 자원의 상태를 주고받는 것을 의미한다.</p>
<h4 id="rest-api란">REST API란?</h4>
<p>REST 아키택쳐를 따르는 API라고 할 수 있다. 또한 이를 따르는 API를 RESTful하다고 표현한다.</p>
<h4 id="그렇다면-rest의-특징은">그렇다면 REST의 특징은?</h4>
<ul>
<li><p><strong>유니폼 인터페이스</strong> - 플랫폼과 기술에 종속되지 않고 일관된 인터페이스를 따른다.</p>
</li>
<li><p><strong>무상태성(Stateless)</strong> - 서버는 클라이언트가 보낸 요청에 대한 정보를 별도 보관하거나 관리하지 않는다. 그러므로 한 클라이언트가 여러 요청을 보내든 여러 클라이언트가 하나의 요청을 보내든 모두 개별적으로 처리하며, 서버가 불필요한 정보를 관리하지 않기 때문에 비즈니스 로직의 자유도가 높고 설계가 둔산하다.</p>
</li>
<li><p><strong>캐시 가능성</strong> - HTTP 표준을 그대로 사용하므로 캐싱을 적용할 수 있다. 별도의 명시가 필요하며 같은 요청의 경우에 클라이언트가 캐시에 저장된 데이터를 불러와 다시 사용한다. 서버의 부하도 줄이고  사용자가 느끼는 성능도 개선된다.</p>
</li>
<li><p><strong>레이어 시스템</strong> - 네트워크 상의 여러 계층으로 구성될 수 있으나, 서버가 복잡한 것과 관계없이 클라이언트는 서버와 연결되는 포인트만 알면 된다.</p>
</li>
<li><p><strong>클라이언트-서버 아키택쳐</strong> - 클라이언트와 서버를 서로 분리하여 설계해 서로의 의존성을 낮춘다.</p>
</li>
</ul>
<h4 id="rest한-uri-설계-규칙">REST한 URI 설계 규칙</h4>
<blockquote>
<p>URI는 Uniform Resource Identifier 의 줄임말이며, 통합 자원 식별자라는 의미를 가지고 있다. 우리에게 익숙한 URL은 Locator, 즉 주소를 의미하며 URI에 포함된 개념이다. (URI가 더 포괄적인 개념)</p>
</blockquote>
<p>REST API를 설계하는 데에 다음과 같은 규칙들이 있다고 한다.</p>
<ul>
<li>URL의 마지막에는 <code>/</code> 을 포함하지 않는다.</li>
<li>언더바<code>_</code>  대신 하이픈 <code>-</code> 을 이용한다.</li>
<li>URL에는 행위(동사) 가 아닌 결과(명사) 를 포함한다.</li>
<li>소문자로 작성해야 한다.</li>
<li>파일의 확장자는 포함하지 않는다.</li>
</ul>
<h3 id="마무리하며">마무리하며</h3>
<p>책을 읽고 공부하면서 바로 와닿은 부분이 하나 있었다. 바로 REST API를 설계할 때의 규칙 중 세번째 규칙이다. URL에 행위가 아닌 결과를 포함한다는 부분이었는데, 스프링을 이용한 API 개발 강의를 들을 때 똑같은 정보(<code>info</code> 라고 가정하자)를 각각 저장, 조회, 삭제, 수정하는 API의 이름을 짓는다고 생각해보면, </p>
<pre><code class="language-http">/save-info, /get-info, /delete-info, /modify-info</code></pre>
<p>이런 식으로 하지 않고</p>
<pre><code class="language-http">GET /info, POST /info, DELETE /info, PUT /info</code></pre>
<p>로 HTTP 메서드만 구분하여 개발하는 이유가 규칙 중 하나였다는 것을 알게 되었다.</p>
<p>아직 책을 많이 읽지는 못했지만, 다 읽고 나면 분명 스프링에 대한 이해를 더 발전시킬 수 있을 것을 기대한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[programmers/JAVA] 비밀 지도]]></title>
            <link>https://velog.io/@ameri-kano/programmersJAVA-%EB%B9%84%EB%B0%80-%EC%A7%80%EB%8F%84</link>
            <guid>https://velog.io/@ameri-kano/programmersJAVA-%EB%B9%84%EB%B0%80-%EC%A7%80%EB%8F%84</guid>
            <pubDate>Tue, 18 Apr 2023 07:15:29 GMT</pubDate>
            <description><![CDATA[<hr>
<h3 id="문제-a-hrefhttpsschoolprogrammerscokrlearncourses30lessons17681-target_blank링크a">문제 <a href="https://school.programmers.co.kr/learn/courses/30/lessons/17681" target="_blank">링크</a></h3>
<p>네오는 평소 프로도가 비상금을 숨겨놓는 장소를 알려줄 비밀지도를 손에 넣었다. 그런데 이 비밀지도는 숫자로 암호화되어 있어 위치를 확인하기 위해서는 암호를 해독해야 한다. 다행히 지도 암호를 해독할 방법을 적어놓은 메모도 함께 발견했다.</p>
<ol>
<li>지도는 한 변의 길이가 <code>n</code>인 정사각형 배열 형태로, 각 칸은 &quot;공백&quot;(&quot; &quot;) 또는 &quot;벽&quot;(&quot;#&quot;) 두 종류로 이루어져 있다.</li>
<li>전체 지도는 두 장의 지도를 겹쳐서 얻을 수 있다. 각각 &quot;지도 1&quot;과 &quot;지도 2&quot;라고 하자. 지도 1 또는 지도 2 중 어느 하나라도 벽인 부분은 전체 지도에서도 벽이다. 지도 1과 지도 2에서 모두 공백인 부분은 전체 지도에서도 공백이다.</li>
<li>&quot;지도 1&quot;과 &quot;지도 2&quot;는 각각 정수 배열로 암호화되어 있다.</li>
<li>암호화된 배열은 지도의 각 가로줄에서 벽 부분을 <code>1</code>, 공백 부분을 <code>0</code>으로 부호화했을 때 얻어지는 이진수에 해당하는 값의 배열이다.
<img src="https://velog.velcdn.com/images/ameri-kano/post/6963aaca-3718-43e2-829d-cdaad30342e2/image.png" alt="">
네오가 프로도의 비상금을 손에 넣을 수 있도록, 비밀지도의 암호를 해독하는 작업을 도와줄 프로그램을 작성하라.</li>
</ol>
<h3 id="입력-형식">입력 형식</h3>
<p>입력으로 지도의 한 변 크기 <code>n</code> 과 2개의 정수 배열 <code>arr1</code>, <code>arr2</code>가 들어온다.</p>
<ul>
<li>1 ≦ <code>n</code> ≦ 16</li>
<li><code>arr1</code>, <code>arr2</code>는 길이 <code>n</code>인 정수 배열로 주어진다.</li>
<li>정수 배열의 각 원소 <code>x</code>를 이진수로 변환했을 때의 길이는 <code>n</code> 이하이다. 즉, 0 ≦ <code>x</code> ≦ 2<sup>n</sup> - 1을 만족한다.</li>
</ul>
<h3 id="출력-형식">출력 형식</h3>
<p>원래의 비밀지도를 해독하여 <code>&#39;#&#39;</code>, <code>공백</code>으로 구성된 문자열 배열로 출력하라.</p>
<hr>
<h3 id="접근-방법">접근 방법</h3>
<p>배열의 각각의 인덱스에서 두 개의 정수를 가져오고, 그 두 정수를 or 비트 연산자(<code>|</code>) 를 수행한 결과가 해독한 결과가 된다. 이를 위해 정수를 이진수로 표현한 문자열로 변환해주는 <code>Integer.toBinaryString()</code> 을 이용해주면 결과를 쉽게 구할 수 있다. 그러나 이 메소드를 실행했을 때 이진수의 자리수가 <code>n</code> 보다 작은 경우 앞에 0이 생략되는데, 이를 고려하여 부족한 자리수만큼 앞에 0을 추가해주면 <code>00111, 01110</code> 등의 경우도 표현 가능해진다.</p>
<h3 id="소스-코드">소스 코드</h3>
<pre><code class="language-java">class Solution {
    public String[] solution(int n, int[] arr1, int[] arr2) {
        String[] answer = new String[n];
        StringBuilder sb = new StringBuilder();

        for (int i=0; i&lt;arr1.length; i++) {
            String t = Integer.toBinaryString(arr1[i] | arr2[i]);
            t = &quot;0&quot;.repeat(n-t.length()) + t;

            for (char c: t.toCharArray()) {
                if (c == &#39;1&#39;) sb.append(&#39;#&#39;);
                else sb.append(&#39; &#39;);
            }
            answer[i] = sb.toString();
            sb.setLength(0);
        }
        return answer;
    }
}</code></pre>
<h3 id="제출-결과">제출 결과</h3>
<p><img src="https://velog.velcdn.com/images/ameri-kano/post/56b943c3-95f8-43b1-8e42-4f13dea8f78b/image.png" alt=""></p>
<hr>
<h3 id="마무리하며">마무리하며</h3>
<p>이 문제는 옛날 카카오 공채 기출문제이다. 근데 난이도가 하 로 책정되어 있어서 그런지 생각보다 풀기 수월했다. 비트 연산자를 활용하는 문제가 생각보다 꽤 있는것 같고, 이 부분에 대한 활용 연습도 더 필요할 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[개발자는 왜 자료구조와 알고리즘을 배워야 할까?]]></title>
            <link>https://velog.io/@ameri-kano/%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8A%94-%EC%99%9C-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EC%99%80-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9D%84-%EB%B0%B0%EC%9B%8C%EC%95%BC-%ED%95%A0%EA%B9%8C</link>
            <guid>https://velog.io/@ameri-kano/%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8A%94-%EC%99%9C-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EC%99%80-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9D%84-%EB%B0%B0%EC%9B%8C%EC%95%BC-%ED%95%A0%EA%B9%8C</guid>
            <pubDate>Fri, 07 Apr 2023 06:52:34 GMT</pubDate>
            <description><![CDATA[<hr>
<p>지금 나는 조금 더 체계적인 배움을 위해 제로베이스 백엔드 스쿨을 수강중이다. 이제 1개월 정도 되었고, 지금까지 자료구조와 알고리즘에 대해서 전공수업의 기억을 살리며 다시 한 번 공부했다. 
본격적인 프로그래밍을 위해서는 그 사용하는 프레임워크에 따른 학습이 필요하지만 아직 그 단계는 아니고, 그렇다면 그 전에 자료구조와 알고리즘을 왜 배워야 하는걸까 개인적으로 생각해보았다.</p>
<h3 id="코딩테스트">코딩테스트?</h3>
<p>코딩테스트, 물론 중요하다. 이것에 합격하지 못하면 개발자가 될 수 없으니까. 다양한 문제들을 코드를 작성해 해결하는 것이고, 거기에서 얼마나 효율적으로 자료구조 및 알고리즘을 응용할 수 있는지를 확인하는 단계이다. 하지만 단순하게 코딩테스트를 합격하기 위해서만 이것들을 공부해야 하는걸까?</p>
<h3 id="사고력">사고력</h3>
<p>대학생 때 비전공학과 대상 교양 코딩과목 수업을 진행하는 조교를 1년 정도 해본 경험이 있다. (공과대학 학생들이었다.) 그 때 내가 가르치는 학생들에게 전공에 직접적으로 도움이 되지는 않겠지만 결국 전공 문제들을 해결하려면 수학적 사고력이 필요하고, 코딩이 그 수학적 사고력을 키워주는데 어느정도 도움이 된다는 이야기를 해주면서 성실히 참여하면 얻어가는 게 있을거라고 말을 해줬던 적이 있다. 위에서 말한 어떤 수단을 어떻게 효율적으로 사용하는지 생각하는 것이 사고력이라고 생각하는데, 이런 사고력을 키울 수 있는 것이다. 그렇다면 이 사고력은 키워서 어디에 써먹을 수 있을까?</p>
<h3 id="문제-해결의-경험">문제 해결의 경험</h3>
<p>진짜 개발의 단계로 넘어와서, 학부생 조별과제 정도의 프로젝트더라도 최소한의 과정이 있고, 우리가 마스터 개발자도 아니기 때문에 다양한 문제들이 발생한다. 우리는 이를 대부분 구글링으로도 해결할 수 있지만, 문제를 어떻게 해결할수 있을지에 대해 생각해본다. 이 때 더 효율적으로 해결할 수 있었던 경험이 쌓이고 쌓여 실력이 될 것이다. 현업에서 발생할 수 있는 문제도 당황하지 않고 이런 경험을 살릴 수 있다면 더욱 사랑받는 개발자가 될 수 있을 것이라고 생각한다.</p>
<h3 id="마치며">마치며</h3>
<p>결국은 경험이 가장 중요한 것이다. 다양한 문제를 해결하고 거기에서 얻을수 있는 것들을 내 것으로 만들어 더 어려운 문제들을 해결해나가도록 노력해야 한다.</p>
]]></description>
        </item>
    </channel>
</rss>