<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>tuter77</title>
    <link>https://dudwls3278.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 20 May 2026 11:49:52 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>tuter77</managingEditor>
    <item>
      <title>자료구조/알고리즘 시간복잡도</title>
      <link>https://dudwls3278.tistory.com/95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 프로그램 알고리즘이란&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 신뢰성, 처리 효율, 범용성, 확장성, 이식성, 가독성 등이 높으면 좋은 알고리즘이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;- Big O 표기법으로 표현한다.( O(n) ) : n 개의 데이터에 증가하는 변화율을 표현한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시로 보면,&lt;/p&gt;
&lt;pre id=&quot;code_1676009473424&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int func1(int[] n) {
	if(n.length &amp;lt; 3)
    	return 0;
        
    int a = n[0];
    a += n[1];
    a += n[2];
    
    return a;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 예시에서 배열 n의 크기가 어느 정도이든 매번 똑같은 횟수로 기능을 처리하기&amp;nbsp;때문에 시간복잡도를 O(1)이라고 표현한다.(일정하다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로,&lt;/p&gt;
&lt;pre id=&quot;code_1676009606043&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int sum(int[] n){
	int s = 0;
    
    for(int i : n){
    	s += i;
    }
    
    return s;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드에서는 배열의 크기가 증가할 수 록 처리하는 횟수도 동일하게 증가하기 때문에 시간복잡도를 O(n)으로 표현한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(n에 정비례해서증가)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676009807371&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void bobbleSort(int[] n){
	for(int i=0; i&amp;lt;n.length; i++){
    	for(int j=0; j&amp;lt;n.length; j++){
        	if(n[i]&amp;lt;n[j]){
        		int temp = n[j];
            	n[j] = n[i];
            	n[i] = temp;
           	}
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 예시에선, n의 증가에 제곱으로 처리횟수가 많아지기 때문에 시간복잡도를 O(n^2)으로 표현한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(예로들면 n이 2일 경우에 첫번째 for문이 2번 돌고, 두번째 for문이 2번돌아 총 4번 처리된다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로,&lt;/p&gt;
&lt;pre id=&quot;code_1676009997290&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int sum(int[] n){
	int sum = 0;
    int max = n.length;
    while (max &amp;gt; 0){
    	sim += n[max - 1];
        max /= 2;
    }
    return sum;
 }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 예시에선 n이 증가할수록 취급하는 데이터의 범위(max)가 절반씩 줄어들기 때문에 시간복잡도를 O(logn)으로 표현한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorism TIL</category>
      <category>algorism</category>
      <category>Java</category>
      <category>시간복잡도</category>
      <author>tuter77</author>
      <guid isPermaLink="true">https://dudwls3278.tistory.com/95</guid>
      <comments>https://dudwls3278.tistory.com/95#entry95comment</comments>
      <pubDate>Fri, 10 Feb 2023 15:24:18 +0900</pubDate>
    </item>
    <item>
      <title>자료구조/알고리즘 자바의 데이터 표현.</title>
      <link>https://dudwls3278.tistory.com/94</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;360&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tWv6O/btrYRRC9j5o/KBUfBmDwQOA1UwgrbT9qc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tWv6O/btrYRRC9j5o/KBUfBmDwQOA1UwgrbT9qc1/img.png&quot; data-alt=&quot;java에서 자료를 활용하는 형태들&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tWv6O/btrYRRC9j5o/KBUfBmDwQOA1UwgrbT9qc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtWv6O%2FbtrYRRC9j5o%2FKBUfBmDwQOA1UwgrbT9qc1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;666&quot; height=&quot;360&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;360&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;java에서 자료를 활용하는 형태들&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Primitive type(기본형) : byte, short, int, long, float, double, char, boolean&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rapper Class type : 위 기본형 자료구조를 Reference 형으로 표현할 수 있도록 해주는 형태(ex. Byte, Integer 등.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference type : 기본형을 제외한 나머지 자료구조(ex. String) // Object type이라고 부르기도 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 타입들은 컴퓨터 메모리에서 존재하는 방식이 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본형은 call by value로 메모리에 존재하며,&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676007980493&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void main(){
	int v = 42;
    System.out.println(v); //42
    method(v);
    System.out.println(v); //42
}

void method(int v){
	v=v*2;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;위의 예시에서 보면 v가 가리키는 메모리는 기존에 저장되어있는 42라는 값자체이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에 method에서 v값을 두배로 해줘도 method가 끝나면 똑같이 42가 출력된다. (즉, method에 매개변수로 전달된 v는 42라는 값뿐이기때문에 42라는 값이 메모리에서 사라진 후 84로 변경되어 저장되지 않는 것을 알 수 있다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면, 참조형예시로 보면 call by reference로 메모리에 존재하는데&lt;/p&gt;
&lt;pre id=&quot;code_1676008197432&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void main(){
	Data v = new Data();
    v.d = 42; //v안의 d를 가리킴.
    System.out.println(v); //42
    method(v);
    System.out.println(v); //84
}

void method(Data v){
	v.d = v.d*2;
}

class Data{
	int d;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v가 주소를 통해 메모리를 가리키고 있기때문에 같은 v를 가리킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;heap 메모리에 저장된 v라는 참조형은 주소를 통해 저장된 데이터가 변할 수 있으므로,&amp;nbsp;method내에서 변경된 d값이 적용되는 것을 볼 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorism TIL</category>
      <category>Algorism study</category>
      <category>java type</category>
      <category>기초튼튼</category>
      <category>프로그래머스</category>
      <author>tuter77</author>
      <guid isPermaLink="true">https://dudwls3278.tistory.com/94</guid>
      <comments>https://dudwls3278.tistory.com/94#entry94comment</comments>
      <pubDate>Fri, 10 Feb 2023 15:04:40 +0900</pubDate>
    </item>
    <item>
      <title>게시판 만들기(11) - 작업내용 수정.</title>
      <link>https://dudwls3278.tistory.com/92</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #5c5c5c;&quot;&gt;● 기존 healthInfo View에 CRUD 구현 수정.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ Entity를 DTO로&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존의 엔티티를 통해 데이터를 전달하는 방식을 완전 수정했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;View와 컨트롤러, 서비스 간에 데이터를 교환할 때 엔티티 자체로 수정하고 보내는 것이아니라 DTO에 값을 저장해서 DTO에 Setter를 구현해 값을 주고받는 형태로 변환했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- homeController&lt;/p&gt;
&lt;pre id=&quot;code_1674992910797&quot; class=&quot;kotlin&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@RequiredArgsConstructor
@Controller
@Slf4j
public class HomeController {
    private final HealthRepository healthRepository;
    private final HomeService homeService;


    //기본형태 사용안함.
    @GetMapping(&quot;/home&quot;) //url localhost:8080/home
    public String home(Model model) {
        model.addAttribute(&quot;list&quot;, healthRepository.findAll());
        return &quot;home&quot;;

    }
    //상세페이지
    @GetMapping(&quot;/home/view&quot;)
    public String homeRead(Model model,@RequestParam Long id){
        HealthResponseDTO dto = homeService.healthView(id);
        List&amp;lt;ReviewResponseDTO&amp;gt; reviews = dto.getReviews();
        // 리뷰
        if(reviews != null &amp;amp;&amp;amp; !reviews.isEmpty()){
            model.addAttribute(&quot;reviews&quot;, reviews);
        }
        // homeService.updateView(id); //view에 추가하는 기능
        model.addAttribute(&quot;healthInfo&quot;, dto);
        return &quot;healthview&quot;;
    }
    // 저장 페이지.
    @GetMapping(&quot;/save&quot;)
    public String writeView(){
        return &quot;save&quot;;
    }

    //저장 기능 구현.
    @PostMapping(&quot;/home/save&quot;)
    // requestDTO에 Setter를 열어서 form데이터 바인딩.
    public String homeSave(HealthRequestDTO healthRequestDTO){
        homeService.saveHealth(healthRequestDTO);

        return &quot;redirect:/page&quot;; //prg패턴.
    }

    //삭제기능.
    @GetMapping(&quot;/home/delete&quot;)
    public String healthDelete(@RequestParam Long id){
        homeService.healthDelete(id);
        return &quot;redirect:/page&quot;;
    }

    //상세 페이지 내 수정페이지 보여주기
    @GetMapping(&quot;/home/modified&quot;)
    public String modifiedView(@RequestParam Long id, Model model) {
        model.addAttribute(HealthResponseDTO
                .toEntity(homeService.healthView(id)));
        return &quot;modified&quot;;
    }


    //상세 페이지 내 수정 기능
    @PostMapping(&quot;/home/modified/update&quot;)
    public String homeModified(HealthRequestDTO healthRequestDTO) {
            homeService.updateHealth(healthRequestDTO);
        return &quot;redirect:/page&quot;;
    }

    @GetMapping(&quot;/page&quot;)
    public String pageHome(Model model, Pageable pageable) {

        Page&amp;lt;HealthInfo&amp;gt; healthInfoPage = homeService.healthList(pageable);
        model.addAttribute(&quot;pages&quot;,healthInfoPage);
        model.addAttribute(&quot;maxPage&quot;,5);

        return &quot;page&quot;;
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요청하는 데이터, 즉 클라이언트가 저장, 수정 기능을 구현하기 위해 입력하는 데이터들은 모두 HealthRequestDTO에 저장한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 데이터는 DB에 저장되기 위해 toEntity라는 HealthRequestDTO클래스의 메서드를 이용하여 엔티티인 HealthInfo 타입으로 변환된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 DTO타입으로 각 값들을 가져오기 위해 조언받은 input 태그의 hidden 타입을 이용했다.(뒤에 html 파일에서 살펴보겠다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Service&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1674992910801&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface HomeService {

        public boolean saveHealth(HealthRequestDTO healthRequestDTO);
        public List&amp;lt;HealthInfo&amp;gt; HealthList();
        public HealthResponseDTO healthView(Long id) ;
        public boolean updateHealth(HealthRequestDTO healthRequestDTO);

        public boolean healthDelete(Long id);
        Page&amp;lt;HealthInfo&amp;gt; healthList(Pageable pageable);
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1674992910803&quot; class=&quot;reasonml&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
@RequiredArgsConstructor
public class HomeServiceImpl implements HomeService {

        private final HealthRepository healthRepository;


    @Override //home에 리스트형식으로 다 찾아오기
    public List&amp;lt;HealthInfo&amp;gt; HealthList() {
        List&amp;lt;HealthInfo&amp;gt;list=healthRepository.findAll();
        return list;
    }

    @Override //상세페이지 보여주기
    public HealthResponseDTO healthView(Long id) {
        HealthInfo healthInfo = healthRepository.findById(id).orElseThrow(IllegalArgumentException::new);
        return HealthResponseDTO.builder()
                .id(healthInfo.getId())
                .brand_name(healthInfo.getBrand_name())
                .category(healthInfo.getCategory())
                .land_number(healthInfo.getLand_number())
                .road_number(healthInfo.getRoad_number())
                .build();
    }

    @Override //저장기능
        public boolean saveHealth(HealthRequestDTO healthRequestDTO) {
        healthRepository.save(healthRequestDTO.toEntity(healthRequestDTO));
        return false;
    }

    @Override
    public boolean updateHealth(HealthRequestDTO healthRequestDTO){
        HealthInfo healthInfo = healthRepository.findById(healthRequestDTO.getId()).orElseThrow(RuntimeException::new);
        System.out.println(healthInfo.getId());

        healthInfo.modifyHealthInfo(healthRequestDTO.getBrand_name()
                ,healthRequestDTO.getCategory()
                ,healthRequestDTO.getLand_number()
                ,healthRequestDTO.getRoad_number());

        healthRepository.save(healthInfo);

        return false;
    }

        @Override //삭제기능
        public boolean healthDelete(@RequestParam Long id){
        healthRepository.deleteById(id);
        return true;
        }

    @Override
    public Page&amp;lt;HealthInfo&amp;gt; healthList(Pageable pageable){
            return healthRepository.findAll(pageable);

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB는 레포지토리와 데이터를 주고받고 Service는 컨트롤러에서 전달받은 데이터를 레포지토리에 전달한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에 healthRepository의 메서드를 사용하는것은 모두 여기서 구현했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장하기 위한 기존의 write.html 파일은 이름만 save로 바꾸었고, 내부 코드은 동일하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;id값을 healthInfo 엔티티에서 자동을 배정해주기 위해서이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 상세페이지 view와 수정페이지 view의 경우, 읽어서 view에 값을 뿌려주는 기능을 DTO로 받아야해서 안에 id를 hidden 타입으로 선언했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 상세페이지 view(healthview.html)&lt;/p&gt;
&lt;pre id=&quot;code_1674992910806&quot; class=&quot;dust&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html xmlns:th=&quot;http://www.thymeleaf.org&quot;&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;title&amp;gt;상세페이지&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
    &amp;lt;form&amp;gt;
        &amp;lt;input type=&quot;hidden&quot; th:name=&quot;id&quot; th:value=&quot;${healthInfo.id}&quot;&amp;gt;&amp;lt;/input&amp;gt;
        &amp;lt;h1 th:text=&quot;${healthInfo.brand_name}&quot;&amp;gt;&amp;lt;/h1&amp;gt;
        &amp;lt;p th:text=&quot;${healthInfo.category}&quot;&amp;gt;&amp;lt;/p&amp;gt;
        &amp;lt;p th:text=&quot;${healthInfo.land_number}&quot;&amp;gt;&amp;lt;/p&amp;gt;
        &amp;lt;p th:text=&quot;${healthInfo.road_number}&quot;&amp;gt;&amp;lt;/p&amp;gt;
        &amp;lt;a th:href=&quot;@{/home/modified(id=${healthInfo.id})}&quot;&amp;gt;수정&amp;lt;/a&amp;gt;
        &amp;lt;a th:href=&quot;@{/home/delete(id=${healthInfo.id})}&quot;&amp;gt;삭제&amp;lt;/a&amp;gt;
        &amp;lt;a th:href=&quot;@{/review(id=${healthInfo.id})}&quot;&amp;gt;리뷰 보기&amp;lt;/a&amp;gt;
        &amp;lt;button type=&quot;submit&quot; onclick=&quot;location.href='/page'&quot;&amp;gt;뒤로&amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DTO타입으로 바인딩하기 위해 기존에 없던 form태그를 활용한 것과 input 태그 내에 id값을 hidden으로 선언해 DTO의 모든 밸류가 다 입력 되어주도록 하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 수정 페이지(modified.html)&lt;/p&gt;
&lt;pre id=&quot;code_1674992910807&quot; class=&quot;dust&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html xmlns:th=&quot;http://www.thymeleaf.org&quot;&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;title&amp;gt;상세페이지&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
    &amp;lt;form th:action=&quot;@{/home/modified/update}&quot; method=&quot;post&quot;&amp;gt;
        &amp;lt;input name=&quot;id&quot; type =&quot;hidden&quot; th:value=&quot;${healthInfo.id}&quot;&amp;gt;
        &amp;lt;input name=&quot;brand_name&quot; type =&quot;text&quot; th:value=&quot;${healthInfo.brand_name}&quot;&amp;gt;
        &amp;lt;input name=&quot;category&quot; type =&quot;text&quot; th:value=&quot;${healthInfo.category}&quot;&amp;gt;
        &amp;lt;input name=&quot;land_number&quot; type =&quot;text&quot; th:value=&quot;${healthInfo.land_number}&quot;&amp;gt;
        &amp;lt;input name=&quot;road_number&quot; type =&quot;text&quot; th:value=&quot;${healthInfo.road_number}&quot;&amp;gt;
        &amp;lt;button type=&quot;submit&quot;&amp;gt;수정&amp;lt;/button&amp;gt;
        &amp;lt;a th:href=&quot;@{/page}&quot;&amp;gt;홈으로&amp;lt;/a&amp;gt;
    &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 id값을 @Pathvariable로 받던것을 빼고 form 데이터를 DTO로 바인딩하여 id값조회를 getId를 통해 DTO내에서 이루어지도록 하고있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정에서 @RequestBody를 이용하고 싶었지만 아쉽게도 Ajax의 Json타입이어야 유효했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에 매개변수로 바인딩 된 DTO를 받고있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 DTO도 뭔지모르겠고 어떻게 이용할지 id 값은 왜 안넘어가는지 뭐가 문제인지 찾지도 못한 입장으로서 지금은 작은 한걸음을 나아갔다고 느껴 정말 뿌듯하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 아직 해야할 review시리즈가있으니 고삐를 놓지말자.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 내용은 2023.01.20에 공부한 내용입니다.&lt;/p&gt;</description>
      <category>GroupStudy</category>
      <category>group study</category>
      <category>side project</category>
      <category>게시판 만들기</category>
      <author>tuter77</author>
      <guid isPermaLink="true">https://dudwls3278.tistory.com/92</guid>
      <comments>https://dudwls3278.tistory.com/92#entry92comment</comments>
      <pubDate>Sun, 29 Jan 2023 20:49:10 +0900</pubDate>
    </item>
    <item>
      <title>게시판 만들기(10) - Review CRUD 구현</title>
      <link>https://dudwls3278.tistory.com/91</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #5c5c5c;&quot;&gt;● Review CRUD 구현.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ 구현하기 전 정보&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;review는 앞서 엔티티를 구현할 때 각 게시글(healthInfo)의 id값을 참조로 가져 해당 id값을 게시글의 리뷰형태로 구현해야한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 때문에 데이터를 view에 보여주는 것부터 고민이었는데, 일단 상세페이지에서 healthinfo id 값을 통해 리뷰를 불러오는 형태로 가기로 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;id값은 review 엔티티에 healthinfo 객체에 저장되는데, db에서 이름이 health_id로 지정이 되어있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;review&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;엔티티를 구현할 때 healthinfo 엔티티에 리뷰를 추가하는 메서드를 구현해 놓았는데 이를 이용할 수 있을지.. 해봐야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;복습해보면, review 엔티티에서 manytoone의 관계를 healthinfo 엔티티와 가지고, 반대로 healthInfo에서는 onetomany의 관계를 가진다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;이는 양방향 관계로 JoinColomn과 mappedBy 로 관계의 주인이 참조값을 저장하는&amp;nbsp; review엔티티임을 명시했었다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;n+1의 문제를 lazy로딩방식으로 대처했고, 엔티티의 상태변화가 cascade로 관계된 엔티티로 전달되게 했다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;review 엔티티의 멤버 변수들은 review의 id, title, contents, health_id(참조값)이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;먼저 필요한 클래스와 파일들을 나열하자면,&amp;nbsp; 클라이언트의 요청을 받을 reviewController, 컨트롤러의 요청을 처리할 reviewService, 값이 저장되는 엔티티와 db와 데이터를 주고받을 repository는 이미 만들어두었고, 그 값을 감싸주는 DTO클래스는 미숙해서 당장은 생성하지 않을 예정이다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;또한 review를 보여줄 view.html파일과 각 저장, 수정 기능이 구현될 save, modify html 파일도 필요할것이다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;당장은 이렇게만 구성되어있지만, MVC패턴을 제대로 이용하려면 DTO와 객체생성을 맡은 Factory도 필요할 것이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 주고 받는 기능자체에서 이해도가 많이 떨어지기 때문에 차근차근 공부해보면서 진행할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷Review 컨트롤러&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1674992851278&quot; class=&quot;kotlin&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.example.demo.controller;

import com.example.demo.domain.HealthInfo;
import com.example.demo.domain.Review;
import com.example.demo.repository.ReviewRepository;
import com.example.demo.service.ReviewService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
@RequiredArgsConstructor
@Slf4j
public class ReviewController {
    public final ReviewService reviewService;


    @GetMapping(&quot;/review&quot;)
    public String healthView(Model model,@RequestParam Long id){
        model.addAttribute(&quot;review&quot;, reviewService.findReview(id));
        return &quot;review&quot;;
    }
    @GetMapping(&quot;/review/write&quot;) // 저장 페이지.
    public String writePage(@RequestParam Long id){
        return &quot;reviewWrite&quot;;
    }

    @PostMapping(&quot;/review/writer&quot;) //저장 기능 구현.
    public String reviewSave(HealthInfo healthInfo, Review review){
        reviewService.reviewWrite(healthInfo, review);

        return &quot;redirect:/review&quot;; //prg패턴.
    }

    @GetMapping(&quot;/review/delete&quot;)
    public String reviewDeleter(@RequestParam Long id){
        reviewService.reviewDelete(id);
        return &quot;redirect:/review&quot;;
    }


}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 만들었던 형태와 유사하게 만들었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;homeContoller에서 repository와 직통으로 연결되는 의존의 형태를 최대한 service를 이용해 완화할 생각이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 리뷰 페이지는 healthInfo.id를 매개변수로 받아 해당 값을 가진 리뷰들이 모두 찾아지도록 만들 예정이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장기능을 대충이나마 구현했는데, healthInfo.id는 자동으로 저장되게끔 해야하는데 객체자체를 저장해야할지, Long id로 저장해야할지 모르겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엔티티에는&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@ManyToOne
@JoinColumn(name = &quot;health_id&quot;)
private HealthInfo healthInfo;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;healthInfo라는 HealthInfo타입의 변수가 선언되어있기는하지만, id값만 딱 저장되는건지는 모르겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ReviewService&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;먼저 인터페이스를 보면 필요한 기능들을 명시해놓았다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1674992851283&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.example.demo.service;

import com.example.demo.domain.HealthInfo;
import com.example.demo.domain.Review;

import java.util.Optional;

public interface ReviewService {

    public void reviewWrite(HealthInfo healthInfo, Review review);
    public Review findReview(Long id) ;
    public Optional&amp;lt;Review&amp;gt; reviewList(HealthInfo healthInfo);
    //수정기능 값이 저장이 안됨.
    void reviewModify(Long id);

    public boolean reviewDelete(Long id);

}&lt;/code&gt;&lt;/pre&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;pre id=&quot;code_1674992851285&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.example.demo.service.impl;

import com.example.demo.domain.HealthInfo;
import com.example.demo.domain.Review;
import com.example.demo.repository.ReviewRepository;
import com.example.demo.service.ReviewService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.Optional;

@Service
@RequiredArgsConstructor
public class ReviewServiceImpl implements ReviewService {

    private final ReviewRepository reviewRepository;
    
    @Override
    public Review findReview(Long id) {
        return reviewRepository.findById(id).orElseThrow(IllegalArgumentException::new);
    }

    @Override
    public Optional&amp;lt;Review&amp;gt; reviewList(HealthInfo healthInfo) {
        Long health_id = healthInfo.getId();
        Optional&amp;lt;Review&amp;gt; list = reviewRepository.findById(health_id);
        return list;
    }


    @Override
    public void reviewWrite(HealthInfo healthInfo, Review review) {
        healthInfo.getId();
        healthInfo.addReview(review);
    }

    @Override
    public void reviewModify(Long id) {

    }

    @Override
    public boolean reviewDelete(@RequestParam Long id) {
        reviewRepository.deleteById(id);
        return true;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;삭제기능은 동일하게 id값으로 지우면되는데, 저장과 데이터 찾아오기에서 고민이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷html파일들&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- review&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1674992851289&quot; class=&quot;dust&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html xmlns:th=&quot;http://www.thymeleaf.org&quot;&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;title&amp;gt;헬스장 리뷰 페이지&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
&amp;lt;table&amp;gt;
    &amp;lt;thead&amp;gt;
    &amp;lt;tr&amp;gt;
        &amp;lt;h1&amp;gt;ReviewPage&amp;lt;/h1&amp;gt;
    &amp;lt;/tr&amp;gt;
    &amp;lt;a th:href=&quot;@{/review/write(id=${healthInfo.id})}&quot;&amp;gt;리뷰 쓰기&amp;lt;/button&amp;gt;
    &amp;lt;/thead&amp;gt;
    &amp;lt;tbody&amp;gt;
    &amp;lt;tr th:each = &quot;review:${list}&quot;&amp;gt;
        &amp;lt;td th:text=&quot;${review.id}&quot;&amp;gt;&amp;lt;/td&amp;gt;
        &amp;lt;td&amp;gt;
            &amp;lt;a th:text=&quot;${review.title}&quot;&amp;gt;&amp;lt;/a&amp;gt;
            &amp;lt;a th:text=&quot;${review.contents}&quot;&amp;gt;&amp;lt;/a&amp;gt;
            &amp;lt;a type=&quot;hidden&quot; th:text=&quot;${review.healthInfo}&quot;&amp;gt;&amp;lt;/a&amp;gt;
            &amp;lt;a th:href=&quot;@{/review/delete(id=${review.id})}&quot;&amp;gt;삭제&amp;lt;/a&amp;gt;
        &amp;lt;/td&amp;gt;
    &amp;lt;/tr&amp;gt;
    &amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- review 저장 view&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1674992851290&quot; class=&quot;dust&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html xmlns:th=&quot;http://www.thymeleaf.org&quot;&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;title&amp;gt;헬스장 정보 저장 페이지&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
&amp;lt;table&amp;gt;
    &amp;lt;form th:action=&quot;@{/review/writer}&quot; method=&quot;post&quot;&amp;gt;
        &amp;lt;p&amp;gt;아래에 자료를 입력하세요.&amp;lt;/p&amp;gt;
        &amp;lt;tr&amp;gt;
            &amp;lt;td&amp;gt;&amp;lt;input type=&quot;text&quot; name=&quot;title&quot;&amp;gt;&amp;lt;/td&amp;gt;
        &amp;lt;/tr&amp;gt;
        &amp;lt;tr&amp;gt;
            &amp;lt;td&amp;gt;&amp;lt;input type=&quot;text&quot; name=&quot;contents&quot;&amp;gt;&amp;lt;/td&amp;gt;
        &amp;lt;/tr&amp;gt;
        &amp;lt;a name=&quot;health_id&quot; type=&quot;hidden&quot; th:href=&quot;@{healthInfo.id}&amp;gt;&amp;lt;/a&amp;gt;
        &amp;lt;tr&amp;gt;
        &amp;lt;td&amp;gt;&amp;lt;input type=&quot;reset&quot; value=&quot;취소&quot;&amp;gt;&amp;lt;/td&amp;gt;
        &amp;lt;td&amp;gt;&amp;lt;button type=&quot;submit&quot;&amp;gt;저장&amp;lt;/button&amp;gt;&amp;lt;/td&amp;gt;
        &amp;lt;/tr&amp;gt;
    &amp;lt;/form&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 내용은 2023.01.19에 공부한 내용입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://dudwls3278.tistory.com/45&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://dudwls3278.tistory.com/45&lt;/a&gt;&lt;/p&gt;</description>
      <category>GroupStudy</category>
      <category>group study</category>
      <category>게시판 리뷰 만들기</category>
      <author>tuter77</author>
      <guid isPermaLink="true">https://dudwls3278.tistory.com/91</guid>
      <comments>https://dudwls3278.tistory.com/91#entry91comment</comments>
      <pubDate>Sun, 29 Jan 2023 20:48:04 +0900</pubDate>
    </item>
    <item>
      <title>Spring : http 요청과 응답(2)</title>
      <link>https://dudwls3278.tistory.com/90</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #5c5c5c;&quot;&gt;● HTTP 요청과 응답&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ Base 64&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 64진법을 의미한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 바이너리 데이터를 텍스트 데이터로 변환할 때 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 64진법은 A~Z :26개, a~z:26개, 0~9:10개 62개에 +, / 까지 64개를 나타낸다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 이는 2진수 데이터를 2^6으로 6bit씩 잘라서 변환한것. (예 : 16진수는 2^4로 2진수를 4bit씩 자른다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 남는 것은 Padding 데이터(=)로 채운다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이는 바이너리 데이터를 텍스트 데이터로 변화할때 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이 6비트로 전달을 하면 서로 다른 OS를 가져도 전달에 문제가 없다는 장점이 있다.&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;p data-ke-size=&quot;size16&quot;&gt;예시) 이미지파일을 base64로 인코딩하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글에 base64 encode 검색&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;566&quot; data-origin-height=&quot;596&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RGcBZ/btrXnKG5t7p/7uKP2bwqT5U3wrdINFiIpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RGcBZ/btrXnKG5t7p/7uKP2bwqT5U3wrdINFiIpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RGcBZ/btrXnKG5t7p/7uKP2bwqT5U3wrdINFiIpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRGcBZ%2FbtrXnKG5t7p%2F7uKP2bwqT5U3wrdINFiIpK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;566&quot; height=&quot;596&quot; data-origin-width=&quot;566&quot; data-origin-height=&quot;596&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 사이트에서 주사위 이미지를 선택하여, encode 버튼으로 텍스트로 인코딩한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 base64 기반 텍스트를 html로 저장하여 브라우저에서 확인한다.(VSCode 사용)&lt;/p&gt;
&lt;pre id=&quot;code_1674992753902&quot; class=&quot;subunit&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&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;title&amp;gt;Document&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;img src=&quot;data:image/jpeg;base64, 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&quot; alt=&quot;&quot;&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우클릭 &amp;gt; Open in Default Browser&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;703&quot; data-origin-height=&quot;548&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQS7yi/btrXqrT2UvO/WVVSzpavK7MuFdPwoNdGT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQS7yi/btrXqrT2UvO/WVVSzpavK7MuFdPwoNdGT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQS7yi/btrXqrT2UvO/WVVSzpavK7MuFdPwoNdGT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQS7yi%2FbtrXqrT2UvO%2FWVVSzpavK7MuFdPwoNdGT0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;703&quot; height=&quot;548&quot; data-origin-width=&quot;703&quot; data-origin-height=&quot;548&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;위가 브라우저에서 출력되는 화면이고 해당 소스를 확인해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우클릭 &amp;gt; 페이지 원본보기 &amp;gt; 자동 줄바꿈 선택&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;738&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgglZk/btrXtSRaeVo/qw8iZ99Rq9AaLhwI0HVnYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgglZk/btrXtSRaeVo/qw8iZ99Rq9AaLhwI0HVnYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgglZk/btrXtSRaeVo/qw8iZ99Rq9AaLhwI0HVnYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgglZk%2FbtrXtSRaeVo%2Fqw8iZ99Rq9AaLhwI0HVnYk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;855&quot; height=&quot;738&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;738&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 텍스트를 html파일로 안전하게 전달하면, 링크가 꼬이거하는 일 없이 안전하게 보관할 수 있다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뒤는 이전에 공부하던 MVC 패턴의 원리에 대해 공부해보겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #5c5c5c;&quot;&gt;● 관심사의 분리 MVC 패턴 - 원리&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ 예제&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1674992753907&quot; class=&quot;pgsql&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.fastcampus.ch2;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.StringJoiner;

public class MethodInfo {
	public static void main(String[] args) throws Exception{

		Class clazz = Class.forName(&quot;com.fastcampus.ch2.YoilTeller&quot;);
		Object obj = clazz.newInstance();
		
		Method[] methodArr = clazz.getDeclaredMethods();
		
		for(Method m : methodArr) {
			String name = m.getName();
			Parameter[] paramArr = m.getParameters();
//			Class[] paramTypeArr = m.getParameterTypes();
			Class returnType = m.getReturnType();
			
			StringJoiner paramList = new StringJoiner(&quot;, &quot;, &quot;(&quot;, &quot;)&quot;);
			
			for(Parameter param : paramArr) {
				String paramName = param.getName();
				Class  paramType = param.getType();
				
				paramList.add(paramType.getName() + &quot; &quot; + paramName);
			}
			
			System.out.printf(&quot;%s %s%s%n&quot;, returnType.getName(), name, paramList);
		}
	} // main
}

/* [실행결과]
java.lang.String main(java.lang.String year, java.lang.String month, java.lang.String day, org.springframework.ui.Model model)
boolean isValid(int year, int month, int day)
*/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;1. YoilTeller 라는 클래스의 객체를 만든다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;YoilTeller&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;의 모든 메서드 정보를 가져와서 배열에 저장한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;&lt;span&gt;3. 반복문으로 메서드 정보를 하나씩 출력한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;StringJoiner paramList = new StringJoiner(&quot;, &quot;, &quot;(&quot;, &quot;)&quot;); 여기선 괄호안엔 &quot;구분자 = , &quot;, &quot;접두사 = ( &quot;, &quot;접미사 = )&quot;로 되어있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 메서드 매개변수 목록을 접두사와 접미사안에 구분자로 구분하여 나열하는 코드다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 실행 결과에서 알 수 있듯이 각 매개변수 타입 이름 순으로 나열해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;void&amp;nbsp;main(javax.servlet.http.HttpServletRequest&amp;nbsp;arg0,&amp;nbsp;javax.servlet.http.HttpServletResponse&amp;nbsp;arg1)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;YoilTeller의 매개변수는 request와 response이지만 여기선 arg0, arg1로 바뀌어있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;그 이유는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;YoilTeller를&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴파일할때 매개변수 타입은 중요하지만 이름은 중요하지않아 저장하지 않기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에 매개변수 이름을 저장하려면 컴파일 옵션에 javac -parameters라고 옵션을 줘야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;STS 기준 옵션설정.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;windows &amp;gt; preference &amp;gt; Compiler 검색 &amp;gt; java Compiler &amp;gt; 옵션중에 Store information - 옵션을 체크하면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 기능은 JDK 1.8 이상만 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해다 JDK버전을 세팅해둔 11버전으로 바꾸고 pom.xml 파일로 가서 java version을 변경해준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;458&quot; data-origin-height=&quot;152&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9lHse/btrXqCH2O7q/EksChygwchRVk6NZfuWYF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9lHse/btrXqCH2O7q/EksChygwchRVk6NZfuWYF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9lHse/btrXqCH2O7q/EksChygwchRVk6NZfuWYF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9lHse%2FbtrXqCH2O7q%2FEksChygwchRVk6NZfuWYF0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;458&quot; height=&quot;152&quot; data-origin-width=&quot;458&quot; data-origin-height=&quot;152&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 맨 아래쪽에 가면 Plugin이 있는데 그 쪽에는 이 자바 버전을 가져올 수 있게 변수명으로 바꿔준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 1.6 &amp;gt; ${java version}&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;452&quot; data-origin-height=&quot;212&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSPQMU/btrXqtqMVGQ/V0g2Pjr3Uuk60y2LiU8gIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSPQMU/btrXqtqMVGQ/V0g2Pjr3Uuk60y2LiU8gIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSPQMU/btrXqtqMVGQ/V0g2Pjr3Uuk60y2LiU8gIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSPQMU%2FbtrXqtqMVGQ%2FV0g2Pjr3Uuk60y2LiU8gIK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;452&quot; height=&quot;212&quot; data-origin-width=&quot;452&quot; data-origin-height=&quot;212&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 pom.xml 파일을 변경해주면 프로젝트를 업데이트 해주어야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;232&quot; data-origin-height=&quot;222&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dWLstn/btrXtTo0qZQ/q0krfhQkyOxPBKHzpsfkwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dWLstn/btrXtTo0qZQ/q0krfhQkyOxPBKHzpsfkwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dWLstn/btrXtTo0qZQ/q0krfhQkyOxPBKHzpsfkwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdWLstn%2FbtrXtTo0qZQ%2Fq0krfhQkyOxPBKHzpsfkwK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;232&quot; height=&quot;222&quot; data-origin-width=&quot;232&quot; data-origin-height=&quot;222&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트를 우클릭해서 maven &amp;gt; Update Project (pom 파일은 maven 설정파일이다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;void&amp;nbsp;main(javax.servlet.http.HttpServletRequest&amp;nbsp;request,&amp;nbsp;javax.servlet.http.HttpServletResponse&amp;nbsp;response)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위는 결과창으로 옵션과 버전 변경 후, 정상적으로 매개변수 명을 가져오는 것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 매개변수 이름을 Spring이 얻는 방법이 2가지 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Reflection API를 이용하는 것.(방금 실행한 -parameters 옵션 설정 방식.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Class file을 직접 읽어오는 것.(위 과정이 실패하면 이 방법으로 매개변수 이름을 얻어와야한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 2번째 방식을 실행하려면 패키지 exploorer말고 다른것으로 봐야 클래스 파일을 볼 수 있다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Windows &amp;gt; Show View &amp;gt; other &amp;gt; navi 검색 &amp;gt; navigator&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;575&quot; data-origin-height=&quot;372&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cPZTVn/btrXo5Rd47y/LKEnYqL6WITPuCkwy4xSMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cPZTVn/btrXo5Rd47y/LKEnYqL6WITPuCkwy4xSMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cPZTVn/btrXo5Rd47y/LKEnYqL6WITPuCkwy4xSMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcPZTVn%2FbtrXo5Rd47y%2FLKEnYqL6WITPuCkwy4xSMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;575&quot; height=&quot;372&quot; data-origin-width=&quot;575&quot; data-origin-height=&quot;372&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 target의 경로로 가면 클래스 파일을 볼 수 있고, 파일을 더블 클릭하면 해석된 내용을 볼 수있다.(STS의 Open with의 Class file Viewer 기능)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;487&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ule1h/btrXnJBplh0/VuNioOIZHAV3qehyphFSqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ule1h/btrXnJBplh0/VuNioOIZHAV3qehyphFSqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ule1h/btrXnJBplh0/VuNioOIZHAV3qehyphFSqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUle1h%2FbtrXnJBplh0%2FVuNioOIZHAV3qehyphFSqK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;637&quot; height=&quot;487&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;487&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해석된 클래스파일의 맨 아래에 Local variable table에서 해당 메서드와 매개변수명을 찾을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 예시)&lt;/p&gt;
&lt;pre id=&quot;code_1674992753913&quot; class=&quot;arduino&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.fastcampus.ch2;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;


class ModelController {
	public String main(HashMap map) {
		map.put(&quot;id&quot;, &quot;asdf&quot;);
		map.put(&quot;pwd&quot;, &quot;1111&quot;);
		
		return &quot;txtView2&quot;;
	}
}

public class MethodCall {
	public static void main(String[] args) throws Exception{
		HashMap map = new HashMap();
		System.out.println(&quot;before:&quot;+map);

		ModelController mc = new ModelController();
		String viewName = mc.main(map);
		
		System.out.println(&quot;after :&quot;+map);
		
		render(map, viewName);
	}
	
	static void render(HashMap map, String viewName) throws IOException {
		String result = &quot;&quot;;
		
		// 1. 뷰의 내용을 한줄씩 읽어서 하나의 문자열로 만든다.
		Scanner sc = new Scanner(new File(viewName+&quot;.txt&quot;));
		
		while(sc.hasNextLine())
			result += sc.nextLine()+ System.lineSeparator();
		
		// 2. map에 담긴 key를 하나씩 읽어서 template의 ${key}를 value바꾼다.
		Iterator it = map.keySet().iterator();
		
		while(it.hasNext()) {
			String key = (String)it.next();

			// 3. replace()로 key를 value 치환한다.
			result = result.replace(&quot;${&quot;+key+&quot;}&quot;, (String)map.get(key));
		}
		
		// 4.렌더링 결과를 출력한다.
		System.out.println(result);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인메서드에서 map을 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;map의 모델 컨트롤러의 main 메서드한테 map을 넘겨준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 map에 Key : id / valuew : asdf 순으로 저장(map.put)한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 viewName(txtView2)을 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(youtube에 참조형 매개변수 ch6- 24, 25 참조)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 반환된 map(저장된 데이터)과 viewName을 render()라는 메서드에게 넘기는데 render()의 기능은 map의 데이터를 view에 보여주는 기능을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;render() 메서드 내에서 viewName.txt (예 : ${id})를 iterator로 한줄씩 읽어 값을 반환해준다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재는 console에 출력하지만, response객체로 클라이언트에 출력할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;txtView1, txtView2를 생성하여 실행해주면, 아래의 결과가 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(txtView의 내용 &amp;gt; id:${id}, pwd:${pwd})&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;275&quot; data-origin-height=&quot;75&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Kndlf/btrXn8gCPnx/CGvGMfNBlEKGksbn4J1ifk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Kndlf/btrXn8gCPnx/CGvGMfNBlEKGksbn4J1ifk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Kndlf/btrXn8gCPnx/CGvGMfNBlEKGksbn4J1ifk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKndlf%2FbtrXn8gCPnx%2FCGvGMfNBlEKGksbn4J1ifk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;275&quot; height=&quot;75&quot; data-origin-width=&quot;275&quot; data-origin-height=&quot;75&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 map을 생성했을 땐 키와 밸류가 비어있지만, 해당 메서드들이 동작하고 나서는 키와 배류의 값을 출력해주고, 맨 아래는 map을 view에 뿌려서 콘솔에 찍어내지만 실제로는 클라이언트에 렌더링해주는 결과가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그룹스터디에서 각 view를 생성하여 db의 데이터를 보여주는 과정과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨트롤러에서 클라이언트의 url로 요청을 받아 service로 전달하고 전달된 값은 repository를 호출하는 service의 기능으로 데이터를 가져와 view 파일들에게 뿌려져 다시 클라이언트로 반환된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래는 이 과정에 DTO 객체로 한번 감싸져서 주고받아져야하지만 아직까지 이해도가 떨어지는 관계로 엔티티를 직접 전송하고 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 내용은 2023.01.19에 공부한 내용입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://dudwls3278.tistory.com/45&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://dudwls3278.tistory.com/45&lt;/a&gt;&lt;/p&gt;</description>
      <category>SpringStudy</category>
      <category>map</category>
      <category>MVC Pattern</category>
      <category>Spring</category>
      <category>View</category>
      <author>tuter77</author>
      <guid isPermaLink="true">https://dudwls3278.tistory.com/90</guid>
      <comments>https://dudwls3278.tistory.com/90#entry90comment</comments>
      <pubDate>Sun, 29 Jan 2023 20:46:52 +0900</pubDate>
    </item>
    <item>
      <title>게시판 만들기(9) -  Controller 및 Service 클래스 수정</title>
      <link>https://dudwls3278.tistory.com/89</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #5c5c5c;&quot;&gt;● Controller 및 Service 클래스 수정&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ 저장 및 수정.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;컨트롤러 내에서 repository를 그대로 이용하는 것은 service클래스를 쓰는 의미가 없다는 것을 잊고 작업하였다가 이번에 수정하게 되었다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 엔티티에서 Setter를 사용하는것은 안좋다고 하여 Setter 어노테이션을 제거했는데, 데이터값이 전달되지않아 다시 넣었다.(이 부분에서 시간을 다 잡아먹었다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 시간이 많이 들었던 부분은 modify 기능이다. 해당 기능을 controller에 Setter로 구현해놓았을때는 괜찮았으나, Service로 옮기면서 수정기능이 실행되지않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정된 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 컨트롤러&lt;/p&gt;
&lt;pre id=&quot;code_1674992670939&quot; class=&quot;kotlin&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@GetMapping(&quot;/write&quot;) // 저장 페이지.
    public String write(){
        return &quot;writer&quot;;
    }

    @PostMapping(&quot;/write/post&quot;) //저장 기능 구현.
    public String writerPost(HealthInfo healthInfo){
        homeService.write(healthInfo);

        return &quot;redirect:/home&quot;; //prg패턴.
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 서비스&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@Override //저장기능
    public void write(HealthInfo healthInfo) {
    healthRepository.save(healthInfo);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 수정하지 못한 업데이트&lt;/p&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1674992670943&quot; class=&quot;reasonml&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@PostMapping(&quot;/home/modified/update/{id}&quot;)
    public String postUpdate(@PathVariable Long id, HealthInfo healthInfo) {
        HealthInfo healthInfoTemp = homeService.healthView(id);
        healthInfoTemp.setBrand_name(healthInfo.getBrand_name());
        healthInfoTemp.setLand_number(healthInfo.getLand_number());
        healthInfoTemp.setRoad_number(healthInfo.getRoad_number());
        healthInfoTemp.setCategory(healthInfo.getCategory());

        homeService.write(healthInfo);
        return &quot;redirect:/home&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;/*    @Override //수정기능 값이 저장이 안됨.
    public void modifiedUpdate(Long id) {
        HealthInfo healthInfotmp = healthView(id);

        healthInfotmp.setBrand_name(healthInfo.getBrand_name());
        healthInfotmp.setLand_number(healthInfo.getLand_number());
        healthInfotmp.setRoad_number(healthInfo.getRoad_number());
        healthInfotmp.setCategory(healthInfo.getCategory());

        write(healthInfotmp);

    }*/&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엔티티값을 setter로 사용하면 안되는데, 아직 id값을 전달하지 못해서 헤메고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;페이징 기능 구현.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 home.html 파일을 두고 페이징 처리한 html 파일을 새로 만들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 서비스 클래스에서는 pageable 객체를 매개변수로 받아 데이터를 모두 찾아 페이지 타입으로 반환했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨트롤러에서는 서비스의 메서드로 찾아온 값들을 페이지 타입의 변수에 저장하고, 해당 변수를 model 객체에 add해준다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 컨트롤러&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;@GetMapping(&quot;/page&quot;)
public String pageHome(Model model, Pageable pageable) {

    Page&amp;lt;HealthInfo&amp;gt; healthInfoPage = homeService.healthList(pageable);
    model.addAttribute(&quot;pages&quot;,healthInfoPage);
    model.addAttribute(&quot;maxPage&quot;,5);

    return &quot;page&quot;;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 서비스&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@Override
public Page&amp;lt;HealthInfo&amp;gt; healthList(Pageable pageable){
        return healthRepository.findAll(pageable);

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 페이지 html&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;dust&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html xmlns:th=&quot;http://www.thymeleaf.org&quot;&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;title&amp;gt;헬스장 정보 페이지&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
&amp;lt;table border=&quot;1&quot;&amp;gt;
  &amp;lt;thead&amp;gt;
  &amp;lt;tr&amp;gt;
    &amp;lt;h1&amp;gt;Homepage&amp;lt;/h1&amp;gt;
  &amp;lt;/tr&amp;gt;
  &amp;lt;button type=&quot;submit&quot; onclick=&quot;location.href='/write'&quot;&amp;gt;글쓰기&amp;lt;/button&amp;gt;
  &amp;lt;/thead&amp;gt;
  &amp;lt;tbody&amp;gt;
  &amp;lt;tr th:each = &quot;healthInfo:${pages}&quot;&amp;gt;
    &amp;lt;td th:text=&quot;${healthInfo.id}&quot;&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;
      &amp;lt;a th:text=&quot;${healthInfo.brand_name}&quot;
         th:href=&quot;@{/home/view(id=${healthInfo.id})}&quot;&amp;gt;
      &amp;lt;/a&amp;gt;
      &amp;lt;a th:href=&quot;@{/home/delete(id=${healthInfo.id})}&quot;&amp;gt;삭제&amp;lt;/a&amp;gt;
    &amp;lt;/td&amp;gt;
  &amp;lt;/tr&amp;gt;
  &amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;div class=&quot;page-num&quot;
     th:with=&quot;start=${(pages.number/maxPage)*maxPage + 1},
                  end=(${(pages.totalPages == 0) ? 1 : (start + (maxPage - 1) &amp;lt; pages.totalPages ? start + (maxPage - 1) : pages.totalPages)})&quot;&amp;gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;li th:if=&quot;${start &amp;gt; 1}&quot;&amp;gt;
      &amp;lt;a th:href=&quot;@{/page?(page=0)}&quot; th:text=&quot;'&amp;lt;&amp;lt;'&quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
    &amp;lt;/li&amp;gt;

    &amp;lt;li th:if=&quot;${start &amp;gt; 1}&quot;&amp;gt;
      &amp;lt;a th:href=&quot;@{/page?(page=${start - maxPage})}&quot; th:text=&quot;'&amp;lt;'&quot;&amp;gt;&amp;lt;/a&amp;gt;
    &amp;lt;/li&amp;gt;

    &amp;lt;li th:each=&quot;page: ${#numbers.sequence(start, end)}&quot;&amp;gt;
      &amp;lt;a th:href=&quot;@{/page?(page=${page-1})}&quot; th:text=&quot;${page}&quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
    &amp;lt;/li&amp;gt;

    &amp;lt;li th:if=&quot;${end &amp;lt; pages.totalPages}&quot;&amp;gt;
      &amp;lt;a th:href=&quot;@{/page?(page=${start + maxPage})}&quot; th:text=&quot;'&amp;gt;'&quot;&amp;gt;&amp;lt;/a&amp;gt;
    &amp;lt;/li&amp;gt;

    &amp;lt;li th:if=&quot;${end &amp;lt; pages.totalPages}&quot;&amp;gt;
      &amp;lt;a th:href=&quot;@{/page?(page=${pages.totalPages-1})}&quot; th:text=&quot;'&amp;gt;&amp;gt;'&quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
    &amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;html 파일에서 번호를 지정하는 계산식은 모두 긁어왔는데, 아직은 계산방법을 온전히 이해하지 못했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 결과 페이지가 정상작동했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 내용은 2023.01.17에 공부한 내용입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://dudwls3278.tistory.com/44&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://dudwls3278.tistory.com/44&lt;/a&gt;&lt;/p&gt;</description>
      <category>GroupStudy</category>
      <category>group study</category>
      <category>side project</category>
      <category>게시판 만들기</category>
      <author>tuter77</author>
      <guid isPermaLink="true">https://dudwls3278.tistory.com/89</guid>
      <comments>https://dudwls3278.tistory.com/89#entry89comment</comments>
      <pubDate>Sun, 29 Jan 2023 20:45:07 +0900</pubDate>
    </item>
    <item>
      <title>Java : java의 여러 클래스</title>
      <link>https://dudwls3278.tistory.com/88</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #5c5c5c;&quot;&gt;●&amp;nbsp; 자바의 유용한 클래스&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ Object 클래스&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 모든 클래스의 최상위 클래스로 import 하지 않아도 자동으로 import 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;- import.java.lang.*;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;- 많이 사용하는 기본 클래스들이 속한 패키지이다.(String, Integer, System...)&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;- 모든 클래스는 Object를 상속받고 Object 클래스의 메서드 중 일부는 재정의해서 사용할 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;- 컴파일러가 extends Object를 추가한다.(class Student =&amp;gt; class Student extends Object)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷Object 클래스의 toString 메서드 오버라이딩&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;예제)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1674992607077&quot; class=&quot;arduino&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch01;

class Book{
	
	private String title;
	private String author;
	
	public Book(String title, String author) {
		this.title = title;
		this.author = author;
	}
	//오버라이딩.

	@Override
	public String toString() {
		return title + &quot;,&quot; +author;
	}
	
	
	

}


public class BookTest {
	public static void main(String[] args) {
		
		Book book = new Book(&quot;데미안&quot;, &quot;헤르만 헤세&quot;);
		System.out.println(book); //ch01.Book@5ca881b5 메모리에 위치의 16진수 가상값이다.
		
		String str = new String(&quot;test&quot;);
		System.out.println(str); // 이경우엔 문자열의 값이 나온다.
		// 이유는 str이 str.toString()으로 오버라이딩 되었기 때문
	
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제 코드에서 알 수 있듯이 toString은 문자열의 경우 자동으로 오버라이딩 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에 특정 클래스의 생성자로 인스턴스를 만들 경우 해당 인스턴스의 값을 인스턴스명으로 불러오려면, toString을 재정의 해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 클래스 Book에서 toString을 오버라이딩하여 리턴값을 변경해주면 book이 JVM에서 제공한 가상 메모리 값이 아닌, 오버라이딩한 toString의 반환값을 출력할 수 있게된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷Object 클래스의 메서드 활용.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- equals() 메서드는 두 인스턴스의 주소 값을 비교하여 true/false를 반환한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;- 재정의하여 두 인스턴스가 논리적으로 동일함의 여부를 구현한다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;- 인스턴스가 다르더라도 논리적으로 동일한 경우 true를 반환하도록 재정의 할 수있다.(같은 학번, 같은 사번, 같은 아이디의 회원 등)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-hashCode() 메서드는 인스턴스의 저장 주소를 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 힙메모리에 인스턴스가 저장되는 방식이 hash방식이며, 이는 정보를 저장 및 검색하는 자료구조이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 자료의 특정 값(키 값)에 대한 저장 위치를 반환해주는 해시 함수를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 때문에 equals() 메서드와 이 메서드는 페어여서 위의 메서드를 재정의하면, hashCode() 메서드의 반환값을 재정의한 equals() 의 키 값으로 설정해 주면된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;index(저장위치) = hash(해시함수)(key(객체정보))&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제) Student 클래스&lt;/p&gt;
&lt;pre id=&quot;code_1674992607082&quot; class=&quot;arduino&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch02;

public class Student {

	private int studentNum;
	private String studentName;
	
	public Student(int studentNum, String studentName) {
		this.studentNum = studentNum;
		this.studentName = studentName;
	}
	
	public String toString() {
		return studentNum + &quot;,&quot; +studentName;
	}

	@Override
	public boolean equals(Object obj) {
		if(obj instanceof Student) {
			Student std = (Student)obj;
			if(this.studentNum == std.studentNum) {
				return true;
			}else {
				return false;
			}
		}
		return false;
	}
	
	@Override
	public int hashCode() {
		return studentNum;
	}


}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 예시에서 toString, equals, hashCode를 재정의 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 아래 test 클래스에서 출력했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1674992607086&quot; class=&quot;reasonml&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch02;

public class EqualsTest {

	public static void main(String[] args) {

		Student std1 = new Student(100, &quot;Lee&quot;);
		Student std2 = new Student(100, &quot;Lee&quot;);
	
		
		System.out.println(std1 == std2); //주소는 다르지만
		System.out.println(std1.equals(std2)); //논리적으로 같은 학생.
	
		System.out.println(std1.hashCode());
		System.out.println(std2.hashCode()); // 해시코드를 바꾸지 않았기 때문에 다른 주소값 출력.
	
		System.out.println(System.identityHashCode(std1));
		System.out.println(System.identityHashCode(std2)); //해시코드 오버라이딩 후 진짜 주소값 찾는 메서드.
	
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 값을 입력한 두 인스턴스 std1과 std2는 주소는 다르지만 논리적으로 같은 학생이기 때문에, equals와 hashCode를 재정의했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 System.out.println(std1.equals(std2)); 코드를 실행하면 주소값만 나오지만 앞서 본 Student클래스에서 studentNum가 같으면 true를 반환하게끔 재정의했기때문에 두 인스턴스는 equals 메서드로 실행해보면 같은값이라는 true가 반환된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 해시코드 값을 찍어보면 다른 주소값이 나오는데 Student클래스에서 hashcode값을 studentNum으로 반환하게 했기때문에 다시 찍어보면 같은 값이 출력된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 진짜 주소값을 알고싶을땐, identityHashCode() 메서드로 출력하면 주소값을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과창.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;237&quot; data-origin-height=&quot;169&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4gjoX/btrXyiIzbP7/fos7mjNntmYJclhcURJcBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4gjoX/btrXyiIzbP7/fos7mjNntmYJclhcURJcBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4gjoX/btrXyiIzbP7/fos7mjNntmYJclhcURJcBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4gjoX%2FbtrXyiIzbP7%2Ffos7mjNntmYJclhcURJcBk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;237&quot; height=&quot;169&quot; data-origin-width=&quot;237&quot; data-origin-height=&quot;169&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷clone() 메서드&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 객체의 원본을 복제하는데 사용하는 메서드로 생성과정의 복잡한 과정을 반복하지 않고 복제할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- clone() 메서드를 사용하면 객체의 정보(멤버 변수 값 등)가 동일한 또 다른 인스턴스가 생성되는 것이므로, 객체 지향프로그램에서의 정보 은닉, 객체 보호의 관점에서 위배될 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 해당 클래스의 clone() 메서드의 사용을 허용한다는 의미로 cloneable 인터페이스를 명시해주어야한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1674992607091&quot; class=&quot;aspectj&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Student implements Cloneable{
	
    
    @Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 형태로 clone 메서드를 재정의하고&amp;nbsp; test 클래스에서 인스턴스를 생성해 아까 재정의된 toString으로 찍어보면,&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1674992607092&quot; class=&quot;abnf&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;		Student copyStudent = (Student)std1.clone();
		System.out.println(copyStudent);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;165&quot; data-origin-height=&quot;44&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FzOno/btrXyiu06Po/fULcYK8mLHJIl7eOwTWC3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FzOno/btrXyiu06Po/fULcYK8mLHJIl7eOwTWC3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FzOno/btrXyiu06Po/fULcYK8mLHJIl7eOwTWC3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFzOno%2FbtrXyiu06Po%2FfULcYK8mLHJIl7eOwTWC3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;165&quot; height=&quot;44&quot; data-origin-width=&quot;165&quot; data-origin-height=&quot;44&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;똑같은 객체 정보를 가져올 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ String 클래스&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- String 선언하기&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1674992607094&quot; class=&quot;arduino&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str1 = new String(&quot;abc&quot;); //힙메모리
String str2 = &quot;abc&quot;; //상수풀 주소만 가리킴.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 힙 메모리에 인스턴스로 생성되는 경우와 상수 풀에 잇는 주소를 참조하는 두 가지 방법이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 힙 메모리는 생성될 때마다 다른 주소값을 가지지만, 상수 풀의 문자열은 모두 같은 주소값을 가진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 한번 생성된 String은 불변이며(선언된 스트링은 자동으로 final로 선언되어있다.), String을 연결하면 기존의 String에 연결되는 것이 아닌 새로운 문자열이 생성된다.(메모리 낭비가 발생할 수 있다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 즉, concat() 메서드를 사용하여 두개의 스트링 변수를 연결하면, 새로운 변수가 생성되는 것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1674992607097&quot; class=&quot;processing&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;abc&quot;;
String str2 = &quot;def&quot;;

java = str.concat(str2);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;java는 새로운 변수이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 때문에 StringBuilder, StringBuffer를 활용하는 것을 권유하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ StringBuilder, StringBuffer 활용하기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 내부적으로 가변적인 char[]를 멤버변수로 갖는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 문자열을 여러번 연결하거나 변경할 때 사용하면 유용하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;- 새로운 인스턴스를 생성하지 않고&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;char[]를 변경한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;StringBuffer&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;는 멀티 쓰레드 프로그래밍에서 동기화를 보장한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 단일 쓰레드 프로그램에서는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;StringBuilder 사용을 권장한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- toString() 메서드로 String을 반환한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제)&lt;/p&gt;
&lt;pre id=&quot;code_1674992607100&quot; class=&quot;reasonml&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class StringTest {
	public static void main(String[] args) {
		
		String java = new String(&quot;java&quot;);
		String android = new String(&quot;android&quot;);
		
		System.out.println(System.identityHashCode(java));
		java = java.concat(android);
		
		System.out.println(System.identityHashCode(java)); //두 개의java는 다른 변수이다.
		System.out.println(java);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;233&quot; data-origin-height=&quot;109&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dpW7bG/btrXuajVXEg/PDggG9at9QuAd7cdi472l1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dpW7bG/btrXuajVXEg/PDggG9at9QuAd7cdi472l1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dpW7bG/btrXuajVXEg/PDggG9at9QuAd7cdi472l1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdpW7bG%2FbtrXuajVXEg%2FPDggG9at9QuAd7cdi472l1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;233&quot; height=&quot;109&quot; data-origin-width=&quot;233&quot; data-origin-height=&quot;109&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 java 변수의 주소값이 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1674992607102&quot; class=&quot;arduino&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class StringBuilderTest {

	public static void main(String[] args) {
		
		String java = new String(&quot;java&quot;);
		String android = new String(&quot;android&quot;);
		
		StringBuilder  buffer = new StringBuilder(java);
		
		System.out.println(System.identityHashCode(buffer));
		buffer.append(android);
		
		System.out.println(System.identityHashCode(buffer)); //같은 메모리 주소를 갖는 것을 알 수 있다.
		String test = buffer.toString(); // 스트링 인자로 사용하기 위해 
		
		System.out.println(test);
		}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;256&quot; data-origin-height=&quot;123&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSfk79/btrXtSQ971P/BM7Ujy9eKMFqoqvvN9KQEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSfk79/btrXtSQ971P/BM7Ujy9eKMFqoqvvN9KQEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSfk79/btrXtSQ971P/BM7Ujy9eKMFqoqvvN9KQEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSfk79%2FbtrXtSQ971P%2FBM7Ujy9eKMFqoqvvN9KQEk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;256&quot; height=&quot;123&quot; data-origin-width=&quot;256&quot; data-origin-height=&quot;123&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 예제에서 보면, concat을 활용한 변수 연결은 다른 주소값을 가진 새로운 인스턴스를 생성한다는 것을 알 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에 StringBuilder를 사용하면 같은 주소값을 확인할 수 있으므로, 연결되기 전후가 같은 변수라는 것을 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;StringBuilder는 배열의 형태이기때문에 toString으로 스트링인자로 값을 형변환 해주어야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ text block 사용하기(java 13 이상)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;- 문자열을 &quot;&quot;&quot; &quot;&quot;&quot; 사이에 이어서 만들 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;- html, json 문자열을 만드는데 유용하게 사용할 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;예제)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1674992607106&quot; class=&quot;ceylon&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch03;

public class TextBlockTest {
	public static void main(String[] args) {
		String textBlocks = &quot;&quot;&quot;
				Hello,
				hi,
				how r u&quot;&quot;&quot;;
		System.out.println(textBlocks);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;240&quot; data-origin-height=&quot;99&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c01Zsc/btrXo4LynTL/2UkrK8uftKNbP1GUINQyLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c01Zsc/btrXo4LynTL/2UkrK8uftKNbP1GUINQyLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c01Zsc/btrXo4LynTL/2UkrK8uftKNbP1GUINQyLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc01Zsc%2FbtrXo4LynTL%2F2UkrK8uftKNbP1GUINQyLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;240&quot; height=&quot;99&quot; data-origin-width=&quot;240&quot; data-origin-height=&quot;99&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ Class 클래스&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 자바의 모든 클래스와 인터페이스는 컴파일 후 class 파일이 생성된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- Class 클래스는 컴파일 된 class 파일을 로드하여 객체를 동적 로드하고, 정보를 가져오는 메서드가 제공된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- Class.forName(&quot;클래스 이름&quot;) 메서드로 클래스를 동적으로 로드한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1674992607108&quot; class=&quot;reasonml&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Class c = Class.forName(&quot;java.lang.String&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 클래스 이름으로 직접 Class 가져오기&lt;/p&gt;
&lt;pre id=&quot;code_1674992607109&quot; class=&quot;delphi&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Class c = String.class;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 생성된 인스턴스에서 Class 클래스 가져오기.&lt;/p&gt;
&lt;pre id=&quot;code_1674992607109&quot; class=&quot;gauss&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String s = new String();
Class c = s.getClass(); //Object 메서드.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 동적로딩&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 컴파일 시에 데이터 타입이 binding 되는 것이 아닌, 실행(runtime) 중에 데이터 타입을 binding 하는 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 프로그래밍 시에는 문자열 변수로 처리했다가, 런타임시에 원하는 클래스로 로딩하여 binding 할 수 있다는 장점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 컴파일 시에 타입이 정해지지 않으므로 동적 로딩시 오류가 발생하면 프로그램의 심각한 장애가 발생 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Class의 newInstance() 메서드로 인스턴스 생성을 할 수 있다. new 키워드를 사용하지 않고도 클래스 정보를 활용하여 인스턴스를 생성할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ 클래스 정보&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;-&amp;nbsp; reflection 프로그래밍: Class 클래스를 사용하여 클래스의 정보(생성자, 변수, 메서드)등을 알 수 있고, 인스턴스를 생성하고 메서드를 호출하는 방식의 프로그래밍이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 로컬 메모리에 객체가 없는 경우, 원격 프로그래밍, 객체의 타입을 알 수 없는 경우에 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- java.lang.reflect 패키지에 있는 클래스를 활용하여 프로그래밍 하며, 일반적으로 자료형을 알고 있는 경우엔 사용하지 않는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;위 내용은 2023.01.17에 공부한 내용입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5;&quot;&gt;링크 : &lt;a href=&quot;https://dudwls3278.tistory.com/44&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://dudwls3278.tistory.com/44&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>JavaStudy</category>
      <category>Java</category>
      <category>클래스 class</category>
      <category>클래스 object</category>
      <author>tuter77</author>
      <guid isPermaLink="true">https://dudwls3278.tistory.com/88</guid>
      <comments>https://dudwls3278.tistory.com/88#entry88comment</comments>
      <pubDate>Sun, 29 Jan 2023 20:44:07 +0900</pubDate>
    </item>
    <item>
      <title>게시판 만들기(8) - update 구현</title>
      <link>https://dudwls3278.tistory.com/87</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #5c5c5c;&quot;&gt;●&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;그룹스터디 게시판 웹 구현&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ CRUD 중 U&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;저번주에 진행하던 DB에서 데이터를 받아와 웹 브라우저에 띄워주는 작업을 마무리했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;조회, 새 글 저장, 기존 글 삭제 는 구현했지만 왜인지 수정기능이 작동하지 않았었는데 알고보니 어노테이션을 잘못 붙였었다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;PostMappting으로 해야 정보를 새로 저장하는 것이 가능한데 데이터를 가져오기만 하는 겟매핑 어노테이션으로 시도하고 있었던것....(멍청한 나.. 오탈자와 기본기에서 너무 모자라다.)&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;정상작동하게 된 코드는 아래와같다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;먼저 상세페이지.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;437&quot; data-origin-height=&quot;371&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TzIYL/btrXyjm91Jb/48nTAcm6inLdFTkVr2kwhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TzIYL/btrXyjm91Jb/48nTAcm6inLdFTkVr2kwhk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TzIYL/btrXyjm91Jb/48nTAcm6inLdFTkVr2kwhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTzIYL%2FbtrXyjm91Jb%2F48nTAcm6inLdFTkVr2kwhk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;437&quot; height=&quot;371&quot; data-origin-width=&quot;437&quot; data-origin-height=&quot;371&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 브라우저에서 해당 이름을 클릭하면 상세정보를 볼 수 있는 상세페이지로 넘어가는데 상세페이지는 아래와 같이 구현했던걸, 저번주에 공부했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 중 수정페이지로 넘어가는 버튼을 상세페이지 안에 구현했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;509&quot; data-origin-height=&quot;321&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cZJ5aj/btrXqr7x1X3/4Tz7ExXzDoxUsGqmW9Pxz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cZJ5aj/btrXqr7x1X3/4Tz7ExXzDoxUsGqmW9Pxz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cZJ5aj/btrXqr7x1X3/4Tz7ExXzDoxUsGqmW9Pxz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcZJ5aj%2FbtrXqr7x1X3%2F4Tz7ExXzDoxUsGqmW9Pxz0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;509&quot; height=&quot;321&quot; data-origin-width=&quot;509&quot; data-origin-height=&quot;321&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d9JB0O/btrWeeJlsZg/Nss194P1MCDuJk1JU6XBy1/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;이 수정버튼을 누르면 수정할 수 있는 html페이지로 넘어가게 된다.&quot;&gt;&lt;/span&gt;이 수정버튼을 누르면 수정할 수 있는 html페이지로 넘어가게 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1674992513288&quot; class=&quot;dust&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html xmlns:th=&quot;http://www.thymeleaf.org&quot;&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;title&amp;gt;상세페이지&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
    &amp;lt;h1 th:text=&quot;${healthInfo.brand_name}&quot;&amp;gt;&amp;lt;/h1&amp;gt;
    &amp;lt;p th:text=&quot;${healthInfo.land_number}&quot;&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;p th:text=&quot;${healthInfo.road_number}&quot;&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;p th:text=&quot;${healthInfo.category}&quot;&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;a th:href=&quot;@{/home/modified/{id}(id=${healthInfo.id})}&quot;&amp;gt;수정&amp;lt;/a&amp;gt;
    &amp;lt;a th:href=&quot;@{/home/delete(id=${healthInfo.id})}&quot;&amp;gt;삭제&amp;lt;/a&amp;gt;
    &amp;lt;button type=&quot;submit&quot; onclick=&quot;location.href='/home'&quot;&amp;gt;뒤로&amp;lt;/button&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 a태그를 사용해 링크를 걸었고, 해당 링크는 id값을 통해 수정페이지에 데이터를 불러온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정 페이지는 아래와 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;858&quot; data-origin-height=&quot;75&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zCDew/btrXwiPxOLq/WCAuO2fB16ZyILBRamJMDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zCDew/btrXwiPxOLq/WCAuO2fB16ZyILBRamJMDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zCDew/btrXwiPxOLq/WCAuO2fB16ZyILBRamJMDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzCDew%2FbtrXwiPxOLq%2FWCAuO2fB16ZyILBRamJMDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;858&quot; height=&quot;75&quot; data-origin-width=&quot;858&quot; data-origin-height=&quot;75&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 페이지는 아래 html로 구현했고, 요청은 컨트롤러에서 처리된다.&lt;/p&gt;
&lt;pre id=&quot;code_1674992513290&quot; class=&quot;dust&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html xmlns:th=&quot;http://www.thymeleaf.org&quot;&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;title&amp;gt;상세페이지&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
    &amp;lt;form th:action=&quot;@{/home/modified/update/{id}(id=${healthInfo.id})}&quot; method=&quot;post&quot;&amp;gt;
        &amp;lt;input name=&quot;brand_name&quot; type =&quot;text&quot; th:value=&quot;${healthInfo.brand_name}&quot;&amp;gt;
        &amp;lt;input name=&quot;land_number&quot; type =&quot;text&quot; th:value=&quot;${healthInfo.land_number}&quot;&amp;gt;
        &amp;lt;input name=&quot;road_number&quot; type =&quot;text&quot; th:value=&quot;${healthInfo.road_number}&quot;&amp;gt;
        &amp;lt;input name=&quot;category&quot; type =&quot;text&quot; th:value=&quot;${healthInfo.category}&quot;&amp;gt;
        &amp;lt;button type=&quot;submit&quot;&amp;gt;수정&amp;lt;/button&amp;gt;
        &amp;lt;a th:href=&quot;@{/home}&quot;&amp;gt;홈으로&amp;lt;/a&amp;gt;
    &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;id를 통해 각 값들을 th:value라는 키워드로 조회해서 가져온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 수정버튼을 누르면 수정기능이 수행되고 '홈으로' 버튼을 누르면 메인페이지로 돌아가게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;형태 자체는 writer.html 과 같지만, id를 통해 안에 값들을 불러서 보여준다는 점이 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상세페이지에서 수정버튼을 눌러 modified.html 페이지를 반환해주고 해당 데이터를 가져오는 컨트롤러의 기능은 아래와 같이 구현했다.&lt;/p&gt;
&lt;pre id=&quot;code_1674992513292&quot; class=&quot;kotlin&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    @GetMapping(&quot;/home/modified/{id}&quot;) //상세 페이지 내 수정
    public String modified(@PathVariable(&quot;id&quot;) Long id, Model model) {
        model.addAttribute(&quot;healthInfo&quot;, homeService.healthView(id));
        return &quot;modified&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 @Pathvariable이 또 보이는데 id값을 파라미터로 전달해주는 역할을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;model객체에 전달된 id값은 homeService의 healthView메서드로 데이터를 조회해서 값을 저장하고 이를 modified 페이지에 보여주게된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;값을 수정해서 새로 저장하여 보여주는 기능은 아래와 같이 구현했다.&lt;/p&gt;
&lt;pre id=&quot;code_1674992513294&quot; class=&quot;reasonml&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    @PostMapping(&quot;/home/modified/update/{id}&quot;)
    public String modifiedUpdate(@PathVariable(&quot;id&quot;) Long id, HealthInfo healthInfo) {
        HealthInfo healthInfoTemp = homeService.healthView(id); //id값으로 조회한 데이터 가져옴

        healthInfoTemp.setBrand_name(healthInfo.getBrand_name());
        healthInfoTemp.setLand_number(healthInfo.getLand_number());
        healthInfoTemp.setRoad_number(healthInfo.getRoad_number());
        healthInfoTemp.setCategory(healthInfo.getCategory());

        homeService.write(healthInfo);

        return &quot;redirect:/home&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기가 문제의 GetMapping 구간이었는데 이를 데이터를 저장할 수 있는 @PostMapping 어노테이션으로 바꾸어주니 정상 작동하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 modifiedUpdate() 메서드는 패스베리어블로 id값을 동일하게 전달 받고 이를 healthinfo 객체에 저장하여 첫 생성자 구문을 통해 값을 반환하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;healthInfo의 인스턴스 healthInfoTemp 는 반환된 값들을 갖고있고 해당 인스턴스에서 get/set 메서드를 통해 값들을 수정하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 값들이 객체에 잘 저장되었으니 db까지 저장시켜주는 코드는 homeService의 write 메서드이다. 이는 앞서 구현한 저장기능과 동일하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과적으로 수정이 잘되면 메인 페이지(home)를 재요청한다.(브라우저에 보여준다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 내용은 2023.01.16에 공부한 내용입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://dudwls3278.tistory.com/43&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://dudwls3278.tistory.com/43&lt;/a&gt;&lt;/p&gt;</description>
      <category>GroupStudy</category>
      <category>group study</category>
      <category>side project</category>
      <category>spring boot</category>
      <category>게시판 만들기</category>
      <author>tuter77</author>
      <guid isPermaLink="true">https://dudwls3278.tistory.com/87</guid>
      <comments>https://dudwls3278.tistory.com/87#entry87comment</comments>
      <pubDate>Sun, 29 Jan 2023 20:42:39 +0900</pubDate>
    </item>
    <item>
      <title>Java : 인터페이스(2)</title>
      <link>https://dudwls3278.tistory.com/86</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #5c5c5c;&quot;&gt;● 인터페이스&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ 실습&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;책 선반 클래스 만들어서 책넣기, 빼기 기능 구현.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Shelf라는 상위 클래스를 만들어 필요한 객체와 기능을 구현한다.&lt;/p&gt;
&lt;pre id=&quot;code_1674992442847&quot; class=&quot;arduino&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch15;

import java.util.ArrayList;

public class Shelf {

	protected ArrayList&amp;lt;String&amp;gt; shelf;
	
	// 위에서 생성자를 써도 되지만 public인 아래의 멤버변수로 생성자를 써주는게 낫다.
	public Shelf() {
		shelf = new ArrayList&amp;lt;&amp;gt;(); //string 안써도됨.
		
	}
	
	public ArrayList&amp;lt;String&amp;gt; getShelf(){
		return shelf;
	}
	
	public int getCount() {
		return shelf.size();
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 클래스는 상속받아야하기에 protected로 String을 매개로 받는 ArrayList &amp;gt; shelf객체를 생성하고 해당 객체는 아래에 pubic 생성자로 초기화한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성된 객체는 아래의 getShelf로 저장된 값을 가져올 수 있고, getCount 메서드로 들어있는 책이 몇권인지 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;getCount() 메서드에서는 ArrayList의 size() 메서드로 저장된 값의 크기를 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 Queue라는 인터페이스를 생성해 필요한 메서드를 정의한다.&lt;/p&gt;
&lt;pre id=&quot;code_1674992442850&quot; class=&quot;routeros&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch15;

public interface Queue {

	void enQueue(String title);
	String deQueue();
	
	int getSize();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 인터페이스에서 제목을 매개변수로 받아 책을 저장하는 enQueue()와 책을 빼내는 deQueue(), 그리고 책이 몇권들었는지 int값을 반환해주는 getSize()를 명시해놓는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 BookShelf 클래스를 만들어 이미 만들어둔 Shelf클래스를 상속하고, 인터페이스를 implements한다.&lt;/p&gt;
&lt;pre id=&quot;code_1674992442851&quot; class=&quot;aspectj&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch15;

public class BookShelf extends Shelf implements Queue{

	@Override
	public void enQueue(String title) {
		shelf.add(title);
	
	}

	@Override
	public String deQueue() {
		return shelf.remove(0);
	}

	@Override
	public int getSize() {
		return getCount(); //getCount가 상위클래스에 구현되어있기때문에
	}

	
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 인터페이스에서 정의된 메서드들을 오버라이딩하는데, enQueue()는 ArrayList의 add기능을 활용하여 책 제목을 저장하는 기능을 가진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 deQueue()는 ArrayList의 remove기능을 활용해 인덱스값이 0번째인 데이터(책제목)를 반환하고 해당 데이터를 삭제한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 getSize()는 상위클래스에서 정의해놓은 getCount() 메서드를 반환해 책이 몇권들었는지 알려준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트클래스.&lt;/p&gt;
&lt;pre id=&quot;code_1674992442855&quot; class=&quot;reasonml&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch15;

public class BookShelfTest {

	public static void main(String[] args) {

		Queue bookQueue = new BookShelf();
		bookQueue.enQueue(&quot;토지1&quot;);
		bookQueue.enQueue(&quot;토지2&quot;);
		bookQueue.enQueue(&quot;토지3&quot;);
		bookQueue.enQueue(&quot;토지4&quot;);
		bookQueue.enQueue(&quot;토지5&quot;);
		
		System.out.println(bookQueue.getSize());
		System.out.println(bookQueue.deQueue());//호출될때마다 한권씩 제거됨.
		System.out.println(bookQueue.deQueue());
		System.out.println(bookQueue.deQueue());
		System.out.println(bookQueue.deQueue());
		System.out.println(bookQueue.deQueue());
		System.out.println(bookQueue.getSize());
		
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트클래스에서 인스턴스를 생성하고, 해당 인스턴스에 5권의 책제목을 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 몇권이 들어있는지 확인한 뒤, 책을 한권한권 꺼내며 인스턴스에서 지워준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과창.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;398&quot; data-origin-height=&quot;202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJhESG/btrXv3dONjn/rPjKTgqkR5LEGP3RWfox9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJhESG/btrXv3dONjn/rPjKTgqkR5LEGP3RWfox9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJhESG/btrXv3dONjn/rPjKTgqkR5LEGP3RWfox9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJhESG%2FbtrXv3dONjn%2FrPjKTgqkR5LEGP3RWfox9K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;398&quot; height=&quot;202&quot; data-origin-width=&quot;398&quot; data-origin-height=&quot;202&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5권의 책을 모두 꺼내서 0권이 된 것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #5c5c5c;&quot;&gt;●&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;실습.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ gameLevel&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;Player가 있고, Player는 G&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;ameLevel속성을 가진다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;각&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;G&lt;/span&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;ameLevel 단계마다 run(), jump(), turn() 세가지 기능이 업그레이드 된다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;초보자 레벨 : 천천히 달립니다.(run() 만 가능)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;중급자 레벨 : 빠르게 달리고, 점프할 수 있습니다.(run(), jump() 가능)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;고급자 레벨 : 매우 빠르게 달리고, 높게 점프하며, 턴 할 수 있습니다.(run(), jump(), turn() 가능)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;player는 한번에 하나의 레벨 상태만을 가질 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;player가 play()중에 레벨에 있는 go(int count)라는 메서드를 호출하면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;run()하고 count횟수만큼 jump()하며, turn()한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;&lt;span&gt;아래 클래스 다이어그램을 참고해 각 레벨에서 go()가 호출될 때 아래와 같이 출력되도록 해야한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;409&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVb1o9/btrXtTo0hGf/RRolAxUvdpGAcAZI8Vg0VK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVb1o9/btrXtTo0hGf/RRolAxUvdpGAcAZI8Vg0VK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVb1o9/btrXtTo0hGf/RRolAxUvdpGAcAZI8Vg0VK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVb1o9%2FbtrXtTo0hGf%2FRRolAxUvdpGAcAZI8Vg0VK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;409&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;409&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;349&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FvRRO/btrXnHXTRVr/DrtelxuJh6KnK63xKRw2yK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FvRRO/btrXnHXTRVr/DrtelxuJh6KnK63xKRw2yK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FvRRO/btrXnHXTRVr/DrtelxuJh6KnK63xKRw2yK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFvRRO%2FbtrXnHXTRVr%2FDrtelxuJh6KnK63xKRw2yK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;536&quot; height=&quot;349&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;349&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 중심이되는 PlayerLevel클래스를 추상클래스로 구현한다.&lt;/p&gt;
&lt;pre id=&quot;code_1674992442864&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch16.gameLevel;

public abstract class PlayerLevel {

	public abstract void run();
	public abstract void jump();
	public abstract void turn();
	public abstract void showLevelMessage();
	
	final public void go(int count) {
		run();
		for(int i=0; i&amp;lt;count; i++) {
			jump();
		} 
		turn();	
	}
		
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;run(), jump(), turn(), showLevelMessage() 메서드를 정의하고 아래에 시나리오를 담고있는 go()메서드를 정의한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;jump()메서드는 count의 숫자만큼 반복하기때문에 for문을 이용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 메서드는 여기서 불리는 것이아니라, Player클래스에서 다른 메서드로 호출할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 객체 생성의 중심이 될 Player 클래스를 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1674992442867&quot; class=&quot;pgsql&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch16.gameLevel;

public class Player{

	private PlayerLevel level;
	
	public Player() {
		level = new BeginnerLevel();
		level.showLevelMessage();
	}
	
	public PlayerLevel getLevel() {
		return level;
	}

	public void upgradeLevel(PlayerLevel level) {
		this.level = level;
		level.showLevelMessage();
	}
	
	public void play(int count) {
		level.go(count);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 좀 헤맸는데, 인터페이스나 추상클래스로 선언을 해야할지 그냥 클래스로 만들어야할지 몰라서 다 시도해보다 일반클래스로 만들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국에 기능구현이 되어있어야하기 때문에 일반 클래스로 만들게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PlayerLevel 클래스의 객체를 하나 생성하여 각 메서드 내에서 PlayerLevel의 메서드들을 호출할 수 있도록했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Player() 메서드에서 level객체를 PlayerLevel을 상속하는 BegunnerLevel()의 인스턴스로 지정한다. (시작할때는 무조건 비기너)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 PlayerLevel의 showLevelMessage()메서드를 이용해 레벨을 한번 출력해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;getLevel은 현재의 레벨을 반환해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;upgradeLevel()은 파라미터로 PlayerLevel 타입의 level 변수를 매개변수로 받는다. 해당 매개변수의 showLevelMessage()메서드를 호출한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 level 변수를 바꿀 때마다 호출할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;play()는 메인 기능으로 level변수의 go기능을 호출하게 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;test에서 Player안의 기능만 사용하여 PlayerLevel의 기능들을 호출하게끔 구성했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 각 레벨의 클래스를 정의한다.&lt;/p&gt;
&lt;pre id=&quot;code_1674992442870&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch16.gameLevel;

public class BeginnerLevel extends PlayerLevel{


	@Override
	public void run() {
		System.out.println(&quot;천천히 달립니다.&quot;);
	}

	@Override
	public void jump() {
		System.out.println(&quot;jump 못하지롱&quot;);		
	}

	@Override
	public void turn() {
		System.out.println(&quot;turn 못하지롱&quot;);	
	}

	@Override
	public void showLevelMessage() {
		System.out.println(&quot;****** 초급자 레벨입니다. ******&quot;);		
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1674992442873&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch16.gameLevel;

public class AdvancedLevel extends PlayerLevel{
	
	@Override
	public void run() {
		System.out.println(&quot;빨리 달립니다.&quot;);
	}

	@Override
	public void jump() {
		System.out.println(&quot;높이 jump 합니다.&quot;);		
	}

	@Override
	public void turn() {
		System.out.println(&quot;turn 못하지롱&quot;);	
	}

	@Override
	public void showLevelMessage() {
		System.out.println(&quot;****** 중급자 레벨입니다. ******&quot;);	
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1674992442875&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch16.gameLevel;

public class SuperLevel extends PlayerLevel{
	
	
	@Override
	public void run() {
		System.out.println(&quot;엄청 빠르게 달립니다.&quot;);
	}

	@Override
	public void jump() {
		System.out.println(&quot;아주 높이 jump 합니다.&quot;);		
	}

	@Override
	public void turn() {
		System.out.println(&quot;turn 합니다.&quot;);	
	}

	@Override
	public void showLevelMessage() {
		System.out.println(&quot;****** 고급자 레벨입니다. ******&quot;);		
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 세 코드를 보면, 모두 extends 키워드로 PlayerLevel 추상 클래스를 상속하고 있고 해당 메서드들을 각 타입에 맞게 재정의하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 테스트 해보면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1674992442878&quot; class=&quot;haxe&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch16.gameLevel;

public class LevelTest {

	public static void main(String[] args) {

		Player player1 = new Player();
		player1.play(1);
		
		AdvancedLevel aLevel = new AdvancedLevel();
		player1.upgradeLevel(aLevel);
		player1.play(2);
		
		SuperLevel sLevel = new SuperLevel();
		player1.upgradeLevel(sLevel);
		player1.play(3);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자를 만들어 Player타입의 Player 클래스의 player1이라는 인스턴스를 생성하는데 아무것도 없이 이렇게 생성하면 기초값은 BeginnerLevel로 지정되어 있기때문에 이는 비기너 레벨을 가진 플레이어가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;play메서드를 호출해서 파라미터에 1만큼 count를 주었기에 jump메서드가 1회 반복될 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 AdvancedLevel 타입으로 aLevel이라는 인스턴스를 생성해 upgradeLevel에 넣어주면 player1 인스턴스는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;AdvancedLevel&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;타입의 메서드들을 호출하게된다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;같은 방식으로 SuperLevel까지 작성한뒤 결과를 돌려주면 아래와 같다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;494&quot; data-origin-height=&quot;389&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0ws0M/btrXrUobGQ3/dRCz3EKulZuway94ezQ3b1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0ws0M/btrXrUobGQ3/dRCz3EKulZuway94ezQ3b1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0ws0M/btrXrUobGQ3/dRCz3EKulZuway94ezQ3b1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0ws0M%2FbtrXrUobGQ3%2FdRCz3EKulZuway94ezQ3b1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;494&quot; height=&quot;389&quot; data-origin-width=&quot;494&quot; data-origin-height=&quot;389&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 결과창을 보면 count 만큼 jump가 반복되었고 각 타입에 맞게 메서드가 호출되었음을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 내용은 2023.01.16에 공부한 내용입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://dudwls3278.tistory.com/43&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://dudwls3278.tistory.com/43&lt;/a&gt;&lt;/p&gt;</description>
      <category>JavaStudy</category>
      <category>Interface</category>
      <category>Java</category>
      <author>tuter77</author>
      <guid isPermaLink="true">https://dudwls3278.tistory.com/86</guid>
      <comments>https://dudwls3278.tistory.com/86#entry86comment</comments>
      <pubDate>Sun, 29 Jan 2023 20:41:16 +0900</pubDate>
    </item>
    <item>
      <title>Java : 인터페이스 요소, 상속</title>
      <link>https://dudwls3278.tistory.com/85</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #5c5c5c;&quot;&gt;● 인터페이스의 여러 요소&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷상수&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 모든 변수는 인터페이스에서 상수로 변환 된다.(public static final)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷추상 메서드&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 모든 선언된 메서드는 추상 메서드가 된다.(public abstract)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ 디폴트 메서드(자바 8이후)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 구현을 가진느 메서드, 인터페이스를 구현하는 클래스들에서 공통으로 사용할 수 있는 기본 메서드이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- default 키워드를 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 구현하는 클래스에서 재정의할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 인터페이스를 구현한 클래스의 인스턴스가 생성되어야 사용가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ 정적 메서드(자바8 이후)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #373a3c;&quot;&gt;&lt;span&gt;- 인스턴스 생성과 상관 없이 인터페이스 타입으로 사용할 수 있는 메서드이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ private 메서드(자바 9이후)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 인터페이스를 구현한 클래스에서 사용하거나 재정의할 수 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 인터페이스 내부에서만 사용하기 위해 구현하는 메서드이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- default 메서드나 static 메서드에서 사용가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;예시)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1674992367045&quot; class=&quot;cs&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch14;

public interface Calc {

	double Pi = 3.14;
	int ERROR = -99999999;
	
	int add(int num1, int num2);
	int substarct(int num1, int num2);
	int times(int num1, int num2);
	int divide(int num1, int num2);
	
	//default 메서드 구현.
	default void description() {
		System.out.println(&quot;점수의 사칙연산을 제공합니다.&quot;);
	}
	
	//static 메서드 구현.
	static int total(int[] arr) {
		int total = 0;
		for(int num : arr) {
			total += num;
		}
		return total;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번 강의때 만들었던 인터페이스를 활용하여 디폴트 메서드와 정적 메서드를 구현했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1674992367051&quot; class=&quot;angelscript&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch14;

public class Calctest {

	public static void main(String[] args) {

		int num1 = 10;
		int num2 = 2;
		
		//인터페이스 타입 상속.
		Calc calc1 = new CompleteCalc();
		
		System.out.println(calc1.add(num1, num2));
		System.out.println(calc1.substarct(num1, num2));
		System.out.println(calc1.times(num1, num2));
		System.out.println(calc1.divide(num1, num2));
		
		CompleteCalc calc2 = new CompleteCalc();
		calc2.showInfo(); //타입이 CompleteCalc여야만 쓸 수 있는 메서드.
		
		//생성된 인스턴스로 default 메서드 실행.
		calc1.description();
		
		//생성자 없이 인터페이스로 호출해서 정적메서드 실행
		int[] arr = {1,2,3,4,5};
		System.out.println(Calc.total(arr));
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스를 implement하는 클래스와 그 클래스를 상속하는 클래스도 가져와서 테스트 클래스에서 디폴트 메서드와 정적 메서드를 실행해본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에서 공부한 바와 같이 디폴트메서드는 생성자를 통한 인스턴스가 있어야만 메서드를 실행할 수 있었고, 정적메서드는 인스턴스없이 인터페이스로 호출해서 사용할 수 있는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;156&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjfdCY/btrXnKmL8Mw/nTrOOXPdEZeEKDKccYfgoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjfdCY/btrXnKmL8Mw/nTrOOXPdEZeEKDKccYfgoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjfdCY/btrXnKmL8Mw/nTrOOXPdEZeEKDKccYfgoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjfdCY%2FbtrXnKmL8Mw%2FnTrOOXPdEZeEKDKccYfgoK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;609&quot; height=&quot;156&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;156&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 정적메서드는 재정의해서 사용할 수 도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;681&quot; data-origin-height=&quot;560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmAfPj/btrXooctMtS/3ydkZp1KdkcjbhuDLMkwEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmAfPj/btrXooctMtS/3ydkZp1KdkcjbhuDLMkwEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmAfPj/btrXooctMtS/3ydkZp1KdkcjbhuDLMkwEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmAfPj%2FbtrXooctMtS%2F3ydkZp1KdkcjbhuDLMkwEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;681&quot; height=&quot;560&quot; data-origin-width=&quot;681&quot; data-origin-height=&quot;560&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 private 메서드는 인터페이스 내에서만 사용하는 메서드로 위 처럼 선언하여 디폴트 또는 스태틱메서드에서 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 메서드는 임플리먼트한 클래스에서 오버라이드할 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #5c5c5c;&quot;&gt;●&amp;nbsp; 인터페이스 상속&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷&amp;nbsp; 여러 인터페이스 구현&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 자바의 인터페이스는 구현코드가 없으므로 하나의 클래스가 여러 인터페이스를 구현할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 디폴트 메서드가 중복 되는 경우는 구현하는 클래스에서 재정의 해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 여러 인터페이스를 구현한 클래스는 인터페이스 타입으로 형 변환 되는 경우 해당 인터페이스에 선언된 메서드만 사용이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 다이아몬드 Problem.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 클래스(GrandFaher)를 두개의 클래스(Father1, Faher2)가 상속하고 두 개의 클래스를 하나의 자식 클래스(Child)가 상속하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 GF클래스의 a(); 라는 메서드가 각각 F1,F2에서 오버라이딩 된다면, Child 클래스의 인스턴스 c가 a(); 메서드를 가져오면 어떤 메서드가 호출이 되는가라는 문제다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;java에서는 이러한 문제를 해결하기위해 다중상속은 할 수 없고 단일 상속만 가능하게 해놓았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다중 상속의 장점은 하나의 클래스(위의 예시에선 Child)가 풍부한 기능을 갖게 되는 것이고, 단점은 모호성이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바는 모호성을 없애서 안전한 방향으로 언어를 구성하고 있다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시) Customer클래스가 Buy와 Sell 두개의 인터페이스를 임플리먼트하는 상황.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Buy 인터페이스&lt;/p&gt;
&lt;pre id=&quot;code_1674992367060&quot; class=&quot;routeros&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch15;

public interface Buy {

	void buy();

	default void order() {
		System.out.println(&quot;buy order&quot;);
	}
	
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Sell 인터페이스&lt;/p&gt;
&lt;pre id=&quot;code_1674992367063&quot; class=&quot;routeros&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch15;

public interface Sell {

	void sell();

	default void order() {
		System.out.println(&quot;sell order&quot;);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 임플리먼트하는 customer 클래스&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1674992367064&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package ch15;

public class Customer implements Buy, Sell{

	@Override
	public void sell() {

		System.out.println(&quot;customer sell&quot;);
	}

	@Override
	public void buy() {
		System.out.println(&quot;customer buy&quot;);		
	}

	//buy도 sell도 아닌 customer 메서드로 재정의함
	@Override
	public void order() {
		System.out.println(&quot;customer order&quot;);	
	}
	
	public void hello() {
		System.out.println(&quot;hello&quot;);	
	}
	
	
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 테스트 클래스이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1674992367067&quot; class=&quot;routeros&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class CustomerTest {

	public static void main(String[] args) {
		
		Customer customer = new Customer();
		customer.buy();
		customer.sell();
		customer.order();
		customer.hello();
		
		Buy buyer = customer;
		buyer.buy();
		buyer.order();
		
		Sell seller = customer;
		seller.sell();
		seller.order();
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과물을 보면 오버라이드 된 메서드와 customer 고유의 메서드 모두 구현되는 걸 알 수 있고, 아래 인터페이스 타입으로 업캐스팅해도 각 메서드는 Customer에서 재정의된 메서드로 구현되는 것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;370&quot; data-origin-height=&quot;197&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m35Bg/btrXnuEwCF7/UupesQVohwRfDw6uLlMnDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m35Bg/btrXnuEwCF7/UupesQVohwRfDw6uLlMnDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m35Bg/btrXnuEwCF7/UupesQVohwRfDw6uLlMnDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm35Bg%2FbtrXnuEwCF7%2FUupesQVohwRfDw6uLlMnDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;370&quot; height=&quot;197&quot; data-origin-width=&quot;370&quot; data-origin-height=&quot;197&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ 인터페이스 상속&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 인터페이스 사이에도 상속을 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- extends 키워드를 사용하며, 인터페이스는 다중 상속이 가능하고 구현 코드의 상속이 아니므로 타입 상속 이라고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;▷ 클래스 상속과 인터페이스 구현 함께 쓰기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;- 실무에서 프레임 워크나 오픈소스와 함께 연동되는 구현을 하게 되면, 클래스 상속과 인터페이스의 구현을 같이 사용하는 경우가 많다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;위 내용은 2023.01.13에 공부한 내용입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f5f5; color: #373a3c;&quot;&gt;링크 : &lt;a href=&quot;https://dudwls3278.tistory.com/42&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://dudwls3278.tistory.com/42&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>JavaStudy</category>
      <category>Interface</category>
      <category>Java</category>
      <category>인터페이스 상속</category>
      <author>tuter77</author>
      <guid isPermaLink="true">https://dudwls3278.tistory.com/85</guid>
      <comments>https://dudwls3278.tistory.com/85#entry85comment</comments>
      <pubDate>Sun, 29 Jan 2023 20:40:02 +0900</pubDate>
    </item>
  </channel>
</rss>