<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>yg_hoon.log</title>
        <link>https://velog.io/</link>
        <description>차곡차곡 쌓아가는 개발 노트</description>
        <lastBuildDate>Sun, 02 Apr 2023 15:58:24 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>yg_hoon.log</title>
            <url>https://velog.velcdn.com/images/yg_hoon/profile/a5d0e549-3882-403e-a2d1-c557ba02bdfb/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. yg_hoon.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/yg_hoon" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Spring Framework의 핵심 용어 개념]]></title>
            <link>https://velog.io/@yg_hoon/Spring-Framework%EC%9D%98-%ED%95%B5%EC%8B%AC-%EC%9A%A9%EC%96%B4-%EA%B0%9C%EB%85%90</link>
            <guid>https://velog.io/@yg_hoon/Spring-Framework%EC%9D%98-%ED%95%B5%EC%8B%AC-%EC%9A%A9%EC%96%B4-%EA%B0%9C%EB%85%90</guid>
            <pubDate>Sun, 02 Apr 2023 15:58:24 GMT</pubDate>
            <description><![CDATA[<h4 id="작성-동기">작성 동기</h4>
<p>이전에 Spring의 Core 개념에 대해 배웠었다.
하지만 시간이 지나면서 점차 옅어진 개념들.. 지금은 머리 속에 두루뭉술하게만 남은 것 같다.
Spring에 가장 기본이 되면서 개발할 때 반드시 알아야 하는 개념인만큼 확실하게 정리해두어야 한다는 생각이 들었다.
가장 확실하게 안다고 말할 수 있는 것은 다른 사람에게 설명할 수 있을 때인 것 같다.
배웠던 개념 위주로 글로 적어보고 말로 해보며 내가 개념을 이해한게 맞는지 확인해보자.</p>
<h3 id="ioc">IoC</h3>
<blockquote>
<p>This part of the reference documentation covers all the technologies that are absolutely integral to the Spring Framework.
Foremost amongst these is the Spring Framework’s Inversion of Control (IoC) container.
<a href="https://docs.spring.io/spring-framework/docs/current/reference/html/core.html">https://docs.spring.io/spring-framework/docs/current/reference/html/core.html</a></p>
</blockquote>
<p>Spring Framework docs의 가장 첫 번째 Core Technologies에 도입부 설명이다.
이 문장을 해석하려면 IoC가 뭘까에 대한 의문을 먼저 풀어야 한다.
IoC는 Inversion of Control의 약자로, 뜻을 그대로 풀면 <code>제어의 반전(역전)</code> 이 된다.
다시 말해서 제어권이 역전되었다고 해석할 수 있다.
제어권이 역전되었다는 것은 객체의 호출 작업 같은 흐름에 대한 제어를 <strong>개발자가 하는 것이 아니라 외부(프레임워크)에서 한다는 것을 의미</strong>한다.</p>
<p>정리하면, IoC는 소프트웨어 디자인 패턴 중 하나로 기존 전통적인 프로그래밍에서는 개발자가 작성한 프로그램이 라이브러리를 호출해서 이용하는 형태였다면, IoC가 적용된 소프트웨어에서는 외부 라이브러리의 코드가 개발자가 작성한 코드를 호출해 사용하는 것을 의미한다.</p>
<h3 id="spring-ioc-container--bean">Spring IoC Container &amp; Bean</h3>
<blockquote>
<p>스프링 프레임워크에서 사용하는 객체의 생명주기와 의존성을 관리해주는 컨테이너</p>
</blockquote>
<p>개발자가 객체의 인스턴스 생성과 소멸 등의 생명 주기를 관리하는 것이 아닌 컨테이너가 그 역할을 해준다.
이를 통해 <strong>개발자가 로직에만 집중할 수 있다는 이점</strong>이 있다.</p>
<p>스프링 컨테이너가 관리하는 객체를 Bean(빈)이라고 하는데, 이러한 빈을 관리해주기 때문에 BeanFactory라는 이름이 붙은 인터페이스를 제공하며 스프링 빈을 관리하고 조회하는 역할을 한다.
하지만 이 BeanFactory를 상속받아 여러 기능을 추가한 <code>ApplicationContext</code> 라는 것을 주로 사용하면서 BeanFactory의 상위 집합으로서 스프링 컨테이너를 통상 <code>ApplicationContext</code>라고 칭하게 됐다.
추가 기능: 메세지 소스를 활용한 국제화, 애플리케이션 이벤트, 환경변수 등</p>
<p>스프링 컨테이너는 XML 기반으로 만들 수 있고 애노테이션 기반의 자바 설정 클래스로 만들 수도 있다.</p>
<ul>
<li>XML을 이용한 스프링 컨테이너 생성<pre><code>ApplicationContext ac = new GenericXmlApplicationContext(&quot;appConfig.xml&quot;);</code></pre></li>
<li>Java 코드를 통한 스프링 컨테이너 생성<pre><code>AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);</code></pre>이 클래스는 ApplicationContext 인터페이스의 구현체이며 AppConfig.class는 구성 정보이다.</li>
</ul>
<p>각 형태별 설정 정보를 읽는 Reader가 존재하며 이를 통해 <code>BeanDefinition</code>을 생성한다.
이처럼 스프링은 다양한 형태의 설정 정보를 <code>BeanDefinition</code>으로 추상화해서 사용한다.</p>
<h3 id="di">DI</h3>
<blockquote>
<p>Dependency Injection, 의존성 주입
객체를 직접 생성하는 대신 외부로부터 주입 받아 사용한다.</p>
</blockquote>
<p>DI 관계는 컨테이너가 <code>Bean Definition</code>이라고 하는 빈 설정 정보를 바탕으로 자동으로 연결해준다.</p>
<p>DI 방법에는 크게 <code>생성자 주입 방식</code>, <code>필드 주입 방식</code>, <code>수정자 주입 방식</code>이 있다.
최근 가장 많이 사용 하는 방식은 <code>생성자 주입 방식</code>으로 클래스의 생성자가 한 개면서 주입 받을 객체가 Bean으로 등록이 되어있다면 <code>@Autowired</code> 없이 <strong>자동으로 의존성을 주입</strong>해준다.
필드 주입 방식은 필드에 @Autowired를 붙여주면 의존성이 주입되는 방식을 말한다.
수정자 주입 방식은 Setter 메소드에 @Autowired를 붙여 의존성을 주입하는 방식이다.</p>
<p>DI를 통해 코드의 재사용성을 높이고 객체 간의 의존성을 낮출 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL 기본 문법 정리 (SELECT ~ DELETE)]]></title>
            <link>https://velog.io/@yg_hoon/SQL-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC-SELECT-DELETE</link>
            <guid>https://velog.io/@yg_hoon/SQL-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC-SELECT-DELETE</guid>
            <pubDate>Tue, 28 Mar 2023 11:13:49 GMT</pubDate>
            <description><![CDATA[<h3 id="작성-동기">작성 동기</h3>
<p>학부 시절, 데이터베이스 과목을 들으면서 배웠던 SQL 문법에 대한 기억이 흐려졌다.
아무래도 SQL을 사용하는 대신 ORM을 이용해 기본적인 CRUD만 사용했기 때문인 것 같다.
하지만 SQL은 백엔드 개발자에게 기본 소양으로도 여겨진다.
복잡한 질의문이 필요할 때는 반드시 SQL을 사용해야한다.
그럼 MySQL을 기준으로 가장 기본이 되는 SQL 문법들을 예시와 함께 정리해보자.</p>
<h3 id="dml-vs-ddl-vs-dcl">DML vs DDL vs DCL</h3>
<h4 id="dml">DML</h4>
<blockquote>
<p>Data Manipulation Language, 데이터 조작 언어</p>
</blockquote>
<p>데이터 조작 -&gt; 선택, 삽입, 수정, 삭제
DML 구문의 대상은 테이블의 행으로 사전에 정의된 테이블에 사용한다.
SELECT, INSERT, UPDATE, DELETE가 이 구문에 해당된다.
트랜잭션이 발생하는 SQL도 DML이다.</p>
<h4 id="ddl">DDL</h4>
<blockquote>
<p>Data Definition Language, 데이터 정의어</p>
</blockquote>
<p>테이블, 인덱스, 뷰 등 데이터베이스 개체를 생성하고 삭제 및 변경하는 역할을 한다.
CREATE, DROP, ALTER 등이 이에 해당된다.
DDL은 트랜잭션을 발생시키지 않기 때문에 실행 즉시 적용된다는 특징이 있다.
(ROLLBACK이나 COMMIT도 적용이 안된다)</p>
<h4 id="dcl">DCL</h4>
<blockquote>
<p>Data Control Language, 데이터 제어 언어</p>
</blockquote>
<p>주로 사용자에게 권한을 부여하거나 뺏을 때 사용하는 구문
GRANT, REVOKE, DENY 등이 이에 해당된다.</p>
<h3 id="use">USE</h3>
<blockquote>
<p>사용할 데이터베이스를 지정한다.</p>
</blockquote>
<p>기본 형식: <code>USE db_name;</code></p>
<p>다른 DB를 사용하겠다고 명시하지 않는 이상 이후에 작성되는 모든 SQL문은 db_name에서 수행된다.</p>
<h3 id="select">SELECT</h3>
<blockquote>
<p>가장 많이 사용되는 질의문으로 테이블에서 원하는 정보를 얻기 위해 사용한다.
쉬우면서도 어려운 질의문이기 때문에 잘 익힐 필요가 있다.</p>
</blockquote>
<p>SELECT 구문은 다양한 옵션들을 가지고 있기 때문에 하나하나 보면 복잡해 보이기도 한다.
하지만 실제로 많이 사용되는 형태는 어느정도 정해져있다.</p>
<p>기본 형식:</p>
<pre><code>SELECT    select_expr
        FROM table_references
        WHERE where_condition
        GROUP BY {col_name | expr | position}
        HAVING where_condition
        ORDER BY {col_name | expr | position}</code></pre><p>각 행으로 구분된 옵션은 생략이 가능하지만 <strong>순서는 지켜져야한다.</strong></p>
<p><code>SELECT * FROM table;</code>
: table에 있는 모든 열 데이터를 조회한다.</p>
<p><code>SELECT * FROM database_name.table_name;</code>
: 앞에서 <code>USE</code>를 사용했기 때문에 그냥 테이블 이름을 주었는데
원래는 테이블의 전체 이름은 <code>데이터베이스_이름.테이블_이름</code> 으로 표현한다.</p>
<p><code>SELECT name FROM table;</code>
<code>SELECT name, age FROM table;</code>
: 전체 열이 아닌 특정 열만 가져오고 싶을 때 * 대신 필요한 열의 이름을 입력하면 된다.
여기서는 테이블에 name 열만 조회하도록 했다.
여러 개의 열을 조회하고자 할 때는 콤마로 구분하면 된다.</p>
<h4 id="where절">WHERE절</h4>
<blockquote>
<p>DB의 모든 데이터를 확인하는 것은 딱히 의미가 없다, 원하는 데이터를 얻기 위해서는 조건에 맞는 데이터를 가져올 수 있어야한다.
WHERE절은 조회 결과에 특정한 조건을 주어서 원하는 데이터를 얻는데 사용한다.</p>
</blockquote>
<p><code>SELECT * FROM member WHERE name = &#39;김계란&#39;;</code>
: 테이블에서 이름이 &#39;김계란&#39;인 사람만 찾는다.</p>
<p><code>SELECT * FROM member WHERE name LIKE &#39;김%&#39;;</code>
: LIKE는 문자열의 내용을 검색할 때 사용하면 유용하다.
<code>김%</code> 라고 하면 김으로 시작하는 이름을 추출한다.
% 문자는 꼭 LIKE 문으로 검색 해야한다.
만약 한 글자만 매치하고자 한다면 <code>_</code> 을 사용하면 된다. (ex: <code>LIKE &#39;_계란&#39;</code>)</p>
<p><code>SELECT name, age FROM member WHERE height &gt;= 170 AND weight &gt;= 60;</code>
: 키가 170이상이고 몸무게가 60이상인 사람들만 찾아서 이름과 나이를 보여준다.
이 예시처럼 관계 연산자를 사용해서 조회가 가능하다.</p>
<p><code>SELECT name, age FROM member WHERE height &gt;= 180 OR height &lt; 160;</code>
: OR 연산자를 사용해서 구성한 예시이다.
키가 180 이상이거나 160 미만인 사람만을 찾을 수 있다.</p>
<p><code>SELECT name, age FROM member WHERE height BETWEEN 170 AND 175;</code>
: 앞의 예제처럼 부등호를 이용해 조회하는 것도 가능하지만 연속적인 값을 가지고 있다면 
BETWEEN과 AND를 사용해도 된다. (키가 170 &lt;= height &lt;= 175인 사람 조회)</p>
<p><code>SELECT name, age FROM member WHERE addr=&#39;서울&#39; OR addr=&#39;경기&#39; OR addr=&#39;인천&#39;;</code>
<code>SELECT name, age FROM member WHERE addr IN (&#39;서울&#39;, &#39;경기&#39;, &#39;인천&#39;);</code>
: 연속적인 값이 아닐 때는 BETWEEN과 AND를 사용할 수 없다.
대신 IN을 사용하면 조금 더 편하게 사용할 수 있다.</p>
<h4 id="서브쿼리subquery-하위쿼리">서브쿼리(SubQuery, 하위쿼리)</h4>
<blockquote>
<p>서브쿼리는 이름 그대로 쿼리문 안에 들어가는 쿼리문을 말한다.
굉장히 자주 사용하기 때문에 익숙해지는 것이 좋다.</p>
</blockquote>
<p>예시:</p>
<pre><code>SELECT     name, height FROM member
        WHERE height &gt; (SELECT height FROM member WHERE name = &#39;김계란&#39;);</code></pre><p>만약 <code>김계란</code> 보다 키가 큰 사람들을 검색하고 싶다면 김계란의 키를 알아야한다.
김계란의 키를 직접 적어줘도 되지만 서브쿼리를 사용해서 김계란의 키를 받아서 넣어주는 식으로 쿼리문을 구성하는 것도 가능하다.
단 주의할 점은 위와 같은 쿼리문은 서브쿼리가 1건이 나와야지 문제가 없다.</p>
<pre><code>SELECT     name, height FROM member
        WHERE height &gt;= (SELECT height FROM member WHERE name LIKE &#39;김%&#39;);</code></pre><p>만약 이와 같은 쿼리문을 실행했다면 어떻게 될까?
이름이 김으로 시작하는 사람이 딱 1명만 존재해야한다.
1명을 넘어가는 순간 쿼리문에 오류가 발생한다.
height와 크거나 같은지를 비교하고자 하는데 1명이 넘어가면 구조적으로 이상하다.</p>
<h4 id="any">ANY</h4>
<p>이럴 때 필요한 구문이 <code>ANY</code> 구문이다.</p>
<pre><code>SELECT     name, height FROM member
        WHERE height &gt;= ANY (SELECT height FROM member WHERE name LIKE &#39;김%&#39;);</code></pre><p>ANY를 사용하면 검색된 결과 중에서 아무거나 크거나 같은 사람을 찾겠다는 의미로 해석된다.
<code>김</code>으로 시작하는 사람이 2명있고 각각 173, 177이라고 할 때, 173보다 크거나 같은 사람 또는 177보다 크거나 같은 사람 모두 출력한다.</p>
<h4 id="all">ALL</h4>
<p><code>ALL</code>을 사용할 경우도 알아보자.
ALL을 사용하면 같은 조건일 때 (<code>김</code>으로 시작하는 사람이 2명있고 각각 173, 177이라고 할 때)
이 값에 대한 식을 둘 다 만족해야한다는 의미가 된다.
따라서 <strong>173보다 크거나 같으면서</strong> <strong>177보다 크거나 같아야 하기</strong> 때문에 결과적으로 177보다 크거나 같은 사람이 조회된다.</p>
<h4 id="order-by">ORDER BY</h4>
<blockquote>
<p>결과에는 영향을 주지 않고, 결과가 출력되는 순서를 조절하는 구문이다.
ORDER BY는 MySQL 성능을 떨어뜨릴 수 있기 때문에 안쓸 수 있다면 안쓰는 것이 좋다.</p>
</blockquote>
<p><code>SELECT name, height FROM member ORDER BY age DESC;</code>
: ORDER BY는 기본적으로 오름차순 정렬(ASC)이다.
내림차순 정렬을 하기 위해서는 <code>DESC</code> 를 붙여주어야 한다.</p>
<p>정렬을 두 가지 조건으로 할 수도 있다.
<code>SELECT name, height FROM member ORDER BY age DESC, name ASC;</code>
: 만약 age가 같다면 이름 순으로 정렬하겠다는 의미이다.</p>
<h4 id="distinct">DISTINCT</h4>
<blockquote>
<p>중복을 제거해주는 구문, 자주 사용한다.</p>
</blockquote>
<p><code>SELECT DISTINCT addr FROM member;</code>
: 주소 중 중복된 것은 1개만 표시하도록 하여 조회한다.</p>
<h4 id="limit">LIMIT</h4>
<blockquote>
<p>출력의 개수를 제한해준다.</p>
</blockquote>
<p><code>SELECT name, age FROM member LIMIT 5;</code>
: 제한을 안두면 엄청나게 많은 데이터가 조회되어 DBMS에게 부담을 줄 수 있다.
LIMIT를 통해 조회 건수의 제한을 두고 원하는 개수만큼을 조회할 수 있다.</p>
<p><code>SELECT name, age FROM member LIMIT 0, 5;</code>
<code>SELECT name, age FROM member LIMIT 5 OFFSET 0;</code>
: LIMIT절은 <code>LIMIT 시작, 개수</code> 또는 <code>LIMIT 개수 OFFSET 시작</code> 형식으도 표현할 수 있는데,
시작은 0부터 시작하며 5개를 출력한다는 의미이다.</p>
<h4 id="select-활용-테이블-복사">SELECT 활용: 테이블 복사</h4>
<p>예시:</p>
<pre><code>USE table;
CREATE TABLE new_table (SELECT * FROM member);
SELECT * FROM new_table;</code></pre><p>SELECT로 member 테이블의 모든 열을 조회한 결과를 new_table에 넣게 된다.
물론 열을 직접 지정하면 new_table에 지정한 열만 복사된다.</p>
<p>주의: PK, FK 같은 테이블 내 제약 조건은 복사 되지 않는다.</p>
<h4 id="group-by">GROUP BY</h4>
<blockquote>
<p>GROUP BY는 말 그대로 그룹으로 묶어주는 역할을 한다.
집계함수와 함께 자주 사용된다.</p>
</blockquote>
<h4 id="집계함수">집계함수</h4>
<ul>
<li>SUM(): 합 계산</li>
<li>AVG(): 평균 계산</li>
<li>MIN(): 최소값 계산</li>
<li>MAX(): 최대값 계산</li>
<li>COUNT(): 행의 개수 계산</li>
<li>COUNT(DISTINCT): 행의 개수를 중복 없이 센다.</li>
<li>VAR_SAMP(): 분산 계산</li>
<li>STDEV(): 표준편차 계산</li>
</ul>
<p><code>SELECT userID, SUM(amount) FROM member_buy GROUP BY userID;</code>
: 사용자별로 구매 개수를 조회하고 싶을 때 이렇게 GROUP BY를 통해 데이터를 그룹화 한다.
사용자별로 amount의 합계를 계산해서 조회할 수 있다.</p>
<p><code>SELECT userID, SUM(price * amount) FROM member_buy GROUP BY userID;</code>
: 사용자별 구매액의 총합을 보고자 할 때 price와 amount를 곱한 값들을 더해서 그룹화 하면 된다.</p>
<p><code>SELECT userID, AVG(amount) FROM member_buy GROUP BY userID;</code>
: 사용자별 amount의 평균을 계산한 결과를 보여준다.</p>
<p>만약 height의 최소값과 최대값이 담긴 행을 조회하고 싶을 때는 어떻게 하면 될까?</p>
<pre><code>SELECT     name, height FROM member
        WHERE height = (SELECT MAX(height) FROM member)
        OR height = (SELECT MIN(height) FROM member);</code></pre><p>서브쿼리와 조합하면 수월하게 구성이 가능하다.</p>
<p><code>SELECT COUNT(*) FROM member;</code>
: member의 전체 데이터 개수를 계산한다.</p>
<p><code>SELECT COUNT(phone_number) FROM member;</code>
: 휴대폰 번호가 있는 member 데이터의 개수만 계산한다.
NULL 값인 경우는 제외한다.</p>
<h4 id="having">HAVING</h4>
<blockquote>
<p>GROUP BY와 함께 사용되는 WHERE절, 집계함수를 사용해 조건을 부여할 수 있다.</p>
</blockquote>
<p>집계함수는 WHERE 절에 사용될 수 없기 때문에 GROUP Function과 관련이 있는 것은 HAVING 절에 사용해야한다.</p>
<pre><code>SELECT     userID, SUM(price * amount) FROM member_buy 
        GROUP BY userID
        HAVING SUM(price * amount) &gt; 1000;</code></pre><p>이렇게 하면 구매액이 1000 이상인 결과만 조회할 수 있다.</p>
<h3 id="insert">INSERT</h3>
<blockquote>
<p>INSERT는 데이터를 삽입하는 명령</p>
</blockquote>
<p>기본형식: <code>INSERT INTO table_name(column1, column2... VALUES (value1, value2 ...)</code></p>
<p>테이블 이름 다음에 나오는 열은 생략이 가능하다.
다만 생략할 경우 VALUES 뒤에 나오는 값들의 순서와 개수가 테이블에 정의된 열 순서, 개수와 동일해야한다.
또한 순서를 바꿔서 입력하는 것도 가능하며, 이 때는 입력한 순서에 맞춰 열 이름과 데이터를 적어야 한다.</p>
<p>특정 값만 입력하고 싶을 때는 직접 지정하면 된다.
<code>INSERT INTO table(id, username) VALUES (2, &#39;계란&#39;);</code>
: 이렇게 할 경우 생략된 열에는 NULL 값이 들어가게 된다.</p>
<h4 id="auto_increment">AUTO_INCREMENT</h4>
<blockquote>
<p>자동으로 값이 입력되는 것으로, 기본은 1부터 증가하는 값이 입력된다.</p>
</blockquote>
<p>테이블 속성에 AUTO_INCREMENT가 지정되어있다면 자동으로 입력되기 때문에 없다고 생각하면 된다.
AUTO_INCREMENT는 반드시 PK 또는 UNIQUE 값으로 지정이 되어야 한다.
또한 증가하는 값이기 때문에 타입은 숫자 형식만 사용 가능하다.</p>
<p><code>ALTER TABLE table_name AUTO_INCREMENT=100;</code>
: 자동 증가되는 입력 값을 100부터 입력되도록 변경할 수 있다.</p>
<p>증가 값은 기본적으로 1씩 증가하는데 이를 바꾸려면 서버 변수를 바꿔야한다.
<code>SET @@auto_increment_increment=5;</code>
: 증가 값을 5로 변경한다.</p>
<p>시작 값은 위에서 100으로 바꾸었다고 가정하면 다음과 같다.
100 -&gt; 105 -&gt; 110 -&gt; 115 ...</p>
<h4 id="insert-into-여러-개-입력하기">INSERT INTO 여러 개 입력하기</h4>
<p><code>INSERT INTO table_name VALUES (value1, value2), (value3, value4), (value5, value6);</code></p>
<p>3개의 쿼리문으로 나눠서 하는 것도 가능하지만 이렇게 할 수도 있다.</p>
<h4 id="조건부-데이터-입력-변경">조건부 데이터 입력, 변경</h4>
<p>만약 INSERT 문을 10개 수행할 때 첫 번째 INSERT 문에서 오류가 발생하면 뒤에 있는 나머지 INSERT 문도 실행되지 않는다. 하지만 MySQL은 오류가 발생해도 계속 진행하는 방법을 제공한다.</p>
<p>INSERT문에 IGNORE를 붙여주면 된다. 
예: <code>INSERT IGNORE INTO ~</code>
(오류 난 것을 무시하고 다음 것을 실행하라는 뜻이다.)</p>
<p>또한 키가 중복일 때 UPDATE로 처리하는 방법도 제공한다.</p>
<pre><code>INSERT INTO table VALUES(&#39;KIM&#39;, &#39;김계란&#39;, &#39;서울&#39;)
    ON DUPLICATE KEY UPDATE name=&#39;김계란&#39;, addr=&#39;서울&#39;);</code></pre><h3 id="update">UPDATE</h3>
<blockquote>
<p>데이터를 수정하는 구문</p>
</blockquote>
<p>기본 형식: <code>UPDATE table_name SET columns=value, columns2=value2 .. WHERE condition;</code></p>
<p>UPDATE 문은 대부분 WHERE 절이 들어가야한다.
WHERE 절이 안들어가면 모든 데이터가 UPDATE 된다. (-&gt; 이런 경우는 많이 없다.)</p>
<p>WHERE 절을 안쓰는 경우 예시
<code>UPDATE buy_table SET price=price*1.5;</code>
: 구매 테이블의 단가가 모두 1.5배 인상 되어서 수정하는 경우</p>
<h3 id="delete">DELETE</h3>
<blockquote>
<p>데이터(행)를 삭제하는 구문</p>
</blockquote>
<p>기본 형식: <code>DELETE FROM table_name WHERE condition;</code></p>
<p>주의: WHERE문이 생략되면 전체 데이터를 삭제한다.
따라서 WHERE절을 쓰는게 일반적이다.</p>
<p><code>DELETE FROM table_name WHERE addr = &#39;부산&#39; LIMIT 5;</code>
: 주소지가 부산인 데이터를 상위 5건만 삭제하는 쿼리문이다.</p>
<h4 id="대용량-테이블의-삭제">대용량 테이블의 삭제</h4>
<pre><code>CREATE TABLE table1 (SELECT * FROM table);
CREATE TABLE table2 (SELECT * FROM table);
CREATE TABLE table3 (SELECT * FROM table);

DELETE FROM table;
DROP TABLE table;
TRUNCATE TABLE table;</code></pre><p>서로 무슨 차이가 있을까?</p>
<ul>
<li>DELETE
  원하는 데이터를 한 행씩 삭제하며 WHERE절로 조건에 따라 행 삭제가 가능하다.
  삭제된 행에 대해 각각 트랜잭션 로그를 기록한다.
  삭제 후 잘못 삭제한 데이터를 되돌리기가 가능하다.</li>
<li>TRUNCATE
  테이블에서 데이터를 한꺼번에 지우며 개별 행 삭제가 안된다. 
  트랜잭션 로그에 한 번만 기록된다.
  삭제 후에는 되돌리기는 불가능하다.</li>
<li>DROP
  테이블 자체를 삭제한다. (테이블 행, 인덱스, 권한 등이 모두 삭제된다.)
  삭제 후 되돌릴 수 없다.</li>
</ul>
<p>셋 중에서 한 행씩 삭제하는 DELETE가 제일 오래걸린다.
DROP은 빠르지만 테이블 구조가 아예 날라간다.</p>
<h3 id="with절과-cte">WITH절과 CTE</h3>
<blockquote>
<p>CTE: Common Table Expression, 재귀적, 비재귀적 두 가지가 존재한다.
기존 뷰, 임시 테이블 등으로 사용하던 것을 대신 할 수 있고 간결하게 보여지는 장점이 있다.
CTE에 집중하는 포스트가 아니므로 비재귀적 CTE만 간단하게 알아보자</p>
</blockquote>
<h4 id="비재귀적-cte">비재귀적 CTE</h4>
<pre><code>WITH CTE_TABLE_NAME(열 이름)
AS
(
    &lt;쿼리문&gt;
)
SELECT 열 이름 FROM CTE_TABLE_NAME;</code></pre><p>CTE는 복잡한 쿼리문장을 단순화 시키는데 적합하다.</p>
<p>예시:</p>
<pre><code>WITH cte_test(userId, total)
AS
(SELECT userId, SUM(price*amount)
    FROM buy_table GROUP BY userId)
SELECT * FROM cte_test ORDER BY total DESC;</code></pre><ul>
<li>테이블 열 매칭 관계
userId -&gt; userId
SUM(price*amount) -&gt; total</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[소프트웨어 개발 프로세스와 애자일]]></title>
            <link>https://velog.io/@yg_hoon/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B0%9C%EB%B0%9C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%99%80-%EC%95%A0%EC%9E%90%EC%9D%BC</link>
            <guid>https://velog.io/@yg_hoon/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B0%9C%EB%B0%9C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%99%80-%EC%95%A0%EC%9E%90%EC%9D%BC</guid>
            <pubDate>Wed, 15 Mar 2023 17:25:30 GMT</pubDate>
            <description><![CDATA[<p>소프트웨어 개발 프로세스는 소프트웨어 공학에서 배우는 세부 분야 중 하나이다.
따라서 소프트웨어 공학이 무엇인지 먼저 짚고 넘어가는 것이 필요하다.</p>
<h3 id="소프트웨어-공학">소프트웨어 공학</h3>
<blockquote>
<p>말 그대로 공학을 소프트웨어에 적용하는 것으로 소프트웨어의 설계, 개발, 구현, 유지보수, 테스팅 등의 소프트웨어 생명주기의 전반적인 과정을 체계적으로 다루는 학문이다.</p>
</blockquote>
<p>일반적으로 소프트웨어 개발은 혼자서 진행 하지 않는다.
즉, 팀 단위의 개발을 진행하기 때문에 좋은 소프트웨어를 만들기 위해선 어떤 프로세스가 필요하다.</p>
<p>최근 소프트웨어 공학의 트렌드는 <strong>고객의 요구사항에 맞는</strong> 소프트웨어를 <strong>빠르게</strong> 개발해내는 것이다.</p>
<h3 id="소프트웨어-개발-프로세스">소프트웨어 개발 프로세스</h3>
<blockquote>
<p>소프트웨어를 개발하기 위해 필요한 과정 또는 구조를 의미</p>
</blockquote>
<p>위에서 말했던 좋은 소프트웨어를 만들기 위해 필요한 프로세스가 바로 이 소프트웨어 개발 프로세스이다.
소프트웨어 개발 프로세스에는 잘 알려진 몇 가지 대표적인 방법이 있는데, 그 중에서 폭포수 모델과 애자일 프로세스를 집중적으로 다뤄보자.</p>
<h3 id="개발-방법론-폭포수-모델">개발 방법론: 폭포수 모델</h3>
<p>왜 이름이 폭포수 모델일까?</p>
<blockquote>
<p>아래 그림은 폭포수 모델 사진인데, 마치 폭포수처럼 아래로 떨어지는 모습을 하고 있기 때문이다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/yg_hoon/post/31a1c750-fa9b-44fa-8399-a2eaa7310f88/image.png" alt=""></p>
<blockquote>
<p>출처: <a href="https://ko.wikipedia.org/wiki/%ED%8F%AD%ED%8F%AC%EC%88%98_%EB%AA%A8%EB%8D%B8">위키백과 폭포수 모델</a></p>
</blockquote>
<p>폭포수 모델을 적용한다는 것은 각 단계를 완벽하게 수행하고 다음 단계로 넘어가는 것을 전제로 한다.
따라서 완벽하게 설계하고, 디자인하며 개발 일정까지 예측해서 정해두고 개발을 진행한다.</p>
<h4 id="무슨-문제가-발생할-수-있을까">무슨 문제가 발생할 수 있을까?</h4>
<p>일정을 다 정해두고 프로젝트를 진행하기 때문에 개발자는 어떻게든 개발 일정에 맞춰야 할 수 밖에 없다.
또 개발 기간 동안 고객의 요구사항이 변경되거나 추가 요구사항을 내면 그만큼 이전에 끝냈던 작업을 다시 해야하는 문제가 생긴다.
실제로 고객이 정해진 요구사항을 바꿔달라고 하는 경우는 빈번하다고 한다.
그런데 설계가 완료된 상태고 개발까지 끝낸 상태였다면..?
요구사항이 반영된 설계를 다시 하고 개발도 다시해야 하는 상황이 발생한다.
때문에 폭포수 모델은 완벽하게 실행하는 것이 불가능에 가깝다라는 비판을 많이 받았다.</p>
<h3 id="개발-방법론-애자일agile-개발-프로세스">개발 방법론: 애자일(Agile) 개발 프로세스</h3>
<blockquote>
<p>반복적인 개발 주기를 통해 끊임없이 프로토타입을 개발해나가는 방식</p>
</blockquote>
<p>새로운 서비스가 출시되는 속도는 점점 빨라지고 고객은 새로운 요구사항을 끊임없이 제시한다.
이러한 변화에 딱 맞는 개발 방법론이 애자일이다.
애자일은 소규모 팀을 구성하여 기획자와 개발자, 디자이너가 함께 소속되도록 한다.
이렇게 구성하면 필요한 작업을 요청하고 처리할 때 용이하다는 장점이 있다.
또한 공동의 목표를 가지고 개발해나갈 수 있으며 고객의 요구사항 변화에 대응하기 유리하다.</p>
<p>애자일은 그 뜻처럼 변화에 대해 신속하고 효과적으로 대응하기 위한 방법론이다.
이와 관련해서 Agile 선언문이라는 것도 존재한다.</p>
<blockquote>
<p>공정과 도구보다 개인과 상호작용을
포괄적인 문서보다 작동하는 소프트웨어를
계약 협상보다 고객과의 협력을
계획을 따르기보다 변화에 대응하기를
<a href="https://agilemanifesto.org/iso/ko/manifesto.html">https://agilemanifesto.org/iso/ko/manifesto.html</a></p>
</blockquote>
<p>이 선언문만 봐도 Agile이 무엇을 중요시 하는지 파악이 가능하다.</p>
<p>애자일 방법론을 적용하는데 핵심적인 몇 가지 개념과 방법이 더 있다.
내용이 너무 방대해질 것 같아서 이와 관련된 내용은 향후 애자일 관련 포스팅을 별도로 구성해서 다뤄보겠다.</p>
]]></description>
        </item>
    </channel>
</rss>