<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>홍인성의 "엄"한 블로그.log</title>
        <link>https://velog.io/</link>
        <description>안녕하세요! 풀스택 노려보고 있는 홍인성입니다!</description>
        <lastBuildDate>Mon, 20 Nov 2023 07:11:56 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>홍인성의 "엄"한 블로그.log</title>
            <url>https://velog.velcdn.com/cloudflare/fulldev_hong/49934d6f-527a-4f9a-8abd-5c921bfc07b8/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. 홍인성의 "엄"한 블로그.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/fulldev_hong" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[퇴원하고 간 우아콘 후기]]></title>
            <link>https://velog.io/@fulldev_hong/%ED%87%B4%EC%9B%90%ED%95%98%EA%B3%A0-%EA%B0%84-%EC%9A%B0%EC%95%84%EC%BD%98-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@fulldev_hong/%ED%87%B4%EC%9B%90%ED%95%98%EA%B3%A0-%EA%B0%84-%EC%9A%B0%EC%95%84%EC%BD%98-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Mon, 20 Nov 2023 07:11:56 GMT</pubDate>
            <description><![CDATA[<h1 id="와-퇴원">와! 퇴원!</h1>
<p>저번 글을 올리고 나서 1달하고 조금이 지난 10월 11일 나는 퇴원했다. ( <del>아싸 이제 놀러갈 수 있겠다고 생각했었죠 이 때는</del> ) 의사쌤은 제발 어디 싸돌아다니지 말고 집에서 얌전하게 얼음찜질하고 안전하게 있으라고 했고 꼬박 1달이 지나서야 걸을 수 있다고 해주셨다</p>
<h1 id="바로-우아콘-지원-가보자">바로 우아콘 지원 가보자</h1>
<p>그렇게 며칠이 지났을 까 우아콘이라는 개발자 컨퍼런스에 지원할 수 있는 찬스가 생겨 바로 지원을 해보았고, 집에서 기다리다가 합격 문자를 받아서 서둘러 짐을 챙겨서 서울로 떠났습니다.
( <del>아침 지하철은 역시 지옥이었습니다..</del> )</p>
<p>전에 NHN 컨퍼런스 때 온 적이 있어서 나름 익숙해 있었다. 히히</p>
<h1 id="우아콘-정리">우아콘 정리</h1>
<h2 id="오프닝-키-노트">오프닝 키 노트</h2>
<p>각가지 트랙 소개 및 여러 분야에서 소개할 세션 소개</p>
<h3 id="ai">AI</h3>
<p>현재는 배달과 ai 기술을 접목해 배달을 해주는 로봇도 만듬</p>
<h3 id="프론트엔드">프론트엔드</h3>
<p>우아한형제들이 자체 제작해서 사용하고 있는 크롬 확장 프로그램 우아한 웹 툴킷, 여러 프론트 세션 소개</p>
<h3 id="보안">보안</h3>
<p>보안은 잘하면 좋지만, 문제가 생기지 않는 이상은 모르는 일이다.</p>
<p>그래서 이런 위험, 보안수준을 가시화해서 관리하는게 중요함</p>
<h3 id="조직-문화">조직 문화</h3>
<p>협업, 소통, 성장, 문화 등 여러가지 기술 외에도 중요한 것이 있다.</p>
<h2 id="오프닝-키-노트-2">오프닝 키 노트 2</h2>
<h3 id="2023년의-변화">2023년의 변화</h3>
<ul>
<li>배달 경험<ul>
<li>음식 배달 주문은 점심, 저녁, 이벤트 시간 때 주문이 집중되고, 1분에 8,000건 이상 주문이 발생할 수 있다.</li>
<li>주문한 음식이 제시간에 도착할 수 있도록 다음과 같은 노력을 하고 있음<ul>
<li>배민1 한집배달 : 배달의 효율을 높이는 것이 굉장히 제한적이었음</li>
<li>알뜰배달 : 데이터와 기술을 바탕으로 만들어진 배달 시스템, 여러 집을 묶어서 배달을 하다 보니 어려움이 있었음<ul>
<li>시간 예측의 문제<ul>
<li>알뜰 배달 같은 경우, 배달 예측 시간을 내기 어려움.</li>
<li>딥 러닝 등을 이용해 해결하는 중</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>탐색 경험<ul>
<li>30만개 음식점, 1만개의 B마트 상품<ul>
<li>선택지가 너무 많다보니 상품을 선택하는 과정이 쉽지 않음</li>
<li>A/B 테스트를 통해 어떻게 해야 UX를 개선할 수 있는지 고민중</li>
<li>사용자가 <strong>더 쉽고 빠르게</strong> 탐색할 수 있는 UX를 제공할 수 있도록 이어갈 예정</li>
</ul>
</li>
<li>추천 기능<ul>
<li>주문 내역과 같은 사용자 데이터를 기반으로 개인화 추천 개선</li>
<li>추천 로직 뿐만 아닌, 추천을 제공하는 방식 또한 개선해나가는 중</li>
<li>기존에 사용하던 머신 러닝 기술이 아닌, GPT(생성aI)를 사용해보기로 함<ul>
<li>앞으로도 다양한 추천 기능을 지속적으로 만들어나갈 예정</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>다양한 경험<ul>
<li>배민은 MAU 20,000,000 + 서비스이다</li>
<li>다양한 상품을 배달주문 할 수 있는 배민 B 마트 이외에, 배민스토어를 열어서 전자제품, 오프라인 마트 등 여러 스토어를 열어서 여러 상품을 살 수 있도록 함</li>
</ul>
</li>
<li>사장님 경험<ul>
<li>가게 운영에 필요한 소식을 놓치지 않게 장사 캘린더를 제공함</li>
<li>가게 운영이나 메뉴 개발에 도움이 되도록 사용자 관리 데이터를 제공</li>
</ul>
</li>
</ul>
<h2 id="세션-1---프론트엔드-개발의-미래-module-federation의-적용">세션 1 - 프론트엔드 개발의 미래, Module Federation의 적용</h2>
<ul>
<li>발표자 : 박세문 / 배민커머스웹프론트개발팀</li>
</ul>
<h3 id="마이크로-프론트엔드란">마이크로 프론트엔드란?</h3>
<h4 id="웹-개발의-역사">웹 개발의 역사</h4>
<ul>
<li>FE + BE = 웹 개발</li>
<li>위 사항에서 문제점이 발생<ul>
<li>배포를 하는 과정에서, FE가 배포를 하면 BE가 안되고, BE가 배포를 하면 FE가 안되는 상황이 발생</li>
<li>결국, FE와 BE가 서로 나뉘게 되어서 개발을 진행함</li>
</ul>
</li>
<li>FE와 BE를 나눠서 웹 개발을 진행했으나 문제점이 여전히 있다</li>
<li>오랜 시간이 지나 고도화가 진행되고, 여러 기술들이 나왔다.<ul>
<li>BE<ul>
<li>Microservices:  하나의 커다란 서비스에서 여러 조그마한 서비스로 나뉘어서 개발을 진행한다.<ul>
<li>도커의 역할이 가장 컸던 것 같다</li>
</ul>
</li>
</ul>
</li>
<li>FE<ul>
<li>컴포넌트 도입 : 재사용성, 생산성, 퍼포먼스 면에서 월등히 높아져서, 고도화 된 프로덕트를 만들어냄<ul>
<li>프로덕트가 많아짐에 따라 복잡함이 커짐<ul>
<li>사이드 이펙트, 의존성 면에서 알아보기 많이 힘들었을거임</li>
</ul>
</li>
<li>그래서 생각해 낸것이 Microservices</li>
</ul>
</li>
<li>Microservices를 도입<ul>
<li>각각의 서비스에 해당하는 백엔드 서비스에 프론트엔드를 각각 개발하여, 불필요한 의사소통을 줄이고 효율을 높임</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="왜-마이크로-프론트엔드를">왜 마이크로 프론트엔드를?</h3>
<ul>
<li>전시 영역 관리 어드민<ul>
<li>각각의 서비스에 어드민이 존재하고, 관리 측면에서 각각의 어드민에 접속<ul>
<li>단, 이 같은 로직에 경우, 서비스가 확장되었을 때 문제가 생김<ul>
<li>N 개의 서비스가 추가될 경우 N개의 어드민이 추가되고, N개의 인증/인가 과정을 만들어야 함</li>
</ul>
</li>
</ul>
</li>
<li>그래서 전시 영역을 하나의 프로덕트로 만들기 시작<ul>
<li>이렇게 만들었을 경우, Host Application 하나에서만 관리하면 되고, 부담이 보다 줄어둔다.</li>
</ul>
</li>
</ul>
</li>
<li>하지만, 마이크로 서비스를 도입했을 때 이점만 있을까?<ul>
<li>유지/보수 관점으로 봤을때는 이점도 있을 수 있다</li>
<li>하지만, 마이크로 프론트엔드를 도입하기 위한 비용, 공부 측면에서는 독이 될 수도 있다.</li>
<li>그리고 새롭게 발생되는 문제도 있다.<ul>
<li>여러개의 프론트엔드로 나뉘었을 때, 여러개의 프론트엔드간에 소통은 어떻게 할지..<ol>
<li>Props 도입<ol>
<li>익숙하고, 허용 가능한 패턴이지만 커플링, 의존성, 리렌더링, 프레임워크를 통일하는 게 전제 조건이다.</li>
</ol>
</li>
<li>Storage API 이용<ol>
<li>브라우저에서 제공하는 세션 스토리지 등을 이용한다.</li>
<li>보안에 취약하지만, 여러 브라우저에서 사용이 가능하고 의존성이 줄어든다.</li>
</ol>
</li>
<li>CustomEvent 이용<ol>
<li>addEventListiner를 이용해 커스텀 이벤트를 추가한다.</li>
</ol>
</li>
<li>Custom MessageBus 이용<ol>
<li>커스텀 이벤트 방식과 유사하지만, 이벤트를 만드는 메시지 박스를 구조에 맞게 설계한다.</li>
</ol>
</li>
</ol>
</li>
<li>프론트엔드의 상태 공유는?</li>
</ul>
</li>
</ul>
</li>
<li>무엇이든 하려 하면 들어가는 것 3가지<ul>
<li>설계</li>
<li>시간</li>
<li>비용</li>
</ul>
</li>
</ul>
<h3 id="마이크로-프론트엔드-아키텍쳐-설계">마이크로 프론트엔드 아키텍쳐 설계</h3>
<ul>
<li>CSR, SSR 모두 렌더링 리엑트 컴포넌트 단계가 존재한다.</li>
<li>프로젝트 외부에 컴포넌트를 불러와서 렌더링을 진행한다면?<ul>
<li>이것이 바로 마이크로 프론트엔드에 개념의 시작이다.</li>
</ul>
</li>
</ul>
<h3 id="module-federation">Module Federation</h3>
<ul>
<li>웹 애플리케이션 개발에서의 코드 공유<ul>
<li>즉, 코드를 배포가 가능한 작은 모듈 단위로 분리하여 분리된 모듈을 동적으로 로드한다.</li>
<li>두가지 옵션이 존재<ul>
<li>export option<ul>
<li>특정 모듈을 다른 애플리케이션에 노출</li>
</ul>
</li>
<li>remote option<ul>
<li>특정 모듈을 다른 애플리케이션에서 로드</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>장점<ul>
<li>유연성의 향상<ul>
<li>애플리케이션을 작고 관리하기 쉬운 모듈로 분할</li>
</ul>
</li>
<li>확장성 향상<ul>
<li>개별 애플리케이션의 크기와 복잡성 감소</li>
<li>유지관리 및 확장의 용이</li>
</ul>
</li>
<li>현업 향상</li>
</ul>
</li>
<li>단점<ul>
<li>복잡성 증가<ul>
<li>dependency, versioning 관리가 필요</li>
<li>개발하고 운영하는데 난이도가 높다</li>
</ul>
</li>
<li>보안 위협<ul>
<li>애플리케이션 강 코드 공유 시 취약점 발생 가능</li>
<li>이에 따른 보안 조치 필요</li>
</ul>
</li>
<li>성능 감소</li>
</ul>
</li>
<li>Nest.js는 다이나믹 임포트를 이용해 사용하게 될것</li>
<li>Module Federation을 이용해서 어떤 프레임워크에 의존성을 가지지 않고, 모듈을 들고와서 임포트를 시켜준다.</li>
</ul>
<h3 id="도입하며-겪었던-문제점--해결-방법">도입하며 겪었던 문제점 &amp; 해결 방법</h3>
<ul>
<li>Typescript 지원 문제<ul>
<li>Remote module을 가져오는 데 있어서 JS에는 타입이 없다.</li>
<li>이것과 관련되어서는 이미 깃허브에 이슈가 있었다.</li>
<li>해결 : 패키지를 사용하자.<ul>
<li>federation type 관련된 패키지를 제공함. (module-federation/typescript)</li>
<li>하지만, 프로젝트를 한번 실행시켜줘야 된다는 이상한 과정이 들어가 있음</li>
</ul>
</li>
<li>또 문제 발생 : 단뱡향만 타입을 지원한다.<ul>
<li>Host는 타입 다운로드만, Remote는 타입 제공만 가능하다.</li>
</ul>
</li>
<li>두번째 해결 방법 : NativeFeferationTypeScriptHost, NativeFeferationTypeScriptRemote 라이브러리 사용<ul>
<li>이상하긴 하지만, 없는것보다는 낫지 않나 쉽다</li>
</ul>
</li>
</ul>
</li>
<li>의존성 비동기 문제<ul>
<li>우리가 가져오고자 하는 모듈이 임포트가 되고 그 다음에 랜더링이 되어야 하는데 먼저 랜더링이 되어버려서 발생하는 문제</li>
<li>해결 : shared 옵션을 넣어서 해결<ul>
<li>이런 방식은 Shell ( Host ) 에서만 제공하는 것을 추천</li>
</ul>
</li>
<li>Next.js 해결 : Next.js 같은 경우는 NextFederatedPlugin을 지원해서 해결했다.</li>
</ul>
</li>
<li>Unstable ( 안정성 부족 )<ul>
<li>빈번한 버전 업데이트<ul>
<li>며칠 지나거나, 개발을 하고 있는 도중에도 버전이 빈번하게 바뀐다.</li>
<li>빠르게 발전하는 걸 보여주는 건 괜찮지만, 개발하는 입장에서는 좀..</li>
</ul>
</li>
<li>레퍼런스 부족</li>
</ul>
</li>
</ul>
<h3 id="도입-이후-얻은-것--잃은-것">도입 이후 얻은 것 &amp; 잃은 것</h3>
<ul>
<li>얻은 것<ul>
<li>프로덕트 공통화</li>
<li>확장의 부담 감소</li>
<li>예측 가능한 리스크 범위</li>
</ul>
</li>
<li>잃은 것<ul>
<li>프로덕트의 단순함</li>
</ul>
</li>
</ul>
<h3 id="앞으로-시도해-보고-싶은-것">앞으로 시도해 보고 싶은 것</h3>
<ul>
<li>Remote Application Generator<ul>
<li>나의 편리함 = 상대방의 불편함</li>
<li>그래서 템플릿을 제공해보자!</li>
<li>프로젝트 템프릿, CLI command를 이용한 generator 구현</li>
<li>배포 파이프라인 구축</li>
</ul>
</li>
<li>Dynamic remotes<ul>
<li>외부의 환경 변수 혹은 리모트 정보를 받아와서 Promise 기반의 처리 방식을 고민중</li>
</ul>
</li>
</ul>
<h3 id="정리">정리</h3>
<ul>
<li>마이크로 프론트엔드 도입으로 의존성은 분리했지만, 구성의 어려움은 존재, 아직 많이 개선할 부분이 남아 있음 ㅇㅇ</li>
</ul>
<h2 id="세션-2-프론트엔드-모킹-환경에-감칠맛-더하기">세션 2. 프론트엔드 모킹 환경에 감칠맛 더하기</h2>
<ul>
<li>발표자 : 류현승 / 코어웹프론트개발팀</li>
</ul>
<h3 id="우리에게-api-모킹-환경이-필요한-이유">우리에게 API 모킹 환경이 필요한 이유?</h3>
<ul>
<li>우리가 생각하는 이상적인 개발 일정<ul>
<li>기획/스펙 검토 → API 서버 개발 → 프론트엔드 개발 → QA</li>
</ul>
</li>
<li>하지만 언제나 이상적인 개발 일정은 아니다.<ul>
<li>만약, API 모킹이 없다면?<ul>
<li>기획/스펙 검토 → 프론트엔드 개발과 동시에 API 서버 개발이 진행되고 API 서버 개발이 지연이 되는 경우 코드가 프리징이 있을 수 있다.</li>
</ul>
</li>
<li>다행히도 우리에게는 API 모킹이 있다<ol>
<li>서버의 의존성을 줄일 수 있다.<ol>
<li>API 스펙을 가진 것만으로 개발이 시작될 수 있다.</li>
</ol>
</li>
<li>API 스펙 사전 검증<ol>
<li>문제점을 사전에 발견할 수 있다.</li>
</ol>
</li>
<li>독립적인 테스트<ol>
<li>유연한 테스트가 가능하다.</li>
<li>실제 API가 없어도 테스트가 가능하다.</li>
</ol>
</li>
</ol>
</li>
</ul>
</li>
<li>요약, 우리는 API 스펙만 있어도 API 모킹을 사용해 테스트가 가능하다.</li>
</ul>
<h3 id="코어-웹프론트-개발팀">코어 웹프론트 개발팀</h3>
<ul>
<li>기능 조직<ul>
<li>주문, 접수, 회원, 앱 등 여러 도메인을 담당하는 팀</li>
<li>협업이 중요한 팀이고, API 도메인, 스펙 등이 분산되어 있음<ul>
<li>이때문에 간단한 작업에도 오래 걸리고, 신입 개발자가 와도 진입장벽이 높다는 문제점이 있다.</li>
</ul>
</li>
<li>배포에 큰 부담감이 있음<ul>
<li>팀 내부적으로 테스트 중요성에 대해 강조하고 있는 상황</li>
</ul>
</li>
</ul>
</li>
<li>이 때문에..<ul>
<li>높은 테스트 커버리지 요구</li>
<li>다양한 테스트 기법 도입</li>
<li>API 호출 케이스가 증가</li>
</ul>
</li>
</ul>
<h3 id="api-모킹-환경-되돌아보기">API 모킹 환경 되돌아보기</h3>
<ul>
<li>사실, 모킹 환경은 이미 도입되어 있었고, 모킹 데이터와 케이스가 준비되어 있었음</li>
<li>개선 전<ul>
<li>Axios를 이용해 모킹을 진행했었다.<ul>
<li>Axios에 종속된 의존성</li>
<li>외부 라이브러리나 Axios를 활용하지 않는 API 모킹이 불가능하다.</li>
<li>네트워크 요청을 브라우저를 통한 트랙킹 불가능</li>
</ul>
</li>
</ul>
</li>
<li>개선 후<ul>
<li>Mock Service Worker<ul>
<li>직관적이고, 단순한 인터페이스</li>
<li>Axios와 같은 라이브러리를 거치지 않고 여러 라이브러리의 모킹 테스트가 가능해짐</li>
<li>노드 환경을 사용하는 서비스에서도 모킹이 가능</li>
<li>또한, 브라우저에서 네트워크 요청을 빠르게 트래킹이 가능하다.</li>
</ul>
</li>
<li>MSW는 충분히 좋은 라이브러리지만, 모든 것을 해결해주지는 않았다.<ul>
<li>실제 프론트엔드를 개발했을 때를 생각해봤을 떄<ul>
<li>결국, 개발자 또한 브라우저를 통해 보는 것이 현실이다.</li>
<li>그리고 모킹이 필요한 이유를 다시 생각해보면 API 스펙 협의 만으로 시작 가능한 병렬 개발도 있었다.<ol>
<li>모킹 동작을 수정해야 하는 경우, 필연적으로 코드 레벨 제어가 필요하다.</li>
<li>갈수록 늘어나는 Mock Data 관리 부담감이 증가한다.</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="api-모킹-환경에-감칠맛-더하기">API 모킹 환경에 감칠맛 더하기.</h3>
<ul>
<li>우선, 브라우저와 MSW 사이에 중간다리 역할이 필요하다.<ul>
<li>그래서 자체개발한 라이브러리가 Mock Service GUI</li>
<li>이것이 무엇을 해결하는 부분들?<ul>
<li>API 단위로 Mock data를 1:n 맵핑할 수 있는 프리셋 기능<ul>
<li>UI에서 즉시 확인 가능</li>
</ul>
</li>
<li>브라우저에서 코드 변경 없이 모킹 환경을 제어할 수 있다.</li>
<li>Mock Data 관리 부담을 완화했다.</li>
</ul>
</li>
<li>현실적인 사용 케이스 관점에서 바라보기<ul>
<li>장바구니에는 여러 장바구니가 존재할 수 있다.</li>
<li>어떤 상황에, 어떤 API를 사용하는지는 거리감이 존재한다.</li>
<li>그래서 나온 것이 “프로파일” 기능<ul>
<li>문서화로서의 효과도 올라가고, 파악이 용이하다.</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>하지만.. 목 데이터의 관리 부담을 줄이는 방법은 없을까?<ul>
<li>API 스펙이 변경되었다면 과제 진행 중 업데이트를 놓친다면?<ul>
<li>응답 값을 체크해보면 어떨까?</li>
</ul>
</li>
<li>이를 이용하여 비교기능을 통해 달라진 부분을 띄워준다.</li>
</ul>
</li>
<li>불편한 점 해소<ul>
<li>개인 설정과 API 모킹 설정은 브라우저에 저장하여, 각 개발 상황에 맞는 모킹 설정, 환경을 제공</li>
</ul>
</li>
<li>테스트 코드에서의 API 모킹 제어<ul>
<li>타입 스크립트를 도입해 제네릭 제어 조건을 설정하여 문자열 리터럴 타입을 추출하고, 동적으로 처리할 수 있도록 구현했다.</li>
</ul>
</li>
</ul>
<h3 id="앞으로-할-일들">앞으로 할 일들</h3>
<ul>
<li>이미 스웨거로 문서화를 잘하고계신답니다.. 굳굳</li>
<li>목 데이터 작성 = 같은 일을 반복하는 것<ul>
<li>스웨거를 OAS로 변환하여 볼 수 있도록 구현</li>
</ul>
</li>
<li>기획자분이나, 서버 개발자와의 협업 개선<ul>
<li>프로파일 기능을 통해 해당 프로젝트에 존재하는 상황을 정의</li>
<li>프리셋 비교 기능을 통한 API 상황 별 비교하여 띄워주는중</li>
</ul>
</li>
<li>이미 베타 환경에서 배포중!</li>
</ul>
<h3 id="우리가-얻은-것">우리가 얻은 것</h3>
<ul>
<li>전달하고자 하는 메시지<ul>
<li>우리는 개발자로써 단순히 코드를 작성하는 것 뿐만 아닌 고객분들께 더 나은 서비스를 제공하는 것!</li>
</ul>
</li>
</ul>
<h1 id="점심시간">점심시간</h1>
<p>이렇게 마치고 점심시간이 되니 무슨 이벤트같은 걸 한다길래 바로 가서 확인해보았다 인재 POOL에 가입하면 뽑기를 해서 경품을 준다고 해서 참여하고 경품을 뽑았더니 개발자 세트가 뽑혔다. 안에는 블루투스 키보드, 거치대 겸 무선 충전기( <del>무선..인가?</del> ), 캐리어 모양 작은 가방, 노트북 거치대가 들어가있었다. ( <del>아싸 노트북 거치대 개꿀</del> )</p>
<h1 id="돌아옴">돌아옴</h1>
<p>그렇게 위 2개 발표를 듣고 점심을 먹은 뒤 다시 돌아왔다. 생각보다 오고가는 시간이 오래 걸려서 2개밖에 못들었지만 시간만 됬다면 다 듣고 왔을 것이다.</p>
<h1 id="비하인드">비하인드</h1>
<p><del>??? : 시간과 예산이 더 있었더라며어어어언</del>
시간이 부족해서 결국 2개만 듣고 나왔다. 이후에 다른 일정도 있었어서 쥬륵
만약 시간이 된다고 하면 프론트엔드와 관련된 세션을 다 듣고 여우롭게 나왔을 것이다..
아무튼 우아콘 후기는 여기까지다. 앞으로는 더뎌진 코딩 실력을 다시 세워야겠다 허허..</p>
<blockquote>
<p>다시 한번 말하지만 여러분들 발 밑은 꼭 보고 다니세요 안그러면 저처럼..</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[학교 갔다 왔더니 발목 인대가 파열되었던 건에 대하여]]></title>
            <link>https://velog.io/@fulldev_hong/%EB%B0%9C%EB%AA%A9-%EB%B8%8C%EB%A0%88%EC%9D%B4%EC%BB%A4-%E3%85%8B%E3%85%8B</link>
            <guid>https://velog.io/@fulldev_hong/%EB%B0%9C%EB%AA%A9-%EB%B8%8C%EB%A0%88%EC%9D%B4%EC%BB%A4-%E3%85%8B%E3%85%8B</guid>
            <pubDate>Mon, 11 Sep 2023 03:54:36 GMT</pubDate>
            <description><![CDATA[<h1 id="왜-세상은-날-억까하는가-대체-왜">왜 세상은 날 억까하는가? 대체 왜?</h1>
<p>2023년 9월 4일 즐겁게 시작한 대학생활 2학기 수업이 일찍 끝나서 &quot;아싸 개꿀~&quot; 이러면서 노래를 들으며 집에 가고 있었는데 갑자기 땅이 파여있어 발이 <strong>뚝- 뚜둑</strong>하고 소리를 내며 고통을 뇌로 보내왔다.</p>
<p>순간 주마등이 스쳐 지나갔지만 정신을 차리고 빨리 택시를 잡아서 집으로 돌아갔다.</p>
<p>결국 그 다음 수업을 전부 캔슬하고 다음날 병원을 갔다.</p>
<h1 id="인대-파열">인대 파열..</h1>
<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/9e8ba43b-3089-4d39-8534-71d2fcb219d2/image.jpg" alt=""></p>
<p>병원에서 진료를 받아봤더니, 다음과 같은 결과가 나왔다.
<strong>뼈는 이상이 없는데요.. 발목의 인대가 2개 이상 파열되서 수술을 해야겠네요..</strong>
이 말을 듣자마자 기분이 오묘해졌다.</p>
<ul>
<li>학교는 어쩌지?</li>
<li>노트북 가져와야 하나?</li>
<li>수술 처음인데;;</li>
<li>입원 처음인데;;</li>
<li>하ㅏㅎ하하하핳ㅎㅎㅎ</li>
</ul>
<h1 id="본인-방금-검사-빨리-끝나는-상상함-ㅋㅋ">본인 방금 검사 빨리 끝나는 상상함 ㅋㅋ</h1>
<p>병원에 간 그날 바로 입원 수속을 밟고 병실로 이동했다.
수술 전에 해야 할 검사가 있다고 해서 후딱 해치우고 오는 상상을 했으나.. 어림없지! 바로 피 안뽑혀버리기!</p>
<p>내 혈관은 워낙 얇아서 맞아도 바로 도망가버린다고 여러번을 꽃아서 성공했다;
( 고생하셨습니다.. 간호사 누나들.. )</p>
<h1 id="수술">수술</h1>
<p>수술에 들어갔다. 원래는 하반신 마취만 한다고 했지만 주사바늘이 자꾸 휜다고 해 결국 전신마취로 들어갔다. 마스크를 씌우고 5초 뒤에 잠든다고 해서 5초를 세봤다. 눈 감고 일어났는데 병실 앞 엘리베이터였다.
<strong>.. 뭐지 시바 타임리프인가?</strong> 시간이 돌아간것처럼 느껴졌는데 수술 끝났단다 ㅋㅋ;
마취가 풀리자마자 갑자기 고통이 찾아왔다. 발목이 겁나 땡겨서 놀랐다.</p>
<h1 id="현황">현황</h1>
<p>현재는 아직 입원을 하고 있고. 오늘( 9/11 ) 목발 연습을 한다고 했다.
통증은 많이 나아졌으며, 아무래도 대학교는 휴학을 내야 된다고 생각해 현재 서류를 정리중이다.
근데 병원에서도 코딩하고 싶어서 노트북 가져온 나면 개추 ㅋㅋ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 #0 - 그게 뭔데 씹X아]]></title>
            <link>https://velog.io/@fulldev_hong/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-0-%EA%B7%B8%EA%B2%8C-%EB%AD%94%EB%8D%B0-%EC%94%B9X%EC%95%84</link>
            <guid>https://velog.io/@fulldev_hong/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-0-%EA%B7%B8%EA%B2%8C-%EB%AD%94%EB%8D%B0-%EC%94%B9X%EC%95%84</guid>
            <pubDate>Tue, 03 Jan 2023 03:29:10 GMT</pubDate>
            <description><![CDATA[<h2 id="시작하기-전">시작하기 전</h2>
<p>본격적으로 알고리즘 공부에 들어서기 전 간단하게 개념만 정리하고 가겠습니다.
참고로 이 시리즈는 <a href="https://www.youtube.com/playlist?list=PLHqxB9kMLLaPOp0jh591QhPvbz4H266SS">주니온TV</a> 에서 강의를 듣고 정리한 내용입니다! ( 무료이니 꼭 봐보세요!! )</p>
<h2 id="알고리즘이-뭔데">알고리즘이 뭔데</h2>
<p>알고리즘이란 어떤 문제를 <strong>컴퓨터</strong>로 풀기위한 <strong>효율적 절차</strong>라고 정의합니다.
중요한 것은, 문제를 그냥 푸는 것이 아닌, <strong>단계</strong>별로 명확하게 기술해야 합니다.</p>
<blockquote>
<p><em>알고리즘의 이름에 어원</em>
7세기에 등장한 페르시아에 수학자인 <strong>알콰리즈미(Al-Khwarizmi)</strong>의 이름에서 따온것이 현재의 <strong>알고리즘</strong>이 되었다.</p>
</blockquote>
<h2 id="왜-공부해야-하는데">왜 공부해야 하는데?</h2>
<p>위에서 말했듯 문제를 <strong>컴퓨터</strong>로 풀기 위해서 공부해야 합니다.
단순히 우리의 뇌로 문제를 푼다면 할수야 있겠지만 너무 오래 걸리겠죠?
그래서 컴퓨터 프로그래밍 언어를 사용해서 문제를 풀어내는 것입니다.</p>
<p>결론적으로 말해서, 다양한 문제 해결 방법을 배워서 알고리즘 문제를 <strong>이해</strong>하고, <strong>효율적</strong>으로 해결하는 방법을 배워야 한다는 거죠.</p>
<h2 id="이거-공부해서-뭐가-좋음">이거 공부해서 뭐가 좋음?</h2>
<p>일단, 코딩 테스트와 면접을 준비하기 위해서는 꼭 배워야 합니다.
그리고 여러 경진대회에서 쓰이는 것이 알고리즘입니다.
만약 알고리즘을 전부 배워서 경진대회 나간다? 상 싹다 쓸어갈 수 있습니다.
그리고 새로운 문제를 만나더라도 그것을 효율적으로 해결할 수 있습니다.</p>
<h2 id="문제는-뭐고-해답은-뭔데">문제는 뭐고, 해답은 뭔데?</h2>
<p>문제는 당연하게 해답을 찾기 위해 물어보는 질문입니다.
근데 여기서 좀 생소한 단어가 등장합니다.</p>
<p><strong>Parameter(파라미터)</strong>, 특정한 값이 지정되어 있지 않은 변수입니다.
f(<strong>x</strong>) &lt;- 요 x를 담당하는 녀석입니다.</p>
<p><strong>instance(인스턴스, 입력사례)</strong>, 문제에 파라미터에 지정된 값입니다.
예를 들어보죠. 만약 f(x) = x + 5 라고 해봅시다.
그럼 f(5)는 뭘까요? f(5) = 5 + 5 / f(5) = 10
이렇게 x에 들어가게 될 값을 <strong>입력사례</strong> 다른 말로는 <strong>인스턴스</strong>라고 합니다.</p>
<p>즉, 특정 입력사례의 해답 = 파라미터를 입력사례로 질문한 문제의 해답이라는 소리입니다.</p>
<h2 id="알고리즘이-뭔데-22">알고리즘이 뭔데 22</h2>
<p>어떤 문제의 <strong>모든 입력사례</strong>에 대해서 해답을 찾아주는 단계별 절차입니다.
f(x) = x + 5 라는 알고리즘을 찾았다고 해봅시다.
그럼 이 x가 실수의 원소다라고 했을때 어떤 값을 대입하든 해답을 찾을 수 있어야 합니다.</p>
<p>즉, 입력 파라미터에 어떤 입력 사례가 주어지더라도 해답을 찾을 수 있는 절차가 알고리즘입니다.</p>
<h2 id="마치며">마치며</h2>
<p>자, 다음시간에는 대표적인 알고리즘 문제인 <strong>순차 탐색 문제</strong>를 알아봅시다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Life.Next() ( 다음 계획 )]]></title>
            <link>https://velog.io/@fulldev_hong/Life.Next-%EB%8B%A4%EC%9D%8C-%EA%B3%84%ED%9A%8D</link>
            <guid>https://velog.io/@fulldev_hong/Life.Next-%EB%8B%A4%EC%9D%8C-%EA%B3%84%ED%9A%8D</guid>
            <pubDate>Tue, 03 Jan 2023 02:08:24 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/4792bbf3-2d4d-4526-bf8c-e1cc66a25422/image.png" alt=""></p>
<h2 id="지난-이야기">지난 이야기</h2>
<p>지난번 인생을 재정의하고 오르지 공부를 하겠다고 선언한 홍XX군..
덕분에 인생에 쓴맛을 깨닫고 L3 공부에 전력을 다한 결과</p>
<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/2d052169-d372-414b-b37f-b68b063212a6/image.png" alt=""></p>
<p>합격하고 말았다. <del>어케했어</del></p>
<p>추가로 더 좋은 소식은 내가 가천대학교 조기취업형계약학과에 붙었다는 것이다.
<img src="https://velog.velcdn.com/images/fulldev_hong/post/9c4927b4-d05c-4829-b81b-c1a287195d6b/image.png" alt=""></p>
<p><del>어케했냐</del></p>
<h2 id="그래서-다음-플랜은">그래서 다음 플랜은?</h2>
<p>일단 내가 지금 부족한것은</p>
<ul>
<li>자바 ( 스프링 )</li>
<li>프론트 기술 ( 전부 )</li>
<li>알고리즘 ( 전부 )</li>
</ul>
<p>위 3가지이다.</p>
<p>그래서 내가 지금 해야 될걸 정했다. 바로 <strong>알고리즘</strong>이다.
알고리즘은 모든 프로그래밍 언어에서 중요한 부분이라고 들었다.
코딩 테스트와 면접때도 알고리즘 기술 하나도 모르면 ㅈ된다고 들었고
그래서 알고리즘에 대한 지식을 키워나가고자 한다.</p>
<h2 id="어떻게-공부할건데">어떻게 공부할건데?</h2>
<p>알고리즘은 우선 파이썬으로 공부한다.
왜 항상 하던 자바가 아니라 파이썬이냐?
현재 가장 거론이 많이 되는 언어가 <strong>파이썬</strong>이기 때문이다.
그래서 먼저 파이썬으로 공부를 한 다음, 이 파이썬 코드를 자바로 바꿔볼것이다.
내가 패스트캠퍼스 강의를 들으면서 강사님도 여러번 말씀해주셨던건데,
<strong>지금 보고 있는 이 코드를 다른 언어로 구현할 수 있다면 너의 기술 폭은 더 성장할 것이다.</strong>
또, 다른 언어로 구현하고 난 뒤에는 프로그래머스, 백준에 있는 여러 문제들을 풀어보고 그 풀이를 쓰면서 어떻게 하면 더 효율적으로 구현할 수 있을지 생각해 볼 것이다.</p>
<h2 id="알고리즘-velog에-올릴거임">알고리즘 Velog에 올릴거임?</h2>
<p>예압.
올리고 나서 또 돌려보면서 공부할 생각이다.</p>
<h2 id="-전-회사-차장님이-해주신-좋은-말">+ 전 회사 차장님이 해주신 좋은 말</h2>
<p>전 회사를 떠나기 전 차장님과 상담을 통해 여러가지 정보를 얻게 되었다.</p>
<h3 id="풀스택을-지향하는-건-좋지만-그걸-이력서에-넣지는-마라">풀스택을 지향하는 건 좋지만 그걸 이력서에 넣지는 마라.</h3>
<p>알다싶이 나는 풀스택 프로그래머가 목표이다. 하지만 차장님께서는
<strong>풀스택을 지향하는 것은 좋지만, 그걸 이력서에 넣으면 좀 위험하다.</strong> 라고 하셨다.</p>
<p>차장님)
풀스택이라고 잡XX같은 사이트에 올린다 치자, 그렇다면 너를 채용하는 회사는 어떤 회사일까? 아마 프론트와 백을 한번에 다 잡고 싶어하는 안좋은 회사일 가능성이 높다.
그래서 IT시장에서 너의 몸값은 상당히 떨어질 것이다.</p>
<p>반면, 백엔드와 프론트 둘중 하나를 확실하게 정하고 간다면 어떻게 될까? 
너를 채용하는 회사는 전문적으로 백엔드 or 프론트를 하는 사람을 뽑는 회사일 가능성이 높다.
그래서 IT시장에서 너의 몸값은 상당히 높아질 것이다.</p>
<h3 id="영어를-많이-배워둬라">영어를 많이 배워둬라.</h3>
<p>차장님 )
영어를 많이 배워둬라. 회화 수준까진 아니더라도, 스택오버플로우나 외국 프로그래밍 공식 Docs를 조금이라도 해석할수 있는 수준까진 가야한다.
요즘엔 해석툴이 많이 나오지만, 그 해석툴 번역하는 성능이 그렇게 좋진 않다.
해석하는 결과가 글쓴이에 글을 잘못 해석하여 줄 가능성이 높다.
또한, 트렌드 시장에서 대부분 새로운 기술이 나오면 그건 영어로 작성되있을 확률이 99%이다.
해석본이 나오면 그때는 이미 늦은것이다. 새로운 트렌드에 대한 정보를 누구보다 빨리 접해야 하는것이 바로 <strong>개발자</strong>다.
영어를 많이 배워두면 너의 몸값은 지금에 1.5배로 오를것이다.</p>
<p>라고 하셨다. 생각해보니 맞는 말이다.
풀스택이라고 이력서에 넣는것보다는 차라리 백엔드, 프론트 둘중 하나를 확실하게 정해서 가는 것이 좋다고 차장님의 말을 듣고 깨달았다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조 #15 - 컬렉션 프레임워크 : Map & HashMap]]></title>
            <link>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-15-%EC%BB%AC%EB%A0%89%EC%85%98-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC-Map-HashMap</link>
            <guid>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-15-%EC%BB%AC%EB%A0%89%EC%85%98-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC-Map-HashMap</guid>
            <pubDate>Wed, 14 Dec 2022 05:40:34 GMT</pubDate>
            <description><![CDATA[<p>이 포스트는 FastCampus에 <a href="https://fastcampus.co.kr/dev_online_javaend"> 이 강의</a>를 보고 포스팅되었습니다.
문제가 될 시 삭제될 예정입니다.</p>
<h2 id="map은-뭐고">Map은 뭐고..</h2>
<p>Map은 <strong>Key-Value</strong> 구조로 되어있는 자료구조입니다.
키와 값이 하나의 쌍으로 연결되어 있어 키를 통해 값에 접근을 할 수 있습니다.
대표적인 클래스는 <strong>HashMap</strong>이 있습니다.</p>
<h2 id="hashmap">HashMap?</h2>
<p>Map 인터페이스를 구현한 클래스입니다.
현재 가장 많이 사용되는 클래스이기도 하죠.
Key-Value를 쌍으로 관리하는 메서드가 존재합니다.
Key를 이용하여 값을 지정, 꺼내오기가 가능합니다.</p>
<ul>
<li>이 부분은 Hash로 구현이 되어 있습니다.</li>
</ul>
<p>Key가 되는 객체는 중복될 수 없고, 객체가 중복되는지 확인하기 위한 equals()와 hashCode() 메서드를 구현해야 합니다.
이 놈으로 멤버십 프로그램을 리팩토링 해보겠습니다.</p>
<h2 id="늘-말하는거긴-하지만-코드는-어디에">늘 말하는거긴 하지만.. 코드는 어디에?</h2>
<p>코드는 제 <a href="https://github.com/BackdevHong/Java-Generic-Collection">깃허브</a>에 올라와 있습니다.
<del>오는 김에 팔로우랑 스타도 눌러줘잉</del></p>
<h2 id="memberhashmap-클래스-생성-및-생성자-구성">MemberHashMap 클래스 생성 및 생성자 구성</h2>
<pre><code class="language-java">public class MemberHashMap {
    private HashMap&lt;Integer, Member&gt; hashMap; // HashMap 클래스 import

    public MemberHashMap() {
        hashMap = new HashMap&lt;&gt;(); // 빈 hashMap 생성
    }
}</code></pre>
<h2 id="create-remove-메서드-구현">Create, Remove 메서드 구현</h2>
<pre><code class="language-java">public void addMember(Member member) {
    hashMap.put(member.getMemberId(), member);
} // memberId : Member 이렇게 저장할 예정

public boolean removeMember(int memberId) {
    if (hashMap.containsKey(memberId)) { // 만약 그 키에 해당하는 유저가 있다면
        hashMap.remove(memberId); // 해당 유저를 지우고
        return true; // 완료됬다는 의미에 True를 반환함.
    }
    System.out.println(&quot;그 아이디에 해당하는 사람이 없습니다.&quot;); // 만약 없다면
    return false; // false를 반환함
}</code></pre>
<h2 id="전체-멤버-출력-메서드-구현">전체 멤버 출력 메서드 구현</h2>
<pre><code class="language-java">public void showAllMember() {
    Iterator&lt;Integer&gt; ir = hashMap.keySet().iterator(); // iterator 생성

    while(ir.hasNext()) { // 다음 id가 없을떄까지
        int key = ir.next(); // key를 다음 요소의 id로 설정하고
        Member member = hashMap.get(key); // 그 key로 Member를 가져온다.
        System.out.println(member); // 출력
    }
}</code></pre>
<h2 id="테스트-코드-작성">테스트 코드 작성</h2>
<pre><code class="language-java">public class MemberHashMapTest {
    public static void main(String[] args) {
        Member member1 = new Member();
        Member member2 = new Member();
        Member member3 = new Member();
        Member member4 = new Member();

        member1.setMemberId(1);
        member1.setMemberName(&quot;아스나&quot;);
        member2.setMemberId(2);
        member2.setMemberName(&quot;키리토&quot;);
        member3.setMemberId(3);
        member3.setMemberName(&quot;홍인성&quot;);
        member4.setMemberId(4);
        member4.setMemberName(&quot;유지오&quot;);

        MemberHashMap hashList = new MemberHashMap();

        hashList.addMember(member1);
        hashList.addMember(member2);
        hashList.addMember(member3);
        hashList.addMember(member4);

        hashList.showAllMember();
    }
}</code></pre>
<p>테스트코드를 돌려보면 다음과 같이 결과가 나옵니다.</p>
<pre><code class="language-java">Member{memberId=1, memberName=&#39;아스나&#39;}
Member{memberId=2, memberName=&#39;키리토&#39;}
Member{memberId=3, memberName=&#39;홍인성&#39;}
Member{memberId=4, memberName=&#39;유지오&#39;}</code></pre>
<h2 id="번외">번외</h2>
<p>HashMap에는 저렇게 귀찮게 while문을 쓰지 않더라도 바로 print를 시킬 수 있습니다.
어떻게 하는건지 알아보겠습니다.</p>
<pre><code class="language-java">public void showAllMember() {
    System.out.println(hashMap);
}</code></pre>
<p>이러고 다시 테스트 코드를 돌려보겠습니다.</p>
<pre><code class="language-java">{
  1=Member{memberId=1, memberName=&#39;아스나&#39;}, 
  2=Member{memberId=2, memberName=&#39;키리토&#39;}, 
  3=Member{memberId=3, memberName=&#39;홍인성&#39;}, 
  4=Member{memberId=4, memberName=&#39;유지오&#39;}
}</code></pre>
<p>이런식으로 key와 value가 출력이 되는것을 보실 수 있습니다.</p>
<h2 id="마치며">마치며</h2>
<p>여기서 다뤄보지는 않았지만 key를 기준으로 정렬을 하는 TreeMap도 있습니다.
여기까지 컬렉션 프레임워크를 다뤄보았습니다.
사실 이 외에도 많은 클래스가 있지만 다 외울 필요는 없고 이런 대표적인 것들만 외우셔도 충분하실 것 같습니다.</p>
<p>그럼 20000!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조 #15 - 컬렉션 프레임워크 : TreeSet With Comparable & Comparator]]></title>
            <link>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-15-%EC%BB%AC%EB%A0%89%EC%85%98-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC-TreeSet-With-Comparable-Comparator</link>
            <guid>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-15-%EC%BB%AC%EB%A0%89%EC%85%98-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC-TreeSet-With-Comparable-Comparator</guid>
            <pubDate>Tue, 13 Dec 2022 07:28:05 GMT</pubDate>
            <description><![CDATA[<p>이 포스트는 FastCampus에 <a href="https://fastcampus.co.kr/dev_online_javaend"> 이 강의</a>를 보고 포스팅되었습니다.
문제가 될 시 삭제될 예정입니다.</p>
<h2 id="treeset은-뭐하는-놈인데">TreeSet은 뭐하는 놈인데?</h2>
<p>TreeSet은 Set중에서도 정렬을 위해서 사용되는 놈입니다.
이 TreeSet은 내부적으로 <strong>BST(이진검색트리)</strong> 로 구현이 되어 있습니다.
BST를 구성하는 방법과 정렬하는 방법은 <a href="https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-3-%EB%B9%84%EC%84%A0%ED%98%95#%ED%8A%B8%EB%A6%ACtree">여기</a>서 확인하시면 됩니다.
여기서 중요한 부분은 요소가 추가될때는 기존에 있던 요소와 비교를 해야 한다.
&quot;그래서 이 비교하는 것을 어떻게 구현할까?&quot;를 정해줘야 합니다.
그래서 전 시간인 HashSet은 Equals()와 hashCode()로 논리적 비교를 했다면
이번 시간에 쓸 TreeSet은 기존에 있던 애하고 비교를 해서 어디로 들어가야 하는지를 구현해야 합니다.
그래서 구현하는 것이 Comparable과 Comparator입니다.</p>
<blockquote>
<p>String, Integer등 JDK의 많은 클래스들은 이미 Comparable를 구현해놓았답니다</p>
</blockquote>
<h2 id="treeset-함-써보자">TreeSet 함 써보자</h2>
<p>테스트 코드를 한번 적어보겠습니다.</p>
<pre><code class="language-java">import java.util.TreeSet;

public class TreeSetTest {

    public static void exportStr(TreeSet&lt;String&gt; T) {
        for(String str : T) {
            System.out.println(str); // 출력
        }
    }
    public static void main(String[] args) {
        TreeSet&lt;String&gt; treeSet = new TreeSet&lt;&gt;(); // TreeSet 생성

        treeSet.add(new String(&quot;홍길동&quot;));
        treeSet.add(new String(&quot;간감상&quot;));
        treeSet.add(new String(&quot;다부진&quot;));
        treeSet.add(new String(&quot;키리토&quot;));
        treeSet.add(new String(&quot;미도리야&quot;));
        treeSet.add(new String(&quot;토리코&quot;)); // String 데이터 집어넣기

        exportStr(treeSet); // 출력 함수 실행
    }
}</code></pre>
<p>결과는 아래와 같이 나왔습니다.</p>
<pre><code>간감상
다부진
미도리야
키리토
토리코
홍길동</code></pre><p><img src="https://velog.velcdn.com/images/fulldev_hong/post/bb39df06-7f61-44e0-8bc1-4410851f85fe/image.png" alt=""></p>
<h2 id="멤버십-리팩토링">멤버십 리팩토링</h2>
<p>전에 만들던 멤버십을 TreeSet을 이용해서 리팩토링 해보겠습니다.</p>
<h2 id="membertreeset-생성">MemberTreeSet 생성</h2>
<pre><code class="language-java">import java.util.TreeSet;
import java.util.Iterator;

public class MemberTreeSet {
    private TreeSet&lt;Member&gt; memberTreeSet;

    public MemberTreeSet() {
        memberTreeSet = new TreeSet&lt;&gt;();
    }

    public void addMember(Member member) {
        memberTreeSet.add(member);
    }

    public boolean removeMember(int memberId) {
        // Iterator 선언
        Iterator&lt;Member&gt; ir = memberTreeSet.iterator();

        // ir.hasNext()가 false가 될 때까지 돈다.
        while(ir.hasNext()) {
            Member member = ir.next(); // 다음 요소를 member에 저장시키고

            if (member.getMemberId() == memberId) { // memberId가 맞는지 확인
                memberTreeSet.remove(member); // 삭제하고
                return true; // true 반환
            }
        }
        System.out.println(&quot;해당 멤버id를 가지고 있는 유저가 없습니다.&quot;);
        return false;
    }

    public void showAllMember() {
        for (Member member : memberTreeSet) {
            System.out.println(member);
        }
    }
}</code></pre>
<h2 id="테스트-코드-작성">테스트 코드 작성</h2>
<pre><code class="language-java">public class MemberTreeSetTest {
    public static void main(String[] args) {
        Member member1 = new Member();
        Member member2 = new Member();
        Member member3 = new Member();
        Member member4 = new Member();
        Member member5 = new Member();

        member1.setMemberId(1); 
        member1.setMemberName(&quot;아스나&quot;);

        member2.setMemberId(2);
        member2.setMemberName(&quot;키리토&quot;);

        member3.setMemberId(3);
        member3.setMemberName(&quot;홍인성&quot;);

        member4.setMemberId(4);
        member4.setMemberName(&quot;유지오&quot;);

        member5.setMemberId(1);
        member5.setMemberName(&quot;홍길동&quot;);

        MemberTreeSet hashList = new MemberTreeSet();

        hashList.addMember(member1);
        hashList.addMember(member2);
        hashList.addMember(member3);
        hashList.addMember(member4);
        hashList.addMember(member5);

        System.out.println();
        hashList.showAllMember();
    }
}</code></pre>
<p>이렇게 돌리시면 바로 오류가 발생합니다.
<code>java.lang.ClassCastException: ...     java.lang.Comparable</code></p>
<p>Comparable이 구현되어 있지 않다는 뜻입니다.
아까 말했듯 String, int는 Comparable이 구현되어 있지만 지금 사용하고 있는 Member 클래스에 경우, Comparable이 구현되어 있지 않다는 것이죠.</p>
<p>그래서 현재 가지고 있는 Member 클래스에 Compare를 구현해보겠습니다.</p>
<h2 id="member-클래스에-comparable-구현">Member 클래스에 Comparable 구현</h2>
<pre><code class="language-java">public class Member implements Comparable&lt;Member&gt;{

    // prev code

    @Override
    public int compareTo(Member member) {
        if (this.memberId &gt; member.memberId) {
            return 1;
        } else if ( this.memberId &lt; member.memberId) {
            return -1;
        } else {
            return 0;
        }
    }
}</code></pre>
<p>Member 클래스에 Comparable 인터페리스를 상속받아서 구현하면 됩니다.
현재는 id로 정렬할 거니까, id쪽만 구현해둡시다.
그리고 다시 테스트 코드를 실행시키면...!
<img src="https://velog.velcdn.com/images/fulldev_hong/post/9f995b47-952c-44ed-b14f-a29decdf12df/image.png" alt=""></p>
<p>짜잔! 이렇게 중복도 없애고, 정렬도 됩니다.</p>
<h2 id="어케믿음-ㅋ-순서대로-집어넣었잖어-ㅋㅋ">어케믿음 ㅋ 순서대로 집어넣었잖어 ㅋㅋ</h2>
<p>뭐, 순서를 섞어서 테스트코드를 적는 방법도 있겠지만, 더 확실한 방법으로 인증하겠습니다.
그렇다면 저 순서를 뒤집어 보겠습니다.</p>
<h2 id="순서-역순출력">순서 역순출력</h2>
<p>그러기 위해선 다시 Member 클래스로 가셔서 compareTo를 수정하셔야 합니다.</p>
<pre><code class="language-java">@Override
public int compareTo(Member member) {
    if (this.memberId &gt; member.memberId) {
        return -1;
    } else if ( this.memberId &lt; member.memberId) {
        return 1;
    } else {
        return 0;
    }
}</code></pre>
<p>return에 있는 1과 -1의 위치를 서로 바꿔주기만 하면 됩니다.
이렇게 놓고 다시 테스트 코드를 돌려보겠습니다.
<img src="https://velog.velcdn.com/images/fulldev_hong/post/a4706bfa-3e4d-4d73-865d-3945de1c24db/image.png" alt=""></p>
<p>자 역순으로 출력됬죠?
이렇게 정렬 기능도 된다는 것을 입증해냈습니다.</p>
<h2 id="너무-코드가-길다">너무 코드가 길다..</h2>
<p>코드를 한번 줄여볼게요.</p>
<pre><code class="language-java">@Override
public int compareTo(Member member) {
    if (this.memberId &gt; member.memberId) {
        return 1;
    } else if ( this.memberId &lt; member.memberId) {
        return -1;
    } else {
        return 0;
    }
}</code></pre>
<p>이 코드를 한줄로 만들어보겠습니다.</p>
<pre><code class="language-java">@Override
public int compareTo(Member member) {
    return this.memberId - member.memberId;
}</code></pre>
<p>이렇게 한줄로 끝낼 수 있습니다.
역순도 진짜 간단합니다.</p>
<pre><code class="language-java">@Override
public int compareTo(Member member) {
    return (this.memberId - member.memberId) * (-1);
}</code></pre>
<p>뒤에 -1을 곱해주시면 됩니다.</p>
<p>자 이제 Comparable은 아셨고, 다음으로 Comparator로 구현해봅시다.</p>
<h2 id="comparable-vs-comparator">Comparable VS Comparator</h2>
<p>Comparable과 Comparator의 다른점은 매개변수에 차이입니다.
Comparable은 매개변수를 한개를 받죠? 하지만 Comparator는 2개를 받습니다.
즉, 비교대상이 다르다는 거죠.
Comparable는 비교대상이 <strong>나</strong>인거고, Comparator은  <strong>나와 비교대상</strong>이라는 거죠.
한번 코드를 짜볼까요?</p>
<pre><code class="language-java">public class Member implements Comparator&lt;Member&gt; {

    public Member(){} // 기본 생성자 생성

    @Override
    public int compare(Member m1, Member m2) { // Compare 구현
        return (m1.memberId - m2.memberId);
    }
}
</code></pre>
<p>그리고 한가지 작업을 더 해주셔야 합니다.
아까 만들었단 MemberTreeMap에 생성자 부분에 자신이 어떤 타입으로 Comparator를 구현해놨는지, 그 대상을 적어주셔야 합니다.</p>
<pre><code class="language-java">public MemberTreeSet() {
    memberTreeSet = new TreeSet&lt;Member&gt;(new Member());
}</code></pre>
<h2 id="comparator-얜-어따-씀">Comparator 얜 어따 씀?</h2>
<p>사실 제일 많이 사용하는 것은 Comparable입니다.
Comparator는 이미 Comparable로 구현된 것을 다시 재구현 시킬 수 있죠.
말보다는 코드를 보시는게 이해가 되실겁니다.</p>
<pre><code class="language-java">import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;

class MyCompare implements Comparator&lt;String&gt; {

    @Override
    public int compare(String s1, String s2) {
        return (s1.compareTo(s2)) * -1;
    }
}

public class ComparableToComparatorTest {
    public static void main(String[] args) {
        Set&lt;String&gt; set = new TreeSet&lt;&gt;(new MyCompare()); // 위에서 만든 Comparator 적용
        set.add(new String(&quot;aaa&quot;)); // 전에 말했듯, String은 이미 Comparable이 구현되어 있음.
        set.add(new String(&quot;aaa&quot;));
        set.add(new String(&quot;ccc&quot;));
        set.add(new String(&quot;bbb&quot;));

        System.out.println(set); // 출력하면 [ccc, bbb, aaa]가 출력됨.
    }
}</code></pre>
<h2 id="마치며">마치며</h2>
<p>다음시간엔 Map 인터페이스를 배워보도록 하겠습니다.
아마 다음시간에 마무리가 될거같네요.
한 2주동안 여러가지 일이 닥쳐오면서 포스팅도 제대로 못올렸네요 ㅎ;
앞으로는 제대로 올려보도록 하겠습니다. 감사합니다.</p>
<h2 id=""></h2>
]]></description>
        </item>
        <item>
            <title><![CDATA[Life.override() ( 인생 재정의 )]]></title>
            <link>https://velog.io/@fulldev_hong/Life.override-%EC%9D%B8%EC%83%9D-%EC%9E%AC%EC%A0%95%EC%9D%98</link>
            <guid>https://velog.io/@fulldev_hong/Life.override-%EC%9D%B8%EC%83%9D-%EC%9E%AC%EC%A0%95%EC%9D%98</guid>
            <pubDate>Fri, 09 Dec 2022 15:08:37 GMT</pubDate>
            <description><![CDATA[<h2 id="문제가-발생했다-cval">문제가 발생했다! C.val()!</h2>
<p>군면제와 성공적인 취업을 위해 정보처리기능사를 준비하던 홍XX씨..
하지만 이 미친새ㄲ는 기능사를 공부하기는 커녕 맨날 천날 보던 곳만 계속 보고, 기출 문제를 풀 생각도 안한다.
그래서 결국 5연패를 하게 되는데..
<del>그니까 왜 그랬어 미친ㄴ아</del>
<img src="https://velog.velcdn.com/images/fulldev_hong/post/b1b0fd53-5aa3-4a64-b19e-e10e8b2df461/image.png" alt=""></p>
<p>이러다간 결국 굳건이의 부름을 받고 군대로 돌진을 박고 코딩 실력이 떨어지게 생겼다..
<img src="https://velog.velcdn.com/images/fulldev_hong/post/d3525b44-3bca-4db0-8a85-cd1bdbc875ed/image.png" alt="">
그러던 중 지인과 선생님에 조언으로 SW개발 L3를 공부하게 되는데..
기능사 공부한것처럼 해서는 인생에 답이 도저히 안보여서 결국 인생 자체를 바꾸기로 했다.</p>
<h2 id="공부하는-방식의-변경">공부하는 방식의 변경</h2>
<p>기존에 공부하던 방식은 다음과 같았다.</p>
<ul>
<li>나올것같은 부분만 중점 공부</li>
<li>기출문제는 도움도 안되니 나몰라라</li>
<li>앞선 개념들은 알고 있으니 건너뛰기~</li>
</ul>
<p><del>이러니까 안되지 ㅆㅂ</del>
그래서 아예 공부하는 방식을 바꿔보기로 했다.</p>
<ul>
<li>전체적인 부분을 공부</li>
<li>기출문제 중점으로 진행</li>
<li>앞서 했었던 개념들도 다시 정리</li>
</ul>
<p>이렇게 공부를 해볼 계획이다.</p>
<h2 id="시간-분배-정상화">시간 분배 정상화</h2>
<p><strong>공부 1시간, 게임 3시간</strong>으로 비정상적인 공부 시간을 분배했던 나는 이 시간을 정상화시킬 계획에 들어간다.
<strong>공부 3시간 30분, 게임 30분</strong> 이런식으로 바꿔보려고 노력해보려고 한다.</p>
<blockquote>
<p>물론 처음엔 잘 안될수도 있지만, 컴퓨터에 있는 게임들을 없애면 어떻게 되지 않을까?</p>
</blockquote>
<h2 id="끊을껀-끊어야지">끊을껀 끊어야지</h2>
<p>핸드폰으로 맨날 보던 애니메이션을 끊어보기로 했다. 최소한 L3를 공부하는 데 집중하고 싶기 때문이다
또, 핸드폰에서 유튜브(쇼츠), 인스타그램, 페이스북 등을 잠시 멈추기로 했다.</p>
<h2 id="제발-노력해-제발">제발 노력해 제발</h2>
<p>위에 있는 노력들이 하루만에 다 바뀔꺼라고는 생각도 하지 않는다.
하지만 L3를 공부하는 만큼은 최대한 위 3가지처럼 살아보려고 한다.
앞으로 Velog에 L3 공부한것도 올릴 예정이다. 잘부탁한다.</p>
<h2 id="쿠키">쿠키</h2>
<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/16f75b6f-9322-47aa-b6bc-9624fb0a0855/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/7556d03e-bb57-4dc9-9fec-533774450881/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/f3fd759a-f2d0-446a-9abb-0c6700fbdd74/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/b9b70954-02a5-429f-bf71-f1ec62fd88b8/image.png" alt=""></p>
<p><del>잘가라 발로란트 L3 끝나고 보자구..</del></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조 #14 - 컬렉션 프레임워크 : Set & HashSet]]></title>
            <link>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-13-%EC%BB%AC%EB%A0%89%EC%85%98-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC-Set</link>
            <guid>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-13-%EC%BB%AC%EB%A0%89%EC%85%98-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC-Set</guid>
            <pubDate>Mon, 05 Dec 2022 07:04:53 GMT</pubDate>
            <description><![CDATA[<p>이 포스트는 FastCampus에 <a href="https://fastcampus.co.kr/dev_online_javaend"> 이 강의</a>를 보고 포스팅되었습니다.
문제가 될 시 삭제될 예정입니다.</p>
<h2 id="set은-뭐고">Set은 뭐고..</h2>
<p>Set은 <strong>중복되지 않게 값을 관리하는</strong> 인터페이스 입니다.
대표적으로는 db를 짤때 쓰는 Unique 기능이라고 생각하시면 됩니다.
대표적인 클래스로는 HashSet이 있습니다.</p>
<h2 id="hashset">HashSet?</h2>
<p>앞에서 말했다싶이, Set 인터페이스를 구현한 클래스중 하나입니다.</p>
<ul>
<li>멤버에 중복 여부를 체크하기 위해 인스턴스의 동일성을 확인해야 합니다.</li>
<li>그래서 HashSet에 넣을때마다 <code>equals()</code>와 <code>hashCode()</code>를 체크합니다.</li>
</ul>
<h2 id="hashset-test">HashSet Test</h2>
<pre><code class="language-java">import java.util.HashSet;

public class hashSetTest {
    public static void main(String[] args) {
        HashSet&lt;String&gt; hashSet = new HashSet&lt;&gt;();

        hashSet.add(new String(&quot;안녕월드&quot;));
        hashSet.add(new String(&quot;안녕월드&quot;));
        hashSet.add(new String(&quot;이건 중복 테스트야&quot;));
        hashSet.add(new String(&quot;이건 중복 테스트야&quot;));
        hashSet.add(new String(&quot;잘가&quot;));
        hashSet.add(new String(&quot;잘가&quot;));

        System.out.println(hashSet);
    }
}</code></pre>
<p>결과 : [잘가, 안녕월드, 이건 중복 테스트야]
<img src="https://velog.velcdn.com/images/fulldev_hong/post/1259dc70-faaa-421b-b1f1-de74c5b48e1b/image.png" alt="">
코드는 <a href="https://github.com/BackdevHong/Java-Generic-Collection/blob/main/Set/src/hashSetTest.java">여기</a>에도 나와있습니다.</p>
<h2 id="이걸-어따-써">이걸 어따 써?</h2>
<p>아까 만든 멤버십 프로그램에서 id의 중복을 제거할때 사용이 가능합니다.
한번 해볼까요?</p>
<h2 id="member-클래스-수정">Member 클래스 수정</h2>
<pre><code class="language-java">@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Member member = (Member) o;
    return memberId == member.memberId;
}

@Override
public int hashCode() {
    return Objects.hash(memberId);
}</code></pre>
<p>멤버 클래스에 equals()와 hashCode()를 추가해줍니다.
단, memberId만 검사하게 하고, memberName은 무시해줍시다.</p>
<h2 id="memberhashset-클래스-생성">MemberHashSet 클래스 생성</h2>
<pre><code class="language-java">import java.util.HashSet;
import java.util.Iterator;

public class MemberHashSet {
    private HashSet&lt;Member&gt; memberHashSet;

    public MemberHashSet() {
        memberHashSet = new HashSet&lt;&gt;();
    }

    public MemberHashSet(int size) {
        memberHashSet = new HashSet&lt;&gt;(size);
    }

    public void addMember(Member member) {
        memberHashSet.add(member);
    }

    public boolean removeMember(int memberId) {
        // Iterator 선언
        Iterator&lt;Member&gt; ir = memberHashSet.iterator();

        // ir.hasNext()가 false가 될 때까지 돈다.
        while(ir.hasNext()) {
            Member member = ir.next(); // 다음 요소를 member에 저장시키고

            if (member.getMemberId() == memberId) { // memberId가 맞는지 확인
                memberHashSet.remove(member); // 삭제하고
                return true; // true 반환
            }
        }
        System.out.println(&quot;해당 멤버id를 가지고 있는 유저가 없습니다.&quot;);
        return false;
    }

    public void showAllMember() {
        for (Member member : memberHashSet) {
            System.out.println(member);
        }
    }
}</code></pre>
<p>ArrayList만 HashSet으로 바꿔주시면 리팩토링이 끝납니다.
한번 테스트 코드를 작성해보죠.</p>
<h2 id="테스트-코드">테스트 코드</h2>
<pre><code class="language-java">public class MemberHashSetTest {
    public static void main(String[] args) {
        Member member1 = new Member();
        Member member2 = new Member();

        member1.setMemberId(1);
        member1.setMemberName(&quot;멤버이름&quot;);

        member2.setMemberId(1);
        member2.setMemberName(&quot;멤버요 ㅋ&quot;);

        MemberHashSet hashList = new MemberHashSet();

        hashList.addMember(member1);
        hashList.addMember(member2);

        System.out.println();
        hashList.showAllMember();
    }
}</code></pre>
<p>결과 : Member{memberId=1, memberName=&#39;멤버이름&#39;}
<img src="https://velog.velcdn.com/images/fulldev_hong/post/7dc79827-d3ac-46a7-91c9-739ac00d4edc/image.png" alt=""></p>
<p>어때요? 중복이 사라졌죠?
해당 코드는 <a href="https://github.com/BackdevHong/Java-Generic-Collection/tree/main/Member/src">여기</a>에도 나와있답니다!
ArrayList와 따로 구분해두었으니 확인해보세요!</p>
<h2 id="마치며">마치며</h2>
<p>자, 이렇게 HashSet은 끝났습니다.
다음시간엔 중복도 제거하고, 정렬도 가능한 TreeSet을 다뤄볼게요!
수고하셨습니다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조 #13 - 컬렉션 프레임워크 : List & Iterator]]></title>
            <link>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-13-%EC%BB%AC%EB%A0%89%EC%85%98-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC-List</link>
            <guid>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-13-%EC%BB%AC%EB%A0%89%EC%85%98-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC-List</guid>
            <pubDate>Mon, 05 Dec 2022 05:18:53 GMT</pubDate>
            <description><![CDATA[<p>이 포스트는 FastCampus에 <a href="https://fastcampus.co.kr/dev_online_javaend"> 이 강의</a>를 보고 포스팅되었습니다.
문제가 될 시 삭제될 예정입니다.</p>
<h2 id="뭐할거야">뭐할거야?</h2>
<p>컬렉션 프레임워크 중 List를 구현한 클래스를 알아보기 위해 멤버십을 관리하는 프로그램을 만들어볼 겁니다.</p>
<h2 id="요구사항">요구사항</h2>
<ul>
<li>이번에 다뤄볼 클래스는 <strong>ArrayList</strong>입니다.</li>
<li>Member 클래스를 만들고, 멤버변수로 아이디와 이름을 선언한다.</li>
<li>Member 클래스로 생성된 인스턴스를 관리하는 클래스를 만들자.<ul>
<li>단, 컬렉션 프레임워크 클래스를 활용해서 구현하자.</li>
</ul>
</li>
</ul>
<h2 id="코드-올라오는-곳">코드 올라오는 곳?</h2>
<p><a href="https://github.com/BackdevHong/Java-All/tree/main/Java-Generic-Collection/Member/src">여기</a>에서 확인하실 수 있습니다.</p>
<h2 id="member-클래스-만들기">Member 클래스 만들기</h2>
<pre><code class="language-java">public class Member {
    private int memberId; // 멤버 id
    private String memberName; // 멤버 이름

    // Getter와 Setter
    public int getMemberId() {
        return memberId;
    }

    public void setMemberId(int memberId) {
        this.memberId = memberId;
    }

    public String getMemberName() {
        return memberName;
    }

    public void setMemberName(String memberName) {
        this.memberName = memberName;
    }

    // ToString 재조정
    @Override
    public String toString() {
        return &quot;Member{&quot; +
                &quot;memberId=&quot; + memberId +
                &quot;, memberName=&#39;&quot; + memberName + &#39;\&#39;&#39; +
                &#39;}&#39;;
    }
}</code></pre>
<h2 id="member를-저장하는-memberarraylist-클래스-만들기">Member를 저장하는 MemberArrayList 클래스 만들기</h2>
<pre><code class="language-java">import java.util.ArrayList; // ArrayList 클래스 import(중요)

public class MemberArrayList {
    private ArrayList&lt;Member&gt; members;

    // 생성자
    public MemberArrayList() {
        members = new ArrayList&lt;&gt;();
    }

    // 생성자(사이즈 있는 버전)
    public MemberArrayList(int size) {
        members = new ArrayList&lt;&gt;(size);
    }

    // 멤버 추가
    public void addMember(Member member) {
        members.add(member);
    }

    // 멤버 제거
    public boolean removeMember(int memberId) {
        for (int i = 0; i &lt; members.size(); i++) {
            Member member = members.get(i); // i번째에 해당하는 멤버를 불러오고
            int tempId = member.getMemberId(); // 해당 멤버에 id를 불러온다.
            if(tempId == memberId) {
                members.remove(i); // 지우고자 하는 id와 멤버 id가 같을때 삭제한다.
                return true;
            }
        }
        System.out.println(&quot;해당 멤버id를 가지고 있는 유저가 없습니다.&quot;);
        return false;
    }

    // 멤버 조회
    public void showAllMember() {
        for (Member member : members) {
            System.out.println(member);
        }
    }
}</code></pre>
<h2 id="테스트-코드-작성">테스트 코드 작성</h2>
<pre><code class="language-java">public class MemberTest {
    public static void main(String[] args) {
        // 멤버 2명 생성
        Member member1 = new Member();
        Member member2 = new Member();

        // 멤버 id, name 설정
        member1.setMemberId(1);
        member1.setMemberName(&quot;홍길동&quot;);

        member2.setMemberId(2);
        member2.setMemberName(&quot;홍상두&quot;);

        // ArrayList 생성, 멤버 추가
        MemberArrayList list = new MemberArrayList();
        list.addMember(member1);
        list.addMember(member2);

        // 멤버 조회
        list.showAllMember();

        // 멤버 삭제
        list.removeMember(2);

        // 다시 멤버 조회
        System.out.println(&quot;&quot;);
        list.showAllMember();
    }
}</code></pre>
<p>이렇게 작성을 끝냈습니다.
이렇게 끝내긴 좀 아쉬우니까, 삭제 부분을 리팩토링해보겠습니다.</p>
<h2 id="어떻게-리팩토링-할껀디">어떻게 리팩토링 할껀디?</h2>
<p>Iterator라는 놈을 쓸겁니다.
Iterator는 컬렉션 프레임워크에 저장된 요소들을 하나씩 참조하는 놈입니다.
순서가 있는 List같은 경우에는 <code>get()</code>이라는 메서드를 사용하면 되겠지만, 
순서가 없는 Set같은 경우 get메서드가 없기에 요놈을 써서 순회해야 합니다.</p>
<h2 id="어떻게-쓰는건데-이거">어떻게 쓰는건데 이거</h2>
<p><code>hasNext()</code> : 다음 요소가 있는지 확인하는 메서드입니다. ( 반환값은 True | False )
<code>Next()</code> : 다음 요소를 반환합니다.</p>
<h2 id="삭제-리팩토링">삭제 리팩토링</h2>
<pre><code class="language-java">public boolean removeMember(int memberId) {
    // Iterator 선언
    Iterator&lt;Member&gt; ir = members.iterator();

    // ir.hasNext()가 false가 될 때까지 돈다.
    while(ir.hasNext()) {
        Member member = ir.next(); // 다음 요소를 member에 저장시키고

        if (member.getMemberId() == memberId) { // memberId가 맞는지 확인
            members.remove(member); // 삭제하고
            return true // true 반환
        }
    }
    System.out.println(&quot;해당 멤버id를 가지고 있는 유저가 없습니다.&quot;);
    return false;
}</code></pre>
<p>성공적으로 리팩토링이 종료되었습니다.</p>
<h2 id="마치며">마치며</h2>
<p>이것으로 List - ArrayList와 Iterator를 이용한 멤버십 만들기는 여기까지 하겠습니다.
다음시간에는 Set 인터페이스를 이용해 멤버십을 다시 리팩토링 해보겠습니다.
수고하셨습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조 #12 - 컬렉션 프레임워크]]></title>
            <link>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-12-%EC%BB%AC%EB%A0%89%EC%85%98-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC</link>
            <guid>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-12-%EC%BB%AC%EB%A0%89%EC%85%98-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC</guid>
            <pubDate>Mon, 05 Dec 2022 02:17:55 GMT</pubDate>
            <description><![CDATA[<p>이 포스트는 FastCampus에 <a href="https://fastcampus.co.kr/dev_online_javaend"> 이 강의</a>를 보고 포스팅되었습니다.
문제가 될 시 삭제될 예정입니다.</p>
<h2 id="이게-뭔데">이게 뭔데</h2>
<p>우리가 전에 했었던 자료구조 대부분이 구현되어 있는 JDK 라이브러리 입니다.
C++에서도 STL이라는 위와 비슷한 라이브러리가 있습니다.
우리가 직접 자료구조를 구현하기에는 시간적 손실이 발생할 수 밖에 없습니다.
그래서 나온것이 컬렉션 프레임워크입니다.
컬렉션 프레임워크는 대부분 <strong>제네릭 클래스</strong>로 구현되어 있습니다.</p>
<h2 id="왜-그럼-굳이-직접-구현해본거임">왜 그럼 굳이 직접 구현해본거임?</h2>
<p>자료구조를 이해하기 위해서입니다.</p>
<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/f1180065-b5cc-4c07-8998-58a4445541e7/image.png" alt=""></p>
<p>요리로 예를 들어보죠. 만약 자신에게 고급 요리기구와 식재료가 주어진다고 생각해봅시다.
근데 레시피도 모르고, 조리하는 방법 조차 모르는 사람에게 <strong>OO를 요리하세요</strong> 라고 한다면?
그 사람은 고급 식재료도 그렇고 요리기구도 그렇고 엉망진창으로 만들어버릴것입니다.</p>
<p>위 예시처럼 아무리 JDK라는 좋은 도구가 있고 안에 구현된 자료구조가 있어도, 
이것을 어디에 쓰고, 어떤식으로 작동을 하는건지 알아야 쓰던 말던 하겠죠?
그래서 먼저 구현해봄으로써 자료구조에 특성을 파악한 뒤, JDK를 사용하는 겁니다.</p>
<h2 id="구조-좀-알려줘">구조 좀 알려줘</h2>
<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/d3e4579a-dea6-4f29-8faf-ffd0619d168b/image.png" alt=""></p>
<p>크게 두가지 인터페이스가 있습니다. <strong>Collection</strong>, <strong>Map</strong>
그 밑으로 여러가지 구현을 해놓은 모습을 알 수 있습니다.
실제 소스로 들어가보시면 어마어마하게 많이 있습니다. 여기선 주로 쓰는것만 다뤄볼 예정입니다.</p>
<h2 id="마치며">마치며</h2>
<p>다음 시간에는 컬렉션에서 구현해놓은 것들 중 <strong>List</strong> 인터페이스를 구현한 클래스를 알아보겠습니다.
수고하셨습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조 #11 - 제네릭 메서드]]></title>
            <link>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-11-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EB%A9%94%EC%84%9C%EB%93%9C</link>
            <guid>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-11-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EB%A9%94%EC%84%9C%EB%93%9C</guid>
            <pubDate>Tue, 29 Nov 2022 05:54:28 GMT</pubDate>
            <description><![CDATA[<p>이 포스트는 FastCampus에 <a href="https://fastcampus.co.kr/dev_online_javaend"> 이 강의</a>를 보고 포스팅되었습니다.
문제가 될 시 삭제될 예정입니다.</p>
<h2 id="제너릭-메서드가-뭐야">제너릭 메서드가 뭐야</h2>
<p>자료형 메개변수를 메서드의 매개변수나 반환 값으로 가지는 메서드입니다.
자료형 매개변수가 하나 이상일 경우도 있습니다.
제너릭 클래스가 아니어도 내부에서 제너릭 메서드를 구현하여 사용이 가능합니다.
제너릭 매서드에 구조는 다음과 같습니다.</p>
<pre><code class="language-java">public &lt;자료형 매개 변수&gt; [반환형] [메서드 이름] [(자료형 매게변수..)] {}</code></pre>
<h2 id="제너릭-메서드-사용한-예시좀-보여줘바">제너릭 메서드 사용한 예시좀 보여줘바</h2>
<p>다음과 같은 요구조건의 메서드를 만들어봅시다.</p>
<ul>
<li>두 점(top, bottom)을 기준으로 사각형을 만들 떄 사각형의 넓이를 구하세요.</li>
<li>단, 두 점은 정수일수도 있고, 실수일수도 있습니다.</li>
</ul>
<p>일단 두 점을 받을 클래스를 만들어봅시다.</p>
<pre><code class="language-java">public class Point&lt;T, V&gt; {
    T x;
    V y;

    public Point(T x, V y) {
        this.x = x;
        this.y = y;
    }

    public T getX() {
        return x;
    }

    public V getY() {
        return y;
    }
}
</code></pre>
<p>그리고 메인쪽에 제너릭 메서드를 만들어 봅시다.</p>
<pre><code class="language-java">// public &lt;자료형 매개 변수&gt; [반환형] [메서드 이름] [(자료형 매게변수..)]
// static은 자유입니다.
public static &lt;T, V&gt; double makeRectangle(Point&lt;T, V&gt; p1, Point&lt;T, V&gt; p2) {
    double left = ((Number)p1.getX()).doubleValue();
    double right = ((Number)p2.getX()).doubleValue();
    double top = ((Number)p1.getY()).doubleValue();
    double bottom = ((Number)p2.getY()).doubleValue();

    double width = right - left;
    double height = bottom - top;

    return width * height;
}</code></pre>
<p>그리고 테스트 코드를 짜주면 완성입니다!</p>
<pre><code class="language-java">public static void main(String[] args) {
    Point&lt;Integer, Double&gt; p1 = new Point&lt;&gt;(0, 0.0);
    Point&lt;Integer, Double&gt; p2 = new Point&lt;&gt;(10, 10.0);
    double rect = GenericMethod.&lt;Integer, Double&gt; makeRectangle(p1, p2);
    System.out.println(rect); // 결과 = 100
}</code></pre>
<p>아까 말했던것처럼 꼭 제네릭 클래스가 아니더라도 이렇게 구현해서 사용하시면 됩니다.</p>
<h2 id="전체코드는요">전체코드는요?</h2>
<p><a href="https://github.com/BackdevHong/Java-All/tree/main/Java-Generic-Collection/Generic/src/rectangleSize">링크</a>
위 링크로 들어가시면 됩니다.</p>
<h2 id="마치며">마치며</h2>
<p>제네릭은 여기까지 다루도록 하겠습니다.
다음 시간에는 드디어 컬렉션을 써볼겁니다!
<del>와 드디어 나오네</del> 그럼 모두 수고하셨습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조 #10 - < T extend 클래스 >]]></title>
            <link>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-10-%EC%9E%90%EB%A3%8C%ED%98%95%EC%A0%9C%ED%95%9C</link>
            <guid>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-10-%EC%9E%90%EB%A3%8C%ED%98%95%EC%A0%9C%ED%95%9C</guid>
            <pubDate>Tue, 29 Nov 2022 05:14:08 GMT</pubDate>
            <description><![CDATA[<p>이 포스트는 FastCampus에 <a href="https://fastcampus.co.kr/dev_online_javaend"> 이 강의</a>를 보고 포스팅되었습니다.
문제가 될 시 삭제될 예정입니다.</p>
<h2 id="t-extend-class--왜-써야됨">&lt; T extend Class &gt; 왜 써야됨?</h2>
<p>제네릭 타입을 쓰면 T 위치에 어느 자료형이든 들어가도 상관이 없습니다.
하지만 전에 말했던것처럼 어느 자료형이든 들어가게 된다면 문제가 생길 수 있습니다.
만약에 3D 프린터에 재료로 물을 넣는다? 그 3D 프린터는 바로 폐기가 되버릴 것입니다.
그래서 이 타입에 대한 제한을 두기위해 상속을 이용하는 겁니다.</p>
<p>상위 클래스에서 상속 받은 클래스만 T 대신에 쓸 수 있다는 겁니다.</p>
<h2 id="오-예시-보여줘바">오 예시 보여줘바</h2>
<p>저번에 제네릭 사용법때 사용한 예시를 T extend Class로 바꿔보겠습니다.</p>
<p>상위 클래스인 Material을 만들어보겠습니다.
보통 T extend Class에서는 상위 클래스를 abstract로 구현합니다.</p>
<pre><code class="language-java">public abstract class Material {
  // no code
}</code></pre>
<p>그리고 GenericPrinter 클래스에 Material을 상속시켜 보겠습니다.
( T에다 상속시켜야 함. )</p>
<pre><code class="language-java">public class GenericPrinter&lt;T extends Material&gt; {
    public T material;

    public T getMaterial() {
        return material;
    }

    public void setMaterial(T material) {
        this.material = material;
    }

    public String toString() {
        return material.toString();
    }
}</code></pre>
<p>마찬가지로 Plastic에 Material을 상속시켜보고 테스트 코드를 돌려보겠습니다.</p>
<pre><code class="language-java">public class ThreeDPrinterExtendTest {
    public static void main(String[] args) {
        GenericPrinter&lt;Powder&gt; GP = new GenericPrinter&lt;&gt;();
        // 이쪽에서 오류가 발생했습니다.
        // 이유는 이 Powder가 Material을 상속받지 않았기 때문입니다.
        // Type parameter &#39;threeDPrinterWithTextend.Powder&#39; is not within its bound

        Powder pw = new Powder();

        GP.setMaterial(pw);

        System.out.println(GP.toString());
    }
}</code></pre>
<p>전 테스트 코드를 그대로 가져왔더니 오류가 생겼습니다.
일단 Powder도 상속시켜보고 테스트 코드를 다시 돌려보겠습니다.</p>
<pre><code class="language-java">public class Powder extends Material{
    public String toString() {
        return &quot;재료는 Powder 입니다.&quot;;
    }
}</code></pre>
<pre><code class="language-java">public class ThreeDPrinterExtendTest {
    public static void main(String[] args) {
        GenericPrinter&lt;Powder&gt; GP = new GenericPrinter&lt;&gt;();

        Powder pw = new Powder();

        GP.setMaterial(pw);

        System.out.println(GP.toString());
    }
}</code></pre>
<p>오류가 사라졌습니다! 만세!</p>
<h2 id="코드-좀">코드 좀</h2>
<p>위 코드들은 전부 제 <a href="https://github.com/BackdevHong/Java-All/tree/main/Java-Generic-Collection/Generic/src/threeDPrinterWithTextend">깃허브</a>에 올라가 있습니다.</p>
<h2 id="다음시간엔-뭐할거임">다음시간엔 뭐할거임?</h2>
<p>다음시간엔 제네릭 메서드를 다뤄보도록 하겠습니다.
수고하셨습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조 #9 - 제네릭 사용법]]></title>
            <link>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-9-%EC%A0%9C%EB%84%A4%EB%A6%AD%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-9-%EC%A0%9C%EB%84%A4%EB%A6%AD%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Tue, 29 Nov 2022 03:27:35 GMT</pubDate>
            <description><![CDATA[<p>이 포스트는 FastCampus에 <a href="https://fastcampus.co.kr/dev_online_javaend"> 이 강의</a>를 보고 포스팅되었습니다.
문제가 될 시 삭제될 예정입니다.</p>
<h2 id="제네릭-얘-어떻게-쓰는건데">제네릭 얘 어떻게 쓰는건데?</h2>
<p>사용법을 알아보기 위해 가정을 하나 해봅시다.
자 여기에 3D 프린터가 있다 칩시다.
3D 프린터는 어떤 <strong>입체</strong>적인 모양을 뽑는 데 쓰죠? 그 모양을 뽑는 데는 재료가 듭니다.
이 재료가 뭐냐에 따라 다르죠.
일단 제네릭을 안 쓰고 코딩해보겠습니다.</p>
<h2 id="no-generic-version">No Generic Version</h2>
<pre><code class="language-js">{
  &quot;프로젝트 이름&quot; : &quot;3D 프린터&quot;,
  &quot;제네릭 사용 여부&quot; : false,
  &quot;개발 도구&quot; : &quot;IntelliJ 2022.2.4&quot;,
  &quot;개발 자바 버전&quot; : 18,
}</code></pre>
<p>일단 각 재료에 대한 클래스를 만들어야 합니다.
일단 저는 예시로 <strong>플라스틱</strong>과 <strong>파우더</strong>로 하겠습니다.</p>
<pre><code class="language-java">public class Powder {
    public String toString() {
        return &quot;재료는 Powder 입니다.&quot;;
    }
}</code></pre>
<pre><code class="language-java">public class Plastic {
    public String toString() {
        return &quot;재료는 Plastic 입니다.&quot;;
    }
}</code></pre>
<p>그 다음으로는 이 두가지 재료를 사용할 클래스 2개를 만들어야 합니다.</p>
<pre><code class="language-java">public class ThreeDPrinter1 {
    private Powder material;

    public Powder getMaterial() {
        return material;
    }

    public void setMaterial(Powder material) {
        this.material = material;
    }
}</code></pre>
<pre><code class="language-java">public class ThreeDPrinter2 {
    private Plastic material;

    public Plastic getMaterial() {
        return material;
    }

    public void setMaterial(Plastic material) {
        this.material = material;
    }
}</code></pre>
<p>이렇게 하면 클래스도 2개 만들어야 하고, 번거롭습니다.
그래서 선대 개발자분들은 재료 자료형을 직접 넣는 대신 Object 클래스를 이용하였었습니다.</p>
<pre><code class="language-java">public class ThreeDPrinter3 {
    private Object material;

    public Object getMaterial() {
        return material;
    }

    public void setMaterial(Object material) {
        this.material = material;
    }
}</code></pre>
<p>근데 이렇게 하면 또 문제가 발생합니다.
테스트 코드를 적어보겠습니다.</p>
<pre><code class="language-java">public class ThreeDPrinterTest {
    public static void main(String[] args) {
        ThreeDPrinter3 test = new ThreeDPrinter3();

        Powder powder = new Powder();

        test.setMaterial(powder);
        // 여기까지만 해도 문제는 없었음

        Powder p = test.getMaterial();
        // 여기에서 문제 발생.

        Powder p2 = (Powder) test.getMaterial();
        // 강제로 형변환을 해줘야 문제가 해결됨
    }
}</code></pre>
<p>깅제로 형변환도 해줘야 하고, Object도 그닥 좋은 방법은 아닌 것 같습니다.
이제 한번 Generic으로 코딩해보겠습니다.</p>
<h2 id="generic-version">Generic Version</h2>
<pre><code class="language-js">{
  &quot;프로젝트 이름&quot; : &quot;3D 프린터&quot;,
  &quot;제네릭 사용 여부&quot; : true,
  &quot;개발 도구&quot; : &quot;IntelliJ 2022.2.4&quot;,
  &quot;개발 자바 버전&quot; : 18,
}</code></pre>
<p>제네릭은 클래스명 뒤에 <code>&lt;T&gt;</code>를 붙여주시고, 자료형을 T로 바꿔주시면 됩니다.</p>
<pre><code class="language-java">public class GenericPrinter&lt;T&gt; {
    public T material;

    public T getMaterial() {
        return material;
    }

    public void setMaterial(T material) {
        this.material = material;
    }

    public String toString() {
        return material.toString();
    }
}
</code></pre>
<p>테스트 클래스를 다시 적어보겠습니다.</p>
<pre><code class="language-java">public class ThreeDPrinterGTest {
    public static void main(String[] args) {
        GenericPrinter&lt;Powder&gt; GP = new GenericPrinter&lt;&gt;();

        Powder pw = new Powder();

        GP.setMaterial(pw);

        System.out.println(GP.toString());
    }
}</code></pre>
<p>오류가 사라진 것을 확인할 수 있었습니다.</p>
<h2 id="--얘는-뭐하는-애임">&lt;&gt; &lt;- 얘는 뭐하는 애임?</h2>
<p>&lt;&gt;는 다이아몬드 연산자라고 하는 놈입니다.
다이아몬드 연산자가 나오기 전엔 이렇게 써줘야 했었습니다.</p>
<pre><code class="language-java">GenericPrinter&lt;Powder&gt; GP = new GenericPrinter&lt;Powder&gt;();</code></pre>
<p>하지만 나온 뒤부터는 이렇게 작성이 가능해졌죠.</p>
<pre><code class="language-java">GenericPrinter&lt;Powder&gt; GP = new GenericPrinter&lt;&gt;();</code></pre>
<h2 id="근데-만약-t에-아무런-자료형도-안넣으면">근데, 만약 T에 아무런 자료형도 안넣으면..?</h2>
<p>T에 아무런 자료형도 넣지 않게 된다면, T는 자동으로 Object 형으로 인식합니다.
그래서 T에서 Object 자료형의 메서드를 사용할 수 있죠.</p>
<h2 id="코드-좀">코드 좀</h2>
<p>위 코드들은 전부 제 <a href="https://github.com/BackdevHong/Java-All/tree/main/Java-Generic-Collection/Generic/src/threeDPrinter">깃허브</a>에 올라가 있습니다.
<strong>제네릭 없는 버전은 noGeneric, 제네릭 쓴 버전은 useGeneric 가셔서 소스 보시면 됩니다.</strong></p>
<h2 id="다음시간엔-뭐할거임">다음시간엔 뭐할거임?</h2>
<p>위처럼 T를 쓰면 어떤 자료형이든 넣을 수 있지만, 도리어 문제가 될 수 있습니다.
그래서 다음 시간에는 자료형을 제한할 수 있는 <strong>T extend</strong>를 배워보도록 하겠습니다.
수고하셨습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조 #8 - 제네릭 프로그래밍?]]></title>
            <link>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-8-%EC%A0%9C%EB%84%A4%EB%A6%AD%EC%9D%B4%EB%AD%94%EB%8D%B0</link>
            <guid>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-8-%EC%A0%9C%EB%84%A4%EB%A6%AD%EC%9D%B4%EB%AD%94%EB%8D%B0</guid>
            <pubDate>Tue, 29 Nov 2022 01:36:31 GMT</pubDate>
            <description><![CDATA[<p>이 포스트는 FastCampus에 <a href="https://fastcampus.co.kr/dev_online_javaend"> 이 강의</a>를 보고 포스팅되었습니다.
문제가 될 시 삭제될 예정입니다.</p>
<h2 id="제네릭-프로그래밍-이게-뭔데">제네릭 프로그래밍? 이게 뭔데</h2>
<p><strong>일반화</strong>라는 뜻을 가지고 있습니다.
클래스에서 사용하는 변수의 자료형이 여러 개 일 수 있습니다.
위 클래스에 기능이 동일하다고 한다면 여러개에 클래스를 만드는 것은 비효율적입니다.
그래서 클래스에서 자료형을 특정하지 않고, 나중에 클래스를 사용할 때 자료형을 지정할 수 있도록 하는것이 <strong>제네릭</strong>에 특징입니다.</p>
<p>실질적인 자료형의 변환은 컴파일러에 의해 검증되므로 안정적으로 프로그래밍을 할 수 있는 방식입니다.</p>
<h2 id="이거-배워서-어따-써먹는데">이거 배워서 어따 써먹는데?</h2>
<p>다음에 배울 <strong>컬렉션</strong>을 다루려면 이 제네릭 프로그래밍을 배워야합니다.
컬렉션은 제네릭을 많이 쓰기 때문이죠.</p>
<h2 id="마치며">마치며</h2>
<p>다음시간엔 이 제네릭 프로그래밍에 장단점에 대해 알아볼겁니다.
수고하셨습니다! 새로운 썸네일 보여드리면서 끝내도록 할게요
<img src="https://velog.velcdn.com/images/fulldev_hong/post/33272cea-619d-44fb-8bac-c64ccd053d06/image.png" alt=""></p>
<p><del>보노보노 생각나는데 나만 그럼?</del></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조 #7 - 큐 구현]]></title>
            <link>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-7-%ED%81%90%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-7-%ED%81%90%EA%B5%AC%ED%98%84</guid>
            <pubDate>Mon, 28 Nov 2022 07:38:08 GMT</pubDate>
            <description><![CDATA[<p>이 포스트는 FastCampus에 <a href="https://fastcampus.co.kr/dev_online_javaend"> 이 강의</a>를 보고 포스팅되었습니다.
문제가 될 시 삭제될 예정입니다.</p>
<h2 id="시작하기-전에-큐-특징-좀-다시-알려줘바">시작하기 전에 큐 특징 좀 다시 알려줘바</h2>
<ul>
<li>맨 앞에선 자료에 탐색과 삭제, 맨 뒤에서 추가를 하는 자료구조 입니다.</li>
<li>맨 앞을 Front, 맨 뒤를 rear라고 부릅니다.</li>
<li>전에 구현했던 스택과는 다르게 FIFO( First In First Out, 선입선출 ) 구조입니다. </li>
<li>가게에 먼저 줄을 선 손님이 먼저 들어가는 것으로 예를 들 수 있습니다.</li>
<li>순차적으로 들어오는 자료를 순서대로 처리하는데 많이 사용되는 자료구조입니다.</li>
</ul>
<p>JDK 클래스에는 ArrayList가 있습니다.</p>
<h2 id="뭘-구현할건데">뭘 구현할건데?</h2>
<p>enQueue, deQueue를 구현해볼겁니다.</p>
<h2 id="잠깐-이거-코드-여기에만-올라옴">잠깐 이거 코드 여기에만 올라옴??</h2>
<p>전편에도 말했지만 모든 코드는 깃허브에 올라갈 예정입니다.
<a href="https://github.com/BackdevHong/Java-All/tree/main/Java-DataStructure/">링크</a></p>
<h2 id="시작하기-전">시작하기 전</h2>
<p>이번에 할 스택 구현은 <a href="https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-5-%EC%97%B0%EA%B2%B0%EB%A6%AC%EC%8A%A4%ED%8A%B8%EA%B5%AC%ED%98%84">저번</a>에 만든 연결리스트 클래스를 가져와서 구현합니다.
<del>히히 재밌겠ㄷ22</del></p>
<h2 id="인터페이스-생성">인터페이스 생성</h2>
<pre><code class="language-java">public interface IQueue {
    public void enQueue(String data);
    public String deQueue();
    public void printQueue();
}
</code></pre>
<h2 id="인터페이스-구현--사전-준비-">인터페이스 구현 ( 사전 준비 )</h2>
<p>구현하기 전, MyLinkedList 부분에 비었는지를 확인하는 코드를 추가합니다.</p>
<pre><code class="language-java">public boolean isEmpty() {
    if (head == null) return true; // head 값이 없을때 True를 반환
    else return false; // 하나라도 있을 경우 false
}</code></pre>
<p>그리고 인터페이스를 구현해보죠.
일단 front와 rear를 선언해야 합니다.</p>
<pre><code class="language-java">public class MyLinkedQueue extends MyLinkedList implements IQueue{

    MyListNode front; // 맨 앞부분인 front
    MyListNode rear; // 맨 뒷부분인 rear}</code></pre>
<h2 id="인터페이스-구현--enqueue-">인터페이스 구현 ( enQueue )</h2>
<pre><code class="language-java">@Override
public void enQueue(String data) {
    MyListNode newNode;
    if(isEmpty()) { // 만약 비었으면
        newNode = addElement(data); // newNode를 만들어서 할당하고
        front = newNode
        rear = newNode; // front와 rear 둘다 newNode로 바꿉니다.
    } else { // 하나라도 있으면
        newNode = addElement(data); // 똑같이 newNode를 만들어서 할당하고
        rear = newNode; // rear만 newNode로 바꿔줍니다.
    }
}</code></pre>
<h2 id="인터페이스-구현--dequeue-">인터페이스 구현 ( deQueue )</h2>
<pre><code class="language-java">@Override
public String deQueue() {
    if (isEmpty()) { // 만약 비었다면?
        return null; // 아무것도 없으므로 null을 return합니다.
    }

    String data = front.getData(); // front 자료 값을 불러옵니다.
    front = front.next; // front를 front에 링크로 바꿉니다.

    if(front == null) { // front가 null이라면?
        rear = null; // 마지막인 rear도 null로 바꿔줍니다.
    }

    return data; // data를 return 합니다.
}</code></pre>
<h2 id="인터페이스-구현--printqueue-">인터페이스 구현 ( printQueue )</h2>
<pre><code class="language-java">@Override
public void printQueue() {
    printAll(); // 전에 만들었던 MyLinkedList에서 불러옵니다.
}</code></pre>
<h2 id="전체-구현-코드좀-줘봐">전체 구현 코드좀 줘봐</h2>
<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/16821dad-9838-4b63-8aaa-56fb509509ba/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/1db53ccf-df37-4757-8a6f-88a19962f615/image.png" alt=""></p>
<p>전체 구현 코드는 <a href="https://github.com/BackdevHong/Java-All/tree/main/Java-DataStructure/Queue/src">여기</a>서도 확인 가능합니다.</p>
<h2 id="마치며">마치며</h2>
<p>이렇게 해서 선형 자료구조는 모두 구현이 끝났습니다.
시간이 남으면 비선형 자료구조도 구현해보겠지만, 일단 강좌를 봐야하기에 구현편은 여기까지 하겠습니다.
그럼 다음시간에 다시 보죠!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조 #6 - 스택 구현]]></title>
            <link>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-6-%EC%8A%A4%ED%83%9D%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-6-%EC%8A%A4%ED%83%9D%EA%B5%AC%ED%98%84</guid>
            <pubDate>Mon, 28 Nov 2022 06:11:01 GMT</pubDate>
            <description><![CDATA[<p>이 포스트는 FastCampus에 <a href="https://fastcampus.co.kr/dev_online_javaend"> 이 강의</a>를 보고 포스팅되었습니다.
문제가 될 시 삭제될 예정입니다.</p>
<h2 id="시작하기-전에-스택-특징-좀-다시-알려줘바">시작하기 전에 스택 특징 좀 다시 알려줘바</h2>
<ul>
<li>맨 마지막 위치인 Top에서만 연산을 수행할 수 있습니다.<ul>
<li>삽입 연산 - Push</li>
<li>꺼내는 연산(<strong>삭제도 같이합니다.</strong>) - Pop </li>
<li>꺼내보기만 하는 연산(<strong>삭제는 안합니다.</strong>) - Peek</li>
</ul>
</li>
<li>LIFO(Last In First Out, 후입선출) 구조로 되어있습니다.</li>
<li>택배 상자가 쌓여있는 모양을 하고 있습니다.</li>
<li>장기에서 무르기를 예로 들 수 있습니다.</li>
</ul>
<p>JDK 클래스에는 Stack이 있습니다.</p>
<h2 id="뭘-구현할건데">뭘 구현할건데?</h2>
<p>Push와 Pop, Peek를 구현해볼까 합니다.</p>
<h2 id="잠깐-이거-코드-여기에만-올라옴">잠깐 이거 코드 여기에만 올라옴??</h2>
<p>전편에도 말했지만 모든 코드는 깃허브에 올라갈 예정입니다.<a href="https://github.com/BackdevHong/Java-All/tree/main/Java-DataStructure">
링크</a></p>
<h2 id="시작하기-전">시작하기 전</h2>
<p>이번에 할 스택 구현은 <a href="https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-4-%EB%B0%B0%EC%97%B4%EA%B5%AC%ED%98%84">저번</a>에 만든 배열 클래스를 가져와서 구현합니다.
<del>히히 재밌겠ㄷ</del></p>
<h2 id="스택-생성">스택 생성</h2>
<pre><code class="language-java">public class MyArrayStack {
    MyArray arrayStack; // 저번에 만든 MyArray를 가져와 선언함
    int top; // top은 Count와 같은 역할임

    public MyArrayStack() {  // 기본 생성자
        top = 0;
        arrayStack = new MyArray();
    }

    public MyArrayStack(int size) { // 사이즈를 받을때는
        top = 0; // Top는 그대로 있어야함!
        arrayStack = new MyArray(size); // MyArray에 사이즈를 전달.
    }
}</code></pre>
<h2 id="스택이-다-찼는지-확인">스택이 다 찼는지 확인</h2>
<pre><code class="language-java">public boolean isFull() {
    if (top == arrayStack.ARRAY_SIZE) { // top과 배열 크기가 같으면
        return true; // 꽉찬거라고 전해줌
    }
    return false; // 아님 안찼다고 전해줌
}</code></pre>
<h2 id="반대로-스택이-비었는지-확인">반대로 스택이 비었는지 확인</h2>
<pre><code class="language-java">public boolean isEmpty() {
    if (top == 0) { // top이 0이라면?
        return true; // 비었다고 전해줌
    }
    return false; // 아님 하나 이상 들어와있다고 전해줌
}</code></pre>
<h2 id="스택-push-구현">스택 Push 구현</h2>
<pre><code class="language-java">public void push(int data) {
    if (isFull()) { // 만약 다 찼다면?
        System.out.println(&quot;꽉차서 자료를 추가할 수 없습니다.&quot;); // 에러 메시지 출력
        return;
    }
    arrayStack.addElement(data); // 자료 추가
    top++; // top 증가
}</code></pre>
<h2 id="스택-pop-구현">스택 Pop 구현</h2>
<pre><code class="language-java">public int pop() {
    if(isEmpty()) { // 만약 비었다면?
        System.out.println(&quot;배열이 비어있습니다.&quot;); // 에러 메시지 출력
        return MyArray.ERROR_NUM; // 에러 넘버 반환
    }
    return arrayStack.deleteElement(--top); // 요소를 삭제함과 동시에 삭제한 요소를 반환
}
</code></pre>
<h2 id="스택-peek-구현">스택 Peek 구현</h2>
<p>Peek를 구현하기 위해 MyArray에 특정 위치에 있는 자료를 반환하는 메서드를 만듭니다.</p>
<pre><code class="language-java">// MyArray.java
public int getElement(int position) {
    // 만약 count가 0라면
    if (isEmpty()) {
        // 예외 발생
        throw new ArrayStoreException(&quot;이미 값이 없는 배열입니다.&quot;);
    }

    // 만약 포지션 값이 이상하게 들어올 경우
    if (position &lt; 0 || position &gt; count - 1) {
        // 예외 발생
        throw new ArrayStoreException(&quot;포지션 값이 이상합니다.&quot;);
    }

    return intArr[position]; // 해당 position 값에 있는 자료 출력
}</code></pre>
<p>그리고 peek를 구현합니다.</p>
<pre><code class="language-java">public int peek() {
    if(isEmpty()) { // 만약 비었다면?
        System.out.println(&quot;배열이 비어있습니다.&quot;); // 에러 메시지 출력
        return MyArray.ERROR_NUM; // 에러 넘버 반환
    }
    return arrayStack.getElement(--top);
}</code></pre>
<h2 id="전체-구현-코드좀-줘바">전체 구현 코드좀 줘바</h2>
<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/c63a7b66-88d7-45b3-ba44-8eaa11f478fc/image.png" alt="">
전체 구현 코드는 <a href="https://github.com/BackdevHong/Java-All/tree/main/Java-DataStructure/Stack/src">여기</a>서도 확인 가능합니다.</p>
<h2 id="마치며">마치며</h2>
<p>배열을 이용한 스택 구현은 여기까지입니다.
다음 시간에는 연결리스트를 이용한 큐(Queue)를 구현해보도록 하겠습니다.
수고하셨습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조 #5 - 연결리스트 구현]]></title>
            <link>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-5-%EC%97%B0%EA%B2%B0%EB%A6%AC%EC%8A%A4%ED%8A%B8%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-5-%EC%97%B0%EA%B2%B0%EB%A6%AC%EC%8A%A4%ED%8A%B8%EA%B5%AC%ED%98%84</guid>
            <pubDate>Mon, 28 Nov 2022 03:06:23 GMT</pubDate>
            <description><![CDATA[<p>이 포스트는 FastCampus에 <a href="https://fastcampus.co.kr/dev_online_javaend"> 이 강의</a>를 보고 포스팅되었습니다.
문제가 될 시 삭제될 예정입니다.</p>
<h2 id="시작하기-전에-연결리스트-특징-복습-ㄱㄱ">시작하기 전에 연결리스트 특징 복습 ㄱㄱ</h2>
<ul>
<li>동일한 데이터 타입을 순서에 따라 관리하는 자료 구조입니다.</li>
<li>하나의 노드에는 자료와 다음 요소를 가리키는 링크가 있습니다.</li>
<li>자료가 추가 될때 노드 만큼의 메모리를 할당 받고 이전 노드의 링크로 연결합니다.</li>
<li>i번째 요소를 찾는데 걸리는 시간은 요소의 개수에 비례합니다. ( O(n) )</li>
</ul>
<p>JDK 클래스에는 LinkedList가 있습니다.</p>
<h2 id="뭘-구현해볼-건데">뭘 구현해볼 건데</h2>
<p>노드 정의, 연결리스트 추가, 삭제, 조회를 구현해볼 예정입니다.</p>
<h2 id="잠깐-이거-코드-여기에만-올라옴">잠깐 이거 코드 여기에만 올라옴??</h2>
<p>전편에도 말했지만 모든 코드는 깃허브에 올라갈 예정입니다.
<a href="https://github.com/BackdevHong/Java-All/tree/main/Java-DataStructure/">링크</a></p>
<h2 id="노드-정의">노드 정의</h2>
<pre><code class="language-java">private String data; // 자료
public myListNode next; // 다음 노드를 가리키는 링크

public myListNode() { // 기본 생성자
    this.data = null;
    this.next = null;
}

public myListNode(String data) { // 자료를 집어넣는 생성자
    this.data = data;
    this.next = null;
}

public myListNode(String data, myListNode next) { // 자료 + 다음 링크를 집어넣는 생성자
    this.next = next;
    this.data = data;
}

public String getData() { // 데이터 Return
    return data;
}</code></pre>
<h2 id="연결리스트-정의">연결리스트 정의</h2>
<pre><code class="language-java">private myListNode head; // 첫번째 자료
private int count; // 노드 수

public myLinkedList() { // 기본 생성자
    this.head = null;
    this.count = 0;
}</code></pre>
<blockquote>
<p>연결리스트를 정의하는 쪽에서는 두 가지 방법이 있습니다.</p>
</blockquote>
<ul>
<li>Head 자체를 첫 번째 자료로 쓰는 방법<ul>
<li>가장 단순하고, 쉬운 방법입니다.</li>
<li>저희가 구현할 방법이기도 합니다.</li>
</ul>
</li>
<li>Head 포인터를 사용하는 방법<ul>
<li>Head를 더미로 놔두고, 더미가 첫 번째 자료를 가리키는 방식입니다.</li>
<li>위 방법을 Head 포인터라고 하죠.</li>
</ul>
</li>
</ul>
<h2 id="연결리스트-추가">연결리스트 추가</h2>
<pre><code class="language-java">public myListNode addElement(String data) {
    myListNode newNode; // 빈 노드를 하나 만든다.
    if(head == null) { // head가 null이라면
        newNode = new myListNode(data); // 빈 노드에 데이터를 넣어주고
        head = newNode; // head를 newNode로 바꾼다.
    }
    else { // 아니라면
        newNode = new myListNode(data); // 마찬가지로 빈 노드에 데이터를 넣어주고
        myListNode temp = head; // temp값을 하나 만들어서 거기에 head를 넣어준 뒤
        while (temp.next != null) { // null이 될때까지 while을 돌린다.
            temp = temp.next; // null이 아니라면 temp에 다음 노드를 temp로 바꾼다.
        }
        temp.next = newNode; // null 이라면 temp에 다음 노드에 newNode를 추가해준다.
    }
    count++; // 어찌됬든 값이 늘어나니 count를 늘려주고

    return newNode; // newNode를 반환한다.
}</code></pre>
<h2 id="연결리스트-삽입">연결리스트 삽입</h2>
<pre><code class="language-java">public myListNode insertElement(int position, String data) {
    int i;
    myListNode tempNode = head; // tempNode는 head를 가리키게 선언
    myListNode preNode = null; // pre노드는 null로 선언

    myListNode newNode = new myListNode(data); // 새로운 노드를 생성한다.
    if(position &lt; 0 || position &gt; count) { // 만약 position이 이상한 값이 들어올 경우
        return null; // null을 반환한다.
    }

    if(position == 0) { // 만약 위치가 첫번째라면?
        newNode.next = head; // 새로운 노드에 링크를 head를 가르키게 바꾸고
        head = newNode; // head를 newNode로 바꾼다.
    }

    else { // 아니라면
        for (i = 0; i &lt; position; i++) { // position 전 값이 될때까지 for문을 돌린다.
            preNode = tempNode; // preNode는 tempNode가 되고
            tempNode = tempNode.next; // tempNode를 tempNode에 링크로 바꿔준다.
        }
        newNode.next = preNode.next; // 찾았다면 newNode에 링크를 preNode에 링크로 바꿔주고
        preNode.next = newNode; // preNode에 링크를 newNode로 바꿔준다.
    }

    count++; // 어찌 됐든 값이 늘어나니 count를 늘려주고
    return newNode; // newNode를 반환한다.
}</code></pre>
<h2 id="연결리스트-삭제">연결리스트 삭제</h2>
<pre><code class="language-java">public myListNode removeElement(int position) {
    int i;
    myListNode tempNode = head; // tempNode는 head를 가리키게 선언
    myListNode preNode = null; // pre노드는 null로 선언

    if(position &lt; 0 || position &gt; count) { // 만약 position이 이상한 값이 들어올 경우
        return null; // null을 반환한다.
    }

    if(position == 0) { // 만약 위치가 첫번째라면?
        head = tempNode.next; // head를 tempNode에 링크로 바꿔준다.
    } else {
        for (i = 0; i &lt; position; i++) { // position 전 값이 될때까지 for문을 돌린다.
            preNode = tempNode; // preNode는 tempNode가 되고
            tempNode = tempNode.next; // tempNode를 tempNode에 링크로 바꿔준다.
        }
        preNode.next = tempNode.next; // preNode에 링크를 tempNode에 링크로 바꿔준다.
    }

    count--; // 카운트를 하나 빼주고
    return tempNode; // 삭제된 노드를 리턴한다.
}</code></pre>
<h2 id="연결리스트-조회-1개-자료-">연결리스트 조회( 1개, 자료 )</h2>
<pre><code class="language-java">public String getElement(int position) {
    int i;
    myListNode tempNode = head;

    if(position &lt; 0 || position &gt; count) { // 만약 position이 이상한 값이 들어올 경우
        System.out.println(&quot;포지션 오류입니다.&quot;); // 오류 메시지를 띄우고
        return null; // null을 반환한다.
    }

    if (position == 0) { // 만약 위치가 첫번째라면?
        return head.getData(); // head에 자료를 가져온다.
    }

    for(i = 0; i &lt; position; i++) { // 위치까지 for문을 돌린다.
        tempNode = tempNode.next; // tempNode를 tempNode에 다음 링크로 바꾼다.
    } 
    return tempNode.getData(); // for문을 다 돌리고 난 뒤 tempNode에 데이터를 가져온다.
}</code></pre>
<h2 id="연결리스트-조회-1개-노드-">연결리스트 조회( 1개, 노드 )</h2>
<pre><code class="language-java">public myListNode getNode(int position) {
    int i;
    myListNode tempNode = head;

    if(position &lt; 0 || position &gt; count) { // 만약 position이 이상한 값이 들어올 경우
        System.out.println(&quot;포지션 오류입니다.&quot;); // 오류 메시지를 띄우고
        return null; // null을 반환한다.
    }

    if (position == 0) { // 만약 위치가 첫번째라면?
        return head; // head에 자료를 가져온다.
    }

    for(i = 0; i &lt; position; i++) { // 위치까지 for문을 돌린다.
        tempNode = tempNode.next; // tempNode를 tempNode에 다음 링크로 바꾼다.
    }
    return tempNode; // for문을 다 돌리고 난 뒤 tempNode에 데이터를 가져온다.
}</code></pre>
<h2 id="연결리스트-조회-모두-">연결리스트 조회( 모두 )</h2>
<pre><code class="language-java">public void printAll() {
    if (count == 0) { // count값이 비어 있을 때 = 아무런 내용이 없을 때
        System.out.println(&quot;출력할 내용이 없답니다.&quot;); // 에러메시지 출력
        return;
    }

    myListNode tempNode = head; // tempNode를 생성, head로 선언한다.
    while(tempNode.next != null) {  // tempNode가 null이 될때까지
        System.out.print(tempNode.getData());
        tempNode = tempNode.next;
        if (tempNode != null) {
            System.out.print(&quot; -&gt; &quot;);
        }
    } // 출력시킨다.
    System.out.println(&quot;&quot;);
}</code></pre>
<h2 id="연결리스트-조회-count-">연결리스트 조회( Count )</h2>
<pre><code class="language-java">public int getCount() {
    return count;
}</code></pre>
<h2 id="연결리스트-전체-삭제">연결리스트 전체 삭제</h2>
<pre><code class="language-java">public void removeAll() {
    head = null; // head를 null로 설정하고
    count = 0; // count를 0으로 설정한다.
}</code></pre>
<h2 id="-테스트-코드">+ 테스트 코드</h2>
<pre><code class="language-java">public static void main(String[] args) {
    MyLinkedList list = new MyLinkedList();
    list.addElement(&quot;A&quot;);
    list.addElement(&quot;B&quot;);
    list.addElement(&quot;C&quot;);
    list.printAll();
    list.insertElement(3, &quot;D&quot;);
    list.printAll();
    list.removeElement(0);
    list.printAll();
    list.removeElement(1);
    list.printAll();

    list.insertElement(0, &quot;A-1&quot;);
    list.printAll();
    System.out.println(list.getSize());

    list.removeElement(0);
    list.printAll();
    System.out.println(list.getSize());

    list.removeAll();
    list.printAll();
    list.addElement(&quot;A&quot;);
    list.printAll();
    System.out.println(list.getElement(0));
    list.removeElement(0);
}</code></pre>
<p>위 코드는 <a href="//https://github.com/easyspubjava/FastCampus/blob/master/Chapter5/src/ch03/MyLinkedListTest.java">여기서</a> 가져왔습니다.</p>
<h2 id="전체-구현-코드좀-줘바">전체 구현 코드좀 줘바</h2>
<p>노드 구현 코드
<img src="https://velog.velcdn.com/images/fulldev_hong/post/8ac181ff-e35c-4eb9-9630-40157497af6b/image.png" alt=""></p>
<p>연결리스트 구현 코드 
<img src="https://velog.velcdn.com/images/fulldev_hong/post/2604dfad-af34-4c70-a461-c50776b3c6f1/image.png" alt=""></p>
<p>전체 구현 코드는 <a href="https://github.com/BackdevHong/Java-All/tree/main/Java-DataStructure/LinkedList/src">여기</a>서도 확인 가능합니다.</p>
<h2 id="마치며">마치며</h2>
<p>연결리스트에 대한 구현은 여기까지입니다.
다음 시간에는 스택을 구현해보도록 하겠습니다.
수고하셨습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[NHN Forward 후기]]></title>
            <link>https://velog.io/@fulldev_hong/NHN-Forward-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@fulldev_hong/NHN-Forward-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Thu, 24 Nov 2022 05:50:39 GMT</pubDate>
            <description><![CDATA[<p>왜 뽑혔는진 모르겠지만 학교를 빼서 기분이 좋다. <del>히히</del>
<img src="https://velog.velcdn.com/images/fulldev_hong/post/0b8ee545-8492-4541-bf2f-57369d85983c/image.jpg" alt=""></p>
<h1 id="0-키노트">0. 키노트</h1>
<p>NHN Cloud에서 만든 AI 목소리가 키노트를 시작하기 전 우리를 반겨주었다.
<del>난 진짜 사람이 마이크에 말하는줄..</del>
아무튼, 처음엔 박근환 AI 본부장님이 오셔서 직접 키노트를 진행해주셨다.
42개에 세션과 12개에 라운지 토크, 게임존/스낵존이 있다고 한다.
여러 분야에서 NHN은 활약중인것같았다.
그중 대표적인 게임, 데이터, 클라우드, AI 4가지 서비스에 대해서 소개를 해주었다.</p>
<h2 id="0-1-게임">0-1. 게임</h2>
<p>NHN Game 류희태 이사님이 오셔서 게임 분야에 대한 소개를 해주셨다.
라인팝, 포코팡, 프렌즈팝 등, 여러 NHN에서 만든 유명한 게임들이 있었다.
캐쥬얼 게임을 제작하기 위해 M Brick이라는 새로운 툴을 직접 만들었다.
M Brick은 아웃 게임 템플릿을 이미 만들어서 제작 기간을 줄였다.
Gamebase와 광고 관련 작업도 이미 다 해놔서 퍼즐게임을 쉽게 만들수 있다.
내년 초 출시 예정인 GameAnvil, GameTalk에 대한 설명을 들었었다.
게임은 NHN에 시작부터 함께 해왔던 분야이다.</p>
<h2 id="0-2-데이터">0-2. 데이터</h2>
<p>NHN DATA 이진수 대표님이 오셔서 데이터 분야에 대한 소개를 해주셨다.
NHN에게 좋은 기술이란? 고객이 체감할 수 있는 고마운 기술이다.
DBTI라는 방식을 이용해 비스니스 유형에 따른 전략을 도출한다.
같은 전략이라고 해도 어떤 방법이 좋은지?에 대한 방법 조차 자동으로 선정하여 제시한다.</p>
<p>2026년까지 글로벌 탑기어 데이터 테크 컴퍼니를 목표로 하고 있답니다.</p>
<h2 id="0-3-클라우드">0-3. 클라우드</h2>
<p>NHN Cloud 김명신 CTO님이 오셔서 클라우드 분야에 대한 소개를 해주셨다.
2014년부터 토스트 클라우드라는 이름으로 서비스를 시작하였다.
2019년엔 일본, 미국 등 해외 진출을 하였고, 2021년엔 이름을 NHN Cloud로 바꿨다.
매해 30% 이상 성장해나가고 있다.
판교, 평촌, 도쿄, LA에 데이터 센터를 설립했고, 광주, 김해에도 데이터 센터를 만들 계획에 있다고 한다.
순천에는 공공 클라우드 데이터 센터를 설립할 예정이라고 한다.
100개 이상에 서비스와 150개 이상에 솔루션이 있다.
현재는 NKS라 부르는 NHN 쿠버네티스 서비스를 제공하고 있고, 사업자중 최초로, 유일하게 Cloud Native 기술력을 보유하고 있다.
NHN Cloud는 AI 서비스를 목표로 하고 있다.</p>
<h2 id="0-4-ai">0-4 AI</h2>
<p>NHN AI 박근환 본부장님이 오셔서 마지막으로 AI에 대해서 설명해주셨다.</p>
<p>AI EasyMaker는 AI 기술을 누구나 쉽게 개발할 수 있게 제공하는 서비스다
<strong>내년 광주 데이터센터를 이용하여 점차 공개할 예정이라 한다.</strong></p>
<p>AI Tech Understanding 이 기술을 이용해서 여러 기술에 접목할 수 있다 한다.
예를 들어 동화책 TTS 시스템, 가상 아나운서, 카툰 생성기술이 있다.</p>
<p>Small Steps make a Big Difference
작은 한 걸음이 큰 변화를 일으킨다.</p>
<p>이렇게 키노트가 끝났다.</p>
<h1 id="세션1---데이터로-알아보는-lol과-esport">세션1 - 데이터로 알아보는 LOL과 Esport</h1>
<p>관심이 생긴 세션이 있어서 참여해보았다.
Your.gg를 개발하신 차민창 CEO님이 발표해주셨다.
데이터를 기반으로 LOL에 전략을 분석하는 서비스가 Your.gg이다.
<del>참여한 사람들 중 플레 이상인 분이 없다는게 더 놀랍</del>
하위권 티어에 있는 사람들에 질의문답을 보면서 &quot;왜 이렇게 주관적이지?&quot; 생각해서 만들어낸것이 Your.gg이다.</p>
<h2 id="1-1-지표">1-1. 지표</h2>
<p>가장 먼저 만든 지표가 &quot;인분&quot;이다.
인분의 단순 정렬이지만 반응이 좋았던 지표인 &quot;등수&quot;,
커뮤니티에서 한탄하는 글을 보고 만든 지표인 &quot;팀운&quot;,
앞선 지표보다 실용성을 극대화 시킨 지표인 &quot;예상 승률(멀티 서치 AI)&quot;,
유료 상품인 PLAYREPORT에 들어간 지표인 &quot;티어 예측(딥러닝 AI)&quot;이 있다.</p>
<h3 id="1-1-1-시행착오">1-1-1. 시행착오</h3>
<h4 id="1-정확도가-낮았다">1. 정확도가 낮았다.</h4>
<h4 id="2-특정-조건에서만-유효함">2. 특정 조건에서만 유효함</h4>
<p>특정 라인이나 어떠한 조건에서만 유효하고, 다른 라인으로 가면 좀 안맞는 경우가 있다.</p>
<h4 id="3-사용자-감성에-부합하지-않음">3. 사용자 감성에 부합하지 않음</h4>
<h3 id="1-1-2-지표-개발-프로세스">1-1-2. 지표 개발 프로세스</h3>
<p>위 시행착오를 겪어가면서 지표 개발 프로세스가 만들어졌다.
발견 -&gt; 연구 -&gt; 구현 -&gt; UX -&gt; 테스트</p>
<h4 id="발견">발견</h4>
<p>인벤, 커뮤니티 등에서 올라오는 게시글로 지표를 만든다.</p>
<h4 id="연구">연구</h4>
<p>타당성 조사 : 이걸 구현할 수 있나? 타당성을 조사한다.
정량적 분석 : 먼저 가설을 정하고, 지표를 만들어서 통과를 하나? 보는 것이다.
탐색적 테스트 : 사용자가 이상하게 느낄수 있나? 같은 부분을 조사한다.</p>
<h4 id="구현">구현</h4>
<p>말 그대로 구현이다.</p>
<h4 id="ux">UX</h4>
<p>아무리 휼륭한 지표라도 중고등학생이 이해하지 못하면 말짱도루묵이다.
그래서 위 지표에 어려운 부분들을 쉽게 바꾸는 것이다.
예) 0.4748 -&gt; 라인전 6:4 이런식으로
그리고 재미를 만들기 위해서 문장을 추가한다.
예) 10분까지 2킬 못하면 골드 못가요.. 왜나면..</p>
<h4 id="테스트">테스트</h4>
<p>공급자에 입장이 아닌 철저하게 사용자의 시각으로 만들어졌는지 테스트한다.
항상 예상보다는 많은 이슈가 생긴다.
<del>앗.. 아아</del></p>
<h3 id="1-1-3-옛-지표가-새로운-지표에-영향을-주며-진화">1-1-3. 옛 지표가 새로운 지표에 영향을 주며 진화</h3>
<p>예를 들어 인분을 만들면, 의도치 않게 다른 지표도 만들어졌었다.</p>
<h2 id="1-2-e-sport">1-2. E-Sport</h2>
<h3 id="1-2-1-머니볼">1-2-1. 머니볼</h3>
<p>머니볼이라는 영화는 데이터를 모집해 야구팀을 더욱 성장시키는 이야기다.
하지만 이 영화로 인해 오해가 여러가지 생겼다.
<strong>OPS만 보면 야구 짱 먹을 수 있겠다!</strong> 이런식으로..</p>
<h3 id="1-2-2-은총알은-없다">1-2-2. 은총알은 없다.</h3>
<p>은총알은 없다. 라는 논문이 있다.
한마디로 요약하자면, 어떤 방법 하나로 본질적인 문제를 해결할 순 없다는 뜻이다.</p>
<h3 id="1-2-3-e-sport는-은총알이-있다">1-2-3. E-sport는 은총알이 있다?</h3>
<p>무조건 우세한 밴픽을 할 수 있는 팀이 있다고 가정해보자.
이것만으로 과연 그 팀이 승리할 수 있을까? 난 아니라고 본다.
밴픽뿐만이 아닌 선수 자체에 스팩, 선발, 전략 등 고려해야할 점이 너무 많다.</p>
<h3 id="1-2-4-데이터를-활용하는-두가지-방법">1-2-4. 데이터를 활용하는 두가지 방법</h3>
<p>Data Driven은 하나에 데이터가 있으면 그 데이터를 중점으로 활용하는 것이고Data Informed는 사람을 중점으로 데이터를 활용하는 것이다.</p>
<h3 id="1-2-5-data-driven이-e-sport에-적합하지-않은-이유">1-2-5. Data Driven이 E-sport에 적합하지 않은 이유?</h3>
<ol>
<li>데이터가 적어 편향이 생길 수 있다.</li>
<li>업계의 성숙도가 부족하다.</li>
<li>아직은 전문가의 직관이 데이터를 뛰어 넘기도 함</li>
</ol>
<h2 id="1-3-정리">1-3. 정리</h2>
<p>지표는 <strong>기술 기반 컨텐츠</strong>이다.
데이터로 경쟁력을 만들 수 있다.</p>
<h1 id="세션2---dooray가-재택근무를-하는-방식">세션2 - Dooray가 재택근무를 하는 방식</h1>
<p>NHN Dooray 기획팀 김형근님께서 발표하신 내용입니다</p>
<h2 id="2-1-재택근무를-시작하게-된-이야기">2-1 재택근무를 시작하게 된 이야기</h2>
<p>오프라인으로 진행되던 모든 업무들이 Dooray! 서비스를 이용해서 온라인으로 진행되었다.
Dooray!가 뭘까?</p>
<h3 id="2-1-1-dooray">2-1-1. Dooray!?</h3>
<p>재택근무에 필요한 모든 서비스를 제공하는 서비스입니다.
화상회의, 메신저, 메일, 업무, 드라이브, 위키, 게시판, 전자결제, 근무관리 등등 재택근무와 협업을 위한 올인원 서비스이다.
언제 어디서나 접속이 가능하도록 PC, 안드로이드, 아이폰, 패드 등등 여러 플렛폼을 지원한다.</p>
<h3 id="2-1-2-dooray의-업무-문화">2-1-2. Dooray!의 업무 문화</h3>
<h4 id="소통문화">소통문화</h4>
<p>일반적인 회사의 소통문화</p>
<pre><code>안녕하세요. OOO 이사님.
스펙 확인해 주실 수 있을까요?
수정된 스펙 첨부 파일로 공유해 드립니다.

확인해 주시면 감사하겠습니다.
감사합니다.</code></pre><p>Dooray! 소통 문화</p>
<pre><code>@홍인성
&quot;ABCD 기획안&quot;
기획안 보내드립니다~ 확인해주세요!</code></pre><h4 id="업무-상태-공유">업무 상태 공유!</h4>
<p>나에 업무 상태, 근태를 공유하는 것은 중요하다.</p>
<h4 id="하위-엄무-첨부-참조로-모든것을-연결하여-기록한다">하위 엄무, 첨부, 참조로 모든것을 연결하여 기록한다.</h4>
<p>생성된 업무들끼리 구조화 시켜서 업무를 분산화시킨다.</p>
<h2 id="2-2-dooray로-재택근무-하는-방법">2-2 Dooray!로 재택근무 하는 방법</h2>
<p>김형근님에 하루를 알아봅시다</p>
<ul>
<li>AM 7시 : 스마트폰으로 <strong>나만을 위한 뉴스</strong>를 확인합니다.<ul>
<li>담당 업무, 알림 주요 내용을 볼 수 있다.</li>
<li>기본적인 알림, Push 메시지를 모아 볼수 있으니까 이것만 보면 
어떤 것을 알아야 하는지 알 수 있다.</li>
<li>그래서 개인에 시간을 좀더 아낄 수 있다.</li>
</ul>
</li>
<li>AM 9시 30분 : 일정확인 및 관리<ul>
<li>재택근무의 시작은 일정 관리부터! 캘린더를 확인해보자.</li>
<li>공유 캘린더로 동료들과 함께 캘린더를 생성, 확인할 수 있다.</li>
<li>아래 바 캘린더로 시간도 확인할 수 있다.</li>
<li>일정 생성할 때도 어떤 일정이 있는지 미리 확인하고 생성할 수 있다.</li>
</ul>
</li>
<li>AM 10시 : 신규 입사자 가이드 위키 공유<ul>
<li>노션같은 위키를 작성해서 공유한다.</li>
<li>외부 공유도 가능</li>
</ul>
</li>
<li>AM 11시 : 화상회의<ul>
<li>화상회의를 진행한다.</li>
<li>뒷배경 가리기, 녹화기능, 화면공유, 반응 등등 여러가지 기능이 들어가있다.</li>
<li>채팅대화를 할때도 글타래같은 기능이 있어서 심층대화가 가능하다. ( 디스코드에 스레드같은 기능 )</li>
</ul>
</li>
<li>점심시간!</li>
<li>긴급메일이 도착했다!<ul>
<li>메일을 업무로, 캘린더로 보낼수없다.</li>
<li>반대로 업무를 메일로 보낼수도 있습니다!</li>
</ul>
</li>
<li>PM 2시 : 보드 뷰로 주간 회의!<ul>
<li>보드 뷰로 현재 업무 상태와 진행자가 누구인지 확인 가능하다.</li>
</ul>
</li>
<li>PM 4시 : 외부 파트너사 직원 분께 손님 계정 발급<ul>
<li>손님 계정을 발급해서 출근할 필요가 없어진다.</li>
</ul>
</li>
<li>PM 5시 : 발표<ul>
<li>발표 모드를 이용해서 ppt를 쉽고 빠르게 만들 수 있다.</li>
</ul>
</li>
</ul>
<h2 id="2-3-재택근무-꿀팁">2-3 재택근무 꿀팁</h2>
<ol>
<li>근무 장소 선정<ul>
<li>안방은 위험함!</li>
<li>집중이 잘되고 좋은 장소를 선정해야함!</li>
</ul>
</li>
<li>너무 편한 의상은 금지!<ul>
<li>잠옷을 공유할 필요는 없음.</li>
</ul>
</li>
<li>가족들에게 미리 말하기<ul>
<li>가족들이 일에 방해를 주면 안되잖어?</li>
</ul>
</li>
<li>직장 동료들과 함께 원격 취미활동</li>
<li>마음을 적극적으로 표현해보자!</li>
</ol>
<h2 id="2-4-재택근무의-장점과-남겨진-숙제">2-4 재택근무의 장점과 남겨진 숙제</h2>
<ul>
<li>출퇴근 시간을 아낄수 있다</li>
<li>효율적인 업무가 가능하다.</li>
<li>지방에서 살아도 재택근무가 가능하다.</li>
<li>가족과 함께 정서적 안정이 가능하다.</li>
</ul>
<p>물론 남겨진 숙제도 있다.</p>
<ul>
<li>체중이 증가(...)한다.</li>
<li>워라밸</li>
<li>정서적인 외로움이 느껴질 수 있다.</li>
<li>접속기기, 환경을 구축하는데 부담을 느낄수있다.</li>
</ul>
<h1 id="정리">정리</h1>
<p>여러기지 게임존, 부스도 있었고 세션도 다양했었던 이번 NHN 컨퍼런스 너무 좋았다.
다음에도 당첨된다면 그때는 맥북과 아이폰을 들고 배터리 운운할거없이 내가 들은 세션을 전부 적으리.
그럼 지금까지 NHN forward 후기였다.
<img src="https://velog.velcdn.com/images/fulldev_hong/post/483e8721-8890-4e6c-8e08-6eb1899aae0d/image.jpg" alt="">
<del>아 행복했다.</del></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조 #4 - 배열 구현]]></title>
            <link>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-4-%EB%B0%B0%EC%97%B4%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-4-%EB%B0%B0%EC%97%B4%EA%B5%AC%ED%98%84</guid>
            <pubDate>Tue, 22 Nov 2022 06:57:16 GMT</pubDate>
            <description><![CDATA[<p>이 포스트는 FastCampus에 <a href="https://fastcampus.co.kr/dev_online_javaend"> 이 강의</a>를 보고 포스팅되었습니다.
문제가 될 시 삭제될 예정입니다.</p>
<h2 id="시작하기-전에-배열-특징-좀-다시-알려줘봐">시작하기 전에 배열 특징 좀 다시 알려줘봐</h2>
<ol>
<li>같은 데이터 타입을 순서에 따라 관리하는 자료구조입니다.</li>
<li>정해진 크기가 있습니다.</li>
<li>요소의 추가와 제거 시 다른 요소들의 이동이 필요합니다 ( 앞 / 뒤 )</li>
<li>배열에 i번째 요소를 찾는 연산이 빠릅니다.</li>
</ol>
<p>JDK 클래스에는 ArrayList와 Vector가 있습니다.</p>
<h2 id="뭘-구현해볼-건데">뭘 구현해볼 건데</h2>
<p>배열 생성, 추가기능, 배열을 중간에 추가하는 것과 제거하는 메서드를 만들어볼 겁니다. 같이 가보시죠.</p>
<h2 id="잠깐-이거-코드-여기에만-올라옴">잠깐 이거 코드 여기에만 올라옴??</h2>
<p>전편에도 말했지만 모든 코드는 깃허브에 올라갈 예정입니다.
<a href="https://github.com/BackdevHong/Java-All/tree/main/Java-DataStructure">링크</a></p>
<h2 id="배열-생성">배열 생성</h2>
<pre><code class="language-java">int[] intArr; // integer 배열
int count; // 개수

public int ARRAY_SIZE;
public static final int ERROR_NUM = -999999999;

// 기본 생성자 생성
public myArray() {
    ARRAY_SIZE = 10; // 크기 지정 안 할 시 기본값 10으로 설정
    count = 0; // 개수 0으로 설정
    intArr = new int[ARRAY_SIZE]; // 새로운 배열로 설정 ( 크기는 기본 10으로 )
}

// 오버라이딩 생성자 생성
public myArray(int size) {
    ARRAY_SIZE = size; // 크기 지정할시 지정한 크기로 설정
    count = 0; // 개수 0으로 설정
    intArr = new int[size]; // 새로운 배열로 설정 ( 크기는 size 값 )
}</code></pre>
<h2 id="값-추가">값 추가</h2>
<pre><code class="language-java">// 값 추가
public void addElement(int num) {
    if (count &gt;= ARRAY_SIZE) { // 만약 count가 배열 크기를 넘는다면
        // 예외처리
        throw new ArrayStoreException(&quot;더는 저장할 수 있는 공간이 없습니다.&quot;);
    }
    intArr[count++] = num; // 아니라면 배열에 값 추가하고 count += 1
}</code></pre>
<h2 id="값-중간에-추가">값 중간에 추가</h2>
<pre><code class="language-java">// 배열 중간에 값을 추가합니다.
public void insertElement(int position, int num) {
    // 만약 포지션 값이 이상하게 들어올 경우
    if (position &lt; 0 || position &gt;= count) { 
        // 예외 발생
        throw new ArrayStoreException(&quot;포지션 값이 이상합니다.&quot;);
    }

    // 만약 count가 배열 크기를 넘는다면
    if (count &gt;= ARRAY_SIZE) { 
        // 예외 발생
        throw new ArrayStoreException(&quot;더는 저장할 수 있는 공간이 없습니다.&quot;);
    }

    // 위 if 문 두 개에 안 걸린다면 중간에 넣기를 실행
    // i는 초깃값 count-1개, position 이상일 경우 종료, i가 하나씩 줄어들면서 진행
    for (int i = count - 1; i &gt;= position; i--) {
        // 배열에 i-1 위치에 있는 값을 i 위치에 있는 값으로 변경
        intArr[i+1] = intArr[i];
    }

    // position 인덱스에 num값 입력
    intArr[position] = num;
    // count + 1
    count++;
}</code></pre>
<h2 id="값-삭제">값 삭제</h2>
<pre><code class="language-java"> public int deleteElement(int position) {
    // 만약 count가 0이라면
    if (isEmpty()) {
        // 예외 발생
        throw new ArrayStoreException(&quot;이미 값이 없는 배열입니다.&quot;);
    }

    // 만약 포지션 값이 이상하게 들어올 경우
    if (position &lt; 0 || position &gt; count - 1) {
        // 예외 발생
        throw new ArrayStoreException(&quot;포지션 값이 이상합니다.&quot;);
    }

    // ret을 intArr[position] 값으로 할당
    int ret = intArr[position];

    // i 초깃값은 position으로, count - 1번까지 돌린다
    for (int i = position; i &lt;= count - 1; i++) {
        // intArr[i]를 intArr[i+1]로 바꾼다.
        intArr[i] = intArr[i+1];
    }

    // count - 1
    count--;

    // ret return
    return ret;
}</code></pre>
<h2 id="값-확인">값 확인</h2>
<pre><code class="language-java">public void checkMyArr() {
    for(int i = 0; i &lt; ARRAY_SIZE; i++) {
        System.out.println(intArr[i]);
    }
}</code></pre>
<h2 id="배열이-비었는지-확인">배열이 비었는지 확인</h2>
<pre><code class="language-java">public boolean isEmpty() {
    // 만약 count가 0이라면
    if ( count == 0 ) {
        // true 리턴
        return true;
    }
    // 아니면 false
    return false;
}</code></pre>
<h2 id="카운트-수-확인">카운트 수 확인</h2>
<pre><code class="language-java">public int getCount() {
    return count;
}</code></pre>
<h2 id="전체-구현-코드좀-줘봐">전체 구현 코드좀 줘봐</h2>
<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/7667a9d4-c281-4edf-a038-c06ab664f9f6/image.png" alt=""></p>
<p>전체 구현 코드는 <a href="https://github.com/BackdevHong/Java-All/tree/main/Java-DataStructure/Array/src">여기</a>서도 확인 가능합니다.</p>
<h2 id="마치며">마치며</h2>
<p>배열에 대한 구현은 여기까지입니다.
다음 시간에는 연결리스트를 구현해보도록 하겠습니다.
수고하셨습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조 #3 - 비선형 자료구조]]></title>
            <link>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-3-%EB%B9%84%EC%84%A0%ED%98%95</link>
            <guid>https://velog.io/@fulldev_hong/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-3-%EB%B9%84%EC%84%A0%ED%98%95</guid>
            <pubDate>Tue, 22 Nov 2022 05:04:19 GMT</pubDate>
            <description><![CDATA[<p>이 포스트는 FastCampus에 <a href="https://fastcampus.co.kr/dev_online_javaend"> 이 강의</a>를 보고 포스팅되었습니다. 
문제가 될 시 삭제될 예정입니다.</p>
<h2 id="비선형">비선형?</h2>
<p>아까 봤던 배열, 연결리스트, 스택, 큐와는 다른 구조입니다.
1:1에 관계가 아닌 1:n, n:m에 관계를 맺죠.</p>
<p>배우기 전에 노드에 대해 좀 짚고 가죠.
노드는 연결구조 또는 계층구조에서 데이터의 기본 단위를 뜻하는 단어입니다.
링크는 노드와 노드를 잇는 연결점입니다.
전에 선형구조에서 배웠던 연결리스트도 노드와 링크로 이루어져 있죠.</p>
<h3 id="트리tree">트리(Tree)</h3>
<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/08799ffd-d8d9-4937-9b01-0382afe96854/image.png" alt="">
부모 노드가 있고, 양옆에 있는 노드를 자식 노드라고 부릅니다.
우리가 프로그래밍에서 많이 쓰는 트리는 <strong>이진 트리</strong>입니다.</p>
<ul>
<li>이진 트리란, 자식 노드가 2개 이하인 트리입니다.</li>
</ul>
<p>이진 트리에서도 대표적으로 쓰는 트리는 <strong>힙(Heap), 이진 검색 트리(BST)</strong>입니다.</p>
<h4 id="힙heap">힙(Heap)</h4>
<p>힙은 완전 이진 트리입니다.
힙은 트리가 채워질 때 무조건 왼쪽 자식 노드부터 채워지죠.
이 트리가 꽉채워질때 이것을 완전 이진 트리라고 부른답니다.
힙에 특징은 다음과 같습니다.</p>
<ul>
<li>루트 노드의 값이 가장 클 때 : Max Heap</li>
<li>루느 노드이 값이 가장 작을 때 : Min Heap</li>
</ul>
<p>이때, 루트를 꺼낸다면, 트리가 다시 구현합니다.</p>
<ul>
<li>서브트리 중, 가장 큰 값을 루트로 부른답니다.</li>
</ul>
<p>이렇게 정렬하는 방법이 Heap Sort이에요.</p>
<ul>
<li>Max Heap으로 정렬하면 역순 정렬이 될 테고</li>
<li>Min Heap으로 정렬하면 차순위 정렬이 된답니다</li>
</ul>
<p>참고로, 힙은 중복 값이 들어갈 수 있습니다.</p>
<h4 id="이진-검색-트리--binary-search-tree-">이진 검색 트리 ( Binary Search Tree )</h4>
<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/3049aa1c-e592-42b6-8020-49c611636cfd/image.png" alt="">
이진 검색 트리는 <strong>검색</strong>을 위해 만들어진 자료구조입니다.
그래서 힙과는 다르게 자료의 중복이 허용되지 않죠.
이 유일한 값을 우리는 <strong>키</strong>라고 부릅니다.
BST의 특징은 자식노드를 중심으로 왼쪽이 작은 값, 오른쪽이 큰 값을 가집니다.
위 사진에서 22를 찾을 때 어떻게 찾을까요?</p>
<ul>
<li>23과 22를 비교 -&gt; 작은 값 = 왼쪽으로</li>
<li>10과 22를 비교 -&gt; 큰 값 = 오른쪽으로</li>
<li>15와 22를 비교 -&gt; 큰 값 = 오른쪽으로</li>
<li>22와 22를 비교 -&gt; 같은 값 = 연산 종료</li>
</ul>
<p>왜 BST가 연산속도가 빠를까요?</p>
<ul>
<li>완전 이진 트리로 생각해봅시다.</li>
<li>레벨이 n이고, 노드에 수는 2ⁿ- 1개이죠.</li>
<li>한번 연산하고 오면 비교해야 하는 범위가 절반이 되어 있죠.</li>
<li>그래서 찾아가는 데 걸리는 최대 시간이 log 2ⁿ시간입니다.</li>
</ul>
<p>하지만, 항상 안정적으로 트리가 구성되지는 않습니다. <img src="https://velog.velcdn.com/images/fulldev_hong/post/4ad74187-e2d9-47b1-8d03-459f8b35aa9c/image.png" alt="">
위 사진처럼 구성될 수도 있죠. 이렇게 된 트리를 편향된 트리라고 합니다.
이렇게 편향된 트리에 BST를 쓴다면 연산 속도는 n이 될 것입니다.
그래서 위 같은 트리는 AVL 트리나 레드-블랙 트리를 사용합니다.
Inorder Traversal 탐색을 하게 된다면 자료가 정렬되어 출력됩니다.</p>
<blockquote>
<p>Inorder Traversal : 부모를 기준으로 왼쪽 자식을 방문하고, 다시 루트를 방문하고 오른쪽 자식을 방문하는 식</p>
</blockquote>
<p>아까 22 찾던 사진을 예로 들어봅시다.</p>
<ul>
<li>23 -&gt; 10 -&gt; 7 -&gt; 10 -&gt; 15 -&gt; 22 -&gt; 23 -&gt; 48 -&gt; 56</li>
<li>= 17 -&gt; 10 -&gt; 15 -&gt; 22 -&gt; 23 -&gt; 48 -&gt; 56 정렬됐죠?</li>
</ul>
<h3 id="그래프--graph-">그래프 ( Graph )</h3>
<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/3ce5f0bb-39c3-41fc-b15d-01ac91967294/image.png" alt="">
그래프도 범위가 굉장히 방대합니다.</p>
<ul>
<li>네비게이션, 구글맵, 카카오맵 등이 그래프에 기반을 둬서 구현된 겁니다.</li>
</ul>
<p>여기서는 노드를 vertex라고 하고, 링크를 edge라고 합니다.
V(vertex)를 서로 연결하는 E(edge)에 방향성이 있느냐 없느냐로 그래프에 종류를 구분할 수 있습니다.
그래프를 구현하는 방법은 크게 두 가지가 있습니다.</p>
<ul>
<li>인접 행렬</li>
<li>인접 리스트</li>
</ul>
<p>그래프를 탐색하는 알고리즘은 BFS, DFS가 있습니다.
이 내용은 너무 방대해서 알고리즘 쪽으로 가서 더 자세히 알아보겠습니다!</p>
<h3 id="해싱--hashing-">해싱 ( Hashing )</h3>
<p>검색을 위한 자료구조입니다.
극장을 생각하시면 됩니다.</p>
<ul>
<li>극장이 있고, 좌석표가 0 ~ 99번까지 있습니다.</li>
<li>이 극장이 사실 꽉 차지 않습니다. 그래서 표를 많이 팔았답니다.</li>
<li>표를 300장을 팔았답니다. 만약 55번 고객이 오면 어디에 앉힐까요?</li>
<li>55 % 100을 해서 나온 나머지 55번에 가서 앉히면 됩니다.</li>
<li>123번이 왔을 때는? 123 % 100를 해서 나온 23번에 앉히면 됩니다.</li>
<li>표 번호 % 좌석 수에서 % 가 해시함수가 되는 겁니다.</li>
</ul>
<p>키는 유일하고, 이에 대한 value를 쌍으로 저장합니다.
사전이랑 비슷한 개념이라고 보시면 됩니다.</p>
<ul>
<li>김치의 뜻을 찾을 때 그 뜻들은 value가 되고 김치는 키가 되는겁니다.</li>
</ul>
<p>그래서 해싱을 다른 말로 딕셔너리라고 합니다.
파이썬에서는 딕셔너리를 제공합니다.
그런데요, 만약 위 예에서 223번이 오면 어떻게 될까요?</p>
<ul>
<li>223 % 100 = 23번 근데 이미 앉고 있죠?</li>
<li>이럴 때에도 여러 가지 해결 방법이 있습니다.</li>
<li>대표적인 건 &quot;옆에 앉으세요~&quot;하면서 키를 1번 increase 시키는 겁니다.</li>
</ul>
<p>이 해시 알고리즘을 쓰는 가장 큰 이유는 검색 속도가 산술적으로 가능하기 때문입니다.
지금까지에 검색 자료구조들은 배열 이외에는 산술적으로 시간이 들어가는 경우가 흔하지 않습니다.
해싱 같은 경우, 검색에 들어가는 속도가 굉장히 빠릅니다.
해싱을 효율적으로 관리할 수 있는 것으로 나온 것이 해시테이블입니다.</p>
<h4 id="해시테이블에-들어가기-전에-중요한-점">해시테이블에 들어가기 전에 중요한 점</h4>
<p>가장 먼저는 해시 함수를 어떻게 만드느냐가 중요합니다.
실제로 키값은 여러 가지 종류가 있어요. 이 키값에 대한 고민을 많이 해보시고 해시함수를 보완해놓으시는 게 중요합니다.
그렇다고 충돌이 발생하지 않는다는 게 아니에요. 상황에 따라서 쓰라는 거죠.
해시테이블을 하나에 줄만 사용한다고 가정해볼게요.
그러면 오히려 데이터 검색할 때나 꺼내올 때 시간이 더 걸릴 수 있어요.
위에처럼 인덱스를 1개 1개 늘려가면서 찾으면 그만큼 시간이 소모되니까요.
이걸 오버헤드라고 해요.
자바에서는 오버헤드가 일어나지 않게끔 해시테이블이 76% 차면 다시 재구성하도록 구현되어 있어요.</p>
<h3 id="해시테이블">해시테이블</h3>
<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/f890d3da-bbe1-4220-9454-a35d1dd71837/image.png" alt="">
2차원 배열처럼 생겼죠?
말 그대로, 23번에 value들이 이웃이 되는 거에요.
하지만 이러면 안 쓰는 공간이 많게 돼요.
그래서 버킷과 슬롯이 많이 있을수록 오버헤드가 일어날 수 있어요.
그래서 대안으로 나온 메모리가 있어요.</p>
<h3 id="체이닝">체이닝</h3>
<p><img src="https://velog.velcdn.com/images/fulldev_hong/post/07ec3abd-592d-4a26-8873-9079ea91ef91/image.png" alt=""></p>
<p>연결 리스트를 활용한 방식이에요.
key에 해당하는 인덱스에 value를 연결하는 방식이에요.
그러면 배열처럼 안 쓰는 공간이 발생한다든가 슬롯이 부족하다던가 하는 문제는 없을 거에요.
하지만, 그만큼 구현이 복잡해요.
아무래도 배열보다는 연결리스트가 구현하기 어렵죠.</p>
<h2 id="자료구조-종류를-우리가-직접-짜야-됨">자료구조 종류를 우리가 직접 짜야 됨?</h2>
<p>우리가 직접 자료구조를 짜야 할 때도 있지만, 자바에서는 거의 짤 필요가 없습니다.
왜냐면 <strong>JDK(Java Developer Kit)</strong>가 자료구조를 많이 구현해놨기 때문이죠.
<img src="https://velog.velcdn.com/images/fulldev_hong/post/1d5fbc8a-f7e0-4e89-8f47-02925964940f/image.png" alt=""></p>
<blockquote>
<p>참고로 C++에서도 STL이라는 라이브러리에서 많이 구현되어 있습니다.</p>
</blockquote>
<p>BST는 TreeSet, TreeMap으로 구현되어 있고, 해싱은 HashMap, Properties로 구현되어 있습니다.
<del>진짜 존나 감사합니다 ㅠㅠ</del></p>
<h2 id="마치며">마치며</h2>
<p>네. 종류에 대한 설명은 이 정도면 될 거 같네요.
이제 한번 앞서 소개한 것들을 구현해볼 거에요.
다음 포스팅 때 말하겠지만 모든 코드는 깃 허브에 올라와 있어요.
Velog 코드블록 기능으로 쓰기도 할 거지만, 될 수 있으면 <a href="https://github.com/BackdevHong/Java-DataStructure">깃헙</a>에서 코드를 보시고 포스팅 글을 보시면 될 거같아요.
수고하셨습니다.</p>
]]></description>
        </item>
    </channel>
</rss>