<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>일지</title>
    <link>https://ubukki.tistory.com/</link>
    <description>좋은 일이 일어날 거예요!</description>
    <language>ko</language>
    <pubDate>Tue, 30 Jun 2026 04:35:24 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>ubukki(@river20s)</managingEditor>
    <image>
      <title>일지</title>
      <url>https://tistory1.daumcdn.net/tistory/7971538/attach/8d8bbb6d06aa40259c11078fbc233045</url>
      <link>https://ubukki.tistory.com</link>
    </image>
    <item>
      <title>깔끔한 Service 코드 만들기(from, map, collect)</title>
      <link>https://ubukki.tistory.com/9</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;스프링 부트로 비즈니스 로직을 구현할 때 엔티티를 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;u&gt;DTO*&lt;/u&gt;&lt;/span&gt;로 변환하거나 리스트 데이터를 가공해야 하는 경우가 많다. 이때 자주 쓰게 되지만 헷갈리는 것이 &lt;code&gt;from()&lt;/code&gt;, &lt;code&gt;map()&lt;/code&gt;, &lt;code&gt;collect()&lt;/code&gt;인데, 이 셋의 스펙과 활용법을 정리해보려 한다.&lt;/p&gt;
&lt;h1&gt;&lt;code&gt;from()&lt;/code&gt; - 객체 간의 전환&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 DTO 클래스 내부에 &lt;u&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;정적 메서드**&lt;/span&gt;&lt;/u&gt;로 구현하며, 어떤 객체로부터 이 DTO가 만들어지는가를 명확히 선언한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Entity &amp;rarr; DTO&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;&lt;u&gt;생성자 대신&lt;/u&gt; &lt;code&gt;from&lt;/code&gt;을 쓰는 이유****&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;읽기 훨씬 자연스러워서 의도가 명확하다. (예: &lt;code&gt;new QuestionResponseDto(...)&lt;/code&gt;보다 &lt;code&gt;QuestionResponseDto.from(question)&lt;/code&gt;이 읽기 자연스러움)&lt;/li&gt;
&lt;li&gt;서비스 로직에서 일일이 &lt;code&gt;Getter&lt;/code&gt;를 호출해 값을 세팅할 필요가 없다. 변환 로직이 DTO 내부에 있으므로 서비스 코드가 깔끔해진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1769426374911&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;from()&quot; data-og-description=&quot;자바 표준 Stream 인터페이스에는 from()이라는 인스턴스 메서드가 없다. 대신 자바의 여러 클래스에서 정적 팩토리 메서드 관례로 사용된다.사례날짜, 시간 관련LocalDateTime.from(temporal)처럼 다른 시&quot; data-og-host=&quot;ubukki.tistory.com&quot; data-og-source-url=&quot;https://ubukki.tistory.com/8&quot; data-og-url=&quot;https://ubukki.tistory.com/8&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cdcSTH/dJMb87NQM29/YWbhoDK7dinXQqFWLcb4Rk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/gYEOc/dJMb87f0OY1/Qmd6xv5U30qSFKtxjIeRo1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/dsdMT6/dJMb83knoYo/abuM7tdRknJBpI2cUVx0c1/img.jpg?width=896&amp;amp;height=896&amp;amp;face=0_0_896_896&quot;&gt;&lt;a href=&quot;https://ubukki.tistory.com/8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ubukki.tistory.com/8&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cdcSTH/dJMb87NQM29/YWbhoDK7dinXQqFWLcb4Rk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/gYEOc/dJMb87f0OY1/Qmd6xv5U30qSFKtxjIeRo1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/dsdMT6/dJMb83knoYo/abuM7tdRknJBpI2cUVx0c1/img.jpg?width=896&amp;amp;height=896&amp;amp;face=0_0_896_896');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;from()&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;자바 표준 Stream 인터페이스에는 from()이라는 인스턴스 메서드가 없다. 대신 자바의 여러 클래스에서 정적 팩토리 메서드 관례로 사용된다.사례날짜, 시간 관련LocalDateTime.from(temporal)처럼 다른 시&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ubukki.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;&lt;code&gt;map()&lt;/code&gt; - 데이터 모양 바꾸기&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터의 개수는 유지하면서 그 내부 형태만 바꿀 때 사용한다. 지금 작업에서 자주 쓰는 것은 두 종류의 &lt;code&gt;map&lt;/code&gt;이다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Java Stream의 &lt;code&gt;map&lt;/code&gt;&lt;br /&gt;&lt;code&gt;List&amp;lt;Question&amp;gt;&lt;/code&gt;을 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;u&gt;&lt;code&gt;Stream&lt;/code&gt;***&lt;/u&gt;&lt;/span&gt;으로 만든 뒤 하나씩 꺼내 DTO로 변환할 때 사용&lt;/li&gt;
&lt;li&gt;Spring Data Page의 &lt;code&gt;map()&lt;/code&gt;&lt;br /&gt;DB에서 페이징 처리된 &lt;code&gt;Page&amp;lt;Question&amp;gt;&lt;/code&gt;을 &lt;code&gt;Page&amp;lt;QuestionResponseDto&amp;gt;&lt;/code&gt;로 바꿀 때 사용&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;별도의 &lt;code&gt;collect()&lt;/code&gt; 과정이 필요 없음. &lt;code&gt;Page&lt;/code&gt; 객체가 가진 페이지 번호, 전체 개수 같은 메타데이터는 유지하면서 엔티티만 DTO로 바꿔준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1769426346455&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;map()&quot; data-og-description=&quot;데이터의 변환map()은 주로 Stream이나 Optional 인터페이스에서 사용된다. 스트림 내부의 요소를 차례대로 다른 형태로 변환하는 역할을 한다. Stream map(Function mapper);입력타입 T를 받아서 결과타입 R&quot; data-og-host=&quot;ubukki.tistory.com&quot; data-og-source-url=&quot;https://ubukki.tistory.com/6&quot; data-og-url=&quot;https://ubukki.tistory.com/6&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/jJ95H/dJMb89x70hR/EPmZkyykspH54raluLV3DK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/sUUwm/dJMb87f0OYS/tKiW1MakY4s21mxdJKkhYK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cmbQGb/dJMb84XTdjz/55TKbyPsK6lkTT8BTFky40/img.jpg?width=896&amp;amp;height=896&amp;amp;face=0_0_896_896&quot;&gt;&lt;a href=&quot;https://ubukki.tistory.com/6&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ubukki.tistory.com/6&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/jJ95H/dJMb89x70hR/EPmZkyykspH54raluLV3DK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/sUUwm/dJMb87f0OYS/tKiW1MakY4s21mxdJKkhYK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cmbQGb/dJMb84XTdjz/55TKbyPsK6lkTT8BTFky40/img.jpg?width=896&amp;amp;height=896&amp;amp;face=0_0_896_896');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;map()&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;데이터의 변환map()은 주로 Stream이나 Optional 인터페이스에서 사용된다. 스트림 내부의 요소를 차례대로 다른 형태로 변환하는 역할을 한다. Stream map(Function mapper);입력타입 T를 받아서 결과타입 R&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ubukki.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;&lt;code&gt;collect()&lt;/code&gt; - 흩어진 데이터를 모으기&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;map&lt;/code&gt;으로 변환된 데이터들은 아직 스트림 상태다. 이를 실제 우리가 사용할 수 있는 리스트 형태로 바궈주는 것이 &lt;code&gt;collect()&lt;/code&gt;다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스트림의 요소들을 &lt;code&gt;List&lt;/code&gt;, &lt;code&gt;Set&lt;/code&gt; 등의 컬렉션으로 취합함&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1769426403066&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;collect()&quot; data-og-description=&quot;데이터의 취합collect()는 스트림의 요소들을 모아서 리스트, 셋, 맵과 같은 컬렉션이나 다른 형태의 결과물로 만드는 최종 연산이다. R collect(Collector collector);가변 축소(Mutable Reduction): 스트림의 요&quot; data-og-host=&quot;ubukki.tistory.com&quot; data-og-source-url=&quot;https://ubukki.tistory.com/7&quot; data-og-url=&quot;https://ubukki.tistory.com/7&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/oppWU/dJMb8QL6tJk/yNym53HdtOjesIK4tjo8Qk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/BhLNq/dJMb8RRMokV/tKWdrcTQS7gHas4ZVWbCHk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cEJpmC/dJMb8U8N6n8/ejsnUzTGTODEEqEE2zt75K/img.jpg?width=896&amp;amp;height=896&amp;amp;face=0_0_896_896&quot;&gt;&lt;a href=&quot;https://ubukki.tistory.com/7&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ubukki.tistory.com/7&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/oppWU/dJMb8QL6tJk/yNym53HdtOjesIK4tjo8Qk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/BhLNq/dJMb8RRMokV/tKWdrcTQS7gHas4ZVWbCHk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cEJpmC/dJMb8U8N6n8/ejsnUzTGTODEEqEE2zt75K/img.jpg?width=896&amp;amp;height=896&amp;amp;face=0_0_896_896');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;collect()&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;데이터의 취합collect()는 스트림의 요소들을 모아서 리스트, 셋, 맵과 같은 컬렉션이나 다른 형태의 결과물로 만드는 최종 연산이다. R collect(Collector collector);가변 축소(Mutable Reduction): 스트림의 요&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ubukki.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;요약&lt;/h2&gt;
&lt;pre id=&quot;code_1769426953600&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    public List&amp;lt;QuestionResponseDto&amp;gt; getAllQuestions() {
        return questionRepository.findAll().stream()
                .map(QuestionResponseDto::from)
                .collect(Collectors.toList());
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;단계&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;코드&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;상태&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;Source&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;repository.findAll()&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;List&amp;lt;Entity&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;Stream&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;.stream()&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;Stream&amp;lt;Entity&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;Map&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;.map(Dto::from)&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;Stream&amp;lt;Dto&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;Collect&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;.collect(Collectors.toList())&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;List&amp;lt;Dto&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 세 가지 메서드만 잘 활용해도 서비스 레이어의 가독성이 비약적으로 상승한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;참고&lt;/h4&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;* DTO: Data Transfer Object, 계층 간 데이터 전송을 위한 객체. DB 설계를 그대로 담은 Entity를 클라이언트에 직접 노출하지 않기 위해 사용한다. 필요한 데이터만 골라 담는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;** 정적 팩토리 메서드(Static Factory Method): 객체 생성을 담당하는 클래스 내의 static 메서드이다. 이름을 가질 수 있어 생성 의도를 드러내기 좋고, 매번 새로운 객체를 생성하지 않아도 되는 등 유연한 설계가 가능하다. 예; from(), of()&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;*** 스트림 (Stream): Java 8부터 도입된 데이터의 흐름이다. 컬렉션(List, Set 등)에 저장된 요소들을 하나씩 참조하면서 선언적인 스타일(어떻게가 아닌 무엇을)로 가공하고 처리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;**** 보통 객체를 만들 때 new QuestionResponseDto(quesion) 처럼 생성자를 직접 부른다. 하지만 from이라는 정적 팩토리 메서드를 쓰면 다음과 같은 차이가 있다. 생성자는 한 클래스의 인스턴스를 만들지만, from은 특정 엔티티로부터 정보를 추출해서 응답용 객체 DTO를 만드는 의도적 작업을 수행한다. 즉 ㄱ객체 생성의 목적이 명확해지고, DTO 내부에서 엔티티의 어떤 필드를 사용할지 결정하므로 서비스 로직이 DTO 내부를 몰라도 되는 캡슐화적인 장점이 있다.&amp;nbsp;&lt;/p&gt;</description>
      <category>Java</category>
      <category>java</category>
      <category>Spring</category>
      <author>ubukki(@river20s)</author>
      <guid isPermaLink="true">https://ubukki.tistory.com/9</guid>
      <comments>https://ubukki.tistory.com/9#entry9comment</comments>
      <pubDate>Mon, 26 Jan 2026 20:32:09 +0900</pubDate>
    </item>
    <item>
      <title>from()</title>
      <link>https://ubukki.tistory.com/8</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;자바 표준 Stream 인터페이스에는 from()이라는 인스턴스 메서드가 없다. 대신 자바의 여러 클래스에서 정적 팩토리 메서드 관례로 사용된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사례&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;날짜, 시간 관련&lt;br /&gt;&lt;code&gt;LocalDateTime.from(temporal)&lt;/code&gt;처럼 다른 시간 객체를 기반으로 새로운 객체를 만들 때&lt;/li&gt;
&lt;li&gt;EnumSet&lt;br /&gt;&lt;code&gt;EnumSet.from(Collection&amp;lt;E&amp;gt; c)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Project Reactor&lt;br /&gt;다른 발행자를 리액티브 타입으로 변환할 때&lt;/li&gt;
&lt;li&gt;DTO 변환&lt;br /&gt;스프링 개발 시 Entity를 DTO로 변환할 때&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java 9 이상에서 컬렉션을 만들 때 사용하는 &lt;code&gt;List.of()&lt;/code&gt;등과 유사한 성격의 객체 생성자 역할을 한다.&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Java</category>
      <category>java</category>
      <author>ubukki(@river20s)</author>
      <guid isPermaLink="true">https://ubukki.tistory.com/8</guid>
      <comments>https://ubukki.tistory.com/8#entry8comment</comments>
      <pubDate>Mon, 26 Jan 2026 20:05:28 +0900</pubDate>
    </item>
    <item>
      <title>collect()</title>
      <link>https://ubukki.tistory.com/7</link>
      <description>&lt;h1&gt;데이터의 취합&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;collect()&lt;/code&gt;는 스트림의 요소들을 모아서 리스트, 셋, 맵과 같은 컬렉션이나 다른 형태의 결과물로 만드는 최종 연산이다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;&amp;lt;R, A&amp;gt; R collect(Collector&amp;lt;? super T, A, R&amp;gt; collector);&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;가변 축소(Mutable Reduction): 스트림의 요소들을 하나의 누적기(Container, 예: ArrayList)에 담아 최종 결과를 산출한다.&lt;/li&gt;
&lt;li&gt;주로 &lt;code&gt;Collectors&lt;/code&gt; 클래스에서 제공하는 정적 메서드(&lt;code&gt;toList()&lt;/code&gt;, &lt;code&gt;toSet()&lt;/code&gt;, &lt;code&gt;joining()&lt;/code&gt; 등)와 함께 사용한다.&lt;/li&gt;
&lt;li&gt;병렬 스트림 환경에서도 안전하게 데이터를 합칠 수 있도록 설계되어 있다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Java</category>
      <category>java</category>
      <category>Stream</category>
      <author>ubukki(@river20s)</author>
      <guid isPermaLink="true">https://ubukki.tistory.com/7</guid>
      <comments>https://ubukki.tistory.com/7#entry7comment</comments>
      <pubDate>Mon, 26 Jan 2026 20:01:56 +0900</pubDate>
    </item>
    <item>
      <title>map()</title>
      <link>https://ubukki.tistory.com/6</link>
      <description>&lt;h1&gt;데이터의 변환&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;map()&lt;/code&gt;은 주로 &lt;code&gt;Stream&lt;/code&gt;이나 &lt;code&gt;Optional&lt;/code&gt; 인터페이스에서 사용된다. 스트림 내부의 요소를 차례대로 다른 형태로 변환하는 역할을 한다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;&amp;lt;R&amp;gt; Stream&amp;lt;R&amp;gt; map(Function&amp;lt;? super T, ? extends R&amp;gt; mapper);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;입력타입 &lt;code&gt;T&lt;/code&gt;를 받아서 결과타입 &lt;code&gt;R&lt;/code&gt;을 반환하는 &lt;code&gt;Function&lt;/code&gt; 인터페이스를 인자로 받는다.&lt;/li&gt;
&lt;li&gt;요소의 개수는 유지하되, 그 내용물(타입이나 값)이 바뀐다.&lt;/li&gt;
&lt;li&gt;지연 연산, 중간 연산이므로 &lt;code&gt;collect()&lt;/code&gt; 같은 최종 연산이 호출되기 전까지는 실제로 실행되지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/Map.html&quot;&gt;Map (Java Platform SE 8 )&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1769425073800&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Map (Java Platform SE 8 )&quot; data-og-description=&quot;If the specified key is not already associated with a value (or is mapped to null), attempts to compute its value using the given mapping function and enters it into this map unless null. If the function returns null no mapping is recorded. If the function&quot; data-og-host=&quot;docs.oracle.com&quot; data-og-source-url=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/Map.html&quot; data-og-url=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/Map.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/Map.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/Map.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Map (Java Platform SE 8 )&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;If the specified key is not already associated with a value (or is mapped to null), attempts to compute its value using the given mapping function and enters it into this map unless null. If the function returns null no mapping is recorded. If the function&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.oracle.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java</category>
      <category>java</category>
      <category>map()</category>
      <author>ubukki(@river20s)</author>
      <guid isPermaLink="true">https://ubukki.tistory.com/6</guid>
      <comments>https://ubukki.tistory.com/6#entry6comment</comments>
      <pubDate>Mon, 26 Jan 2026 19:58:05 +0900</pubDate>
    </item>
    <item>
      <title>Java의 &amp;lt; &amp;gt; 기호 - 제네릭(Generics)</title>
      <link>https://ubukki.tistory.com/5</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;&amp;lt; &amp;gt;&lt;/code&gt; 기호의 의미&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;제네릭&lt;/b&gt;은 &lt;b&gt;클래스 내부에서 사용할 데이터 타입을 외부에서 결정하는 것&lt;/b&gt;이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;왜 필요한가?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제네릭을 사용하면 컴파일러에게 클래스에 들어갈 데이터 타입을 미리 알려줄 수 있다.&lt;/p&gt;
&lt;pre class=&quot;lasso&quot;&gt;&lt;code&gt;List list = new ArrayList();
List&amp;lt;String&amp;gt; list = new ArrayList&amp;lt;&amp;gt;();&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;제네릭을 사용하지 않은 위의 경우 꺼낼 때 형변환이 필요하다.&lt;/li&gt;
&lt;li&gt;그 아래의 제네릭을 사용한 경우 문자열만 넣을 수 있으므로 꺼낼 때 안전하다.오늘 마주친 제네릭들&lt;/li&gt;
&lt;li&gt;1. &lt;code&gt;ResponseEntity&amp;lt;어쩌고Dto&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;HTTP 응답을 보낼 때 응답 본문에 &lt;code&gt;어쩌고Dto&lt;/code&gt;라는 객체를 담아서 보내겠다는 뜻.&lt;/li&gt;
&lt;li&gt;데이터를 받는 쪽에서 '이 응답을 뜯어보면 &lt;code&gt;어쩌고Dto&lt;/code&gt;가 들어있겠구나'하고 확신할 수 있음.2. &lt;code&gt;Response&amp;lt;Void&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;응답은 보내지만 본문에 담을 데이터는 없다는 뜻.&lt;/li&gt;
&lt;li&gt;보통 &lt;code&gt;deleteTag()&lt;/code&gt;처럼 데이터를 삭제하는 작업은 성공 여부만 중요하고 딱히 돌려줄 데이터 객체가 없어서 &lt;code&gt;Void&lt;/code&gt;를 사용함.3. &lt;code&gt;&amp;lt;List&amp;lt;Question&amp;gt;&amp;gt;&lt;/code&gt; 중첩 사용&lt;/li&gt;
&lt;li&gt;응답 본문에 &lt;code&gt;Question&lt;/code&gt; 객체들이 여러 개 담긴 리스트를 넣어서 보내겠다는 의미.4. &lt;code&gt;Map&amp;lt;String, Integer&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Key는 String 타입, Value는 Integer 타입인 Map을 의미함제네릭을 쓰면 좋은 점&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;타입 안정성&lt;br /&gt;잘못된 타입이 들어오면 컴파일 단계에서 에러를 잡아줌&lt;/li&gt;
&lt;li&gt;불필요한 형변환 제거&lt;br /&gt;데이터를 꺼낼 때마다 타입을 강제로 변환할 필요가 없어서 코드가 깔끔해짐메서드 앞에 붙는 &lt;code&gt;&amp;lt;T&amp;gt;&lt;/code&gt;예를 들어
&lt;pre class=&quot;excel&quot;&gt;&lt;code&gt;public &amp;lt;T&amp;gt; T genericMethod(T t)&lt;/code&gt;&lt;/pre&gt;
처럼 메서드 앞에 &lt;code&gt;&amp;lt; &amp;gt;&lt;/code&gt;가 붙는 경우도 있는데, 이는 &lt;b&gt;이 메서드가 호출될 때 타입을 결정하는 제너릭 메서드&lt;/b&gt;라는 선언이다.왜 &lt;code&gt;T&lt;/code&gt;를 쓰는가?&lt;code&gt;&amp;lt; &amp;gt;&lt;/code&gt;안에는 아무거나 써도 되는데 보통 관례적으로 다음과 같이 쓴다.&lt;/li&gt;
&lt;/ol&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;기호&lt;/th&gt;
&lt;th&gt;의미&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Type&lt;/td&gt;
&lt;td&gt;가장 일반적으로 타입을 나타낼 때 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;E&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Element&lt;/td&gt;
&lt;td&gt;리스트나 셋 같은 컬렉션 내부 요소&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;K&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Key&lt;/td&gt;
&lt;td&gt;Map의 키 타입&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;V&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Value&lt;/td&gt;
&lt;td&gt;Map의 값 타입&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;N&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;숫자 타입을 강조&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;code&gt;&amp;lt;?&amp;gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 보다보면 &lt;code&gt;&amp;lt;?&amp;gt;&lt;/code&gt;가 적힌 경우도 보이는데 이건 &lt;b&gt;와일드 카드&lt;/b&gt;라고 한다.&lt;br /&gt;예를 들어 &lt;code&gt;List&amp;lt;?&amp;gt;&lt;/code&gt;는 어떤 타입이든 상관없이 다 받을 수 있는 리스트라는 뜻이다.&lt;br /&gt;&lt;code&gt;List&amp;lt;? extends Number&amp;gt;&lt;/code&gt;는 적어도 Number 클래스나 그 자식들이 들어올 수 있다고 상한선을 정하는 것이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;제네릭 메서드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스 전체가 아니라 메서드 하나만 제네릭으로 만들고 싶을 때는 다음과 같이 쓴다.&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public &amp;lt;T&amp;gt; void printArray(T[] array) {
    for (T element : array) {
        System.out.println(element);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 메서드는 호출할 때 &lt;code&gt;String[]&lt;/code&gt;을 넣으면 T가 String이고, &lt;code&gt;Integer[]&lt;/code&gt;를 넣으면 T가 Integer가 된다. 하나의 코드로 모든 타입을 대응할 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;요약&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;lt; &amp;gt;&lt;/code&gt;는 타입을 변수처럼 처리하겠다는 약속이다. 컴파일할 때 미리 타입을 체크해서 좋다. 코드 재사용성이 올라간다.&lt;/p&gt;</description>
      <category>Java</category>
      <category>java</category>
      <category>제네릭</category>
      <author>ubukki(@river20s)</author>
      <guid isPermaLink="true">https://ubukki.tistory.com/5</guid>
      <comments>https://ubukki.tistory.com/5#entry5comment</comments>
      <pubDate>Mon, 26 Jan 2026 19:32:26 +0900</pubDate>
    </item>
    <item>
      <title>엔드 포인트(Endpoint)</title>
      <link>https://ubukki.tistory.com/4</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;엔드포인트란&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엔드포인트는 외부(클라이언트)에서 소프트웨어 서비스나 API에 접근할 수 있도록 공개된 통신의 종단점-끝점을 의미한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Spring에서의 엔드포인트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring MVC나 Spring Boot에서 만드는 &lt;code&gt;Controller&lt;/code&gt; 안의 메서드 하나하나가 엔드포인트이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;URL 경로(Path): 어디로 갈 것인가 (예: &lt;code&gt;/api/users&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;HTTP 메서드(Method): 어떤 행위를 할 것인가 (예: &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;POST&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 &lt;code&gt;TagController.java&lt;/code&gt; 코드의 일부이다. 이 코드는 태그라는 리소스를 관리하기 위해 여러 엔드포인트를 갖고 있다.&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;package com.moyalist.backend.controller;

import com.moyalist.backend.dto.QuestionResponseDto;
import com.moyalist.backend.dto.TagRequestDto;
import com.moyalist.backend.dto.TagResponseDto;
import com.moyalist.backend.service.TagService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

@RestController
@RequestMapping(&quot;/api/tags&quot;)
@RequiredArgsConstructor
public class TagController {

    private final TagService tagService;

    @GetMapping
    public ResponseEntity&amp;lt;List&amp;lt;TagResponseDto&amp;gt;&amp;gt; getAllTags() {
        // 모든 태그 반환
        return ResponseEntity.ok(tagService.getAllTags());
    }

    @GetMapping(&quot;/{id}&quot;)
    public ResponseEntity&amp;lt;TagResponseDto&amp;gt; getTag(@PathVariable Long id) {
        // 특정 태그 반환
        return ResponseEntity.ok(tagService.getTag(id));
    }

    @PostMapping
    public ResponseEntity&amp;lt;TagResponseDto&amp;gt; createTag(@RequestBody Map&amp;lt;String, String&amp;gt; request) {
        Long userId = Long.parseLong(request.get(&quot;userId&quot;));
        String name = request.get(&quot;name&quot;);
        return ResponseEntity.ok(tagService.createTag(userId, name));
    }

    @PutMapping(&quot;/{id}&quot;)
    public  ResponseEntity&amp;lt;TagResponseDto&amp;gt; updateTag(@RequestBody TagRequestDto request, @PathVariable Long id) {
        return ResponseEntity.ok(tagService.updateTag(id, request));
    }

    @DeleteMapping(&quot;/{id}&quot;)
    public ResponseEntity&amp;lt;Void&amp;gt; deleteTag(@PathVariable Long id) {
        tagService.deleteTag(id);
        return ResponseEntity.noContent().build();
    }

    @GetMapping(&quot;/{id}/questions&quot;)
    public ResponseEntity&amp;lt;List&amp;lt;QuestionResponseDto&amp;gt;&amp;gt;
    getQuestionByTagId(@PathVariable Long id) {
        return ResponseEntity.ok(tagService.getQuestionsByTagId(id));
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/river20s/moya-list/blob/main/backend/src/main/java/com/moyalist/backend/controller/TagController.java&quot;&gt;TagController.java&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Tag 엔드포인트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스 상단에 &lt;code&gt;@RequestMapping(&quot;/api/tags&quot;)&lt;/code&gt;가 선언되어 있으므로, 모든 엔드포인트의 기본 주소는 &lt;code&gt;/api/tags&lt;/code&gt;로 시작한다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;HTTP 메서드&lt;/th&gt;
&lt;th&gt;엔드포인트 경로(Path)&lt;/th&gt;
&lt;th&gt;역할&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/tags&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;저장된 모든 태그 목록을 가져옴&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/tags/{id}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;특정 ID를 가진 태그 하나를 조회함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/tags&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;새로운 태그를 생성함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/tags{id}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;기존 태그 정보를 수정함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/tags/{id}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;특정 태그를 삭제함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/tags/{id}/questions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;특정 태그가 달린 궁금증 목록을 가져옴&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;경로 변수&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;@GetMapping(&quot;/{id}&quot;)&lt;/code&gt;나 &lt;code&gt;@DeleteMapping(&quot;/{id}&quot;)&lt;/code&gt;에서 보이는 &lt;code&gt;{id}&lt;/code&gt;는 고정된 주소가 아니라 변하는 값이다.&lt;/li&gt;
&lt;li&gt;사용자가 &lt;code&gt;/api/tags/10&lt;/code&gt;으로 요청을 보내면, Spring은 &lt;code&gt;{id}&lt;/code&gt; 자리에 &lt;code&gt;10&lt;/code&gt;을 넣어서 &lt;code&gt;getTag(10L)&lt;/code&gt; 메서드를 실행한다.&lt;/li&gt;
&lt;li&gt;이를 &lt;b&gt;동적 엔드포인트&lt;/b&gt;라고 부르기도 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;같은 경로, 다른 목적&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;/api/tags/{id}&lt;/code&gt;라는 똑같은 주소를 사용하는 엔드포인트가 3개나 있다(GET, PUT, DELETE).
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;GET&lt;/b&gt;으로 보내면 조회를 하고&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PUT&lt;/b&gt;으로 보내면 수정을 하며&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DELETE&lt;/b&gt;로 보내면 삭제를 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이렇게 같은 URL이라도 HTTP 메서드에 따라 행위를 달리하는 것이 RESTful API 설계의 핵심이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Request Body&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;createTag&lt;/code&gt; 메서드를 보면 &lt;code&gt;@RequestBody Map&amp;lt;String, String&amp;gt; request&lt;/code&gt;가 있다.&lt;/li&gt;
&lt;li&gt;엔드포인트는 단순 주소만 있는 게 아니라, 사용자가 보내는 JSON 데이터가 서버로 들어오는 통로 역할도 한다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Spring</category>
      <category>java</category>
      <category>Spring</category>
      <category>엔드포인트</category>
      <author>ubukki(@river20s)</author>
      <guid isPermaLink="true">https://ubukki.tistory.com/4</guid>
      <comments>https://ubukki.tistory.com/4#entry4comment</comments>
      <pubDate>Mon, 26 Jan 2026 19:01:11 +0900</pubDate>
    </item>
    <item>
      <title>소개 About</title>
      <link>https://ubukki.tistory.com/3</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;u&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;rarr;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;e-mail (&lt;a title=&quot;river20s@naver.com&quot; href=&quot;mailto:river20s@naver.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;river20s@naver.com&lt;/a&gt;)&lt;/span&gt;&lt;/u&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;u&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;rarr;Developer&lt;/span&gt;&lt;/u&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;u&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;rarr;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;GitHub (&lt;a title=&quot;@river20s&quot; href=&quot;https://github.com/river20s&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;@river20s&lt;/a&gt;)&lt;/span&gt;&lt;/u&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;u&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;rarr;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Currently creating a &lt;a title=&quot;Moya List&quot; href=&quot;https://github.com/river20s/moya-list&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Moya List ...&lt;/a&gt;&lt;/span&gt;&lt;/u&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;profile cat.jpg&quot; data-origin-width=&quot;64&quot; data-origin-height=&quot;64&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blFzij/dJMcabXjfRM/y1Isr2NDQPnI2h2w4aE8X1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blFzij/dJMcabXjfRM/y1Isr2NDQPnI2h2w4aE8X1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blFzij/dJMcabXjfRM/y1Isr2NDQPnI2h2w4aE8X1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblFzij%2FdJMcabXjfRM%2Fy1Isr2NDQPnI2h2w4aE8X1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;32&quot; height=&quot;32&quot; data-filename=&quot;profile cat.jpg&quot; data-origin-width=&quot;64&quot; data-origin-height=&quot;64&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>@river20s</category>
      <author>ubukki(@river20s)</author>
      <guid isPermaLink="true">https://ubukki.tistory.com/3</guid>
      <comments>https://ubukki.tistory.com/3#entry3comment</comments>
      <pubDate>Mon, 26 Jan 2026 18:38:02 +0900</pubDate>
    </item>
    <item>
      <title>TypeError: list indices must be integer or slices, not tuple</title>
      <link>https://ubukki.tistory.com/1</link>
      <description>&lt;pre&gt;&lt;code&gt;예외가 발생했습니다. TypeError
list indices must be integers or slices, not tuple
  File &amp;quot;C:\Users\eunbe\leetcode\leetcode-study\longest-increasing-subsequence\river20s.py&amp;quot;, line 11, in lengthOfLIS_bruteforce
    for idx_j in nums[idx_i, n-1]:
                 ~~~~^^^^^^^^^^^^
  File &amp;quot;C:\Users\eunbe\leetcode\leetcode-study\longest-increasing-subsequence\river20s.py&amp;quot;, line 23, in &amp;lt;module&amp;gt;
    result = solver.lengthOfLIS_bruteforce(test_nums)
TypeError: list indices must be integers or slices, not tuple&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;range() 함수&lt;/code&gt;는 특정 범위의 연속된 &lt;strong&gt;정수&lt;/strong&gt;들을 만들어내는 객체(이터레이터)를 반환한다. 이 정수들은 주로 for 루프에서 &lt;strong&gt;인덱스&lt;/strong&gt;로 사용된다.&lt;/p&gt;
&lt;p&gt;파이썬에서 리스트의 요소를 여러 개 선택하거나 범위를 지정할 때는 &lt;strong&gt;슬라이싱(slicing)&lt;/strong&gt; 을 사용하며, 콜론&lt;code&gt;:&lt;/code&gt;으로 구분한다.&lt;/p&gt;</description>
      <author>ubukki(@river20s)</author>
      <guid isPermaLink="true">https://ubukki.tistory.com/1</guid>
      <comments>https://ubukki.tistory.com/1#entry1comment</comments>
      <pubDate>Sat, 10 May 2025 21:55:43 +0900</pubDate>
    </item>
  </channel>
</rss>