<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>범진연습장</title>
    <link>https://bj-practice.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 22 Jun 2026 21:57:54 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>범진연습장</managingEditor>
    <item>
      <title>JAVA</title>
      <link>https://bj-practice.tistory.com/129</link>
      <description>&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;JAVA의 장단점?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- JVM 위에서 실행되기 때문에 OS에 종속적이지 않고, 독립적으로 실행될 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 객체지향 언어로, 객체지행 프로그래밍이 가능하다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;JVM이란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- JVM은 Java Virtual Machine의 줄임말로, OS와 Java Application 사이를 중재해주는 가상 머신입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- JVM은 크게 ClassLoader, Execution Engine, Garbage Collector, Runtime Data Area로 구성돼있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Java Application 실행 과정&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1.JVM은 OS로부터 적당한 메모리를 할당받음&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2.자바 소스 코드(.java)를 자바 컴파일러(javac)에 의해 바이트코드 파일(.class)로 변환&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. Class Loader를 통해 .class 파일을 Runtime Data Area로 로딩&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 로딩된 class 파일을 Execution Engine을 통해 해석 및 실행&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Garbage Collector란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;동적으로 할당한 메모리 영역 중, 사용하지 않는 영역을 탐지해 해제하는 역할을 합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Java에서 동적 변수를 할당하는 영역은 Heap 영역이므로 Jvm의 GC의 작동 대상은 Heap 메모리 입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;GC사용시 장점&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-메모리 누수 방지&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-해제된 메모리에 대해 접근하는 것을 방지&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-개발자가 일일히 동적변수의 제거 선언을 하지 않아도 됨&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;==와 Equals의 차이?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;==은 동일성( 메모리 내 주소값이 같은지 비교 ), equals는 동등성( 내용이 같은지 비교)&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Java의 접근 제한자에 대해 설명해주세요&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-public : 접근에 제한이 없음&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-private : 자기 자신 클래스 내에서만 접근 가능&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-default : 동일한 패키지 내에서만 접근 가능&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-protected : 동일한 패키지 내에서만 접근 가능 + 상속을 이용한 접근 가능&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Java의 hashcode()란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;두 객체가 동일한 객체인지 비교할 때 사용하고,&amp;nbsp; Heap 영역에 저장된 객체의 메모리 주소를 반환합니다.&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Boxing과 Unboxing에 대해 설명해주세요&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기본 타입의 변수를 래퍼 클래스의 인스턴스로 변경하는 과정을 박싱, 래퍼 클래스의 인스턴스를 다시 기본 타입으로 꺼내는 과정을 언박싱이라고 합니다.&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Java의 static 변수란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;클래스당 하나만 생성되고, 동일한 클래스의 모든 객체들에 의해 공유됩니다. 다른 객체들이 생기기 전에 이미 생성되고, 프로그램 종료시에 사라집니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;직렬화와 역직렬화&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;직렬화 : 자바 시스템 내부에서 사용되는 객체 또는 데이터를 외부의 자바 시스템에서도 사용할 수 있도록 바이트 형태로 데이터를 변환하는 기술&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;역직렬화 : 바이트로 변환된 데이터를 다시 객체로 변환하는 기술&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;추상클래스와 인터페이스&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추상클래스는 abstract 키워드를 사용해서 선언한 클래스로, 한개 이상의 추상 메소드를 포함한 클래스.&lt;/p&gt;
&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;p data-ke-size=&quot;size16&quot;&gt;인터페이스는 interface 키워드를 사용해 선언하며 default와 static을 제외하고는 추상 메소드와 상수만을 포함합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스 내부의 모든 메소드는 추상 메소드로, abstract public이 생략되어 있는 상태입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;인터페이스는 다중 상속이 가능하며 관련성이 없는 클래스들의 논리적으로 같은 기능을 자신에 맞게 구현을 강제하는데에 목적을 갖는다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Wrapper Class&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원시 자료형 타입의 데이터를 객체로 취급해야 하는 경우 사용하는 클래스로 기본 타입의 데이터를 객체로 변환해주는 클래스입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;오버로딩과 오버라이딩&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오버라이딩 : 상위 클래스의 메소드를 재정의 하는것을 의미 &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오버로딩 : 같은 클래스 내에서 동일한 메서드 이름을 가지지만, 반환형, 매개변수의 타입 등을 다르게해 구현하는것을 의미 &lt;/b&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;&amp;nbsp;&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;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;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;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;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;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;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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>면접준비</category>
      <author>범진연습장</author>
      <guid isPermaLink="true">https://bj-practice.tistory.com/129</guid>
      <comments>https://bj-practice.tistory.com/129#entry129comment</comments>
      <pubDate>Sun, 29 Sep 2024 16:47:31 +0900</pubDate>
    </item>
    <item>
      <title>Spring2</title>
      <link>https://bj-practice.tistory.com/128</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;서블릿이란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- WAS안에서 동적인 처리를 하는데 사용하는 서버 프로그램&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;싱글톤 패턴이란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 컨트롤러는 컴포넌트 스캔이 되면서 스프링 빈 컨테이너에 올라갑니다. 또한 빈 객체는 싱글톤 패턴으로 구현되어있기 때문에 &lt;b&gt;여러 쓰레드의 요청이 들어와도 하나의 컨트롤러 객체를 공유하면서 처리합니다.&lt;/b&gt; 즉, 여러 쓰레드가 메서드에 대해 공유 자원으로 접근해 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-메모리 측면에서 최초 한 번의 new 연산자를 통해 고정된 메모리 영역을 사용하기 때문에 해당 객체에 접근할 때 메모리 낭비를 방지할 수 있고, 이미 생성된 인스턴스를 활용하니 속도 측면에도 이점이 있습니다.&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;&lt;b&gt;싱글톤 패턴으로 구현되어 있다는 점은 ,Thread-Safe 하지 않다는 의미이므로, 상태를 공유하거나 저장하는 코드가 없도록 Stateless하게 정의해야 합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;AOP란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-관점 지향 프로그래밍의 약어로, &lt;b&gt;공통 관심사항과 핵심 관심사항을 분리하는 것을 의미합니다. 각 소스코드에서 여러 번 반복해서 사용하는 코드를 흩어진 관심사라고 부르고, 이것을 Aspect로 모듈화해 핵심 로직에서 분리해 재사용하는 것이라고 볼 수 있습니다.&lt;/b&gt; 예를 들어, 로그, 성능테스트, 권한, 트랜잭션 등을 모든 메소드에 적용하고 싶을 때 일일히 추가하는 것이 아니라 AOP를 활용해 적용할 수 있다는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;DAO,DTO,BO,VO란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-DAO(Data Access Object)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB데이터를 조회하거나 조작하는 기능을 전담하는 객체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-DTO(Data Transfer Object)&lt;/b&gt;&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;b&gt;-VO(Value Object)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DTO와 동일한 개념, Read Only로 수정불가, getter setter 이외의 추가 로직 포함가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-BO(Business Object)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비즈니스 로직을 포함하는 오브젝트로, 여러 DAO를 사용해 데이터를 처리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;커넥션 풀이란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 어플리케이션이 DB를 사용하기 위해서는 Connection이 필요한데, 이 생성 및 소멸 비용이 크기 때문에, 커넥션 풀을 미리 생성하고 애플리케이션이 시작하는 시점에 커넥션을 미리 다 생성하고 이것을 재활용하며 사용하게 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Springboot 이후 부터는 hikariCP를 기본으로 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;트랜잭션을 추상화해서 사용하는 이유&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-다양한 데이터 접근 기술이 등장하면서, 코드레벨에서는 다르지만 논리적으로는 같은 기능을 수행하기 때문에 트랜잭션을 추상화 하여 사용한다. 다양한 접근 기술로는 JDBC,JPA,하이버네이트 등이 있습니다.&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>면접준비</category>
      <author>범진연습장</author>
      <guid isPermaLink="true">https://bj-practice.tistory.com/128</guid>
      <comments>https://bj-practice.tistory.com/128#entry128comment</comments>
      <pubDate>Sat, 28 Sep 2024 14:40:23 +0900</pubDate>
    </item>
    <item>
      <title>Spring</title>
      <link>https://bj-practice.tistory.com/127</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;WAS와 WS의 차이를 설명하시오.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WAS(Web Application Server)&lt;/p&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;Tomcat,PHP,ASP,.NET 등&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WS(Web Server)&lt;/p&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;Nginx, Apache 등&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;http://1.Web&quot;&gt;1.Web&lt;/a&gt; Server&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-클라이언트에게 요청을 받고 정적인 Request라면 (html, css 등) 정적인 콘텐츠를 Response합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-클라이언트에게 요청을 받고 동적인 Request라면 WAS로 처리를 이관한 뒤 WAS에서 처리한 결과를 클라이언트에게 전달 합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;WAS&lt;/li&gt;
&lt;li&gt;DB 조회가 필요하거나 사용자의 입력을 받아 &lt;b&gt;서버에서 가변적으로 로직을 수행하는 등의 동적인 처리가 필요한 요청을 처리&lt;/b&gt;하기 위해 만들어졌습니다. Web Container의 JSP/Servlet 구동 환경을 제공하고 프로그래밍 언어(JSP,PHP 등)로 작성한 뒤 HTML 문서로 만들고 Web Server로 전달합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Web Server와 WAS를 분리해 놓는 이유&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;Web Server를 두는 가장 큰 이유. 만약 정적 컨텐츠 요청까지 WAS가 처리한다면 정적 데이터 처리로 인해 부하가 커지게 되고, 동적 컨텐츠의 처리가 지연됨에 따라 수행 속도가 느려집니다. 그렇기에 &lt;b&gt;단순한 정적 컨텐츠 요청은 Web Server에서 빠르게 클라이언트에 제공하여 WAS로 넘어오지 않게 막는 것이 줗습니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;물리적으로 분리하여 보안 강화&lt;/li&gt;
&lt;li&gt;여러대의 WAS를 연결 가능&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Web Server하나에 여러 대의 WAS를 설치&lt;/b&gt;하고 Load Balancing을 하여 WAS의 부하를 더 낮춰줄 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Spring Framework에 대해 설명해주세요&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링 프레임워크는 자바 개발을 편리하게 해주는 오픈소스 프레임워크 입니다.&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;b&gt;-각각의 객체 생성, 소멸과 같은 라이프 사이클을 관리하며 스프링으로부터 필요한 객체를 얻어올 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-제어의 역전(IoC)이라는 기술을 통해 어플리케이션의 느슨한 결합을 도모&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-컨트롤의 제어권이 사용자가 아닌 프레임워크에 있어서 필요에 따라 스프링에서 사용자의 코드를 호출한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-의존성 주입(DI, Dependency Injection)을 지원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-각각의 계층이나 서비스들 간에 의존성이 존재할 경우 프레임워크가 서로 연결시켜 준다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-관점 지향 프로그래밍(AOP, Aspect-Oriented Programming)을 지원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-트랜잭션이나 로깅, 보안과 같이 여러 모듈에서 공통적으로 사용하는 기능의 경우 해당 기능을 분리하여 관리할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Spring MVC에 대해 설명해주세요&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-MVC는 Model, View, Controller의 약자이며, &lt;b&gt;각 레이어간 기능을 구분하는데 중점을 둔 디자인 패턴입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-Model은 데이터 관리 및 비즈니스 로직을 처리하는 부분&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-View는 비즈니스 로직의 처리 결과를 유저 인터페이스가 표현되는 구간&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-Controller는 사용자의 요청을 처리하고 Model과 View를 중개하는 역할&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DispatcherServlet : 클라이언트에게 요청을 받아 응답까지의 MVC처리과정을 통제한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HandlerMapping : 클라이언트의 요청 URL을 어떤 Controller가 처리할지 결정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HandlerAdapter : HandlerMapping에서 결정된 핸들러 정보로 해당 메소드를 직접 호출해주는 역할을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ViewResolver : Controller의 처리 결과를 생성할 view를 결정한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;클라이언트는 URL을 통해 요청을 전송한다.&lt;/li&gt;
&lt;li&gt;DispatcherServlet은 HandlerMapping을 통해 해당 요청이 어느 컨트롤러에게 온 요청인지 찾는다.&lt;/li&gt;
&lt;li&gt;DispatcheServlet은 HandlerAdapter에게 요청의 전달을 맡긴다.&lt;/li&gt;
&lt;li&gt;HandlerAdapter는 해당 컨트롤러에 요청을 전달한다.&lt;/li&gt;
&lt;li&gt;컨트롤러는 비즈니스 로직을 처리한 후에 반환할 뷰의 이름을 반환한다.&lt;/li&gt;
&lt;li&gt;DispatcherServlet은 ViewResolver를 통해 반환할 뷰를 찾는다.&lt;/li&gt;
&lt;li&gt;DispatcherServlet은 컨트롤러에서 뷰에 전달할 데이터를 추가한다.&lt;/li&gt;
&lt;li&gt;데이터가 추가된 뷰를 반환한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;제어의 역전(IoC)에 대해 아는대로 설명해주세요.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 객체에 대한 라이프 사이클을 개발자가 아닌 Ioc컨테이너에게 넘긴 것을 말합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 개발자는 로직에 집중할 수 있는 장점이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링은 Ioc컨테이너에 객체들을 생성하면 객체끼리 의존성을 주입(DI)하는 역할을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*&lt;b&gt;컨테이너에 등록된 객체를 빈이라고합니다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링 컨테이너(=IoC 컨테이너)의 종류&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링 컨테이너가 관리하는 객체를 빈(Bean)이라고 하고, 이 빈들을 관리한다는 의미로 컨테이너를 빈 팩토리(Bean Factory)라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-객체의 생성과 객체 사이의 런타임 관계를 DI관점에서 볼 때 컨테이너를 BeanFactory라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-BeanFactory에 여러가지 기능을 추가한 ApplicationContext가 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DI(Dependency Injection) 란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 클래스간의 의존관계를 빈 설정(Bean Definition) 정보를 바탕으로 컨테이너가 자동으로 연결해주는 것&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;의존성 주입의 3가지 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring은 @Autowired 어노테이션을 이용한 다양한 의존성 주입(DI, Dependency Injection) 방법을 제공합니다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Autowired는 Spring에게 의존성을 주입하는 지시자 역할로 쓰입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;의존성 주입 필요성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-코드의 재사용성을 높여준다.&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;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;의존성 주입 3가지 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.생성자 주입(Constructor Injection)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.필드 주입(Field Injection)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3.수성자 주입(Setter Injection)&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;/ol&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;@Controller
public class ConsController{
//final을 붙일 수 있음
	private final ConsService consService;
	
	//@Autowired
	public ConsController(ConsService consService){
		this.consService = consService;
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스의 생성자가 하나이고, 그 생성자로 주입받을 객체가 빈으로 등록되어 있다면 @Autowired를 생략 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.필드 주입(Field Injection)&lt;/p&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;@Controller
public class FiledController{
	@Autowired
	private FiledService filedService;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필드에 @Autowired 어노테이션만 붙여주면 자동으로 의존성 주입 됩니다.&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;b&gt;단점&lt;/b&gt;&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3.수정자 주입(Setter Injection)&lt;/p&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;@Controller
public class SetterController{
	private SetterService setterService;
	
	@Autowired
	public void setSetterController(SetterService setterService){
		this.setterService = setterService;
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Setter 메소드에 @Autowired 어노테이션을 붙이는 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-수정자 주입을 사용하면 setXXX메소드를 public으로 열어두어야 하기 때문에 언제 어디서든 변경이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 주입 방식을 사용하는게 좋을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SpringFramework reference에서 권장하는 방법은 &lt;b&gt;생성자를 통한 주입&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;순환 참조를 방지할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필드 주입과 수정자 주입은 빈이 생성된 후에 참조를 하기 때문에 어플리케이션이 아무런 오류없이 구동됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 생성자를 통해 주입하고 실행하면 BeanCurrentlyInCreationException이 발생하게 되어 오류 체크를 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;불변성(Immutability)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자로 의존성을 주입할 때 final로 선언할 수 있고, 이로인해 런타임에서 의존성을 주입받는 객체가 변할 일이 없어지게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 수정자 주입이나 일반 메소드 주입을 이용하게 되면 불필요 하게 수정의 가능성을 열어두게 되고 이는 OOP의 5가지 원칙 중 OCP(Open-Closed Principal, 개방-폐쇄의 원칙)를 위반하게 됩니다. &lt;b&gt;그러므로 생성자 주입을 통해 변경의 가능성을 배제하고 불변성을 보장하는 것이 좋습니다.&lt;/b&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;관점지향 프로그래밍(AOP, Aspect Oriented Programming)은 무엇이고, 언제 사용할 수 있을까요?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AOP는 핵심 비즈니스 로직에 있는 &lt;b&gt;공통 관심사항을 분리&lt;/b&gt;하여 각각을 모듈화 하는 것을 의미하며 공통 모듈인 &lt;b&gt;인증, 로깅, 트랙잭션 처리&lt;/b&gt;에 용이합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 비즈니스 로직에 부가기능을 하는 모듈이 중복되어 분포되어 있을 경우 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AOP의 가장 큰 특징이자 장점은 중복 코드 제거, 재활용성의 극대화, 변화수용의 용이성이 좋다는 점입니다.&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;AOP는 OOP를 돕는 보조적인 기술로, AOP는 기능을 &lt;b&gt;핵심 관심 사항(Core Concern)과 공통 관심 사항(Cross-Cuttin Concern)으로 분리시키고 각각을 모듈화&lt;/b&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;OOP를 적용하여도 핵심 기능에서 부가 기능을 쉽게 분리된 모둘로 작성하기 어려운 문제점을 AOP가 해결해준다.&lt;/li&gt;
&lt;li&gt;AOP는 부가기능을 애스펙트(Aspect)로 정의하여, 핵심 기능에서 부가 기능을 분리함으로써 핵심 기능을 설계 하고 구현할 때 객체지향적인 가치를 지킬 수 있게 도와주는 개념이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>면접준비</category>
      <author>범진연습장</author>
      <guid isPermaLink="true">https://bj-practice.tistory.com/127</guid>
      <comments>https://bj-practice.tistory.com/127#entry127comment</comments>
      <pubDate>Thu, 19 Sep 2024 16:36:00 +0900</pubDate>
    </item>
    <item>
      <title>요청 매핑</title>
      <link>https://bj-practice.tistory.com/126</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;MappingController&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1724650888031&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package hello.springmvc.basic.requestmapping;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MappingController {

    private Logger log = LoggerFactory.getLogger(getClass());

    @RequestMapping(&quot;/hello-basic&quot;)
    public String helloBasic(){
        log.info(&quot;hellobasic&quot;);
        return &quot;ok&quot;;

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@RequestMapping(&quot;/hello-basic&quot;)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;'/hello-basic' URL 호출이 오면 이 메서드가 실행도도록 매핑한다&lt;/li&gt;
&lt;li&gt;대부분의 속성을 '배열{ }'로 제공하므로 다중 설정이 가능하다 {&quot;/hello-basic&quot;,&quot;/hello-go&quot;}&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;HTTP Method&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@RequestMapping 으로 HTTP메서드를 지정해주지 않으면 HTTP메서드와 무관하게 호출된다.&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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;경로 변수(PathVariable) 사용&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1724651475870&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@GetMapping(&quot;/mapping/{userid}&quot;)
    public String mappingPath(@PathVariable(&quot;userid&quot;)String data){
        log.info(&quot;mappingPath userId={}&quot;,data);
        return &quot;ok&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 HTTP API는 다음과 같이 리소스 경로에 식별자를 넣는 스타일을 선호한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;/mapping/userA&lt;/li&gt;
&lt;li&gt;/users/1&lt;/li&gt;
&lt;li&gt;'@RequestMapping'은 URL경로를 템플릿화 할 수 있는데 '@PathVariable'을 사용하면 매칭 되는 부분을 편리하게 조회할 수 있다.&lt;/li&gt;
&lt;li&gt;'@PathVariable'의 이름과 파라미터 이름이 같으면 생략할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1724651768862&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; @GetMapping(&quot;/mapping/{userid}&quot;)
    public String mappingPath(@PathVariable String userid){
        log.info(&quot;mappingPath userId={}&quot;,userid);
        return &quot;ok&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;특정 헤더 조건 매핑&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1724652055313&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@GetMapping(value = &quot;/mapping-header&quot;,headers = &quot;mode=debug&quot;)
    public String mappingHeader(){
        log.info(&quot;mappingHeader&quot;);;
        return&quot;ok&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1071&quot; data-origin-height=&quot;294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eCCAos/btsJg5WXKde/ukSfkHXaSjkmKm6pot4950/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eCCAos/btsJg5WXKde/ukSfkHXaSjkmKm6pot4950/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eCCAos/btsJg5WXKde/ukSfkHXaSjkmKm6pot4950/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeCCAos%2FbtsJg5WXKde%2FukSfkHXaSjkmKm6pot4950%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;1071&quot; height=&quot;294&quot; data-origin-width=&quot;1071&quot; data-origin-height=&quot;294&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;&lt;b&gt;미디어 타입 조건 매핑 - HTTP 요청 Content-Type, consume&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1724652253292&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@GetMapping(value = &quot;/mapping-consume&quot;,consumes = &quot;application/json&quot;)
    public String mappingConsumes(){
        log.info(&quot;mappingConsumes&quot;);
        return &quot;ok&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CY4U6/btsJfETO0jv/kLhlPDQJHkLGAWgy2DwT1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CY4U6/btsJfETO0jv/kLhlPDQJHkLGAWgy2DwT1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CY4U6/btsJfETO0jv/kLhlPDQJHkLGAWgy2DwT1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCY4U6%2FbtsJfETO0jv%2FkLhlPDQJHkLGAWgy2DwT1k%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;1058&quot; height=&quot;225&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;225&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;</description>
      <category>Spring 백엔드 핵심 기술/springMVC</category>
      <author>범진연습장</author>
      <guid isPermaLink="true">https://bj-practice.tistory.com/126</guid>
      <comments>https://bj-practice.tistory.com/126#entry126comment</comments>
      <pubDate>Mon, 26 Aug 2024 15:08:40 +0900</pubDate>
    </item>
    <item>
      <title>로깅 간단히 알아보기</title>
      <link>https://bj-practice.tistory.com/125</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;운영 시스템에서는 System.out.println() 같은 시스템 콘솔을 사용해서 필요한 정보를 출력하지 않고, 별도의 로깅 라이브러리를 사용해서 로그를 출력한다.&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;&lt;b&gt;로깅 라이브러리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링 부트 라이브러리를 사용하면 스프링 부트 로깅 라이브러리 'spring-boot-starter-logging' 가 함께 포함된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링 부트 로깅 라이브러리는 기본으로 다음 로깅 라이브러리를 사용한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SLF4J&lt;/li&gt;
&lt;li&gt;Logback&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그 라이브러리는 Logback, Log4J, Log4J2 등등 수 많은 라이브러리가 있는데, 그것을 통합해서 인터페이스로 제공하는 것이 바로 SLF4J 라이브러리다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 이야기해서 SLF4J는 인터페이스이고, 그 구현체로 Logback 같은 로그 라이브러리를 선택하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무에서는 스프링 부트가 기본으로 제공하는 Logback을 대부분 사용한다.&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;&lt;b&gt;로그 선언&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;private Logger log = LoggerFactory.getLogger(getClass());&lt;/li&gt;
&lt;li&gt;private static final Logger log = LoggerFactory.getClass(Xxx.class)&lt;/li&gt;
&lt;li&gt;@Slf4j : 롬복 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;로그 호출&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;log.info(&quot;hello&quot;)&lt;/li&gt;
&lt;/ul&gt;
&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LogTestController&lt;/p&gt;
&lt;pre id=&quot;code_1724649603203&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package hello.springmvc.basic;

import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
public class LogTestController {
//    private final Logger log = LoggerFactory.getLogger(getClass());

    @RequestMapping(&quot;/log-test&quot;)
    public String logTest(){
        String name = &quot;spring&quot;;

        System.out.println(name);
        
        log.trace(&quot;trace log={}&quot;, name);
        log.debug(&quot;debug log={}&quot;,name);
        log.info(&quot;info log={}&quot;, name);
        log.warn(&quot;warn log={}&quot;, name);
        log.error(&quot;error log={}&quot;, name);

        return &quot;ok&quot;;
    }
}&lt;/code&gt;&lt;/pre&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로그가 출력되는 포멧 확인
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간,로그,레벨,프로세스,ID,쓰레드,클래스명,로그 메시지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;로그 레벨 설정을 변경해서 출력 결과를 바꿀 수 있다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Level : TRACE &amp;gt; DEBUG &amp;gt; INFO &amp;gt; WARN &amp;gt; ERROR&lt;/li&gt;
&lt;li&gt;개발 서버는 debug 출력&lt;/li&gt;
&lt;li&gt;운영 서버는 info 출력&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;@Slf4j로 변경&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;로그 레벨 설정&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;780&quot; data-origin-height=&quot;264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zUxMW/btsJgeUy4b8/um0VJgjChKY5D73whGefC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zUxMW/btsJgeUy4b8/um0VJgjChKY5D73whGefC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zUxMW/btsJgeUy4b8/um0VJgjChKY5D73whGefC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzUxMW%2FbtsJgeUy4b8%2Fum0VJgjChKY5D73whGefC1%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;780&quot; height=&quot;264&quot; data-origin-width=&quot;780&quot; data-origin-height=&quot;264&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;&lt;b&gt;올바른 로그 사용법&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;log.debug(&quot;data=&quot;+data)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로그 출력 레벨을 info로 설정해도 해당 코드에 있는 &quot;data=&quot;+data가 실제 실행이 되어 버린다. 결과적으로 문자 더하기 연산이 발생한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;log.debug(&quot;data={}&quot;,data)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로그 출력 레벨을 info로 설정하면 아무일도 발생하지 않는다. 따라서 앞과 같은 의미없는 연산이 발생하지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;로그 사용시 장점&lt;/b&gt;&lt;/p&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;b&gt;로그 레벨에 따라 개발 서버에서는 모든 로그를 출력하고, 운영서버에서는 출력하지 않는 등 로그를 상황에 맞게 조절할 수 있다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;시스템 아웃 콘솔에만 출력하는 것이 아니라, 파일이나 네트워크 등, 로그를 별도의 위치에 남길 수 있다. 특히 파일로 남길 때는 일별, 특정 용량에 따라 로그를 분할하는 것도 가능하다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;성능도 일반 System.out보다 좋다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Spring 백엔드 핵심 기술/springMVC</category>
      <author>범진연습장</author>
      <guid isPermaLink="true">https://bj-practice.tistory.com/125</guid>
      <comments>https://bj-practice.tistory.com/125#entry125comment</comments>
      <pubDate>Mon, 26 Aug 2024 14:35:36 +0900</pubDate>
    </item>
    <item>
      <title>JSP로 회원 관리 웹 애플리케이션 만들기</title>
      <link>https://bj-practice.tistory.com/124</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 JSP로 회원 등록 html을 만들자.&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;&lt;b&gt;newForm.jsp&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1724639245551&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot; language=&quot;java&quot; %&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Title&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;form action=&quot;/jsp/members/save.jsp&quot; method=&quot;post&quot;&amp;gt;
    username: &amp;lt;input type=&quot;text&quot; name=&quot;username&quot; /&amp;gt;
    age:
    &amp;lt;input type=&quot;text&quot; name=&quot;age&quot; /&amp;gt;
    &amp;lt;button type=&quot;submit&quot;&amp;gt;전송&amp;lt;/button&amp;gt;
&amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;save.jsp&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1724639264962&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page import=&quot;hello.servlet.domain.member.MemberRepository&quot; %&amp;gt;
&amp;lt;%@ page import=&quot;hello.servlet.domain.member.Member&quot; %&amp;gt;
&amp;lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot; language=&quot;java&quot; %&amp;gt;
&amp;lt;%
    //request, response 사용 가능
    MemberRepository memberRepository = MemberRepository.getInstance();
    System.out.println(&quot;save.jsp&quot;);
    String username = request.getParameter(&quot;username&quot;);
    int age = Integer.parseInt(request.getParameter(&quot;age&quot;));
    Member member = new Member(username, age);
    System.out.println(&quot;member = &quot; + member);
    memberRepository.save(member);
%&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Title&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
성공
&amp;lt;ul&amp;gt;
    &amp;lt;li&amp;gt;id=&amp;lt;%=member.getId()%&amp;gt;&amp;lt;/li&amp;gt;
    &amp;lt;li&amp;gt;username=&amp;lt;%=member.getUsername()%&amp;gt;&amp;lt;/li&amp;gt;
    &amp;lt;li&amp;gt;age=&amp;lt;%=member.getAge()%&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;a href=&quot;/index.html&quot;&amp;gt;메인&amp;lt;/a&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;members.jsp&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1724639277465&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;%@ page import=&quot;hello.servlet.domain.member.MemberRepository&quot; %&amp;gt;
&amp;lt;%@ page import=&quot;java.util.List&quot; %&amp;gt;
&amp;lt;%@ page import=&quot;hello.servlet.domain.member.Member&quot; %&amp;gt;
&amp;lt;%@ page import=&quot;java.util.ArrayList&quot; %&amp;gt;&amp;lt;%
    MemberRepository memberRepository= MemberRepository.getInstance();
    List&amp;lt;Member&amp;gt; members = memberRepository.findAll();
%&amp;gt;
&amp;lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot; language=&quot;java&quot; %&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Title&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;a href=&quot;/index.html&quot;&amp;gt;메인&amp;lt;/a&amp;gt;
&amp;lt;table&amp;gt;
    &amp;lt;thead&amp;gt;
    &amp;lt;th&amp;gt;id&amp;lt;/th&amp;gt;
    &amp;lt;th&amp;gt;username&amp;lt;/th&amp;gt;
    &amp;lt;th&amp;gt;age&amp;lt;/th&amp;gt;
    &amp;lt;/thead&amp;gt;
    &amp;lt;tbody&amp;gt;
    &amp;lt;%
        for(Member member : members){
            out.write(&quot;     &amp;lt;tr&amp;gt;&quot;);
            out.write(&quot;            &amp;lt;td&amp;gt;&quot; + member.getId() +&quot;&amp;lt;/td&amp;gt;&quot;);
            out.write(&quot;            &amp;lt;td&amp;gt;&quot; + member.getUsername() +&quot;&amp;lt;/td&amp;gt;&quot;);
            out.write(&quot;            &amp;lt;td&amp;gt;&quot; + member.getAge() +&quot;&amp;lt;/td&amp;gt;&quot;);
            out.write(&quot;     &amp;lt;/tr&amp;gt;&quot;);
        }
    %&amp;gt;
    &amp;lt;/tbody&amp;gt;

&amp;lt;/table&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JSP는 자바 코드를 그대로 다 사용할 수 있다.&lt;/li&gt;
&lt;li&gt;&amp;lt;%@ page import=&quot;hello.servlet.domain.member.MemberRepository&quot; %&amp;gt; 자바의 import 문과 같다.&lt;/li&gt;
&lt;li&gt;&amp;lt;% ~~ %&amp;gt; 이 부분에는 자바 코드를 입력할 수 있다.&lt;/li&gt;
&lt;li&gt;&amp;lt;%= ~~ %&amp;gt; 이 부분에는 자바 코드를 출력할 수 있다.&lt;/li&gt;
&lt;li&gt;회원 저장 JSP를 보면, 회원 저장 서블릿 코드와 같다. 다른 점이 있다면, HTML을 중심으로 하고, 자바 코드를 부분부분 입력해주었다. &amp;lt;% ~ %&amp;gt;를 사용해서 HTML 중간에 자바 코드를 출력하고 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서블릿과 JSP의 한계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서블릿으로 개발할 때는 뷰(View)화면을 위한 HTML을 만드는 작업이 자바 코드에 섞여서 지저분하고 복잡하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSP를 사용한 덕분에 뷰를 생성하는 HTML 작업을 깔끔하게 가져가고, 중간중간 동적으로 변경이 필요한 부분에만 자바 코드를 적용했다. 그런데 이렇게 해도 해결되지 않는 몇가지 고민이 남는다.&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;회원 저장 JSP를 보자. 코드의 상위 절반은 회원을 저장하기 위한 비즈니스 로직이고, 나머지 하위 절반만 결과를 HTML로 보여주기 위한 뷰 영역이다. 회원 목록의 경우에도 마찬가지이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 잘 보면, JAVA코드, 데이터를 조회하는 리포지토리 등등 다양한 코드가 모두 JSP에 노출되어 있다. JSP가 너무 많은 역할을 한다.&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;MVC패턴의 등장&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비즈니스 로직은 서블릿 처럼 다른곳에서 처리하고, JSP는 목적에 맞게 HTML로 화면(View)를 그리는 일에 집중하도록 하자. 과거 개발자들도 모두 비슷한 고민이 있었고, 그래서 MVC 패턴이 등장했다. 우리도 직접 MVC 패턴을 적용해서 프로젝트를 리팩토링 해보자.&lt;/p&gt;</description>
      <category>Spring 백엔드 핵심 기술/servlet</category>
      <author>범진연습장</author>
      <guid isPermaLink="true">https://bj-practice.tistory.com/124</guid>
      <comments>https://bj-practice.tistory.com/124#entry124comment</comments>
      <pubDate>Mon, 26 Aug 2024 11:34:55 +0900</pubDate>
    </item>
    <item>
      <title>HTTP 응답 데이터 - API JSON</title>
      <link>https://bj-practice.tistory.com/122</link>
      <description>&lt;pre id=&quot;code_1724634956712&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package hello.servlet.basic.response;

import com.fasterxml.jackson.databind.ObjectMapper;
import hello.servlet.basic.HelloData;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

@WebServlet(name = &quot;responseJsonServlet&quot;,urlPatterns = &quot;/response-json&quot;)
public class ResponseJsonServlet extends HttpServlet {

    private ObjectMapper objectMapper = new ObjectMapper();
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType(&quot;application/json&quot;);
        resp.setCharacterEncoding(&quot;utf-8&quot;);

        HelloData helloData = new HelloData();
        helloData.setUsername(&quot;kim&quot;);
        helloData.setAge(20);

        String result = objectMapper.writeValueAsString(helloData);
        resp.getWriter().write(result);

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;962&quot; data-origin-height=&quot;534&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTn0ZE/btsJd7bA2he/57tQHKMz9c5vQTBnQtk2nK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTn0ZE/btsJd7bA2he/57tQHKMz9c5vQTBnQtk2nK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTn0ZE/btsJd7bA2he/57tQHKMz9c5vQTBnQtk2nK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTn0ZE%2FbtsJd7bA2he%2F57tQHKMz9c5vQTBnQtk2nK%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;962&quot; height=&quot;534&quot; data-origin-width=&quot;962&quot; data-origin-height=&quot;534&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP 응답으로 JSON을 반환할 때는 content-type을 application-json으로 지정해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Jackson 라이브러리가 제공하는 objectMapper.writeValueAsString을 사용하면 객체를 JSON 문자로 변경할 수 있다&lt;/p&gt;</description>
      <category>Spring 백엔드 핵심 기술/servlet</category>
      <author>범진연습장</author>
      <guid isPermaLink="true">https://bj-practice.tistory.com/122</guid>
      <comments>https://bj-practice.tistory.com/122#entry122comment</comments>
      <pubDate>Mon, 26 Aug 2024 10:18:26 +0900</pubDate>
    </item>
    <item>
      <title>HTTP 응답 데이터 - 단순 텍스트, HTML</title>
      <link>https://bj-practice.tistory.com/121</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;/li&gt;
&lt;li&gt;HTML 응답&lt;/li&gt;
&lt;li&gt;HTTP API - Message Body JSON 응답&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1724634641585&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package hello.servlet.basic.response;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name = &quot;responseHtmlServlet&quot;,urlPatterns = &quot;/response-html&quot;)
public class ResponseHtmlServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //Content-type : text/html; charset : UTF-8
        resp.setContentType(&quot;text/html&quot;);
        resp.setCharacterEncoding(&quot;utf-8&quot;);

        PrintWriter writer = resp.getWriter();
        writer.println(&quot;&amp;lt;html&amp;gt;&quot;);
        writer.println(&quot;&amp;lt;body&amp;gt;&quot;);
        writer.println(&quot;&amp;lt;div&amp;gt;안녕&amp;lt;/div&amp;gt;&quot;);
        writer.println(&quot;&amp;lt;/body&amp;gt;&quot;);
        writer.println(&quot;&amp;lt;/html&amp;gt;&quot;);

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1040&quot; data-origin-height=&quot;513&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9DXuC/btsJgv9bjVA/X3ECfzIu5Dz6qQTVNpL0FK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9DXuC/btsJgv9bjVA/X3ECfzIu5Dz6qQTVNpL0FK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9DXuC/btsJgv9bjVA/X3ECfzIu5Dz6qQTVNpL0FK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9DXuC%2FbtsJgv9bjVA%2FX3ECfzIu5Dz6qQTVNpL0FK%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;1040&quot; height=&quot;513&quot; data-origin-width=&quot;1040&quot; data-origin-height=&quot;513&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Spring 백엔드 핵심 기술/servlet</category>
      <author>범진연습장</author>
      <guid isPermaLink="true">https://bj-practice.tistory.com/121</guid>
      <comments>https://bj-practice.tistory.com/121#entry121comment</comments>
      <pubDate>Mon, 26 Aug 2024 10:11:05 +0900</pubDate>
    </item>
    <item>
      <title>HTTP 요청 데이터 -API 메시지 바디 - JSON</title>
      <link>https://bj-practice.tistory.com/120</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 HTTP API에서 주로 사용하는 JSON 형식으로 데이터를 전달해보자.&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;&lt;b&gt;JSON형식 전송&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;객체로 전송하기 위한 HelloData class생성&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1724478004875&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package hello.servlet.basic;

import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class HelloData {
    private String username;
    private int age;

}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1724477992978&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package hello.servlet.basic.request;

import com.fasterxml.jackson.databind.ObjectMapper;
import hello.servlet.basic.HelloData;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

@WebServlet(name = &quot;requestBodyJsonServlet&quot;, urlPatterns = &quot;/request-body-json&quot;)
public class RequestBodyJsonServlet extends HttpServlet {

    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletInputStream inputStream = req.getInputStream();
        String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

        System.out.println(&quot;messageBody = &quot; + messageBody);

        HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
        System.out.println(&quot;helloData = &quot; + helloData.getUsername());
        System.out.println(&quot;helloData = &quot; + helloData.getAge());


    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;참고&lt;/b&gt;&lt;b&gt;JSON 결과를 파싱해서 사용할 수 있는 자바 객체로 변환하려면 Jackson, Gson과 같은 JSON 변환 라이브러리를 추가해서 사용해야 한다. 스프링 부트로 Spring MVC를 선택하면 기본으로 Jackson 라이브러리(ObjectMapper)를 함께 제공한다.&lt;/b&gt;&lt;b&gt;참고 &lt;/b&gt;&lt;b&gt;HTML form 데이터도 메시지 바디를 통해 전송되므로 직접 읽을 수 있다. 하지만 편리한 파라미터 조회 기능(request.getParamger(...))을 이미 제공하기 때문에 파라미터 조회 기능을 사용하면 된다.&lt;/b&gt;&lt;/p&gt;</description>
      <author>범진연습장</author>
      <guid isPermaLink="true">https://bj-practice.tistory.com/120</guid>
      <comments>https://bj-practice.tistory.com/120#entry120comment</comments>
      <pubDate>Sat, 24 Aug 2024 14:46:32 +0900</pubDate>
    </item>
    <item>
      <title>HTTP 요청 데이터 -API 메시지 바디 - 단순 텍스트</title>
      <link>https://bj-practice.tistory.com/119</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP message body에 데이터를 직접 담아서 요청&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP API 에서 주로 사용 JSON, XML, TEXT&lt;/li&gt;
&lt;li&gt;데이터 형식은 주로 JSON 사용&lt;/li&gt;
&lt;li&gt;POST, PUT, PATCH&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-먼저 가장 단순한 텍스트 메시지를 HTTP 메시지 바디에 담아서 전송하고 읽어보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-HTTP메시지 바디의 데이터를 InputStream을 사용해서 직접 읽을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1724477270843&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package hello.servlet.basic.request;

import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

@WebServlet(name = &quot;RequestBodyStringServlet&quot;, urlPatterns = &quot;/request-body-string&quot;)
public class RequestBodyStringServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletInputStream inputStream = req.getInputStream();
        String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);//바이트를 문자열로 바꿀때는 인코딩 정보를 알려주어야함

        System.out.println(&quot;messageBody = &quot; + messageBody);

        resp.getWriter().write(&quot;ok&quot;);


    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1106&quot; data-origin-height=&quot;672&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRv2lX/btsJdyAbujT/b3UTxKe7ktt5WwWay76nJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRv2lX/btsJdyAbujT/b3UTxKe7ktt5WwWay76nJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRv2lX/btsJdyAbujT/b3UTxKe7ktt5WwWay76nJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRv2lX%2FbtsJdyAbujT%2Fb3UTxKe7ktt5WwWay76nJk%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;1106&quot; height=&quot;672&quot; data-origin-width=&quot;1106&quot; data-origin-height=&quot;672&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결과&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1797&quot; data-origin-height=&quot;241&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cPCFpQ/btsJdoEnPrU/d4Eahykw9baIXgY6qkGKc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cPCFpQ/btsJdoEnPrU/d4Eahykw9baIXgY6qkGKc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cPCFpQ/btsJdoEnPrU/d4Eahykw9baIXgY6qkGKc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcPCFpQ%2FbtsJdoEnPrU%2Fd4Eahykw9baIXgY6qkGKc0%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;1797&quot; height=&quot;241&quot; data-origin-width=&quot;1797&quot; data-origin-height=&quot;241&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Spring 백엔드 핵심 기술/servlet</category>
      <author>범진연습장</author>
      <guid isPermaLink="true">https://bj-practice.tistory.com/119</guid>
      <comments>https://bj-practice.tistory.com/119#entry119comment</comments>
      <pubDate>Sat, 24 Aug 2024 14:28:56 +0900</pubDate>
    </item>
  </channel>
</rss>