<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>개발계발</title>
    <link>https://cod2048.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Tue, 14 Jul 2026 17:34:52 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Ju_Nik_E</managingEditor>
    <item>
      <title>[MSA 프로젝트] AWS S3 연결하기</title>
      <link>https://cod2048.tistory.com/44</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;어려운 건 아니지만 프로젝트를 진행하면서 AWS S3 연결할 때마다 방법을 까먹어서 기록해놓기&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 의존성 추가&lt;/p&gt;
&lt;pre id=&quot;code_1721373690611&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//s3
	implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'&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;2. yml파일 aws관련 코드 작성&lt;/p&gt;
&lt;pre id=&quot;code_1721373758716&quot; class=&quot;yaml&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;cloud:
  aws:
    stack:
      auto: false
    region:
      static: AWS지역
    credentials:
      access-key: 액세스키
      secret-key: 비밀키
    s3:
      bucket: 버킷명​&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;3. S3Config 파일 작성&lt;/p&gt;
&lt;pre id=&quot;code_1721373793658&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class S3Config {

    @Value(&quot;${cloud.aws.credentials.access-key}&quot;)
    private String accessKey;

    @Value(&quot;${cloud.aws.credentials.secret-key}&quot;)
    private String secretKey;

    @Value(&quot;${cloud.aws.region.static}&quot;)
    private String region;

    @Bean
    public AmazonS3 amazonS3Client() {
        BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);

        return AmazonS3ClientBuilder
                .standard()
                .withRegion(region)
                .withCredentials(new AWSStaticCredentialsProvider(credentials))
                .build();
    }
}&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;4. S3Serivce 파일 작성(기본적으로 파일 업로드, 삭제기능, 필요 시 추가)&lt;/p&gt;
&lt;pre id=&quot;code_1721373848622&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import com.amazonaws.services.s3.AmazonS3;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

@Service
@RequiredArgsConstructor
public class S3Service {
    private final AmazonS3 amazonS3Client;

    @Value(&quot;${cloud.aws.s3.bucket}&quot;)
    private String bucket;

    public String uploadFile(String fileName, MultipartFile file) throws IOException {
        amazonS3Client.putObject(bucket, fileName, file.getInputStream(), null);
        return amazonS3Client.getUrl(bucket, fileName).toString();
    }

    public void deleteFile(String fileName) {
        amazonS3Client.deleteObject(bucket, fileName);
    }
}&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;5. 아래와 같이 서비스 코드에 S3Service 주입하고 사용하면 끝!&lt;/p&gt;
&lt;pre id=&quot;code_1721377545552&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Slf4j
@Service
@RequiredArgsConstructor
public class LectureNoteService {
    private final LectureNoteRepository lectureNoteRepository;
    private final S3Service s3Service;
    
    /**
     * 강의 노트 등록
     */
    @Transactional
    public LectureNoteResponseDto create(Long lectureId, String title, MultipartFile file) {
        String fileUrl;
        try {
            String fileName = &quot;lecture-notes/&quot; + UUID.randomUUID() + &quot;-&quot; + file.getOriginalFilename();
            fileUrl = s3Service.uploadFile(fileName, file);
        } catch (IOException e) {
            throw new CustomException(ErrorCode.FILE_UPLOAD_FAILED);
        }

        LectureNote lectureNote = LectureNote.builder()
                .lectureId(lectureId)
                .title(title)
                .fileUrl(fileUrl)
                .build();

        LectureNote savedLectureNote = lectureNoteRepository.save(lectureNote);

        return LectureNoteResponseDto.builder()
                .noteId(savedLectureNote.getNoteId())
                .lectureId(savedLectureNote.getLectureId())
                .title(savedLectureNote.getTitle())
                .fileUrl(savedLectureNote.getFileUrl())
                .build();
    }
}​&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프로젝트</category>
      <author>Ju_Nik_E</author>
      <guid isPermaLink="true">https://cod2048.tistory.com/44</guid>
      <comments>https://cod2048.tistory.com/44#entry44comment</comments>
      <pubDate>Fri, 19 Jul 2024 16:25:12 +0900</pubDate>
    </item>
    <item>
      <title>[MSA 프로젝트] 각 서비스끼리 통신하기 만들기</title>
      <link>https://cod2048.tistory.com/43</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-size: 1em; letter-spacing: 0px; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif;&quot;&gt;MSA 구조 프로젝트를 진행하던 중 각 서비스끼리 통신하는 방법에 대해 기록해놓으려고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;WebClient&lt;/b&gt;와&amp;nbsp;&lt;b&gt;FeignClient, &lt;/b&gt;크게 두 가지 방법이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 프로젝트에 적용한 것은 &lt;b&gt;FeignClient&lt;/b&gt;이지만, 두 가지 방법 모두 기록해놓자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;WebClient&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹클라이언트를 사용하려면 아래 과정을 따라가면 된다.(의존성 파일에 spring-boot-starter-webflux가 추가필요)&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;1. Bean 등록&lt;/p&gt;
&lt;pre id=&quot;code_1721372956907&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;

@Configuration
public class WebClientConfig {

    @Bean
    public WebClient.Builder webClientBuilder() {
        return WebClient.builder();
    }
}&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;2. 요청 작성(Get, Post요청 예시)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1721373039491&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

@Service
public class MyService {

    @Autowired
    private WebClient.Builder webClientBuilder;

    public String getExample() {
        WebClient webClient = webClientBuilder.build();
        Mono&amp;lt;String&amp;gt; response = webClient.get()
            .uri(&quot;http://example.com/api/resource&quot;)
            .retrieve()
            .bodyToMono(String.class);

        return response.block();
    }
    
    public String postExample() {
        WebClient webClient = webClientBuilder.build();
        MyRequestObject request = new MyRequestObject(&quot;data1&quot;, &quot;data2&quot;);
        Mono&amp;lt;String&amp;gt; response = webClient.post()
            .uri(&quot;http://example.com/api/resource&quot;)
            .bodyValue(request)
            .retrieve()
            .bodyToMono(String.class);

        return response.block();
    }
}&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;b&gt;WebClient&lt;/b&gt; 사용법인데, 요청의 상세내용을 메서드로 상세하게 작성해줘야하는 번거로움이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이에 반해&amp;nbsp;&lt;b&gt;FeignClient&lt;/b&gt;는 인터페이스를 이용해 선언적 방식으로 아주 간단하게 요청을 보낼 수가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;FeignClient&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;feignClient를 이용하기위해선 우선 의존성 추가가 필요하다.&lt;/p&gt;
&lt;pre id=&quot;code_1721373175894&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:4.1.0'&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;p data-ke-size=&quot;size16&quot;&gt;이후 FeignClient 어노테이션을 이용해 아래와 같이 코드를 작성하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1721373281790&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.jk.module_lecture.client;

import com.jk.module_lecture.common.config.FeignConfig;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

@FeignClient(name = &quot;lectureResourceClient&quot;, url = &quot;${feign.lectureResourceClient.url}&quot;, configuration = FeignConfig.class)
public interface LectureResourceClient {

    @RequestMapping(method = RequestMethod.POST, value = &quot;/api/v1/internal/lectures/notes&quot;, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    void createNote(@RequestPart(&quot;file&quot;) MultipartFile file, @RequestParam(&quot;lectureId&quot;) Long lectureId, @RequestParam(&quot;title&quot;) String title);

    @RequestMapping(method = RequestMethod.POST, value = &quot;/api/v1/internal/lectures/multimedia&quot;, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    void createVideo(@RequestPart(&quot;file&quot;) MultipartFile file, @RequestParam(&quot;lectureId&quot;) Long lectureId);

    @RequestMapping(method = RequestMethod.GET, value = &quot;/api/v1/internal/lectures/notes/{lectureId}&quot;, consumes = &quot;application/json&quot;)
    String getNoteUrl(@PathVariable(&quot;lectureId&quot;) Long noteId);

    @RequestMapping(method = RequestMethod.GET, value = &quot;/api/v1/internal/lectures/multimedia/{lectureId}&quot;, consumes = &quot;application/json&quot;)
    String getVideoRul(@PathVariable(&quot;lectureId&quot;) Long videoId);
}&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;pre id=&quot;code_1721373361990&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Slf4j
@Service
@RequiredArgsConstructor

public class LectureService {
	private final LectureRepository lectureRepository;
	private final LectureResourceClient lectureResourceClient;
    
    
    /**
     * 강의 등록
     */
    @Transactional
    public LectureCreateResponseDto create(Long teacherId, LectureCreateRequestDto lectureCreateRequestDto) {
        Lecture lecture = Lecture.builder()
                .title(lectureCreateRequestDto.title())
                .description(lectureCreateRequestDto.description())
                .teacherId(teacherId)
                .price(lectureCreateRequestDto.price())
                .build();

        Lecture savedLecture = lectureRepository.save(lecture);

        lectureResourceClient.createNote(
                lectureCreateRequestDto.file(),
                savedLecture.getLectureId(),
                savedLecture.getTitle()
        );

        lectureResourceClient.createVideo(
                lectureCreateRequestDto.video(),
                savedLecture.getLectureId()
        );

        return LectureCreateResponseDto.builder()
                .lectureId(savedLecture.getLectureId())
                .title(savedLecture.getTitle())
                .description(savedLecture.getDescription())
                .teacherId(savedLecture.getTeacherId())
                .price(savedLecture.getPrice())
                .build();
    }
}&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;위와 같이 서비스 코드에 lectureResourceClient를 주입받아와 간단하게 요청을 보낼 수 있게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 요청을 받는 서비스 모듈은 InternalController api주소를 생성해서 받으면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1721373477871&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@RestController
@RequiredArgsConstructor
@RequestMapping(&quot;/api/v1/internal/lectures/notes&quot;)
public class InternalLectureNoteController {
    private final LectureNoteService lectureNoteService;
    
    @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ResponseEntity&amp;lt;Void&amp;gt; createNote(
            @RequestPart(name = &quot;file&quot;) MultipartFile file,
            @RequestParam(name = &quot;lectureId&quot;) Long lectureId,
            @RequestParam(name = &quot;title&quot;) String title
    ) {
        lectureNoteService.create(lectureId, title, file);
        return ResponseEntity.ok().build();
    }
    
}&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;내부적으로 데이터를 주고 받는 것이기 때문에, 요청/응답에 대한 상세내용 또한 외부로 알릴 필요가 없어, WebClient보다 훨씬 간단하게 사용가능한 FeignClient를 사용하자.&lt;/p&gt;</description>
      <category>프로젝트</category>
      <author>Ju_Nik_E</author>
      <guid isPermaLink="true">https://cod2048.tistory.com/43</guid>
      <comments>https://cod2048.tistory.com/43#entry43comment</comments>
      <pubDate>Fri, 19 Jul 2024 16:19:23 +0900</pubDate>
    </item>
    <item>
      <title>배열에서 중복을 제거하는 법</title>
      <link>https://cod2048.tistory.com/42</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/120852&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/120852&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1718287051540&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/120852&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bf7NUH/hyWlibVvuP/QxBZoIUw7XpFLmLoRyedKk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/3TppS/hyWlcJyBhE/9Vs9kKZrtgNrgvqfbt4wE1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/120852&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/120852&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bf7NUH/hyWlibVvuP/QxBZoIUw7XpFLmLoRyedKk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/3TppS/hyWlcJyBhE/9Vs9kKZrtgNrgvqfbt4wE1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 문제를 풀다가 answer를 반환할 때 중복을 제거하는 방법에서 막힘&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_1718287091244&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(n):
    answer = []
    divide_num = 2
    while divide_num &amp;lt;= n:
        if n % divide_num == 0:
            answer.append(divide_num)
            n = n / divide_num
        else:
            divide_num += 1
    return list(set(answer))&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;위와 같았는데, 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;그래서 dict을 써서 아래와 같이 중복을 제거하고 순서도 보장해주는 아래와 같이 변경함.&lt;/p&gt;
&lt;pre id=&quot;code_1718287138479&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(n):
    answer = []
    divide_num = 2
    while divide_num &amp;lt;= n:
        if n % divide_num == 0:
            answer.append(divide_num)
            n = n / divide_num
        else:
            divide_num += 1
    return list(dict.fromkeys(answer))&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결론&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;list(dict.fromkeys(answer))&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드 잘 기억하자&lt;/p&gt;</description>
      <category>알고리즘</category>
      <author>Ju_Nik_E</author>
      <guid isPermaLink="true">https://cod2048.tistory.com/42</guid>
      <comments>https://cod2048.tistory.com/42#entry42comment</comments>
      <pubDate>Thu, 13 Jun 2024 22:59:19 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 - 3진법 뒤집기(68935)</title>
      <link>https://cod2048.tistory.com/41</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제링크&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/68935&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/68935&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1715905229957&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/68935&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/pwBsc/hyV6ipxz3E/cYEvOANWlvQ9VOHElQpdok/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/KAsyF/hyV6lNqW8x/WxVelKDzkw87W6X5NG1Pd0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/68935&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/68935&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/pwBsc/hyV6ipxz3E/cYEvOANWlvQ9VOHElQpdok/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/KAsyF/hyV6lNqW8x/WxVelKDzkw87W6X5NG1Pd0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;접근방식&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 입력값 n을 3으로 나눈 나머지를 3진법으로 변환한 코드에 넣는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. n을 3으로 나눈 몫으로 바꾼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 위 과정을 n이 0이 될 때까지 반복한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이코드&lt;/h2&gt;
&lt;pre id=&quot;code_1715905305035&quot; class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;def solution(n):
    answer = 0
    formation_3 = &quot;&quot;
    # i = 1
    
    while n &amp;gt; 0:
        formation_3 += str(n % 3)
        n = n // 3
        
    # for j in range(len(formation_3)-1, -1 ,-1):
    #     answer += i * int(formation_3[j])
    #     i *= 3

    answer = int(formation_3, 3)
    
    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;알아두면 좋은 것&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 위 코드에 while문 블록에 있는 3을 다른 숫자로 바꾸면 그대로 [해당 숫자진법]이 된다.(단, 변환 결과가 거꾸로 나오니 다시 뒤집어줘야함, 이 문제는 애초에 뒤집어서 반환하는 거라 안 뒤집엇음)&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;- int함수의 2번째 매개변수로 숫자를 주면 첫번째 매개변수를 해당 숫자진법으로 해석하고 10진법으로 변환해줌&lt;/p&gt;</description>
      <category>알고리즘</category>
      <author>Ju_Nik_E</author>
      <guid isPermaLink="true">https://cod2048.tistory.com/41</guid>
      <comments>https://cod2048.tistory.com/41#entry41comment</comments>
      <pubDate>Fri, 17 May 2024 09:24:15 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 - 큰 수 만들기(42883)</title>
      <link>https://cod2048.tistory.com/40</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 링크&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42883&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/42883&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1715840080482&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42883&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/n0kZk/hyV57nNk8A/8Zr1BmaymDPIVasgvFg7F0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/fPHsv/hyV6cvRDXa/e2N4LGsKJDSvMgfgZT7Suk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42883&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42883&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/n0kZk/hyV57nNk8A/8Zr1BmaymDPIVasgvFg7F0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/fPHsv/hyV6cvRDXa/e2N4LGsKJDSvMgfgZT7Suk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;접근 방식1 (틀림)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 입력값인 number를 정렬&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 정렬된 값에서 순서대로 작은 숫자 k를 삭제한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 값을 지우고 남은 숫자들을 원래 순서대로 다시 조합한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이 코드1&amp;nbsp; (틀림)&lt;/h2&gt;
&lt;pre id=&quot;code_1715840289650&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(number, k):
    answer = ''
    numbers = []
    
    for idx, num in enumerate(number):
        numbers.append((idx, int(num)))
        
    numbers.sort(key = lambda x : (x[1], x[0]), reverse = True)
    
    for _ in range(k):
        numbers.pop()
        
    numbers.sort(key = lambda x : x[0])
        
    for i in range(len(numbers)):
        answer += str(numbers[i][1])
        
    return answer&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;- 문제의 1, 2번 예시는 맞는데 3번 예시는 틀림&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 작은수를 k개 빼는 게 아니라 자릿수의 대소관계를 생각해야 함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;접근방식 2 (시간초과)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. number의 맨 앞자리와 바로 뒷자리를 비교&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 앞자리가 더 작을경우 삭제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 위 과정을 k번 반복&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 앞자리가 더 작은 경우가 없으면 number의 맨 뒤 숫자 삭제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이코드 2 (로직은 맞음,&amp;nbsp;시간초과)&lt;/h2&gt;
&lt;pre id=&quot;code_1715840413230&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(number, k):
    answer = ''
    front_num = ''
    back_num = ''
    
    # i가 i+1보다 커야만 함, 작으면 지워져야함
    for count in range(k):
        for i in range(len(number)-1):
            if int(number[i]) &amp;lt; int(number[i+1]):
                front_num = number[:i]
                back_num = number[i+1:]
                number = front_num + back_num
                break
        else:
            number = number[:-1]
            
    return number&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;- stack을 이용한 아래 코드로 개선&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이코드3 (정답)&lt;/h2&gt;
&lt;pre id=&quot;code_1715840548635&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(number, k):
    answer = ''
    stk = []
    
    for num in number:
        while stk and stk[-1] &amp;lt; num and k &amp;gt; 0:
            stk.pop()
            k -= 1
        stk.append(num)
    
    answer = &quot;&quot;.join(stk)
    
    if k &amp;gt; 0:
        answer = answer[:-k]
    
    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;주의사항&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- number가 &quot;333222111&quot;처럼 맨 앞에서 맨 뒤까지 계속해서 같거나 작아지는 경우만 있는 경우 while을 들어가지 못함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;--&amp;gt; 이런 경우 맨 뒷자리를 지우면 되기 때문에 남은 k만큼 뒤를 지워주면 됨&lt;/p&gt;</description>
      <category>알고리즘</category>
      <author>Ju_Nik_E</author>
      <guid isPermaLink="true">https://cod2048.tistory.com/40</guid>
      <comments>https://cod2048.tistory.com/40#entry40comment</comments>
      <pubDate>Thu, 16 May 2024 15:24:18 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 - 기사단원의 무기(136798)</title>
      <link>https://cod2048.tistory.com/39</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 설명&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/136798&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/136798&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1715839598529&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/136798&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/urFa0/hyV6dO36T8/BJxNR5DrExR36vcL6H0qB1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ddm3hn/hyV59TqDvq/rr17Ny96nbq50zxZtPDJBK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/136798&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/136798&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/urFa0/hyV6dO36T8/BJxNR5DrExR36vcL6H0qB1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ddm3hn/hyV59TqDvq/rr17Ny96nbq50zxZtPDJBK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;접근 방식&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. [1~number]까지의 약수의 갯수를 모두 구해서 리스트에 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1-1. 약수의 갯수가 limit보다 크면 리스트에 약수의 갯수 대신 power를 넣음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 리스트의 합 구해서 반환&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이 코드1(정답)&lt;/h2&gt;
&lt;pre id=&quot;code_1715839726525&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def count_divisors(number, limit):
    if number == 1:
        return 1
    
    result = 0
    
    for num in range(1, int(number**(1/2)) + 1):
        if number % num == 0:
            if num * num == number:
                result += 1
            else:
                result += 2
            
            if result &amp;gt; limit:
                return 0
    
    return result

def solution(number, limit, power):
    answer = 0
    divisors = []
    for num in range(1, number+1):
        result = count_divisors(num, limit)
        if result == 0:
            divisors.append(power)
        else:
            divisors.append(result)
        
    return sum(divisors)&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;- 약수의 갯수를 구할 때 for문의 범위를 해당 숫자의 제곱근 + 1 까지로 하지 않으면 시간초과가 난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 같은 수끼리 곱했을 때는 1만 더해주고 아닐 경우에는 2씩 더해주면 된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 16의 약수의 갯수를 구할 때 for문의 범위는 (제곱근+1)인 5까지로 하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1*16 일때는 1과 4, 약수가 2개 구해지기때문에 약수의 갯수에 2를 더해주고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4*4 일때는 약수가 1개이기 때문에 약수의 갯수에 1을 더해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이 코드2 (스터디원의 풀이, 약수 구하는 시간 복잡도 개선)&lt;/h2&gt;
&lt;pre id=&quot;code_1715839918425&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(number, limit, power):
    divisor_count = [0] * (number + 1)
    
    for i in range(1, number + 1):
        for j in range(i, number + 1, i):
            divisor_count[j] += 1
            
    for idx in range(1, number + 1):
        if divisor_count[idx] &amp;gt; limit:
            divisor_count[idx] = power
            
    return sum(divisor_count)&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;1. 약수의 갯수를 저장할 리스트를 초기화한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 2중 for문으로 리스트를 도는데, 안쪽 for문은 i씩(i의 배수) 커지도록 한다.&lt;/p&gt;</description>
      <category>알고리즘</category>
      <author>Ju_Nik_E</author>
      <guid isPermaLink="true">https://cod2048.tistory.com/39</guid>
      <comments>https://cod2048.tistory.com/39#entry39comment</comments>
      <pubDate>Thu, 16 May 2024 15:13:42 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 - 행렬의 곱셈(12949)</title>
      <link>https://cod2048.tistory.com/38</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 설명&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;2차원 행렬 arr1과 arr2를 입력받아, arr1에 arr2를 곱한 결과를 반환하는 함수, solution을 완성해주세요.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;제한 조건&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;- 행렬 arr1, arr2의 행과 열의 길이는 2 이상 100 이하입니다.&lt;br /&gt;- 행렬 arr1, arr2의 원소는 -10 이상 20 이하인 자연수입니다.&lt;br /&gt;- 곱할 수 있는 배열만 주어집니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;접근 방식&lt;/h2&gt;
&lt;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;519&quot; data-origin-height=&quot;197&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/drTQkf/btsG6Y8ujWL/w2DTd3ABkcWioklMepJ7G0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/drTQkf/btsG6Y8ujWL/w2DTd3ABkcWioklMepJ7G0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/drTQkf/btsG6Y8ujWL/w2DTd3ABkcWioklMepJ7G0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdrTQkf%2FbtsG6Y8ujWL%2Fw2DTd3ABkcWioklMepJ7G0%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;519&quot; height=&quot;197&quot; data-origin-width=&quot;519&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;- a*b 크기의 행렬과 c*d 크기의 곱셈의 결과 행렬의 크기는 a*d이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 첫째 행렬의 열 갯수와 둘째 행렬의 행 갯수가 동일해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 곱셈한 결과의 1행의 0번 인덱스는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[첫번째 행렬의 (0,0) 원소 * 두번째 행렬의 (0,0) 원소] + [첫번째 행렬의 (0,1) 원소 * 두번째 행렬의 (1,0) 원소]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 즉, 첫번째 행렬은 행의 인덱스(x)가 증가, 두번째행렬은 열의 인덱스(y)가 증가&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;1. [arr2의 안에 1차원 배열의 크기 * arr2의 1차원 배열의 크기] 의 배열 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 첫번째 행렬의 y값이 1씩 증가하고, 두번째 행렬의 x값이 1씩 증가하도록 중첩 for문 구현&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정답 코드&lt;/h2&gt;
&lt;pre id=&quot;code_1714696975783&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(arr1, arr2):
    answer = [[0] * len(arr2[0]) for _ in range(len(arr1))]
    
    for i in range(len(arr1)):
        for j in range(len(arr2[0])):
            for k in range(len(arr2)):
                answer[i][j] += arr1[i][k] * arr2[k][j]
    
    return answer&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘</category>
      <author>Ju_Nik_E</author>
      <guid isPermaLink="true">https://cod2048.tistory.com/38</guid>
      <comments>https://cod2048.tistory.com/38#entry38comment</comments>
      <pubDate>Fri, 3 May 2024 09:43:38 +0900</pubDate>
    </item>
    <item>
      <title>인터페이스의 타입 변환과 다형성</title>
      <link>https://cod2048.tistory.com/37</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;타입 변환&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;인터페이스의 타입 변환은&amp;nbsp;&lt;b&gt;인터페이스와 구현 클래스 간에 발생한다.&lt;/b&gt;&lt;br /&gt;자동 타입 변환과 강제타입 변환이 있는데, 인터페이스 변수에 구현 객체를 대입하면 구현 객체는 인터페이스 타입으로 자동 타입 변환되고, 인터페이스 타입을 구현 클래스로 타입으로 변환시킬 때는 강제 타입 변환이 필요하다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자동 타입 변환&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;말 그대로 자동으로 타입 변환이 일어나는 것으로, 아래와 같은 조건에서 일어난다.&lt;br /&gt;&lt;b&gt;인터페이스 변수 = 구현객체;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;552&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCUj0F/btsG8pjk4wl/Q6qQx9riYCa2dsSbDOma30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCUj0F/btsG8pjk4wl/Q6qQx9riYCa2dsSbDOma30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCUj0F/btsG8pjk4wl/Q6qQx9riYCa2dsSbDOma30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCUj0F%2FbtsG8pjk4wl%2FQ6qQx9riYCa2dsSbDOma30%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;560&quot; height=&quot;345&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;552&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 이미처럼 인터페이스를 구현한 B, C 클래스가 있고, B와 C클래스를 각각 상속한 D, E 자식 클래스가 있을 때,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;B,C,D,E로부터 생성된 객체는 모두 인터페이스 A로 자동 타입 변환이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;B,C,D,E가 클래스가 모두 작성됐다고 가정하면 아래와 같이 자동 타입 변환이 가능하다.&lt;/p&gt;
&lt;pre id=&quot;code_1714634924431&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class PromotionExample {
	public static void main(String[] args) {
    	//구현 객체 생성
        B b = new B();
        C c = new C();
        D d = new D();
        E e = new E();
        
        //인터페이스 변수
        A a;
        
        //자동 타입 변환
        a = b;
        a = c;
        a = d;
        a = c;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예시처럼, 구현 객체인 b,c,d,e의 타입은 모두 A로 타입변환이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;강제 타입 변환&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;강제 타입 변환은 캐스팅 기호를 이용해 인터페이스 타입을 구현 클래스 타입으로 변환시키는 것이다.&lt;br /&gt;&lt;b&gt;구현 클래스 변수 = (구현클래스) 인터페이스변수;&lt;/b&gt;&lt;/blockquote&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_1714635326399&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface Vehicle {
	// 추상 메소드
    void run();
}

public class Bus implements Vehicle {
	// 추상 메소드 재정의
	@Override
    public void run() {
    	System.out.println(&quot;버스 운행 시작&quot;);
    }
    
    // 추가 메소드
    public void checkFare() {
    	System.out.println(&quot;요금 확인&quot;);
    }
}

public class CastingExample {
	public static void mian(String[] args) {
    	// 인터페이스에 구현 객체를 대입해 자동 타입 변환
    	Vehicle vehicle = new Bus();
        
        // 인터페이스의 메소드 사용
        vehicle.run();
        // vehicle.checkFare(); 자동타입변환되어 Bus클래스의 추가 메소드 사용 불가
        
        // 강제 타입변환
        Bus bus = (Bus) vehicle;
        bus.checkFare(); // 강제타입 변환을 했기 때문에 사용 가능
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다형성&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;사용 방법은 동일하지만 다양한 결과가 나오는 성질인 다형성은 상속에서도 사용하지만, 인터페이스를 통해 다형성을 구현하는 경우가 많다.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;534&quot; data-origin-height=&quot;252&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8hVFB/btsG6eb239T/VzMlWNlunMKN72pjZ7AXGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8hVFB/btsG6eb239T/VzMlWNlunMKN72pjZ7AXGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8hVFB/btsG6eb239T/VzMlWNlunMKN72pjZ7AXGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8hVFB%2FbtsG6eb239T%2FVzMlWNlunMKN72pjZ7AXGK%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;534&quot; height=&quot;252&quot; data-origin-width=&quot;534&quot; data-origin-height=&quot;252&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 그림에서 객체B와 C중 어느 객체가 인터페이스에 대입됐냐에 따라 객체 A의 메소드 호출 결과가 달라질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 코드예시를 보자.&lt;/p&gt;
&lt;pre id=&quot;code_1714635802151&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public interface Tire {
	void roll();
}

public class HankookTire implements Tire {
	// 메소드 재정의
    @Override
    public void roll() {
    	// 한국 타이어
    }
}

public class KumhoTire implements Tire {
	// 메소드 재정의
    @Override
    public void roll() {
    	// 금호 타이어
    }
}

public class Car {
	//필드
    Tire tire1 = new HankookTire();
    Tire tire2 = new HankookTire();
    
    //메소드
    void run() {
    	tire1.roll();
        tire2.roll();
    }
}

public class CarExample {
	public static void main(String[] args) {
    	// 객체 생성
    	Car myCar = new Car();
        
        // run()메소드 실행
        myCar.run();
        
        // 타이어 객체 교체
        myCar.tire1 = new KumhoTire();
        
        // 다형성으로 인해 결과 변경
        myCar.run();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>자바</category>
      <author>Ju_Nik_E</author>
      <guid isPermaLink="true">https://cod2048.tistory.com/37</guid>
      <comments>https://cod2048.tistory.com/37#entry37comment</comments>
      <pubDate>Thu, 2 May 2024 16:46:25 +0900</pubDate>
    </item>
    <item>
      <title>다중 인터페이스 구현</title>
      <link>https://cod2048.tistory.com/36</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;이전에 인터페이스에 대해 포스팅했는데, 구현 객체는 &lt;b&gt;여러 개의 인터페이스를 implements&lt;/b&gt;할 수 있다.&lt;br /&gt;사용법은 아래와 같다.&lt;/blockquote&gt;
&lt;pre id=&quot;code_1714632413984&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class 구현클래스 implements 인터페이스1, 인터페이스2 {

}&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;h3 data-ke-size=&quot;size23&quot;&gt;인터페이스 상속&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;자바의 클래스는 다중 상속을 허용하지 않으나, 인터페이스는 다중 상속이 허용된다.&lt;br /&gt;사용법은 아래와 같다.&lt;/blockquote&gt;
&lt;pre id=&quot;code_1714632860891&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface 자식인터페이스 extends 부모인터페이스1, 부모인터페이스2 {
	...
}&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;아래 예시를 보자&lt;/p&gt;
&lt;pre id=&quot;code_1714633138983&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface InterfaceA {
	void methodA();
}

public interface InterfaceB {
	void methodB();
}

public interface InterfaceC extends InterfaceA, InterfaceC {
	void methodC();
}

public class InterfaceCImple implements InterfaceC {
    // 추상 메소드 재정의
	public void methodA() {
    	
    }
    
    public void methodB() {
    	
    }
    
    public void methodC() {
    	
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1714633281833&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class ExtendsExample {
	public static void main(String[] args) {
    	InterfaceCImpl impl = new InterfaceCImpl();
        
        //부모 인터페이스 변수에 대입
        InterfaceA ia = impl;
        ia.methodA();
        // ia.methodB(); 사용불가
        // ia.methodC(); 사용불가
        
        InterfaceB ia = impl;
        // ib.methodA(); 사용불가
        ib.methodB();
        // ib.methodC(); 사용불가
        
        InterfaceC ic = impl;
        ic.methodA();
        ic.methodb();
        ic.methodc();
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>자바</category>
      <author>Ju_Nik_E</author>
      <guid isPermaLink="true">https://cod2048.tistory.com/36</guid>
      <comments>https://cod2048.tistory.com/36#entry36comment</comments>
      <pubDate>Thu, 2 May 2024 16:16:23 +0900</pubDate>
    </item>
    <item>
      <title>인터페이스</title>
      <link>https://cod2048.tistory.com/35</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;인터페이스란?&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;두 객체를 연결하는 역할을 하는 것으로, 인터페이스를 통해 객체가 다른 객체를 직접 사용하지 않음으로&amp;nbsp;&lt;b&gt;다형성 구현&lt;/b&gt;에 주된 기술로 이용된다.&lt;/blockquote&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;524&quot; data-origin-height=&quot;146&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WV6g4/btsG6ggkFJI/Pq7PWVvKLF1TkswCskdwtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WV6g4/btsG6ggkFJI/Pq7PWVvKLF1TkswCskdwtk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WV6g4/btsG6ggkFJI/Pq7PWVvKLF1TkswCskdwtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWV6g4%2FbtsG6ggkFJI%2FPq7PWVvKLF1TkswCskdwtk%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;524&quot; height=&quot;146&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;146&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 아래와 같이 객체 B가 객체 C로 변경된다 하더라도, 객체 A는 인터페이스의 메소드만 사용하기 때문에 아무 상관이 없다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;552&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhOdOz/btsG8oYNTYJ/MCKwnfhAwmWQzww0qkZb01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhOdOz/btsG8oYNTYJ/MCKwnfhAwmWQzww0qkZb01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhOdOz/btsG8oYNTYJ/MCKwnfhAwmWQzww0qkZb01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhOdOz%2FbtsG8oYNTYJ%2FMCKwnfhAwmWQzww0qkZb01%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;552&quot; height=&quot;232&quot; data-origin-width=&quot;552&quot; data-origin-height=&quot;232&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;인터페이스 선언&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;인터페이스는 class 키워드 대신 interface 키워드를 사용한다.(파일 자체는 클래스와 동일하게 .java의 형태)&lt;/blockquote&gt;
&lt;pre id=&quot;code_1714628349918&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface 인터페이스명 {...} // default 접근 제한

// public 접근 제한
public interface 인터페이스명 {
	// public 상수 필드
    // public 추상 메소드(선언부만 있고, 실행부인 중괄호가 없는 메소드)
    // public 디폴트 메소드
    // public 정적 메소드
    // private 메소드
    // private 정적 메소드
}&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;메인(사람)이 인터페이스(리모컨)을 이용해 객체(티비)를 조작하는 예시이다.&lt;/p&gt;
&lt;pre id=&quot;code_1714628560430&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 인터페이스
public interface RemoteControl {
	// 추상 메소드
    public void turnOn();
}

// 객체1
public class Television implements RemoteControl {
	@Override
    public void turnOn() {
    	System.out.println(&quot;tv를 킨다.)
    }
}

// 객체2
public class Audio implements RemoteControl {
	@Override
    public void turnOn() {
    	System.out.println(&quot;오디오를 킨다.)
    }
}

// 메인
public class RemoteControlExample {
	public static void main(String[] args) {
    	RemoteControl rc;
        
        // rc변수에 Television 객체 대입
        rc = new Television();
        rc.turnOn();
        
        // rc변수에 Audio 객체 교체
        rc = new Audio();
        rc.turnOn();
    }
}&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;위의 예시처럼 인터페이스는 추상메소드를 가지고 있고, Television 클래스와 Audio 클래스는 인터페이스를 상속받아서, 인터페이스의 메소드와 같은 이름의 메소드를 Override해서 사용할 수 있다.&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;이렇게 되면 메인 클래스(사람)은 RemoteControl 인터페이스를 통해 Television과 Audio를 자유롭게 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주의사항&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 인터페이스를 상속받은 클래스는 반드시 해당 인터페이스에 정의된 모든 추상 메소드를 재정의해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;인터페이스의 필드&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;인터페이스는 public static final특성을 갖는 &lt;b&gt;불변의 상수 필드만을&lt;/b&gt;&amp;nbsp;멤버로 가질 수 있다.&lt;br /&gt;&lt;b&gt;public static final 타입 변수명 = 값;&lt;br /&gt;&lt;/b&gt;public static final 키워들르 생략해도 컴파일 과정에서 자동으로 붙는다. 아래와 같이 선언할 수 있다.&lt;/blockquote&gt;
&lt;pre id=&quot;code_1714629183647&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface RemoteControl {
	int MAX_VOLUME = 10;
    public static final int MIN_VOLUME= 0;
    
    // 둘다 같은 접근 제한을 갖게 됨
}&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;pre id=&quot;code_1714629983754&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class RemoteControlExample {
	public static void main(String[] args) {
    	System.out.println(&quot;리모콘 최대 볼륨: &quot; + RemoteControl.MAX_VOLUME);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;디폴트 메소드&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;인터페이스에는 추상메소드 외에도 완전한 실행 코드를 갖는 디폴트 메소드를 선언할 수 있다.&lt;br /&gt;바로 아래의 예시를 보자&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1714630275502&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface RemoteControl {
	// 추상 메소드
    void setVolume(int volume);
	
	// 디폴트 인스턴스 메소드
    default void setMute(boolean mute) {
    	if(mute) {
      		System.out.println(&quot;무음 설정&quot;);
        	setVolume(MIN_VOLUME);
        } else {
        	System.out.println(&quot;무음 해제&quot;);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정적 메소드&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;구현 객체없이 인터페이스에 직접 접근해 사용할 수 있는 정적 메소드도 선언가능하다.&lt;br /&gt;아래의 예시를 보자&lt;/blockquote&gt;
&lt;pre id=&quot;code_1714630398189&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface RemoteControl {
	// 정적 메소드
    static void changeBattery() {
    	System.out.println(&quot;건전지 교체&quot;)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주의사항&lt;/b&gt; : 정적메소드는 실행부에 상수필드를 제외한 추상 메소드, 디폴트 메소드, private 메소드 등을 호출할 수 없다.(이 메소드들은 구현 객체가 필요한 인스턴스 메소드이기 때문)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;private 메소드&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;인터페이스의 상수 필드, 추상 메소드, 디폴트 메소드, 정적 메소드는 모두 public의 접근 제한을 갖는다.&lt;br /&gt;선언할 때 public 키워드를 생략해도 컴파일 과정에서 public 접근 제한자가 자동으로 붙는데,&lt;br /&gt;private 키워드를 명시해줌으로써 private 접근제한을 갖는 메소드를 선언할 수 있다.(외부에서 접근 불가능)&lt;/blockquote&gt;</description>
      <category>자바</category>
      <author>Ju_Nik_E</author>
      <guid isPermaLink="true">https://cod2048.tistory.com/35</guid>
      <comments>https://cod2048.tistory.com/35#entry35comment</comments>
      <pubDate>Thu, 2 May 2024 15:18:31 +0900</pubDate>
    </item>
  </channel>
</rss>