<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>dev_dbdb1114</title>
    <link>https://dev-dbdb1114.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sat, 13 Jun 2026 21:54:53 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>dbdb1114</managingEditor>
    <item>
      <title> Servlet이란?</title>
      <link>https://dev-dbdb1114.tistory.com/89</link>
      <description>&lt;h1&gt;1. Servlet ( 서블릿 )&lt;/h1&gt;
&lt;p&gt;클라이언트의 요청을 처리하고, 그 결과를 반환하는 Servlet 클래스의 구현 규칙을 지킨 자바 웹 프로그래밍 기술 간단히 말해서, 서블릿이란 자바를 사용하여 웹을 만들기 위해 필요한 기술입니다. 좀 더 들어가서 설명하면 클라이언트가 어떠한 요청을 하면 그에 대한 결과를 다시 전송해주어야 하는데, 이러한 역할을 하는 자바 프로그램입니다. 예를 들어, 어떠한 사용자가 요청을 보냈을 때 서버는 응답 페이지를 띄워주어야 하는데, 이러한 역할을 수행하는 것이 서블릿(Servlet)입니다. 그래서 서블릿은 자바로 구현된 CGI라고 합니다. &lt;/p&gt;
&lt;p&gt;*CGI : 서버와 애플리케이션 간에 데이터를 주고 받는 방식 또는 컨벤션 &lt;/p&gt;
&lt;h3&gt;Servlet특징&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;클라이언트의 요청에 대해 동적으로 작동하는 웹 어플리케이션 컴포넌트&lt;/li&gt;
&lt;li&gt;html을 사용하여 요청에 응답한다.&lt;/li&gt;
&lt;li&gt;Java Thread를 이용하여 동작한다.&lt;/li&gt;
&lt;li&gt;MVC 패턴에서 Controller로 이용된다.&lt;/li&gt;
&lt;li&gt;HTTP 프로토콜 서비스를 지원하는 javax.servlet.http.HttpServlet 클래스를 상속받는다.&lt;/li&gt;
&lt;li&gt;UDP보다 처리 속도가 느리다.&lt;/li&gt;
&lt;li&gt;HTML 변경 시 Servle을 재컴파일해야 하는 단점이 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이러한 서블릿은 WAS내의 서블릿 컨테이너에서 동작하며, 요청 ( Request )을 받으면 요청에 맞는 로직을 실행하고 클라이언트에게 HTTP 형식으로 응답(Response)하게 된다. &lt;/p&gt;
&lt;h1&gt;Servlet Container&lt;/h1&gt;
&lt;h2&gt;정의&lt;/h2&gt;
&lt;p&gt;서블릿 컨테이너는 서블릿을 담고 관리해주는 컨테이너이다. 서블릿 컨테이너는 구현되어 있는 서블릿 클래스의 규칙에 맞게 서블릿을 관리하며 클라이언트의 요청을 받으면 HttpServletRequest와 HttpServletReponse 객체를 생성하여 post,get 여부에 따라 동적인 페이지를 생성하여 응답한다. &lt;/p&gt;
&lt;h2&gt;역할&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;서블릿 생명주기 관리&lt;br&gt;서블릿 컨테이너에 서블릿의 탄생과 죽음을 관리한다. 서블릿 클래스를 로딩하여 인스턴스화하고, 초기화 메서드를 호출하고, 요청이 들어오면 적절한 서블릿 메서드를 찾아서 동작한다. 또한 서블릿의 생명이 다하면 가비지 컬렉션(Garbage Collection)을 통해 메모리를 제거하다.&lt;/li&gt;
&lt;li&gt;통신지원&lt;br&gt;서블릿 컨테이너는 웹 서버와 소켓을 만들어서 클라이언트의 요청을 받고 응답할 수 있는 통신을 지원해준다. 통신을 하기 위한 Listen, accept 등의 과정을 API로 제공하여 복잡한 과정을 생략해주기 때문에 개발자가 비즈니스 로직 개발에 집중할 수 있게 도와준다. &lt;/li&gt;
&lt;li&gt;멀티쓰레드 지원 및 관리&lt;br&gt;서블릿 컨테이너는 클라이언트의 요청을 받을 때마다 새로운 자바 스레드를 생성한다. 따라서 동시에 여러 요청이 들어와도 멀티쓰레딩 환경에서 동시다발적인 작업을 관리할 수 있다. &lt;/li&gt;
&lt;li&gt;선언적인 보안 관리&lt;br&gt;서블릿 컨테이너는 보안 관련 기능을 제공하기 때문에 개발자는 서블릿에 보안 관련 메서드를 구현하지 않아도 된다. &lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Servlet 생명주기&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Servlet Request, Servlet Response 객체를 생성합니다. &lt;/li&gt;
&lt;li&gt;설정 파일을 참고하여 매핑할 Servlet을 확인합니다.&lt;/li&gt;
&lt;li&gt;해당 서블릿 인스턴스 존재의 유무를 확인하여 없으면 Init()메소드를 호출하여 생성합니다. &lt;/li&gt;
&lt;li&gt;Servlet Container에 스레드를 생성하고 service를 실행합니다.&lt;/li&gt;
&lt;li&gt;응답을 처리하였으면 distroy()메소드를 실행하여 Servlet Request, Servlet Response 객체를 소멸합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Servlet 메소드&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;init() : 서블릿이 메모리에 로드될 때 한번만 호출 ( 코드 수정 시 다시 호출 )&lt;/li&gt;
&lt;li&gt;doGet() : Get 방식으로 data 전송 시 호출 &lt;/li&gt;
&lt;li&gt;doPost() : Post 방식으로 data 전송 시 호출 &lt;/li&gt;
&lt;li&gt;service() : 모든 요청은 service()를 통해 doxxx()메소드로 이동 &lt;/li&gt;
&lt;li&gt;destroy() : 서블릿이 메모리에서 해제되면 호출 &lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;참고 블로그&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://coding-factory.tistory.com/742&quot;&gt;https://coding-factory.tistory.com/742&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mangkyu.tistory.com/14&quot;&gt;https://mangkyu.tistory.com/14&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://velog.io/@falling_star3/Tomcat-%EC%84%9C%EB%B8%94%EB%A6%BFServlet%EC%9D%B4%EB%9E%80&quot;&gt;https://velog.io/@falling_star3/Tomcat-서블릿Servlet이란&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code-lab1.tistory.com/210&quot;&gt;https://code-lab1.tistory.com/210&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>프로그래밍/JAVA</category>
      <author>dbdb1114</author>
      <guid isPermaLink="true">https://dev-dbdb1114.tistory.com/89</guid>
      <comments>https://dev-dbdb1114.tistory.com/89#entry89comment</comments>
      <pubDate>Fri, 15 Sep 2023 23:39:24 +0900</pubDate>
    </item>
    <item>
      <title>DB 관련 면접 질문 대비 ( 기본편 )</title>
      <link>https://dev-dbdb1114.tistory.com/88</link>
      <description>&lt;h1&gt;제약조건&lt;/h1&gt;
&lt;h2&gt;PrimaryKey&lt;/h2&gt;
&lt;h3&gt;정의&lt;/h3&gt;
&lt;p&gt;데이터베이스 테이블에서 특정 레코드를 고유하게 식별하는 역할을 하는 칼럼&lt;/p&gt;
&lt;h3&gt;속성&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;not null, unique 제약조건을 내포하고 있음 &lt;/li&gt;
&lt;li&gt;DB 시스템은 Primary Key 필드를 보통 인덱스로 설정해서 Primary key 기반으로 레코드를 빠르게 검색할 수 있음. &lt;/li&gt;
&lt;li&gt;데이터의 일관성을 보장하는데 중요한 역할을 하며 대개 숫자나 문자열로 구성되며, 주로 테이블의 첫번째 열로 설정됨.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Foreign Key&lt;/h2&gt;
&lt;h3&gt;정의&lt;/h3&gt;
&lt;p&gt;RDBMS에서 중요한 개념으로 테이블 간의 관계를 정의하고 데이터 무결성과 무결성 유지를 위해 사용됨 &lt;/p&gt;
&lt;h3&gt;속성&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;부모 테이블의 PrimaryKey를 자식 테이블의 ForeignKey로 설정함으로써 부모 테이블과 자식 테이블의 관계가 정의&lt;/li&gt;
&lt;li&gt;연관 테이블이 부모테이블과 자식 테이블로 설계 되면서 부모의 레코드가 삭제 되었을 때 자식 테이블의 레코드에도 반영이 되면서 데이터 무결성을 유지시킬 수 있다. &lt;/li&gt;
&lt;li&gt;CASCADE 옵션을 설정함으로써 부모 레코드가 삭제되거나 업데이트 되었을 때 자식 테이블의 레코드도 삭제 되거나 업데이트 되게끔 설정할 수 있다. &lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Unique&lt;/h2&gt;
&lt;p&gt;특정 열에 대해 고유한 값을 가져야함. 중복된 값을 허용하지 않으며 Null값을 가질 수 없음 &lt;/p&gt;
&lt;h2&gt;Default&lt;/h2&gt;
&lt;p&gt;새로운 레코드가 추가될 때 열에 대한 기본값을 설정할 수 있음 &lt;/p&gt;
&lt;h2&gt;DDL ( Data DefinitionLanguage )&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;목적 : 데이터베이스 스키마(schema)를 정의하거나 수정하기 위해 사용된다. 스키마는 데이터베이스 객체의 구조를 정의함&lt;/li&gt;
&lt;li&gt;주요 명령어&lt;ol&gt;
&lt;li&gt;Create : 데이터베이스 객체 ( 테이블, 뷰, 인덱스 등 )을 생성함&lt;/li&gt;
&lt;li&gt;Alter : 이미 존재하는 데이터베이스 객체를 수정함 &lt;/li&gt;
&lt;li&gt;Drop : 데이터베이스 객체를 삭제함 &lt;/li&gt;
&lt;li&gt;Truncate : 테이블의 모든 레코드를 삭제하지만 테이블 구조는 유지함 &lt;/li&gt;
&lt;li&gt;Rename : 데이터베이스 객체의 이름을 변경함 &lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;DML ( Data Manipulation Language )&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;목적 : 데이터를 조회, 삽입, 수정, 삭제하는 등 데이터 조작을 위해 사용&lt;/li&gt;
&lt;li&gt;주요 명령어&lt;ol&gt;
&lt;li&gt;Select : 데이터를 조회할 때 씀 ( select * from user; )&lt;/li&gt;
&lt;li&gt;Insert : 데이터를 삽입할 때 씀 ( insert into user ( id, pw ) valeus ( “DBDB”, “1234” );&lt;/li&gt;
&lt;li&gt;update : 데이터를 수정할 때 씀 ( update user set id = “dbdb11” where id = “DBDB”; ) &lt;/li&gt;
&lt;li&gt;Delete : 데이터를 삭제함 ( delete from user where id = “dbdb11”; )&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;DCL ( Data Control Language )&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;목적 : 데이터베이스에 대한 접근 권한을 관리하고, 데이터 보안 및 무결성을 유지하기 위해 사용함&lt;/li&gt;
&lt;li&gt;주요 명령어&lt;ol&gt;
&lt;li&gt;grant : 사용자에게 특정 권한을 부여함. 서버에 계정마다 조회 권한만 줄지 수정권한 까지 줄지 등을 정할 수 있음&lt;/li&gt;
&lt;li&gt;revoke : 사용자에게 부여된 권한을 취소함.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;&lt;strong&gt;&lt;strong&gt;트랜잭션 (Transaction)&lt;/strong&gt;&lt;/strong&gt;&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;정의 : 하나 이상의 SQL 명령문을 논리적으로 묶어서 실행하는 데이터베이스 작업의 단위입니다. 트랜잭션은 데이터의 일관성과 무결성을 보장합니다. &lt;/li&gt;
&lt;li&gt;특성 : ACID( 원자성, 일관성, 고립성, 지속성) 특성을 가지며, 각 특성의 의미와 중요성을 설명할 수 있습니다. &lt;/li&gt;
&lt;li&gt;롤백 ( Rollback ) : 트랜잭션 중에 오류가 발생하거나 롤백 명령이 내려진 경우, 트랜잭션의 모든 변경사항을 이전 상태로 복구하는 역할을 합니다.&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>프로그래밍/MySQL</category>
      <author>dbdb1114</author>
      <guid isPermaLink="true">https://dev-dbdb1114.tistory.com/88</guid>
      <comments>https://dev-dbdb1114.tistory.com/88#entry88comment</comments>
      <pubDate>Thu, 14 Sep 2023 23:35:19 +0900</pubDate>
    </item>
    <item>
      <title>MSA란 무엇인가?</title>
      <link>https://dev-dbdb1114.tistory.com/87</link>
      <description>&lt;h1&gt;MSA ( MicroServiceArchitecture )&lt;/h1&gt;
&lt;p&gt;MSA란 작고, 독립적으로 배포 가능한 각각의 기능을 수행하는 서비스로 구성됨 프레임워크라고 할 수 있다. 마이크로 서비스는 완전히 독립적으로 배포가 가능하고, 다른 기술 스택 (개발 언어, 데이터에비스 등)이 사용 가능한 단일 사업 영역에 초점을 둔다.&lt;/p&gt;
&lt;h1&gt;MSA는 왜 탄생했는가?&lt;/h1&gt;
&lt;h2&gt;Monolithic Architecture&lt;/h2&gt;
&lt;p&gt;MSA가 등장하기 이전에 가장 많이 사용되던 아키텍처이다. Monolithic Architecture의 한계점으로 MSA가 생겨났다고 볼 수 있기 때문에 Monolithic Architecture에 대해 알아두면 좋을 것 같다. 이 아키텍처는 소프트웨어의 모든 구성요소가 한 프로젝트에 통합되어 있는 형태로, 기능 개발은 나눠서 하지만 결과물인 애플리케이션을 빌드하고 배포할 때는 하나의 결과물로 패키징 하여 배포되는 형태를 말한다. &lt;/p&gt;
&lt;h2&gt;Monolithic Architectur의 한계&lt;/h2&gt;
&lt;p&gt;Monolithic Architecture를 기반으로 쇼핑몰을 구축한다면 우리는 하나의 프로젝트 내에서 고객관리, 상품관리, 이벤트 관리 등등을 한 번에 처리했다. 그렇다면 이렇게 했을 때 어떤 점이 불편했을까? &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;고객관리, 상품관리, 이벤트 관리 중에서 이벤트에 대한 비즈니스 로직만 변경이 생겼다. 하지만 우리는 전체 프로젝트를 다시 빌드해야한다. 즉 우리가 다시 배포 하려는 건 이벤트 관리만 해당하는데 전체를 다시 빌드하고, 다시 배포해야한다는 것이다. &lt;/li&gt;
&lt;li&gt;프로젝트 자체의 사이즈가 크기 때문에 작은 변화에 적용할 테스트에도 높은 수준의 테스트 비용이 발생하기도 한다. &lt;/li&gt;
&lt;li&gt;한 Framework와 언어에 종속적이다. 예를 들어 프레임 워크 마다 장단점이 있다. 어떤 기능에서는 스프링이 좋고, 어떤 기능에서는 nodejs가 더 좋을 수 있다. 하지만 처음에 spring을 사용했다면, 모든 기능을 spring과 Java로 해야할 것이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;그렇기 때문에 프로젝트 필드를 한 번에 하는 것이 아닌 기능단위의 API를 설계하여 유저가 사용할 때는 하나의 어플리케이션으로 느끼지만 사실상 업무부서별로 다른 프레임워크를 사용하기도 하고, 다른 DB를 사용하기도 하는 것이다. &lt;/p&gt;
&lt;h2&gt;MSA&lt;/h2&gt;
&lt;p&gt;MonolighticArchitecture의 한계점을 보완하기 위해 나온 것이니 만큼 분산적인 느낌이 강하다. API별로 분산되어 있는 형태를 가져서 기능별로 독립적인 CI/CD가 가능해진다. 위 예를 그대로 가져오면 고객관리, 상품관리, 이벤트 관리에 대한 부서별로 서로 다른 API와 프레임워크 및 언어를 사용할 수 있게 된다는 것이다. &lt;/p&gt;
&lt;h2&gt;MSA의 장점&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;각각의 서비스가 모듈화 되어있으며, 모듈끼리 RPC 또는 message-driven API 등을 이용하는데 이러한 방식은 각각 개별의 서비스 개발을 빠르게 하고, 유비보수도 쉽게 할 수 있도록 한다. &lt;/li&gt;
&lt;li&gt;부서나 팀 단위로 적절한 수준의 기술 스택을 다르게 사용할 수 있다. 어떤 부서는 spring을 사용하더라도 다른 부서는 node.js로 다른 서비스를 개발할 수 있다. &lt;/li&gt;
&lt;li&gt;서비스별로 독립적 배포가 가능하다. 지속적인 배포 CD도 Monolithic에 비해서 가볍게 할 수 있다. &lt;/li&gt;
&lt;li&gt;개별적인 scale-out이 가능하여 메모리, CPU 부분에서 상당부분 이득이 있다. &lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;MSA의 단점&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;서비스가 모두 분산되어 있기 때문에 내부 시스템의 통신 방식을 정해야한다. 그리고 통신의 장애와 서버의 부하 등 transaction 유지에 대한 정책이 필요하다. &lt;/li&gt;
&lt;li&gt;monolithic에서는 단일 트랜잭션을 유지하면 됐지만 MSA에서는 비즈니스에 대한 DB를 가지고 있는 서비스도 각기 다르다. &lt;/li&gt;
&lt;li&gt;통합테스트가 어렵다. 모두 분산되어 있더라도 하나의 서비스이기 때문에 통합 테스트는 필수적이다.&lt;/li&gt;
&lt;li&gt;테스트 당시 다른 서비스들과의 연계가 정상적으로 이루저지고 있는지도 확인해야한다. &lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;마치며&lt;/h1&gt;
&lt;p&gt;프로그래밍을 하다보면 모듈화는 습관적으로 고민하며 하게 되는것 같다. 이런 모듈화의 단위가 코드 작성부터 이제는 API 설계를 분산하는 모습까지 온 것 같다. 아마 MSA가 테스트나 통신 부분에서 어려움이 있겠지만 지금보다 더 편해진 무언가가 나오지 않을까 싶고 MSA 방식이 앞으로도 많이 사용될 것 같다. 하지만 어디까지나 내 개인적인 생각이고 코드단위의 모듈화와 전체 서비스 설계에 있어서의 분산은 조금 다른 영역이기도 하기 때문에 쉽지만은 않을 것 같다는 생각이 든다.&lt;/p&gt;</description>
      <category>프로그래밍/server</category>
      <author>dbdb1114</author>
      <guid isPermaLink="true">https://dev-dbdb1114.tistory.com/87</guid>
      <comments>https://dev-dbdb1114.tistory.com/87#entry87comment</comments>
      <pubDate>Wed, 13 Sep 2023 23:53:20 +0900</pubDate>
    </item>
    <item>
      <title>OAuth2.0, 인증과 인가</title>
      <link>https://dev-dbdb1114.tistory.com/86</link>
      <description>&lt;h1&gt;인증과 인가 ( Authorization, Authentication )&lt;/h1&gt;
&lt;p&gt;인증은 사용자의 신원을 검증하는 프로세스를 뜻한다. 로그인 하는 행위를 인증이라고 할 수 있다. 인증된 사용자가 어떠한 자원에 접근할 수 있는지를 확인하는 절차가 인가이다. 즉 모든 웹 사이트는 인증과 인가를 필요로 한다. 조금 더 확실히 설명하자면, 인증은 사용자의 신원을 확인하는 프로세스이고, 인가는 특정 자원이나 기능에 대한 액세스 권한을 부여하는 프로세스이다. 즉 인증 후 인가이다.&lt;/p&gt;
&lt;h1&gt;OAuth2.0이란?&lt;/h1&gt;
&lt;p&gt;OAuth는 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의(FaceBook, Twitter, Google) 접근 권한을 부여할 수 있는 공통적인 수단으로서 사용되는, 접근 위임을 위한 개방형 표준이다. ( 위키백과 )&lt;/p&gt;
&lt;p&gt;즉 우리가 로그인 하거나 회원가입을 할 때 우리가 직접 하는 것 보다는 우리가 이미 정보를 제공해준 서비스에서 로그인이나 회원가입을 대신 처리해주는 것이다. 예를 들어 우리가 새로운 웹 서비스에 회원가입을 하거나 로그인을 하려면 우리의 정보를 결국 입력 해줘야한다. 이 과정을 생략하기 위해서 우리가 이미 정보를 제공한 업체에서 우리의 정보를 가입하려는 서비스에 제공을 함으로써 로그인이나 회원가입을 진행하는 것이다. &lt;/p&gt;
&lt;h1&gt;역할 구분&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;Resource Server : Client가 제어하고자 하는 자원을 보유하고 있는 서버&lt;ol&gt;
&lt;li&gt;sns로그인을 사용할 때 해당하는 sns 서비스 서버&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Resource Owner : 자원의 소유자 입니다. &lt;ol&gt;
&lt;li&gt;Client가 제공하는 서비스를 통해 로그인하는 실제 유저의 정보를 가진 서비스&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Client : Resource Server에 접속해서 정보를 가져오고자 하는 클라이언트 즉, sns 자원을 통해 지금 현재 로그인 하려는 애플리케이션&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;필요한 용어들&lt;/h1&gt;
&lt;h3&gt;Resource Owner&lt;/h3&gt;
&lt;p&gt;사용자를 말한다. ( Resource 는 사용자 정보를 이야기 하는 것이다. )&lt;/p&gt;
&lt;h3&gt;Authorization &amp;amp; Resource Server&lt;/h3&gt;
&lt;p&gt;Authorization은 인가를 말한다. 인증과 인가라는 개념이 있는데 인증은 사용자의 신원을 검증하는 프로세스를 뜻한다. 인가는 인증된 사람에게 새로운 정보에 대한 접근을 허용하는 개념을 말한다. &lt;/p&gt;
&lt;h3&gt;Client&lt;/h3&gt;
&lt;p&gt;지금 로그인 하려는 새로운 애플리케이션을 말한다.&lt;br&gt;( Google이나 Facebook 등이 아닌 Google이나 Facebook을 통해 로그인 하려는 새 애플리케이션이다. )&lt;/p&gt;
&lt;h2&gt;인증 순서 ( Authorization 순서 )&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;ResourceOwner가 Client에게 로그인 요청 ( Google 로그인 요청, Facebook 로그인 요청 등   ) &lt;/li&gt;
&lt;li&gt;Client( 새로운 어플리케이션 )가 AuthorizationServer(Ex:Google서버)로 로그인 요청을 보내면 로그인 페이지를 제공 받습니다.&lt;/li&gt;
&lt;li&gt;ResourceOwner가 제공받은 로그인 페이지에 id, pw를 입력해서 AuthorizationServer로 부터 AuthorizationCode를 발급 받습니다. 직후 AuthorizationCode를 Client( 새로운 어플리케이션 )에게 전송합니다.&lt;/li&gt;
&lt;li&gt;Client는 전달받은 코드로 AuthorizationServer에 AccessToken을 요청하고 발급받은 토큰을 이용해서 AuthorizationServer로 자원을 요청합니다. &lt;/li&gt;
&lt;li&gt;Client는 응답값으로 받은 자원들을 이용해서 회원가입이나 로그인을 진행합니다.&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>프로그래밍/server</category>
      <author>dbdb1114</author>
      <guid isPermaLink="true">https://dev-dbdb1114.tistory.com/86</guid>
      <comments>https://dev-dbdb1114.tistory.com/86#entry86comment</comments>
      <pubDate>Tue, 12 Sep 2023 22:29:04 +0900</pubDate>
    </item>
    <item>
      <title>파이썬이 뭔가요...? (3)</title>
      <link>https://dev-dbdb1114.tistory.com/85</link>
      <description>&lt;h1&gt;문자열 함수&lt;/h1&gt;
&lt;p&gt;문자열 여러 행으로 작성하기 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;sentence3 = &amp;quot;&amp;quot;&amp;quot;
나는 소년이고,
파이썬은 쉬워요.
&amp;quot;&amp;quot;&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;위치 찾기 / 갯수 찾기 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; # find는 찾는 값이 없을 때는 -1을 반환함. 
 # index는 찾는 값이 없을 때는 에러를 반환함
 print(python.find(&amp;quot;Java&amp;quot;))
 # print(python.index(&amp;quot;Java&amp;quot;))

 # 해당 변수에서 특정 문자열이 몇 번 반복되는지 알려줌
 print(python.count(&amp;#39;n&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;슬라이싱&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; jumin = &amp;quot;971114-1234567&amp;quot;
 print(jumin.split(&amp;#39;-&amp;#39;))
 print(&amp;quot;성별 : &amp;quot; + jumin[8])

 # 시작 인덱스 부터 끝 인덱스 + 1 까지 
 print(&amp;quot;연 : &amp;quot; +jumin[0:2])
 print(&amp;quot;월 : &amp;quot; + jumin[2:4])
 print(&amp;quot;일 : &amp;quot; + jumin[4:6])

 # 시작인덱스가 0이면 입력하지 않고 콜론만 입력해줘도 됨. 
 print(&amp;quot;생년월일 : &amp;quot; + jumin[0:6])
 print(&amp;quot;생년월일 : &amp;quot; + jumin[:6])

 # 마지막인덱스 까지 가져올 땐 마지막 인덱스도 생략할 수 있음
 # 음수 인덱싱도 가능 
 print(&amp;quot;뒤 7자리 : &amp;quot; + jumin[7:14])
 print(&amp;quot;뒤 7자리 : &amp;quot; + jumin[7:])
 print(&amp;quot;뒤 7자리 : &amp;quot; + jumin[-7:])&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;대문자, 소문자 관련 함수&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; # 문자열 처리 함수
 python = &amp;quot;Python is Amazing&amp;quot; 

 # 소문자 변환 함수
 print(python.lower())
 # 대문자 변환 함수
 print(python.upper())
 # 대문자인지 소문자인지 확인 함수 
 print(python[0].isupper())
 print(python[0].islower())
 # 문자열 길이 
 print(len(python))
 # 문자열 교체 
 print(python.replace(&amp;quot;Python&amp;quot;,&amp;quot;Java&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;문자열에 변수 삽입하기 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; # 문자열 포맷
 # 1. %d를 이용
 print(&amp;quot;나는 %d살 입니다.&amp;quot;%20)
 # 2. %s를 이용 (정수,문자열 모두 가능)
 print(&amp;quot;나는 %s를 좋아해요&amp;quot;%&amp;quot;파이썬&amp;quot;)
 # 3. %c를 이용
 print(&amp;quot;Apple은 %c로 시작해요.&amp;quot; % &amp;quot;A&amp;quot;)
 # 4. %s 
 print(&amp;quot;나는 %s색과 %s색을 좋아해요.&amp;quot; %(&amp;quot;파란&amp;quot;,&amp;quot;빨강&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;.format 함수 ( 문자열에 변수 삽입하기. )&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; # {}를 사용
 print(&amp;quot;나는 {}살입니다.&amp;quot;.format(40))

 # 인덱싱 사용 가능
 print(&amp;quot;나는 {0}색과 {1}색을 좋아해요 &amp;quot;.format(&amp;quot;파란&amp;quot;,&amp;quot;빨간&amp;quot;))
 print(&amp;quot;나는 {1}색과 {0}색을 좋아해요 &amp;quot;.format(&amp;quot;파란&amp;quot;,&amp;quot;빨간&amp;quot;))

 # 변수 이용 가능 
 print(&amp;quot;나는 {age}살이며, {color}색을 좋아해요.&amp;quot;.format(age = 20, color = &amp;quot;빨간&amp;quot;))
 print(&amp;quot;나는 {age}살이며, {color}색을 좋아해요.&amp;quot;.format( color = &amp;quot;빨간&amp;quot;, age = 20,))

 # (v3.6 이상~)
 age = 20
 color = &amp;quot;빨간&amp;quot;
 print(f&amp;quot;나는 {age}살이며, {color}색을 좋아해요.&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;전역변수 사용&lt;/h1&gt;
&lt;p&gt;전역변수 gun을 사용하려면 global 키워드를 붙여줘야함.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;gun = 10

def checkpoint(soldiers):
    global gun # 전역 공간에 있는 gun 사용
    gun = gun - soldiers
    print(&amp;quot;[함수 내] 남은 총 : {0}&amp;quot;.format(gun))&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;리스트&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;순서를 가지는 객체의 집합&lt;/li&gt;
&lt;li&gt;다른 자료형에 list()함수를 써서 리스트 형태로 변경 가능하다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;subway = [&amp;quot;유재석&amp;quot;, &amp;quot;조세호&amp;quot;, &amp;quot;박명수&amp;quot;]
num_list = [5,4,12,1]&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;리스트 관련 메소드&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;해당 요소의 인덱스 찾기 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; subway.index(&amp;quot;조세호&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;해당 요소의 갯수 찾기 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; subway.count(&amp;quot;유재석&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;마지막 위치에 객체를 추가하기 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; subway.append(&amp;quot;하하&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;원하는 위치에 추가하기 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; subway.insert(1,&amp;quot;정형돈&amp;quot;) &lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;마지막 요소 꺼내기 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; subway.pop()&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; num_list = [5,4,12,1]&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;요소를 역순으로 정렬하기 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; num_list.reverse()&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;요소 정방향 정렬하기 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; num_list.sort()&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;list 지우기 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; num_list.clear()&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;두 배열 합치기&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;num_list.extend(mix_list)&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;튜플&lt;/h1&gt;
&lt;p&gt;리스트는 변경 가능 하지만 튜플은 변경할 수 없다. &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;선언 방식 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; menu = (&amp;quot;돈까스&amp;quot;, &amp;quot;치즈까스&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;구조분해할당?&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; (name, age, hobby ) = (&amp;quot;김종국&amp;quot; ,20 , &amp;quot;코딩&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;Dictionary&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;key값과 value값으로 구성된다. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;key값에 또 다른 값을 넣으려고 한다면 기존값은 지워진다. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;선언 방식 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; cabinet = {3:&amp;quot;유재석&amp;quot;, 100:&amp;quot;김태호&amp;quot;}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;value 접근 방식 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; print(cabinet[3])
 print(cabinet.get(3))&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;접근시 value의 값이 없을 때 default를 정해줄 수 있다. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; print(cabinet.get(5,&amp;quot;Default&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;새로운 값 추가 및 재할당&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; cabinet[&amp;quot;A-3&amp;quot;] = &amp;quot;김종국&amp;quot; 
 cabinet[&amp;quot;C-20&amp;quot;] = &amp;quot;조세호&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;특정 값 삭제&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; del cabinet[&amp;quot;A-3&amp;quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;모든 key 출력 , 모든 value 반환, 모든 key-value 반환&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; cabinet.keys()
 cabinet.values()
 cabinet.items()&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;모든 값 지우기 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt; cabinet.clear()&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;자료구조 변환&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;menu = list(menu)
menu = tuple(menu)
menu = set(menu)&lt;/code&gt;&lt;/pre&gt;</description>
      <category>프로그래밍/Python</category>
      <author>dbdb1114</author>
      <guid isPermaLink="true">https://dev-dbdb1114.tistory.com/85</guid>
      <comments>https://dev-dbdb1114.tistory.com/85#entry85comment</comments>
      <pubDate>Sun, 10 Sep 2023 22:52:25 +0900</pubDate>
    </item>
    <item>
      <title>파이썬이 뭔가요...? (2)</title>
      <link>https://dev-dbdb1114.tistory.com/84</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;강의를 들으며 정리한 내용입니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;숫자 자료형 출력&lt;/h2&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;print(5)
print(-10)
print(3.14)
print(1000)
print(5+3)
print(2*8)
print(3*(3+1))
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문자 자료형 출력&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특이한 점 : 문자열 반복 횟수를 곱하기로 할 수 있다는 거 되게 직관적이다.&lt;/p&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;print('풍선')
print(&quot;나비&quot;)
print(&quot;ㅋㅋㅋㅋㅋㅋ&quot;)
print(&quot;ㅋ&quot;*9)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Boolean&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특이한 점 : not 연산자를 쓰면 반대로 참 거짓을 반대로 바꿔준다. js에서 !만 쓰던걸 생각하면 되게 재밌다.&lt;/p&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;print(5&amp;gt;10)
print(5&amp;lt;10)
print(True)
print(False)
print(not True)
print(not False)
print(not (5&amp;gt;10))
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문자열과 변수 한 번에 출력하기&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JAVA나 JS 처럼 &amp;ldquo;+&amp;rdquo; 연산자를 사용해서 문자열과 변수를 한 번에 묶을 수 있다.&lt;/li&gt;
&lt;li&gt;숫자나 Boolean 값은 str()함수를 사용해야 문자열로 바뀐다. ( 타입 캐스팅이 자동으로 안 되는것이 의외였다. )&lt;/li&gt;
&lt;li&gt;쉼표를 쓰면 str()함수를 쓰지 않아도 되지만, 쉼표 바로 뒤에 공백이 발생한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;#문자열 안에 변수 넣기
anymal = &quot;고양이&quot;
name = &quot;해피&quot;
age = 4
hobby = &quot;낮잠&quot;
is_adult = age &amp;gt; 3

print(&quot;우리집 &quot;+anymal+&quot;의 이름은 &quot;+name+&quot;에요&quot;)

# 문자열이 아닌 변수를 출력시 문자열로 바꿔줘야함 str() 함수.
print(name+&quot;는 &quot;+str(age)+&quot;살이며, &quot;+hobby+&quot;을 아주 좋아해요.&quot;)

# + 없이 쉼표로 연결할 수 있으며, 
# 쉼표로 연결하면 쉼표 다음에 공백이 생김. 
# 쉼표로 연결할 땐 정수형이나 Boolean에 str()함수를 쓰지 않아도 됨.
print(name+&quot;는 &quot;,age,&quot;살이며, &quot;,hobby,&quot;을 아주 좋아해요.&quot;)
print(name+&quot;는 어른일까요? &quot; + str(is_adult))
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;수식 연산&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JAVA나 JS랑 비슷한데 나누기를 했을 때 소수점까지 바로 나오는건 신기했다.&lt;/li&gt;
&lt;li&gt;몫을 구하는 연산자가 따로 있다. &amp;ldquo; // &amp;ldquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;print(5+3)
print(5-3)
print(5/3)
print(5*3)

print(5**3) # 이건 5^3 = 125
print(10%3) # 나머지 구하기 
print(10//3) # 몫만 구하기
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;논리 연산자&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;or 연산자가 or 이고, |를 하나만 쓴다.&lt;/li&gt;
&lt;li&gt;and 연산자가 and 이고, &amp;amp;를 하나만 쓴다.&lt;/li&gt;
&lt;li&gt;not은 논리 연산의 결과값 앞에 붙이는 것 같다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;# 논리 연산자 
print(10&amp;gt;3) # True
print(4&amp;gt;=7) # False
print(10 &amp;lt; 3) # False
print(5 &amp;lt;= 5) # True

print(3==3) # True
print(4 == 1) # False
print(4 != 1) # True
print(not(1 != 3)) # False

print((3&amp;gt;0) and (3&amp;lt;5)) # True
print((3&amp;gt;0) &amp;amp; (3&amp;lt;5)) # True

# or 논리 연산자
print((3 &amp;gt; 0) or (3 &amp;gt; 5)) # True
print((3 &amp;gt; 0) | (3 &amp;gt; 5)) # True

print(5 &amp;gt; 4 &amp;gt; 3) # False
print(5 &amp;gt; 4 &amp;gt; 3) # False
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사칙 연산&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다른 언어와 거의 같다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;fortran&quot;&gt;&lt;code&gt;# 사칙연산 
print( 2 + 3 * 4) # 14
print((2+3) * 4) # 20
number = 2 + 3 * 4
number = number + 2
print(number)
number += 2
print(number)
number *= 2
print(number)
number /= 2
print(number)
number -= 2
print(number)
number %= 5
print(number)
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>프로그래밍/Python</category>
      <author>dbdb1114</author>
      <guid isPermaLink="true">https://dev-dbdb1114.tistory.com/84</guid>
      <comments>https://dev-dbdb1114.tistory.com/84#entry84comment</comments>
      <pubDate>Sat, 9 Sep 2023 23:47:40 +0900</pubDate>
    </item>
    <item>
      <title>파이썬이 뭔가요...? (1)</title>
      <link>https://dev-dbdb1114.tistory.com/83</link>
      <description>&lt;h1&gt;개요&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬은 쉬운 언어로 많이 알려져있다. 동적 타이핑로 다양한 플랫폼에서 쓸 수 있고, 라이브러리가 풍부하여 대학을 비롯한 여러 교육 기관, 연구 기관 및 산업계에서 이용이 증가하고 있다. 또 파이썬은 순수한 프로그램 언어로서의 기능 이외에도 다른 언어로 쓰인 모듈들을 연결하는 접착제 언어로써 자주 이용된다. 실제 파이썬은 많은 상용 응용 프로그램에서 스크립트 언어로 채용되고 있다.&lt;/p&gt;
&lt;h1&gt;특징&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파이썬은 인터프리터 언어 방식으로 실행되는 스크립트 언어임.&lt;/li&gt;
&lt;li&gt;문법이 쉽고 간결하지만 들여쓰기를 신경써서 해야함.&lt;/li&gt;
&lt;li&gt;플랫폼 독립적인 언어로 운영체제에 상관없이 사용할 수 있는 언어임&lt;/li&gt;
&lt;li&gt;객체 지향 언어임.&lt;/li&gt;
&lt;li&gt;동적 타이핑 언어임.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;파이썬의 실행 과정&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬 가상머신(CPython)에 의해 바이트 코드로 변환되고, 다시 문장 단위로 기계어로 변화 후 실행됨. JAVA의 JVM 같은 개념인듯. 아래는 순서를 조금 더 세세하게 작성해본 것.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;소스 코드 작성 Python 프로그램을 작성하기 위해 텍스트 편집기나 개발환경( 예: Visual Studio Code, PyCharm, Jupyter Notebook 등 )을 사용하여 소스 코드를 작성합니다. Python은 고수준의 언어로, 문법이 간단하고 가독성이 높아서 쉽게 코드를 작성할 수 있습니다.&lt;/li&gt;
&lt;li&gt;소스 코드 저장 작성한 Python 소스코드를 .py확장자를 가진 파일로 저장합니다. 이 파일은 파이썬 인터프리터에 의해 실행됩니다.&lt;/li&gt;
&lt;li&gt;파이썬 인터프리터 호출 명령 줄 인터페이스나 통합 개발 환경(IDE)에서 파이썬 인터프리터를 호출합니다. 그런 다음 실행하려는 Pyhon 스크립트 파일을 지정하여 인터프리터를 실행시킵니다.&lt;/li&gt;
&lt;li&gt;소스 코드 파싱 인터프리터는 지정한 Python 스크립트 파일을 읽어들이고, 코드를 파싱하여 실행 가능한 중간 표현식으로 변환합니다. 파싱 과정에서 문법 오류가 발견되면 오류 메세지가 표시됩니다.&lt;/li&gt;
&lt;li&gt;바이트 코드 생성 파싱이 완료되면 인터프리터는 실행 가능한 바이트 코드로 컴파일 합니다. 이 바이트 코드는 파이썬 가상 머신 ( Python Virtual Machine, CPython 에서는 이를 사용)에서 실행됩니다.&lt;/li&gt;
&lt;li&gt;실행 파이썬 가상 머신은 바이트 코드를 실행하면서 프로그램을 실행합니다. 이 과정에서 프로그램이 수행해야 할 작업을 수행하고, 결과를 출력하거나 필요한 경우 파일에 쓰거나 다른 프로세스와 상호 작용합니다.&lt;/li&gt;
&lt;li&gt;종료 프로그램이 실행을 마치면 인터프리터는 종료되고, 프로그램의 실행 결과나 오류 메시지 등이 화면에 표시됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;파이썬의 백엔드 개발 프레임워크&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Django&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;특징&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ORM을 통한 데이터베이스 모델링을 지원하며, 다양한 데이터베이스 시스템과 연동이 가능함&lt;/li&gt;
&lt;li&gt;자동으로 생성되는 관리자 패널을 통해 데이터 관리가 용이함&lt;/li&gt;
&lt;li&gt;강력한 보안 기능과 사용자 인증을 기본으로 제공함&lt;/li&gt;
&lt;li&gt;다국어 및 시간대 지원, 캐싱, URL 라우팅 등의 기능을 내장함&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;장점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;강력하고 포괄적인 기능 세트를 제공하여 큰 프로젝트에 적합함.&lt;/li&gt;
&lt;li&gt;커뮤니티와 생태계가 크고 활발하며, 다양한 서드파티 앱 및 플러그인을 사용할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;러닝 커브가 높고 초기 설정 및 학습이 다소 복잡할 수 있음&lt;/li&gt;
&lt;li&gt;프로젝트의 크기가 작거나 간단한 애플리케이션에는 과도한 기능을 가질 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Flask&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;특징&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;마이크로 웹 프레임워크로 경량형이며, 확장 가능함. 필요한 기능을 선택적으로 추가할 수 있음&lt;/li&gt;
&lt;li&gt;Jinja2 템플릿 엔진과 연동하여 템플릿 렌더링을 지원함.&lt;/li&gt;
&lt;li&gt;웹 애플리케이션 구조를 직접 정의하고 개발자에게 큰 자유를 제공함.&lt;/li&gt;
&lt;li&gt;확장기능(플러그인)을 통해 다양한 기능을 추가할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;장점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가볍고 간단한 애플리케이션을 빠르게 개발하기에 적합함.&lt;/li&gt;
&lt;li&gt;초기 설정이 간단하며 학습 곡선이 낮음&lt;/li&gt;
&lt;li&gt;다른 라이브러리와 잘 통합됨&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본적인 기능만 내장되어 있어 큰 프로젝트나 기능 풍부한 애플리케이션에는 추가 작업이 필요함&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;FastAPI&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;특징&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;빠른 속도와 현대적인 API 개발을 지향하는 웹 프레임워크로, ASGI를 사용하여 비동기 처리를 지원함.&lt;/li&gt;
&lt;li&gt;타임 힌트와 자동 문서 생성을 통해 API 개발 및 문서화를 간편하게 만듬&lt;/li&gt;
&lt;li&gt;데이터 유효성 검사, 응답 모델링 등의 기능을 지원하여 개발 생산성을 높임&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;장점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;높은 성능과 효율성을 제공하며, 비동기 처리를 통해 동시 요청을 처리할 수 있음.&lt;/li&gt;
&lt;li&gt;Pydantic을 사용한 데이터 유효성 검사와 자동 문서화로 개발 및 유지 관리를 용이하게 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Django나 Flask와 달리 레거시 코드를 지원하는 기능이 부족할 수 있음.&lt;/li&gt;
&lt;li&gt;상대적으로 새로운 프레임워크이므로 생태계와 커뮤니티가 다른 두 프레임워크에 비해 작을 수 있음.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>프로그래밍/Python</category>
      <author>dbdb1114</author>
      <guid isPermaLink="true">https://dev-dbdb1114.tistory.com/83</guid>
      <comments>https://dev-dbdb1114.tistory.com/83#entry83comment</comments>
      <pubDate>Fri, 8 Sep 2023 23:12:01 +0900</pubDate>
    </item>
    <item>
      <title>자바 Collection</title>
      <link>https://dev-dbdb1114.tistory.com/82</link>
      <description>&lt;h1&gt;관계도&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관계도를 그려보면 아래와 같다. List와 Set은 Collection을 상속하고있고, 그 아래에 있는 ArrayList, Vector, LinkedList, HashSet, TreeSet 은 모두 각각 List와 Set을 구현하는 구현체이다. 특성에 맞게 각자 여러가지 다른점을 가지고 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-09-07 오후 11.35.30.png&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;357&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7rI3T/btstnvYNvBT/SzDuPwjx2LyqqLyXWAQKU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7rI3T/btstnvYNvBT/SzDuPwjx2LyqqLyXWAQKU0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7rI3T/btstnvYNvBT/SzDuPwjx2LyqqLyXWAQKU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7rI3T%2FbtstnvYNvBT%2FSzDuPwjx2LyqqLyXWAQKU0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;626&quot; height=&quot;357&quot; data-filename=&quot;스크린샷 2023-09-07 오후 11.35.30.png&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;357&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;List 컬렉션&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;List 컬렉션은 객체를 일렬로 늘어놓은 구조를 가지고 있다. 인덱스로 관리하기 때문에 객체 저장시 자동 인덱스가 부여되고, 인덱스를 통해서 검색 및 삭제가 가능하다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;List 구현체의 공통 메소드&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메소드 기능 설명&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;boolean add(E e)&lt;/td&gt;
&lt;td&gt;주어진 객체를 맨 끝에 추가&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;void add(int index, E element)&lt;/td&gt;
&lt;td&gt;주어진 인덱스에 객체를 추가&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E set(int index, E element)&lt;/td&gt;
&lt;td&gt;주어진 인덱스에 저장된 객체를 주어진 객체로 바꾼후 이전 객체 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;boolean contains(Object O)&lt;/td&gt;
&lt;td&gt;주어진 객체가 저장되어있는지 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E get(int index)&lt;/td&gt;
&lt;td&gt;주어진 인덱스에 저장된 객체를 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;boolean isEmpty()&lt;/td&gt;
&lt;td&gt;컬렉션이 비었는지 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;int size()&lt;/td&gt;
&lt;td&gt;저장되어 있는 전체 객체 수를 리턴&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;void clear()&lt;/td&gt;
&lt;td&gt;저장된 모든 객체를 삭제&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E remove(int index)&lt;/td&gt;
&lt;td&gt;해당 인덱스 객체를 삭제후 삭제된 객체를 반환한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;boolean remove(Object o )&lt;/td&gt;
&lt;td&gt;주어진 객체가 있다면 삭제후 true/false로 결과를 알려준다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ArrayList&lt;/h3&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;List&amp;lt;String&amp;gt; sample = new ArrayList&amp;lt;String&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ArrayList는 일반적인 배열의 업그레이드 버전이라고 보면 조금 편할 수 있다. 크기를 처음에 정해주지 않아도 되며, 요소를 추가시키는 만큼 계속해서 늘어난다. 크기를 지정하고싶다면, 생성자 괄호 안에 숫자를 넣어주면 된다. 더하여 위 표에 있는 모든 메소드를 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, ArrayList는 생성시 메모리 구조가 아래 사진과 같다. 그렇기 때문에 삽입 혹은 삭제가 일어날 때 굉장히 불리하다. 인덱스에 값을 삭제 했을 때는 뒤의 인덱스를 한칸씩 앞당겨야하고, 값을 중간에 삽입하고자 한다면 해당 인덱스 뒤의 인덱스들을 모두 한칸씩 뒤로 밀어야한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-09-07 오후 11.36.24.png&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;77&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/efVwJG/btstq65hN6i/hkZLnUueTkTducsedzKqhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/efVwJG/btstq65hN6i/hkZLnUueTkTducsedzKqhk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/efVwJG/btstq65hN6i/hkZLnUueTkTducsedzKqhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FefVwJG%2Fbtstq65hN6i%2FhkZLnUueTkTducsedzKqhk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;714&quot; height=&quot;77&quot; data-filename=&quot;스크린샷 2023-09-07 오후 11.36.24.png&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;77&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기 때문에 삽입과 삭제가 많이 일어날 수 있는 자료에 대해서는 LinkedList를 보통 권장한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;LinkedList&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LinkedList도 ArrayList와 사용법은 거의 유사하다. 하지만 내부적인 구조는 매우 다르다. ArrayList의 경우 특정 크기의 연결된 셀을 확보하여 인덱스를 할당하는 반면 LinkedList는 연결된 셀을 사용하는 것이 아니라 떨어져 있는 셀들을 연결하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연결하는 방식은 특정셀마다 자신의 주소, 바로 다음 연결된 셀의 주소를 가지고 있다. 즉 셀의 주소를 공유하여 List형태를 갖추는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-09-07 오후 11.36.53.png&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;76&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTgHex/btstrRmtJ0A/2Snm6sehnKXBnvipobBj51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTgHex/btstrRmtJ0A/2Snm6sehnKXBnvipobBj51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTgHex/btstrRmtJ0A/2Snm6sehnKXBnvipobBj51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTgHex%2FbtstrRmtJ0A%2F2Snm6sehnKXBnvipobBj51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;714&quot; height=&quot;76&quot; data-filename=&quot;스크린샷 2023-09-07 오후 11.36.53.png&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;76&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사진과 같은 방식으로 구현되어 있기 때문에 중간에 삽입을 하거나 삭제를 했을때 간단하게 참조하는 주소만 다르게 설정해줌으로써 변경이 가능하다. 아래 사진이 삭제가 일어났을 때의 LinkedList 형태이다. (참고로 여기 나오는 숫자들은 인덱스가 아닌 값이다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-09-07 오후 11.37.10.png&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;76&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ewo7Ql/btstqCcihGo/ARphFkrTvbFxoAjkoH8SYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ewo7Ql/btstqCcihGo/ARphFkrTvbFxoAjkoH8SYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ewo7Ql/btstqCcihGo/ARphFkrTvbFxoAjkoH8SYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fewo7Ql%2FbtstqCcihGo%2FARphFkrTvbFxoAjkoH8SYk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;714&quot; height=&quot;76&quot; data-filename=&quot;스크린샷 2023-09-07 오후 11.37.10.png&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;76&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Set 컬렉션&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Set컬렉션은 저장 순서가 유지되지 않는다. 또한 객체를 중복해서 저장할 수 없다. 수학의 집합과 비슷한 느낌이라고 생각할 수 있다. 또한 인덱스가 없기 때문에 인덱스를 이용하는 메소드는 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메소드 설명&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;boolean add(E e)&lt;/td&gt;
&lt;td&gt;주어진 객체를 저장하고 성공시 true, 실패시 false를 반환한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;boolean containse(Object o)&lt;/td&gt;
&lt;td&gt;주어진 객체가 있는지 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;boolean isEmpty&lt;/td&gt;
&lt;td&gt;컬렉션이 비어있는지 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iterator&amp;lt;E&amp;gt; Iterator&lt;/td&gt;
&lt;td&gt;저장된 객체를 한 번씩 가져오는 반복자를 리턴&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;int size()&lt;/td&gt;
&lt;td&gt;저장되어 있는 전체 객체 수 리턴&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;void clear()&lt;/td&gt;
&lt;td&gt;저장된 모든 객체를 삭제&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;boolean remove(Object O )&lt;/td&gt;
&lt;td&gt;주어진 객체를 삭제&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Iterator&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;iterator는 요소를 하나씩 반환하는 객체이다. Set은 자체적으로 인덱스를 사용하지도 않고 주소를 가진 특정한 요소가 없기 때문에 set이나 map 같은 경우는 iterator를 사용해야 요소들에 접근할 수 있다. 보통 자주 쓰는 메서드는 아래와 같다. 보통 iterator에서 빈 값에 다음 요소를 불렀을 때는 nullPointException이 발생할 수 있기 때문에 hasNext() 메소드로 다음 요소가 존재하는지 확인한 이후에 요소에 접근해야한다.&lt;/p&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;Iterator&amp;lt;String&amp;gt; setIter = set.iterator();

setIter.hasNext() =&amp;gt; 다음 요소가 있는지 확인한다.
setIter.next() =&amp;gt; 다음 요소를 가져온다. 

while(setIter.hasNext()){
	String str = setIter.next();
	System.out.print(setIter.next);
	if( str.equals(&quot;할라&quot;) ){
		strIter.remove(); =&amp;gt; set의 객체를 삭제한다.
	}
}

&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HashSet&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HashSet은 위에서 이미 언급했듯 객체들을 순서 없이 저장하고 동일한 객체는 중복 저장하지 않는다. 또한 이름에서 알 수 있듯이 저장하기 전에 hashCode 메소드를 통해 해시코드를 얻고, 다른 객체를 저장할 때마다 해시코드를 비교하여 동일 객체는 저장하지 않는다. 일반적으로 hashCode메소드는 같은 객체여도 다른 값을 만들지만, 이를 HashSet에서 재정의 해서 사용하기 때문에 가능한 것이다. HashSet의 경우 삽입, 검색 모두 빠르다. 또한 재밌는 사실인데 내부적으로 보면 HashMap을 사용하여 정의하는 것을 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>dbdb1114</author>
      <guid isPermaLink="true">https://dev-dbdb1114.tistory.com/82</guid>
      <comments>https://dev-dbdb1114.tistory.com/82#entry82comment</comments>
      <pubDate>Thu, 7 Sep 2023 23:38:44 +0900</pubDate>
    </item>
    <item>
      <title>CleanCode 강의 후기(feat.WantedOnBoarding)</title>
      <link>https://dev-dbdb1114.tistory.com/81</link>
      <description>&lt;h1&gt;개요&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WantedOnBoarding 백엔드 챌린지에 참가했다. 3시간 길이의 강의 였다. 그동안 들었던 &amp;lsquo;클린코드&amp;rsquo;라는 개념에 대해서 설명을 들을 수 있었고, 나름의 기준을 만들어가기에 좋은 수업이었다. 자신만의 기준이 없는 나 같은 사람이라면 따라하며 기초를 잡기에 좋았다. 물론 강의에서 들은 내용이 전부 정답이라고 생각하지 않는다. 프로그래밍을 공부하면서 느꼈던 점은 매번 요구사항에 맞는 여러가지 방법들 중에서 제일 적합해 보이는 것을 골라서 사용하는 것이다. 정답은 없다. 하지만 기준이 없는 상태라면 누군가가 고심끝에 만들어낸 프로그래밍 기법이고, 유명하기에 한 번 익혀두면 좋겠다는 생각이든다.&lt;/p&gt;
&lt;h1&gt;MeaningfulNaming - 변수도 담백하게&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;변수도 담백하게&quot; 라는 말은 내 머릿속에서 나온 말이다. 나는 담백하다는 말을 좋아한다. 음식 보다는 사람에게 많이 쓴다. &amp;ldquo;너 참 담백하구나&amp;rdquo; 이런 느낌? 이런 칭찬을 부담스럽게 느끼는 사람들이 있어서 자주 쓰지는 않는다. 다만, 내가 사람에게 느끼는 담백함은 이런 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인간의 담백함&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;본인의 마음에 솔직하다.&lt;/li&gt;
&lt;li&gt;하는 말이 받아들이기에 이질감이 없고 매끄럽다.&lt;/li&gt;
&lt;li&gt;말을 헷갈리게 하지 않고, 쉬운 단어를 쓴다.&lt;/li&gt;
&lt;li&gt;불필요한 말을 하지 않는다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수의 담백함&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;역할이 명확히 드러나야 한다.&lt;/li&gt;
&lt;li&gt;다른 변수와 헷갈려서는 안된다.&lt;/li&gt;
&lt;li&gt;읽기에 좋아야한다. ( 가독성 )&lt;/li&gt;
&lt;li&gt;최대한 명확히 구분되어야 한다. ( 검색의 용이, 로그 파악에 용이 )&lt;/li&gt;
&lt;li&gt;불필요한 내용은 포함시키지 않는다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;수업내용에서 말씀하신 규칙들을 내 느낌을 위주로 써봤다. 이 규칙들을 생각하면서 변수명을 짓는다면 군더더기 없이 깔끔하겠다는 생각이 든다. 하지만 난이도는 담백한 사람이 되는 것 만큼이나 어려운 것 같다. 프로그래밍 공부를 하면서 매순간 느끼는 것 처럼 부단히 노력해야하는 것이 하나 추가된 느낌이다.&lt;/span&gt;&lt;/p&gt;
&lt;h1&gt;함수는 작게 만들자&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Atomic 디자인 패턴이 생각났다. Atomic 디자인 패턴은 모든 컴포넌트를 원자 단위로 쪼개어 사용한다고 해서 Atomic이라는 이름이 붙었는데 함수는 작게 만들라니까 이게 생각났다. 수업중에 들었던 내용은 나중에 쓸지 안 쓸지 모르기 때문에 함수는 가능한한 작은 단위로 만들어 두는 것이 좋다고 말씀하셨는데 끝에 강사님 본인도 처음 프로그래밍 할 때는 굳이 나눠야하나 생각했지만, 여태껏 개발을 하다보니 굳이 나눠두는게 좋다고 한다. ( 이런 얘기를 들으니 더 설득력 있었다. )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 중 명령과 조회를 분리하라는 말씀을 하셨는데 내가 이해한 기준으로 설명하자면 이렇다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령 : 어떤 행동을 하게 하는 것 &lt;br /&gt;조회 : 존재여부, 어떤게 맞는지 등을 알려주는 것&amp;nbsp;&lt;br /&gt;여러가지 함수가 있을텐데 내 머리속으로 예시를 들어보자면, 회원가입을 할 때 기존 회원인지 확인을 해야할 것이다. 보통 id를 중복체크를 한다고 하더라도, email이 같거나 전화번호가 같은 회원이 있을 수 있다. 이럴 때 회원가입 하는 함수에 이미 회원인지 확인하는 함수를 넣지 말라는 이야기이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변경 전&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;public int join(User user){
	if ( null != userService.getUser(user.getId)){
		return userService.insertUser(user);
	} else {
		return &quot;fail&quot;;
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변경후&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;public int join(User user){
	if ( userService.isExist(user) ){
		return userService.insertUser(user);
	} else {
		return &quot;fail&quot;;
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;너 정말 private 하게 쓰고있어? ( 디미터 법칙 )&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔직하게 한 대 맞았다. 아직은 이해할 수 없지만 써야한다는 약간의 의무감으로 인해 'private'이라는 접근제어자를 쓰고있었다. 어떤 객체를 만들 때 안에 정보를 안전하게 다뤄야 하니까 private을 썼는데 그래놓고 늘 getter와 setter를 만들어서 객체의 정보에 접근했다. 항상 의문이 있었지만 &amp;ldquo;뭐 조금은 도움이 되겠지&amp;ldquo; 하며 안일한 생각에 늘 그렇게 코드를 작성했다. 강의를 들으며 제대로 꼬집혔다. 이때 말씀해주신 관련 법칙이 디미터 법칙 이었다. 내가 이해하기로는 필요하다면 getter와 setter 보다는 기능단위로 만들어서 함수를 사용해야 한다는 이야기로 이해했다.&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;후기&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 수업 내용을 정리하듯 여기에 올리기에는 강사님이 열심히 준비한 자료를 배포하는 느낌이 들어서 올리지 않았다. 다만 나중에 언젠가 나도 여러 책을 보고 연습을 해서 완전히 내 것이 된다면 잘 정리해서 보는 사람들이 뭐라도 하나 얻어갈 수 있는 글을 쓰고싶다. 그런 날이 될 때 까지 열심히 공부해야겠다. 내가 아직 취준생 입장이라 그런지 모르겠지만 프로그래밍을 공부하다보면 공부할 것 들이 계속해서 내 앞에 떨어진다.( 현업자들 이야기를 들어보면 평생 그렇다고 하더라 ) 새로운 기술, 내가 익히지 못한 기술, 디자인패턴 등등 처음에는 너무 낯설고 어렵고 막막했지만 이제는 즐기며 공부하고 있다. 하나 하나 알아가는 즐거움이 참 좋다. 이번 강의도 그렇게 하나 하나 알게 된 순간 이었고 좋은 강의를 들을 수 있어서 원티드와 수업해주신 진호님께 감사하다.&lt;/p&gt;</description>
      <category>강의 강연 정리/WantOnboardChall(2023.09)</category>
      <author>dbdb1114</author>
      <guid isPermaLink="true">https://dev-dbdb1114.tistory.com/81</guid>
      <comments>https://dev-dbdb1114.tistory.com/81#entry81comment</comments>
      <pubDate>Wed, 6 Sep 2023 16:23:31 +0900</pubDate>
    </item>
    <item>
      <title>Spring 버전별 특징</title>
      <link>https://dev-dbdb1114.tistory.com/80</link>
      <description>&lt;h1&gt;Overview&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Spring이 뭘까?&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Spring Framework는 Java Web Framework이다.&lt;/li&gt;
&lt;li&gt;개발 생산성을 위해 지원하는 강력한 기능들에 비하여 경량 Framework이고 다른 복잡한 부분들을 Framework단에서 처리해주어 개발자들이 business login에만 신경쓸 수 있도록 지원하다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Spring의 특징&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;IOC ( Inversion of Control 제어의 반전 )
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;java를 이용한 프로그래밍에서는 new 연산자, 인터페이스 호출, 데이터 클래스 호출 방식으로 객체를 생성하고 소멸시킨다.&lt;/li&gt;
&lt;li&gt;IoC는 객체의 생성부터 소멸까지 개발자가 아닌 SpringContainer가 대신 해주는 것이다.&lt;/li&gt;
&lt;li&gt;제어권이 개발자가 아닌 IOC에 있으며, IoC가 개발자의 코드를 호출해 객체를 생성, 소멸하여 생명주기를 관리한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;DI ( Dependency Injection, 의존성 주입 )
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;프로그램에서 구성 요소의 의존관계가 소스코드 내부가 아닌 외부의 설정 파일을 통해 정의되는 방식이다.&lt;/li&gt;
&lt;li&gt;코드간의 재사용성을 높이고, 소스코드를 다양한 곳에 사용하며 모듈간의 결합도를 낮출 수 있다.&lt;/li&gt;
&lt;li&gt;대표적으로 라이브러리나 API,프레임워크를 연동할 때 연결하는 소스코드를 직접 작성하는게 아닌 외부 파일을 연결해 불러오는 방식이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;AOP (Aspect Object Programing, 관점 지향 프로그래밍 )
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;logging, transaction, security 등 여러 모듈에서 공통적으로 사용하는 기능을 분리하여 관리할 수 있다.&lt;/li&gt;
&lt;li&gt;여러 객체에 공통으로 적용할 수 있는 기능을 구분함으로써 재사용성을 높여주는 프로그래밍 기법&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;경량 ( Light-wighted )
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;크기와 부하 측면에서 독립된 몇 개의 jar 파일로 구성되어 있기 때문에 설치가 용이하며 POJO를 사용한다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;POJO( Plain Old Java Object ) POJO는 JAVA EE를 사용하면서 해당 플랫폼에 종속되어 있는 무거운 객체들을 만드는 것에 반발하여 나타난 용어이다. 별도의 프레임워크 없이 JavaEE 를 사용할 때에 비해 인터페이스를 직접 구현하거나 상속받을 필요가 없어 기존 라이브러리르 지원하기 용이하고, 객체가 가볍다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Transaction 관리
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Java Objec에 대한 transaction을 지원하지만 J2EE와 같은 환경에 얽매이지 않는다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Container
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Application 객체의 Life Cycle과 객체들 간 의존 관계를 container 형태로 관리한다. Servlet Container와 Spring Container의 차이점은 특정 WAS, 벤더에 종속적이지 않으며 자유로운 확장이 가능하다는 것이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 style=&quot;color: #000000; text-align: start;&quot;&gt;Spring 3.2.x &lt;span&gt;( ~ 2016.12.31 )&lt;/span&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Java 5의 지원되면서 Generic이나 가변인자 등과 같은 개선 사항이 추가되었다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;rArr; BeanFactory 등 핵심 API의 업데이트&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;전체 프레임워크를 하나의 Spring.jar 파일로 제공하던 부분을 여러개의 jar 파일로 나누어 제공한다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;spring-core, spring-web&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SPEL (Spring Expression Language)가 도입되었다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;XML및 Annotation 기반 Bean 정의에서 사용할 수 있게 되었고, 외부 프로퍼티 파일이나 환경 변수에서 값을 가져오기 쉬워졌다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Rest API에 대한 지원이 추가되었다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버로서는 기존 MVC Framework레벨에서 Annotation 기반 확장이 추가되었다.&lt;/li&gt;
&lt;li&gt;클라이언트로서는 RestTemplate을 추가해 지원한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;OXM ( Object XML Mapping ) 기능이 추가되어 XML 형태로 할 수 있게 지원한다 .&lt;/li&gt;
&lt;li&gt;@Configuration, @Bean 등의 Java Annotation을 이용해서 직접 메타 데이터를 설정하고, DI 지원이 가능해졌다.&lt;/li&gt;
&lt;li&gt;HSQL, H2, Derby 같은 내장 자바 데이터베이스 엔진을 편리하게 지원한다.&lt;/li&gt;
&lt;li&gt;@Async 주석을 통하여 비동기 메서드 호출을 지원했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Spring 4.1&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Java Config로 설정할 수 있는 부분이 증가했다.&lt;/li&gt;
&lt;li&gt;@JmsListener annotation으로 listener를 추가할 수 있게 했다.&lt;/li&gt;
&lt;li&gt;Spring Messaging abstraction이 JMS를 지원하기 시작했다.&lt;/li&gt;
&lt;li&gt;Caching 기능 향상
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CasheResolver를 사용해 캐시를 런타임에 결정하는 것이 가능해졌다.&lt;/li&gt;
&lt;li&gt;@CacheConfig 어노테이션을 이용한 어노테이션 레벨에서의 공통 세팅을 활성화 했다.&lt;/li&gt;
&lt;li&gt;cache resolver, cache manager, key generator 등의 커스터 마이징이 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Web
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@RequestParam, @RequestHeader, @MatrixVariable에 Optrional 사용 가능&lt;/li&gt;
&lt;li&gt;ResourceResolver, ResourceTransformer, ResourceUrlProvider 사용 가능&lt;/li&gt;
&lt;li&gt;ResponseEntity가 빌더 형식의 api를 제공한다. ( ex: ResponseEntity.ok() )&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Spring 4.2&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@Bean이 default method 감지&lt;/li&gt;
&lt;li&gt;@Import로 @Configuration class나 @Component class 임포트 가능.&lt;/li&gt;
&lt;li&gt;@Order 로 @Configuration 클래스가 로딩되는 순서 설정 가능&lt;/li&gt;
&lt;li&gt;annotation attribute를 위한 @AliasFor를 제공한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Spring 4.3&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Java 8 기능을 완전히 지원하기 시작함.&lt;/li&gt;
&lt;li&gt;Starter Pack이 생겨서 POM 설정을 도와준다.&lt;/li&gt;
&lt;li&gt;Groovy를 통한 Bean 설정이 가능하다.&lt;/li&gt;
&lt;li&gt;core
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;생성자 주입시 @Autowired 키워드 생략 가능&lt;/li&gt;
&lt;li&gt;@Configuration에서 생성자 주입 지원&lt;/li&gt;
&lt;li&gt;@Scheduled, @Schedules를 meta-annotation으로 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;caching
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@Cacheable의 sync 속성을 통한 동시성 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;WEB
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@RequestMapping의 다양한 형태 @GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping 추가&lt;/li&gt;
&lt;li&gt;class level에서 @ResponseStatus 지원&lt;/li&gt;
&lt;li&gt;@PathVariable Optional 사용 가능&lt;/li&gt;
&lt;li&gt;MvcExceptionHandler에 지속적인 혹은 커스텀 에러 처리 가능&lt;/li&gt;
&lt;li&gt;@RestControllerAdivce 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Spring 5.0&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Java 8 버전이 기본으로 설정됨 ( Java EE 7 API 이상 사용 가능 )&lt;/li&gt;
&lt;li&gt;CoreFramework
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Java8이 기본이 되면서 코어 스프링 인터페이스들이 디폴트 메서드 기반의 선택적 정의를 제공함&lt;/li&gt;
&lt;li&gt;@Nullable, @NotNull annotation을 사용해서 명시적으로 nullable 인자를 표시하고 값을 얻어올 수 있다. 이것은 컴파일 타임에 null값을 다룰 수 있게 됨을 뜻함.&lt;/li&gt;
&lt;li&gt;spring-jcl이라는 공통 로깅 브릿지 모듈 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Core Container
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;후보 컴포넌트 인덱스 기능 추가 (classpath 기반의 Component 스캔을 대체할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;non-blocking과 함수형 프로그래밍, reactive stream의 구현을 할 수 있는 Spring WebFlux를 지원한다. ( Spring MVC도 가능 )
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Spring Framework5로 업그레이드하면 Spring WebFlux를 사용하기 위해 애플리케이션을 다시 작성할 필요가 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Kotlin을 사용한 함수형 프로그래밍&lt;/li&gt;
&lt;li&gt;Testing
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Junit 5의 Jupiter 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;참고&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@jmjmjmz732002/Spring-Spring-버전별-특징#spring-4x&quot;&gt;https://velog.io/@jmjmjmz732002/Spring-Spring-버전별-특징#spring-4x&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hirlawldo.tistory.com/204&quot;&gt;https://hirlawldo.tistory.com/204&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://good-or-bad.tistory.com/54&quot;&gt;https://good-or-bad.tistory.com/54&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://m.blog.naver.com/whdgml1996/222001483936&quot;&gt;https://m.blog.naver.com/whdgml1996/222001483936&lt;/a&gt;&lt;/p&gt;</description>
      <category>프로그래밍/SPRING</category>
      <author>dbdb1114</author>
      <guid isPermaLink="true">https://dev-dbdb1114.tistory.com/80</guid>
      <comments>https://dev-dbdb1114.tistory.com/80#entry80comment</comments>
      <pubDate>Tue, 5 Sep 2023 23:05:21 +0900</pubDate>
    </item>
  </channel>
</rss>