<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>sg-moomin.log</title>
        <link>https://velog.io/</link>
        <description>backend 개발자를 꿈꾸는 직장인입니다.</description>
        <lastBuildDate>Mon, 09 Oct 2023 06:46:12 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>sg-moomin.log</title>
            <url>https://images.velog.io/images/sg-moomin/profile/d0d9d69d-1c05-4756-b4e1-39d8a953b3f8/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. sg-moomin.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/sg-moomin" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Spring Boot + GraphQL 활용하기]]></title>
            <link>https://velog.io/@sg-moomin/Spring-Boot-GraphQL-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sg-moomin/Spring-Boot-GraphQL-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 09 Oct 2023 06:46:12 GMT</pubDate>
            <description><![CDATA[<p>기존 Tistory에 적었던 GraphQl에 대한 학습 내용을 글로 남겨보려고 한다. </p>
<ul>
<li>Tistory : <a href="https://sg-moomin.tistory.com/manage/newpost/197?type=post&amp;returnURL=https%3A%2F%2Fsg-moomin.tistory.com%2Fentry%2F%EC%84%B8%EB%AC%B4%EB%AF%BC%EC%9D%98-%EC%BD%94%EB%94%A9%EC%9D%BC%EA%B8%B0-Spring-Boot-GraphQL-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0">GraphQL + SpringBoot</a></li>
</ul>
<h2 id="graphql">GraphQL?</h2>
<ul>
<li>GraphQL은 페이스북에서 만든 쿼리 언어입니다.</li>
<li>GrahpQl은 웹 클라이언트가 데이터를 서버로부터 효율적으로 가져올 수 있도록 되어있습니다.</li>
<li><strong>REST API의 경우는 다양한 EndPoint가 존재한다면 GraphQL은 하나의 EndPoint</strong>를 가집니다. </li>
</ul>
<h3 id="graphql은-기존에-url을-보면-이해하기-쉽다">GraphQL은 기존에 Url을 보면 이해하기 쉽다.</h3>
<ul>
<li>Rest Api의 경우는 /newPost, /comments, /user 등 다양한 endPoint를 가지지만 </li>
<li>gql(GraphQL)은 /graphql 하나의 endpoint 만으로도 사용이 가능하다는 점이다. </li>
</ul>
<h2 id="spring-boot--graphql">Spring Boot + GraphQL</h2>
<h3 id="1-create-project">1) Create Project</h3>
<p><img src="https://velog.velcdn.com/images/sg-moomin/post/74bea781-95ce-40dc-b4ba-fcfbe069a0ce/image.png" alt=""></p>
<ul>
<li>dependencies 추후 추가해도 무관함으로 jpa, web만 추가하면 됨 </li>
</ul>
<h4 id="11-build-gradle">1.1) build gradle</h4>
<pre><code>implementation &#39;com.graphql-java-kickstart:graphql-spring-boot-starter:11.0.0&#39;
testImplementation &#39;com.graphql-java-kickstart:graphql-spring-boot-starter-test:11.0.0&#39;</code></pre><h4 id="12-applicationpropertiesyml">1.2) application.properties(yml)</h4>
<pre><code>graphql.servlet.mapping=/graphql
graphql.tools.schema-location-pattern=**/*.graphqls
graphql.servlet.cors-enabled=true
graphql.servlet.max-query-depth=100
graphql.servlet.exception-handlers-enabled=true</code></pre><h3 id="2-directory-구조">2) directory 구조</h3>
<p><img src="https://velog.velcdn.com/images/sg-moomin/post/f3d847a6-ab2a-4cbf-bac5-f9b476232469/image.png" alt=""></p>
<h3 id="3-create-graphqls-file">3) Create Graphqls File</h3>
<pre><code>schema {
    query: Query,
    mutation: Mutation,
}

type Mutation {
    registerMember(membersn: Int!, memberid: String!, memberemail: String!, membernumber: String!): Member
    deleteMember(memberid: String!): Boolean
}

type Query{
    findMembers(memberid: String!): Member!
    allFindMembers: [Member]
}

type Member{
    membersn: Int
    memberid: String
    memberemail : String
    membernumber : String
}</code></pre><ul>
<li>Query : 서버에게 데이터를 요청하여 호출 </li>
<li>Mutation : 서버에게 데이터 수정을 위해 호출</li>
<li><strong>Query 유형에서 조회, Mutation 유형에서는 생성 및 삭제, 수정 연산에서 사용된다고 보면된다</strong></li>
</ul>
<h3 id="4-create-domainquerymutation-class">4) Create Domain/Query/Mutation Class</h3>
<h4 id="41-domain">4.1) domain</h4>
<pre><code>@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Entity(name=&quot;member&quot;)
public class Member{

    @Id
    @Column(nullable = false)
    private int membersn;

    @Column(nullable = false)    
    private String memberid;

    @Column(nullable = false)
    private String memberemail;

    @Column(nullable = false)
    private String membernumber;
}</code></pre><h4 id="42-query">4.2) Query</h4>
<pre><code>@Service
@RequiredArgsConstructor
public class MemberQuery implements GraphQLQueryResolver{

    private final MemberRepository memberRepository;

    public Member findMembers(String memberId) {

        List&lt;Member&gt; members = memberRepository.findAll();
        Member member = new Member();
        for(Member newMember : members) {
            if(newMember.getMemberid().equals(memberId)) {
                member = memberRepository.findById(newMember.getMembersn())
                        .orElse(null);
            }
        }
        return member;
    }

    public List&lt;Member&gt; allFindMembers(){

        List&lt;Member&gt; member = memberRepository.findAll();

        return member;
    }
}</code></pre><ul>
<li>graphql의 호출 과정은 graphqls schema file -&gt; resolver -&gt; repository 구조로 볼 수 있다. </li>
<li>kickstart의 경우 별도의 resolver 구현이 필요 없으나 추후 커스텀을 해야 할 경우 kickstart를 사용이 어렵다.</li>
</ul>
<h4 id="43-mutation">4.3) Mutation</h4>
<pre><code>@Service
@RequiredArgsConstructor
public class MemberMutation implements GraphQLMutationResolver {

    private final MemberRepository memberRepository;

    public Member registerMember(int memberSn, String memberId, String memberEmail, String memberNumber) {

        Member newMember = Member.builder()
                .membersn(memberSn)
                .memberid(memberId)
                .memberemail(memberEmail)
                .membernumber(memberNumber).build();

        return memberRepository.save(newMember);
    }


    public Boolean deleteMember(String memberId) {
        List&lt;Member&gt; memberList = memberRepository.findAll();
        int deleteChk = 0;

        for(Member member : memberList) {
            if(member.getMemberid().equals(memberId)) {
                memberRepository.delete(member);
                deleteChk += 1;
            }
        }

        if(deleteChk &gt; 0) {
            return true;
        } else {
            return false;            
        }
    }

}</code></pre><h3 id="5-result">5. Result</h3>
<p><img src="https://velog.velcdn.com/images/sg-moomin/post/4292c21f-34fe-421b-885c-cd7b66427774/image.png" alt=""></p>
<ul>
<li>전체 맴버 조회 가능</li>
</ul>
<p><img src="https://velog.velcdn.com/images/sg-moomin/post/dc2ddc5c-c415-4687-8f3d-fc15d6129201/image.png" alt=""></p>
<ul>
<li>특정 맴버를 조회하는것도 가능</li>
</ul>
<p><img src="https://velog.velcdn.com/images/sg-moomin/post/24507b82-9a95-47ae-a6e2-3df6f77e7314/image.png" alt=""></p>
<ul>
<li>맴버 생성 가능 </li>
</ul>
<p><img src="https://velog.velcdn.com/images/sg-moomin/post/6f9fd16e-bf34-4afa-a16a-b14b9411b0f1/image.png" alt=""></p>
<ul>
<li>맴버 삭제 가능 </li>
</ul>
<h2 id="마무리">마무리</h2>
<ul>
<li>현재 포스팅의 경우 Graphqls 파일을 단일로 사용하였으나 추후 N개를 사용하기 위해서는 dataFatcher를 직접 구현해줘야 한다.</li>
</ul>
<h2 id="github-link">GitHub Link</h2>
<ul>
<li><a href="https://github.com/sg-moomin/graphQl_backend_poc_study">GraphQL</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Tistory 대신 Velog를 사용하는 이유]]></title>
            <link>https://velog.io/@sg-moomin/Tistory-%EB%8C%80%EC%8B%A0-Velog%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-3m8d0wsn</link>
            <guid>https://velog.io/@sg-moomin/Tistory-%EB%8C%80%EC%8B%A0-Velog%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-3m8d0wsn</guid>
            <pubDate>Mon, 09 Oct 2023 06:23:37 GMT</pubDate>
            <description><![CDATA[<p>최근까지 신입으로서 직장 생활을 하다보니 포스팅을 할 시간 조차 없었다.
(나름의 변명)</p>
<p>결론을 먼저 말하자면 내가 왜 Tistory에서 Velog로 넘어가려고 하는지를 적어보려고 한다.</p>
<h1 id="담백한-디자인">담백한 디자인</h1>
<ul>
<li>개발자들에게는 마크다운 형식이 익숙하기 때문에 티스토리보다 기록용으로 적합하다고 판단</li>
<li>또한 마크다운 형식으로 굳이 디자인에 신경을 쓰지 않아도 된다는 장점이 매력적인 포인트</li>
</ul>
<h1 id="개발자들의-reference">개발자들의 reference</h1>
<ul>
<li>실제 개발을 하면서 나온 정보들을 볼 수 있다</li>
<li>티스토리에 비해 개발자들에게 적합한 블로그</li>
</ul>
<p>티스토리에 비해 벨로그가 적합하다고 판단은 들지만 블로그 작업 시간적인 여유가 생긴다면 github.io로 넘어가려고 한다. </p>
<p>우선 포스팅을 하러 가야겠다..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 다트게임]]></title>
            <link>https://velog.io/@sg-moomin/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%8B%A4%ED%8A%B8%EA%B2%8C%EC%9E%84</link>
            <guid>https://velog.io/@sg-moomin/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%8B%A4%ED%8A%B8%EA%B2%8C%EC%9E%84</guid>
            <pubDate>Mon, 25 Apr 2022 12:48:59 GMT</pubDate>
            <description><![CDATA[<p>오늘 포스팅 할 내용은 프로그래머스 문제 중 하나인 다트게임 문제를 풀어봤습니다. </p>
<hr>
<p><strong>1. 문제 설명</strong> 
<img src="https://cdn.discordapp.com/attachments/911905192407101463/968126143662280815/unknown.png" alt=""></p>
<hr>
<p><strong>2. 문제 예시</strong> 
<img src="https://cdn.discordapp.com/attachments/911905192407101463/968126272624549918/unknown.png" alt=""></p>
<hr>
<p><strong>3. 문제 풀이</strong> </p>
<p>내용을 잘 읽어보면 문제를 쉽게 풀 수 있습니다. </p>
<p>먼저 S, D, T는 제곱근을 이용해서 구해주면 됩니다.  </p>
<p>스타상(*)과 아차상(#)은 중복이 될 수 있고 효과 중첩이 될 수 있다는 부분만 주의해주면 된다.  </p>
<p><em>*그리고 마지막으로 확인하면 되는 부분은 아차상(#)과 스타상(</em>)은 DartResult 맨 뒤에 나올 수 있다는 점 ** </p>
<p>마지막에 나올 수 있기 때문에 마지막에 종료 표시를 위한 값(&quot;K&quot;)을 넣어주면 조금 더 쉽게 풀 수 있습니다. </p>
<p>코드는 아래와 같습니다.</p>
<pre><code>import math

def solution(dartResult):
    darts = []
    starsNum = []
    result = [0] * 3
    dartStr = &quot;&quot;
    chks = &quot;&quot;
    rDartResult = &quot;&quot;

    rDartResult = dartResult + &quot;K&quot;

    for i in range(len(rDartResult)):
        if rDartResult[i] == &quot;S&quot; or rDartResult[i] == &quot;D&quot; or rDartResult[i] == &quot;T&quot; or rDartResult[i] == &quot;K&quot;:
            darts.append(dartStr + rDartResult[i])
            dartStr = &quot;&quot;
        else:
            dartStr += rDartResult[i]

    for i in range(len(darts)):
        chks = &quot;&quot;
        for j in darts[i]:
            if j == &quot;S&quot;:
                result[i] = int(chks)
                result[i] = int(math.pow(result[i], 1))
            elif j == &quot;D&quot;:
                result[i] = int(chks)
                result[i] = int(math.pow(result[i], 2))
            elif j == &quot;T&quot;:
                result[i] = int(chks)
                result[i] = int(math.pow(result[i], 3))
            elif j == &quot;#&quot; or j == &quot;*&quot;:
                if j == &quot;#&quot;:
                    result[i-1] *= (-1)
                else:
                    result[i-1] *= 2
                    result[i-2] *= 2
            else:
                chks += j

    return sum(result)</code></pre><p>우선 S, D, T, K로 구분을 해준다. </p>
<p>ex) 1S2D*3T -&gt; 1S, 2D, *3T </p>
<p>구분해준 뒤 S, D, T, #, *에 대한 조건들을 부여해주면 됩니다. </p>
<hr>
<p><strong>4. GitHub Code</strong></p>
<p><a href="https://github.com/sg-moomin/algorithmStudy_CodingTest">Sg-moomin GitHub 다트 게임 코드!</a></p>
<p>위의 이미지 링크를 클릭하면 코드 확인이 가능합니다. </p>
<p>GitHub에도 동일하게 코드를 올려놨습니다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[객체지향언어 요약]]></title>
            <link>https://velog.io/@sg-moomin/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%96%B8%EC%96%B4-%EC%9A%94%EC%95%BD</link>
            <guid>https://velog.io/@sg-moomin/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%96%B8%EC%96%B4-%EC%9A%94%EC%95%BD</guid>
            <pubDate>Sun, 13 Feb 2022 08:30:46 GMT</pubDate>
            <description><![CDATA[<p>이번에 다뤄볼 포스팅은 절차지향에 대한 내용입니다. </p>
<h3 id="1-절차지향과-객체지향">1. 절차지향과 객체지향</h3>
<ol>
<li><strong>절차지향(순차적인 처리)</strong><ul>
<li>프로시저 호출의 개념을 바탕으로 하고 있는 프로그래밍이라고 보면 된다. </li>
<li>즉 <strong>함수들의 집합으로 구성되어 연속적으로 처리하는 방법</strong>을 말한다. </li>
<li>이 방법은 실행속도가 빠르다는 장점이 존재했으나 현재는 객체지향을 주로 사용한다. </li>
<li>그 이유는 <strong>유지보수가 어렵다는 단점</strong>이 존재하기 때문이다.<br></li>
</ul>
<ol start="2">
<li><strong>객체지향</strong></li>
</ol>
<ul>
<li>절차와 달리 <strong>객체</strong>들의 집합으로 구성되다. </li>
<li>객체들의 집합으로 프로그램이 유연하며 변경이 쉽게 가능하여 최근에도 많이 사용된다. </li>
</ul>
</li>
</ol>
<h3 id="2-객체지향-특징">2. 객체지향 특징</h3>
<ol>
<li><p><strong>상속</strong></p>
<ul>
<li>클래스들 사이에서 관계를 가진다고 볼 수 있다.</li>
<li>즉 새로 만든 클래스가 기존의 클래스의 자료와 연산을 이용할 수 있다는 것이다.</li>
<li>새로운 클래스는 <strong>자식(서브)클래스</strong>, 기존 클래스는 <strong>부모(수퍼)클래스</strong>라고 부르며 상속을 통해 기존의 클래스를 상속받아 객체를 <strong>조직화</strong> 가능하다. </li>
</ul>
</li>
<li><p><strong>다형성</strong></p>
<ul>
<li>객체의 유형에 따라서 <strong>동일한 명칭의 메소드를 다른 역할로 사용 가능</strong>하다는 의미이다. </li>
<li>이는 <strong>오버라이딩</strong>, <strong>오버로딩</strong>을 말한다. </li>
<li>다형성을 통해 객체의 관계를 조직화 가능하다. </li>
</ul>
</li>
<li><p><strong>캡슐화</strong></p>
<ul>
<li>외부에서 객체 내부의 자료와 메소드에 대한 접근을 하지 못하도록 통제하는 것을 말한다. </li>
<li>이는 <strong>객체의 접근은 오직 공개된 자료와 공개된 메소드만 가능하다는 것</strong>을 말한다. </li>
<li>이에 따라 private, public으로 나눠 공개여부를 구분 가능하다. </li>
</ul>
</li>
</ol>
<h3 id="3-객체지향-장단점">3. 객체지향 장단점</h3>
<ul>
<li><p><strong>장점</strong></p>
<ul>
<li><strong>재사용성</strong><ul>
<li>상속을 통해 기존의 코드 사용하여 표현 가능하며 이는 새로운 프로그램 개발시에 재사용성을 높일 수 있다.  </li>
</ul>
</li>
<li><strong>유지보수가 간편</strong> <ul>
<li>수정 및 기능 추가 시 캡슐화 되어 있어서 주변에 미치는 영향은 적지만 상속을 통해서 기존 코드를 사용가능하기 때문에 유지보수적인 측면에서 효율적이다.</li>
</ul>
</li>
<li><strong>직관적인 코드 분석</strong><ul>
<li>객체로 구분되어 직관적으로 객체,매소드별 코드 분석이 쉬움 </li>
</ul>
</li>
<li><strong>모델링이 좋음</strong><ul>
<li>생각하는 방식대로 개발 가능하기 때문 </li>
</ul>
</li>
</ul>
</li>
<li><p><strong>단점</strong>      </p>
<ul>
<li><strong>절차지향에 비해 실행속도가 느림</strong> </li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[LeetCode] Second Highest Salary 문제풀이]]></title>
            <link>https://velog.io/@sg-moomin/LeetCode-Second-Highest-Salary-%EB%AC%B8%EC%A0%9C%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@sg-moomin/LeetCode-Second-Highest-Salary-%EB%AC%B8%EC%A0%9C%ED%92%80%EC%9D%B4</guid>
            <pubDate>Mon, 10 Jan 2022 13:16:58 GMT</pubDate>
            <description><![CDATA[<p>오늘 포스팅 할 내용은 LeetCode 문제 중 하나인 Second Highest Salary 문제를 풀어봤습니다. </p>
<p><a href="https://sg-moomin.tistory.com/entry/%EC%84%B8%EB%AC%B4%EB%AF%BC%EC%9D%98-%EC%BD%94%EB%94%A9%EC%9D%BC%EA%B8%B0-LeetCode-Second-Highest-Salary-%EB%AC%B8%EC%A0%9C%ED%92%80%EC%9D%B4"><img src="https://cdn.discordapp.com/attachments/911905192407101463/929640817671405599/image_3.png" alt=""></a></p>
<p>위의 이미지 링크를 클릭하면 Tistory 포스팅을 볼 수 있습니다. </p>
<p>포스팅은 위의 Tistory에도 동일하게 진행했습니다. </p>
<hr>
<p><strong>1. 문제 설명</strong> 
<img src="https://images.velog.io/images/sg-moomin/post/8cae0c6f-6eaf-4292-a3d4-03aa95a4b1bd/image.png" alt=""></p>
<hr>
<p><strong>2. 문제 예시</strong> </p>
<p><img src="https://images.velog.io/images/sg-moomin/post/cd22c6c3-b282-4f8f-9959-c12e855774d0/image.png" alt=""></p>
<hr>
<p><strong>3. 문제 풀이</strong> </p>
<p>이번 문제는 말 그대로 2번째로 급여가 높은 사용자의 급여를 출력하면 되며</p>
<p>만약에 2번째로 높은 급여가 없는 경우 Null을 출력하면 된다.</p>
<p>위의 경우를 가장 쉽게 생각해보면 가장 Max의 값을 제외한 값이 2번째의 값이다. </p>
<p><strong>따라서 Max인 값을 제외하고 가장 첫번째의 값을 출력하면 된다.</strong> </p>
<pre><code># Code 
SELECT max(salary) as SecondHighestSalary  
FROM Employee
where salary not in (select max(salary) from Employee)</code></pre><p>위의 설명대로 풀면 위와 같다. </p>
<p>말처럼 가장 첫번째의 Max값을 구하고 해당 값이 아닌 </p>
<p>Max(2번째) 값을 구해주면 된다. </p>
<hr>
<p><strong>4. 결과</strong>
<img src="https://images.velog.io/images/sg-moomin/post/8ba9fca3-97c2-4b9f-acfd-ad12bd243066/image.png" alt=""></p>
<hr>
<p><strong>5. GitHub Code</strong></p>
<p><a href="https://github.com/sg-moomin/algorithmStudy_CodingTest/blob/main/LeetCode/178.%20Rank%20Scores.sql"><img src="https://images.velog.io/images/sg-moomin/post/c0a959b5-a5a3-4e43-b2a0-e20cd7ab6392/image.png" alt=""></a></p>
<p>위의 이미지 링크를 클릭하면 코드 확인이 가능합니다. </p>
<p>GitHub에도 동일하게 코드를 올려놨습니다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[GIT] SSH Key 등록하기]]></title>
            <link>https://velog.io/@sg-moomin/GIT-SSH-Key-%EB%93%B1%EB%A1%9D%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sg-moomin/GIT-SSH-Key-%EB%93%B1%EB%A1%9D%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 09 Jan 2022 09:28:46 GMT</pubDate>
            <description><![CDATA[<p>GitHub에서 레파지토리에 커밋을 할 때 SSH Key를 요청하는데 이 때 매번 ssh-token을 입력하는 것도 귀찮을 때가 있다. </p>
<p>그래서 나는 우선 ssh-key를 github에 등록해줬다. </p>
<p>등록하기 전 내 로컬 .ssh에 key가 존재하는지 확인한다. 
<img src="https://images.velog.io/images/sg-moomin/post/44151d0a-26eb-421f-96fe-aa435fbb3e7c/image.png" alt=""></p>
<p>우선 나는 id_rsa에 키가 존재하기 때문에 따로 키를 만들어주지 않았다. </p>
<p>만약에 자신의 key가 없다고 한다면 아래와 같이 입력하면 된다. </p>
<h3 id="ssh-keygen--t-rsa--c-github-이메일">ssh-keygen -t rsa -C [github 이메일]</h3>
<p>위와 같이 입력하게 되면 rsa key가 발급된다. </p>
<p>해당 키를 가지고 이제 아래와 같은 순서대로 진행하면 된다. </p>
<p><img src="https://images.velog.io/images/sg-moomin/post/3e0cb5c9-8b5a-4188-9f6f-b8d837894306/image.png" alt=""></p>
<ol>
<li>우선 자신의 Setting 화면으로 접속</li>
<li>SSH amd GPG keys -&gt; New SSH key 클릭</li>
</ol>
<p><img src="https://images.velog.io/images/sg-moomin/post/6d0f7be6-5d2e-4107-8fbd-71035c358c51/image.png" alt=""></p>
<ol start="3">
<li>Title과 Key를 작성하면 끝 <ul>
<li>Key는 id_rsa.pup 파일에 있는 내용을 추가 </li>
</ul>
</li>
</ol>
<p>위와 같이 진행하면 SSH-Key가 발급된다. </p>
<p>여기서 중요한건 이제부터 Clone을 받을 때 SSH로 받아야 나중에 push시 SSH-Key에 대해서 확인하지 않는다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[GIT] master Merging 충돌 해결 방법]]></title>
            <link>https://velog.io/@sg-moomin/GIT-master-Merging-%EC%B6%A9%EB%8F%8C-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@sg-moomin/GIT-master-Merging-%EC%B6%A9%EB%8F%8C-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Sat, 18 Dec 2021 17:38:08 GMT</pubDate>
            <description><![CDATA[<h3 id="git-mastermerging-충돌-해결-방법">Git master|Merging 충돌 해결 방법</h3>
<hr>
<h3 id="1-mastermerging-생기는-요인">1. master|merging 생기는 요인</h3>
<p>  <img src="https://cdn.discordapp.com/attachments/817029870944911373/921800213511958608/unknown.png" alt="Gitlab"></p>
<ul>
<li>현재 진행하고 있는 프로젝트에서 기존에 있는 파일명과 동일한 파일을 레파지토리(원격 저장소)에 올릴려고 하다가 충돌이 난 상황이다.  </li>
<li>충돌이 난 경우에 파일 내에서 merge를 하는 방법도 있으나 현재의 경우는 기존에 동일한 파일명이 존재하는데 파일명이 같은 파일을 Push하여 Merge를 하라고 메세지를 알려준다.</li>
<li>현재 상황이 되면 master 옆에 Merging이라고 나오며 현재 병합중 상태임으로 다른 브런치로 넘어갈 수 없다.</li>
</ul>
<h3 id="2-시도한-방법">2. 시도한 방법</h3>
<p>  <img src="https://cdn.discordapp.com/attachments/911905192407101463/921804285983985684/unknown.png" alt="Gitlab"></p>
<ul>
<li>위의 그림처럼 우선 같은 명을 가진 파일이 충돌난 상황이면 merge를 먼저하는 것이 맞다.</li>
<li>그리고 아마도 레파지토리(원격 저장소)의 커밋과 로컬의 커밋이 변경되어서 push를 허용하지 않았던것 같다.  </li>
</ul>
<ol>
<li><h4 id="파일을-직접-변경해주는-방법">파일을 직접 변경해주는 방법</h4>
<p><img src="https://cdn.discordapp.com/attachments/817029870944911373/921811958695604224/unknown.png" alt="Gitlab"></p>
<ul>
<li><p>우선 &quot;git diff&quot; 명령어를 이용하여 레파지토리(원격 저장소)와 로컬의 차이를 비교한다.</p>
</li>
<li><p>비교한 뒤 해당 충돌난 부분을 수정해서 다시 커밋해주면 문제를 해결할 수 있다.</p>
</li>
</ul>
</li>
<li><h4 id="overwrite-update">overwrite update</h4>
<ul>
<li>위의 방식처럼 수정하는 것도 있으나 overwrite update 방법을 진행해봤다.</li>
</ul>
</li>
</ol>
<h3 id="3-overwrite-update">3. overwrite update?!</h3>
<ul>
<li>overwrite update는 기존 레파지토리(원격 저장소)에 있는 내용을 내 로컬에 업데이트 한다는 의미이다.</li>
<li>즉 레파지토리(원격 저장소)에 존재하는 내용과 현재 내 로컬의 내용에서 충돌났을 때 해결할 수 있는 방법 중 하나이다.</li>
</ul>
<h3 id="4-git-로컬-파일-업데이트-하기">4. git 로컬 파일 업데이트 하기</h3>
<ul>
<li><p>가장 먼저 레파지토리(원격 저장소)에 있는 최신 commit 이력을 가져와야 한다.(최신 파일들로 로컬을 업데이트 할 것이기 때문이다.)</p>
</li>
<li><p>그후 레파지토리(원격 저장소)에 있는 파일들을 가져오는 방법으로 진행하면 overwrite update의 과정을 밟을 수 있다.</p>
<p><img src="https://cdn.discordapp.com/attachments/817029870944911373/921813724795387994/unknown.png" alt="Gitlab"></p>
</li>
</ul>
<ol>
<li><h4 id="git-fetch">git fetch</h4>
<ul>
<li>로컬의 master와 레파지토리(원격 저장소)의 master의 최신 이력을 확인할 수 있고 최신 커밋 이력을 로컬로 가져옵니다.</li>
</ul>
</li>
<li><h4 id="git-reset---hard-originmaster">git reset --hard origin/master</h4>
<ul>
<li>현재 HEAD가 가리키는 브랜치를 옮기고 현재 로컬의 디렉토리 상태를 변경해줍니다.</li>
</ul>
</li>
</ol>
<ul>
<li>위의 단계를 진행하고 나면 merging 표기가 사라지게 된다.</li>
<li>즉 overwrite update가 완료되었고 현재 충돌은 해결된 상태이다.</li>
<li>마지막으로 충돌났던 동일한 파일명을 변경하 pull과 merge를 이용해서 레파지토리(원격 저장소)와 로컬 master를 통합시켜주면 내가 올릴려는 파일을 문제없이 레파지토리(원격 저장소)(원격 저장소)에 올릴 수 있다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[GraphQL Study 1탄]]></title>
            <link>https://velog.io/@sg-moomin/GraphQL-Study-1%ED%83%84</link>
            <guid>https://velog.io/@sg-moomin/GraphQL-Study-1%ED%83%84</guid>
            <pubDate>Sat, 18 Dec 2021 16:01:52 GMT</pubDate>
            <description><![CDATA[<h6 id="그래프-ql-study">그래프 QL Study</h6>
<hr>
<h6 id="graphql">GraphQL?</h6>
<ul>
<li>GraphQL은 페이스북에서 만든 쿼리 언어</li>
<li>아직 GraphQl API를 Open API로 공개하지는 않았으나 인기가 높은 편이다.
<img src="https://cdn.discordapp.com/attachments/911905192407101463/920306566731800606/unknown.png" alt="Gitlab"></li>
</ul>
<h6 id="graphql-1">GraphQL?</h6>
<ul>
<li>(SQL)Stucted Query Language와 마찬가지로 쿼리 언어이다.</li>
<li>SQL과 GQL의 언어적 구조 차이가 존재한다.</li>
<li>SQL은 DB 시스템에서 데이터를 가져오는 목적이라면 GQL은 웹 클라이언트가 데이터를 서버로 부터 가져오는 것에 목적을 가진다.</li>
<li>문장은 SQL은 백앤드 시스템에서 작성해서 호출한다면 GQL은 클라이언트 시스템에서 작성하여 호출한다.</li>
</ul>
<h6 id="gql-vs-sql">GQL vs SQL</h6>
<ol>
<li><p>SQL</p>
<ul>
<li>SELECT CUST_NO FROM CUST_MST_TB;</li>
</ul>
</li>
<li><p>GQL</p>
<pre><code>     {
     cust{
         CUST_NO
       }
     }</code></pre></li>
</ol>
<h6 id="rest">REST</h6>
<ol>
<li><p>REST</p>
<ul>
<li><p>Representational State TransFer</p>
</li>
<li><p>자원의 이름을 구분하여 해당 자원의 상태를 주고 받는 것</p>
</li>
<li><p>HTTP URL을 통해 자원을 명시,</p>
</li>
<li><p>HTTP Method(post, get, put, delete)를 통하여 자원에 대한 CRUD Operation을 적용하는 것을 말한다.</p>
<ul>
<li><p>장점</p>
<ol>
<li>Http 프로토콜의 인프라를 그대로 사용하기 때문에 별도의 인프라를 구축할 필요가 없다.</li>
<li>Http 표준 프로토콜에 따르는 모든 플랫폼에서 사용이 가능</li>
<li>서버와 클라이언트의 역할을 분리</li>
</ol>
</li>
<li><p>단점</p>
<ol>
<li>사용가능한 메소드가 4개이다.</li>
<li>표준이 존재하지 않음</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ol>
<ol start="2">
<li>REST API<ul>
<li>REST 기반으로 서비스를 구현  </li>
<li>HTTP 표준을 기반으로 구현하기 때문에 HTTP 지원하는 프로그램 언어로 클라이언트, 서버를 구현 가능하다.</li>
</ul>
</li>
</ol>
<h6 id="graphql-구조">GraphQl 구조</h6>
<ul>
<li><p>쿼리</p>
<pre><code>  {
    cust{
      name
    }
  }</code></pre></li>
<li><p>응답 데이터</p>
<pre><code>    &quot;data&quot; : {
      &quot;cust&quot; : {
        &quot;name&quot; : &quot;sg-moomin&quot;
      }
    }</code></pre><ul>
<li>느낌표를 이용하면 필수 값을 표현한다.</li>
</ul>
</li>
</ul>
<h6 id="오퍼레이션-네임-쿼리">오퍼레이션 네임 쿼리</h6>
<ul>
<li>DB에서 프로시저 개념과 유사</li>
<li>오퍼레이션 네임 쿼리를 이용하면 한번에 인터넷 네트워크 왕복으로 모든 데이터를 가져올 수 있다.</li>
</ul>
<h6 id="리졸버resolver">리졸버(resolver)</h6>
<ul>
<li>GQL에서는 데이터를 가져오는 구체적인 과정을 직접 구현해야 한다.</li>
<li>GQL에서 데이터를 가져오는 구체적인 과정을 resolver가 담당한다.</li>
<li>GQL쿼리에는 각각의 필드마다 함수가 하나씩 존재하는데 해당 함수들을 리졸버라고 한다.<pre><code>ex) async (parent, args, context, info) =&gt; {
}</code></pre></li>
<li>parent : 부모 리졸버가 리턴한 객체</li>
<li>args : 쿼리에서 입력으로 넣은 인자</li>
<li>context : 모든 리졸버에게 전달되며 주로 미들웨어를 통해 입력된 값이 들어 있음</li>
<li>info : 스키마 정보와 더불어 현재 쿼리의 특정 필드 정보를 가짐</li>
</ul>
<h6 id="인트로스펙션resolver">인트로스펙션(resolver)</h6>
<ul>
<li>기존 방식(서버-클라이언트)  <ul>
<li>API 명세서를 주고 받는 절차가 필요함(현재 회사 업무와 동일)</li>
<li>API 명세서 업데이트가 잘 안되는 오차 및 전달하는 타이밍이 오류 발생하는 경우가 다수임</li>
<li>REST 방식의 API 명세서 공유 문제를 해결한 것이 GQl의 인트로스펙션 기능</li>
<li><h5 id="서버-자체에서-스키마로-실시간으로-정보를-공유할-수-있도록-함">서버 자체에서 스키마로 실시간으로 정보를 공유할 수 있도록 함</h5>
</li>
<li><h5 id="이는-스키마-정보만-알면-연동-규격서가-필요-없어짐">이는 스키마 정보만 알면 연동 규격서가 필요 없어짐</h5>
</li>
<li><h5 id="인트로스펙션-쿼리가-따로-존재하지만-gql-라이브러리에-쿼리용-ide를-제공함">인트로스펙션 쿼리가 따로 존재하지만 GQL 라이브러리에 쿼리용 IDE를 제공함</h5>
</li>
</ul>
</li>
</ul>
<h6 id="별칭aliases">별칭(Aliases)</h6>
<ul>
<li>별칭을 사용하는 경우가 있는데 별칭을 사용하는 경우 필드의 결과의 이름을 원하는 이름으로 바꿀 수 있다.
<img src="https://cdn.discordapp.com/attachments/911905192407101463/921043324259934298/unknown.png" alt="Gitlab"></li>
<li>hero 필드는 충돌이 났지만 별칭(empireHero, jediHero)을 지정할 수 있다.</li>
</ul>
<h6 id="fragments">Fragments</h6>
<ul>
<li><p>GQL을 호출해올 경우 쿼리의 속도는 천차 만별인데 이 때 필드를 한번 이상 반복해야 하는 경우가 생긴다.</p>
</li>
<li><p>이 때 Fragments를 이용하여 재사용 가능한 단위를 묶으주면 된다.</p>
<pre><code>{
  &quot;data&quot;: {
    &quot;leftHome&quot;: {
      &quot;name&quot;: &quot;퇴사&quot;,
      &quot;appearsIn&quot;: [
        &quot;집&quot;,
        &quot;야근&quot;,
        &quot;sgMoomin&quot;
      ],
      &quot;friends&quot;: [
        {
          &quot;name&quot;: &quot;가나 초콜릿&quot;
        },
        {
          &quot;name&quot;: &quot;초콜릿 존맛탱&quot;
        },
        {
          &quot;name&quot;: &quot;쉬림프 파스타&quot;
        },
        {
          &quot;name&quot;: &quot;떡볶이 존맛탱구&quot;
        }
      ]
    },
    &quot;rightHome&quot;: {
      &quot;name&quot;: &quot;취직&quot;,
      &quot;appearsIn&quot;: [
        &quot;회사&quot;,
        &quot;정시출근&quot;,
        &quot;rominPic&quot;
      ],
      &quot;friends&quot;: [
        {
          &quot;name&quot;: &quot;코딩업무&quot;
        },
        {
          &quot;name&quot;: &quot;데이터 보정&quot;
        },
        {
          &quot;name&quot;: &quot;할렐루야&quot;
        }
      ]
    }
  }
}
</code></pre></li>
<li><p>위의 필드를 보면 내용이 반복되는 것을 볼 수 있는데 아래와 같이 함축할 수 있다.</p>
<pre><code>{
leftHome: hero(episode: sgMoomin) {
  ...comparisonFields
}
rightHome: hero(episode: rominPic) {
  ...comparisonFields
}
}

fragment comparisonFields on Character {
name
appearsIn
friends {
  name
}</code></pre></li>
<li><p>즉 프래그먼트의 개념은 복잡한 애플리케이션 데이터 요구사항을 더 작게 분할하기 위해 자주 사용합니다.</p>
</li>
</ul>
<hr>
<h6 id="참고자료">참고자료</h6>
<ul>
<li><a href="https://graphql.org/">https://graphql.org/</a></li>
<li><a href="https://tech.kakao.com/2019/08/01/graphql-basic/">https://tech.kakao.com/2019/08/01/graphql-basic/</a></li>
</ul>
]]></description>
        </item>
    </channel>
</rss>