<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>가원이의 코딩 일대기</title>
    <link>https://gawonstory.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sun, 5 Apr 2026 03:00:26 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>가원스 토리</managingEditor>
    <item>
      <title>Selenium으로 리로스쿨 수강신청 자동화 매크로 만들기 (Java + SpringBoot)</title>
      <link>https://gawonstory.tistory.com/19</link>
      <description>&lt;p data-end=&quot;257&quot; data-start=&quot;182&quot; data-ke-size=&quot;size16&quot;&gt;이번 글에서는 &lt;b&gt;Java + Selenium을 사용해 리로스쿨 수강신청을 자동화하는 매크로&lt;/b&gt;를 만들어본 과정을 정리하려고 한다.&lt;/p&gt;
&lt;p data-end=&quot;335&quot; data-start=&quot;259&quot; data-ke-size=&quot;size16&quot;&gt;수강신청은 보통 &lt;b&gt;정해진 시간에 빠르게 신청해야 하기 때문에&lt;/b&gt;&lt;br /&gt;자동화 프로그램을 만들어 버튼 클릭을 자동으로 처리하도록 구현했다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;337&quot; data-ke-size=&quot;size16&quot;&gt;사용한 기술 스택은 다음과 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;406&quot; data-start=&quot;357&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;366&quot; data-start=&quot;357&quot; data-section-id=&quot;2kc2oi&quot;&gt;Java 17&lt;/li&gt;
&lt;li data-end=&quot;380&quot; data-start=&quot;367&quot; data-section-id=&quot;rvusbz&quot;&gt;Spring Boot&lt;/li&gt;
&lt;li data-end=&quot;391&quot; data-start=&quot;381&quot; data-section-id=&quot;e9kbt4&quot;&gt;Selenium&lt;/li&gt;
&lt;li data-end=&quot;406&quot; data-start=&quot;392&quot; data-section-id=&quot;2o9ko8&quot;&gt;ChromeDriver&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;툴은 intellij를 사용함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 data-end=&quot;424&quot; data-start=&quot;413&quot; data-section-id=&quot;1u0lbja&quot;&gt;프로젝트 생성&lt;/h1&gt;
&lt;p data-end=&quot;452&quot; data-start=&quot;426&quot; data-ke-size=&quot;size16&quot;&gt;먼저 Spring Boot 프로젝트를 생성했다.&lt;/p&gt;
&lt;p data-end=&quot;489&quot; data-start=&quot;454&quot; data-ke-size=&quot;size16&quot;&gt;Spring Initializr를 이용해 다음과 같이 설정했다.&lt;/p&gt;
&lt;p data-end=&quot;489&quot; data-start=&quot;454&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;489&quot; data-start=&quot;454&quot; data-ke-size=&quot;size16&quot;&gt;- Project 설정&lt;/p&gt;
&lt;pre id=&quot;code_1772954093639&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Project : Gradle
Language : Java
Spring Boot : 3.x
Group : selfproject
Artifact : mechro
Java : 17&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;- dependency&lt;/p&gt;
&lt;pre id=&quot;code_1772954138772&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Spring Web
Lombok (optional)&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 Selenium 의존성 추가&lt;/p&gt;
&lt;pre id=&quot;code_1772954170154&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dependencies {
    implementation 'org.seleniumhq.selenium:selenium-java:4.37.0'
}&lt;/code&gt;&lt;/pre&gt;
&lt;h1 data-end=&quot;856&quot; data-start=&quot;837&quot; data-section-id=&quot;1kucdic&quot;&gt;ChromeDriver 설정&lt;/h1&gt;
&lt;p data-end=&quot;908&quot; data-start=&quot;858&quot; data-ke-size=&quot;size16&quot;&gt;Selenium은 &lt;b&gt;브라우저를 직접 제어하기 위해 ChromeDriver가 필요하다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;938&quot; data-start=&quot;910&quot; data-ke-size=&quot;size16&quot;&gt;Chrome 버전에 맞는 드라이버를 설치해야 한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;chrome://settings/help&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;996&quot; data-start=&quot;979&quot; data-ke-size=&quot;size16&quot;&gt;ChromeDriver 다운로드&lt;/p&gt;
&lt;p data-end=&quot;1041&quot; data-start=&quot;998&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://chromedriver.chromium.org/downloads&quot;&gt;https://chromedriver.chromium.org/downloads&lt;/a&gt;&lt;/p&gt;
&lt;p data-end=&quot;1072&quot; data-start=&quot;1043&quot; data-ke-size=&quot;size16&quot;&gt;다운로드 후 프로젝트에서 사용할 수 있도록 설정한다.&lt;/p&gt;
&lt;p data-end=&quot;1072&quot; data-start=&quot;1043&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1072&quot; data-start=&quot;1043&quot; data-ke-size=&quot;size16&quot;&gt;- chrome 드라이버 여는 코드 작성 (쿠키, 캐쉬 컴퓨터 브라우저에 저장)&lt;/p&gt;
&lt;pre id=&quot;code_1772954234353&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;System.setProperty(&quot;webdriver.chrome.driver&quot;, &quot;/경로/chromedriver&quot;);

ChromeOptions options = new ChromeOptions();
options.addArguments(&quot;--remote-allow-origins=*&quot;);

WebDriver driver = new ChromeDriver(options);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;1072&quot; data-start=&quot;1043&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 data-end=&quot;1604&quot; data-start=&quot;1593&quot; data-section-id=&quot;mo0h69&quot;&gt;로그인 자동화&lt;/h1&gt;
&lt;p data-end=&quot;1628&quot; data-start=&quot;1606&quot; data-ke-size=&quot;size16&quot;&gt;먼저 리로스쿨 로그인 페이지에 접속한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;pre id=&quot;code_1772954272486&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;driver.get(&quot;https://relo-school-url&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1694&quot; data-start=&quot;1682&quot; data-ke-size=&quot;size16&quot;&gt;아이디와 비밀번호 입력&lt;/p&gt;
&lt;pre id=&quot;code_1772954298153&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;driver.findElement(By.name(&quot;id&quot;)).sendKeys(&quot;아이디&quot;);
driver.findElement(By.name(&quot;pw&quot;)).sendKeys(&quot;비밀번호&quot;);
driver.findElement(By.id(&quot;login_btn&quot;)).click();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 data-end=&quot;1881&quot; data-start=&quot;1865&quot; data-section-id=&quot;tw63dd&quot;&gt;특정 시간까지 대기하기&lt;/h1&gt;
&lt;pre id=&quot;code_1772954318254&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;LocalTime targetTime = LocalTime.of(20, 30);

while(LocalTime.now().isBefore(targetTime)){
    Thread.sleep(500);
}

System.out.println(&quot;시간 도달&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;h1 data-end=&quot;2130&quot; data-start=&quot;2118&quot; data-section-id=&quot;y4x566&quot;&gt;페이지 새로고침&lt;/h1&gt;
&lt;p data-end=&quot;2159&quot; data-start=&quot;2132&quot; data-ke-size=&quot;size16&quot;&gt;수강신청 버튼이 활성화되기 전에 새로고침을 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1772954337269&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;for(int i=0;i&amp;lt;3;i++){
    driver.navigate().refresh();
    Thread.sleep(1000);
}&lt;/code&gt;&lt;/pre&gt;
&lt;h1 data-end=&quot;2273&quot; data-start=&quot;2260&quot; data-section-id=&quot;1m2awvv&quot;&gt;메뉴 클릭 자동화&lt;/h1&gt;
&lt;p data-end=&quot;2321&quot; data-start=&quot;2275&quot; data-ke-size=&quot;size16&quot;&gt;리로스쿨 메뉴는 일반적인 링크가 아니라 &lt;b&gt;JavaScript 함수로 동작한다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1772954378320&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;((JavascriptExecutor) driver).executeScript(
&quot;menuAction('/lecture.php?db=1701&amp;amp;cate=32&amp;amp;action=certificate', 'new');&quot;
);&lt;/code&gt;&lt;/pre&gt;
&lt;h1 data-end=&quot;2833&quot; data-start=&quot;2823&quot; data-section-id=&quot;18o5o9z&quot;&gt;버튼 클릭&lt;/h1&gt;
&lt;p data-end=&quot;2845&quot; data-start=&quot;2835&quot; data-ke-size=&quot;size16&quot;&gt;수강신청 버튼 클릭&lt;/p&gt;
&lt;pre id=&quot;code_1772954411351&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;WebElement btn = driver.findElement(By.xpath(&quot;//span[contains(text(),'배드민턴')]&quot;));

((JavascriptExecutor) driver).executeScript(
&quot;arguments[0].click();&quot;, btn
);&lt;/code&gt;&lt;/pre&gt;
&lt;h1 data-end=&quot;3046&quot; data-start=&quot;3025&quot; data-section-id=&quot;zby3dx&quot;&gt;WebDriverWait 사용&lt;/h1&gt;
&lt;p data-end=&quot;3112&quot; data-start=&quot;3048&quot; data-ke-size=&quot;size16&quot;&gt;페이지 로딩 문제를 방지하기 위해&lt;br /&gt;&lt;b&gt;Selenium의 명시적 대기(Explicit Wait)&lt;/b&gt; 를 사용한다.&lt;/p&gt;
&lt;pre id=&quot;code_1772954437870&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;-- new_memo라는 요소가 페이지상에 찾아질때까지 지정한 시간만큼 대기한다. (중요 : 페이지로딩 후 동작)
wait.until(ExpectedConditions.visibilityOfElementLocated(By.name(&quot;new_memo&quot;)));&lt;/code&gt;&lt;/pre&gt;
&lt;h1 data-end=&quot;3335&quot; data-start=&quot;3325&quot; data-section-id=&quot;yjubnc&quot;&gt;메모 입력&lt;/h1&gt;
&lt;p data-end=&quot;3349&quot; data-start=&quot;3337&quot; data-ke-size=&quot;size16&quot;&gt;수강신청 시 메모 입력 (필수입력때 사용할것 ! 아닐시에는 해당 요소가 시간 지체 가능)&lt;/p&gt;
&lt;pre id=&quot;code_1772954510651&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;driver.findElement(By.name(&quot;new_memo&quot;)).sendKeys(&quot;수강신청&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;h1 data-end=&quot;3440&quot; data-start=&quot;3427&quot; data-section-id=&quot;junt15&quot;&gt;alert 처리 (많은 웹페이지에서 필수로 처리해줘야함. )&lt;/h1&gt;
&lt;p data-end=&quot;3464&quot; data-start=&quot;3442&quot; data-ke-size=&quot;size16&quot;&gt;수강신청 과정에서 alert 창이 뜬다.&lt;/p&gt;
&lt;p data-end=&quot;3479&quot; data-start=&quot;3466&quot; data-ke-size=&quot;size16&quot;&gt;이를 자동으로 처리한다.&lt;/p&gt;
&lt;pre id=&quot;code_1772954540850&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static void acceptAlert(WebDriver driver){
    try{
        Alert alert = driver.switchTo().alert();
        alert.accept();
    }catch(Exception e){
    }
}
// 사용
acceptAlert(driver);
acceptAlert(driver);&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;- 실제 매크로 프로그램에서 사용함 유용한 함수 및 코드&lt;/p&gt;
&lt;pre id=&quot;code_1772954572767&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// ================================
// Selenium 요소 찾기 및 자동화 기본 예제
// ================================

// Selenium 기본 객체 import
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;

import java.time.Duration;

public class SeleniumExample {

    public static void main(String[] args) {

        // ================================
        // 1. WebDriver 실행 (Chrome 브라우저 실행)
        // ================================
        WebDriver driver = new ChromeDriver();

        // 테스트 사이트 접속
        driver.get(&quot;https://example.com&quot;);


        // ================================
        // 2. id 로 요소 찾기
        // ================================
        // HTML 예시
        // &amp;lt;button id=&quot;login_btn&quot;&amp;gt;로그인&amp;lt;/button&amp;gt;

        WebElement loginBtn = driver.findElement(By.id(&quot;login_btn&quot;));
        loginBtn.click();  // 버튼 클릭


        // ================================
        // 3. name 으로 요소 찾기 (텍스트 입력)
        // ================================
        // HTML 예시
        // &amp;lt;input type=&quot;text&quot; name=&quot;user_id&quot;&amp;gt;

        WebElement idInput = driver.findElement(By.name(&quot;user_id&quot;));
        idInput.sendKeys(&quot;myID&quot;);   // 텍스트 입력

        WebElement pwInput = driver.findElement(By.name(&quot;password&quot;));
        pwInput.sendKeys(&quot;1234&quot;);   // 비밀번호 입력


        // ================================
        // 4. class 로 요소 찾기
        // ================================
        // HTML 예시
        // &amp;lt;button class=&quot;submit-btn&quot;&amp;gt;제출&amp;lt;/button&amp;gt;

        WebElement submitBtn = driver.findElement(By.className(&quot;submit-btn&quot;));
        submitBtn.click();


        // ================================
        // 5. XPath 로 요소 찾기
        // ================================
        // HTML 예시
        // &amp;lt;span&amp;gt;수강내역 조회&amp;lt;/span&amp;gt;

        WebElement lectureBtn =
                driver.findElement(By.xpath(&quot;//span[contains(text(),'수강내역 조회')]&quot;));

        lectureBtn.click();


        // ================================
        // 6. CSS Selector 로 요소 찾기
        // ================================
        // HTML 예시
        // &amp;lt;input id=&quot;user_id&quot;&amp;gt;

        WebElement cssInput =
                driver.findElement(By.cssSelector(&quot;#user_id&quot;));

        cssInput.sendKeys(&quot;testUser&quot;);


        // ================================
        // 7. WebDriverWait (요소가 나타날 때까지 기다리기)
        // ================================

        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));

        // 요소가 클릭 가능할 때까지 최대 5초 대기
        WebElement waitBtn = wait.until(
                ExpectedConditions.elementToBeClickable(By.id(&quot;apply_btn&quot;))
        );

        waitBtn.click();


        // ================================
        // 8. JavaScript 로 강제 클릭
        // ================================
        // 일부 사이트는 Selenium click() 이 동작하지 않을 때가 있다.
        // 이때 JavascriptExecutor를 사용한다.

        WebElement jsBtn = driver.findElement(By.id(&quot;apply_btn&quot;));

        ((JavascriptExecutor) driver).executeScript(
                &quot;arguments[0].click();&quot;,
                jsBtn
        );


        // ================================
        // 9. 텍스트 입력 예시
        // ================================
        // HTML
        // &amp;lt;input name=&quot;memo&quot;&amp;gt;

        WebElement memoInput = driver.findElement(By.name(&quot;memo&quot;));
        memoInput.sendKeys(&quot;수강신청&quot;);


        // ================================
        // 10. 브라우저 종료
        // ================================
        driver.quit();
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>개인 공부/백</category>
      <author>가원스 토리</author>
      <guid isPermaLink="true">https://gawonstory.tistory.com/19</guid>
      <comments>https://gawonstory.tistory.com/19#entry19comment</comments>
      <pubDate>Sun, 8 Mar 2026 16:27:37 +0900</pubDate>
    </item>
    <item>
      <title>[flutter] Failed to bind web development server:SocketException: Failed to create server socket (OS Error: Failed to start accept), address = localhost, port = '포트번호'</title>
      <link>https://gawonstory.tistory.com/18</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;vs코드에서 실행시에 해당 오류 고치기&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;pre id=&quot;code_1754293054522&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;flutter run -d chrome --web-hostname=127.0.0.1&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;나는 vs코드에서 툴을 이용해 F5로만 열고싶다!&amp;nbsp; 그럼 해당 프로젝트 폴더 안의 .VSCODE의 launch.json에&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1754293006359&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; &quot;configurations&quot;: [
        {
            &quot;name&quot;: &quot;flutter_stagram&quot;,
            &quot;request&quot;: &quot;launch&quot;,
            &quot;type&quot;: &quot;dart&quot;,
            &quot;args&quot;: [
            &quot;--web-hostname&quot;,
            &quot;127.0.0.1&quot;
        ]
        },&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 입력 후 실행&lt;/p&gt;</description>
      <category>error</category>
      <category>error</category>
      <category>Flutter</category>
      <category>port</category>
      <category>SOCKET</category>
      <category>vscode</category>
      <author>가원스 토리</author>
      <guid isPermaLink="true">https://gawonstory.tistory.com/18</guid>
      <comments>https://gawonstory.tistory.com/18#entry18comment</comments>
      <pubDate>Mon, 4 Aug 2025 16:40:14 +0900</pubDate>
    </item>
    <item>
      <title>rest-api 만들기 기본설정</title>
      <link>https://gawonstory.tistory.com/17</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1.&amp;nbsp; 종속성 추가(Gradle)&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;plugins { &lt;br /&gt;&amp;nbsp; &amp;nbsp; // Java 애플리케이션을 위한 기본 플러그인 &lt;br /&gt;&amp;nbsp; &amp;nbsp; id 'application' &lt;br /&gt;&amp;nbsp; &amp;nbsp; // Spring Boot 플러그인 추가 &lt;br /&gt;&amp;nbsp; &amp;nbsp; id 'org.springframework.boot' version '2.7.4' &lt;br /&gt;&amp;nbsp; &amp;nbsp; // Spring Boot 의존성 관리 플러그인 (권장) &lt;br /&gt;&amp;nbsp; &amp;nbsp; id 'io.spring.dependency-management' version '1.0.11.RELEASE' &lt;br /&gt;}&lt;br /&gt;dependencies{&lt;br /&gt;&amp;nbsp; &amp;nbsp; implementation 'org.springframework.boot:spring-boot-starter-web'&lt;br /&gt;}&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. main 함수가 있는 실행 파일에 @SpringBootApplication 어노테이션 (class위에 )&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. 2번과 함께 @RestController 어노테이션 추가&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4. ./main/에 resources폴더 생성 후 application.properties or application.yml파일 생성 후 포트 넣어주기 &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;(기본포트 : 8080 바꾸고싶을때만 하기)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;예시&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1727853077597&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//.yml
server:
  port: 5678
  address: 0.0.0.0
//.properties
server.port:5678&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;5. main 함수 생성 후 SpringApplication.run(...)&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727853111083&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static void main(String[] args) {
        // Spring Boot 애플리케이션을 실행
        SpringApplication.run({클래스 명}.class, args);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SpringApplication.run(App.class, args);는 Spring Boot 애플리케이션을 시작하는 메인 메서드&lt;/li&gt;
&lt;li&gt;SpringApplication 클래스는 Spring Boot의 핵심 클래스 중 하나로, 애플리케이션의 시작, 구성, 종료 등을 처리&lt;/li&gt;
&lt;li&gt;{클래스명}.class는 애플리케이션의 메인 클래스로, 이 클래스에 있는 @SpringBootApplication 어노테이션을 기반으로 Spring이 애플리케이션 설정을 자동으로 구성&lt;/li&gt;
&lt;li&gt;args는 커맨드 라인 인수입니다. 프로그램을 실행할 때 전달된 인자들이 args 배열에 저장되며, Spring Boot 애플리케이션 실행 중에 이 값들을 사용할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개인 공부/백</category>
      <author>가원스 토리</author>
      <guid isPermaLink="true">https://gawonstory.tistory.com/17</guid>
      <comments>https://gawonstory.tistory.com/17#entry17comment</comments>
      <pubDate>Wed, 2 Oct 2024 16:16:38 +0900</pubDate>
    </item>
    <item>
      <title>유용한 Integer함수들</title>
      <link>https://gawonstory.tistory.com/16</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. &lt;b&gt;Integer.parseInt(String s)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 문자열을 정수로 변환합니다. 기본적인 문자열을 정수로 변환할 때 사용됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845508946&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int num = Integer.parseInt(&quot;123&quot;);
System.out.println(num); // 출력: 123&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. &lt;b&gt;Integer.valueOf(String s)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 문자열을 Integer 객체로 변환합니다. Integer.parseInt()와 달리 객체로 반환됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845525446&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Integer num = Integer.valueOf(&quot;123&quot;);
System.out.println(num); // 출력: 123&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. &lt;b&gt;Integer.toString(int i)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 정수를 문자열로 변환합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845542456&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = Integer.toString(123);
System.out.println(str); // 출력: &quot;123&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. &lt;b&gt;Integer.compare(int x, int y)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 두 정수를 비교합니다. x가 y보다 작으면 음수, 같으면 0, 크면 양수를 반환합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845566064&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int result = Integer.compare(10, 20);
System.out.println(result); // 출력: -1 (10이 20보다 작음)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. &lt;b&gt;Integer.max(int a, int b)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 두 정수 중 큰 값을 반환합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845579720&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int max = Integer.max(10, 20);
System.out.println(max); // 출력: 20&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. &lt;b&gt;Integer.min(int a, int b)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 두 정수 중 작은 값을 반환합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845594186&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int min = Integer.min(10, 20);
System.out.println(min); // 출력: 10&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;7. &lt;b&gt;Integer.bitCount(int i)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 이진수로 변환했을 때 1로 설정된 비트의 개수를 반환합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845608576&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int count = Integer.bitCount(5); // 5의 이진수 표현은 101이므로 1이 두 개 있음. 
System.out.println(count); // 출력: 2&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;8. &lt;b&gt;Integer.reverse(int i)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 주어진 정수의 비트를 역순으로 정렬합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845624800&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int reversed = Integer.reverse(13); // 13의 이진수는 1101, 역순으로 하면 1011이 됨 
System.out.println(reversed); // 출력: 2952790016&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;9. &lt;b&gt;Integer.signum(int i)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 주어진 정수의 부호를 반환합니다. 음수이면 -1, 0이면 0, 양수이면 1을 반환합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845639265&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int sign = Integer.signum(-100); 
System.out.println(sign); // 출력: -1&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;10. &lt;b&gt;Integer.highestOneBit(int i)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 가장 높은 비트에 위치한 1을 유지하고, 나머지 비트를 0으로 만듭니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845652204&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int highBit = Integer.highestOneBit(10); // 10의 이진수는 1010, 가장 높은 비트는 1000 
System.out.println(highBit); // 출력: 8&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;11. &lt;b&gt;Integer.lowestOneBit(int i)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 가장 낮은 비트에 위치한 1을 유지하고, 나머지 비트를 0으로 만듭니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845665491&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int lowBit = Integer.lowestOneBit(10); // 10의 이진수는 1010, 가장 낮은 비트는 0010 
System.out.println(lowBit); // 출력: 2&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;12. &lt;b&gt;Integer.toBinaryString(int i)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 정수를 이진수 문자열로 변환합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845678360&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String binary = Integer.toBinaryString(10); 
System.out.println(binary); // 출력: &quot;1010&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;13. &lt;b&gt;Integer.toHexString(int i)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 정수를 16진수 문자열로 변환합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845689626&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String hex = Integer.toHexString(255);
System.out.println(hex); // 출력: &quot;ff&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;14. &lt;b&gt;Integer.toOctalString(int i)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 정수를 8진수 문자열로 변환합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845699999&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String octal = Integer.toOctalString(10); 
System.out.println(octal); // 출력: &quot;12&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;15. &lt;b&gt;Integer.sum(int a, int b)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 두 정수의 합을 반환합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845713321&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int sum = Integer.sum(10, 20); 
System.out.println(sum); // 출력: 30&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;16. &lt;b&gt;Integer.hashCode(int value)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 정수 값에 대한 해시 코드를 반환합니다. int 값을 해시화할 때 유용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845729696&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int hash = Integer.hashCode(1234); 
System.out.println(hash); // 출력: 1234&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;17. &lt;b&gt;Integer.numberOfLeadingZeros(int i)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 정수를 이진수로 표현했을 때 앞쪽에 있는 0의 개수를 반환합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845746275&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int leadingZeros = Integer.numberOfLeadingZeros(16); // 16은 이진수로 10000, 앞에 27개의 0이 있음 
System.out.println(leadingZeros); // 출력: 27&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;18. &lt;b&gt;Integer.numberOfTrailingZeros(int i)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 정수를 이진수로 표현했을 때 뒤쪽에 있는 0의 개수를 반환합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845758109&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int trailingZeros = Integer.numberOfTrailingZeros(16); // 16은 이진수로 10000, 뒤에 4개의 0이 있음 
System.out.println(trailingZeros); // 출력: 4&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;19. &lt;b&gt;Integer.rotateLeft(int i, int distance)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 주어진 정수를 distance만큼 왼쪽으로 회전(순환)합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845771027&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int rotated = Integer.rotateLeft(15, 2); 
System.out.println(rotated); // 출력: 60&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;20. &lt;b&gt;Integer.rotateRight(int i, int distance)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설명&lt;/b&gt;: 주어진 정수를 distance만큼 오른쪽으로 회전(순환)합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727845781890&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int rotated = Integer.rotateRight(15, 2); 
System.out.println(rotated); // 출력: -1073741821&lt;/code&gt;&lt;/pre&gt;</description>
      <category>개인 공부/백</category>
      <author>가원스 토리</author>
      <guid isPermaLink="true">https://gawonstory.tistory.com/16</guid>
      <comments>https://gawonstory.tistory.com/16#entry16comment</comments>
      <pubDate>Wed, 2 Oct 2024 14:11:22 +0900</pubDate>
    </item>
    <item>
      <title>Jackson라이브러리 활용하여 json 형태의 파일 읽고 데이터 변환 후 새 파일로 저장</title>
      <link>https://gawonstory.tistory.com/15</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;u&gt;&lt;b&gt;Jackson 을 활용하여 json형태의 파일 읽고 저장하기&lt;/b&gt;&lt;/u&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;- Jackson 라이브러리 추가&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;dependencies {&lt;br /&gt;implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.3' &lt;br /&gt;}&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;u&gt;&lt;b&gt;json형태의 파일 읽는법&amp;nbsp;&lt;/b&gt;&lt;/u&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&amp;nbsp;파일의 경로부터 파일 명까지 변수에 저장&lt;/li&gt;
&lt;li&gt;&amp;nbsp;ObjectMapper를 선언 :&lt;/li&gt;
&lt;li&gt;&amp;nbsp;해당 파일의 데이터를 담을 변수 선언 밑에 코드에는 List&amp;lt;Map&amp;lt;String,Object&amp;gt;&amp;gt; customer;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;customer=objectMapper.readValue(new File(파일 경로),List.class);&lt;/li&gt;
&lt;li&gt;&amp;nbsp;exeption처리&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1727843904701&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

    // json type의 파일 읽기
    public static List&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt; getFile() {
        String jsonFilePath = &quot;{json 형식의 파일 경로와 파일 이름}&quot;;
        //파일의 데이터를 담을 구조 선언
        ObjectMapper objectMapper = new ObjectMapper();
        List&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt; customers=new ArrayList&amp;lt;&amp;gt;();
        try {
             customers = objectMapper.readValue(new File(jsonFilePath), List.class);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return customers;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;u&gt;&lt;b&gt;json형태의 파일 저장&amp;nbsp;&lt;/b&gt;&lt;/u&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;ObjectMapper 객체 생성&lt;/li&gt;
&lt;li&gt;파일 안의 데이터를 원하는 형태에 맞춰 변환 후 Map&amp;lt;&amp;gt;에 저장&lt;/li&gt;
&lt;li&gt;ObjectMapper의 writeValue 사용 mapper.writeValue(new File(&quot;{파일의 경로와 파일명}&quot;,넣을 데이터);&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1727845057953&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
import java.util.Map;

    // JSON 파일로 저장하는 메서드
    public static void saveTotalCustomers(int total) throws IOException {
        // ObjectMapper 객체 생성
        ObjectMapper mapper = new ObjectMapper();

        // 결과를 Map 형식으로 저장
        Map&amp;lt;String, Integer&amp;gt; result = Map.of(&quot;total&quot;, total);

        // JSON 파일로 저장
        mapper.writeValue(new File(&quot;file경로/fileName.확장자&quot;), result);
    }&lt;/code&gt;&lt;/pre&gt;</description>
      <category>개인 공부/백</category>
      <author>가원스 토리</author>
      <guid isPermaLink="true">https://gawonstory.tistory.com/15</guid>
      <comments>https://gawonstory.tistory.com/15#entry15comment</comments>
      <pubDate>Wed, 2 Oct 2024 14:02:48 +0900</pubDate>
    </item>
    <item>
      <title>size,size(),length,length()</title>
      <link>https://gawonstory.tistory.com/14</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. &lt;b&gt;size()&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;어디에서 사용?&lt;/b&gt;: List, Set, Map 같은 &lt;b&gt;컬렉션 클래스&lt;/b&gt;에서 사용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;리턴값&lt;/b&gt;: 컬렉션에 포함된 &lt;b&gt;요소의 개수&lt;/b&gt;를 반환
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;기억법&lt;/b&gt;: size()는 &lt;b&gt;컬렉션&lt;/b&gt;에서 그 안에 들어 있는 &lt;b&gt;요소의 개수&lt;/b&gt;를 반환하는 메서드입니다. 괄호 ()가 붙는 이유는 메서드이기 때문&lt;/li&gt;
&lt;li&gt;예시&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727692257179&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;String&amp;gt; list = new ArrayList&amp;lt;&amp;gt;();
list.add(&quot;Hello&quot;); list.add(&quot;World&quot;);
int size = list.size(); // size는 2&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;h3 data-ke-size=&quot;size23&quot;&gt;2. &lt;b&gt;length()&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;어디에서 사용?&lt;/b&gt;: **문자열 (String)**이나 **배열 (Array)**에서 사용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;리턴값&lt;/b&gt;: 문자열의 &lt;b&gt;문자 개수&lt;/b&gt; 또는 배열의 &lt;b&gt;길이&lt;/b&gt;를 반환&lt;/li&gt;
&lt;li&gt;&lt;b&gt;기억법&lt;/b&gt;: length()는 &lt;b&gt;문자열의 문자 수&lt;/b&gt;를 반환할 때 사용되며, 배열에서는 &lt;b&gt;속성&lt;/b&gt;으로 사용됩니다(괄호 없음). 문자열에서는 메서드이므로 괄호 ()가 붙고, 배열에서는 속성이므로 괄호가 붙지 않음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시 &lt;/b&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727692373174&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//배열
int[] arr = {1, 2, 3, 4, 5}; 
int length = arr.length; // length는 5
// 문자열
String str = &quot;Hello&quot;;
int length = str.length(); // length는 5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. &lt;b&gt;size&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;어디에서 사용?&lt;/b&gt;: 배열 (Array)의 크기를 표현할 때 가끔 사용되지만, 보통 잘못된 사용법으로 간주. Java에서는 배열의 크기를 표현할 때 **length**를 사용해야 . size는 단순히 배열 크기를 설명할 때 비공식적으로 사용될 수 있지만, 실제로 메서드나 속성으로 존재하지 않음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;기억법&lt;/b&gt;: size는 &lt;b&gt;Java에서 공식적인 속성이나 메서드가 아님&lt;/b&gt;으로, 주로 &lt;b&gt;컬렉션 클래스&lt;/b&gt;에서 size() 메서드를 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. &lt;b&gt;length&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;어디에서 사용?&lt;/b&gt;: **배열 (Array)**의 크기를 구할 때 사용되는 &lt;b&gt;속성&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;리턴값&lt;/b&gt;: 배열의 크기를 반환&lt;/li&gt;
&lt;li&gt;&lt;b&gt;기억법&lt;/b&gt;: length는 &lt;b&gt;배열의 속성&lt;/b&gt;으로, 괄호 () 없이 사용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727692491046&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int[] arr = {1, 2, 3, 4, 5};
int length = arr.length; // length는 5&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;차이점 요약&lt;/b&gt;&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;size()&lt;/td&gt;
&lt;td&gt;컬렉션 (List, Set, Map)&lt;/td&gt;
&lt;td&gt;() O&lt;/td&gt;
&lt;td&gt;컬렉션에 들어 있는 &lt;b&gt;요소의 개수&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;length()&lt;/td&gt;
&lt;td&gt;문자열 (String)&lt;/td&gt;
&lt;td&gt;() O&lt;/td&gt;
&lt;td&gt;문자열의 &lt;b&gt;문자 개수&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;length&lt;/td&gt;
&lt;td&gt;배열 (Array)&lt;/td&gt;
&lt;td&gt;() X&lt;/td&gt;
&lt;td&gt;배열의 &lt;b&gt;길이&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;size&lt;/td&gt;
&lt;td&gt;잘못된 사용&lt;/td&gt;
&lt;td&gt;() X&lt;/td&gt;
&lt;td&gt;사용하지 않음 (컬렉션의 size()와 혼동)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정리&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;size()는 &lt;b&gt;컬렉션&lt;/b&gt;의 요소 개수를 반환하는 메서드&lt;/li&gt;
&lt;li&gt;length()는 &lt;b&gt;문자열&lt;/b&gt;에서 사용되며, 문자열의 문자 개수를 반환하는 메서드&lt;/li&gt;
&lt;li&gt;length는 &lt;b&gt;배열&lt;/b&gt;에서 사용되며, 배열의 길이를 반환하는 &lt;b&gt;속성&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;size는 &lt;b&gt;Java에서 공식적으로 사용되지 않는 표현&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개인 공부/백</category>
      <author>가원스 토리</author>
      <guid isPermaLink="true">https://gawonstory.tistory.com/14</guid>
      <comments>https://gawonstory.tistory.com/14#entry14comment</comments>
      <pubDate>Mon, 30 Sep 2024 19:37:45 +0900</pubDate>
    </item>
    <item>
      <title>String 함수들</title>
      <link>https://gawonstory.tistory.com/13</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. charAt(int index) : 문자열에서 특정 인덱스에 있는 문자 반환&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691365707&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;Hello&quot;;
char ch = str.charAt(1); // 'e' 반환&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;2. length(): 문자열 길이 반환&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727692091476&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;Hello&quot;;
int len = str.length(); // 5 반환&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;3. substring(int beginIndex)&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691409533&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;Hello&quot;;
String subStr = str.substring(2); // &quot;llo&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;3-1. substring(int beginIndex,int endIndex) : 시작 인덱스부터 종료 인덱스 직전까지의 문자열 반환&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691459820&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;Hello&quot;;
String subStr = str.substring(1, 4); // &quot;ell&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;4. equals(Object anotherString): 두 문자열이 동일한지 비교합니다. (대소문자 구분)&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691559915&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str1 = &quot;Hello&quot;;
String str2 = &quot;hello&quot;;
boolean result = str1.equals(str2); // false 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. equalsIgnoreCase(String anotherString): &lt;/b&gt;&lt;b&gt;두 문자열이 동일한지 대소문자를 구분하지 않고 비교합니다.&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1727691584647&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str1 = &quot;Hello&quot;;
String str2 = &quot;hello&quot;;
boolean result = str1.equalsIgnoreCase(str2); // true 반환&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6. compareTo(String anotherString): &lt;/b&gt;&lt;b&gt;두 문자열을 사전순으로 비교합니다. (같으면 0, 크면 양수, 작으면 음수)&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1727691602217&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str1 = &quot;apple&quot;;
String str2 = &quot;banana&quot;;
int result = str1.compareTo(str2); // 음수 반환&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;7. contains(CharSequence s): &lt;/b&gt;&lt;b&gt;특정 문자열이 포함되어 있는지 확인합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691619418&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;Hello, world&quot;;
boolean result = str.contains(&quot;world&quot;); // true 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;8. startsWith(String prefix): &lt;/b&gt;&lt;b&gt;문자열이 주어진 접두사로 시작하는지 확인합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691633846&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;Hello&quot;;
boolean result = str.startsWith(&quot;He&quot;); // true 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;9. endsWith(String suffix): &lt;/b&gt;&lt;b&gt;문자열이 주어진 접미사로 끝나는지 확인합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691647575&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;Hello&quot;;
boolean result = str.endsWith(&quot;lo&quot;); // true 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;10. indexOf(String str): &lt;/b&gt;&lt;b&gt;주어진 문자열이 처음 등장하는 위치의 인덱스를 반환합니다. 없으면 -1을 반환합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691661912&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;Hello, world&quot;;
int index = str.indexOf(&quot;world&quot;); // 7 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;11. lastIndexOf(String str): &lt;/b&gt;&lt;b&gt;주어진 문자열이 마지막으로 등장하는 위치의 인덱스를 반환합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691677863&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;Hello, Hello&quot;;
int index = str.lastIndexOf(&quot;Hello&quot;); // 7 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;12. replace(CharSequence target, CharSequence replacement): &lt;/b&gt;&lt;b&gt;문자열 내의 특정 부분을 다른 문자열로 대체합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691696282&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;Hello, world&quot;;
String newStr = str.replace(&quot;world&quot;, &quot;Java&quot;); // &quot;Hello, Java&quot; 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;13. replaceAll(String regex, String replacement): &lt;/b&gt;&lt;b&gt;정규식을 사용하여 문자열의 특정 패턴을 모두 대체합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691721095&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;a1b2c3&quot;;
String newStr = str.replaceAll(&quot;\\d&quot;, &quot;&quot;); // &quot;abc&quot; 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;14. split(String regex): &lt;/b&gt;&lt;b&gt;주어진 정규식에 따라 문자열을 분리하여 배열로 반환합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691738009&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;apple,banana,orange&quot;;
String[] fruits = str.split(&quot;,&quot;); // [&quot;apple&quot;, &quot;banana&quot;, &quot;orange&quot;] 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;15. toLowerCase(): &lt;/b&gt;&lt;b&gt;문자열을 모두 소문자로 변환합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691756836&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;Hello&quot;;
String lowerStr = str.toLowerCase(); // &quot;hello&quot; 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;16. toUpperCase(): &lt;/b&gt;&lt;b&gt;문자열을 모두 대문자로 변환합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691776624&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;Hello&quot;;
String upperStr = str.toUpperCase(); // &quot;HELLO&quot; 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;17. trim(): &lt;/b&gt;&lt;b&gt;문자열의 앞뒤 공백을 제거합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691791583&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;  Hello  &quot;;
String trimmedStr = str.trim(); // &quot;Hello&quot; 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;18. isEmpty():문자열이 비어있는지 확인합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691822818&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;&quot;;
boolean isEmpty = str.isEmpty(); // true 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;19. format(String format, Object... args): &lt;/b&gt;&lt;b&gt;형식을 지정한 문자열을 반환합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691849835&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String formatted = String.format(&quot;Hello %s&quot;, &quot;World&quot;); // &quot;Hello World&quot; 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;20. join(CharSequence delimiter, CharSequence... elements): &lt;/b&gt;&lt;b&gt;주어진 구분자를 사용해 여러 문자열을 하나의 문자열로 결합합니다.&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1727691867015&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String joined = String.join(&quot;-&quot;, &quot;2023&quot;, &quot;09&quot;, &quot;30&quot;); // &quot;2023-09-30&quot; 반환&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;21. valueOf(Object obj): &lt;/b&gt;&lt;b&gt;다른 타입의 데이터를 문자열로 변환합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691887185&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = String.valueOf(123); // &quot;123&quot; 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;22. matches(String regex): &lt;/b&gt;&lt;b&gt;문자열이 주어진 정규식과 일치하는지 확인합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691900914&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;abc123&quot;;
boolean isMatch = str.matches(&quot;\\w+&quot;); // true 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;23. intern(): &lt;/b&gt;&lt;b&gt;문자열을 상수 풀(constant pool)에 추가하고 그 참조를 반환합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691920323&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = new String(&quot;Hello&quot;).intern();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;24. toCharArray(): &lt;/b&gt;&lt;b&gt;문자열을 문자 배열로 변환합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727691941014&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String str = &quot;Hello&quot;;
char[] chars = str.toCharArray(); // ['H', 'e', 'l', 'l', 'o'] 반환&lt;/code&gt;&lt;/pre&gt;</description>
      <category>개인 공부/백</category>
      <author>가원스 토리</author>
      <guid isPermaLink="true">https://gawonstory.tistory.com/13</guid>
      <comments>https://gawonstory.tistory.com/13#entry13comment</comments>
      <pubDate>Mon, 30 Sep 2024 19:28:25 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 코딩테스트 시간복잡도 해결 문제 #1</title>
      <link>https://gawonstory.tistory.com/12</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&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;이진수에서 '1'의 개수를 유지하면서 다음 큰 수 찾기&lt;/p&gt;
&lt;pre id=&quot;code_1727690874522&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//내가 적은 코드
import java.lang.*;
class Solution {
    public int solution(int n) {
        int answer = 0;
        String nn = Integer.toBinaryString(n);
        int n_count = 0;
        for (int i = 0; i &amp;lt; nn.length(); i++) {
            if (nn.charAt(i) == '1') {
                n_count++;
            }
        }
        for (int i = 1; i &amp;lt; Integer.MAX_VALUE; i++) {
            int target = n + i;
            String target_s = Integer.toBinaryString(target);
            int t_c = 0;
            for (int j = 0; j &amp;lt; target_s.length(); j++) {
                if (target_s.charAt(j) == '1') {
                    t_c++;
                }
            }
            if (t_c == n_count) {
                answer = target;
                break;
            }
        }
        return answer;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;시간 복잡도:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 숫자를 이진수로 변환하고 '1'의 개수를 세는 데 O(log n).&lt;/li&gt;
&lt;li&gt;최악의 경우 n에서 target까지의 거리는 O(n)이 될 수 있습니다.&lt;/li&gt;
&lt;li&gt;총 시간 복잡도는 O(n * log n).&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727690913862&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//개선 한 코드
class Solution {
    public int solution(int n) {
        int nCount = Integer.bitCount(n); // 1의 개수 계산
        int target = n + 1;
        while (Integer.bitCount(target) != nCount) {
            target++;
        }
        return target;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;개선한 이유:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;직접 1 개수 비교하지 않고 Integer.bitCount()를 사용해 효율적으로 1의 개수 세기&lt;/li&gt;
&lt;li&gt;루프는 n + 1부터 시작해 1의 개수가 같은 수를 찾는 데 필요한 최소 반복&lt;/li&gt;
&lt;li&gt;최종 총 시간 복잡도는 O(n * log n)이지만&amp;nbsp; 문자열 변환을 줄였기 때문에 성능 향상됨&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중복 신고 방지와 신고 횟수 계산&lt;/p&gt;
&lt;pre id=&quot;code_1727691059727&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//처음 작성한 코드
import java.util.*;

class Solution {
    public int[] solution(String[] id_list, String[] report, int k) {
        int[] answer = new int[id_list.length];
        List&amp;lt;String&amp;gt; r = new ArrayList&amp;lt;&amp;gt;(Arrays.asList(report));
        Set&amp;lt;String&amp;gt; reports = new HashSet&amp;lt;&amp;gt;(r); // 중복 제거
        List&amp;lt;String&amp;gt; list = new ArrayList&amp;lt;&amp;gt;(reports);
        int[] num = new int[id_list.length];
        for (int i = 0; i &amp;lt; list.size(); i++) {
            String[] sp = list.get(i).split(&quot; &quot;);
            for (int j = 0; j &amp;lt; id_list.length; j++) {
                if (sp[1].equals(id_list[j])) {
                    num[j] += 1;
                }
            }
        }
        for (int i = 0; i &amp;lt; answer.length; i++) {
            if (num[i] &amp;gt;= k) {
                String target = id_list[i];
                for (int j = 0; j &amp;lt; list.size(); j++) {
                    if (target.equals(list.get(j).split(&quot; &quot;)[1])) {
                        for (int o = 0; o &amp;lt; id_list.length; o++) {
                            if (id_list[o].equals(list.get(j).split(&quot; &quot;)[0])) {
                                answer[o] += 1;
                            }
                        }
                    }
                }
            }
        }
        return answer;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;시간 복잡도:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중복 신고 제거를 위해 HashSet을 사용하는 것은 O(n) (n은 신고 횟수)&lt;/li&gt;
&lt;li&gt;내부적으로 각 신고가 해당 사용자를 신고했는지 확인하는 부분에서 중복된 split과 반복문이 있어 성능 저하가 발생&lt;/li&gt;
&lt;li&gt;총 시간 복잡도는 O(n * m) (n은 신고 횟수, m은 유저의 수)로 아주아주아주 비효율적임&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727691118782&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//개선한 코드
import java.util.*;

class Solution {
    public int[] solution(String[] id_list, String[] report, int k) {
        int[] answer = new int[id_list.length];
        Map&amp;lt;String, Set&amp;lt;String&amp;gt;&amp;gt; reports = new HashMap&amp;lt;&amp;gt;(); // 각 사용자의 신고 리스트
        Map&amp;lt;String, Integer&amp;gt; reportCounts = new HashMap&amp;lt;&amp;gt;(); // 신고 받은 횟수

        // 신고 기록 처리
        for (String r : report) {
            String[] split = r.split(&quot; &quot;);
            String reporter = split[0];
            String reported = split[1];
            
            reports.putIfAbsent(reported, new HashSet&amp;lt;&amp;gt;());
            if (!reports.get(reported).contains(reporter)) {
                reports.get(reported).add(reporter);
                reportCounts.put(reported, reportCounts.getOrDefault(reported, 0) + 1);
            }
        }

        // 신고된 횟수가 k 이상인 사용자 찾기
        for (int i = 0; i &amp;lt; id_list.length; i++) {
            String user = id_list[i];
            if (reportCounts.getOrDefault(user, 0) &amp;gt;= k) {
                for (String reporter : reports.get(user)) {
                    answer[Arrays.asList(id_list).indexOf(reporter)]++;
                }
            }
        }
        return answer;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;개선된 시간 복잡도:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HashSet과 HashMap을 사용해 중복 신고를 방지하고 효율적으로 처리했기 때문에 중복 확인이 O(1)&lt;/li&gt;
&lt;li&gt;총 시간 복잡도는 O(n + m)입니다. (n은 신고 횟수, m은 유저의 수)로 훨씬 효율적&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개인 공부/백</category>
      <author>가원스 토리</author>
      <guid isPermaLink="true">https://gawonstory.tistory.com/12</guid>
      <comments>https://gawonstory.tistory.com/12#entry12comment</comments>
      <pubDate>Mon, 30 Sep 2024 19:14:04 +0900</pubDate>
    </item>
    <item>
      <title>프로젝트 진행중 다양한 에러들과 해결방법</title>
      <link>https://gawonstory.tistory.com/10</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. &lt;b&gt;이메일 시스템 구축 (SMTP와 IMAP 사용)&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;문제:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;SMTP 서버와의 연결 실패&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: SMTP 서버 설정을 확인해야 합니다. 특히 포트, 호스트 이름, 인증 정보가 정확한지 확인해야 하며, TLS/SSL 설정이 필요할 수 있음. 외부 이메일 서버를 사용할 때는 방화벽 설정도 확인필요&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;IMAP을 통해 메일 수신 시 메시지 인코딩 문제&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: IMAP 프로토콜에서 수신한 이메일의 인코딩 형식을 확인하고, UTF-8로 변환하는 코드를 추가. 이메일 헤더의 Content-Type을 분석하여 적절한 인코딩 방식을 적용하는 것이 중요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. &lt;b&gt;REST API 및 SOAP API 개발 (MSA 기반)&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;문제:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;API 호출 시 데이터 형식 불일치&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: REST API와 SOAP API 모두 서로 다른 데이터 포맷을 지원 따라서 JSON과 XML 간의 변환 로직을 추가하여 클라이언트와 서버 간 데이터 형식의 일관성을 유지필요!!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MSA 간 인증 문제 (JWT 토큰 만료)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: 마이크로서비스 간의 통신에서 JWT 토큰이 만료될 수 있음. 이를 해결하기 위해 Refresh Token 메커니즘을 도입하고, 각 서비스에서 토큰의 유효성을 주기적으로 검증하는 로직을 추가필요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. &lt;b&gt;프로젝트 '벌판' (Groupware 서비스)&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;문제:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;전자결재 시스템의 데이터베이스 구조 설계&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: 결재 문서와 관련된 복잡한 데이터 구조를 MongoDB에 저장할 때, 스키마를 명확히 설계해야 함. 특히 결재 문서, 승인 이력, 결재 상태 등의 정보를 잘 관리할 수 있는 스키마를 도입하고, 이를 효율적으로 쿼리할 수 있도록 인덱스를 설정필요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;공간 및 차량 예약 시스템의 중복 예약 처리&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: 예약 기능에서 동일 시간대에 중복 예약을 방지하기 위해 트랜잭션을 사용하거나, 예약이 확정되기 전까지 일정 임시 저장소를 관리하여 중복 발생을 방지하는 로직을 추가필요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. &lt;b&gt;스케줄 관리 및 전자결재 시스템 (MongoDB 사용)&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;문제:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;MongoDB 연결 실패&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: MongoDB의 포트, 인증 정보, IP 접근 설정을 확인해야함. 특히 방화벽 규칙이나 네트워크 연결이 문제일 수 있으며, bind_ip 설정이 로컬 호스트로만 제한되어 있을 경우 외부에서 접근할 수 없으므로 이를 수정필요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;결재 문서의 대량 처리 시 성능 저하&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: MongoDB에서 대량의 결재 문서를 처리할 때는, 효율적인 인덱싱과 샤딩(Sharding)을 적용하여 성능을 최적화해야함. 또한, 자주 사용되는 쿼리에 대해 인덱스를 생성하는 것이 중요!!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. &lt;b&gt;출퇴근 관리 시스템 (React, Axios 사용)&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;문제:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;출퇴근 시간 변환 로직 오류&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: 시간대 변환 시 Date 객체를 사용하여 사용자의 로컬 시간대로 변환하는 로직을 추가함. 시간을 관리하는 모든 데이터는 UTC로 저장하고, 출력할 때는 사용자의 로컬 시간대로 변환하여 사용.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Axios를 통한 데이터 불러오기 시 지연 문제&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: API 호출이 지연되는 경우 로딩 상태를 추가하여 UX를 개선 함 useState와 useEffect를 사용해 로딩 상태를 관리하고, 데이터가 완전히 로드되기 전까지 로딩 스피너를 표시함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. &lt;b&gt;Socket 통신 기반 실시간 채팅 기능 개발 (Kafka, WebSocket)&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;문제:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Kafka에서의 데이터 누락 문제 (서버 재시작 후)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: Kafka에서 AUTO_OFFSET_RESET_CONFIG를 &quot;earliest&quot;로 설정하여 서버 재시작 후에도 모든 메시지를 불러오도록 설정가능. 이 설정이 없으면 Kafka는 마지막 읽은 오프셋 이후의 데이터만 가져오므로, 이를 방지하려면 컨슈머 설정을 조정해야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>error</category>
      <author>가원스 토리</author>
      <guid isPermaLink="true">https://gawonstory.tistory.com/10</guid>
      <comments>https://gawonstory.tistory.com/10#entry10comment</comments>
      <pubDate>Sat, 21 Sep 2024 19:24:44 +0900</pubDate>
    </item>
    <item>
      <title>채팅 서비스 에러와 해결</title>
      <link>https://gawonstory.tistory.com/9</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;채팅 서비스 개발 중 여러 문제들과 해결방법 간단 정리&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Frontend 문제 및 해결 과정&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Uncaught TypeError: Cannot read properties of undefined (reading 'value')&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;문제 설명&lt;/b&gt;: 데이터가 없는 상태에서 undefined 또는 null 값을 접근할 때 발생한 오류.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: JSX 내에서 요소가 존재하는지 조건부로 검사하여, 값이 있을 때만 접근할 수 있도록 조건부 렌더링을 적용.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모달에서 참가자 선택 시 중복된 데이터 처리 문제&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;문제 설명&lt;/b&gt;: 모달에서 참가자를 선택할 때 중복된 참가자가 추가되는 문제.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: item.id로 중복 여부를 체크하여, 중복된 값이 있으면 추가하지 않도록 로직을 수정함. map 함수와 filter 함수를 사용하여 중복을 제거.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로딩 상태를 UI에 표시하기 위한 설정&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;문제 설명&lt;/b&gt;: API 요청에 시간이 소요되기 때문에 로딩 상태를 나타낼 필요가 있었음.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: useState를 활용해 loading 상태를 관리하고, Axios 요청이 완료되면 로딩 상태를 해제하여, 로딩 중일 때는 프로그레스바를 표시하는 UX를 개선함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Axios 요청 실패 문제 (403 Forbidden)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;문제 설명&lt;/b&gt;: 서버에 대한 POST 요청이 403 Forbidden 오류로 실패함.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: 요청에 필요한 헤더 정보, 특히 인증 정보 또는 권한을 확인하여 적절히 수정함. CORS 설정도 확인하여 클라이언트 요청이 서버에서 허용되도록 조정함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;참가자 자동 추가 문제&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;문제 설명&lt;/b&gt;: 모달에서 다른 사용자를 선택할 때 현재 사용자 정보가 자동으로 추가되지 않음.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: 현재 사용자 정보를 불러오는 autoSelect() 함수를 모달이 열릴 때 호출하고, 중복된 참가자가 포함되지 않도록 로직을 구현함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Backend 문제 및 해결 과정&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Kafka 브로커 연결 문제 (403 Forbidden)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;문제 설명&lt;/b&gt;: Kafka 브로커에 접근 시, 권한 설정 문제로 인해 연결 실패.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: Kafka 브로커 설정에서 올바른 서버 주소와 포트를 지정하고, CORS 및 인증 설정을 확인하여 수정함.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Kafka earliest 설정 적용 문제&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;문제 설명&lt;/b&gt;: Kafka에서 컨슈머가 시작할 때, 처음부터 메시지를 읽어야 했으나 중간부터 읽기 시작함.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: Kafka 컨슈머 설정에서 AUTO_OFFSET_RESET_CONFIG 값을 &quot;earliest&quot;로 설정하여 처음부터 메시지를 읽을 수 있도록 구성함. 또한 ValueDeserializer 설정이 적용되어야 하며, 이를 누락할 경우 제대로 동작하지 않음을 확인함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MongoDB와 Kafka 연동 문제&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;문제 설명&lt;/b&gt;: 서버가 껐다 켜질 때 메시지가 제대로 유지되지 않음.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: Kafka와 MongoDB를 연동하여, Kafka에서 처리된 데이터를 MongoDB에 저장함으로써 서버 재시작 후에도 동일한 메시지를 불러올 수 있도록 설정. MongoDB가 데이터를 영구 저장하므로 데이터 손실을 방지함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Kafka 컨슈머 그룹 리셋 문제&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;문제 설명&lt;/b&gt;: Kafka 컨슈머 그룹이 특정 시점 이후의 데이터만 처리.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: Kafka CLI 명령어인 kafka-consumer-groups.sh를 사용하여 컨슈머 그룹의 오프셋을 리셋하고 처음부터 데이터를 읽도록 설정함. --reset-offsets 명령어를 활용하여 오프셋을 초기화함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MongoDB 외부 접근 문제&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;문제 설명&lt;/b&gt;: MongoDB Docker 컨테이너를 외부에서 접근하지 못함.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: docker-compose.yml에서 포트 설정을 수정하여 MongoDB 컨테이너의 포트를 외부와 매핑함. 27017:27017로 외부와 연결 가능하도록 포트 포워딩을 설정하고, 인증 정보(root 계정)를 통해 접근할 수 있도록 수정함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Zookeeper 설정 문제&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;문제 설명&lt;/b&gt;: Zookeeper 설정이 제대로 되지 않아 Kafka와의 연결이 불안정.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;해결 방법&lt;/b&gt;: Zookeeper의 설정 파일을 확인하고, Zookeeper와 Kafka 간의 네트워크 연결 설정을 수정함. Kafka의 zookeeper.connect 설정을 통해 Zookeeper 서버에 올바르게 연결되도록 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>error</category>
      <author>가원스 토리</author>
      <guid isPermaLink="true">https://gawonstory.tistory.com/9</guid>
      <comments>https://gawonstory.tistory.com/9#entry9comment</comments>
      <pubDate>Sat, 21 Sep 2024 18:15:28 +0900</pubDate>
    </item>
  </channel>
</rss>