<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Eco 의 개발일기</title>
    <link>https://gangda.tistory.com/</link>
    <description>가나강다(ganagda)</description>
    <language>ko</language>
    <pubDate>Sat, 11 Jul 2026 11:39:37 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Eco</managingEditor>
    <item>
      <title>MockTest 간단 사용법 (RestDocs 를 위한)</title>
      <link>https://gangda.tistory.com/38</link>
      <description>&lt;article id=&quot;038ec325-45d9-4269-96b2-679fcdece61c&quot; class=&quot;page sans Notion_P&quot;&gt;&lt;div class=&quot;page-body&quot;&gt;&lt;h3 id=&quot;d9555b2b-778f-47f5-91c3-2e3a6d18d39e&quot; class=&quot;&quot;&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;&amp;lt;피드백 언제나 환영합니다! 댓글 감사합니다&amp;gt;&lt;/mark&gt;&lt;/h3&gt;&lt;p id=&quot;67ab8d7d-69d8-4c77-b4bb-78398a8f9cf3&quot; class=&quot;&quot;&gt;&lt;a href=&quot;https://gangda.tistory.com/37&quot;&gt;Spring swagger 3.0.0 설정&lt;/a&gt; 에서 사용한 repository를 그대로 따라갈 예정 입니다. 기본적인 RestDocs 사용법 이 끝난 이후는 Test 부분을 다뤄 볼 예정 입니다.&lt;/p&gt;&lt;h2 id=&quot;61550eb3-57e8-4d9f-9c90-c0599abf1b2b&quot; class=&quot;&quot;&gt;Mock 이란?&lt;/h2&gt;&lt;ul id=&quot;32df13ad-ad42-4937-9f52-0b412e726581&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;실제 객체를 만들어 사용하기에 시간, 비용등이 높거나 객체 서로간의 의존성이 강해 힘들경우 가짜 객체를 만들어 사용하는 방법&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;c15b7922-ed1e-4994-a284-aa81dfbf4a09&quot; class=&quot;&quot;&gt;실제 Spring Web 을 이용한 Controller 부분 이나 Service 부분이 이해 해당됩니다 조금더 구체적으로 말하면 네트워크 데이터베이스등, 단위 테스트가
어려울때 즉, 시스템의 다른 부분에 많이 얽혀 있고 의존해 있다면 &lt;del&gt;고려해볼만 합니다.&lt;/del&gt; 사용해야 합니다.&lt;/p&gt;&lt;h2 id=&quot;fc227878-6a6f-4be2-8056-6b6a0babee48&quot; class=&quot;&quot;&gt;라이브러리 추가&lt;/h2&gt;&lt;pre id=&quot;5dbcce64-1c01-46bf-80fd-f47c9d805b97&quot; class=&quot;code&quot;&gt;&lt;code&gt;//build.gradle
dependencies {
	  ....
    testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
		....
}&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;2fb6cb33-884a-4c17-b525-1ea7f81b9265&quot; class=&quot;&quot;&gt;&lt;strong&gt;Mock을 통해 유닛 테스트하기&lt;/strong&gt;&lt;/h2&gt;&lt;p id=&quot;9824fb99-cf3c-4768-9da9-627af8ca8aa1&quot; class=&quot;&quot;&gt;테스트를 하기전 기존의 코드에 간단하게 추가해야할 부분이 있어 추가 할 예정 입니다.&lt;/p&gt;&lt;ul id=&quot;9e19343c-5578-4a99-82a8-59a52a6bc63a&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;TestController.java&lt;/summary&gt;&lt;pre id=&quot;62c70f6a-d8fa-4f80-b8da-fb169b27f290&quot; class=&quot;code&quot;&gt;&lt;code&gt;....
@RestController
public class TestController {

    @Autowired
    private TestUserService userService;

    @PostMapping(value = &quot;/user&quot;)
    public UserDto helloUser(@RequestBody UserDto userDto){
        return userService.createUserDto(userDto);
    }

		@GetMapping(value = &quot;/userInformation/{id}&quot;)
    public UserDto userInformation(@PathVariable Integer id){
        return userService.findUserDto(id);
    }
	....
}&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;dc780c58-1c03-4e48-923f-c6f5c7e28df6&quot; class=&quot;&quot;&gt;UserDto 를 이용하여 User 를 등록하는 Controller를 추가 해 줍니다. → Controller 를 통하여 등록 과 조회를 두부분을 나누어 이야기 해볼 생각입니다.&lt;/p&gt;&lt;ul id=&quot;f44d5914-604c-4374-a53f-e7a8342ccc1f&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;TestUserService.java&lt;/summary&gt;&lt;pre id=&quot;7c00c239-eb0a-49f5-ab4a-a4c551bf3558&quot; class=&quot;code&quot;&gt;&lt;code&gt;@Service
public class TestUserService {
    private static final Map&amp;lt;Integer, UserDto&amp;gt; USER_DTO_MAP = new HashMap&amp;lt;&amp;gt;();

    public UserDto createUserDto(UserDto userDto) {
        if(USER_DTO_MAP.containsKey(userDto.getId())){
            throw new IllegalArgumentException(&quot;중복 Id&quot;);
        }
        USER_DTO_MAP.put(userDto.getId(), userDto);
        return userDto;
    }

    public UserDto findUserDto(Integer id) {
        return USER_DTO_MAP.get(id);
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;46112baa-ce12-4ada-b5a2-3c9923bfb5e8&quot; class=&quot;&quot;&gt;DB 연동의 경우 설정 부분이 많아 간소화 하여, Map 형태로 관리하는 형식으로 지정 해둡니다.&lt;/p&gt;&lt;p id=&quot;c214a74c-b793-48b4-9fd2-f1d8ef7214df&quot; class=&quot;&quot;&gt;위의 두 코드가 추가가 되었다면 test 모듈에서 TestController 에 대한 Test 를 만들어 줍니다.&lt;/p&gt;&lt;ul id=&quot;f8981888-2060-498f-9910-41caae1fc759&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;TestControllerTest.java&lt;/summary&gt;&lt;pre id=&quot;869516b9-de9a-4587-b989-f099cd0dc215&quot; class=&quot;code&quot;&gt;&lt;code&gt;//@SpringBootTest
@WebMvcTest(TestController.class)
@AutoConfigureRestDocs
class TestControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @MockBean
    private TestUserService userService;

    private UserDto getUserDto(String hello_MockTest) {
        UserDto userDto = new UserDto();
        userDto.setStatus(true);
        userDto.setId(1);
        userDto.setCreateAt(LocalDateTime.now());
        userDto.setName(hello_MockTest);
        return userDto;
    }

    @Test
    public void mockMvcTestCreate() throws Exception {
        UserDto userDto = getUserDto(&quot;MockTest&quot;);

        given(userService.createUserDto(userDto)).willReturn(userDto);

        String content = objectMapper.writeValueAsString(userDto);

        ResultActions perform = mockMvc.perform(post(&quot;/user&quot;)
                .content(content)
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON));

        perform.andExpect(status().isOk())
                .andExpect(jsonPath(&quot;$.id&quot;).exists())
                .andExpect(jsonPath(&quot;$.name&quot;).value(userDto.getName()))
                .andDo(print());
    }

    @Test
    public void mockMvcTestFind() throws Exception {
        UserDto userDto = getUserDto(&quot;MockTest&quot;);

        given(userService.createUserDto(userDto)).willReturn(userDto);
        when(userService.findUserDto(userDto.getId())).thenReturn(userDto);

        ResultActions perform = mockMvc.perform(get(&quot;/userInformation/{id}&quot;, 1)
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON));

        perform.andExpect(status().isOk())
                .andExpect(jsonPath(&quot;$.id&quot;).exists())
                .andExpect(jsonPath(&quot;$.name&quot;).value(userDto.getName()))
                .andDo(print());
    }&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;ef82c79e-bc3c-47cd-ab43-7def15f4ad4c&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;//@SpringBootTest → MockTest를 할때 Spring 을 사용해야해서 켜놓을거라 생각하지만 실제 
&lt;code&gt;IllegalStateException: Configuration error:found multiple declarations of @BootstrapWith&lt;/code&gt; 에러를 발생 시킵니다.&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;df95e52f-fd56-47ee-9235-67309212ae20&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;@WebMvcTest(TestController.class) → MockTest 시 반드시 써야 하는 부분이며 해당 Controller 또는 Service를 적어 사용 하면 됩니다.
&lt;code&gt;@SpringBootTest&lt;/code&gt; 와 함께 쓰면 안되는데 이유는 이 어노테이션 안에도 &lt;code&gt;@BootstrapWith&lt;/code&gt; 가 내장되어 있어 중복 설정 오류를 발생 시킵니다.&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;fdca5bc2-25d3-4bc5-87a4-08981fc4d1ca&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;@AutoConfigureRestDocs → 후 Rest docs 로 Swagger와 연계하기위해 만들어둔 어노테이션 입니다. (후에 RestDocs 에 다루겠습니다.)&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;589127ef-cab0-414d-83fd-4aa1a2194f10&quot; class=&quot;&quot;&gt;
&lt;/p&gt;&lt;p id=&quot;4954ac28-942d-473b-9405-f814e21479d2&quot; class=&quot;&quot;&gt;Controller 에서 새로 추가된 두 method 만 테스트를 진행 하였으며 간략히 살펴보겠습니다.&lt;/p&gt;&lt;p id=&quot;14d8cc0a-a9c0-456f-a2be-4fba943d4461&quot; class=&quot;&quot;&gt;(MockTest 의 경우 static으로 추가된 부분이 많습니다. 어떤 부분을 사용하였는지 적어 놓을 예정입니다.)&lt;/p&gt;&lt;pre id=&quot;6423c9d7-e4a6-421f-925e-f78c977401da&quot; class=&quot;code&quot;&gt;&lt;code&gt;@Test
    public void mockMvcTestCreate() throws Exception {
        UserDto userDto = getUserDto(&quot;MockTest&quot;);

        given(userService.createUserDto(userDto)).willReturn(userDto);

        String content = objectMapper.writeValueAsString(userDto);

        ResultActions perform = mockMvc.perform(post(&quot;/user&quot;)
                .content(content)
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON));

        perform.andExpect(status().isOk())
                .andExpect(jsonPath(&quot;$.id&quot;).exists())
                .andExpect(jsonPath(&quot;$.name&quot;).value(userDto.getName()))
                .andDo(print());
    }&lt;/code&gt;&lt;/pre&gt;&lt;ul id=&quot;a42bde03-15bc-4579-af74-e35cbad0149f&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;given() → &lt;code&gt;import static org.mockito.BDDMockito.&lt;/code&gt;&lt;code&gt;&lt;em&gt;given&lt;/em&gt;&lt;/code&gt;&lt;code&gt;;&lt;/code&gt;&lt;ul id=&quot;f6cd56b6-8081-48de-a49f-bebedd8acf11&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;mock 에서 가로채 실제 url 이 호출될때 작업해야하는걸 잡아 둡니다. &lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;55f46371-11ba-4493-b073-393ccca34af4&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;mock 객체의 동작을 미리 정의 하여 리턴되는 값을 미리 생성 합니다&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;f17a544a-6e04-4905-abbb-b497ada370bf&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;perform() → Rest 를 정의하고 들어가는 url을 정의합니다.&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;b498d5eb-001a-47d8-bd4d-84cb2bcd51fa&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;post() → &lt;code&gt;org.springframework.test.web.servlet.request.MockMvcRequestBuilders.&lt;/code&gt;&lt;code&gt;&lt;em&gt;post&lt;/em&gt;&lt;/code&gt;&lt;code&gt;;&lt;/code&gt; → &lt;code&gt;MockMvcRequestBuilders&lt;/code&gt; 로 간단히 표시&lt;ul id=&quot;6ce408f3-a937-4114-aa9c-ead8adff5da1&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;Rest 중 post 로 정의하고 url 을 정의합니다.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;3a2921e9-3fd5-47e9-bc1c-5331b49aa814&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;status() → &lt;code&gt;MockMvcRequestBuilders&lt;/code&gt; &lt;ul id=&quot;c2d22c87-4c90-473e-b2df-8b9c03fcffd1&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;HTTP의 상태 코드 값을 정의 합니다.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;485ec29d-dcee-4524-a5d6-51646ed9b838&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;jsonPath() → &lt;code&gt;MockMvcRequestBuilders&lt;/code&gt; &lt;ul id=&quot;1d740edd-4c1b-4659-8a79-f55bf98e1f11&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;결과 값이 json 형태로 왔을시 $ 를 이용하여 json 값을 표현할 수 있습니다.&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;ce6021e0-214f-4803-995e-bc498d9c3e5b&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;$.{…} → {…} depthLevel 을 뜻하며 json 값들을 호출하여 불러올 수 있습니다.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre id=&quot;a5dd8909-ddc6-4fc1-a367-3aa79206bb37&quot; class=&quot;code&quot;&gt;&lt;code&gt;@Test
    public void mockMvcTestFind() throws Exception {
        UserDto userDto = getUserDto(&quot;MockTest&quot;);

        given(userService.createUserDto(userDto)).willReturn(userDto);
        when(userService.findUserDto(userDto.getId())).thenReturn(userDto);

        ResultActions perform = mockMvc.perform(get(&quot;/userInformation/{id}&quot;, 1)
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON));

        perform.andExpect(status().isOk())
                .andExpect(jsonPath(&quot;$.id&quot;).exists())
                .andExpect(jsonPath(&quot;$.name&quot;).value(userDto.getName()))
                .andDo(print());
    }&lt;/code&gt;&lt;/pre&gt;&lt;ul id=&quot;30788cbe-769d-4d66-a013-82fe37fc488b&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;when() → &lt;code&gt;MockMvcRequestBuilders&lt;/code&gt; &lt;ul id=&quot;226084d8-a63c-472c-b3a5-adcf53c777e4&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;mock 에서 when 안에 동작을 할때 return 으로 어떤 값을 내보내는지 정의 하기 위함입니다.&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;1d53ed34-5682-467d-859c-48d47b496ef9&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;실제 mock 에서 url 이 호출 될때 when 동작을 통해 값을 확인할때 사용 합니다.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;85bf017f-7b3d-4a82-8e74-d3fc8e890d8c&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;get() → &lt;code&gt;MockMvcRequestBuilders&lt;/code&gt; &lt;ul id=&quot;56c8255a-87d5-4877-9f73-4dc7728fc99d&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;Rest 중 get으로 정의하고 url 을 정의합니다.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;9e2c88e9-f65c-472f-b566-fe0fd7c3d306&quot; class=&quot;&quot;&gt;
&lt;/p&gt;&lt;p id=&quot;5aac3721-d316-4e7f-9958-69dbbf468906&quot; class=&quot;&quot;&gt;github 코드 : &lt;a href=&quot;https://github.com/Eco-Min/Swagger&quot;&gt;https://github.com/Eco-Min/Swagger&lt;/a&gt;&lt;/p&gt;&lt;div class=&quot;n2t_comment&quot;&gt;&lt;p&gt;
&lt;/p&gt;&lt;p class=&quot;block-color-gray&quot;&gt;&lt;a href=&quot;https://boltlessengineer.github.io/Notion2Tistory&quot;&gt;Uploaded by Notion2Tistory v1.1.0&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/article&gt;</description>
      <category>SPRING/Spring Boot</category>
      <author>Eco</author>
      <guid isPermaLink="true">https://gangda.tistory.com/38</guid>
      <comments>https://gangda.tistory.com/38#entry38comment</comments>
      <pubDate>Tue, 28 Jun 2022 01:36:19 +0900</pubDate>
    </item>
    <item>
      <title>Spring swagger 3.0.0 설정</title>
      <link>https://gangda.tistory.com/37</link>
      <description>&lt;article id=&quot;54858678-ca5f-49e3-95e0-b3dd2f3d3838&quot; class=&quot;page sans Notion_P&quot;&gt;&lt;div class=&quot;page-body&quot;&gt;&lt;h3 id=&quot;8424512c-8bab-49e0-9d38-cb914b949d77&quot; class=&quot;&quot;&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;&amp;lt;피드백 언제나 환영합니다! 댓글 감사합니다&amp;gt;&lt;/mark&gt;&lt;/h3&gt;&lt;p id=&quot;3d564151-1807-47c5-87ca-9eab58fce275&quot; class=&quot;&quot;&gt;swagger는 RestFul APi → OpenAPI 스펙을 기준으로 문서화 해서 HTML 페이지로 바꿔주는 역활을 합니다. &lt;/p&gt;&lt;p id=&quot;7ecf283a-2b19-4345-9672-dab404377179&quot; class=&quot;&quot;&gt;저는 3.0.0 을 기준으로 작성하였으며 2.X.X 의 경우 조금 다릅니다. 아래 springfox 문서를 통해서 작성했으며 간단하게 알아보도록 하겠습니다.&lt;/p&gt;&lt;figure id=&quot;e971257d-8f92-419f-a8b6-26f4e8411aa0&quot;&gt;&lt;a href=&quot;https://springfox.github.io/springfox/docs/current/&quot; class=&quot;bookmark source&quot;&gt;&lt;div class=&quot;bookmark-info&quot;&gt;&lt;div class=&quot;bookmark-text&quot;&gt;&lt;div class=&quot;bookmark-title&quot;&gt;Springfox Reference Documentation&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;bookmark-href&quot;&gt;https://springfox.github.io/springfox/docs/current/&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;&lt;h3 id=&quot;08dda2fe-2fbe-4a1e-b529-9812539eb0a7&quot; class=&quot;&quot;&gt;Spring 설정&lt;/h3&gt;&lt;ul id=&quot;c18ec782-5662-44c5-94ad-a5947501a512&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;spring 2.7.0&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;86385cc7-c90a-460c-a1da-20385556062e&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;java 17&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;8fabdf4e-87c5-406e-9bed-63e6e9361c20&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;dependency : Spring Web, Lombok&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;4dd3e002-ebaa-421b-9bf5-1652c95bece8&quot; class=&quot;&quot;&gt;dependency 는 하나씩 추가하면서 해보도록 하겠습니다.&lt;/p&gt;&lt;h3 id=&quot;aecc1998-dd8f-4e2e-a7ae-29546c8a4814&quot; class=&quot;&quot;&gt;라이브러리 추가&lt;/h3&gt;&lt;pre id=&quot;c5ba9fc9-2172-45dd-88a5-693cb14d8334&quot; class=&quot;code&quot;&gt;&lt;code&gt;....
dependencies {
    ....
	  // https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui
    implementation 'io.springfox:springfox-swagger-ui:3.0.0'
    // https://mvnrepository.com/artifact/io.springfox/springfox-boot-starter
    implementation 'io.springfox:springfox-boot-starter:3.0.0'
}
....&lt;/code&gt;&lt;/pre&gt;&lt;p id=&quot;7ab60bdd-98e2-4ca6-8615-0373003af4bd&quot; class=&quot;&quot;&gt;3.0.0 버전을 사용했으며 UI 및 기타 설정시 2.X.X 버전과 다를수 있습니다.&lt;/p&gt;&lt;pre id=&quot;cbabd598-b832-41df-8acc-6e376ebdbacd&quot; class=&quot;code&quot;&gt;&lt;code&gt;* Swagger 버전에 따른 UI URL 체크* 
2.X.X  :  http://localhost:8080/swagger-ui.html
3.X.X  :  http://localhost:8080/swagger-ui/index.html&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;54e6cb22-4e19-4821-b52f-2ecc61cfa2c9&quot; class=&quot;&quot;&gt;간단한 코드 작성&lt;/h3&gt;&lt;ul id=&quot;34faab56-6519-45f5-a093-c6db33ed5b98&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;SwaggerConfig.java&lt;/summary&gt;&lt;pre id=&quot;de27a8b8-cd31-43f6-9238-e0b005600040&quot; class=&quot;code&quot;&gt;&lt;code&gt;package com.example.swagger_restdocs.swagger;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    private final static String API_NAME = &quot;Swagger_Study API&quot;;
    private final static String API_VERSION = &quot;0.0.1&quot;;
    private final static String API_DESCRIPTION = &quot;Swagger_Study API 명세서&quot;;

    @Bean
    public Docket api(){
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build().apiInfo(apiInfo());
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title(API_NAME)
                .description(API_DESCRIPTION)
                .version(API_VERSION)
                .build();
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;4eacd71c-1b39-435a-832b-5c09e1ed8e00&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;@EnableSwagger2 → Swagger2 활성화&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;b64ba792-2a50-49f4-9d22-d26f77807912&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;new Docket(DocumentationType.SWAGGER_2).select() → API 에 사용되는 builder 생성 입니다.&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;ad3c5469-b72b-4c18-8d9a-2be70223b324&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;apis() → RequestHandlerSelectors 를 이용 api 스펙이 작성되는 즉, Controller 부 basepackage를 지정 합니다.&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;ab3313dd-0757-4027-9f96-fcacd1ef1fa8&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;paths() → PathSelectors를 이용 apis() 에 선택된 스팩들중 특정 path 조건을 다시 필터링 합니다.&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;a2fedd11-acee-4a83-bbb1-7aae17b927ea&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;ApiInfo → Swagger에 사용되는 title, description, version 등이 사용이됩니다.&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;72913d96-7f93-4ff3-b624-4ae87b827a76&quot; class=&quot;&quot;&gt;위 관련 설정은 가장 기본적인 설정이며 지금은 저런 설정이 있다 정도만 알아둘 예정입니다. (나중에 조금더 심층적으로 파보겠습니다.)&lt;/p&gt;&lt;p id=&quot;fbdfad4d-2c34-42d1-bf25-e61febf60625&quot; class=&quot;&quot;&gt;⨳위 설정후 Swagger UI를 통해 기본적인 UI를 확인할수 있습니다. 하지만 3.0.0 부터는 빌드시 Err 가 발생합니다.&lt;/p&gt;&lt;pre id=&quot;d26a9468-7b8d-4915-b84b-baa98ab492a6&quot; class=&quot;code&quot;&gt;&lt;code&gt;org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; 
nested exception is java.lang.NullPointerException: Cannot invoke 
&quot;org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getPatterns()&quot; because &quot;this.condition&quot; is null
// 위 같이 Err 발생시 application.yml 파일에 설정을 해야할게 하나 있습니다.&lt;/code&gt;&lt;/pre&gt;&lt;pre id=&quot;b5191d50-2096-43fc-ae7d-a7b15f97299f&quot; class=&quot;code&quot;&gt;&lt;code&gt;spring:
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher&lt;/code&gt;&lt;/pre&gt;&lt;ul id=&quot;68dfa61a-b581-4cff-b7d0-ce5bab03d92c&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;TestController.java&lt;/summary&gt;&lt;pre id=&quot;9a3c2109-5d31-432a-bab2-0761da425b59&quot; class=&quot;code&quot;&gt;&lt;code&gt;package com.example.swagger_restdocs.controller;

import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@RestController
public class TestController {

    @ApiOperation(value = &quot;user&quot;, notes = &quot;user 정보&quot;)
    @GetMapping(value = &quot;/user&quot;)
    public UserDto helloUser(){
        UserDto userDto = new UserDto();
        userDto.setId(5);
        userDto.setName(&quot;hello&quot;);
        userDto.setStatus(true);
        userDto.setCreateAt(LocalDateTime.now());
        return userDto;
    }

    @ApiOperation(value = &quot;paramSample&quot;, notes = &quot;테스트입니다&quot;)
    @ApiResponses({
            @ApiResponse(code = 200, message = &quot;ok&quot;),
            @ApiResponse(code = 404, message = &quot;페이지 못찾음&quot;)
    })
    @GetMapping(value = &quot;/paramSample&quot;)
    public Map&amp;lt;String, String&amp;gt; selectBoard(@ApiParam(value = &quot;샘플번호&quot;, required = true, example = &quot;1&quot;)
                                           @RequestParam String no) {

        Map&amp;lt;String, String&amp;gt; result = new HashMap&amp;lt;&amp;gt;();
        result.put(no, &quot;테스트&quot;);
        result.put(&quot;test contents&quot;, &quot;테스트 내용&quot;);
        return  result;
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;ba0ef9de-e9af-4477-88d5-4429c0d4f231&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;UserDto.java&lt;/summary&gt;&lt;pre id=&quot;9de35cf8-346c-438b-bf34-c3b7ba099725&quot; class=&quot;code code-wrap&quot;&gt;&lt;code&gt;package com.example.swagger_restdocs.controller;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;

@Data
public class UserDto {
    @ApiModelProperty(example = &quot;유저 아이디&quot;)
    private Integer id;
    @ApiModelProperty(example = &quot;유저 이름&quot;)
    private String name;
    private boolean status;
    private LocalDateTime createAt;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;c05e8868-190f-4afe-8581-6ce08d438081&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;@ApiOperation → 어노테이션을 API에 추가해 API에 대한 주석을 달 수 있음(옵션)&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;b6167e50-8c53-4799-8a23-c55d6397a990&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;@ApiResponses → response 상태 값에 따라 설명을 적어놓는 있다&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;e7680af4-a5b9-404a-bb49-4a29fb846ffd&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;@ApiParam → @RequestParam 시 필요한 부분을 테스트 할수 있도록 적어 놓은 부분&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;bc17300e-48e5-4374-8428-8ac43b82645e&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;@ApiModelProperty → Dto 들의 값(JSON) 표현시 사용되는 일종의 값&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;3e4c3981-9160-421f-8954-c043e955ad97&quot; class=&quot;&quot;&gt;
&lt;/p&gt;&lt;h3 id=&quot;3fedf4b0-7150-4824-b1a4-72436226936b&quot; class=&quot;&quot;&gt;Swagger UI&lt;/h3&gt;&lt;div id=&quot;91c5c737-af4d-49ff-8fc8-0203b2c511cb&quot; class=&quot;column-list&quot;&gt;&lt;div id=&quot;6129ba16-2db3-4a55-8385-e084989c36a9&quot; style=&quot;width:50%&quot; class=&quot;column&quot;&gt;&lt;figure id=&quot;3afd1323-d00f-438e-bf44-dd9cd7c66686&quot; class=&quot;image&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dQpUfN/btrFseqanlv/0HrCIXupYoylHwuQ45JInK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dQpUfN/btrFseqanlv/0HrCIXupYoylHwuQ45JInK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dQpUfN/btrFseqanlv/0HrCIXupYoylHwuQ45JInK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdQpUfN%2FbtrFseqanlv%2F0HrCIXupYoylHwuQ45JInK%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/figure&gt;&lt;/div&gt;&lt;div id=&quot;eeecfe68-ded9-4445-afa8-9945d6703de6&quot; style=&quot;width:50%&quot; class=&quot;column&quot;&gt;&lt;figure id=&quot;8150ba4a-e498-497a-97d9-437e79478df8&quot; class=&quot;image&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brOEML/btrFoZ11Fxf/OLjflpJlcbSzHd6PHqAtb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brOEML/btrFoZ11Fxf/OLjflpJlcbSzHd6PHqAtb0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brOEML/btrFoZ11Fxf/OLjflpJlcbSzHd6PHqAtb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrOEML%2FbtrFoZ11Fxf%2FOLjflpJlcbSzHd6PHqAtb0%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/div&gt;&lt;p id=&quot;76089fd4-8668-4de8-a482-869884390ccd&quot; class=&quot;&quot;&gt;위 그림처럼 표현 되며 페이지에 Rest Api 가 문서화 되서 생성이 된다. 주요 할점은 2.X.X 랑 3.0.0의 URL 주소 방식이 다르기 때문에 꼭 비교하면서 써야한다.&lt;/p&gt;&lt;p id=&quot;1eb67d65-42db-4651-bfe9-c395dcae8e71&quot; class=&quot;&quot;&gt;github 코드 : &lt;a href=&quot;https://github.com/Eco-Min/Swagger&quot;&gt;https://github.com/Eco-Min/Swagger&lt;/a&gt;&lt;/p&gt;&lt;div class=&quot;n2t_comment&quot;&gt;&lt;p&gt;
&lt;/p&gt;&lt;p class=&quot;block-color-gray&quot;&gt;&lt;a href=&quot;https://boltlessengineer.github.io/Notion2Tistory&quot;&gt;Uploaded by Notion2Tistory v1.1.0&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/article&gt;</description>
      <category>SPRING/Spring Boot</category>
      <author>Eco</author>
      <guid isPermaLink="true">https://gangda.tistory.com/37</guid>
      <comments>https://gangda.tistory.com/37#entry37comment</comments>
      <pubDate>Wed, 22 Jun 2022 01:52:15 +0900</pubDate>
    </item>
    <item>
      <title>Notion 블로그 (Tistory 이전)</title>
      <link>https://gangda.tistory.com/36</link>
      <description>&lt;article id=&quot;b8915040-3201-4691-bf1d-1ac50490bf82&quot; class=&quot;page sans Notion_P&quot;&gt;&lt;div class=&quot;page-body&quot;&gt;&lt;p id=&quot;45d3bd2b-c7be-4999-8313-30feb0e4863b&quot; class=&quot;&quot;&gt;티스토리 쓰기전 Notion에 미리 공부하기위해 적어 놓은 것들이 있습니다. (notion 못버려...)&lt;/p&gt;&lt;p id=&quot;48504abc-ce39-4b3f-93f9-9eadb8225c7d&quot; class=&quot;&quot;&gt;혹시나 도움이 될까봐 올려 놓겠습니다.&lt;/p&gt;&lt;p id=&quot;139dc9ab-18a5-414d-a66f-bdd328568525&quot; class=&quot;&quot;&gt;&lt;mark class=&quot;highlight-red&quot;&gt;&lt;em&gt;&lt;strong&gt;&amp;lt;피드백 언제나 환연합니다 -&amp;gt; Notion은 댓글 기능이 없으므로 여기에 피드백 부탁 드립뉘당...&amp;gt;&lt;/strong&gt;&lt;/em&gt;&lt;/mark&gt;&lt;/p&gt;&lt;figure id=&quot;88302866-ae5b-4389-8cef-8daef05aa94b&quot;&gt;&lt;a href=&quot;https://just-musician-4e4.notion.site/0d03987b0bae4d418378b134b3fa4db1?v=ecbbcbb2362e4e8abdfd160e2e86f9c7&quot; class=&quot;bookmark source&quot;&gt;&lt;div class=&quot;bookmark-info&quot;&gt;&lt;div class=&quot;bookmark-text&quot;&gt;&lt;div class=&quot;bookmark-title&quot;&gt;Eco_Min 블로그&lt;/div&gt;&lt;div class=&quot;bookmark-description&quot;&gt;티스토리 블로그 : https://gangda.tistory.com → 많이 와주세요..&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;bookmark-href&quot;&gt;https://just-musician-4e4.notion.site/0d03987b0bae4d418378b134b3fa4db1?v=ecbbcbb2362e4e8abdfd160e2e86f9c7&lt;/div&gt;&lt;/div&gt;&lt;img src=&quot;https://just-musician-4e4.notion.site/image/https%3A%2F%2Fjust-musician-4e4.notion.site%2Fimages%2Fpage-cover%2Fnasa_transonic_tunnel.jpg?table=collection&amp;amp;id=8819682c-b2e4-4ccc-aec3-405b5a01ed87&amp;amp;spaceId=ca94b917-0da4-4a05-a178-7677c58e14b4&amp;amp;width=2000&amp;amp;userId=&amp;amp;cache=v2&quot; class=&quot;bookmark-image&quot;&gt;&lt;/a&gt;&lt;/figure&gt;&lt;p id=&quot;61dd47aa-014d-43bc-86fc-d7d49cb857af&quot; class=&quot;&quot;&gt;
&lt;/p&gt;&lt;div class=&quot;n2t_comment&quot;&gt;&lt;p&gt;
&lt;/p&gt;&lt;p class=&quot;block-color-gray&quot;&gt;&lt;a href=&quot;https://boltlessengineer.github.io/Notion2Tistory&quot;&gt;Uploaded by Notion2Tistory v1.1.0&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/article&gt;</description>
      <category>공지사항</category>
      <author>Eco</author>
      <guid isPermaLink="true">https://gangda.tistory.com/36</guid>
      <comments>https://gangda.tistory.com/36#entry36comment</comments>
      <pubDate>Tue, 14 Jun 2022 22:51:48 +0900</pubDate>
    </item>
    <item>
      <title>MS_SQL 에서 쿼리가 너무 늦게 나가요&amp;hellip;</title>
      <link>https://gangda.tistory.com/35</link>
      <description>&lt;article id=&quot;89fa51ba-2eaf-48cd-8473-d2b9c9589f6a&quot; class=&quot;page sans Notion_P&quot;&gt;&lt;div class=&quot;page-body&quot;&gt;&lt;h3 id=&quot;a08b7daa-c9c4-4993-bef5-f714bab8578b&quot; class=&quot;&quot;&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;&amp;lt;피드백 언제나 환영합니다! 댓글 감사합니다&amp;gt;&lt;/mark&gt;&lt;/h3&gt;&lt;p id=&quot;ae7869cc-3c1b-4da4-b539-7204f0ca0b16&quot; class=&quot;&quot;&gt;쿼리에 인덱싱을 걸어서 사용하였음에도 불구하고 DB 속도가 너무 늦게 나오네요 분명 DB tool 에서 조회시에는 느리지 않았는데..&lt;/p&gt;&lt;p id=&quot;e8047836-df81-470e-b3da-19814ff5d341&quot; class=&quot;&quot;&gt;그래서 검색 해본결과 MS_SQL 은 성능을 추적 할 수 있는 도구가 있어서 실행 해보았습니다.&lt;/p&gt;&lt;blockquote id=&quot;236e8d8e-c179-4b09-aff8-0d69bb1d0096&quot; class=&quot;&quot;&gt;Profileing 하는 법은 아래 두 블로그를 보고 확인 하였습니다.&lt;/blockquote&gt;&lt;ul id=&quot;154755e7-ae63-4c70-bf74-e5e553431913&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;a href=&quot;https://vitalholic.tistory.com/329&quot;&gt;[MS_SQL] 프로파일러 사용법 (tistory.com)&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;66fb6781-58db-4af3-ab42-aa383b69df6b&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;a href=&quot;https://bebeya.tistory.com/entry/MSSQL-%ED%94%84%EB%A1%9C%ED%8C%8C%EC%9D%BC%EB%9F%ACProfiler-%EC%8B%A4%ED%96%89-%EC%BF%BC%EB%A6%AC-%EC%B6%94%EC%A0%81-%EC%82%AC%EC%9A%A9%EB%B2%95&quot;&gt;[MSSQL] 프로파일러(Profiler) 실행 &amp;amp; 쿼리 추적 사용법 (tistory.com)&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;e5649f83-d230-40d1-9888-d27acbd1a776&quot; class=&quot;&quot;&gt;확인 해보니 varchar 로 지정 하던 것이 nvarchar로 나가게 되면서 인덱싱 또한 깨지게 됩니다.
관련 검색중 &lt;mark class=&quot;highlight-brown&quot;&gt;&lt;code&gt;우아한 형제 블로그&lt;/code&gt;&lt;/mark&gt;&lt;mark class=&quot;highlight-brown&quot;&gt; &lt;/mark&gt;에서 저와 비슷한 증상이 있어 적용해 보니 해결이 되었습니다. &lt;/p&gt;&lt;figure id=&quot;330f88ad-12cf-4ac4-a439-f4f427393ab8&quot;&gt;&lt;a href=&quot;https://techblog.woowahan.com/2605/&quot; class=&quot;bookmark source&quot;&gt;&lt;div class=&quot;bookmark-info&quot;&gt;&lt;div class=&quot;bookmark-text&quot;&gt;&lt;div class=&quot;bookmark-title&quot;&gt;SQL Server 에게 String 이란? (NVARCHAR 인가 VARCHAR 인가) | 우아한형제들 기술블로그&lt;/div&gt;&lt;div class=&quot;bookmark-description&quot;&gt;SQL Server JDBC Driver 를 사용하면서 배운, 그리고 주의해야 할 특징 안녕하세요. 비즈상품개발팀에서 광고시스템을 개발하고 있는 김승영입니다. 현재 광고시스템의 일부분이 Spring Boot / JPA 기반에 SQL Server JDBC Driver 를 사용해서 운영하고 있는데요. 그 SQL Server JDBC Driver 를 사용하면서 배운, 주의해야 할 1가지 특징을 공유하고자 합니다.&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;bookmark-href&quot;&gt;&lt;img src=&quot;https://techblog.woowahan.com/wp-content/uploads/2020/08/favicon.ico&quot; class=&quot;icon bookmark-icon&quot;&gt;https://techblog.woowahan.com/2605/&lt;/div&gt;&lt;/div&gt;&lt;img src=&quot;https://techblog.woowahan.com/wp-content/uploads/2021/06/screenshot.jpg&quot; class=&quot;bookmark-image&quot;&gt;&lt;/a&gt;&lt;/figure&gt;&lt;p id=&quot;c20c9c6e-41f0-4ae9-b30e-2e570427ded1&quot; class=&quot;&quot;&gt;그래서 간단히 적용 하는 방법과 왜 그런 문제가 있는지 간단하게 알아 보겠습니다.&lt;/p&gt;&lt;p id=&quot;1f572350-6ada-424e-b5df-eb775a1495d4&quot; class=&quot;&quot;&gt;
&lt;/p&gt;&lt;h3 id=&quot;78b2d931-c27e-4b15-b8da-9e6d9188bc2a&quot; class=&quot;&quot;&gt;문제점&lt;/h3&gt;&lt;p id=&quot;7a7f691b-5c03-4687-9e79-97a367bd2d73&quot; class=&quot;&quot;&gt;&lt;strong&gt;SQL Server JDBC Driver &lt;/strong&gt;의 String 파라미터들은 &lt;strong&gt;nvarchar &lt;/strong&gt;로 매핑합니다 심지어 &lt;strong&gt;PreparedStatement.set&lt;/strong&gt; 호출시 &lt;strong&gt;varcar &lt;/strong&gt;로 매핑하여도 &lt;strong&gt;nvarchar&lt;/strong&gt;로 매핑 되는 문제&lt;/p&gt;&lt;p id=&quot;285879de-cad2-4b9f-9115-1c50c1ab3673&quot; class=&quot;&quot;&gt;MS 공식 문서에 따르면 &lt;a href=&quot;https://docs.microsoft.com/ko-kr/sql/t-sql/data-types/data-type-precedence-transact-sql?view=sql-server-2017&quot;&gt;데이터 형식 우선순위&lt;/a&gt; 위가 있었습니다. 그래서 묵시적 변환이 일어나는 현상이 일어납니다.&lt;/p&gt;&lt;h3 id=&quot;ce03ee3b-987e-4ac9-9feb-816b703d471b&quot; class=&quot;&quot;&gt;해결 방법&lt;/h3&gt;&lt;p id=&quot;bf9d90eb-e3cb-4c84-8e5c-f43325833850&quot; class=&quot;&quot;&gt;가장 간단한 해결방법은 JDBC URL 에 &lt;code&gt;sendStringParametersAsUnicode=false&lt;/code&gt; 를 추가하는 방법 입니다.&lt;/p&gt;&lt;pre id=&quot;90283810-2d09-4ebf-9cc0-b657a6db15b5&quot; class=&quot;code&quot;&gt;&lt;code&gt;spring:
  datasource:
    driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
		# 아래 sendStringParametersAsUnicode=false 추가
    url: jdbc:sqlserver://localhost:1433;database=데이터베이스;sendStringParametersAsUnicode=false&lt;/code&gt;&lt;/pre&gt;&lt;p id=&quot;a30deeac-a332-4928-ae34-f83d90897f72&quot; class=&quot;&quot;&gt;이 설정 후 모든 String을 varchar로 매핑이 됩니다.&lt;/p&gt;&lt;figure class=&quot;block-color-gray_background callout&quot; style=&quot;white-space:pre-wrap;display:flex&quot; id=&quot;9b7934f7-7a1e-464d-bdd5-7736792290fb&quot;&gt;&lt;div style=&quot;font-size:1.5em&quot;&gt;&lt;span class=&quot;icon&quot;&gt; &lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;width:100%&quot;&gt;만약 반대로 Index 가 nvarchar 로 되어 있고 url 에 &lt;code&gt;sendStringParametersAsUnicode=false&lt;/code&gt; 를 적으면 어떻게 될까요?
→ 우선순위에 따라 조건으로 들어온 Paramater가 형변환이 일어나는거라 Index에 영향이 없습니다.
→ (varchar → nvarchar) 로 되는 형변환이 문제 이기 때문에 Index유지 되고 성틍에 큰 문제가 안됩니다.&lt;/div&gt;&lt;/figure&gt;&lt;p id=&quot;c26a9e7b-c964-484a-9769-67b30307838d&quot; class=&quot;&quot;&gt;그래도 나는 &lt;code&gt;sendStringParametersAsUnicode=false&lt;/code&gt; 설정 후 nvarchar를 꼭 지정해서 사용하고 싶어 하는 경우&lt;/p&gt;&lt;ul id=&quot;f0a6f44d-1a75-467c-8f8c-6bc66f83dcc7&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;JPA / Hibernate / JPQL&lt;p id=&quot;38411185-2399-4829-8245-395db29da1ca&quot; class=&quot;&quot;&gt;매핑하는 컬럼 필드에 &lt;mark class=&quot;highlight-brown&quot;&gt;&lt;code&gt;@Nationalized&lt;/code&gt;&lt;/mark&gt; 를 사용 하면 됩니다.&lt;/p&gt;&lt;pre id=&quot;ddbeed4b-e72c-40c8-8df9-946278ac9993&quot; class=&quot;code&quot;&gt;&lt;code&gt;@Nationalized
@Colum(name =&quot;Member_name&quot;)
private String memberName;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;b56e13cb-9b5a-4ce7-950a-e52576a0a974&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;jdbcTemplate&lt;pre id=&quot;ca3b5acf-e904-4f77-a50b-685c515088ef&quot; class=&quot;code&quot;&gt;&lt;code&gt;String sql = &quot;select * from Member where member_name = ?&quot;
Connection con = DataSourceUtils.getConnection(dataSource);;
psmt = con.prepareStatement(sql);           
psmt.setString(1, memberName);&lt;/code&gt;&lt;/pre&gt;&lt;pre id=&quot;a0a91488-be18-4f72-83ed-9bb2c8239614&quot; class=&quot;code&quot;&gt;&lt;code&gt;JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        jdbcTemplate.query(&quot;select * from Member where member_name = ?&quot;,
                ps -&amp;gt; {
                    ps.setNString(1, &quot;Min&quot;);
                },
                rs -&amp;gt; {
                    log.info(rs.getString(&quot;memberName&quot;));
                });&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class=&quot;n2t_comment&quot;&gt;&lt;p&gt;
&lt;/p&gt;&lt;p class=&quot;block-color-gray&quot;&gt;&lt;a href=&quot;https://boltlessengineer.github.io/Notion2Tistory&quot;&gt;Uploaded by Notion2Tistory v1.1.0&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/article&gt;</description>
      <category>DB</category>
      <author>Eco</author>
      <guid isPermaLink="true">https://gangda.tistory.com/35</guid>
      <comments>https://gangda.tistory.com/35#entry35comment</comments>
      <pubDate>Sat, 4 Jun 2022 23:50:37 +0900</pubDate>
    </item>
    <item>
      <title>Spring ServerSentEvent (작성중...)</title>
      <link>https://gangda.tistory.com/32</link>
      <description>&lt;article id=&quot;947b9e15-ace5-4584-9042-be047ffd31cd&quot; class=&quot;page sans Notion_P&quot;&gt;&lt;div class=&quot;page-body&quot;&gt;&lt;p id=&quot;5b7cd7c7-ad35-4166-bede-6df7142be5c8&quot; class=&quot;&quot;&gt;작성중입니다. → 완전히 다적힐때까지 조금만 기다려주세요...&lt;/p&gt;&lt;h3 id=&quot;2dee0537-8c71-4630-941f-3078041d93d7&quot; class=&quot;&quot;&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;&amp;lt;피드백 언제나 환영합니다! 댓글 감사합니다&amp;gt;&lt;/mark&gt;&lt;/h3&gt;&lt;p id=&quot;108e6d54-ee76-443a-97c5-a659ffdd4dcb&quot; class=&quot;&quot;&gt;알림을 보내줘야할때 또는 실시간으로 데이터를 보내줘야 할 경우가 있습니다. 그때 사용하는 기술중 하나인
SSE(Server Sent Event)를 알아볼 예정입니다.&lt;/p&gt;&lt;h2 id=&quot;8b08400e-9e4a-481c-9354-fb1f11547108&quot; class=&quot;&quot;&gt;실시간 웹앱 개발시 사용되는 방법&lt;/h2&gt;&lt;p id=&quot;12cf02d8-628a-4ba2-af98-e207cc665c9b&quot; class=&quot;&quot;&gt;실제 실시간 통신에서 사용되는 기술들이 있습니다. 그중 3가지를 뽑아 간단하게 알아 보겠습니다.&lt;/p&gt;&lt;ul id=&quot;55fcb7ad-03fc-451d-a1d5-56015bb33974&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Polling(client pull)&lt;br&gt;
클라이언트가 일정한 주기로 서버에 업데이트 요청을 보내는 방법, 지속적인 HTTP 요청발생 → 리소스 낭비 발생&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;bc8e9876-785b-46e8-8b74-a8ddd10186fd&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;WebSocket(server push)&lt;br&gt;
실시간 양방향 통신을 위한 스펙, 서버와 브라우저가 지속적으로 연결된 TCP 라인을 통해 실시간으로 데이터를 주고받는
HTML5 사양 → 연결지향 양방향 전이중 통신이 가능 (채팅, 게임 주식, 차트등에 사용된다) → 서버 클라이언트간 양방향 통신&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;9fac0740-eec3-4a44-9106-9ba099c9ef85&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Server Sent Event(SSE)&lt;br&gt;
이벤트가 (서버 → 클라이언트) 방향으로만 흐르는 단방향 통신 채널 http 요청을 보낼 필요 없이 http 연결을 통해 서버에서
클라이언트로 데이터를 보낼 수 있다.&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;9884eca8-4318-46bc-97c6-ad400adcea6b&quot; class=&quot;&quot;&gt;Server Sent Event(SSE)&lt;/h3&gt;&lt;ul id=&quot;56c2b282-0e5e-4cb6-b31a-ca0497fe0ab3&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;HTTP 스트리밍을 통해 서버에서 클라이언트로 단방향의 Push Notification을 전송할 수 있는 HTML5 표준 기술&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;d7e99ba2-a78c-4714-a642-a48f5cc3119a&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;EventStream 최대 개수는 HTTP/1.1 6개, HTTP/2 사용시 최대 100개까지 유지 가능 합니다.&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;96f65e1d-3477-44ea-a2ed-3376c1511804&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Javascript의 EventSource를 이용하여 사용 가능 → 접속에 문제가 있으면 자동으로 연결을 재시도 하는 특징이 있습니다.&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;fe495859-470f-489c-9c28-21cd4c91e4dd&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;IE 에서 polyfill을 통해 사용가능 → 이제는 보내줍시다...&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;a3249922-1b63-4213-bd72-1e8033987722&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Server To Client 단반향 연결 지원 → 서버에서 데이터를 프론트로 일방적으로 내려주는 케이스에서 적절&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;8980e346-b9ce-42e9-a13f-94b7db235bb4&quot; class=&quot;&quot;&gt;Spring 에서 SSE를 적용 해보자&lt;/h2&gt;&lt;p id=&quot;84271f27-f31d-4554-b637-be06451f35f9&quot; class=&quot;&quot;&gt;적용전 해줘야 할는게 있는데 바로 Postman 과 VsCode 를 설치 해야 합니다 → Data 전송 과 화면 표시를 위해&lt;/p&gt;&lt;ul id=&quot;f25d2928-7e88-400b-b4c7-3f8536dc047f&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;VsCode Extension LiveServer 설치 → html 파일을 바로 로드하여 확인하기 위해&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;54a5eeda-cd47-48bc-a611-5d541d4f9611&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;PostMan → 서버 Event 발생 도구&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;133ac391-db7c-4c4b-9def-3bde2b152109&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Spring → web, lombock, devtool (dependecy 설정)&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;3ee8f6e1-c97b-471d-9256-daec27c1e74b&quot; class=&quot;&quot;&gt;요구 사항&lt;/h3&gt;&lt;ul id=&quot;936610af-1c39-4b3e-8710-0e53c1049e9c&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;화면&lt;ul id=&quot;901b58bb-2f58-484a-8b90-a1af1be92eed&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;데이터를 화면에서 실시간으로 표시&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;24b1139c-e855-4f0c-a987-dc320130da44&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;[ Title ] --&amp;gt; [ Text ]&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;b297368b-95ba-4036-be5e-d038a098b237&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;서버 컨트롤러&lt;ul id=&quot;28c9a2e9-8e19-4ace-ac64-c2e84c1932fd&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;Cros / GetMapping → SseEmitter 를 이용 (서버 → 클라이언트) 단방향 통신 대기&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;c4be8eb1-98a9-4c87-8181-06b292f904fd&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;Cros / PostMapping(ToALL) → 연결 되어 있는 &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;b41a8dd4-bb3b-4643-8b58-a9388535b002&quot; class=&quot;&quot;&gt;먼저 코드를 적어놓고 하나씩 분석해 가면서 설명 하겠습니다.&lt;/p&gt;&lt;ul id=&quot;493c269a-6b66-44f4-9895-d321a7b79b34&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;VsCode - sseIndex.html&lt;/summary&gt;&lt;p id=&quot;96e98d1b-076e-4f64-9171-6736b961fb41&quot; class=&quot;&quot;&gt;VsCode 에 임의로 html 파일을 만들어 표시되는걸 보기위한것 → 간단히 작성할 예정&lt;/p&gt;&lt;pre id=&quot;a615e435-08eb-4a73-bbed-5c428ca78c3e&quot; class=&quot;code&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;en&quot;&amp;gt;

&amp;lt;head&amp;gt;
    &amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
    &amp;lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&amp;gt;
    &amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&amp;gt;
    &amp;lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;title&amp;gt;Document&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
    &amp;lt;input id=&quot;userId&quot; disabled=&quot;false&quot;&amp;gt;
    &amp;lt;ol id=&quot;list&quot;&amp;gt;

    &amp;lt;/ol&amp;gt;
    &amp;lt;script&amp;gt;
        $(document).ready(function () {

            let userId = Math.floor((Math.random() * 1000) + 1);
            document.getElementById(&quot;userId&quot;).value = userId; // LiveServer 에서 사용하는 userId
            let urlENdPoint = 'http://localhost:8080/subscribe?userId=' + userId;
            let eventSource = new EventSource(urlENdPoint); // javascript SSE 받아서 사용하는 부분

            eventSource.addEventListener(&quot;latestNews&quot;, function (event) {
                console.log(&quot;urlEndPoint : &quot; + urlENdPoint)
                console.log(&quot;EVENT : &quot; + event);
                console.log(&quot;EVENT : &quot; + event.data);
                let artilceSource = JSON.parse(event.data);
                console.log(&quot;artilceSource : &quot;+ artilceSource)

                $(&quot;#list&quot;).append(&quot;&amp;lt;li&amp;gt;&quot; + artilceSource.Title +&quot; --&amp;gt; &quot;+ artilceSource.Text + &quot;&amp;lt;/li&amp;gt;&quot;);
            });

        })
    &amp;lt;/script&amp;gt;

&amp;lt;/body&amp;gt;

&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;20909872-e9fd-4736-9d87-6aaba4aba34a&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;NewsController.java&lt;/summary&gt;&lt;pre id=&quot;3162001e-ac91-4b0a-8b76-7ad5418f9c54&quot; class=&quot;code&quot;&gt;&lt;code&gt;package com.example.RealTimeNews.controller; // package 위치 -&amp;gt; Controller 형태로 받을 예정

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

@RestController
@Slf4j
public class NewsController {

    public List&amp;lt;SseEmitter&amp;gt; emitters = new CopyOnWriteArrayList&amp;lt;&amp;gt;();
    public Map&amp;lt;String, SseEmitter&amp;gt; mapEmitters = new ConcurrentHashMap&amp;lt;&amp;gt;();
    // method for client subscription
    @CrossOrigin
    @GetMapping(value = &quot;/subscribe&quot;, consumes = MediaType.ALL_VALUE)
    public SseEmitter subscribe(@RequestParam String userId) {
        SseEmitter sseEmitter = new SseEmitter(Long.MAX_VALUE);
        sendInitEvent(sseEmitter);

        logFormListEmitters(sseEmitter);
        logFormMapEmitters(userId, sseEmitter);

        return sseEmitter;
    }

    // method for dispatching events to all clients
    @CrossOrigin
    @PostMapping(value = &quot;/dispatchEventToAll&quot;)
    public void dispatchEventToClients(@RequestParam String title, @RequestParam String text){
        Map&amp;lt;String, String&amp;gt; mapForJson = Map.of(&quot;Title&quot;, title, &quot;Text&quot;, text);
        for (SseEmitter emitter : emitters) {
            try {
                emitter.send(SseEmitter.event().name(&quot;latestNews&quot;).data(mapForJson));
                log.info(&quot;PostMapping for all clients SSE Emitters : {}&quot;, emitters);
            } catch (IOException e) {
                emitters.remove(emitter);
                log.info(&quot;Exception SSE Emitters : {}&quot;, emitters);
            }
        }
    }

    // method for dispatching events to specific clients
    @CrossOrigin
    @PostMapping(value = &quot;/dispatchEventToSpecific&quot;)
    public void dispatchEventToSpecificClients(@RequestParam String title, @RequestParam String text, @RequestParam String userId){
        Map&amp;lt;String, String&amp;gt; mapForJson = Map.of(&quot;Title&quot;, title, &quot;Text&quot;, text);
        SseEmitter sseEmitter = mapEmitters.get(userId);
        if (sseEmitter != null) {
            try {
                sseEmitter.send(SseEmitter.event().name(&quot;latestNews&quot;).data(mapForJson));
                log.info(&quot;PostMapping for specific clients SSE Emitters : {}&quot;, mapEmitters);
            } catch (IOException e) {
//                emitters.remove(sseEmitter);
                mapEmitters.remove(userId);
                log.info(&quot;Exception SSE Emitters : {}&quot;, mapEmitters);
            }
        }
    }

    private void sendInitEvent(SseEmitter sseEmitter) {
        try {
            sseEmitter.send(SseEmitter.event().name(&quot;INIT&quot;));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void logFormListEmitters(SseEmitter sseEmitter) {
        log.info(&quot;------------------All Clients-----------------&quot;);
        log.info(&quot;first SSE Emitters : {}&quot;, emitters);

        sseEmitter.onCompletion(() -&amp;gt; emitters.remove(sseEmitter));
        log.info(&quot;onCompletion remove SSE Emitters : {}&quot;, emitters);

        emitters.add(sseEmitter);
        log.info(&quot;after add SSE Emitters : {}&quot;, emitters);
    }

    private void logFormMapEmitters(String userId, SseEmitter sseEmitter) {
        log.info(&quot;------------------SpecificClients-----------------&quot;);
        log.info(&quot;first SSE Emitters : {}&quot;, mapEmitters);
        mapEmitters.put(userId, sseEmitter);
        log.info(&quot;map SSE Emitters : {}&quot;, mapEmitters);


        sseEmitter.onCompletion(() -&amp;gt; mapEmitters.remove(userId));
        log.info(&quot;onCompletion remove SSE Emitters : {}&quot;, mapEmitters);

        sseEmitter.onTimeout(() -&amp;gt; mapEmitters.remove(userId));
        log.info(&quot;onTimeout remove SSE Emitters : {}&quot;, mapEmitters);

        sseEmitter.onError((e) -&amp;gt; mapEmitters.remove(userId));
        log.info(&quot;onError remove SSE Emitters : {}&quot;, mapEmitters);
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;3349c299-0e31-44bd-af0a-2fca0d27ad28&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;PostMan 데이터 &lt;/summary&gt;&lt;p id=&quot;58c2f094-f253-48de-b709-bd90e185f962&quot; class=&quot;&quot;&gt;http://localhost:8080/dispatchEventToAll&lt;mark class=&quot;highlight-purple&quot;&gt;?title=Corona is ending&amp;amp;text=I am Happy&lt;/mark&gt;&lt;/p&gt;&lt;ul id=&quot;b5194255-8fbc-43a8-8a43-f263bc9344ad&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Params / key : title | value : Corona is ending&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;e8b156f2-ea0d-46c7-a7b0-62e7ba9dcff7&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Params / key : text | value : I am Happy&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;0c3d30aa-2063-4ed7-975e-d3c1cf1ddfc3&quot; class=&quot;&quot;&gt;http://localhost:8080/dispatchEventToSpecific&lt;mark class=&quot;highlight-purple&quot;&gt;?title=only this id sent&amp;amp;text=hello!!!&amp;amp;userId=853&lt;/mark&gt;&lt;/p&gt;&lt;ul id=&quot;132f97d7-dee5-4d9c-9ac9-786c36d2a522&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Params / key : title | value : only this id sent&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;15c2b0b7-15f9-45e2-87fe-276eca1a9407&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Params / key : text | value : hello!!!&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;8567a81a-91b2-4fbd-b886-c1c18132b6a8&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Params / key : userId | value : 853 (VsCode 에 있는 userId)&lt;/li&gt;&lt;/ul&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;4654579a-7514-421a-b678-5d36dc26f16c&quot; class=&quot;&quot;&gt;참조&lt;/h3&gt;&lt;ul id=&quot;36c64566-486a-4f43-98f6-29c05dfcab76&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;a href=&quot;https://sg-choi.tistory.com/542&quot;&gt;https://sg-choi.tistory.com/542&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;658e8e45-fc34-4270-9104-685e04d6d64f&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;a href=&quot;https://velog.io/@max9106/Spring-SSE-Server-Sent-Events%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%8B%A4%EC%8B%9C%EA%B0%84-%EC%95%8C%EB%A6%BC&quot;&gt;https://velog.io/@max9106/Spring-SSE-Server-Sent-Events를-이용한-실시간-알림&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;7599dd8c-f56b-4162-9f53-86ed016293ab&quot; class=&quot;&quot;&gt;
&lt;/p&gt;&lt;div class=&quot;n2t_comment&quot;&gt;&lt;p&gt;
&lt;/p&gt;&lt;p class=&quot;block-color-gray&quot;&gt;&lt;a href=&quot;https://boltlessengineer.github.io/Notion2Tistory&quot;&gt;Uploaded by Notion2Tistory v1.1.0&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/article&gt;</description>
      <category>SPRING/Spring Framework</category>
      <author>Eco</author>
      <guid isPermaLink="true">https://gangda.tistory.com/32</guid>
      <comments>https://gangda.tistory.com/32#entry32comment</comments>
      <pubDate>Tue, 12 Apr 2022 01:06:17 +0900</pubDate>
    </item>
    <item>
      <title>LogBack - 설정(.xml)</title>
      <link>https://gangda.tistory.com/26</link>
      <description>&lt;article id=&quot;ee3323bd-b448-4a3a-a691-280210433ebf&quot; class=&quot;page sans Notion_P&quot;&gt;&lt;div class=&quot;page-body&quot;&gt;&lt;h3 id=&quot;a92b5df1-35f1-4f1e-a59f-9b15357c7a95&quot; class=&quot;&quot;&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;&amp;lt;피드백 언제나 환영합니다! 댓글 감사합니다&amp;gt;&lt;/mark&gt;&lt;/h3&gt;&lt;p id=&quot;fccb76d9-a2ec-47bc-b0ec-ff24a92c297e&quot; class=&quot;&quot;&gt;Apache Tomcat 운영중 stdout, stderr 같은 log의 경우 날짜별로 쌓이는게 아닌 한 log 파일에 쌓이게 된다.&lt;/p&gt;&lt;p id=&quot;d9ce813a-c70c-43d1-a515-fd1868a990f8&quot; class=&quot;&quot;&gt;이런부분 때문에 apache tomcat의 log를 막고 logback 이용하여 log를 관리할 예정이다.&lt;/p&gt;&lt;h2 id=&quot;2d0f60c9-5fe7-41e4-afa4-b1d3e986e464&quot; class=&quot;&quot;&gt;들어가기전...&lt;/h2&gt;&lt;p id=&quot;992939d6-5060-459b-a2e3-651b8c6a323d&quot; class=&quot;&quot;&gt;들어가기전 &lt;strong&gt;Profile.active &lt;/strong&gt;를 이용 다른 application.properties or application.yml 을 먼저 설정 해야 한다.&lt;/p&gt;&lt;p id=&quot;e2dd80bc-4138-41e5-899c-fb2b6eacd1f8&quot; class=&quot;&quot;&gt;→ 무조건 필요한게 아니지만 logback 시작때 다시한번 언급 할 예정입니다. 아래 링크를 확인하여 설정을 할 수 있습니다.&lt;/p&gt;&lt;figure id=&quot;29360aa1-9aa8-42f3-8224-c39dfe148474&quot;&gt;&lt;a href=&quot;https://gangda.tistory.com/25&quot; class=&quot;bookmark source&quot;&gt;&lt;div class=&quot;bookmark-info&quot;&gt;&lt;div class=&quot;bookmark-text&quot;&gt;&lt;div class=&quot;bookmark-title&quot;&gt;Profile.active 를 이용 다른 설정 정보 (작성중..)&lt;/div&gt;&lt;div class=&quot;bookmark-description&quot;&gt;우리는 properteis 또는 yml 을 통해 spring의 설정을 합니다. 실무에서의 개발에서는 application은 다양한 환경에서 일어납니다. dev → application-dev → 개발..&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;bookmark-href&quot;&gt;&lt;img src=&quot;https://gangda.tistory.com/favicon.ico&quot; class=&quot;icon bookmark-icon&quot;&gt;https://gangda.tistory.com/25&lt;/div&gt;&lt;/div&gt;&lt;img src=&quot;https://img1.daumcdn.net/thumb/R800x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlTExH%2FbtruI7XF73r%2FMRqp5V3WBcnqatnxLQvCeK%2Fimg.png&quot; class=&quot;bookmark-image&quot;&gt;&lt;/a&gt;&lt;/figure&gt;&lt;p id=&quot;423ac631-934f-4eca-ab4e-76d9ff014e7c&quot; class=&quot;&quot;&gt;application.proerteis 또는 .yml 파일에서도 설정을 할 수 있지만 세부적인 설정까지는 어렵습니다. 그래서&lt;/p&gt;&lt;p id=&quot;e5b8958d-4abe-4965-84d6-5f121681f5f2&quot; class=&quot;&quot;&gt;logback.properteis, logbakc-spring.xml 로 나누어 설정을과 예제를 보여드릴 예정 입니다.&lt;/p&gt;&lt;h2 id=&quot;5062210d-ae7d-4cc1-873e-63426d6c2768&quot; class=&quot;&quot;&gt;Log를 왜 쓸까요??&lt;/h2&gt;&lt;p id=&quot;2fdfb802-5747-41b6-b0a8-77e3ae61b3fa&quot; class=&quot;&quot;&gt;너무 간단한 이야기 입니다. Log를 통해 우리는 개발과정 혹은 운영 과정에서 예상치 못한 어플리케이션의 문제를 진단 및
사용자 로그를 이용 분석하여 조금더 사용자에게 친화적인 환경을 구성할수 있습니다.
하지만 로깅을 하는 단계에서 로그 기준을 잡지 못하면 방대한양의 로그파일이 쌓여 의미있는 로그가 쌓이지 않습니다.&lt;/p&gt;&lt;p id=&quot;be6c3b02-d996-44a4-b3b3-4026ac4261d9&quot; class=&quot;&quot;&gt;&lt;mark class=&quot;highlight-red&quot;&gt;&lt;strong&gt;결국 효율적으로 로깅하는 방법이 중요합니다 &lt;/strong&gt;&lt;/mark&gt;&lt;strong&gt;→&lt;/strong&gt;&lt;mark class=&quot;highlight-red&quot;&gt;&lt;strong&gt; &lt;/strong&gt;&lt;/mark&gt;&lt;strong&gt;실무마다 적용이&lt;/strong&gt;&lt;mark class=&quot;highlight-red&quot;&gt;&lt;strong&gt; &lt;/strong&gt;&lt;/mark&gt;&lt;strong&gt;달라 우리는 &lt;/strong&gt;&lt;mark class=&quot;highlight-red&quot;&gt;&lt;strong&gt;사용하는 방법 위주로 공부 할 예정&lt;/strong&gt;&lt;/mark&gt;&lt;strong&gt;입니다.!!&lt;/strong&gt;&lt;/p&gt;&lt;h2 id=&quot;e404e2d0-5496-4efe-b5fb-23d9294682f6&quot; class=&quot;&quot;&gt;스프링에서는 어떻게 사용 할까요??&lt;/h2&gt;&lt;p id=&quot;0ba43839-2688-4473-b90e-e92d0d2a08ef&quot; class=&quot;&quot;&gt;Log4j와 LogBack으로 스프링 부트의 로그구현체를 사용 합니다.
Logback 은 log4j 이후에 출시된 Java 기반 Logging Framework 중 하나로 가장 널리 사용되고 있습니다.
SLF4j 의 구현체이며 Spring Boot 환경이라면 별도의 dependency 추가 없이 기본적으로 포함되어 있습니다.
logback.properteis, logbakc-spring.xml 을 이용 log를 이용하여 관리할 예정입니다.&lt;/p&gt;&lt;p id=&quot;4a243602-4af8-4d7f-913e-5c37e88d7167&quot; class=&quot;&quot;&gt;즉, logback은 Java / Spring 에 조금 친화적이며 후 Log4J를 이용 Log 관리를 알아보도록 하겠습니다.&lt;/p&gt;&lt;ul id=&quot;c98f08e2-c120-4f07-8b95-71f31c7c9b2c&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Log4J 보안 이슈&lt;/li&gt;&lt;/ul&gt;&lt;figure id=&quot;19118af8-4c27-4386-a068-d0f465a9e365&quot;&gt;&lt;a href=&quot;https://nhj12311.tistory.com/575&quot; class=&quot;bookmark source&quot;&gt;&lt;div class=&quot;bookmark-info&quot;&gt;&lt;div class=&quot;bookmark-text&quot;&gt;&lt;div class=&quot;bookmark-title&quot;&gt;Log4J(Log4Shell) 역대급 보안 취약점 정리(22.01.24 업데이트)&lt;/div&gt;&lt;div class=&quot;bookmark-description&quot;&gt;역대급 핫 이슈였던 `Log4J(Log4Shell) 역대 최악 보안 취약점( CVE-2021-44228)` 외 8개까지 정리해봅니다.(`22.01.24 업데이트). 한번 터지더니 최근 계속해서 이슈가 되고 있는 것 같습니다. 아예 log4j 취약점을 찾는 사람들이 계속해서 파고 있는 느낌? 나름 IT 밥을 먹고 있는 사람으로 정리를 하지 않고 넘어가면 안될것 같아서 남들이 정리한걸 다시 재정리하는 느낌으로 정리해봅니다.&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;bookmark-href&quot;&gt;https://nhj12311.tistory.com/575&lt;/div&gt;&lt;/div&gt;&lt;img src=&quot;https://img1.daumcdn.net/thumb/R800x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB2W4N%2FbtrnUIwdd7o%2FtKV47pUBQlgOv7PQl893B0%2Fimg.jpg&quot; class=&quot;bookmark-image&quot;&gt;&lt;/a&gt;&lt;/figure&gt;&lt;h2 id=&quot;61301a0c-10d3-47be-aabb-f37634995d7a&quot; class=&quot;&quot;&gt;간단한 Log 표시 사용법&lt;/h2&gt;&lt;ul id=&quot;1f063e21-3fc8-4ad1-a199-2e1ee9b4db1d&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;1. LoggerFactory 를 이용한 생성&lt;/summary&gt;&lt;pre id=&quot;338d68ce-54eb-41cc-be11-9d677719bd10&quot; class=&quot;code&quot;&gt;&lt;code&gt;package com.log.findlog.log1;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class log1Controller {

    private static final Logger log = LoggerFactory.getLogger(log1Controller.class);

    @GetMapping(&quot;/log1&quot;)
    public String log1() {
        log.info(&quot;hello log1&quot;);
        return &quot;ok&quot;;
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;17983363-90ec-4596-92c6-5c60910db9c4&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;2. lombok @Slf4j 을 이용한 방법&lt;/summary&gt;&lt;pre id=&quot;74cbd3cd-3964-46f5-8d78-ae83c974b757&quot; class=&quot;code&quot;&gt;&lt;code&gt;package com.log.findlog.log2;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
public class log2Controller {

    @GetMapping(&quot;/log2&quot;)
    public String log1() {
        log.info(&quot;hello log2&quot;);
        return &quot;ok&quot;;
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;817abc61-a66e-45be-9f5d-7255f3b25efc&quot; class=&quot;&quot;&gt;로그 레벨 관련&lt;/h3&gt;&lt;p id=&quot;1c517094-e44d-40e0-89cb-991fb34520b9&quot; class=&quot;&quot;&gt;Logback 은 5단계의 로그 레벨을 가진다.심각도 수준은 Error &amp;gt; Warn &amp;gt; Info &amp;gt; Debug &amp;gt; Trace 이다.&lt;/p&gt;&lt;ul id=&quot;1567dbec-db01-4b4f-98b9-0ed2340a8332&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;⛔️ Error : 예상하지 못한 심각한 문제가 발생하는 경우, 즉시 조취를 취해야 할 수준의 레벨&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;c83ff3c3-c203-4953-b9bd-0232b3b62226&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;⚠ ️Warn : 로직 상 유효성 확인, 예상 가능한 문제로 인한 예외 처리, 당장 서비스 운영에는 영향이 없지만 주의해야 할 부분&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;03544860-c455-44a5-b268-9125aeb74b00&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;✅ Info : 운영에 참고할만한 사항, 중요한 비즈니스 프로세스가 완료됨&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;f13ff4e0-58bc-4d34-a8f2-bd98046d0893&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;⚙️ Debug : 개발 단계에서 사용하며, SQL 로깅을 할 수 있음&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;35e29c0e-e691-4b48-9cc1-867732158497&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;  Trace : 모든 레벨에 대한 로깅이 추적되므로 개발 단계에서 사용함&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;eca0549c-9f08-4f88-ab50-8d2b1dd72f25&quot; class=&quot;&quot;&gt;✨로그파일 작성하기&lt;/h2&gt;&lt;p id=&quot;a4287ddb-426f-4e91-a164-ed8c15dd320a&quot; class=&quot;&quot;&gt;먼저 로그 관련하여 전반적인 코드를 먼저 작성하고 하나하나 뜯어보면서 하겠습니다.&lt;/p&gt;&lt;ul id=&quot;2c6eef8a-faf8-4539-b711-f1c74df2ee13&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;strong&gt;resources 폴더에 저장하면 됩니다.&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;50bf9070-d7ed-43ef-8337-088e028ee429&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;application.properties&lt;/summary&gt;&lt;pre id=&quot;de06ca5a-bcba-4569-9bc1-a429872159cf&quot; class=&quot;code&quot;&gt;&lt;code&gt;spring.profiles.active=dev&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;b1130f2e-d90c-477f-9405-63fc785cc7e1&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;application-dev.properties&lt;/summary&gt;&lt;pre id=&quot;79d02882-c874-44be-a251-3c3fdc2acde6&quot; class=&quot;code&quot;&gt;&lt;code&gt;server.port=9090&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;e7e6da95-780a-4000-8fd6-5f6d5f36d10b&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;logback-dev.properties&lt;/summary&gt;&lt;pre id=&quot;13c028ff-bd2c-4373-99ed-27b6cc4d8275&quot; class=&quot;code&quot;&gt;&lt;code&gt;log.config.path=D:\\logs
log.config.normal.filename=normal
log.config.error.filename=error&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;88facd00-0e0f-4ab2-9bce-7f696018703f&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;logback-spring.xml&lt;/summary&gt;&lt;pre id=&quot;769565ac-cf83-4d18-925b-cc0e597dc3cf&quot; class=&quot;code&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;configuration&amp;gt; 
	&amp;lt;!-- springProfile --&amp;gt;
	&amp;lt;springProfile name=&quot;dev&quot;&amp;gt;
		&amp;lt;property resource=&quot;logback-dev.properties&quot; /&amp;gt;
	&amp;lt;/springProfile&amp;gt;
	
	&amp;lt;!-- log file path --&amp;gt;
	&amp;lt;property name=&quot;LOG_PATH&quot; value=&quot;${log.config.path}&quot; /&amp;gt;
	
	&amp;lt;!-- log file name --&amp;gt;
	&amp;lt;property name=&quot;NOR_LOG_FILE_NAME&quot; value=&quot;${log.config.normal.filename}&quot; /&amp;gt;
	
	&amp;lt;!-- err log file name --&amp;gt;
	&amp;lt;property name=&quot;ERR_LOG_FILE_NAME&quot; value=&quot;${log.config.error.filename}&quot; /&amp;gt;
	
	&amp;lt;!-- pattern --&amp;gt;
	&amp;lt;conversionRule conversionWord=&quot;clr&quot; converterClass=&quot;org.springframework.boot.logging.logback.ColorConverter&quot; /&amp;gt;
	&amp;lt;conversionRule conversionWord=&quot;wex&quot; converterClass=&quot;org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter&quot; /&amp;gt;
	&amp;lt;conversionRule conversionWord=&quot;wEx&quot; converterClass=&quot;org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter&quot; /&amp;gt;
	&amp;lt;property name=&quot;LOG_PATTERN&quot; value=&quot;%clr(%d{yy-MM-dd E HH:mm:ss.SSS}){magenta} %clr(%-5p) %clr(${PID}){yellow} %clr(---){faint} %clr([%15.15t]){cyan} %clr(%-45.45c){faint} %clr(::){red} %clr(%m){green}%n&quot; /&amp;gt;
	&amp;lt;property name=&quot;FILE_LOG_PATTERN&quot; value=&quot;${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}&quot;/&amp;gt;

	&amp;lt;!-- Console Appender --&amp;gt;
	&amp;lt;appender name=&quot;CONSOLE&quot; class=&quot;ch.qos.logback.core.ConsoleAppender&quot;&amp;gt;
		&amp;lt;encoder class=&quot;ch.qos.logback.classic.encoder.PatternLayoutEncoder&quot;&amp;gt;
			&amp;lt;pattern&amp;gt;${LOG_PATTERN}&amp;lt;/pattern&amp;gt;
		&amp;lt;/encoder&amp;gt;
	&amp;lt;/appender&amp;gt; 
	
	&amp;lt;!-- Nomal File Appender --&amp;gt;
	&amp;lt;appender name=&quot;NORMAL&quot; class=&quot;ch.qos.logback.core.rolling.RollingFileAppender&quot;&amp;gt; 
		&amp;lt;!-- 파일경로 설정 --&amp;gt;
		&amp;lt;file&amp;gt;${LOG_PATH}/${NOR_LOG_FILE_NAME}.log&amp;lt;/file&amp;gt; 
		
		&amp;lt;!-- 출력패턴 설정 --&amp;gt;
		&amp;lt;encoder class=&quot;ch.qos.logback.classic.encoder.PatternLayoutEncoder&quot;&amp;gt;
			&amp;lt;pattern&amp;gt;${FILE_LOG_PATTERN}&amp;lt;/pattern&amp;gt;
		&amp;lt;/encoder&amp;gt; 
		
		&amp;lt;!-- Rolling 정책 --&amp;gt;
		&amp;lt;rollingPolicy class=&quot;ch.qos.logback.core.rolling.TimeBasedRollingPolicy&quot;&amp;gt; 
			&amp;lt;!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 --&amp;gt;
			&amp;lt;fileNamePattern&amp;gt;${LOG_PATH}/${NOR_LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.zip&amp;lt;/fileNamePattern&amp;gt;
			&amp;lt;timeBasedFileNamingAndTriggeringPolicy class=&quot;ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP&quot;&amp;gt; 
				&amp;lt;!-- 파일당 최고 용량 kb, mb, gb --&amp;gt;
				&amp;lt;maxFileSize&amp;gt;5KB&amp;lt;/maxFileSize&amp;gt;
			&amp;lt;/timeBasedFileNamingAndTriggeringPolicy&amp;gt; 
			
			&amp;lt;!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거 --&amp;gt;
			&amp;lt;maxHistory&amp;gt;30&amp;lt;/maxHistory&amp;gt;
		&amp;lt;/rollingPolicy&amp;gt;
	&amp;lt;/appender&amp;gt; 
	
	&amp;lt;!-- Error File Appender --&amp;gt;
	&amp;lt;appender name=&quot;ERROR&quot; class=&quot;ch.qos.logback.core.rolling.RollingFileAppender&quot;&amp;gt;
		&amp;lt;filter class=&quot;ch.qos.logback.classic.filter.LevelFilter&quot;&amp;gt;
			&amp;lt;level&amp;gt;error&amp;lt;/level&amp;gt;
			&amp;lt;onMatch&amp;gt;ACCEPT&amp;lt;/onMatch&amp;gt;
			&amp;lt;onMismatch&amp;gt;DENY&amp;lt;/onMismatch&amp;gt;
		&amp;lt;/filter&amp;gt;
		
		&amp;lt;file&amp;gt;${LOG_PATH}/${ERR_LOG_FILE_NAME}.log&amp;lt;/file&amp;gt;
		
		&amp;lt;encoder class=&quot;ch.qos.logback.classic.encoder.PatternLayoutEncoder&quot;&amp;gt;
			&amp;lt;pattern&amp;gt;${FILE_LOG_PATTERN}&amp;lt;/pattern&amp;gt;
		&amp;lt;/encoder&amp;gt;
		
		&amp;lt;!-- Rolling 정책 --&amp;gt;
		&amp;lt;rollingPolicy class=&quot;ch.qos.logback.core.rolling.TimeBasedRollingPolicy&quot;&amp;gt; 
			&amp;lt;!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 --&amp;gt;
			&amp;lt;fileNamePattern&amp;gt;${LOG_PATH}/${ERR_LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log&amp;lt;/fileNamePattern&amp;gt;
			&amp;lt;timeBasedFileNamingAndTriggeringPolicy class=&quot;ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP&quot;&amp;gt; 
				&amp;lt;!-- 파일당 최고 용량 kb, mb, gb --&amp;gt;
				&amp;lt;maxFileSize&amp;gt;10MB&amp;lt;/maxFileSize&amp;gt;
			&amp;lt;/timeBasedFileNamingAndTriggeringPolicy&amp;gt; 
			&amp;lt;!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거 --&amp;gt;
			&amp;lt;maxHistory&amp;gt;30&amp;lt;/maxHistory&amp;gt;
		&amp;lt;/rollingPolicy&amp;gt;
	&amp;lt;/appender&amp;gt;
	
	&amp;lt;!-- root레벨 설정 --&amp;gt;
	&amp;lt;root level=&quot;INFO&quot;&amp;gt;
		&amp;lt;appender-ref ref=&quot;CONSOLE&quot; /&amp;gt;
		&amp;lt;appender-ref ref=&quot;NORMAL&quot; /&amp;gt;
		&amp;lt;appender-ref ref=&quot;ERROR&quot; /&amp;gt;
	&amp;lt;/root&amp;gt;
	
	&amp;lt;!-- 특정패키지 로깅레벨 설정 --&amp;gt;
	&amp;lt;logger name=&quot;com.log.findlog.log2&quot; level=&quot;DEBUG&quot; additivity=&quot;false&quot;&amp;gt;
		&amp;lt;appender-ref ref=&quot;CONSOLE&quot; /&amp;gt;
		&amp;lt;appender-ref ref=&quot;NORMAL&quot; /&amp;gt;
		&amp;lt;appender-ref ref=&quot;ERROR&quot; /&amp;gt;
	&amp;lt;/logger&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;3bbe8ed8-bf13-40c2-b9d3-520d61c48424&quot; class=&quot;&quot;&gt;1. configuration 설정&lt;/h3&gt;&lt;ul id=&quot;e724db98-8807-4c04-b4c8-28a90fd390cb&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;configuration &lt;/summary&gt;&lt;pre id=&quot;b0bc702f-3cca-4133-948d-254f70711c5e&quot; class=&quot;code&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;configuration&amp;gt; 
	&amp;lt;!-- springProfile --&amp;gt;
	&amp;lt;springProfile name=&quot;dev&quot;&amp;gt;
		&amp;lt;property resource=&quot;logback-dev.properties&quot; /&amp;gt;
	&amp;lt;/springProfile&amp;gt;
	....
	....
&amp;lt;configuration&amp;gt; &lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;a3ddb917-2997-41f0-8ebc-89da8b7c752c&quot; class=&quot;&quot;&gt;설정 정보들을 넣을 수 있다. 예로들어 application.properteis 에서 사용하는 profile 설정, properties resource를 사용하여
log 를 메시지화 하여 관리 할 수 있다.&lt;/p&gt;&lt;h3 id=&quot;e89e3ae0-fcb0-411c-812a-f6967f5fc0ed&quot; class=&quot;&quot;&gt;2. path 설정 및 fileName 설정&lt;/h3&gt;&lt;ul id=&quot;5601b7de-6327-491e-9846-0dc3d3268576&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;path 설정 및 fileName&lt;/summary&gt;&lt;pre id=&quot;578f4433-ace7-4c71-a8ff-e3a2c7275ce1&quot; class=&quot;code&quot;&gt;&lt;code&gt;&amp;lt;!-- log file path --&amp;gt;
&amp;lt;property name=&quot;LOG_PATH&quot; value=&quot;${log.config.path}&quot; /&amp;gt;
&amp;lt;!-- log file name --&amp;gt;
&amp;lt;property name=&quot;NOR_LOG_FILE_NAME&quot; value=&quot;${log.config.normal.filename}&quot; /&amp;gt;	
&amp;lt;!-- err log file name --&amp;gt;
&amp;lt;property name=&quot;ERR_LOG_FILE_NAME&quot; value=&quot;${log.config.error.filename}&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;53c028d0-a106-482c-ac82-5a657f11f009&quot; class=&quot;&quot;&gt;logback-dev.properties 에서 설정한 메시지 들을 xml내에 사용가능한 proerty화(메시지화)되어 재사용이 가능하다.&lt;/p&gt;&lt;h3 id=&quot;78611cce-ac1d-492b-8512-d1a90d5fc387&quot; class=&quot;&quot;&gt;3. pattern&lt;/h3&gt;&lt;ul id=&quot;2aa1a277-a875-4004-9fb7-7869fa851dee&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;pattern&lt;/summary&gt;&lt;pre id=&quot;56b84daf-5c04-473d-a203-4ec5ec63e49e&quot; class=&quot;code&quot;&gt;&lt;code&gt;&amp;lt;!-- pattern --&amp;gt;
&amp;lt;conversionRule conversionWord=&quot;clr&quot; converterClass=&quot;org.springframework.boot.logging.logback.ColorConverter&quot; /&amp;gt;
&amp;lt;conversionRule conversionWord=&quot;wex&quot; converterClass=&quot;org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter&quot; /&amp;gt;
&amp;lt;conversionRule conversionWord=&quot;wEx&quot; converterClass=&quot;org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter&quot; /&amp;gt;
&amp;lt;property name=&quot;LOG_PATTERN&quot; value=&quot;%clr(%d{yy-MM-dd E HH:mm:ss.SSS}){magenta} %clr(%-5p) %clr(${PID}){yellow} %clr(---){faint} %clr([%15.15t]){cyan} %clr(%-45.45c){faint} %clr(::){red} %clr(%m){green}%n&quot; /&amp;gt;
&amp;lt;property name=&quot;FILE_LOG_PATTERN&quot; value=&quot;${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}&quot;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;fa81df0e-d1de-40e0-903c-716a42528295&quot; class=&quot;&quot;&gt;로그를 적을시 패턴을 적어서 사용하기위해 이용 된다. 주로 콘솔의 log와 파일의 log 패턴을 분류해서 사용한다.&lt;/p&gt;&lt;ul id=&quot;df5e1f92-4b0b-454b-9a4c-7c32c3f8dcf3&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;clr : console에 색을 입혀 잘 보기 위해&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;24cf0a41-ac37-4964-8424-b1a93151c0bb&quot; class=&quot;&quot;&gt;4. console appender&lt;/h3&gt;&lt;ul id=&quot;029cec27-c586-4969-b590-b8092561cc29&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;console appender&lt;/summary&gt;&lt;pre id=&quot;cf5a3c46-0ddb-457f-a67c-db6c3c1c43b0&quot; class=&quot;code&quot;&gt;&lt;code&gt;&amp;lt;!-- Console Appender --&amp;gt;
&amp;lt;appender name=&quot;CONSOLE&quot; class=&quot;ch.qos.logback.core.ConsoleAppender&quot;&amp;gt;
	&amp;lt;encoder class=&quot;ch.qos.logback.classic.encoder.PatternLayoutEncoder&quot;&amp;gt;
		&amp;lt;pattern&amp;gt;${LOG_PATTERN}&amp;lt;/pattern&amp;gt;
	&amp;lt;/encoder&amp;gt;
&amp;lt;/appender&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;287e96a7-b9ad-4095-ac67-ee90f0195b00&quot; class=&quot;&quot;&gt;idea 에서 작업시 로그를 출력하기 위한 appender 이며  pattern에서 정의한 LOG_PATTERN의 정보를 사용한다.&lt;/p&gt;&lt;h3 id=&quot;f7d63ca5-6e03-42b9-b7a4-59b7fff801c9&quot; class=&quot;&quot;&gt;5. normal fileAppender 출력 패턴 설정, rolling 설정&lt;/h3&gt;&lt;ul id=&quot;cdc3a784-6555-4e0a-8cea-f00b51e139b5&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;fileAppender 출력 패턴 설정&lt;/summary&gt;&lt;pre id=&quot;7eec45f9-0819-4bbe-ae49-87b59e75e904&quot; class=&quot;code&quot;&gt;&lt;code&gt;&amp;lt;appender name=&quot;NORMAL&quot; class=&quot;ch.qos.logback.core.rolling.RollingFileAppender&quot;&amp;gt; 
	&amp;lt;!-- 파일경로 설정 --&amp;gt;
	&amp;lt;file&amp;gt;${LOG_PATH}/${NOR_LOG_FILE_NAME}.log&amp;lt;/file&amp;gt; 
		
	&amp;lt;!-- 출력패턴 설정 --&amp;gt;
	&amp;lt;encoder class=&quot;ch.qos.logback.classic.encoder.PatternLayoutEncoder&quot;&amp;gt;
		&amp;lt;pattern&amp;gt;${FILE_LOG_PATTERN}&amp;lt;/pattern&amp;gt;
	&amp;lt;/encoder&amp;gt;
	&amp;lt;!-- Rolling 정책 --&amp;gt;
	.... 
&amp;lt;/appender&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;7e7b34c9-a00f-4a12-bb11-c5589df45cd3&quot; class=&quot;&quot;&gt;file appender 는 파일의 경로 출력패턴 rolling 설정들을 하는 곳입니다. 저같은 경우 normal과 error 파일들을 분류하여
설정 하였습니다. 파일의 경로와 log 파일에 찍히는 패턴을 설정 합니다. &lt;strong&gt;(2.path 설정, 3.pattern&lt;/strong&gt; 에서 정의한 내요을 사용 합니다.&lt;strong&gt;)&lt;/strong&gt;&lt;/p&gt;&lt;ul id=&quot;ab7c0da5-dd09-4225-b067-52ef201b3fef&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;rolling 설정&lt;/summary&gt;&lt;pre id=&quot;f44de4c5-7ef6-4fcf-9ad4-2fa6cc4c63a7&quot; class=&quot;code&quot;&gt;&lt;code&gt;&amp;lt;!-- Rolling 정책 --&amp;gt;
&amp;lt;rollingPolicy class=&quot;ch.qos.logback.core.rolling.TimeBasedRollingPolicy&quot;&amp;gt; 
	&amp;lt;!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 --&amp;gt;
	&amp;lt;fileNamePattern&amp;gt;${LOG_PATH}/${NOR_LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log&amp;lt;/fileNamePattern&amp;gt;
		&amp;lt;timeBasedFileNamingAndTriggeringPolicy class=&quot;ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP&quot;&amp;gt; 
		&amp;lt;!-- 파일당 최고 용량 kb, mb, gb --&amp;gt;
		&amp;lt;maxFileSize&amp;gt;5KB&amp;lt;/maxFileSize&amp;gt;
		&amp;lt;/timeBasedFileNamingAndTriggeringPolicy&amp;gt; 		
		&amp;lt;!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거 --&amp;gt;
	&amp;lt;maxHistory&amp;gt;30&amp;lt;/maxHistory&amp;gt;
&amp;lt;/rollingPolicy&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;95cfd4fb-8c97-465f-8dba-bc0bc864616e&quot; class=&quot;&quot;&gt;rolling 정책은 로그파일의 용량과 일정 용량을 넘어갈시 log파일의 이름을 새로 만들어저장 최대 보한 기한을 설정 하빈다.&lt;/p&gt;&lt;p id=&quot;ec11776d-9aa8-43f6-8917-a141778cbba7&quot; class=&quot;&quot;&gt;&lt;mark class=&quot;highlight-brown&quot;&gt;&lt;code&gt;fileNamePattern&lt;/code&gt;&lt;/mark&gt; : logfile의 지정 size 를 넘길시 새로운 이름을 부여해 저장합니다.
(zip, gz 로 만들경우 log 파일을 압축하여 저장 합니다. → .log 로 남는게 아닌 name에 부여되 이름의 log 파일을 압축합니다)&lt;/p&gt;&lt;p id=&quot;7f303de0-788f-4404-9d58-a7dc20522ce3&quot; class=&quot;&quot;&gt;&lt;mark class=&quot;highlight-brown&quot;&gt;&lt;code&gt;maxFileSize&lt;/code&gt;&lt;/mark&gt;&lt;mark class=&quot;highlight-brown&quot;&gt; &lt;/mark&gt;: logfile의 size를 지정 할 수있으며 size가 오버되면 &lt;mark class=&quot;highlight-brown&quot;&gt;&lt;code&gt;fileNamePattern&lt;/code&gt;&lt;/mark&gt; 에 의해 이름이 정의 된다&lt;/p&gt;&lt;p id=&quot;5dfc764e-d77c-4fe1-ae60-365f41a40472&quot; class=&quot;&quot;&gt;&lt;mark class=&quot;highlight-brown&quot;&gt;&lt;code&gt;maxHistory&lt;/code&gt;&lt;/mark&gt;&lt;mark class=&quot;highlight-brown&quot;&gt; &lt;/mark&gt;: 로그파일의 최대 보관 주기(일) 로 되며 해당 설정일 이상이된 파일은 자동으로 제거 됩니다.&lt;/p&gt;&lt;h3 id=&quot;c8885757-de4e-4d2f-8ee2-19d169b2616f&quot; class=&quot;&quot;&gt;6. error fileAppender&lt;/h3&gt;&lt;p id=&quot;372f53dd-7598-4d55-8b5e-36d36e3d4322&quot; class=&quot;&quot;&gt;error 와 관련된게 따로 분류한 이유는 error와 관련된 부분만 저장하기 위해서이다.
normalfileAppdender 와 별 다를점이 없다 그래서 다른 점 만 확인하겠습니다.&lt;/p&gt;&lt;ul id=&quot;9267b8ea-0a3c-48ff-bd5c-62dac59fe2ae&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;error fileAppdender&lt;/summary&gt;&lt;pre id=&quot;bf7b5416-f095-4034-8384-54e03f21bd67&quot; class=&quot;code&quot;&gt;&lt;code&gt;&amp;lt;appender name=&quot;ERROR&quot; class=&quot;ch.qos.logback.core.rolling.RollingFileAppender&quot;&amp;gt;
	&amp;lt;filter class=&quot;ch.qos.logback.classic.filter.LevelFilter&quot;&amp;gt;
		&amp;lt;level&amp;gt;error&amp;lt;/level&amp;gt;
		&amp;lt;onMatch&amp;gt;ACCEPT&amp;lt;/onMatch&amp;gt;
		&amp;lt;onMismatch&amp;gt;DENY&amp;lt;/onMismatch&amp;gt;
	&amp;lt;/filter&amp;gt;
	....
&amp;lt;/appender&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;06531f60-17dd-48fa-8f09-73451c71b1ac&quot; class=&quot;&quot;&gt;log level 중 error 만을 사용하기위해 입니다. level을 설정한후 onMatch onMismatch 설정으로 leve단위로 설정할 수 있습니다.&lt;/p&gt;&lt;h3 id=&quot;a9614487-8b37-49e5-a760-a082913a682d&quot; class=&quot;&quot;&gt;7. append-ref 설정&lt;/h3&gt;&lt;ul id=&quot;639ebae3-61ba-4fba-bb50-f836e4f21adb&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;append-ref 설정&lt;/summary&gt;&lt;pre id=&quot;901564a3-afd9-4992-a294-00312ff1c37e&quot; class=&quot;code&quot;&gt;&lt;code&gt;&amp;lt;!-- root레벨 설정 --&amp;gt;
&amp;lt;root level=&quot;INFO&quot;&amp;gt;
	&amp;lt;appender-ref ref=&quot;CONSOLE&quot; /&amp;gt;
	&amp;lt;appender-ref ref=&quot;NORMAL&quot; /&amp;gt;
	&amp;lt;appender-ref ref=&quot;ERROR&quot; /&amp;gt;
&amp;lt;/root&amp;gt;
	
&amp;lt;!-- 특정패키지 로깅레벨 설정 --&amp;gt;
&amp;lt;logger name=&quot;com.log.findlog.log2&quot; level=&quot;DEBUG&quot; additivity=&quot;false&quot;&amp;gt;
	&amp;lt;appender-ref ref=&quot;CONSOLE&quot; /&amp;gt;
	&amp;lt;appender-ref ref=&quot;NORMAL&quot; /&amp;gt;
	&amp;lt;appender-ref ref=&quot;ERROR&quot; /&amp;gt;
&amp;lt;/logger&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p id=&quot;38dd8e13-2bbf-43d4-9e16-b235cef3d3f0&quot; class=&quot;&quot;&gt;append-ref 에 들어갈 값은 append name들의 이름 입니다.&lt;/p&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;eaab961d-776f-4238-9a61-377b5164c622&quot; class=&quot;&quot;&gt;&lt;code&gt;&lt;mark class=&quot;highlight-brown&quot;&gt;root &lt;/mark&gt;&lt;/code&gt;설정은 spring 의 전박적인 package의 log 설정과 level 설정 후 실행합니다.&lt;/p&gt;&lt;p id=&quot;e4bc20ba-36a7-4ad0-ab04-72145e46a986&quot; class=&quot;&quot;&gt;&lt;code&gt;&lt;mark class=&quot;highlight-brown&quot;&gt;logger&lt;/mark&gt;&lt;/code&gt;&lt;mark class=&quot;highlight-brown&quot;&gt; &lt;/mark&gt;설정은&lt;mark class=&quot;highlight-brown&quot;&gt; &lt;/mark&gt;특정 pacakge에 관한 log 설정과 level 설정후 실행합니다.&lt;/p&gt;&lt;p id=&quot;19765f82-a4ad-4786-ad36-ed25ed496cde&quot; class=&quot;&quot;&gt;console 또는 logfile 의 내용들을 실행하며 이전에 설정해놓은 appender 들을 실행하는 곳입니다.&lt;/p&gt;&lt;h2 id=&quot;03060ff7-1546-4972-8829-ba21b581ba4b&quot; class=&quot;&quot;&gt;마치며..&lt;/h2&gt;&lt;p id=&quot;8caf17d9-6b97-46e8-8311-816928be1746&quot; class=&quot;&quot;&gt;기본적인 사용법과 설정을 알아 보았습니다. 이걸로 apache에서 제공하는 log 보다는 이부분을 사용하여 log파일을 따로&lt;/p&gt;&lt;p id=&quot;0473da57-11d1-4dd8-afbb-22aeb746c65f&quot; class=&quot;&quot;&gt;관리하는게 이점이 크다고 생각 합니다. 여러 블로그들을 확인하여 본 결과 로그파일의 크기는 100MB 정도로 하고 180일을 주기로&lt;/p&gt;&lt;p id=&quot;3c327911-9427-4ee6-86f2-1c15ab0fd245&quot; class=&quot;&quot;&gt;log파일들을 관리를 한다고 합니다 (물론 이점이 무조건 맞다는 아닙니다) 다음 번에는 properties에서 설정 하는 법을 확인해보도록 하겠습니다.&lt;/p&gt;&lt;p id=&quot;1bda9a06-a679-4ee3-ae35-66aad1957bfc&quot; class=&quot;&quot;&gt;감사합니다!!&lt;/p&gt;&lt;h3 id=&quot;2dba1a66-2463-4cf9-a8bf-e536dd85d084&quot; class=&quot;&quot;&gt;참조&lt;/h3&gt;&lt;p id=&quot;b2bb613a-c10d-472f-8386-9772a2635afd&quot; class=&quot;&quot;&gt;&lt;a href=&quot;https://tecoble.techcourse.co.kr/post/2021-08-07-logback-tutorial/&quot;&gt;https://tecoble.techcourse.co.kr/post/2021-08-07-logback-tutorial/&lt;/a&gt;&lt;/p&gt;&lt;p id=&quot;e29290a1-7aaa-4ae7-b17c-1b8ea8b138ba&quot; class=&quot;&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=1MD5xbwznlI&quot;&gt;[10분 테코톡] ☂️ 검프의 Logging(로깅) #1 - YouTube&lt;/a&gt;&lt;/p&gt;&lt;p id=&quot;c91ced32-ed55-49c0-bb07-3a94f7de9cfe&quot; class=&quot;&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=JqZzy7RyudI&quot;&gt;[10분 테코톡] ☂️ 검프의 Logging(로깅) #2 - YouTube&lt;/a&gt;&lt;/p&gt;&lt;p id=&quot;d8ce160d-ccb6-41c6-b5f6-bd92362e98bc&quot; class=&quot;&quot;&gt;
&lt;/p&gt;&lt;div class=&quot;n2t_comment&quot;&gt;&lt;p&gt;
&lt;/p&gt;&lt;p class=&quot;block-color-gray&quot;&gt;&lt;a href=&quot;https://boltlessengineer.github.io/Notion2Tistory&quot;&gt;Uploaded by Notion2Tistory v1.1.0&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/article&gt;</description>
      <category>SPRING/Spring Boot</category>
      <author>Eco</author>
      <guid isPermaLink="true">https://gangda.tistory.com/26</guid>
      <comments>https://gangda.tistory.com/26#entry26comment</comments>
      <pubDate>Mon, 7 Mar 2022 23:22:01 +0900</pubDate>
    </item>
    <item>
      <title>Profile.active 설정 정보 (작성중..)</title>
      <link>https://gangda.tistory.com/25</link>
      <description>&lt;article id=&quot;bb5cd829-336e-48f9-9abe-31d304f926fe&quot; class=&quot;page sans Notion_P&quot;&gt;
&lt;div class=&quot;page-body&quot;&gt;
&lt;h3 id=&quot;18afa5c3-6007-4f1f-9558-c2a1e05cb2d0&quot; class=&quot;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;&amp;lt;피드백 언제나 환영합니다! 댓글 감사합니다&amp;gt;&lt;/mark&gt;&lt;/h3&gt;
&lt;p id=&quot;cb3ff224-05d6-4dad-94b9-544a46be2948&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;우리는 properteis 또는 yml 을 통해 spring의 설정을 합니다. 실무에서의 개발에서는 application은 다양한 환경에서 일어납니다.&lt;/p&gt;
&lt;ul id=&quot;8a117555-4fcd-4c6a-9301-b188b4ac88bd&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;dev &amp;rarr; application-dev &amp;rarr; 개발환경&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;71ae00a7-5634-459a-9409-af3a405d471b&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;test &amp;rarr; application-test &amp;rarr; 테스트 환경&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;afa9c728-0049-41eb-9fd2-289168a5c2bc&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;prod &amp;rarr; application-prod &amp;rarr; 실서버 환경&lt;/li&gt;
&lt;/ul&gt;
&lt;p id=&quot;fc359b75-39c2-4750-b318-cdff800549b6&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;profile에 들어가는 단어는 미리 정의되어 있는것이 아닙니다. 개발자 마음이지만 통상 위의 약어를 사용 합니다.&lt;/p&gt;
&lt;h2 id=&quot;415e0149-681a-49d5-b928-346bad90fe03&quot; class=&quot;&quot; data-ke-size=&quot;size26&quot;&gt;profile 을 한 곳에서&lt;/h2&gt;
&lt;p id=&quot;2a01d2ce-a62f-4c58-889a-46da43f7a89a&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;profile을 한곳에서 전부 정의하여 쓰는 방법이다. yml 에서만 사용 가능하다 &amp;rarr; &lt;b&gt;&lt;mark class=&quot;highlight-red&quot;&gt;추천하지 않는 방법이다.&lt;/mark&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul id=&quot;baa9ffd9-b089-4324-b611-32727bad6a0f&quot; class=&quot;toggle&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;details&gt;
&lt;summary&gt;application.yml&lt;/summary&gt;
&lt;pre id=&quot;52d06e12-17a7-4e34-b7a0-ccfcecc72cc2&quot; class=&quot;code yaml&quot;&gt;&lt;code&gt;spring:
  profiles:
    active: dev # 여기서 profile 의 이름을 선택해서 사용 하면 됩니다.

---
  spring:
    profiles: dev
  server:
    port: 8080

---
  spring:
    profiles: prod
  server:
    port: 9090&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p id=&quot;030d745b-7509-430f-bcfa-96986c30aa09&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;위 코드를 실제 이름을 변경하여 실행 해보면 port 가 다른부분을 확인할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;9d88eb4f-3726-415d-bb1e-f293d22e3d1a&quot; class=&quot;&quot; data-ke-size=&quot;size26&quot;&gt;profile 을 나누어서&lt;/h2&gt;
&lt;p class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;profile을 나누어서 사용하는 방법이다 &amp;rarr; &lt;mark class=&quot;highlight-red&quot;&gt;&lt;b&gt;가장 추천하는 방법이다.&lt;/b&gt;&lt;/mark&gt;&lt;/p&gt;
&lt;p id=&quot;e702bfd7-4d81-47a9-8d44-7df155878900&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;properteis 와 yml 둘다 사용할 수 있으며 application-XXX 로 구분 가능하다.&lt;/p&gt;
&lt;ul id=&quot;61fda9da-29fb-4e23-9a4c-dc5fcafa351c&quot; class=&quot;toggle&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;details&gt;
&lt;summary&gt;properteis&lt;/summary&gt;
&lt;p id=&quot;e2e10384-1d37-48ac-989a-8b68ad26bfef&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;application.properties&lt;/p&gt;
&lt;pre id=&quot;0b5e32a2-d501-4224-b8ae-59a514e62823&quot; class=&quot;code ini&quot;&gt;&lt;code&gt;# 여기서 pforiles.actiavte 의 이름을 바꾸면 됩니다.
spring.profiles.active=dev&lt;/code&gt;&lt;/pre&gt;
&lt;p id=&quot;dba6cf0b-6e1a-4157-9c88-49b64d764f31&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;application-dev.properties&lt;/p&gt;
&lt;pre id=&quot;8abbc311-86ca-4951-b116-047084266e76&quot; class=&quot;code ini&quot;&gt;&lt;code&gt;server.port=8090&lt;/code&gt;&lt;/pre&gt;
&lt;p id=&quot;873ed257-51fe-4ce0-b24b-ca1e5c33430d&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;application-prod.properties&lt;/p&gt;
&lt;pre id=&quot;79d0a5b1-90e4-4c25-b961-80a6f025d6f3&quot; class=&quot;code ini&quot;&gt;&lt;code&gt;server.port=9090&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;97964aef-ba69-4251-94f0-328c83d544b1&quot; class=&quot;toggle&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;details&gt;
&lt;summary&gt;yml&lt;/summary&gt;
&lt;p id=&quot;2c7d5e94-97c8-43a4-ad81-065a45995497&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;application.yml&lt;/p&gt;
&lt;pre id=&quot;868cb448-ec9a-49f0-8ba2-056ceb821024&quot; class=&quot;code dts&quot;&gt;&lt;code&gt;# 여기서 pforiles.actiavte 의 이름을 바꾸면 됩니다.
spring:
  profiles:
    active: dev&lt;/code&gt;&lt;/pre&gt;
&lt;p id=&quot;857209eb-75d2-4f8c-bb87-3bddbb7ed9ed&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;application-dev.yml&lt;/p&gt;
&lt;pre id=&quot;63501f4f-2e8a-4df3-abf1-8d92c8c66778&quot; class=&quot;code yaml&quot;&gt;&lt;code&gt;server:
  port: 8090&lt;/code&gt;&lt;/pre&gt;
&lt;p id=&quot;ffba05df-11f2-41e9-82cf-489e37a9c78b&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;application-prod.yml&lt;/p&gt;
&lt;pre id=&quot;413eb2af-0d22-4ebb-8e43-1c8bbfbe75da&quot; class=&quot;code yaml&quot;&gt;&lt;code&gt;server:
  port: 9090&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p id=&quot;18ee0328-9124-40e2-827c-b3f18afcb362&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;위 코드를 실행 시켜보면 port 가 다른 부분을 확인할 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;8aa448c2-f67d-4e48-8aaa-93270971be2b&quot; class=&quot;&quot; data-ke-size=&quot;size23&quot;&gt;참조&lt;/h3&gt;
&lt;p id=&quot;dcc66bbf-ccc6-41ef-ad68-808c30e8e9c9&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://lejewk.github.io/springboot-gradle-spring-profiles-active/&quot;&gt;https://lejewk.github.io/springboot-gradle-spring-profiles-active/&lt;/a&gt;&lt;/p&gt;
&lt;p id=&quot;86134cb4-a11c-4faa-9a0f-b5e86b3e7351&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://bepoz-study-diary.tistory.com/371&quot;&gt;https://bepoz-study-diary.tistory.com/371&lt;/a&gt;&lt;/p&gt;
&lt;p id=&quot;85a85ed7-44c1-44e3-a702-35421f1a6a9a&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;n2t_comment&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;block-color-gray&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://boltlessengineer.github.io/Notion2Tistory&quot;&gt;Uploaded by Notion2Tistory v1.1.0&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/article&gt;</description>
      <category>SPRING/Spring Boot</category>
      <author>Eco</author>
      <guid isPermaLink="true">https://gangda.tistory.com/25</guid>
      <comments>https://gangda.tistory.com/25#entry25comment</comments>
      <pubDate>Wed, 2 Mar 2022 23:27:15 +0900</pubDate>
    </item>
    <item>
      <title>Pattern</title>
      <link>https://gangda.tistory.com/23</link>
      <description>&lt;article id=&quot;3f0e1884-f86c-4dbc-9cfb-699243690767&quot; class=&quot;page sans Notion_P&quot;&gt;
&lt;div class=&quot;page-body&quot;&gt;
&lt;h3 id=&quot;707d298d-4cfc-4bab-9602-cde19bb1f852&quot; class=&quot;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;&amp;lt;피드백 언제나 환영합니다! 댓글 감사합니다&amp;gt;&lt;/mark&gt;&lt;/h3&gt;
&lt;p id=&quot;bce3b2e7-cd96-4457-922f-5e4c5afd6841&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;java 에서 정규표현식을 사용하려면 반드시 알아야하는 Pattern, Matcher Class가 있습니다. (JDK 17 사용)&lt;/p&gt;
&lt;p id=&quot;3cc122af-ae9a-42b5-a6d0-39efa9e56e7a&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;제가 사용해 보면서 꼭 필요한 기준으로 정리하려 합니다.&lt;/p&gt;
&lt;p id=&quot;6ccf86bf-0e8e-4684-8bc0-9daa0054d7df&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;먼저, 사용하기에 앞서 정규식 표현방법을 알아야 합니다.&lt;/p&gt;
&lt;ul id=&quot;f547fe6a-5ac2-41a1-bf77-628257a8e06a&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;a href=&quot;https://gngsn.tistory.com/51&quot;&gt;https://gngsn.tistory.com/51&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;fab950c6-3f04-41da-8cea-31549a6c2a8e&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;a href=&quot;https://gngsn.tistory.com/52&quot;&gt;https://gngsn.tistory.com/52&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;8d72c2f4-b8de-436d-8481-646975d18e59&quot; class=&quot;&quot; data-ke-size=&quot;size26&quot;&gt;Pattern Class&lt;/h2&gt;
&lt;p id=&quot;b97da0ad-e3b0-4aa4-9aa8-f3ad7e2ca0aa&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;정규 표현식에 대상 문자열을 검증하는 기능으로 일치 불일치로 true, false를 반환합니다.&lt;/p&gt;
&lt;p id=&quot;e46a95f1-6dfe-4424-a485-11d7900a6fdc&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;주로 검증에 활용 됩니다.&lt;/p&gt;
&lt;h2 id=&quot;bee8b2eb-c82b-4b76-b629-4ffddca68917&quot; class=&quot;&quot; data-ke-size=&quot;size26&quot;&gt;Matcher Class&lt;/h2&gt;
&lt;p id=&quot;5e138d51-e219-410e-a77a-1d7db041e5aa&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;Pattern Class를 받아 대상 문자열과 패턴이 일치하는 부분을 찾거나 전체일치 여부등을 판별하기위해 사용됩니다.&lt;/p&gt;
&lt;h2 id=&quot;6e418bd2-2b65-4918-9877-1e7c93f4b891&quot; class=&quot;&quot; data-ke-size=&quot;size26&quot;&gt;활용&lt;/h2&gt;
&lt;p id=&quot;c31d8904-cf0d-4d93-b599-f3bcd73f294f&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;먼저 코드와 코드 결과를 본후 이어 설명하겠습니다&lt;/p&gt;
&lt;pre id=&quot;245bbaf4-d4c1-4f0d-bf0f-107e551b8a00&quot; class=&quot;code arduino&quot;&gt;&lt;code&gt;public class Main {

    public static void main(String[] args) {
        String operator = &quot;[+*/-]&quot;;
        String number = &quot;[0-9]+&quot;;
        String value = &quot;123+456&quot;;

        Pattern operatorCompile = Pattern.compile(operator);
        Matcher operatorMatcher = operatorCompile.matcher(value);
        String[] split = operatorCompile.split(value);

        for (String s : split) {
            System.out.println(&quot;split = &quot; + s);
        }

        boolean isValid = operatorMatcher.find();
        if (isValid) {
            System.out.println(&quot;operatorMatcher = &quot; + operatorMatcher.group());
        }

        Matcher numberMatcher = Pattern.compile(number).matcher(value);
        while (numberMatcher.find()) {
            System.out.println(&quot;numberMatcher = &quot; + numberMatcher.group());
        }

        List&amp;lt;String&amp;gt; oldNumberMatcherList = numberMatcher.results().map(MatchResult::group).toList();
        System.out.println(&quot;oldNumberMatcherList = &quot; + oldNumberMatcherList);

        List&amp;lt;String&amp;gt; newNumberMatcherList = Pattern.compile(number).matcher(value)
                .results().map(MatchResult::group).toList();
        System.out.println(&quot;newNumberMatcherList = &quot; + newNumberMatcherList);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul id=&quot;ecef274d-f0bb-4f8f-9241-0b48378ceda3&quot; class=&quot;toggle&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;details&gt;
&lt;summary&gt;결과&lt;/summary&gt;
&lt;pre id=&quot;22a7cacc-6291-4a49-8e32-2f350a4621c4&quot; class=&quot;code ini&quot;&gt;&lt;code&gt;split = 123
split = 456
operatorMatcher = +
numberMatcher = 123
numberMatcher = 456
oldNumberMatcherList = []
newNumberMatcherList = [123, 456]&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;06e869a1-64d9-4b52-b5e2-98251987418f&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;Pattern compile(regex)String 값으로 들어온 정규식을 Pattern 객체로 바꿔주는 역활을 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;eb9d1cfc-4270-4689-99db-86514f829aa2&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;Matcher matcher(value)들어온 value 값과 compile 에 설정한 정규식이 매칭되게 Matcher 객체를 만들어 줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;da48ae69-2f35-4adb-a624-0438b303b1ce&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;String split(value) [Patter 파생]Pattern의 regx 값과 value를 비교하여 regx 값의 항목 중심으로 문자열을 자릅니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;6fbe92ce-362c-4085-b459-bfc8dec37635&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;boolean find() [Matcher 파생]regx 값과 value 값에서 일치한 값이 있으면&lt;mark class=&quot;highlight-orange&quot;&gt;true &lt;/mark&gt;없으면&lt;mark class=&quot;highlight-orange&quot;&gt;false&lt;/mark&gt; 를 반환합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;f1e60cd4-063c-4430-a261-880c5048677d&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;String group [Matcher 파생]regx 값과 value 값에서 일치한 문자열을 반환 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;d6b57728-eed1-4334-a9b4-be40798524ba&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;Stream&amp;lt;&amp;gt; results() [Matcher 파생]Matcher 에서 나온 값들을 stream화 합니다.&lt;/li&gt;
&lt;li id=&quot;d3dfd9de-2f69-4630-94e8-0b8c45ae76ba&quot; class=&quot;&quot;&gt;.results().map(...) 처럼 stream화 하여 list 형태로 뽑아 사용 가능합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;854969a0-6c3f-402b-b2b2-30ededc547e2&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;String replaceAll(replacement)패턴과 일치하는 모든 문자열을 replacement 로 변경&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;ab268675-291f-4878-9d37-7f53489f5407&quot; class=&quot;&quot; data-ke-size=&quot;size23&quot;&gt;확인해 봐야할 점&lt;/h3&gt;
&lt;p id=&quot;1ce7466b-80b9-450f-97df-cb08352e631d&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;oldNumberMatcherList&lt;/code&gt; &lt;code&gt;newNumberMatcherList&lt;/code&gt; 를 비교를 해보자&lt;/p&gt;
&lt;ul id=&quot;d51047d9-1aeb-46b0-aba6-0278d3a39909&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;code&gt;oldNumberMatcherList&lt;/code&gt; 의 경우 &lt;code&gt;numberMatcher&lt;/code&gt; 에서 find() &amp;rarr; group() 을하여 값을 사용결과 에서 보듯 값이 list에 안담아지는걸 확인이 가능하다&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;a189c3de-8104-49c6-8107-57254b73458b&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;code&gt;newNumberMatcherList&lt;/code&gt; 처럼 값을 사용 하고 싶은곳에 따로 사용 하여야 한다 (여러번 사용불가)&lt;/li&gt;
&lt;/ul&gt;
&lt;p id=&quot;66d449a1-e229-4c7d-bba2-8538a753ee9e&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;700c9e4c-05fa-46ee-9a20-80b3ccf6783b&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;923a787f-f1f7-495a-8ee9-c310cae59b2b&quot; class=&quot;&quot; data-ke-size=&quot;size23&quot;&gt;참고&lt;/h3&gt;
&lt;ul id=&quot;512fbf26-bda2-48e2-a9c0-e098017d9620&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;a href=&quot;https://coding-factory.tistory.com/529&quot;&gt;https://coding-factory.tistory.com/529&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;c15e6a12-76a2-4a7f-9c31-c875855c3e3c&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;a href=&quot;https://gngsn.tistory.com/53&quot;&gt;https://gngsn.tistory.com/53&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;1b86777b-45b6-4ca3-93f0-eb2165fc46d0&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;a href=&quot;https://girawhale.tistory.com/77&quot;&gt;https://girawhale.tistory.com/77&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p id=&quot;b0363d85-84dd-4413-83b3-1ec344c08cf0&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;n2t_comment&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;block-color-gray&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://boltlessengineer.github.io/Notion2Tistory&quot;&gt;Uploaded by Notion2Tistory v1.1.0&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/article&gt;</description>
      <category>JAVA</category>
      <author>Eco</author>
      <guid isPermaLink="true">https://gangda.tistory.com/23</guid>
      <comments>https://gangda.tistory.com/23#entry23comment</comments>
      <pubDate>Tue, 15 Feb 2022 14:25:58 +0900</pubDate>
    </item>
    <item>
      <title>Java Optional2</title>
      <link>https://gangda.tistory.com/22</link>
      <description>&lt;article id=&quot;ec397781-b70b-410f-9023-812fd4a76dec&quot; class=&quot;page sans Notion_P&quot;&gt;
&lt;div class=&quot;page-body&quot;&gt;
&lt;h3 id=&quot;2f3e781b-9972-401a-8a37-de276eda7c45&quot; class=&quot;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;&amp;lt;피드백 언제나 환영합니다! 댓글 달아주세요 감사합니다&amp;gt;&lt;/mark&gt;&lt;/h3&gt;
&lt;p id=&quot;e249a74e-0ed3-498e-997b-5eeb196dae9a&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://gangda.tistory.com/18&quot;&gt;Java Optional 1 &lt;/a&gt;에서 정확한 설명을 하지 못해서 보충 설명 및 사용시 주의사항 위주로 이야기 해보려고 합니다.&lt;/p&gt;
&lt;ul id=&quot;16bcb8fe-c143-408d-a1ee-6c3c3f3f29a4&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;orElse, orElseGet두 메소드의 차이점을 쉽게 생각하려다보니 놓친 부분이 있다.orElseGet(Supplier ...) &amp;rarr; other.get()이 실행이된다 &amp;rarr; value 값이 null 인 경우에 method 가 실행이 되는형태 (method 가 들어온 형태라면)&lt;/li&gt;
&lt;li id=&quot;3847af38-4b5e-4f66-8875-810e0e5cf3d8&quot; class=&quot;&quot;&gt;orElse(T other) &amp;rarr; 안에 있는 값이 무조건 실행되는걸 확인할 수있다. 즉, println() 과 같은 형태이다. 즉 T other 에 method가 들어간 형태이기 때문 (반환값이 있는)&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;d868c5e1-7e49-4682-8772-15067f12a7a6&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;Optional.steam() 통해 스트림을 생성(Java 9부터 추가) &amp;rarr; Optional은 stream용 메서드가 아니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;6aaf127b-0ed3-40de-9262-9b49231b4c2a&quot; class=&quot;&quot; data-ke-size=&quot;size26&quot;&gt;Java Optional 주의사항&lt;/h2&gt;
&lt;p id=&quot;1a55725e-aed9-453c-a004-58460e4a211a&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;앞전에도 말했듯이 Optional은 Wrapper class 입니다 &amp;rarr; Wrapper class 는 비용문제가 발생 &amp;rarr; 객체 생성, 참조 비용...&lt;/p&gt;
&lt;p id=&quot;951bdbaa-7718-4061-8849-ccab9babbf30&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;primitive type 비해 비싸다 필요할 때만 써야합니다. &lt;b&gt;Effective Java 에서 Optional &lt;/b&gt;활용에 따르면&lt;/p&gt;
&lt;ul id=&quot;6b7f57dc-a3dc-4301-ab87-426334a49170&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;b&gt;Optional 활용1 - 기본값(defalut)를 정해둘 수 있다.&lt;/b&gt;
&lt;ul id=&quot;02dd03ff-d3c3-4f03-8e66-390076196d38&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: circle;&quot;&gt;&lt;code&gt;optionalS1.orElse(&amp;rdquo;이름 없음&amp;rdquo;);&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;183848d0-c37e-4a5d-8269-38489428091f&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;b&gt;Optional 활용2 - 원하는 예외를 던질 수 있다.&lt;/b&gt;
&lt;ul id=&quot;c5f95f3e-d13c-4dcc-a30e-8d0ecb0364b2&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: circle;&quot;&gt;값이 없는경우 원하는 예외를 던져 사용이 가능하다&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;89dbf06f-a9c3-40da-a79e-7fff8e1e9135&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: circle;&quot;&gt;&lt;code&gt;optionalS1.orElseThrow(Exception::new);&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;ab815dc0-a4a5-4027-bebc-779b89842586&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;b&gt;Optional 활용3 - 항상 값이 채워져 있는 경우&lt;/b&gt;
&lt;ul id=&quot;0262de42-99b4-4a1a-8d34-af415546903c&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: circle;&quot;&gt;.get()을 이용하여 출력 &amp;rarr; 값이 있다고 확신이 들때만 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;db456089-076e-4263-a9d3-769c8e2450e8&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;b&gt;Optional 활용4 - 기본값을 설정하는 비용이 큰 경우&lt;/b&gt;
&lt;ul id=&quot;64ca60ac-274b-4dc1-80f3-72271332db8f&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: circle;&quot;&gt;활용1 에서 기본값 비용이 클경우 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;535446ee-fd9d-476a-809d-df049a5f885e&quot; class=&quot;&quot; data-ke-size=&quot;size23&quot;&gt;Java Optional 안티 패턴&lt;/h3&gt;
&lt;ul id=&quot;74267644-5162-4db4-91b8-4268a3e6eb0c&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;b&gt;Collection, Stream, 배열은 Optional로 되도록이면 감싸지 말자&lt;/b&gt;
&lt;ul id=&quot;318d7047-9024-4f08-9d55-8e4281a7c71e&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: circle;&quot;&gt;List 는 값을 담아두는 그릇 &amp;rarr; 빈 ArrayList를 반환하면 된다. &amp;rarr; Optional 처리코드를 넣지 않아도 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;cc95109d-e4a6-461d-a0b9-e529296ee06e&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;b&gt;Optional을 Map의 키나 값으로 사용 금지&lt;/b&gt;
&lt;ul id=&quot;86d9ca97-48fc-49ed-9b5b-a31349d649e8&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: circle;&quot;&gt;key 자체가 없는경우&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;bc91aa6d-1f35-4444-9a2d-206c92465c3f&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: circle;&quot;&gt;key는 있지만, 속이 빈 Optional 인경우&lt;/li&gt;
&lt;/ul&gt;
&amp;rarr; 쓸데없이 복잡도만 높아지게되고 쓸모없는짓중 하나입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;69e57522-8ac9-4c6d-9318-c9fd780b030c&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;b&gt;isPresent() 를 사용하지 말자&lt;/b&gt;
&lt;ul id=&quot;72a69ff9-9337-479a-ab77-3ebb0700dbef&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: circle;&quot;&gt;if 문을 벗어나기위해 Optional을 사용한거다.. 이점을 꼭 생각해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;c7c69af1-648e-4baf-87a5-ff9e9a7e7010&quot; class=&quot;&quot; data-ke-size=&quot;size23&quot;&gt;추가적으로 알아야 할 것들&lt;/h3&gt;
&lt;ul id=&quot;b014551e-9d0c-4734-8299-95086f6ef42b&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;박싱된 기본타입 사용시 &amp;rarr; OptionalInt, OptionalDouble, OptionalLong 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;ed98ad26-db20-40bf-9646-dffc7e0eeed1&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;값을 반환하지 못할 가능성이 있고, 호출할 때마다 반환값이 없을 가능성을 염두에 둬야하는 메소드 &amp;rarr; Optional을 반환해야하는 상황일 수 있다. (JpaRepository save() 같은 기능들)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;1a70ebcc-6600-4490-8da0-06f04a5af550&quot; class=&quot;&quot; data-ke-size=&quot;size26&quot;&gt;추가 Optional Method&lt;/h2&gt;
&lt;p id=&quot;53de2c1f-476b-4518-86df-12630887709b&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://gangda.tistory.com/18&quot;&gt;Java Optional 1 :: Eco 의 개발일기&lt;/a&gt; 에서 get(), orElseThorw(), orElse(), orElseGet()외 다른 method를 확인 해보겠습니다.&lt;/p&gt;
&lt;ul id=&quot;cf3af87a-5292-4d01-99ca-5b2582e46f4e&quot; class=&quot;toggle&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;details&gt;
&lt;summary&gt;예제 class&lt;/summary&gt;
&lt;pre id=&quot;2873819f-7cf7-4708-b855-8ea28fa51c85&quot; class=&quot;code dart&quot;&gt;&lt;code&gt;@Data
static class Team{
	Subject subject;
	List&amp;lt;Member&amp;gt; memberList;
}
@Data
static class Subject{
	String gameName;
}
@Data
static class Member {
	Long id;
	String name;
	String email;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;1bf8f1b4-e0c6-42df-8996-64e6ebfc8008&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;b&gt;void ifPresent(Consumer&amp;lt;? super T&amp;gt; consumer)&lt;/b&gt;
&lt;ul id=&quot;32ae4a34-cb70-4657-869c-28392f6c7e95&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: circle;&quot;&gt;Optional 내부의 값이 있는 경우 consumer 함수를 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;1144cbf5-dfbf-45d8-a3af-2291a2005520&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;b&gt;Optional&amp;lt;T&amp;gt; filter(Predicate&amp;lt;T&amp;gt; predicate)&lt;/b&gt;
&lt;ul id=&quot;f90314a1-189a-4019-8804-bb4ee26d2d34&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: circle;&quot;&gt;Optional에 filter 조건을 걸어 조건에 맞을 때만 Optional 내부 값이 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;7b2b23dc-f7e6-43d6-8de2-944041744dd9&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: circle;&quot;&gt;조건이 맞지 않으면 Optional.empty를 리턴&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;6873f02c-ab5d-430e-a392-f0371d7fc9ea&quot; class=&quot;toggle&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;details&gt;
&lt;summary&gt;Optional.filter() 예제&lt;/summary&gt;
&lt;pre id=&quot;1588a3de-4339-4d88-a5ca-ec8cb3473e0e&quot; class=&quot;code reasonml&quot;&gt;&lt;code&gt;Member member1 = new Member(1L, &quot;hello1&quot;);
Member member2 = new Member(null, null);
List&amp;lt;Member&amp;gt; memberList = new ArrayList&amp;lt;&amp;gt;(List.of(member1, member2));

Subject subject = new Subject();
subject.setGameName(&quot;LOL&quot;);

Team team = new Team();
team.setMembers(memberList);
team.setSubject(subject);
Team team1 = Optional.ofNullable(team)
        .filter(item -&amp;gt; item.getSubject().getGameName().equals(&quot;LOL&quot;))
        .orElse(null);
System.out.println(&quot;team1 = &quot; + team1);
/*team1 = OptionalJava.Team(subject=OptionalJava.Subject(gameName=LOL), 
					members=[OptionalJava.Member(id=1, name=hello1, email=null), 
										OptionalJava.Member(id=null, name=null, email=null)])
/*&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;3404617a-5308-4e0f-9817-65e954886d20&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;b&gt;Optional&amp;lt;U&amp;gt; map(Funtion&amp;lt;? super T, ? extends U&amp;gt; f)&lt;/b&gt;
&lt;ul id=&quot;1391210c-42e5-445f-b503-790aebf3fcf6&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: circle;&quot;&gt;Optional 내부의 값을 Function을 통해 가공&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;cd97421e-50db-4e14-bd7f-cd49a339d0f8&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: circle;&quot;&gt;Optional.empty를 리턴&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;ecef4efc-46d6-400a-b644-77d30efa8bf7&quot; class=&quot;toggle&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;details&gt;
&lt;summary&gt;Optional.map() 예제&lt;/summary&gt;
&lt;pre id=&quot;317dad8a-e7c2-4b8c-aa41-cbc217714960&quot; class=&quot;code reasonml&quot;&gt;&lt;code&gt;Team team = new Team();
String gameObject = Optional.ofNullable(team)
								.map(Team::getSubject)
                .map(Subject::getGameName)
                .orElse(&quot;game 종목이 없네&quot;);
System.out.println(&quot;gameObject = &quot; + gameObject );
/* 게임종목이 없네/*&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;bc80804c-2ef9-4d9f-a3c0-33c432bff540&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;Stream을 이용한 Optional중간에 비어있는 Optional 객체가 반환되는 경우, Stream.empty()가 반환되며 함수 체이닝이 더 이상 진행되지 않는점을 유의하자. 스트림 연산이 멈춘다.
&lt;ul id=&quot;44e5da62-edcd-49af-a504-7a986af3c192&quot; class=&quot;toggle&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;details&gt;
&lt;summary&gt;Stream 예제 코드&lt;/summary&gt;
&lt;pre id=&quot;308cfa9e-ede3-47f6-9f0f-75d5014eefd3&quot; class=&quot;code reasonml&quot;&gt;&lt;code&gt;List.of(4, 3, 2, 5)
		.stream() // stream으로 복사해서 사용가능하다.
		.map(value -&amp;gt; value &amp;gt; 2 ? Optional.of(value) : Optional.empty())
		.flatMap(Optional::stream)
		.forEach(System.out::println);
/* 3
	 4
	 5 */&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;&lt;/li&gt;
&lt;/ul&gt;
물론 람다식과 메서드 레퍼런스는 선택사항이다. 꼭 필요하다면 익명클래스를 사용해도 상관없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;8aa1b8a5-a7ca-4251-854e-d532b3ccefd4&quot; class=&quot;&quot; data-ke-size=&quot;size26&quot;&gt;참고&lt;/h2&gt;
&lt;ul id=&quot;e1e2610b-e502-4302-90a7-c3920a55bb76&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;a href=&quot;https://jiwondev.tistory.com/89&quot;&gt;#12. Optional API (Null값 처리) (tistory.com)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;bc09d88b-66a4-4256-b8fd-edad37d8babf&quot; class=&quot;bulleted-list&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;a href=&quot;https://jaehun2841.github.io/2019/02/24/effective-java-item55/#optional-%ED%99%9C%EC%9A%A93-%ED%95%AD%EC%83%81-%EA%B0%92%EC%9D%B4-%EC%B1%84%EC%9B%8C%EC%A0%B8-%EC%9E%88%EB%8A%94-%EA%B2%BD%EC%9A%B0&quot;&gt;Item 55. 옵셔널 반환은 신중히 하라 | Carrey`s 기술블로그 (jaehun2841.github.io)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p id=&quot;8785c1e8-c621-4208-bad4-84bd929a53b5&quot; class=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;n2t_comment&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;block-color-gray&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://boltlessengineer.github.io/Notion2Tistory&quot;&gt;Uploaded by Notion2Tistory v1.1.0&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/article&gt;</description>
      <category>JAVA</category>
      <category>java8</category>
      <author>Eco</author>
      <guid isPermaLink="true">https://gangda.tistory.com/22</guid>
      <comments>https://gangda.tistory.com/22#entry22comment</comments>
      <pubDate>Thu, 3 Feb 2022 15:28:32 +0900</pubDate>
    </item>
    <item>
      <title>Tomcat SSL 적용 (Windows)</title>
      <link>https://gangda.tistory.com/21</link>
      <description>&lt;article id=&quot;8caa38b1-eaa4-4e78-adf3-9a83fccf45b0&quot; class=&quot;page sans Notion_P&quot;&gt;&lt;div class=&quot;page-body&quot;&gt;&lt;p id=&quot;75a1a86e-b9ed-4815-a35f-fce07c5f0712&quot; class=&quot;&quot;&gt;협력업체가 http → https 로 변경을 원하는 상황입니다. 검증된 SSL 인증서를 구하여 적용 하겠으나, 
test를위해 임의의 인증서를 만들어보고 적용해보겠습니다. (window 입니다, Linux는 나중에...)&lt;/p&gt;&lt;p id=&quot;a9359c5e-1608-40a8-bfcf-b6e8dc7bd331&quot; class=&quot;&quot;&gt;openSSL을 사용하여 임이의 인증서를 만들 예정입니다 (아래 링크에서openSSL 사용법이 있습니다.)&lt;/p&gt;&lt;figure id=&quot;1e91f2a9-306a-434b-97eb-0ceaa45c1daa&quot;&gt;&lt;a href=&quot;https://www.lesstif.com/software-architect/openssl-command-tip-7635159.html&quot; class=&quot;bookmark source&quot;&gt;&lt;div class=&quot;bookmark-info&quot;&gt;&lt;div class=&quot;bookmark-text&quot;&gt;&lt;div class=&quot;bookmark-title&quot;&gt;OpenSSL 자주 쓰는 명령어(command) 및 사용법, tip 정리&lt;/div&gt;&lt;div class=&quot;bookmark-description&quot;&gt;RHEL/CentOS Linux 는 기본 패키지에 포함되어 있으므로 별도 설치를 안해도 됩니다. Windows 나 기타 Unix 에서 설치는 OpenSSL 컴파일(compile) &amp;amp; 빌드(build) 참고하세요 설치된 openssl 의 version 은 다음 명령어로 확인할 수 있습니다.&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;bookmark-href&quot;&gt;&lt;img src=&quot;https://www.lesstif.com/download/attachments/12025869/SA?version=1&amp;amp;amp;modificationDate=1477314931000&amp;amp;amp;api=v2&quot; class=&quot;icon bookmark-icon&quot;&gt;https://www.lesstif.com/software-architect/openssl-command-tip-7635159.html&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;&lt;p id=&quot;90b55f7c-0161-49ae-be42-cb5be8cd9e57&quot; class=&quot;&quot;&gt;OpenSSL을 다운로드 받는거보다 gitBash에서 지원을 해주니 그부분을 사용 하겠습니다.&lt;/p&gt;&lt;pre id=&quot;495b8778-b108-41d3-9814-a9ce7178ecba&quot; class=&quot;code&quot;&gt;&lt;code&gt;#gitBash, 원하는 디렉토리에 들어가서 실행 하면 됩니다
openssl version // 버전확인이 가능합니다.&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;block-color-gray_background callout&quot; style=&quot;white-space:pre-wrap;display:flex&quot; id=&quot;a314080d-3170-44e9-9497-4d1c0743fec8&quot;&gt;&lt;div style=&quot;font-size:1.5em&quot;&gt;&lt;span class=&quot;icon&quot;&gt; &lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;width:100%&quot;&gt;윈도우에서 openssl pkcs export 멈춤현상 → window 터미널 입출력 문제 → 유닉스 터미널 동작필요(winpty)
winpty bash&lt;/div&gt;&lt;/figure&gt;&lt;ul id=&quot;ca686304-bc39-4d65-b58f-074b95426f82&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;openssl req -newkey rsa:2048 -nodes -keyout &lt;mark class=&quot;highlight-teal&quot;&gt;key.pem &lt;/mark&gt;-x509 -days 365 -out &lt;mark class=&quot;highlight-teal&quot;&gt;certificate.pem&lt;/mark&gt;&lt;br&gt;
개인키 생성 → 이름, city 등등 정보를 적어야 한다&lt;ul id=&quot;d27445e9-4888-4a32-aea0-b6d255099d01&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;입력 값(test형태로 입력 바꿔도 됩니다.)&lt;/summary&gt;&lt;pre id=&quot;e7dc5298-710c-4bb6-a072-c1c27374d6f0&quot; class=&quot;code&quot;&gt;&lt;code&gt;Country Name (2 letter code) [AU]:82
State or Province Name (full name) [Some-State]:testName
Locality Name (eg, city) []:busan
Organization Name (eg, company) [Internet Widgits Pty Ltd]:testCompany
Organizational Unit Name (eg, section) []:testSection
Common Name (e.g. server FQDN or YOUR name) []:TEST
Email Address []:test@gmail.com&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;cafbb026-c473-4576-bbda-276d1fcb3aa1&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;openssl x509 -text -noout -in &lt;mark class=&quot;highlight-teal&quot;&gt;certificate.pem&lt;br&gt;
&lt;/mark&gt;작성된 인증서 검토&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;b0af85b6-0fd8-4eb0-ad3a-1dfbbf156996&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;openssl pkcs12 -inkey key.pem -in &lt;mark class=&quot;highlight-teal&quot;&gt;certificate.pem&lt;/mark&gt; -export -out &lt;mark class=&quot;highlight-teal&quot;&gt;certificate.p12&lt;/mark&gt;&lt;br&gt;
pkcs12(p12) 로 인증서 결합&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;6d278b6d-8983-46b5-aa07-6f507acf78b9&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;openssl pkcs12 -in &lt;mark class=&quot;highlight-teal&quot;&gt;certificate.p12&lt;/mark&gt; -noout -info&lt;br&gt;
pkcs12 유효성 검증&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;2ce2c744-fa72-4455-ad1c-4e5cbee48f12&quot; class=&quot;&quot;&gt;1. Spring (내장톰켓)에 적용해 봅시다.&lt;/h2&gt;&lt;p id=&quot;82b009d5-9414-4c63-86f9-2b9bf1846ab8&quot; class=&quot;&quot;&gt;먼저 전 ui와 api단을 나눠서 진행 하겠습니다 → 둘다 ssl 을 적용시킨후 하고 싶지만 아직 ui 쪽만 가능합니다.
→ api와의 ssl 통신은 다음에 적용되는 즉시 포스팅 해보겠습니다.&lt;/p&gt;&lt;p id=&quot;f668d7d7-16bb-431e-9441-30c4610e99ad&quot; class=&quot;&quot;&gt;application.properties&lt;/p&gt;&lt;pre id=&quot;bd126eca-f91c-424f-8bfa-24d6ea8e2921&quot; class=&quot;code&quot;&gt;&lt;code&gt;server.ssl.enabled=true
#파일위치
server.ssl.key-store=D:/apach/certificate.p12
#비밀번호
server.ssl.key-store-password=test123&lt;/code&gt;&lt;/pre&gt;&lt;p id=&quot;d95d0d71-1de3-41ad-8c8a-a04823ca21a0&quot; class=&quot;&quot;&gt;첫 사진은 http로 접근시 입니다 두번재 사진은 https 로 접근시 입니다.&lt;/p&gt;&lt;ul id=&quot;340ed840-1471-4afb-b6a4-d82651be84fe&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;https 로 접근시 임의로 만든 ssl 이기 때문에 인증이 되지않아 접근이막힙니다.
 이부분을 연결로 하여 들어가면 가능 합니다.&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;a7906205-3c9d-40f1-8d58-cac1a3907643&quot; class=&quot;&quot;&gt;→ 두번재 사진처럼 주의요함이 뜨는게 정상입니다 (chrome 에서는 인증을 안해주었기 때문에)&lt;/p&gt;&lt;ol type=&quot;1&quot; id=&quot;6c41b792-eb01-4904-bec4-0c599d53ad92&quot; class=&quot;numbered-list&quot; start=&quot;1&quot;&gt;&lt;li&gt;http 접근&lt;figure id=&quot;c0841b92-d012-4b88-836d-30f09f2c149f&quot; class=&quot;image&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lRsJF/btrrPPd5xzh/0BkprPQ02dH1lIJd2VAusk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lRsJF/btrrPPd5xzh/0BkprPQ02dH1lIJd2VAusk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lRsJF/btrrPPd5xzh/0BkprPQ02dH1lIJd2VAusk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlRsJF%2FbtrrPPd5xzh%2F0BkprPQ02dH1lIJd2VAusk%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/figure&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol type=&quot;1&quot; id=&quot;c40d7483-769f-4c1c-b471-f86cd890b1b4&quot; class=&quot;numbered-list&quot; start=&quot;2&quot;&gt;&lt;li&gt;https 접근&lt;figure id=&quot;f95dbd3a-3445-4195-9e24-810c546242d1&quot; class=&quot;image&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Tyz1j/btrrRUFxj7d/5bUhgKQNE5Tlk48ZDFkR7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Tyz1j/btrrRUFxj7d/5bUhgKQNE5Tlk48ZDFkR7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Tyz1j/btrrRUFxj7d/5bUhgKQNE5Tlk48ZDFkR7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTyz1j%2FbtrrRUFxj7d%2F5bUhgKQNE5Tlk48ZDFkR7K%2Fimg.png&quot; width=&quot;100%&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/figure&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;147d7668-7139-4cc1-8b13-4cd580d34bcb&quot; class=&quot;&quot;&gt;2. 외장 Tomcat을 이용한 배포 입니다.&lt;/h2&gt;&lt;p id=&quot;b1e28b16-9291-4252-8455-1c7a42c8cdd4&quot; class=&quot;&quot;&gt;&lt;a href=&quot;https://gangda.tistory.com/9&quot;&gt;Apache Tomcat War 배포 (Window)&lt;/a&gt; 에서 톰켓을 배포한 이후의 상황으로 하겠습니다.&lt;/p&gt;&lt;ul id=&quot;f2ca525d-2491-41da-ba06-2c0f4a65ef50&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;현재 톰켓 버전은 8.5로 하였습니다 → 나중에 톰켓 10 버전도 업로드 할 예정입니다.&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;67f072f6-071c-410e-aaf1-f768ed400b43&quot; class=&quot;&quot;&gt;→ application.properties 에서 ssl 설정을 하여도 외장 tomcat에서는 적용이 안됩니다.
따로 지정을 해줘야 합니다. 주의 사항이 있는데 ssl 적용을 하고 war 로 압축을 진행할 예정이면,
파일위치 비밀번호를 &lt;mark class=&quot;highlight-red&quot;&gt;외장톰켓 설정과 맞춰줘야 합니다&lt;/mark&gt;.&lt;/p&gt;&lt;h3 id=&quot;ec9d4487-3e9e-4880-b61f-e241859896f2&quot; class=&quot;&quot;&gt;1. tomcat/conf/server.xml&lt;/h3&gt;&lt;pre id=&quot;06b07a92-4976-459c-bbfb-f9086965f6c4&quot; class=&quot;code&quot;&gt;&lt;code&gt;&amp;lt;Connector port=&quot;기존 포트 번호&quot; protocol=&quot;HTTP/1.1&quot;
		connectionTimeout=&quot;20000&quot;
		redirectPort=&quot;SSL 적용 포트 번호&quot; /&amp;gt;

&amp;lt;Connector port=&quot;SSL 적용 포트 번호&quot; protocol=&quot;HTTP/1.1&quot; SSLEnabled=&quot;true&quot;
		maxThreads=&quot;150&quot; scheme=&quot;https&quot; secure=&quot;true&quot;
		keystoreFile=&quot;파일 경로&quot;
		keystorePass=&quot;ssl 비밀번호&quot;
		clientAuth=&quot;false&quot; sslProtocol=&quot;TLS&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p id=&quot;3fcf09ea-4894-401f-a6c2-776d7d14ae5d&quot; class=&quot;&quot;&gt;위코드를 추가 하면됩니다. 여기서 &lt;mark class=&quot;highlight-blue&quot;&gt;“기존 포트 번호”&lt;/mark&gt; : 80, &lt;mark class=&quot;highlight-blue&quot;&gt;“SSL 적용 포트 번호”&lt;/mark&gt; : 443 으로 진행 하겠습니다.&lt;/p&gt;&lt;ul id=&quot;6d020ace-17d6-4422-b3f7-7b5522c6630b&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;예시 코드&lt;/summary&gt;&lt;pre id=&quot;985a4827-164e-481a-99bd-a11d2787089f&quot; class=&quot;code&quot;&gt;&lt;code&gt;&amp;lt;Connector port=&quot;80&quot; protocol=&quot;HTTP/1.1&quot;
		connectionTimeout=&quot;20000&quot;
		redirectPort=&quot;443&quot; /&amp;gt;

&amp;lt;Connector port=&quot;443&quot; protocol=&quot;HTTP/1.1&quot; SSLEnabled=&quot;true&quot;
		maxThreads=&quot;150&quot; scheme=&quot;https&quot; secure=&quot;true&quot;
		keystoreFile=&quot;D:/apach/certificate.pkcs12&quot;
		keystorePass=&quot;test123&quot;
		clientAuth=&quot;false&quot; sslProtocol=&quot;TLS&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;82825689-40db-49cb-991a-e48e7e803406&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;80 → http 접속시 포트번호 없이 접근&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;94be130c-b518-458a-b761-9fb2fd36e465&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;443 → https 접속시 포트번호 없이 접근&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;block-color-gray_background callout&quot; style=&quot;white-space:pre-wrap;display:flex&quot; id=&quot;891c6670-0435-4438-bfcf-ab2f88100cde&quot;&gt;&lt;div style=&quot;font-size:1.5em&quot;&gt;&lt;span class=&quot;icon&quot;&gt; &lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;width:100%&quot;&gt;위 포트 외 다른 포트로 변경이 됩니다 그럴경우 도메인 뒤에 포트 번호를 붙여야 합니다
ex&amp;gt; localhost:8090/...&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;dd693193-5eb9-49d9-8b37-3c85914242cf&quot; class=&quot;&quot;&gt;2. tomcat/conf/web.xml&lt;/h3&gt;&lt;ul id=&quot;9fe09376-78d4-467f-b66a-8b3f39292e66&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;conf/web.xml&lt;/summary&gt;&lt;pre id=&quot;bfa4e64b-2062-4c5a-9711-e4facf2301f3&quot; class=&quot;code&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
....
&amp;lt;web-app xmlns=&quot;http://xmlns.jcp.org/xml/ns/javaee&quot;
	xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
	xsi:schemaLocation=&quot;http://xmlns.jcp.org/xml/ns/javaee
	http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd&quot;
	version=&quot;3.1&quot;&amp;gt;
....
&amp;lt;!-- 이 위치에 session-config 위에 코드를 적어줘야 합니다 --&amp;gt;
/* 코드 적는 위치 */
&amp;lt;session-config&amp;gt;
	&amp;lt;session-timeout&amp;gt;30&amp;lt;/session-timeout&amp;gt;
	&amp;lt;/session-config&amp;gt;
....
&amp;lt;mime-mapping&amp;gt;
	&amp;lt;extension&amp;gt;123&amp;lt;/extension&amp;gt;
	&amp;lt;mime-type&amp;gt;application/vnd.lotus-1-2-3&amp;lt;/mime-type&amp;gt;
&amp;lt;/mime-mapping&amp;gt;
&amp;lt;mime-mapping&amp;gt;
	&amp;lt;extension&amp;gt;3dml&amp;lt;/extension&amp;gt;
	&amp;lt;mime-type&amp;gt;text/vnd.in3d.3dml&amp;lt;/mime-type&amp;gt;
	&amp;lt;/mime-mapping&amp;gt;
....&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;559038cd-3a51-4ed4-b55e-55d22964e90e&quot; class=&quot;toggle&quot;&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;위 /* 코드 적는 위치 */ 에 아래 코드를 넣으면 됩니다.&lt;/summary&gt;&lt;pre id=&quot;6894b4fd-8c64-4de3-a472-ae52f9824318&quot; class=&quot;code&quot;&gt;&lt;code&gt;&amp;lt;!-- http -&amp;gt; https 로 리다이렉트 하게 해줍니다. --&amp;gt;
&amp;lt;security-constraint&amp;gt;
	&amp;lt;web-resource-collection&amp;gt;
		&amp;lt;web-resource-name&amp;gt;HTTP&amp;lt;/web-resource-name&amp;gt;
		&amp;lt;url-pattern&amp;gt;/*&amp;lt;/url-pattern&amp;gt;
	&amp;lt;/web-resource-collection&amp;gt;
	&amp;lt;user-data-constraint&amp;gt;
		&amp;lt;transport-guarantee&amp;gt;CONFIDENTIAL&amp;lt;/transport-guarantee&amp;gt;
	&amp;lt;/user-data-constraint&amp;gt;
&amp;lt;/security-constraint&amp;gt;
&amp;lt;!-- 특정 리소스 /images/*, /css/* 리소스는 http or https 모두 처리됩니다. --&amp;gt;
&amp;lt;security-constraint&amp;gt;
	&amp;lt;web-resource-collection&amp;gt;
		&amp;lt;web-resource-name&amp;gt;HTTPS or HTTP&amp;lt;/web-resource-name&amp;gt;
		&amp;lt;url-pattern&amp;gt;/images/*&amp;lt;/url-pattern&amp;gt;
		&amp;lt;url-pattern&amp;gt;/css/*&amp;lt;/url-pattern&amp;gt;
	&amp;lt;/web-resource-collection&amp;gt;
	&amp;lt;user-data-constraint&amp;gt;
		&amp;lt;transport-guarantee&amp;gt;NONE&amp;lt;/transport-guarantee&amp;gt;
	&amp;lt;/user-data-constraint&amp;gt;
&amp;lt;/security-constraint&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;1f7a2cd3-bbfa-4e35-88c4-29fe7f402008&quot; class=&quot;&quot;&gt;
&lt;/p&gt;&lt;p id=&quot;ccfe4e47-bf74-4adc-9366-c62fa47381a9&quot; class=&quot;&quot;&gt;참고&lt;/p&gt;&lt;ul id=&quot;0ebb6e9c-19c7-487f-be85-1b1e6672c0d7&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;a href=&quot;https://www.ibm.com/docs/ko/api-connect/5.0.x?topic=profiles-generating-self-signed-certificate-using-openssl&quot;&gt;https://www.ibm.com/docs/ko/api-connect/5.0.x?topic=profiles-generating-self-signed-certificate-using-openssl&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;fdba7ead-9ccf-4bae-90a4-d19ec479f327&quot; class=&quot;bulleted-list&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;a href=&quot;https://ayoteralab.tistory.com/entry/Spring-Boot-24-https-TLS-SSL-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0&quot;&gt;[Spring Boot] 24. https TLS SSL 적용하기 (tistory.com)&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;17bab0f3-fd18-45a8-9f80-8182efd0d3ca&quot; class=&quot;&quot;&gt;
&lt;/p&gt;&lt;div class=&quot;n2t_comment&quot;&gt;&lt;p&gt;
&lt;/p&gt;&lt;p class=&quot;block-color-gray&quot;&gt;&lt;a href=&quot;https://boltlessengineer.github.io/Notion2Tistory&quot;&gt;Uploaded by Notion2Tistory v1.1.0&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/article&gt;</description>
      <category>Apache Tomcat</category>
      <author>Eco</author>
      <guid isPermaLink="true">https://gangda.tistory.com/21</guid>
      <comments>https://gangda.tistory.com/21#entry21comment</comments>
      <pubDate>Wed, 26 Jan 2022 18:23:00 +0900</pubDate>
    </item>
  </channel>
</rss>