<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>seasame_oil.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sun, 09 Apr 2023 09:25:30 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. seasame_oil.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/seasame_oil" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Spring swagger 사용법]]></title>
            <link>https://velog.io/@seasame_oil/Spring-swagger-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@seasame_oil/Spring-swagger-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Sun, 09 Apr 2023 09:25:30 GMT</pubDate>
            <description><![CDATA[<p>프로젝트를 진행하던 중, API를 정리한 문서가 필요해졌고 Swagger를 통해 API를 정리하기로 팀원과 결정하였다. 문제는... swagger 의존성이 주입되지 않고 계속 whiteLable Error가 발생했다는 점...</p>
<p>다른 프로젝트에서는 잘 진행되었는데 왜 이번 프로젝트에서는 에러가 나는지... 공식문서, Configuration, gradle, yml 등 설정 관련 파일들을 계속 만지다가 결국 알아낸 건,<em>Spring 버전에 따라 gradle implement</em> 가 다르다는 것...!</p>
<p>바로 공식문서와 코드로 알아보자.</p>
<h1 id="진행-과정">진행 과정</h1>
<p>아마 대부분 아래와 같은 의존성을 주입하고 있을 것이다. 많은 블로그에서 아래와 같이 설명하고 있고 관련 설정들도 알려주기 때문이다. 그런데 내 프로젝트에서는 진행이 안 된다? 스프링 버전을 한 번 살펴보자.</p>
<pre><code>implementation &#39;org.springdoc:springdoc-openapi-ui:1.6.15</code></pre><p><a href="https://springdoc.org/#properties">spring-docs/v1</a>
위의 링크를 확인해보면
<img src="https://velog.velcdn.com/images/seasame_oil/post/cf34688b-9977-497e-b48f-79cb3459120e/image.png" alt="">
다음과 같은 문구를 확인 가능하다</p>
<p>스프링 v3이상을 사용중이라면
<a href="https://springdoc.org/v2/">spring-docs/v2</a>
위의 링크를 확인해보자</p>
<p><img src="https://velog.velcdn.com/images/seasame_oil/post/9d0d47fa-a2f8-4fbe-9bad-e0caa0108e2e/image.png" alt="">
다음과 같은 라이브러리를 지원하고,</p>
<ul>
<li>xml<pre><code> &lt;dependency&gt;
    &lt;groupId&gt;org.springdoc&lt;/groupId&gt;
    &lt;artifactId&gt;springdoc-openapi-starter-webmvc-ui&lt;/artifactId&gt;
    &lt;version&gt;2.1.0&lt;/version&gt;
 &lt;/dependency&gt;</code></pre></li>
<li>gradle<pre><code>implementation &#39;org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0&#39;</code></pre>를 통해 사용 가능하다.</li>
</ul>
<p>바꿔주면, 바로 Swagger 접속 가능!</p>
<h3 id="configuration">Configuration</h3>
<p>혹시나 관련 Config 파일이 궁금하실까봐,,,</p>
<pre><code>import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
public class SwaggerConfig implements WebMvcConfigurer {

    @Bean
    public OpenAPI OpenApi() {

        return new OpenAPI()
                .info(new Info().title(&quot;Test API&quot;)
                    .description(&quot;Test api 입니다.&quot;)
                    .version(&quot;v0.0.1&quot;));
    }
}
</code></pre><h1 id="spring-security">spring-security</h1>
<p>이거는 추가적인 내용인데, 우리 프로젝트에서는 로그인 관련하여 spring-security를 사용중이다.
이를 간과하고 swagger로 바로 접속하면 &quot;Failed to load remote configuration&quot;이라는 메시지가 뜨면서 내용을 볼 수 없다는 내용이 나온다.</p>
<p>이는 간단하게 해결 가능한데, spring-security 관련 config 파일에</p>
<pre><code>.requestMatchers( &quot;/&quot;,&quot;/swagger-ui/**&quot;, &quot;/v3/api-docs/**&quot;).permitAll()</code></pre><p>를 추가해주면 된다.</p>
<hr>
<p>그럼 이만...!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[@Builder 와 Modelmapper - (1) @Builder]]></title>
            <link>https://velog.io/@seasame_oil/Builder-%EC%99%80-Modelmapper-1-Builder</link>
            <guid>https://velog.io/@seasame_oil/Builder-%EC%99%80-Modelmapper-1-Builder</guid>
            <pubDate>Sun, 05 Feb 2023 14:35:54 GMT</pubDate>
            <description><![CDATA[<p>주로 엔티티와 DTO간의 데이터 전달에서, 빌더 모델매퍼와 같은 방식이 있다는 것은 알고 있었지만 정확한 개념이나 사용방법을 잘 익히지 못하고 있었기에 사용을 미루고 있었다. 제일 기본적인</p>
<pre><code>public void toEntity(Member member) {
    this.memberName = member.getMemberName();
    this.memberPhone = member.getMemberPhone();
}</code></pre><p>과 같은 방식으로 데이터를 주고 받았었다.</p>
<p>프로젝트 상에서 큰 문제를 일으키지 않았고, 잘 작동했기 때문에 이를 바꾸려고 하지는 않았었다. 그러나 엔티티의 컬럼들이 많아지고 넣어야 하는 테이터들이 증가하자 이렇게 사용하기에는 귀찮고 더 편한 방법을 찾기 시작했다.</p>
<p>그렇게 찾게된게 1. @Builder 2. Modelmapper 이다. 각각의 장단점과 사용방법에 대해 알아보려 한다.</p>
<h1 id="1-builder">1. @Builder</h1>
<p>빌더패턴에는 1. 점증적 생성자 패턴 2. 자바 빈즈 패턴 3. 빌더 패턴이 있다. 1번과 2번의 경우 코드량도 많고 가독성이 그렇게 좋지 않기 때문에 생략하도록 하겠다.
** 자바 빈즈 패턴
뒤에 잠깐 언급이 나와 설명하자면,</p>
<pre><code>public class Member {
    private String name;
    private int age;

    public Member() {}

    public void setName(String name) {
        this.name = name;
       }

    public void setAge(int age) {
        this.age = age;
    }
}</code></pre><pre><code>Member member = new Member(); // 선 객체 생성, 후 값 부여
member.setName(&quot;ABC&quot;);
member.setAge(22);</code></pre><h2 id="1-1-빌더-패턴의-장점">1-1. 빌더 패턴의 장점</h2>
<p>생성자에 매개변수가 많을 경우 빌더를 고려하면 좋다. 정보들은 자바빈즈패턴처럼 받지만, 데이터 일관성을 위해 정보들을 다 받은 후에 객체를 생성한다.</p>
<ul>
<li>불필요한 생성자 제거</li>
<li>데이터의 순서에 상관없이 객체 생성 가능</li>
<li>setter 메서드가 없으므로 변경 불가능한 객체 만들수 있음</li>
<li>build() 함수가 null인지 체크해주기 때문에 검증 가능</li>
</ul>
<h2 id="1-2-빌더-패턴-사용-방법1">1-2. 빌더 패턴 사용 방법(1)</h2>
<p>빌더 클래스를 직접 만드는 방법도 있지만 이것은 스킵... 
롬복을 이용해서 사용하는 방법은 다음과 같다.</p>
<pre><code>@Builder
public class Member{
    private final String name;
    private final int age;
}</code></pre><pre><code>Member member = Member.builder()
    .name(&quot;ABC&quot;)
    .age(22)
    .build();</code></pre><p>간단하게 생성이 가능하다.</p>
<h2 id="1-3-빌터-패던-사용-방법2">1-3. 빌터 패던 사용 방법(2)</h2>
<p>우리가 엔티티에 빌더를 바로 적용해서 원하는 값을 넣을 수 있지만, RequestDto나 다른 Dto를 통해 값을 얻어올 경우 엔티티의 컬럼과 정확하게 일치하지 않을 경우가 많다. 이 경우의 빌더 사용법을 보자.</p>
<ol>
<li>빌더를 사용하지 않을 경우</li>
</ol>
<p>** RequestDto에서 name, age만 받아온다는 가정
Entity</p>
<pre><code>public class Member {
    private String name;
    private int age;
    private String house;

    public void toEntity(RequestDto requestDto, String house) {
        this.name = requestDto.getName();
        this.age = requestDto.getAge();
        this.house = house;
    }
}</code></pre><pre><code>@Service
@RequiredArgsConstructor
public class MemberService {

    private final MemberRepository memberRepository;

    @Trnasactional
    public void saveMember(RequestDto requestDto, String house) {

        Member member = new Member();
        member.toEntity(requestDto, house);
        memberRepository.save(member);
    }
}</code></pre><ol start="2">
<li><p>빌더를 사용할 경우</p>
<pre><code>public class Member {
 private String name;
 private int age;
 private String house;

 @Builder
 public Member(RequestDto requestDto, String house) {
     this.name = requestDto.getName();
     this.age = requestDto.getAge();
     this.house = house;
 }
}</code></pre><pre><code>@Service
@RequiredArgsConstructor
public class MemberService {

 private final MemberRepository memberRepository;

 @Trnasactional
 public void saveMember(RequestDto requestDto, String house) {

     Member member = Member.builder()
         .requestDto(requestDto)
         .house(house)
         .build();

     memberRepository.save(member);
 }
}</code></pre></li>
</ol>
<h1 id="마무리하며">마무리하며</h1>
<p>사실 빌더를 사용했을 때 코드상의 큰 차이점을 아직은 잘 모르겠다. 그래도 엔티티와 DTO의 데이터 전달 방법의 새로운 길을 찾은 것 같아 기분이 좋다.</p>
<p>모델매퍼와 같이 정리하려 했는데 나눠 정리하는게 가독성이 좋을 것 같아 이쯤에서 마무리하려 한다. 2부에서 모델매퍼를 정리해보겠다.
<a href="https://esoongan.tistory.com/82">참고 1</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[H2 database + SpringBoot (Mac)]]></title>
            <link>https://velog.io/@seasame_oil/H2-database-SpringBoot-Mac</link>
            <guid>https://velog.io/@seasame_oil/H2-database-SpringBoot-Mac</guid>
            <pubDate>Sat, 04 Feb 2023 15:35:08 GMT</pubDate>
            <description><![CDATA[<p>프로젝트를 하면서 다양한 DB를 쓸 수 있지만, 가장 간편하고 테스트 하기 좋은 DB가 h2라 생각해서 개발 시에는 항상 h2를 사용합니다. 주로 다른 데이터베이스는 배포 시에 갈아끼운다는 느낌으로 진행했습니다. </p>
<ul>
<li>각 DB에 맞는 쿼리를 쓴다면 이야기가 다르겠지만 복잡한 쿼리를 쓰지 않는 프로젝트를 진행하시는 분이라면 h2를 추천합니다.</li>
</ul>
<h2 id="1-h2-다운로드">1. H2 다운로드</h2>
<p><a href="http://www.h2database.com/html/download.html">h2 다운로드 하는 곳</a>
<img src="https://velog.velcdn.com/images/seasame_oil/post/124c5fa1-2992-4361-abad-5185264c0553/image.png" alt="h2 download 화면"></p>
<p>각자 환경에 맞는 것으로 다운로드 하면 됩니다.
(Window - window installer / mac - platform-independent)</p>
<h2 id="2-실행">2. 실행</h2>
<p><img src="https://velog.velcdn.com/images/seasame_oil/post/1f0cf8ad-9a7e-4054-ab61-375125262b09/image.png" alt=""></p>
<p>압축을 풀고, 해당 bin 폴더에 가신 후</p>
<pre><code>./h2.sh</code></pre><p>를 실행하시면 됩니다.
만약 권한이 없다면</p>
<pre><code>chmod 755 ./h2.sh</code></pre><p>로 권한을 부여하면 됩니다.</p>
<h2 id="3-처음-실행">3. 처음 실행</h2>
<p>처음 진입했을 때, JDBC URL만</p>
<pre><code>jdbc:h2:~/(원하는 DB 명)
// ex. jdbc:h2:~/pillSolution</code></pre><p>다음과 같이 바꿔줍니다.
<img src="https://velog.velcdn.com/images/seasame_oil/post/73293f1d-d82f-4908-91fa-7d7491cb923b/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/seasame_oil/post/fc8223aa-11fa-4e0f-9b8f-49d57213872b/image.png" alt="">
그러면 root 파일에 pillSolution.mv.db 파일이 생기는데, 이가 생겼는지 한 번 확인후 연결을 끊어줍니다.</p>
<h2 id="4-이후-접속">4. 이후 접속</h2>
<p><img src="https://velog.velcdn.com/images/seasame_oil/post/956bc621-f7fd-40c0-97f1-6c018e50b475/image.png" alt=""></p>
<pre><code>jdbc:h2:tcp://localhost/~/(DB명)
//ex. jdbc:h2:tcp://localhost/~/pillSolution</code></pre><p>이후부터는 위와 같이 접속해서 사용하면 됩니다.</p>
<h2 id="5-springboot-연결">5. SpringBoot 연결</h2>
<p>application.yml에 다음과 같이 설정한 후 사용하시면 됩니다. jpa도 사용하신다면 아래와 같이 추가적으로 설정해주시면 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/seasame_oil/post/ee16691c-14ab-41d6-8cb2-bf469da12a87/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[4장 - 프로그램의 구조와 실행]]></title>
            <link>https://velog.io/@seasame_oil/4%EC%9E%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%98-%EA%B5%AC%EC%A1%B0%EC%99%80-%EC%8B%A4%ED%96%89</link>
            <guid>https://velog.io/@seasame_oil/4%EC%9E%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%98-%EA%B5%AC%EC%A1%B0%EC%99%80-%EC%8B%A4%ED%96%89</guid>
            <pubDate>Thu, 10 Nov 2022 14:10:44 GMT</pubDate>
            <description><![CDATA[<h2 id="1-프로그램의-구조와-인터럽트">1. 프로그램의 구조와 인터럽트</h2>
<p>프로그램이 CPU에서 명령을 수행하려면 해당 명령을 담은 프로그램의 주소 영역이 메모리에 올라가 있어야 함</p>
<p>프로그램의 주소 영역 = 코드(code) 영역 / 데이터(data) 영역 / 스택(stack) 영역</p>
<p>코드 영역 : 작성한 프로그램 함수들의 코드가 CPU에서 수행할 수 있는 기계어 명령 형태로 변환되어 저장 됨</p>
<p>데이터 영역 : 전역 변수 등 프로그램이 사용하는 데이터를 저장하는 부분</p>
<p>스택 영역 : 함수가 호출될 때 호출된 함수의 수행을 마치고 복귀할 주소 및 데이터를 임시로 저장하는 데 사용되는 공간</p>
<p>프로그램 내에서 발생되는 함수호출에 필요한 복귀 주소는 각 프로그램의 주소 공간 중 스택 영역에 보관</p>
<p>인터럽트 때문에 CPU를 빼앗긴 위치는 운영체제가 관리하는 프로세스 제어블록에 저장</p>
<p>(인터럽트가 발생한 시점에서 그 프로그램의 어느 부분까지 수행했는지를 저장)</p>
<p>인터럽트 처리 후 프로세스 제어블록에 저장된 주소를 복원 → 수행하던 일 재개</p>
<h2 id="2-컴퓨터-시스템의-작동-개요">2. 컴퓨터 시스템의 작동 개요</h2>
<p>프로그램 카운터(program counter:PC) : CPU가 수행해야 할 메모리 주소를 담고 있는 레지스터</p>
<p>CPU는 매번 프로그램 카운터가 가리키는 메모리 위치의 명령 처리</p>
<p>CPU에서 명령 수행 + 컴퓨터 외부장치와 입출력 이루어짐</p>
<p>하드웨어(CPU와 메모리) + 입출력 장치별(입출력 컨트롤러와 버퍼)</p>
<p>✔️ 커널모드, 운영자 모드, 특권 명령</p>
<p><a href="https://velog.io/@seasame_oil/3%EC%9E%A5-%EC%BB%B4%ED%93%A8%ED%84%B0-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%98-%EB%8F%99%EC%9E%91%EC%9B%90%EB%A6%AC">3장 - 컴퓨터 시스템의 동작원리</a></p>
<p>시스템 콜(system call) : 운영체제에게 특권명령의 대행을 요청</p>
<p>사용자 프로그램이 시스템 콜을 할 시, 운영체제는 사용자 프로그램의 코드가 아닌 커널 영역에 정의된 시스템 콜 처리 코드를 사용하게 됨</p>
<p>인터럽트를 사용해 CPU에게 서비스를 요청하기 때문에 주변 장치는 인터럽트 라인(interrupt line)을 세팅하고 CPU는 매번 명령을 수행한 후 인터럽트 라인을 체크해 서비스 요청이 들어왔는지 확인</p>
<h2 id="3-프로그램의-실행">3. 프로그램의 실행</h2>
<p>프로그램의 실행</p>
<p>1) 디스크에 존재하던 실행 파일이 메모리에 적재</p>
<p>2) 프로그램이 CPU를 할당받고 명령(instruction)을 수행하고 있는 상태</p>
<p>프로그램의 주소 공간 중 당장 CPU에 필요한 부분은 메모리에 올려둠</p>
<p>그렇지 않은 부분은 스왑 영역에 내려놓음</p>
<p>✅ 스왑 영역 : 디스크 중 메모리의 연장 공간</p>
<p>커널 역시 코드, 데이터, 스택의 주소 공간 구성 가짐</p>
<p>데이터 : 각종 자원을 관리하기 위한 자료구조 저장</p>
<p>하드웨어 자원을 관리하는 자료구조 + 현재 수행 중인 프로그램(프로세스:process)을 관리하기 위한 자료구조</p>
<p>각 프로세스의 상태, CPU 사용 정보, 메모리 사용 정보 등을 유지하기 위한 자료구조(PCB) 두고 있음</p>
<p>스택 : 함수호출 시의 복귀 주소를 저장하기 위한 용도로 사용</p>
<p>❗현재 수행 중인 프로세스마다 별도의 스택을 두어 관리</p>
<p>→ 프로세스가 특권 명령을 수행하려고 커널에 정의된 시스템 콜을 호출하고 시스템 콜 내부에서 다른 함수를 호출하는 경우 그 복귀 주소는 커널 내의 주소가 되어 사용자 프로그램의 스택과는 별도의 저장공간이 필요하게 되기 때문</p>
<p>→ 커널은 일종의 공유 코드이기 때문에, 일관성 유지를 위해 각 프로세스마다 커널 내에 별도의 스택을 둠</p>
<p>⇒ 자기 자신의 코드 내에서 함수호출 및 복귀 주소를 유지하기 위해서는 자기 주소 공간 내의 스택을 사용, 시스템 콜이나 인터럽트 등으로 운영체제의 코드가 실행되는 중에 함수호출이 발생할 경우 커널 스택을 사용하게 됨</p>
<p>❗CPU의 수행주체가 운영체제로 바뀌는 순간에는 직전에 수행되는 프로그램의 복귀 정보를 스택이 아닌 PCB에 저장함</p>
<h2 id="4-사용자-프로그램이-사용하는-함수">4. 사용자 프로그램이 사용하는 함수</h2>
<p>1) 사용자 정의 함수 : 프로그래머 본인이 직접 작성한 함수</p>
<p>2) 라이브러리 함수 : 누군가 작성해놓은 함수를 호출만 하여 사용하는 함수</p>
<p>⇒ 두 함수 모두 그 프로그램의 코드 영역에 기계어 명령 형태로 존재함</p>
<p>3) 커널함수 : 운영체제 커널의 코드에 정의된 함수</p>
<p>1️⃣ 시스템 콜 함수 : 사용자 프로그램이 운영체제의 서비스를 요청하기 위해 호출하는 함수</p>
<p>2️⃣ 인터럽트 처리 함수 : 각종 하드웨어 및 소프트웨어가 CPU를 요청하기 위해 발생시키는 함수</p>
<p>⇒ 운영체제 내에 있는 함수를 사용자 프로그램이 호출해서 사용하는 것</p>
<h2 id="5-인터럽트">5. 인터럽트</h2>
<p>현재 수행 중인 프로세스로부터 CPU를 회수해 CPU가 다른 일을 수행하도록 하기 위해서는 인터럽트 메커니즘이 필요</p>
<p>❓인터럽트 처리 중에 또 다른 인터럽트가 발생하는 경우</p>
<p>원칙적으로는 데이터 일관성 유지 문제 때문에 인터럽트 처리 중에 또 다른 인터럽트가 발생하는 것을 허용하지 X</p>
<p>그러나, 인터럽트의 중요도에 따라 이를 허용하기도 함</p>
<h2 id="6-시스템-콜">6. 시스템 콜</h2>
<p>함수 호출이긴하지만 자신의 주소 공간을 거스르는 영역에 존재하는 함수를 호출하는 것</p>
<p>= 커널의 주소공간에 존재하는 함수를 호출하는 것</p>
<p>✏️ 프로그램이 CPU를 할당받고 명령 수행 중 CPU를 빼앗기는 경우</p>
<p>1) 타이머에 의해 인터럽트 발생</p>
<p>타이머 : 특정 프로그램에 의해 CPU가 독점되는 것을 방지하기 위한 하드웨어</p>
<p>CPU 할당 시간이 완료되면 인터럽트 발생</p>
<p>시분할 시스템 구현을 위한 필수적인 요소</p>
<p>2) 입출력 요청을 위해 시스템 콜을 하는 경우</p>
<p>시간이 오래 걸리는 입출력 작업이 완료되기 전까지 CPU를 다른 프로세스에 이양</p>
<p>입출력이 완료된 후 컨트롤러가 인터럽트를 발생시킨 후부터 다시 CPU를 얻을 수 있는 자격 부여 받음</p>
<h2 id="7-프로세스의-두-가지-실행-상태">7. 프로세스의 두 가지 실행 상태</h2>
<p>1) 사용자 모드에서의 실행상태(user mode runnning)</p>
<p>사용자 정의함수나 라이브러리 함수 호출 시</p>
<p>2) 커널모드에서의 실행 상테(kenel mode running)</p>
<p>커널모드로 진입해 커널의 주소 공간에 정의된 함수를 실행하는 경우</p>
<p>❗️시스템 콜을 통해 실행되는 것이 프로세스 A의 코드가 아닌 운영체제 커널의 코드이지만, 시스템 콜이 수행되는 동안 프로세스 A가 실행상태에 있다고 말함</p>
<p>→ 사실상 커널이 프로세스 A가 해야할 일을 대행하고 있는 것이기 때문</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring]Spring bean 개념과 생성 원리]]></title>
            <link>https://velog.io/@seasame_oil/Spring-bean</link>
            <guid>https://velog.io/@seasame_oil/Spring-bean</guid>
            <pubDate>Thu, 03 Nov 2022 11:54:22 GMT</pubDate>
            <description><![CDATA[<h1 id="스프링-빈spring-bean이란">스프링 빈(Spring Bean)이란?</h1>
<p>Spring IoC 컨테이너가 관리하는 자바 객체
Spring에서는 직접 new를 이용하여 생성한 객체가 아니라, 필요한 객체를 생성하고 생성한 객체에 의존을 주입한다. Spring에 의하여 생성되고 관리되는 자바 객체를 Bean이라 한다.</p>
<p>new 연산자로 어떤 객체를 생성한 것은 빈이 아님
ApplicationContext.getBean()으로 얻어질 수 있는 객체가 빈</p>
<blockquote>
<p>✔️ 제어의 역전(Inversion of Control)이란?
일반적으로 처음에 배우는 자바 프로그램에서는 각 객체들이 프로그램의 흐름을 결정하고 각 객체를 직접 생성하고 조작하는 작업을 한다.
(즉, 모든 작업을 사용자가 제어한다.)</p>
</blockquote>
<pre><code>public class Student {
    private int age;
    private String name;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}</code></pre><pre><code>Student student = new Student(&quot;Tom&quot;, 22);</code></pre><blockquote>
<p>하지만, IoC가 적용된 경우 객체를 사용자가 직접 생성하지 않고, 객체의 생명주기를 Spring IoC 컨테이너가 컨트롤 하도록 한다.</p>
</blockquote>
<h1 id="spring-bean-사용-이유">Spring Bean 사용 이유</h1>
<p>스프링에서는 각각의 자바 클래스들이 의존관계를 가지고 있다.
MVC 구조에 따라 설계를 하면, 먼저 Model 클래스를 만들고, Model 객체를 담는 Repository 클래스를 구현한다. 또한 Repository에 인덱싱하기 위한 Service 클래스, Service를 통해 Model이 담겨 있는 Repository에 접근하기 위한 Controller 클래스가 있다.</p>
<p>웹 프로그래밍은 멀티유저에 대한 동시성 제어가 중요하기 때문에 이를 위해 스프링 컨테이너에서는 싱글톤 패턴으로 관리한다.</p>
<blockquote>
<p>✔️ 싱글톤패턴(Singleton Pattern) 이란?
객체의 인스턴스가 오직 1개만 생성되는 패턴
생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이며 이후에 호출된 생성자는 최초의 생성자가 객체를 리턴하는 것</p>
</blockquote>
<p>자주 사용하는 객체를 싱글톤 패턴으로 생성해 둔 후, 필요할 때 언제든 사용 가능하다.
즉, 매번 요청 시마다 빈 객체를 생성하는 것보다 한 번 생성해 둔 후 사용하는 것이 서버의 성능에 훨씬 좋기 때문에 사용한다.</p>
<p>또한 의존성 주입과 라이프사이클 관리에도 용이하기에 빈을 등록하여 사용한다.</p>
<h1 id="spring-bean을-spring-ioc-container에-등록하는-방법">Spring Bean을 Spring IoC Container에 등록하는 방법</h1>
<h2 id="1-자바-어노테이션java-annotation을-사용하는-방법">1) 자바 어노테이션(Java Annotation)을 사용하는 방법</h2>
<h3 id="ㄱ-componentscan">ㄱ) @ComponentScan</h3>
<p>어느 지점부터 컴포넌트를 찾으라고 알려주는 역할이다.
@ComponentScan이 붙어있는 클래스가 있는 패키지에서부터 모든 하위 패키지의 모든 클래스를 훑어 보며 @Component이 붙은 클래스를 찾는다.</p>
<h3 id="ㄴ-component">ㄴ) @Component</h3>
<p>자동으로 스프링 빈으로 등록됨
@Controller, @Service, @Repository 들은 @Component를 포함하고 있다.</p>
<h2 id="2-빈-설정파일bean-configuration-file에-직접-bean-등록하는-방법">2) 빈 설정파일(Bean Configuration File)에 직접 Bean 등록하는 방법</h2>
<p>자바 클래스를 생성해서 작성 가능(일반적으로 xxxConfiguration으로 명명)</p>
<pre><code>@Configuration
public class SpringConfig {

    @Bean
    public MemberService memberService() {
        return new MemberService();
    }
}</code></pre><p>@Configuration 안에 @Component를 사용하기 때문에 @ComponentScan의 스캔 대상이 된다.
그에 따라 빈 설정 파일이 읽힐 때 그 안에 정의된 빈들이 IoC 컨테이너에 등록된다.</p>
<h1 id="의존관계-설정">의존관계 설정</h1>
<p>스프링 빈을 등록한다고 해서 의존관계가 설정되는 것은 아니고, 싱글톤 객체로 생성되어 관리되는 클래스들의 의존관계를 설정해주어야 한다.</p>
<h2 id="1-자동-의존관계">1) 자동 의존관계</h2>
<p>컴포넌트 스캔을 통해 스프링 빈을 등록했을 경우, 클래스 생성자에 @Autowired를 명시해주면 된다.</p>
<pre><code>@Service
public class MemberService {

    private final MemberRepository memberRepository;

    @Autowired
    public MemberService(MemberRepository memberRepository) {
        this.memberRepostiory = memberRepository;
    }

    //이후 서비스 관련 코드
    ...
}</code></pre><h2 id="2-수동-의존관계">2) 수동 의존관계</h2>
<p>Configuration을 통해 직접 빈을 등록할 경우, 실제 클래스의 구현된 생성자의 형태와 동일하게 Configuration에서도 객체를 리턴해주면 된다.</p>
<pre><code>@Configuration
public class SpringConfig {

    @Bean
    public MemberService memberService() {
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepostiory() {
        return new MemberRepository();
    }
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[3장 - 컴퓨터 시스템의 동작원리]]></title>
            <link>https://velog.io/@seasame_oil/3%EC%9E%A5-%EC%BB%B4%ED%93%A8%ED%84%B0-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%98-%EB%8F%99%EC%9E%91%EC%9B%90%EB%A6%AC</link>
            <guid>https://velog.io/@seasame_oil/3%EC%9E%A5-%EC%BB%B4%ED%93%A8%ED%84%B0-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%98-%EB%8F%99%EC%9E%91%EC%9B%90%EB%A6%AC</guid>
            <pubDate>Mon, 24 Oct 2022 16:34:04 GMT</pubDate>
            <description><![CDATA[<h2 id="1-컴퓨터-시스템의-구조">1. 컴퓨터 시스템의 구조</h2>
<p>컴퓨터 내부장치 : CPU, 메모리</p>
<p>컴퓨터 외부장치(입출력 장치) : 디스크, 키보드, 마우스, 모니터, 네트워크 장치 등</p>
<p>컴퓨터 내부로 데이터가 들어오는 것 = 입력(input)</p>
<p>컴퓨터 외부로 데이터가 나가는 것 = 출력(output)</p>
<p>컨트롤러 : 일종의 작은 CPU / 각 하드웨어 장치마다 존재하면서 이들을 제어</p>
<p>커널(kernel) : 항상 메모리에 올라가 있는 부분 (전체 운영체제 중 핵심적인 부분)</p>
<h2 id="2-cpu-연산과-io-연산">2. CPU 연산과 I/O 연산</h2>
<p>입출력 장치들의 I/O 연산 - 입출력 컨트롤러가 담당, 컴퓨터 내에서 수행되는 연산 - 메인 CPU 담당</p>
<p>로컬 버퍼(local buffer) : 각 장치를 제어하기 위해 설치된 장치 컨트롤러라는 장치로부터 들어오고 나가는 데이터를 임시로 저장하기 위한 작은 메모리</p>
<p>CPU는 매 시점 메모리에서 명령(instruction)을 하나씩 읽어와서 수행</p>
<p>작업을 하던 중 인터럽트 라인(interrupt line)에 신호가 들어오면 하던 일을 멈추고 인터럽트와 관련된 일을 먼저 처리</p>
<p>⇒ 명령을 하나 처리할 때마다 인터럽트가 발생했는지 확인</p>
<h2 id="3-인터럽트의-일반적-기능">3. 인터럽트의 일반적 기능</h2>
<p>운영체제 커널 내에 있는 인터럽트 처리루틴은 다양한 인터럽트에 대해 각각 처리해야 할 업무들을 정의함</p>
<p>ex. 디스크 컨트롤러가 인터럽트 발생시킬 경우</p>
<p>CPU는 하던 일을 멈추고 인터럽트 발생시 실행시킬 코드를 찾아 수행</p>
<p>수행 하는 일 : 디스크의 로컬 버퍼에 있는 내용을 사용자 프로그램의 메모리로 전달하고, 해당 프로그램이 CPU를 할당받을 경우 다음 명령을 수행할 수 있음을 표시하는 일</p>
<p>하드웨어 인터럽트 : 하드웨어 장치가 CPU의 인터럽트 라인을 세팅</p>
<p>소프트웨어 인터럽트 : 소프트웨어가 CPU의 인터럽트 라인을 세팅</p>
<p>⇒ 인터럽트 라인에 신호를 보내서 인터럽트가 발생했음을 알려주는 방식은 둘 다 동일</p>
<p>인터럽트 벡터(interrupt vector) : 인터럽트 종류마다 번호를 정해서, 번호에 따라 처리해야 할 코드가 위치한 부분을 가리키고 있는 자료구조</p>
<p>인터럽트 처리 루틴(interrupt service routine), 인터럽트 핸들러(interrupt handler) : 실제 처리해야 할 코드</p>
<p>소프트웨어 인터럽트(트랩, trap)</p>
<ul>
<li>예외상황(exception)</li>
</ul>
<p>비정상적인 작업을 시도하거나 권한이 없는 작업을 시도할 때 발생</p>
<ul>
<li>시스템 콜(system call)</li>
</ul>
<p>사용자 프로그램이 운영체제 내부에 정의된 코드를 실행하고 싶을 때 운영체제에 서비스를 요청하는 방법</p>
<h2 id="4-인터럽트-핸들링">4. 인터럽트 핸들링</h2>
<p>인터럽트 핸들링(interrupt handling) : 인터럽트가 발생한 경우에 처리해야 할 일의 절차</p>
<p>프로세스 제어 블록(Process Control Block: PCB) : 각각의 프로그램마다 하나씩 존재하며 해당 프로그램의 어느 부분이 실행 중이었는지를 저장</p>
<p>→ 실행 중이던 코드의 메모리 주소, 레지스터 값, 하드웨어 상태 등이 저장</p>
<p>오늘날의 컴퓨터 운영체제는 인터럽트가 발생할 때만 실행됨</p>
<h2 id="5-입출력-구조">5. 입출력 구조</h2>
<p>입출력 : 컴퓨터 시스템이 컴퓨터 외부의 입출력 장치들과 데이터를 주고받는 것</p>
<p>*CPU의 명령 수행 속도는 빠르지만 입출력 장치에서 데이터를 읽어오는 등의 입출력 연산은 상대적으로 느림</p>
<p>1) 동기식 입출력</p>
<p>입출력이 진행되는 동안 그 프로그램의 다음 명령을 수행하지 않고 기다림</p>
<p>입출력이 완료되어 인터럽트 통제 사실이 전달된 후에야 CPU의 제어권이 그 프로그램에게 넘어가서 다음 명령 수행 가능</p>
<p>✔️ CPU는 입출력 연산이 끝날 때 까지 인터럽트를 기다리며 자원 낭비</p>
<p>다른 프로그램에게 CPU를 양도하지 않고 입출력 연산이 완료될 때까지 기다린다면, 매 시점 하나의 입출력 연산이 실행</p>
<p>입출력이 실행되는 동안 다른 프로그램에게 CPU를 양도하면, 동시에 다수의 입출력 연산 가능</p>
<p>✔️ 다수의 입출력이 진행될 경우, 명령 수행 순서가 바뀔수 있음</p>
<p>입출력 요청의 동기화를 위해 장치별로 큐(queue)를 두어 요청한 순서대로 처리할 수 있도록 함</p>
<p>연산 완료의 통보는 인터럽트를 통해 수행</p>
<p>운영체제 커널은 인터럽트 처리루틴으로 가서 해당 프로그램의 상태를 봉쇄 상태로부터 해제</p>
<p>2) 비동기식 입출력</p>
<p>CPU의 제어권을 입출력 연산을 호출한 그 프로그램에게 다시 부여</p>
<p>데이터와 관련 없이 수행 할 수 있는 일은 먼저 수행하고, 읽어오(쓰)는 데이터가 있어야 수행 가능한 일은 입출력이 완료된 후에 수행하게 됨</p>
<p>인터럽트를 통해 입출력 완료 여부를 알려줌</p>
<h2 id="6-dma">6. DMA</h2>
<p>원칙적으로 메모리는 CPU에 의해서만 접근 가능함</p>
<p>CPU 외의 장치가 메모리 데이터에 접근하기 위해서는 CPU에 인터럽트를 발생시켜 CPU가 이를 대행해야 함</p>
<p>메모리 접근 연산이 CPU에 의해서만 진행되면 연산 처리 속도 및 효율성이 떨어짐</p>
<p>이를 극복하기 위해 CPU 이외에 메모리 접근이 가능한 장치를 하나 더 둠</p>
<p>DMA(Direct Memory Access)</p>
<p>: 일종의 컨트롤러, CPU가 입출력 장치들의 메모리 접근 요청에 의해 자주 인터럽트 당하는 것을 막아 줌</p>
<p>DMA는 바이트(byte) 단위가 아니라 블록(block) 단위로 메모리 읽어 옴 → CPU에 인터럽트 발생시켜 해당 작업의 완료 알림</p>
<h2 id="7-저장장치의-구조">7. 저장장치의 구조</h2>
<p>1) 주기억장치 (메모리)</p>
<p>대부분 전원이 나가면 저장되었던 내용이 모두 사라져버리는 휘발성의 RAM을 매체로 사용함</p>
<p>2) 보조기억장치</p>
<p>주로 전원이 나가도 저장된 내용을 기억할 수 있는 비휘발성의 마그네틱 디스크를 주로 사용</p>
<p>① 파일 시스템용 (file system)</p>
<p>전원이 나가도 유지해야 할 정보가 있으면 그것을 파일 형태로 보조기억 장치에 저장</p>
<p>디스크를 파일 시스템용으로 사용</p>
<p>② 스왑 영역 (swap area)</p>
<p>메모리의 연장 공간 (하드디스크가 가장 널리 이용)</p>
<p>프로그램 수행에 당장 필요한 부분만 메모리에 올려놓고 그렇지 않은 부분은 디스크 스왑 영역에 내려 놓음</p>
<p>스왑 아웃(swap out) : 디스크에 내려놓는 일</p>
<ul>
<li>하드디스크 물리적 구조</li>
</ul>
<p>여러개의 마그네틱 원판들이 존재하고, 암(arm)이 이동하며 원판에 저장된 데이터를 읽고 쓰는 방식으로 동작</p>
<p>디스크 원판의 표면은 트랙(track)으로 나뉘고, 각 트랙은 섹터(sector)로 나뉨</p>
<p>섹터에 최소한의 단위 정보 저장됨</p>
<h2 id="8-저장장치의-계층-구조">8. 저장장치의 계층 구조</h2>
<p>빠른 저장장치부터 느린 저장장치까지 단계적인 계층구조로 이루어짐</p>
<p>빠른 저장장치 : 단위 공간 당 가격이 높음, 적은 용량 사용</p>
<p>느린 저장장치 : 가격이 저렴하여 대용량으로 사용, 접근 속도가 느림</p>
<ul>
<li>Primary(Excuatable)</li>
</ul>
<p>CPU 내부에 존재</p>
<p>레지스터(register), 캐시 메모리(cache memory), 메인 메모리(main memory)</p>
<p>휘발성 저자장치로 구성 됨</p>
<ul>
<li>Secondary</li>
</ul>
<p>전원이 나가도 지워지지 않는 비휘발성 저장장치</p>
<p>당장 필요한 정보만을 선별적으로 저장하면 성능 좋음</p>
<ul>
<li>캐싱 기법 : 상대적으로 용량이 적은 빠른 저장장치를 이용해 느린 저장장치의 성능을 향싱시키는 기법</li>
</ul>
<h2 id="9-하드웨어의-보안">9. 하드웨어의 보안</h2>
<p>다중 프로그래밍 환경에서 동작함</p>
<p>각 프로그램이 다른 프로그램의 실행을 방해하거나 프로그램 간의 충돌을 일으키는 문제를 막기 위해 하드웨어에 대한 보안 기법 필요</p>
<p>1) 커널 모드(kernel mode, system mode) : CPU의 제어권을 가지고 운영체제 코드를 실행하는 모드 → 모든 종류의 명령 실행 가능</p>
<p>2) 사용자 모드(user mode) : 일반 사용자 프로그램 실행 → 제한적인 명령만 수행 가능</p>
<ul>
<li>모드비트(mode bit)</li>
</ul>
<p>0으로 세팅되어 있으면 커널모드로서 모든 명령 수행할 수 있음</p>
<p>1로 세팅되어 있으면 사용자모드로서 제한된 명령 수행할 수 있음</p>
<p>CPU는 보안과 관련된 명령을 수행하기 전에는 항상 모드비트 조사 후 수행</p>
<p>인터럽트가 발생할 때 모드비트는 자동으로 0 세팅</p>
<p>요청된 작업이 모두 끝난 후에는 모드비트를 다시 1로 만들어 사용자 프로그램에게 CPU 넘겨 줌</p>
<p>특권 명령 : 시스템의 보안과 관련된 명령들 / 모드비트가 0 일때 = 커널모드에서 운영체제에 의해서만 수행 가능</p>
<p>하드웨어 장치에서 보안이 유지되는 방식</p>
<p>⇒ 모든 입출력 명령은 특권명령으로 규정해서 사용자 프로그램이 직접 입출력하는 것 차단</p>
<p>(입출력이 필요한 경우, 운영체제가 입출력 명령 대신 수행)</p>
<p>사용자 프로그램이 입출력을 하고 싶으면 시스템 콜로 운영체제에 요청해야 함</p>
<h2 id="10-메모리-보안">10. 메모리 보안</h2>
<p>하나의 사용자 프로그램이 다른 사용자 프로그램이나 운영체제가 위치한 메모리 영역을 침범할 수 있기에 보안 필요</p>
<p>적어도 인터럽트 벡터와 인터럽트 처리루틴이 있는 곳은 각별한 보안이 필요</p>
<p>(사용자 프로그램이 인터럽트 처리루틴을 접근하거나 변경할 수 있을 경우, 특권명령을 보안성이 침해되는 명령으로 변형할 수 있기 때문)</p>
<p>2개의 레지스터를 사용해 프로그램이 접근하려는 메모리 부분의 합법성 체크</p>
<p>1) 기준 레지스터(base register)</p>
<p>: 어떤 프로그램이 수행되는 동안 그 프로그램이 합법적으로 접근 가능한 메모리상의 가장 작은 주소 보관</p>
<p>2) 한계 레지스터(limit register)</p>
<p>: 프로그램이 기준 레지스터값부터 접근할 수 있는 메모리의 범위 보관</p>
<p>⇒ 어떤 프로그램이 실제 메모리에 올라가 있는 부분의 시작 주소와 그 프로그램의 길이</p>
<p>접근하려는 주소가 기준 레지스터+한계 레지스터 밖이면 불법적인 메모리 접근 → 인터럽트 발생</p>
<p>(이후 paging 기법에 대해서도 살펴볼 예정)</p>
<ul>
<li><p>메모리 접근 연산 - 사용자 프로그램이 CPU를 가지고 있는 동안 수행 할 수 있는 연산(특권 명령 X)</p>
<p>  운영체제만이 수행할 수 있는 입출력 연산 - 커널모드에서만 수행 할 수 있는 연산(특권 명령 O)</p>
</li>
<li><p>사용자모드의 경우 - 기준 레지스터와 한계 레지스터를 사용하여 메모리 보호</p>
<p>  커널모드의 경우 - 메모리에 무제한으로 접근 가능</p>
</li>
</ul>
<p>⇒ 운영체제가 2개의 레지스터값을 직접 세팅해주고 사용자 프로그램은 값을 변경할 수 없게 함.</p>
<h2 id="11-cpu-보호">11. CPU 보호</h2>
<p>CPU가 하나의 프로그램에 의해 독점되는 것을 막기 위해 타이머(timer)라는 하드웨어를 사용</p>
<p>→ 정해진 시간이 지나면 인터럽트를 발생시켜 운영체제가 CPU의 제어권을 획득할 수 있도록 함</p>
<p>일정한 시간 단위로 세팅될 수 있으며, 매 클럭 틱(clock tick) 당 1씩 감소</p>
<p>0이 되는 순가 인터럽트 발생</p>
<p>→ 시분할 시스템에서 현재 시간을 계산하기 위해서도 사용</p>
<p>로드 타이머(load timer) : 타이머의 값을 세팅하는 명령(특권 명령)</p>
<p>시분할 시스템 : 여러 프로그램이 CPU의 시간을 조금씩 나누어 사용하는 시스템</p>
<h2 id="12-시스템-콜을-이용한-입출력-수행">12. 시스템 콜을 이용한 입출력 수행</h2>
<p>입출력 명령은 운영체제 코드에 구현되어 있으며, 사용자 프로그램은 운영체제에 시스템 콜이라는 서비스 대행 요청을 하여 입출력 수행</p>
<p>시스템 콜 : 소프트웨어적인 인터럽트</p>
<p>→ 사용자 프로그램이 시스템 콜을 할 경우 트랩이 발생해 CPU의 제어권이 운영체제로 넘어감</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2장 - 운영체제 개요]]></title>
            <link>https://velog.io/@seasame_oil/2%EC%9E%A5-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EA%B0%9C%EC%9A%94</link>
            <guid>https://velog.io/@seasame_oil/2%EC%9E%A5-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EA%B0%9C%EC%9A%94</guid>
            <pubDate>Sat, 22 Oct 2022 06:18:01 GMT</pubDate>
            <description><![CDATA[<h2 id="1-운영체제의-정의">1. 운영체제의 정의</h2>
<p>운영체제(operating system) : 하드에어 바로 윗단에 설치되는 소프트웨어</p>
<p>→ 하드웨어가 운영체제와 한 몸이 되어야만 사용자에게 쓰일 수 있는 시스템이 됨</p>
<p>운영체제 중 필요한 부분만을 전원이 켜짐과 동시에 메모리에 올려놓고 그렇지 않은 부분은 필요할 때 메모리로 올려서 사용</p>
<ul>
<li>커널(kernel) : 메모리에 상주하는 운영체제의 부분</li>
</ul>
<h2 id="2-운영체제의-기능">2. 운영체제의 기능</h2>
<p>1) 하드웨어를 위한 역할 : 하드웨어를 운영체제가 관리</p>
<p>= 컴퓨터 시스템 내의 자원(resource)을 효율적으로 관리</p>
<p>자원관리자(resource manager)라고도 불림</p>
<p>자원 = 하드웨어 자원 (CPU, 메모리, 하드디스크 등) + 소프트웨어 자원</p>
<p>2) 사용자를 위한 역할 : 인터페이스 제공</p>
<p>= 시스템을 편리하게 사용할 수 있는 환경 제공</p>
<p>3) 컴퓨터 시스템 내의 자원을 효율적으로 관리</p>
<p>4) 사용자와 운영체제 자신을 보호하는 역할</p>
<h2 id="3-운영체제의-분류">3. 운영체제의 분류</h2>
<p>✔️동시 작업을 지원하는지의 여부</p>
<p>1) 단일작업(single tasking)</p>
<p>한 번에 하나의 프로그램만 실행시킬 수 있음 (주로 초창기 운영체제)</p>
<p>ex. 도스(Disk Operating System : DOS)</p>
<p>2) 다중작업(multi tasking)</p>
<p>ex. MS 윈도우, 유닉스</p>
<p>시분할 시스템(time sharing system) : CPU의 작업시간을 여러 프로그램들이 조금씩 나누어서 쓰는 시스템 </p>
<p>다중 프로그래밍 시스템(multi-programming system) : 메모리 공간을 분할해 여러 프로그램들을 동시에 올려놓고 처리하는 시스템</p>
<p>대화형 시스템(interactive system) : 사용자 개개인의 관점에서는 각 프로그램에 대한 결과를 곧바로 화면에 나타내는 시스템</p>
<p>다중처리기 시스템(multi-processor system) : 하나의 컴퓨터 안에 CPU가 여러 개 설치된 경우</p>
<p>✔️다중 사용자에 대한 동시 지원 여부</p>
<p>1) 단일 사용자용 운영체제 : 한 번에 한 명의 사용자만이 사용하도록 허용하는 운영체제</p>
<ul>
<li>한 번에 하나의 작업만 수행 가능한 경우</li>
<li>다중작업이 가능한 경우</li>
</ul>
<p>2) 다중 사용자용 운영체제 : 여러 사용자가 동시에 접속해 사용할 수 있게 하는 운영체제 ex. 서버</p>
<p>✔️작업을 처리하는 방식</p>
<p>1) 일괄처리(batch processing) 방식 : 요청된 작업을 일정량씩 모아서 한번에 처리하는 방식</p>
<p>처리해야할 여러 작업들을 일정량 모아 일괄적으로 처리하고, 모든 작업이 완전히 종료된 후에 결과 얻을 수 있음</p>
<p>⇒ 응답시간이 김</p>
<p>ex. 펀치 카드 처리 시스템</p>
<p>2) 시분할 방식 : 컴퓨터의 처리 능력을 일정한 시간 단위로 분할해 사용하는 방식</p>
<p>⇒ 일괄처리 방식에 비해 짧은 응답시간 가짐</p>
<p>⇒ 대화형 시스템(사용자의 요청에 대한 결과를 곧바로 얻을 수 있는 시스템)</p>
<p>3) 실시간(real time) 운영체제 : 정해진 시간 안에 어떠한 일이 반드시 처리됨을 보장해야 하는 시스템</p>
<p>ex. 원자로, 공장제어 시스템, 미사일 제어 시스템</p>
<ul>
<li>경성 실시간 시스템(hard realtime system) : 주어진 시간을 지키지 못할 경우 매우 위험한 결과 초래 가능</li>
<li>연성 실시간 시스템(soft realtime system) : 데이터가 정해진 시간 단위로 전달되어야 올바른 기능 수행 가능</li>
</ul>
<h2 id="4-운영체제의-예">4. 운영체제의 예</h2>
<h2 id="5-운영체제의-자원-관리-기능">5. 운영체제의 자원 관리 기능</h2>
<p>운영체제의 핵심적인 기능 = 자원을 효율적으로 관리하는 것</p>
<p>자원 = 하드웨어 자원 + 소프트웨어 자원</p>
<p>1) 하드웨어 자원</p>
<p>CPU 스케쥴링 : 어떤 프로그램에 CPU를 줄 것인가?</p>
<p>메모리 관리 : 한정된 메모리를 어떻게 나누어 사용할 것인가?</p>
<p>파일 관리 : 디스크에 파일을 어떻게 보관할 것인가?</p>
<p>입출력 관리 : 각기 다른 입출력 장치와 컴퓨터 간에 어떻게 정보를 주고받을 것인가?</p>
<p>✔️CPU관리 방법</p>
<p>CPU가 하나밖에 없는 컴퓨터 구조에서도 프로세스는 여러 개가 동시에 수행 될 수 있음</p>
<p>CPU 스케쥴링(CPU scheduling) : 어떤 프로세스에 CPU를 할당하여 작업을 처리할지</p>
<p>→ 가장 효율적으로 사용하면서도 특정 프로세스가 불이익을 당하지 않도록 하는 것</p>
<p>→ 선입선출(First Com First Served: FCFS), 라운드 로빈(Round Robin), 우선순위(proprity)</p>
<ul>
<li>선입선출</li>
</ul>
<p>CPU를 사용하기 위해 도착한 프로세스들 중 먼저 온 것을 먼저 처리</p>
<p>CPU를 필요로하는 프로세스가 여럿 있을 때 CPU를 먼저 얻은 프로세스가 원하는 작업을 완료할 때까지 다른 프로세스들이 CPU를 사용하지 못함</p>
<p>CPU 자체의 효율성 : 나쁘지 않음 / 시스템 전체의 효율성 : 비효율적</p>
<ul>
<li>라운드 로빈</li>
</ul>
<p>CPU를 한 번 할당받아 사용할 수 있는 시간을 일정하게 고정된 시간으로 제한</p>
<p>긴 작업을 요하는 프로세스가 CPU를 할당받더라도 정해진 시간이 지나면 CPU를 내어놓고 CPU 대기열의 제일 뒤에 가서 줄을 서야 함</p>
<ul>
<li>우선순위</li>
</ul>
<p>대기 중인 프로세스들에 우선순위를 부여하고 우선순위가 높은 프로세스에 CPU를 먼저 할당</p>
<p>✔️메모리 관리 방법</p>
<p>메모리 : CPU가 직접 접근할 수 있는 컴퓨터 내부의 기억장치</p>
<p>프로그램이 CPU에서 실행되려면 해당 부분이 메모리에 올라와 있어야 함</p>
<p>주소(address)를 통해 관리됨</p>
<p>프로그램에 메모리가 필요할 때 할당하고, 더 이상 필요하지 않을 때 회수함</p>
<p>→ 고정분할(fixed partition) 방식, 가변분할(variable partition) 방식, 가상메모리(virtual memory) 방식 등</p>
<ul>
<li>고정분할 방식</li>
</ul>
<p>물리적 메모리를 몇 개의 분할로 미리 나누어 관리</p>
<p>나뉜 각각의 분할에는 하나의 프로그램 적재 가능 → 융통성 X</p>
<p>내부조각(internal fragment) : 해당 분할에 올라온 프로그램에 의해서도 사용되지 않고, 다른 프로그램에도 할당될 수 없음 = 비효율적으로 낭비되는 공간</p>
<ul>
<li>가변분할 방식</li>
</ul>
<p>매 시점 프로그램의 크기에 맞게 메모리를 분할해서 사용하는 방식</p>
<p>분할의 크기 때문에 실행이 제한되지는 않지만 물리적 메모리의 크기보다 큰 프로그램의 실행은 불가능</p>
<p>분할의 크기와 개수가 동적</p>
<p>외부조각(external fragment) : 프로그램에 할당되지는 않았지만 그 크기가 작아 프로그램을 올리지 못하는 메모리 영역</p>
<ul>
<li>가상메모리 방식</li>
</ul>
<p>현대 범용 컴퓨터 환경에서 가장 널리 사용되는 메모리 관리 기법</p>
<p>물리적 메모리보다 더 큰 프로그램이 실행되는 것 지원함</p>
<p>가상 메모리의 주솔르 물리적 메모리의 주소로 매핑하여 주소를 변환시킨 후 프로그램을 물리적 메모리에 올림</p>
<p>현재 사용되는 부분만 메모리에 올리고, 나머지는 보조기억장치에 저장해두었다가 필요할 때 적재함</p>
<p>스왑 영역(swap area) : 이 때 이용되는 보조기억장치의 영역</p>
<p>페이징(paging) 기법 : 동일한 단위로 메모리를 나누는 기법 / 가상메모리 주소 공간은 페이지(page)라는 동일한 크기의 작은 단위로 나누어 물리적 메모리와 스왑 영역에 일부분씩 저장됨</p>
<p>✔️주변장치 및 입출력 장치</p>
<p>인터럽트(interrupt)라는 메커니즘을 통해 관리 이루어짐</p>
<p>인터럽트 : CPU의 서비스가 필요한 경우 서비스를 요청하기 위해 발생시키는 신호</p>
<p>CPU는 평소에 스케쥴링에 따라 자기에게 주어진 작업을 수행하다가 인터럽트가 발생하면 하던 일을 잠시 멈추고 인터럽트에 의한 요청 서비스를 수행 함</p>
<p>요청하는 장치와 발생 상황에 따라 다양한 종류가 있음</p>
<p>→ 인터럽트 처리 루틴 : 인터럽트가 발생했을 때 해주어야 할 작업을 정의한 프로그램 코드</p>
<p>컨트롤러(controller) : 주변장치들은 각 장치마다 그 장치에서 일어나는 업무를 관리하기 위한 일종의 작은 CPU</p>
<p>→ 해당 장치에 대한 업무를 처리하고 메인 CPU에 인터럽트를 발생시켜 보고하는 역할을 함</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[1장 - 컴퓨터 및 정보기술의 역사]]></title>
            <link>https://velog.io/@seasame_oil/1%EC%9E%A5-%EC%BB%B4%ED%93%A8%ED%84%B0-%EB%B0%8F-%EC%A0%95%EB%B3%B4%EA%B8%B0%EC%88%A0%EC%9D%98-%EC%97%AD%EC%82%AC</link>
            <guid>https://velog.io/@seasame_oil/1%EC%9E%A5-%EC%BB%B4%ED%93%A8%ED%84%B0-%EB%B0%8F-%EC%A0%95%EB%B3%B4%EA%B8%B0%EC%88%A0%EC%9D%98-%EC%97%AD%EC%82%AC</guid>
            <pubDate>Sat, 22 Oct 2022 06:16:41 GMT</pubDate>
            <description><![CDATA[<h2 id="1-컴퓨터의-선사시대">1. 컴퓨터의 선사시대</h2>
<h3 id="1-이론적인-컴퓨터의-역사">1) 이론적인 컴퓨터의 역사</h3>
<p>컴퓨터의 이론적인 임무 = 숫자의 표현과 처리 방식 고안</p>
<p>튜링머신 : 컴퓨터에 대한 가장 단순하고 매력적인 모델</p>
<p>처치의 가정 : 튜링머신보다 더 처리력이 우수한 컴퓨터 구조는 있을 수 없음</p>
<p>튜링머신의 정지 문제 : 주어진 튜링 머신과 주어진 입력 데이터를 가지고 튜링 머신을 동작시킨 결과, 과연 튜링머신이 처리를 마친 후 정지할 것인지, 아니면 정지하지 않고 끝없이 동작하는 무한루프에 빠질 것인지를 알 수 있는가하는 문제</p>
<p>⇒ 컴퓨터에 어떠한 문제를 적용했을 때 그 문제에 대한 풀이가 유한 시간 내에 이루어질 수 있는가?</p>
<h3 id="2-기계식-컴퓨터의-역사">2) 기계식 컴퓨터의 역사</h3>
<p>19세기 해석기관 ← 최초의 기계식 컴퓨터</p>
<h3 id="3-전자식-컴퓨터의-초기-역사">3) 전자식 컴퓨터의 초기 역사</h3>
<p>20세기 초 최초의 전자식 계산기</p>
<p>콘라트 추제 : 최초의 범용 디지털 컴퓨터 개발 (이진 체계의 디지털컴퓨터)</p>
<p>미국의 존 모클리와 프레스퍼 에커트 : 제2차 세계대전 중 총의 탄도 거리를 정확하게 계산하기 위한 ENIAC (Electrionic Numerical Integrator And Computer)을 개발 → 이후 최초의 현대적 컴퓨터</p>
<h2 id="2-근대적-컴퓨터의-역사">2. 근대적 컴퓨터의 역사</h2>
<p>주로 1940년대 중반부터 이루어진 하드웨어 기술의 발전을 토대로, 제1세대 ~ 제4세대로 분류</p>
<p>제 1세대 - 진공관 기반 컴퓨터</p>
<p>1세대 컴퓨터는 건물 하나의 공간을 가득 차지할 만큼 부피가 크고 가격이 비쌈</p>
<p>부피문제 + 수명 짧음</p>
<p>제 2세대 - 트랜지스터 기반 컴퓨터</p>
<p>벨 연구소에서 트랜지스터 개발</p>
<p>부피가 훨씬 작고 가격 저렴 + 신뢰성 높음</p>
<p>⇒ 프로그래밍의 중요성이 대두되기 시작, 기호에 의해 컴퓨터의 정보를 표현하는 어셈블리(Assembly)언어 등장</p>
<p>포트란(Fortran) 생김</p>
<p>소프트웨어 공학적인 측면 부각 → 구조적 프로그래밍(structured programming) 기법</p>
<blockquote>
<p>구조적 프로그래밍 : 인간이 한 번에 파악하기 힘든 대형 프로그램을 작성할 때 이를 인간이 이해하기 쉬운 단위들로 나누어 각 단위를 독립적으로 프로그래밍하는 기법</p>
</blockquote>
<p>운영체제 개발 시작, 데이터베이스 관리 시스템(Data Base Management System: DBMS) 등장</p>
<p>제 3세대 - 집적회로 기반의 컴퓨터</p>
<p>신뢰성의 향상 : 집적회로로 구성된 컴퓨터는 각 칩이 컴퓨터에 설치되기 전인 제작 단계에서 이미 엄격한 테스트를 거침</p>
<p>크기의 감소 : 하나의 칩은 수백 ~ 수천 개의 트랜지스터 포함</p>
<p>속도, 전력 소모, 발열, 비용 등 다양한 측면에서 트랜지스터 기반 컴퓨터에 비해 장점 가짐</p>
<blockquote>
<p>무어의 법칙 (Moore’s law) : 반도체 집적 회로의 성능이 적어도 20년 동안은 1.5년마다 2배씩 발전할 것</p>
</blockquote>
<p>컴퓨터 하드웨어의 부피 점점 작아짐 + 컴퓨터의 가격 낮아짐 = 개인용 컴퓨터 등장</p>
<p>C언어 개발 / 개발 지원 툴들이 유명해짐, 유닉스 등장</p>
<p>제 4세대 - 고밀도 집적회로 및 초고밀도 집적회로 기반 마이크로컴퓨터</p>
<p>소프트웨어 특면에서 새로운 방법론 많이 등장</p>
<p>객체지향 언어의 성공 → 신뢰성과 재사용성이 높은 소프트웨어 개발 이룸</p>
<h2 id="3-현대의-컴퓨터">3. 현대의 컴퓨터</h2>
<p>범용 컴퓨터 : 임의의 목적으로 사용 가능한 컴퓨터</p>
<p>임베디드 컴퓨터 : 특수한 목적을 위해 각종 장치의 제어용으로 내장되는 컴퓨터</p>
<h3 id="1-슈퍼컴퓨터와-메인프레임-컴퓨터">1) 슈퍼컴퓨터와 메인프레임 컴퓨터</h3>
<p>메인프레임 컴퓨터 : 주로 터미널을 통해 사용하게 됨</p>
<p>시분할(time sharing) 방식 사용</p>
<blockquote>
<p>시분할 방식 : 컴퓨터 처리 능력을 짧은 시간 단위로 구분하고 이를 여러 사용자에게 조금씩 분할 해 서비스하는 방식</p>
</blockquote>
<p>슈퍼컴퓨터 : 메인프레임 컴퓨터보다 처리 능력이 뛰어난 컴퓨터</p>
<p>최근에는 원격으로 사용하고 사용료를 지불하는 새로운 형태의 클라우드 컴퓨팅이 각광받음</p>
<p>가상 머신(virtual machine) : 한 대의 물리적인 컴퓨터를 여러 사용자들이 공유해서 사용할 때 사용자가 느끼는 독자적인 컴퓨터</p>
<p>미니컴퓨터 : 메인프레임 컴퓨터보다는 성능이 느리지만 개인용 컴퓨터보다는 성능이 빠른 컴퓨터</p>
<p>역사 속에서 소멸</p>
<h3 id="2-개인용-컴퓨터">2) 개인용 컴퓨터</h3>
<p>1인 사용자를 위해 만들어진 컴퓨터</p>
<p>워크스테이션 : 10인 이내의 구성원이 공동으로 사용하기에 적절한 컴퓨터</p>
<p>서버 : 네트워크로 연결된 다른 컴퓨터에 서비스를 제공하는 일종의 소프트웨어</p>
<h3 id="3-휴대용-컴퓨터">3) 휴대용 컴퓨터</h3>
<h3 id="4-임베디드-컴퓨터">4) 임베디드 컴퓨터</h3>
<p>기기 내부에 장착되는 형태</p>
<p>각종 기기 내부에 내장되어 그 기능을 향상시키거나 연산, 처리, 전달하는 등의 업무를 담당</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[QueryDsl 생성 및 사용]]></title>
            <link>https://velog.io/@seasame_oil/QueryDsl-%EC%83%9D%EC%84%B1-%EB%B0%8F-%EC%82%AC%EC%9A%A9</link>
            <guid>https://velog.io/@seasame_oil/QueryDsl-%EC%83%9D%EC%84%B1-%EB%B0%8F-%EC%82%AC%EC%9A%A9</guid>
            <pubDate>Mon, 03 Oct 2022 05:23:57 GMT</pubDate>
            <description><![CDATA[<h1 id="querydsl">QueryDsl</h1>
<h3 id="buildgradle">build.gradle</h3>
<p>(querydsl 관련 부분만 남겨둠)</p>
<pre><code>buildscript {
    ext {
        queryDslVersion = &quot;5.0.0&quot;
    }
}

plugins {
    ...
    id &#39;com.ewerk.gradle.plugins.querydsl&#39; version &#39;1.0.10&#39;
}

...

dependencies {
    ...

    implementation &quot;com.querydsl:querydsl-jpa:${queryDslVersion}&quot;
    implementation &quot;com.querydsl:querydsl-apt:${queryDslVersion}&quot;

    annotationProcessor &quot;org.springframework.boot:spring-boot-configuration-processor&quot;
}

def querydslDir = &quot;$buildDir/generated/querydsl&quot;

querydsl {
    jpa = true
    querydslSourcesDir = querydslDir
}

sourceSets {
    main.java.srcDir querydslDir
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
    querydsl.extendsFrom compileClasspath
}

compileQuerydsl {
    options.annotationProcessorPath = configurations.querydsl
}
...</code></pre><h3 id="q클래스-생성">Q클래스 생성</h3>
<p><img src="https://velog.velcdn.com/images/seasame_oil/post/297f235a-7d96-4304-885c-ef6280c60cf9/image.png" alt=""></p>
<ol>
<li>Gradle 탭을 들어간다</li>
<li>Tasks-&gt;other-&gt;compileQuerydsl</li>
<li>Run</li>
</ol>
<p><img src="https://velog.velcdn.com/images/seasame_oil/post/b69523bb-3bc7-4370-a926-3a95e85a25db/image.png" alt="">
Q클래스 생성!</p>
<h2 id="examples">Examples</h2>
<h3 id="jpa">JPA</h3>
<pre><code>QCustomer customer = QCustomer.customer;
JPAQuery&lt;?&gt; query = new JPAQuery&lt;Void&gt;(entityManager);
Customer bob = query.select(customer)
  .from(customer)
  .where(customer.firstName.eq(&quot;Bob&quot;))
  .fetchOne();</code></pre><hr>
<p><a href="http://querydsl.com/">Querydsl</a>
<a href="https://velog.io/@jkijki12/Spring-QueryDSL-%EC%99%84%EB%B2%BD-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0">QueryDSL 완벽 이해하기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring]Spring vs Spring boot]]></title>
            <link>https://velog.io/@seasame_oil/Spring-vs-Spring-boot</link>
            <guid>https://velog.io/@seasame_oil/Spring-vs-Spring-boot</guid>
            <pubDate>Wed, 21 Sep 2022 10:56:48 GMT</pubDate>
            <description><![CDATA[<h2 id="1-spring이란">1. Spring이란?</h2>
<p><img src="https://velog.velcdn.com/images/seasame_oil/post/3ac173eb-0ad5-40c7-86b9-e1a56b85a3d1/image.png" alt="">
Spring이란 Spring Framework, Spring Boot, Spring Data 등등 여러 프로젝트들의 모음
(<a href="https://spring.io/projects">https://spring.io/projects</a>)</p>
<p>스프링을 통해 웹 개발 뿐만 아니라 Microservies, Reactive, Cloud, Web apps, Serverless, Event Driven, Batch 등 여러 가지가 가능함</p>
<p>Spring은 프로젝트 별로 하위 프로젝트(모듈)을 가지고 있음
각자가 개발하려는 애플리케이션에 맞게 각 프로젝트에서 제공해주는 모듈들을 조합해서 사용하면 됨
ex. 스프링 프레임워크 모듈에는 웹 MVC 뿐만 아니라 약 20개의 모듈 존재</p>
<blockquote>
<p>Spring은 Spring 프로젝트들의 모음을 이야기하고, 프로젝트들마다 하위모듈이 존재</p>
</blockquote>
<p>Spring 프로젝트들은 스프링 프레임워크 기반에서 돌아감
ex. 스프링 데이터, 스프링 데이터 JDBC, 스프링 데이터 JPA 등의 모듈을 사용할 때는 스프링 프레임워크가 꼭 필요함</p>
<h2 id="2-spring-framework란">2. Spring Framework란?</h2>
<blockquote>
<p> The Spring Framework provides a comprehensive programming and configuration model for modern Java-based enterprise applications - on any kind of deployment platform.
 A key element of Spring is infrastructural support at the application level: Spring focuses on the &quot;plumbing&quot; of enterprise applications so that teams can focus on application-level business logic, without unnecessary ties to specific deployment environments.
(Spring은 어떤 종류의 배포 플랫폼에서도 최신 자바 기반 기업용 애플리케이션을 위한 종합적인 프로그래밍 및 구성 모델을 제공해준다.
Spring의 핵심 요소는 에플리케이션의 수준에서의 인프라 지원이다. Spring은 기업용 애플리케이션의 plumbing에 초점을 맞춰 팀이 특정 배포 환경과 불필요한 시도 없이 애플리케이션 수준의 비즈니스 로직에 집중할 수 있게 해준다.)</p>
</blockquote>
<p>&quot;자바 기반&quot; = 객체지향 언어가 가진 특징을 잘 활용하게 해주면서 
&quot;비즈니스 로직에만 집중&quot; = 다른 부분은 신경쓰지 않고 비즈니스 로직에만 집중 할 수 있게 해줌</p>
<p>즉, Spring Framework는 객체 지향의 특징을 잘 활용할 수 있게 해주며, 개발자들은 핵심 비즈니스 로직 구현에만 집중할 수 있게 해주는 프레임워크</p>
<p>초기 Spring 기본 설정만 잘 해놓는다면, 스프링 관련 코드를 신경 쓸 일 거의 없음</p>
<ul>
<li>스프링의 기본 전략
: 비즈니스 로직을 담은 코드와 엔터프라이즈 기술을 처리하는 코드 분리</li>
<li>코드 분리로 인해 개발자들은 이제 객체지향 설계에 초점을 맞출 수 있고 이를 돕기 위해 스프링은 DI 같은 기능 제공</li>
<li>Spring Framework는 DI나 IoC같은 기능을 통해 객체지향 특징 중 다형성을 극대화해서 사용할 수 있게 해줌
(느슨하게 결합된 애플리케이션)</li>
</ul>
<h2 id="3-spring-boot란">3. Spring Boot란?</h2>
<blockquote>
<p>Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can &quot;just run&quot;.
We take an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. Most Spring Boot applications need minimal Spring configuration.
(Spring Boot는 독립적이며, 운영 할 수 있는 수준의 Spring 기반 애플리케이션을 쉽게 만들 수 있게 해준다. 그냥 실행해라.
최소한의 설정으로 Spring 플랫폼과 서드파티 라이브러리를 사용할 수 있다. 대부분 Spring Boot 애플리케이션은 최소한의 Spring 설정을 필요로한다.)</p>
</blockquote>
<p>Spring Boot는 Spring Framework 기반의 애플리케이션을 쉽게 만들 수 있게 해주는 것</p>
<p>Spring Boot가 나왔다는 것은 Spring의 어떤 부분들이 불편해서 개선하고 싶었다는 것!
어떤 부분 때문에 Spring Boot가 나왔을까?</p>
<p>Spring Framework는 초창기에 애플리케이션 개발에 필요한 객체들을 생성하고 객체 사이의 의존성을 제공해주는 역할만 했으나 점점 다양한 기술들을 지원하기 시작함
➡️ 복잡해지니 개발자가 처리해야되는 설정도 많아지고 복잡해짐 (초기 설정이 중요한데, 초기 설정이 쉽지 않은 일이 되어버림)
➡️ Spring Boot라는 서버 프로젝트 진행됨</p>
<p>✔️ Spring Boot는 약간의 설정만으로 Spring 애플리케이션을 만들 수 있게 해줌
✔️ Spring Boot는 Spring 프로젝트 중 하나로, Spring Framework를 쉽게 사용하게 해주는 도구이지, Spring Framework와 별개로 사용할 수 있는 것이 아님</p>
<h2 id="4-spring-boot를-사용하면-달라지는-점">4. Spring Boot를 사용하면 달라지는 점</h2>
<p>Spring Boot가 지원하는 여러가지 설정 중 대표적인 4가지</p>
<ul>
<li><p>의존성 관리</p>
</li>
<li><p><em>기존 Spring*</em> : 개발에 필요한 모듈의 의존성을 각각 다운받아야함 + 각 모듈의 버전을 개발자가 하나하나 명시해줘야 함
👎 모듈 간에 의존성이 존재하는 경우가 있고, 서로 버전 때문에 충돌이 일어날 수도 있음 (개발자가 직접 설정)</p>
</li>
<li><p><em>Spring Boot*</em> : &quot;spirng-boot-starter&quot;를 지원해 줌 + 자주 사용하게 되는 모듈 간의 의존성과 버전 조합을 제공해줌
✔️ spring-boot-starter-parent : 각 모듈의 현재 Spring Boot 버전에 가장 적합한 버전을 제공해줌</p>
</li>
<li><p>자동 설정</p>
</li>
<li><p><em>기존 Spring*</em> : 많은 환경설정 필요</p>
</li>
<li><p><em>Spring Boot*</em> : 어노테이션을 통해 자동 설정 </p>
</li>
<li><p>내장 WAS(Web Application Server)</p>
</li>
<li><p><em>기존 Spring*</em> : 애플리케이션 WAR 패키징 ➡️ WAS 설치(Tomcat, Undertow, Jetty) ➡️ WAS에 WAR 파일 올리기</p>
</li>
<li><p><em>Spring Boot*</em> : WAS가 내장되어 있음
웹 애플리케이션을 WAR 파일이 아닌 JAR파일로 패키징하여 바로 사용할 수 있음
(WAR, JAR 모두 사용 가능)</p>
</li>
<li><p>모니터링</p>
</li>
<li><p><em>Spring Boot*</em> : &quot;Actuator&quot;는 애플리케이션의 관리 및 모니터링을 지원해줌</p>
</li>
</ul>
<p>✔️Actuator : 상용 서비스 수준에서 필요로 할 모니터링 기능을 엔드포인트로 미리 만들어서 제공해줌
⚠️ Actuator는 민감한 정보도 많이 제공하기 때문에 운영 시에는 Spring Security 등을 이용하여 보안에 신경써줘야 함 / Actuator의 데이터를 영구 저장소에 저장해주지 않으면 없어질 수 있음</p>
<h2 id="5-정리">5. 정리</h2>
<p>Spring은 Spring Framework를 기반으로 여러 서브 프로젝트들의 모음으로 이루어져 있으며, 서브 프로젝트들은 여러 모듈을 가지고 있음. 개발할 애플리케이션에 맞게 모듈들을 조합해서 사용함</p>
<p>Spring Boot도 Spring 프로젝트 중 하나로, Spring Fremework와 별개로 사용할 수 없으며 Spring을 편하게 사용하게 해주는 역할.</p>
<p>Spring Boot는 의존성 관리, 자동 설정, 내장 WAS, 모니터링 등의 장점이 있음</p>
<p><a href="https://www.youtube.com/watch?v=Y11h-NUmNXI">🏀 에어의 Spring vs Spring Boot</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring]DTO vs VO]]></title>
            <link>https://velog.io/@seasame_oil/DTO-vs-VO</link>
            <guid>https://velog.io/@seasame_oil/DTO-vs-VO</guid>
            <pubDate>Wed, 14 Sep 2022 08:32:34 GMT</pubDate>
            <description><![CDATA[<h2 id="1-들어가며">1. 들어가며</h2>
<p>왜 DTO와 VO를 혼동해서 사용하는가?</p>
<p><img src="https://velog.velcdn.com/images/seasame_oil/post/c8377aa5-9ed6-412d-8787-f2192b2177d5/image.jpeg" alt="">
이 책이 초반에 getter, setter를 언급하고 데이터 전송을 위해 사용되는 객체는 VO라 언급
그러나 이후 2판부터는 VO가 아니라 DTO라 정정</p>
<h2 id="2-결론-먼저">2. 결론 먼저</h2>
<p>DTO = 데이터 전달용
VO = 값 표현용</p>
<h2 id="3-dto-란">3. DTO 란?</h2>
<p>DTO
= Data Transfer Object
= 데이터를 전달하기 위해 사용하는 객체
= 데이터를 담아서 전달하는 바구니</p>
<p>“계층 간” 데이터를 전달하기 위한 객체</p>
<p>데이터 전달용인 DTO의 특성</p>
<ul>
<li>오직 getter/setter 메서드만을 가짐</li>
<li>다른 로직을 가지지 않음</li>
</ul>
<p>보내는 쪽 -&gt; setter를 사용해 데이터를 DTO에 담아보냄
받는 쪽 -&gt; 전달받은 DTO로부터 데이터를 꺼내는 방식</p>
<p><img src="https://velog.velcdn.com/images/seasame_oil/post/817c96bf-c7d5-40e1-a7d5-aea96f0cacfe/image.png" alt="">
getter와 setter 외의 로직 메서드는 가지고 있지 않음</p>
<p><img src="https://velog.velcdn.com/images/seasame_oil/post/dae48f29-d88b-4f13-aac0-5ede111540e3/image.png" alt="">
데이터를 보내주는 서비스레이어 측에서 setter를 통해 전달하고자 하는 데이터를 담아 반환해줌
(setter 메서드를 삭제하고 생성자를 통해 속성 값들을 초기화하게 만들어 불변객체로 만들면 전달 과정 중에 변조되지 않음을 보장 가능 = 안정적)</p>
<p><img src="https://velog.velcdn.com/images/seasame_oil/post/f7e886ff-493a-45ea-bade-bad825ccbe89/image.png" alt="">
데이터를 받는 쪽인 웹 레이어 측에서 getter를 통해 전달받은 데이터를 꺼내서 사용하면 됨</p>
<h3 id="✔️-entity란">✔️ Entity란?</h3>
<p>Entity 클래스는 절대로 요청이나 응답 값을 전달하는 클래스로 사용 X
실제 데이터베이스와 매핑되어 있는 핵심 클래스
(Id로 구분, 로직 포함 가능)</p>
<p>수많은 서비스 클래스나 비즈니스 로직들이 Entity 클래스를 기준으로 동작</p>
<p>Entity 클래스를 기준으로 테이블이 생성되고 스키마 변경
만약, Entity 클래스를 요청이나 응답 값을 전달하는 클래스로 사용한다면 뷰가 변경될 때마다 Entity 클래스를 그에 맞춰서 매번 같이 변경해야 함</p>
<p>Entity 클래스를 변경하면 관련되어 얽혀있는 무수히 많은 클래스들에 영향 미침
-&gt; 요청이나 응답값을 전달하는 클래스로는 반드시 뷰의 변경에 따라 다른 클래스들에게 영향을 끼치지 않고 자유롭게 변경할 수 있는 DTO를 사용해야 함
응답값으로 여러 테이블을 조인한 결과값을 줘야 할 경우가 빈번함
-&gt; Entity 클래스만으로는 결과값을 전달하기 어려운 경우가 많음
-&gt; Entity 클래스와 뷰의 결과값을 전달해주는 DTO는 분리해서 사용해야 함</p>
<p>(스키마 : 데이터베이스의 구조와 제약조건에 대한 명세를 기술한 것
View : 비즈니스 요구사항에서 자주 변경되는 부분 )</p>
<h3 id="✔️entity를-dto-대신-사용할-수-있을까">✔️Entity를 DTO 대신 사용할 수 있을까?</h3>
<p>사용할 수는 있지만,,,
View에서 표현하는 속성 값들이 요청에 따라 계속 달라질 수 있는데, 그때마다 Entity의 속성값들을 변경하면 영속성 모델을 표현한 Entity의 순수성이 모호해지기 때문에 Controller에서 쓸 DTO와 Entity 클래스를 분리하는 것이 좋음</p>
<h2 id="4-vo-란">4. VO 란?</h2>
<p>VO
= Value Object
= 값 그 자체를 표현하는 객체
(값으로만 비교되는 객체 / 불변객체)
서로 다른 이름을 가진 VO의 인스턴스가 모든 속성값이 같다면 같은 객체</p>
<p>VO의 특성</p>
<ul>
<li>다른 로직 포함 가능</li>
<li>생성자를 통해서만 값 초기화</li>
</ul>
<h2 id="5-dto-vs-vo--vs-entity">5. DTO vs VO ( vs Entity)</h2>
<p>DTO
용도 : 레이어 간 데이터 전달
동등 결정 : 속성값이 모두 같다고 해서 같은 객체가 아님
가변/불변 : setter 존재시 가변, setter 비존재시 불변
로직 : getter/setter 외의 로직을 갖지 않음</p>
<p>VO
용도 : 값 자체 표현
동등 결정 : 속성값이 모두 같으면 같은 객체
가변/불변 : 불변
로직 : getter/setter 외의 로직을 가질 수 있음</p>
<p>Entity
용도 : DB 테이블과 매핑되는 클래스
가변/불변 : 가변
로직 : 로직 포함 가능</p>
<hr>
<p>참조 링크
<a href="https://www.youtube.com/watch?v=J_Dr6R0Ov8E">라흐의 DTO vs VO</a>
<a href="https://www.youtube.com/watch?v=z5fUkck_RZM">인비의 DTO vs VO</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Linked List - Iter]]></title>
            <link>https://velog.io/@seasame_oil/Linked-List-Iter</link>
            <guid>https://velog.io/@seasame_oil/Linked-List-Iter</guid>
            <pubDate>Fri, 08 Oct 2021 16:04:12 GMT</pubDate>
            <description><![CDATA[<p>linked list 자료구조 연습
(아직 미완)</p>
<pre><code>#include &lt;iostream&gt;
using namespace std;

template&lt;class T&gt; class Chain;
template&lt;class T&gt; class ChainIterator;

template&lt;class T&gt; class ChainNode {
    friend class Chain&lt;T&gt;;
    friend class ChainIterator&lt;T&gt;;
public:
    ChainNode(T element = 0);
private:
    T data;
    ChainNode&lt;T&gt;* link;
};

template&lt;class T&gt; class Chain {
    friend class ChainIterator&lt;T&gt;;
public:
    Chain() {first = 0;};
    void Delete(void);
    int Length();
    void Add(const T&amp; element);
    void Invert();
    void Concatenate(Chain&lt;T&gt; b);
    //template &lt;class T&gt;
    friend ostream&amp; operator&lt;&lt;(ostream&amp;, Chain&lt;T&gt;);
    //int Minimum();
private:
    ChainNode&lt;T&gt;* first;
};

template&lt;class T&gt;
class ChainIterator {
public:
    ChainIterator(const Chain&lt;T&gt;&amp; I):list(I), current(I.first) {};
    T&amp; operator *() const {return current-&gt;data;};
    T* operator -&gt;() const {return &amp;current-&gt;data;};
    //increment
    ChainIterator&lt;T&gt;&amp; operator ++();
    ChainIterator&lt;T&gt; operator ++(int);
    bool NotNull();
    bool NextNotNull();

    T* First();
    T* Next();
private:
    const Chain&lt;T&gt;&amp; list; //refers to an existing list
    ChainNode&lt;T&gt;* current; // points to a node in list
};

template&lt;class T&gt;
ChainNode&lt;T&gt;::ChainNode(T element) {
    data = element;
    link = 0;
}

template&lt;class T&gt;
void Chain&lt;T&gt;::Delete(void) {
    ChainNode&lt;T&gt;* current, *next;
    if(first != nullptr) {
        next = first-&gt;link;

        ChainNode&lt;T&gt;* temp = first;
        first = next;
        delete temp;
    }
    else cout &lt;&lt; &quot;Error - Empty List. Not deleted&quot; &lt;&lt; &quot;\n&quot;;
}

template&lt;class T&gt;
void Chain&lt;T&gt;::Add(const T&amp; element) {
    ChainNode&lt;T&gt;* newNode = new ChainNode&lt;T&gt;(element);

    if(!first) {
        first = newNode;
        return;
    }
    newNode-&gt;link = first;
    first = newNode;
}

template&lt;class T&gt;
void Chain&lt;T&gt;::Invert() {
    ChainNode&lt;T&gt;* p =first, *q = 0; //q trails p
    while(p) {
        ChainNode&lt;T&gt;* r = q;
        q = p;
        p = p-&gt;link;
        q-&gt;link = r;
    }
    first = q;
}

template&lt;class T&gt;
void Chain&lt;T&gt;::Concatenate(Chain&lt;T&gt; b) {
    ChainNode&lt;T&gt;* p;
    if(!first) {
        first = b.first;
        return;
    }
    if(b.first) {
        for(p = first; p-&gt;link;p = p-&gt;link)
            p-&gt;link = b.first;
    }
}

template&lt;class T&gt;
ChainIterator&lt;T&gt;&amp; ChainIterator&lt;T&gt;:: operator++() {
    current = current-&gt;link;
    return *this;
}

template&lt;class T&gt;
ChainIterator&lt;T&gt; ChainIterator&lt;T&gt;::operator++(int) {
    ChainIterator&lt;T&gt; old = *this;
    current = current-&gt;link;
    return old;
}

template&lt;class T&gt;
bool ChainIterator&lt;T&gt;::NotNull() {
    if(current) return 1;
    else return 0;
}

template&lt;class T&gt;
bool ChainIterator&lt;T&gt;::NextNotNull() {
    if(current &amp;&amp; current-&gt;link) return 1;
    else return 0;
}

template&lt;class T&gt;
T* ChainIterator&lt;T&gt;::First() {
    if(list.first) return &amp;list.first-&gt;data;
    else return 0;
}

template&lt;class T&gt;
T* ChainIterator&lt;T&gt;::Next() {
    if(current) {
        current = current-&gt;link;
        return &amp;current-&gt;data;
    }
    else return 0;
}

template&lt;class T&gt;
int Show(const Chain&lt;T&gt;&amp; I) {
    ChainIterator&lt;T&gt; li(I);

    if(!li.NextNotNull()) return 0;

    T retvalue = *li.First();
    cout &lt;&lt; retvalue;

    while(li.NextNotNull()) {
        retvalue = *li.Next();
        cout &lt;&lt; &quot; &lt;- &quot; &lt;&lt; retvalue;
    }
    return retvalue;
}

template&lt;class T&gt;
int sum(const Chain&lt;T&gt;&amp; I) {
    ChainIterator&lt;T&gt; li(I);

    if(!li.NotNull()) return 0;

    T retvalue = *li.First();
    while(li.NextNotNull()) {
        retvalue += *li.Next();
    }
    return retvalue;
}

template&lt;class T&gt;
int SumProductFifth(const Chain&lt;T&gt;&amp; I) {
    // Sum(Xi * Xi+5)
    return 0;
}

template&lt;class T&gt;
int Length(const Chain&lt;T&gt;&amp; I) {
    //list 갯수
    return 0;
}

template&lt;class T&gt;
int Maximum(const Chain&lt;T&gt;&amp; I) {
    //list에서 최솟값
    return 0;
}

template&lt;class T&gt;
int Minimun(const Chain&lt;T&gt;&amp; I) {
    //list에서 최솟값
    return 0;
}

template&lt;class T&gt;
int MakeArray(const Chain&lt;T&gt;&amp; I, int []) {
    //list 원소를 읽어 배열에 저장
    return 0;
}

int main(void) {
    int select;
    //ChainNode&lt;int&gt; nd;
    Chain&lt;int&gt; a, b;
    ChainIterator&lt;int&gt; cit(a);
    int value;
    do{
        cout &lt;&lt; &quot;\n1. Add new value to chain &#39;A\n2. Add new value to chain &#39;B&#39;&quot;;
        cout &lt;&lt; &quot;\n3. Print all chains\n4. Invert Chain\n5. Concatenate A and B\n6. Delete first node in Chain&quot;;
        cout &lt;&lt; &quot;\n7. Get Sum of the chain\n8. Get length of the chain\n9. Get Max val in Chain\n10. Quit\n&quot;;
        cout &lt;&lt; &quot;Selet command(1~10) : &quot;;
        cin &gt;&gt; select;
        switch (select)
        {
        case 1:
            cout &lt;&lt; &quot;Add a new value: &quot;;
            cin &gt;&gt; value;
            a.Add(value);
            break;
        case 2:
            cout &lt;&lt; &quot;Add a new value: &quot;;
            cin &gt;&gt; value;
            b.Add(value);
            break;
        case 3:
            cout &lt;&lt; &quot;Chain A: &quot;;
            Show(a);
            cout &lt;&lt; &quot;\n&quot;;
            cout &lt;&lt; &quot;Chain B: &quot;;
            Show(b);
            cout &lt;&lt; &quot;\n&quot;;
        case 4:
            cout &lt;&lt; &quot;\nWhich chain will you invert?\n1. Chain A\n2.Chain B\n\nSelect command(1~2) : &quot;;
            cin &gt;&gt; value;
            if(value == 1) {
                a.Invert();
            } else if(value == 2) {
                b.Invert();
            } else {
                cout &lt;&lt; &quot;Invalid value\n&quot;;
            }
            break;
        case 5:
            cout &lt;&lt; &quot;\nConcatenate chain\n&quot;;
            a.Concatenate(b);
            Show(a);
            cout &lt;&lt; &quot;\n&quot;;
            break;
        case 6:
            cout &lt;&lt; &quot;\nWhich chain will you delete?\n[1] Chain A\n[2]Chain B\n\nSelect Command(1~2) : &quot;;
            cin &gt;&gt; value;

            if(value == 1)
                a.Delete();
            else if(value == 2)
                b.Delete();
            else
                cout &lt;&lt; &quot;Invalid value\n&quot;;
            break;
        case 7:
            cout &lt;&lt; &quot;\nWhich chain will you sum?\n[1]Chain A\n[2]Chain B\n\nSelect Command(1~2) : &quot;;
            cin &gt;&gt; value;

            if(value == 1)
                sum(a);
            else if(value == 2)
                sum(b);
            else
                cout &lt;&lt; &quot;Invalid value\n&quot;;
            break;
        case 8:
            cout &lt;&lt; &quot;\nWhich chain&#39;s length do you want?\n[1]Chain A\n[2]Chain B\n\nSelect Command(1~2) : &quot;;
            cin &gt;&gt; value;

            if(value == 1)
                cout &lt;&lt; Length(a) &lt;&lt; &quot;\n&quot;;
            else if(value == 2)
                cout &lt;&lt; Length(b) &lt;&lt; &quot;\n&quot;;
            else
                cout &lt;&lt; &quot;Invalid value\n&quot;;
            break;
        case 9:
        cout &lt;&lt; &quot;\nWhich chain&#39;s max-value do you want?\n[1]Chain A\n[2]Chain B\n\nSelect Command(1~2) : &quot;;
            cin &gt;&gt; value;

            if(value == 1)
                cout &lt;&lt; Maximum(a) &lt;&lt; &quot;\n&quot;;
            else if(value == 2)
                cout &lt;&lt; Maximum(b) &lt;&lt; &quot;\n&quot;;
            else
                cout &lt;&lt; &quot;Invalid value\n&quot;;
            break;
        case 10:
            cout &lt;&lt; &quot;Quit the program...&quot;;
            break;
        default:
            cout &lt;&lt; &quot;WRONG INPUT\n&quot;; 
            break;
        }
    } while(select != 10);
    system(&quot;pause&quot;);
    return 0;
}</code></pre>]]></description>
        </item>
    </channel>
</rss>