<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jwlee_dev.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Mon, 15 Apr 2024 02:10:41 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. jwlee_dev.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jwlee_dev" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[AWS Event Bridge Cross Account]]></title>
            <link>https://velog.io/@jwlee_dev/AWS-Event-Bridge-Cross-Account</link>
            <guid>https://velog.io/@jwlee_dev/AWS-Event-Bridge-Cross-Account</guid>
            <pubDate>Mon, 15 Apr 2024 02:10:41 GMT</pubDate>
            <description><![CDATA[<p>Service Catalog dptj</p>
<p><img src="https://velog.velcdn.com/images/jwlee_dev/post/34fa8dc0-585a-4d89-a30e-b756c29a9b22/image.png" alt=""></p>
<p>이슈</p>
<ol>
<li>AWS Service에서 발생하는 Event는 Default Event Bus로만 보내짐. 캐치하길 원하는 이벤트는 Service Catalog에서 발생하여 Cloud Trail 찍힌 이벤트인데, Custom Event Bus 생성 후에도 이벤트가 안 넘어감.</li>
<li>DevOps Account(수신 계정)에서도 Default Event Bus의 Rule에서만 Event를 Catch할 수 있음, 아래 처럼, Event 수신 계정에서 Custom Event Bus에는 Matched Event가 안 찍히는 것 확인
<img src="https://velog.velcdn.com/images/jwlee_dev/post/b9377f03-78d6-481b-895d-dbb57449031f/image.png" alt=""></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS EBS]]></title>
            <link>https://velog.io/@jwlee_dev/EBS</link>
            <guid>https://velog.io/@jwlee_dev/EBS</guid>
            <pubDate>Sat, 13 Apr 2024 12:14:28 GMT</pubDate>
            <description><![CDATA[<h2 id="ebs-특징">EBS 특징</h2>
<h3 id="--ebs는-인스턴스에-부착할-수-있는-network-device">- EBS는 인스턴스에 부착할 수 있는 Network Device</h3>
<h3 id="--persistent-data-저장공간으로-인스턴스-종료-후에도-데이터가-남아-있을-수-있음">- Persistent Data 저장공간으로, 인스턴스 종료 후에도 데이터가 남아 있을 수 있음</h3>
<h3 id="--한-번에-한-개의-인스턴스에-마운트됨인스턴스는-여러-개의-ebs를-갖을-수-있음">- 한 번에 한 개의 인스턴스에 마운트됨(인스턴스는 여러 개의 EBS를 갖을 수 있음)</h3>
<h3 id="--한-개의-az내에서-사용-가능">- 한 개의 AZ내에서 사용 가능</h3>
<h3 id="--쉽게-생각하여-네트워크-상에-존재하는-usb로-이해하면-됨-한-개-이상의-인스턴스에-옮기면서-사용-가능함">- 쉽게 생각하여, 네트워크 상에 존재하는 USB로 이해하면 됨. 한 개 이상의 인스턴스에 옮기면서 사용 가능함</h3>
<h4 id="--프리티어-1mssd30gb">- 프리티어: 1M/SSD(30GB)</h4>
<h3 id="--네트워크-통신으로-일부-지연이-발생할-수-있음">- 네트워크 통신으로 일부 지연이 발생할 수 있음</h3>
<h3 id="--instance-storage-탭에서-확인-가능">- Instance Storage 탭에서 확인 가능</h3>
<h3 id="--instance-생성-시-같이-만들어지는-root-ebs-volume은-instance-삭제-시-삭제되는게-기본-옵션삭제-안-되도록-수정-가능-attached-ebs-volume은-삭제-안-되는게-기본-옵션">- Instance 생성 시 같이 만들어지는 Root EBS Volume은 Instance 삭제 시, 삭제되는게 기본 옵션.(삭제 안 되도록 수정 가능), Attached EBS Volume은 삭제 안 되는게 기본 옵션</h3>
<h2 id="ebs-snaphot">EBS Snaphot</h2>
<h3 id="--ebs-volume을-특정-시점에-backup-진행">- EBS Volume을 특정 시점에 Backup 진행</h3>
<h3 id="--snapshot-할-때-volume-detachment가-필수는-아니나-권장">- Snapshot 할 때, Volume Detachment가 필수는 아니나 권장</h3>
<h3 id="--다른-az나-region에-이동-가능함">- 다른 AZ나 Region에 이동 가능함</h3>
<h3 id="--ebs-snapshot-archive">- EBS Snapshot Archive</h3>
<ul>
<li>archive Tier로 이동, 75% 저렴</li>
<li>24 ~ 72 시간 내에, restore 해야함<h3 id="--recycle-bin-for-ebs-snapshots">- Recycle Bin for EBS Snapshots</h3>
</li>
<li>rule 설정 후, EBS Snapshot을 삭제해도 recover 가능함</li>
<li>1 day ~ 1 year 까지 보관 가능<h3 id="--aws-console에서-ebs의-volumes-탭에서-ebs-actions---create-snapshot---snapshot-탭에서-snapshot-확인">- AWS Console에서 EBS의 Volumes 탭에서 EBS Actions -&gt; Create Snapshot -&gt; Snapshot 탭에서 Snapshot 확인</h3>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[ArgoCD RBAC 관리]]></title>
            <link>https://velog.io/@jwlee_dev/ArgoCD-RBAC-%EA%B4%80%EB%A6%AC</link>
            <guid>https://velog.io/@jwlee_dev/ArgoCD-RBAC-%EA%B4%80%EB%A6%AC</guid>
            <pubDate>Mon, 04 Mar 2024 14:10:22 GMT</pubDate>
            <description><![CDATA[<h2 id="1-argocd-유저-관리">1. ArgoCD 유저 관리</h2>
<ul>
<li>ArgoCD 설치 시 admin role을 가진 admin 유저가 생성됩니다.</li>
<li>ArgoCD의 유저 종류엔 Local User(ArgoCD 서버 관리), SSO(OKTA) 연동 user로 나뉩니다.</li>
<li>ArgoCD 유저 관련 명령어<pre><code>argocd account list # To list all the users
argocd account get &lt;username&gt; # To get specific user details
argocd account update-password --account &lt;username&gt; --new-password</code></pre></li>
</ul>
<h2 id="2-local-user-관리">2. Local User 관리</h2>
<h3 id="1-local-user-생성-방법">(1) Local User 생성 방법</h3>
<ul>
<li>ArgoCD admin 유저 로그인<pre><code>argocd login &lt;argocdIP:port&gt;
# 콘솔에 username:admin, 비밀번호:초기값 입력</code></pre><img src="https://velog.velcdn.com/images/jwlee_dev/post/a65fc3d4-7cb6-40eb-b383-1b474a99d71d/image.png" alt=""></li>
</ul>
<ul>
<li>argocd-cm 설정 내용을 yaml 파일로 저장<pre><code>  kubectl get cm argocd-cm -n argocd -o yaml &gt; argocd-cm.yaml </code></pre></li>
<li>argocd-cm 설정 내용을 yaml에 추가<pre><code>apiVersion: v1
data:
accounts.ccoe: apiKey, login
accounts.devops: apiKey, login
accounts.developer: apiKey,login
...</code></pre></li>
<li>argocd-cm.yaml 반영<pre><code>kubectl apply -f argocd-cm.yaml</code></pre></li>
<li>유저 목록 확인<pre><code>argocd account list</code></pre></li>
</ul>
<h3 id="2-local-user-비밀번호-설정">(2) Local User 비밀번호 설정</h3>
<p><img src="https://velog.velcdn.com/images/jwlee_dev/post/ebd72da3-8d8b-4ecf-9c9e-7f3fac0b82ab/image.png" alt=""></p>
<ul>
<li>유저별 비밀번호 설정<pre><code>argocd account update-password --account ccoe
argocd account update-password --account devops
argocd account update-password --account developer</code></pre><img src="https://velog.velcdn.com/images/jwlee_dev/post/562458d4-d8ba-49b9-b0bf-3e89d9d383d9/image.png" alt=""></li>
</ul>
<h3 id="3-local-user-권한role-설정">(3) Local User 권한(Role) 설정</h3>
<ul>
<li>ArgoCD role을 관리하는 argocd-rabc-cm을 yaml파일로 저장<pre><code>kubectl get cm -n argocd argocd-rbac-cm -o yaml &gt; argocd-rbac-cm.yaml</code></pre></li>
<li>role-policy 및 유저에 role 할당<pre><code>apiVersion: v1
kind: ConfigMap
data:
policy.csv: |
  p, role:ccoe-role, *, *, *, allow
  p, role:devops-role, applications, *, *, allow
  p, role:devops-role, clusters, *, *, allow
  p, role:devops-role, repositories, *, *, allow
  p, role:developer-role, applications, get, *, allow
  p, role:developer-role, clusters, get, *, allow
  p, role:developer-role, repositories, get, *, allow
  g, ccoe, role:ccoe-role
  g, devops, role:devops-role
  g, developer, role:developer-role
...</code></pre></li>
</ul>
<h2 id="3-okta-user-관리">3. Okta User 관리</h2>
<ul>
<li>ArgoCD 설치 시, Dex가 함께 설치됨, Dex는 인증 서비스로, 다른 서비스 간에 인증 작업을 수행한다.
<img src="https://velog.velcdn.com/images/jwlee_dev/post/b63f3544-8d68-4e50-a657-07bd8be8852b/image.png" alt=""><ul>
<li>Dex는 Okta, SAML, OIDC, LDAP 연동 등을 지원한다.</li>
</ul>
</li>
</ul>
<h3 id="1-okta에-argocd-등록-방법">(1) Okta에 ArgoCD 등록 방법</h3>
<ul>
<li>Okta 페이지에서, Applications -&gt; Applications 이동</li>
<li>Create App Integration 선택</li>
<li>SAML 2.0 -&gt; Next 선택</li>
<li>App name: ArgoCD ~~ 입력</li>
<li>SAML 설정, 
-&gt; SSO URL: ArgoCD URL/api/dex/callback
**  - 서비스별 ArgoCD 생성 마다, Okta에서 유저그룹을 ArgoCD에 매핑해주는 작업이 필요함**</li>
</ul>
<h3 id="2-argocd에-okta-인증-정보-등록">(2) ArgoCD에 Okta 인증 정보 등록</h3>
<ul>
<li><p>Okta에 Argocd 등록 후, url/certificate를 argocd-cm에 등록</p>
<pre><code>dex.config: |
connectors:
- type: saml
  id: okta
  name: Okta
  config:
    ssoURL: &lt;okta sso url&gt;
    caData: |
      &lt;x.509 certificate&gt;
    usernameAttr: name
    emailAttr: email
    groupsAttr: groups</code></pre><p><img src="https://velog.velcdn.com/images/jwlee_dev/post/f137bbe0-b7b1-4e7c-9c86-39a4487dca68/image.png" alt=""></p>
</li>
<li><p>argocd-rbac-cm에 okta user group에 role을 매핑
<img src="https://velog.velcdn.com/images/jwlee_dev/post/31c3a82b-f24a-4916-854b-c57ad3520a8c/image.png" alt=""></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[K8S] ArgoCD Ingress]]></title>
            <link>https://velog.io/@jwlee_dev/K8S-ArgoCD-Ingress</link>
            <guid>https://velog.io/@jwlee_dev/K8S-ArgoCD-Ingress</guid>
            <pubDate>Mon, 27 Nov 2023 09:07:04 GMT</pubDate>
            <description><![CDATA[<p>사내 ALB 설정은 아래와 같다.</p>
<pre><code>apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/healthcheck-path: /
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/healthcheck-protocol: HTTP
    alb.ingress.kubernetes.io/subnets: subnet-041a058cf4f06363c, subnet-06c5935aee30890a9
    alb.ingress.kubernetes.io/listen-ports: &#39;[{&quot;HTTP&quot;:80}]&#39;
  name: devops-argocd-alb-ingress
  namespace: argocd    # 설치할 네임스페이스
spec:
  rules:
  - http:
      paths:
      - backend:
          service:
            name: argocd-server 
            port:
              number: 80 
        path: /*
        pathType: ImplementationSpecific</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[K8S] 도커 이미지 커스터마이징]]></title>
            <link>https://velog.io/@jwlee_dev/K8S-%EB%8F%84%EC%BB%A4-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%BB%A4%EC%8A%A4%ED%84%B0%EB%A7%88%EC%9D%B4%EC%A7%95</link>
            <guid>https://velog.io/@jwlee_dev/K8S-%EB%8F%84%EC%BB%A4-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%BB%A4%EC%8A%A4%ED%84%B0%EB%A7%88%EC%9D%B4%EC%A7%95</guid>
            <pubDate>Sun, 26 Nov 2023 14:22:10 GMT</pubDate>
            <description><![CDATA[<p>ArgoCD를 운영하면서, argocd-server 필요한 </p>
<p>m1 맥북에서 리눅스 이미지 빌드하기 위해선, linux/amd64 플랫폼 옵션을 지정해야한다.</p>
<pre><code>docker build --platform linux/amd64 -t docker-test .</code></pre><p>윈도우 도커 설치 
wsl2 설치 -&gt; docker agent 설치</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS VPC]]></title>
            <link>https://velog.io/@jwlee_dev/AWS-VPC</link>
            <guid>https://velog.io/@jwlee_dev/AWS-VPC</guid>
            <pubDate>Sun, 28 May 2023 16:28:06 GMT</pubDate>
            <description><![CDATA[<ol>
<li><p>AWS와 VPC 네트워킹</p>
<ul>
<li>AWS는 근본적으로 회사 또는 개인의 서비스의 운영 환경(on-premise)을 AWS 데이터 센터로 옮기는 사업을 영위함. 따라서 대부분의 기존 운영 환경 보다 편리하고, 안전한 클라우드 환경을 제공하기 위해 노력함.</li>
<li>이 과정에서 가장 중요한 개념이 VPC(Virtual Private Cloud)인데, 이를 통해 사용자들이 기존 운영 환경에서 마이그레이션을 할 때, 보다 편리하고 쉽게 작업할 수 있도록 만들어 놓은 논리적 네트워크 망이다.</li>
</ul>
</li>
<li><p>VPC(Virtual Private Cloud)</p>
<ul>
<li>VPC란?
: VPC는 사용자에게 자신만의 네트워크 영역을 만들기 위한 개인 고유의 영토를 AWS에서 주는 것에 비유할 수 있음.
: VPC가 생성이 됐을 지라도, 이것만으론 어떠한 것도 할 수 없기 때문에 VPC 네트워킹을 통해 VPC 내/외로 여러 서비스 및 리소스들을 만들고 서로 네트워크 연결을 설정함으로써, 하나의 완성형 인프라를 구축해 나갈 수 있음. 이렇게 각 서비스와 리소스들에 대한 연결을 이어주는 작업을 VPC 네트워킹이라 함.</li>
</ul>
<ol start="3">
<li>VPC 네트워킹
: VPC 네트워킹을 위해선 인스턴스(EC2, RDS 등)에 네트워크 인터페이스를 다른 곳과 연결에 통신이 필요함, VPC 내에 운영중인 모든 인스턴스들은 네트워크 인터페이스가 필수적으로 연결되어 있어야 함.
: 네트워크 인터페이스
-&gt; 네트워크 인터페이스는 보안 그룹이 할당되어야 함
-&gt; 네트워크 인터페이스는 서브넷이 생성되어야 그 안에 인스턴스가 만들어 지면서 네트워크 인터페이스가 같이 생성될 수 있음
-&gt; 네트워크 인터페이스는 서브넷에 매핑된 NACL과 라우팅 테이블과 연결되어 통신함</li>
</ol>
</li>
<li><p>VPC 네트워킹의 구성 요소
: 공간, 연결, 컴퓨팅
: 공간
 -&gt; VPC에서 공간은 다른 무언가를 포함하는 영역을 의미
 -&gt; 계정, 리전, VPC, 가용 영역, 서브넷
 -&gt; 계정: AWS 계정, AWS Cloud의 모든 리전에 접근하여 환경 구축 가능, 기본적으로 계정간에 서비스들은 통신이 불가능함
 -&gt; 리전: 전세계적으로 위치한 지역별 AWS 데이터센터를 의미
 -&gt; VPC: 논리적인 사설 네트워크 망
 -&gt; 가용 영역: 실제 AWS 데이터센터에서 할당된 물리적 공간
 -&gt; 서브넷: VPC 내에서 실제 인스턴스가 실행되는 논리적인 영역, VPC와 가용영역의 공통 부분
: 연결
 -&gt; 공간 사이를 잇는 요소를 의미, VPC의 트래픽에 관련된 연결 및 통제 기능을 하는 역할을 함
 -&gt; NACL: NACL은 서브넷으로 유입되는 트래픽을 통제함. 화이트리스트 기반 결합 방식으로 유입 IP를 통제함, 예를 들어 CIDR 범위에 속하는 특정 IP를 차단하고 싶을 때 CIDR 범위를 지정하는 시퀀스 보다 앞에 특정 IP를 위치시키는 형태임. 마지막 시퀀스엔 화이트 방식과 동일하게 All Deny가 적용. NACL은 source IP에 대해 Stateless하기 때문에, inbound 뿐만 아니라, outbound도 미리 오픈해야 함.(ip/port 포함)
 -&gt; Secuiry Group: Security Group은 서비스의 ENI에 유입되는 트래픽 접근일 제어함. 화이트 리스트 방식으로 허용하고자 하는 IP 또는 CIDR 범위를 지정할 수 있음. Inbound, Outbound 적용 시, SG그룹을 반영할 수 있음.</p>
</li>
<li></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[minikube 설치 m1 mac]]></title>
            <link>https://velog.io/@jwlee_dev/minikube-%EC%84%A4%EC%B9%98-m1-mac</link>
            <guid>https://velog.io/@jwlee_dev/minikube-%EC%84%A4%EC%B9%98-m1-mac</guid>
            <pubDate>Wed, 22 Mar 2023 13:26:16 GMT</pubDate>
            <description><![CDATA[<p>curl -LO <a href="https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-arm64">https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-arm64</a></p>
<p>chmod +x minikube-darwin-arm64
sudo mv minikube /usr/local/bin/
minikube start --driver=docker --alsologtostderr</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CKA Pod scale out]]></title>
            <link>https://velog.io/@jwlee_dev/CKA-Pod-scale-out</link>
            <guid>https://velog.io/@jwlee_dev/CKA-Pod-scale-out</guid>
            <pubDate>Sun, 19 Mar 2023 14:43:56 GMT</pubDate>
            <description><![CDATA[<p>Question : Expand the number of running Pods in eshop-order from 1 to 5.</p>
<p>TASK :</p>
<p>namespace : 본인 namespace
deployment : eshop-order
image : ghcr.io/shclub/nginx</p>
<pre><code>kubectl scale --replicas=5 deployment eshop-order
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[CKA 하나의 파드에 여러개의 컨테이너 올리기]]></title>
            <link>https://velog.io/@jwlee_dev/CKA-%ED%95%98%EB%82%98%EC%9D%98-%ED%8C%8C%EB%93%9C%EC%97%90-%EC%97%AC%EB%9F%AC%EA%B0%9C%EC%9D%98-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-%EC%98%AC%EB%A6%AC%EA%B8%B0</link>
            <guid>https://velog.io/@jwlee_dev/CKA-%ED%95%98%EB%82%98%EC%9D%98-%ED%8C%8C%EB%93%9C%EC%97%90-%EC%97%AC%EB%9F%AC%EA%B0%9C%EC%9D%98-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-%EC%98%AC%EB%A6%AC%EA%B8%B0</guid>
            <pubDate>Sun, 19 Mar 2023 14:29:03 GMT</pubDate>
            <description><![CDATA[<pre><code>vi multi-container.yaml

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: multi-container
  name: multi-container
  namespace: edu18
spec:
  containers:
  - image: ghcr.io/shclub/nginx
    name: nginx
  - image: ghcr.io/shclub/redis
    name: redis
  - image: ghcr.io/shclub/memcached
    name: memcashed
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}</code></pre><p>kubectl create -f multi-container.yaml</p>
<p>kubectl get pod -n edu18
<img src="https://velog.velcdn.com/images/jwlee_dev/post/a4bc44a9-357c-475c-91cc-d3925dad2067/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Nexus(넥서스) Repository Manager 설치 가이드]]></title>
            <link>https://velog.io/@jwlee_dev/NEXUS-Repository-Manager-%EC%84%A4%EC%B9%98</link>
            <guid>https://velog.io/@jwlee_dev/NEXUS-Repository-Manager-%EC%84%A4%EC%B9%98</guid>
            <pubDate>Tue, 07 Mar 2023 08:30:17 GMT</pubDate>
            <description><![CDATA[<h2 id="nexus-설치">Nexus 설치</h2>
<h3 id="1-자바-18-버전-설치">1. 자바 1.8 버전 설치</h3>
<pre><code>yum install java-1.8.0-openjdk-devel</code></pre><h3 id="2-nexus-3311-01-버전-다운로드">2. Nexus 3.31.1-01 버전 다운로드</h3>
<pre><code>wget https://download.sonatype.com/nexus/3/nexus-3.31.1-01-unix.tar.gz</code></pre><h3 id="3-nexus-압축-해제-및-이름-변경">3. nexus 압축 해제 및 이름 변경</h3>
<pre><code>tar -xvzf nexus-3.31.1-01-unix.tar.gz
mv nexus-3.31.1-01 nexus</code></pre><h3 id="4-압축파일-삭제-후-opt-경로로-nexus-sonatype-work-디렉터리-이동">4. 압축파일 삭제 후, /opt 경로로 nexus, sonatype-work 디렉터리 이동</h3>
<pre><code>rm -rf nexus-3.31.1-01-unix.tar.gz
mv nexus /opt
mv sonatype-work /opt</code></pre><h3 id="5-opt-경로에서-아래와-같이-nexus-유저-생성-후-권한-부여">5. /opt 경로에서 아래와 같이 nexus 유저 생성 후 권한 부여</h3>
<pre><code>adduser nexus
passwd nexus
chown -R nexus:nexus nexus
chown -R nexus:nexus sonatype-work/</code></pre><h3 id="6-nexusvmoptions-설정">6. nexus.vmoptions 설정</h3>
<pre><code>vi /opt/nexus/bin/nexus.vmoptions</code></pre><pre><code>  -Xms2703m

  -Xmx2703m

  -XX:MaxDirectMemorySize=2703m

  -XX:+UnlockDiagnosticVMOptions

  -XX:+LogVMOutput

  -XX:LogFile=(nexus 디렉터리 경로)/sonatype-work/nexus3/log/jvm.log # nexus 디렉터리 기준으로 경로 설정

  -XX:-OmitStackTraceInFastThrow

  -Djava.net.preferIPv4Stack=true

  -Dkaraf.home=.

  -Dkaraf.base=.

  -Dkaraf.etc=etc/karaf

  -Djava.util.logging.config.file=etc/karaf/java.util.logging.properties

  -Dkaraf.data=(nexus 디렉터리 경로)/sonatype-work/nexus3 # nexus 디렉터리 기준으로 경로 설정

  -Dkaraf.log= (nexus 디렉터리 경로)/sonatype-work/nexus3/log # nexus 디렉터리 기준으로 경로 설정

  -Djava.io.tmpdir= (nexus 디렉터리 경로)/sonatype-work/nexus3/tmp # nexus 디렉터리 기준으로 경로 설정

  -Dkaraf.startLocalConsole=false

  -Djdk.tls.ephemeralDHKeySize=2048</code></pre><h3 id="7-nexusservice-파일-설정">7. nexus.service 파일 설정</h3>
<pre><code>vi /etc/systemd/system/nexus.service</code></pre><pre><code>  [Unit]

  Description=nexus service

  After=network.target


  [Service]

  Type=forking

  LimitNOFILE=65536

  ExecStart=(nexus 디렉터리의 절대 경로)/bin/nexus start 

  ExecStop=(nexus 디렉터리의 절대 경로)/opt/nexus/bin/nexus stop

  User=nexus

  Restart=on-abort

  TimeoutSec=600


  [Install]

  WantedBy=multi-user.target</code></pre><h3 id="8-아래-명령어로-nexus-실행">8. 아래 명령어로 Nexus 실행</h3>
<pre><code>sudo systemctl daemon-reload
sudo systemctl enable nexus.service
sudo systemctl start nexus.service</code></pre><h3 id="9-8081-포트-접속-후-로그인">9. 8081 포트 접속 후, 로그인</h3>
<ul>
<li><p>user는 admin</p>
</li>
<li><p>password는 아래 명령어로 확인 </p>
<p> cat /opt/sonatype-work/nexus3/admin.password</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript 비동기 흐름은 함수 안에서]]></title>
            <link>https://velog.io/@jwlee_dev/JavaScript-%EB%B9%84%EB%8F%99%EA%B8%B0-%ED%9D%90%EB%A6%84%EC%9D%80-%ED%95%A8%EC%88%98-%EC%95%88%EC%97%90%EC%84%9C</link>
            <guid>https://velog.io/@jwlee_dev/JavaScript-%EB%B9%84%EB%8F%99%EA%B8%B0-%ED%9D%90%EB%A6%84%EC%9D%80-%ED%95%A8%EC%88%98-%EC%95%88%EC%97%90%EC%84%9C</guid>
            <pubDate>Sun, 15 Jan 2023 10:28:20 GMT</pubDate>
            <description><![CDATA[<pre><code>let manifestDetailInfoList = [];

        await (async () =&gt; {
            const ret = assetIdAndSha256Names.map((assetIdAndSha256Name) =&gt; {
                const assetIds = assetIdAndSha256Name.assetIds;
                const manifestDetail = assetIds.map(async (assetId) =&gt; await fetchManifestDetail(token, assetId));

                manifestDetail.map((e) =&gt; {
                    console.log(e.then(e =&gt; e));
                })

                manifestDetailInfoList = [...manifestDetailInfoList, ...manifestDetail];
                return null;
            });
        })();</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[React 프로젝트 Nginx 설정 ]]></title>
            <link>https://velog.io/@jwlee_dev/React-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-Nginx-%EC%84%A4%EC%A0%95</link>
            <guid>https://velog.io/@jwlee_dev/React-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-Nginx-%EC%84%A4%EC%A0%95</guid>
            <pubDate>Wed, 04 Jan 2023 05:40:06 GMT</pubDate>
            <description><![CDATA[<p>React 프로젝트를 Nginx서버에 배포하면서 환경내에서 발생한 문제점들에 대해 정리하고자 합니다.</p>
<ol>
<li>요청 url 설정<ul>
<li>Nginx 상에서 HTTP 요청을 할 때 기본적으로 해당 Nginx 서버의 IP 주소(혹은 도메인 주소)가 기존의 URL의 앞단에 덮어 써지는 것을 확인하였습니다. 따라서 개발 환경에서 요청하는 경우와 배포환경에서 요청하는 방식이 달라야했습니다. 프로젝트에서 주로 사용되는 REST API 주소는 배포환경일 때는 IP주소를 앞부분에 넣지 않고 요청을하고 개발 환경일 때는 IP주소를 넣고 요청하는 하드코딩으로 해결하였습니다.<ul>
<li>3rd party API 요청
jira 이슈 상태 실시간 현황을 파악하기 위해 Jira 서버에 요청을 보냈습니다. 이때도 Nginx 주소가 덮어써져서 요청이 올바로 진행되지 않았습니다. 따라서 nginx.conf 파일의 server 블록에 아래 내용을 추가해주었습니다.<pre><code>server {
...
location /rest {
  proxy-pass https://jira.xxxx.xx.co.kr; # 사내 지라 서버 주소
}
...
}</code></pre>위 코드는 /rest로 시작하는 API요청이 왔을 때, 목적지 Origin을 proxy-pass 값으로 하겠다는 의미입니다.</li>
</ul>
</li>
</ul>
</li>
</ol>
<p><strong>브라우저(url: nginx주소/path) -&gt; Nginx(url: <a href="https://jira.xxx.xx.co.kr">https://jira.xxx.xx.co.kr</a>) -&gt; Jira 서버</strong> 순서로 요청이 진행 됩니다.</p>
<ol start="2">
<li>Nginx 환경에서 SPA 에플리케이션 새로고침 시 404 Error Fallback UI 설정
Nginx에 React 프로젝트 배포 완료 후, 몇 페이지 타고 들어간 상태에서 새로고침 시, 404 Error가 발생하는 문제가 생겼습니다. 이 문제는 History API와 연관이 있었습니다. React 웹 앱에서의 React-Router는 History를 사용해 (가짜)라우팅 처리를 하는 반면, Nginx 서버에서는 (가짜)라우팅 처리된 것이 진짜인줄 착각하고 발생시키는 에러였습니다. 따라서 nginx.conf 파일에서 알 수 없는 url로 요청이 왔을 땐 초기화면인 index.html로 반환하도록 설정 값을 수정하여 해결하였습니다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[Prettier 설정 방법]]></title>
            <link>https://velog.io/@jwlee_dev/Prettier-%EC%84%A4%EC%A0%95-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@jwlee_dev/Prettier-%EC%84%A4%EC%A0%95-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Wed, 28 Dec 2022 12:00:56 GMT</pubDate>
            <description><![CDATA[<ol>
<li>npm run prettier  명령어로 prettier를 프로젝트에 설치합니다.</li>
<li>command + p 입력 후 settings 검색
<img src="https://velog.velcdn.com/images/jwlee_dev/post/553d4bb5-cb45-49b9-be6a-f0a6c46a162c/image.png" alt="">
settings.json에 아래 내용을 겹치면 수정/ 없으면 추가합니다.<pre><code>&quot;prettier.configPath&quot;: &quot;.prettierrc.js&quot;,
&quot;[jsonc]&quot;: {
 &quot;editor.defaultFormatter&quot;: &quot;esbenp.prettier-vscode&quot;
},
&quot;[javascript]&quot;: {
 &quot;editor.formatOnSave&quot;: true,
 &quot;editor.defaultFormatter&quot;: &quot;esbenp.prettier-vscode&quot;
},
&quot;editor.defaultFormatter&quot;: &quot;esbenp.prettier-vscode&quot;,
&quot;editor.formatOnSave&quot;: true
</code></pre></li>
</ol>
<pre><code>![](https://velog.velcdn.com/images/jwlee_dev/post/0a75ddfe-7bd1-49a3-b56f-e0104dcac72a/image.png)

3. Code &gt; Preferences &gt; settings에 들어가서 Default Formatter로 검색합니다. 그리고 콤보박스에서 Prettier - Code formatter를 선택합니다.
![](https://velog.velcdn.com/images/jwlee_dev/post/6fb919f9-5d1f-40e8-9dc1-d59c3d81498b/image.png)

4. Format On Save를 검색하여 체크박스에 체크합니다.
![](https://velog.velcdn.com/images/jwlee_dev/post/a7074f13-e44b-4a55-903f-c8d0b8df52dd/image.png)

5. root 경로의 prettierrc.js 파일에 다음과 같은 명령어를 입력합니다. </code></pre><p>module.exports = {</p>
<pre><code>printWidth: 80,


tabWidth: 2,


useTabs: true,


semi: true,


singleQuote: true,


jsxSingleQuote: true,


trailingComma: &#39;all&#39;,


jsxBracketSameLine: true,

bracketSpacing: true,</code></pre><p>};</p>
<p>```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[브라우저 History API]]></title>
            <link>https://velog.io/@jwlee_dev/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-History-API</link>
            <guid>https://velog.io/@jwlee_dev/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-History-API</guid>
            <pubDate>Thu, 22 Dec 2022 01:21:40 GMT</pubDate>
            <description><![CDATA[<h2 id="history-api란">History API란?</h2>
<h3 id="history-객체는-브라우저-내장-객체로-spa-구현에-있어서-필수적인-api입니다-spa는-브라우저에서-페이지를-새로-업로드-하지-않고도-history-객체의-url-정보를-가지고-화면에-렌더링합니다-mpa는-페이지-전환을-위해서-새로운-웹-페이지-리소스html-파일-등가-필요하였지만-spa는-이러한-방식으로-초기-한-번의-리소스-요청만으로도-웹-에플리케이션-구현이-가능하도록-설계되었습니다">History 객체는 브라우저 내장 객체로, SPA 구현에 있어서 필수적인 API입니다. SPA는 브라우저에서 페이지를 새로 업로드 하지 않고도, History 객체의 url 정보를 가지고 화면에 렌더링합니다. MPA는 페이지 전환을 위해서 새로운 웹 페이지 리소스(html 파일 등)가 필요하였지만, SPA는 이러한 방식으로 초기 한 번의 리소스 요청만으로도 웹 에플리케이션 구현이 가능하도록 설계되었습니다.</h3>
<h2 id="history-api-사용법">History API 사용법</h2>
<h3 id="historypushstate">History.pushState()</h3>
<p>pushState 함수는 History의 state 큐에 새로운 url 정보를 추가하고 현재 url도 기존에 추가된 상태로 업데이트합니다. 단, 현재 Origin값이 유지되는 형식에 한해서 추가 되어야 합니다.</p>
<pre><code>const state = { &#39;page_id&#39;: 1, &#39;user_id&#39;: 5 } // history.state에 등록된 값
const title = &#39;&#39; // 상태에 대한 제목..? 대부분 브라우저에서 무시하는 값
const url = &#39;hello-world.html&#39; // 업데이트될 url 정보

history.pushState(state, title, url)</code></pre><h3 id="historyreplacestate">History.replaceState()</h3>
<h4 id="replacestate-함수는-history의-state-큐에서-pop한-뒤-새로운-url-정보를-push하고-현재-url도-업데이트합니다-단-현재-origin값이-유지되는-형식에-한해서-추가-되어야-합니다">replaceState 함수는 History의 state 큐에서 pop한 뒤, 새로운 url 정보를 push하고 현재 url도 업데이트합니다. 단, 현재 Origin값이 유지되는 형식에 한해서 추가 되어야 합니다.</h4>
<pre><code>history.replaceState(null, &#39;&#39;, &#39;bar2.html&#39;);  // pop하고 bar2.html을 url 정보로 대신합니다.
</code></pre><h3 id="사용-사례">사용 사례</h3>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;Document&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div id=&quot;container&quot;&gt;&lt;/div&gt;
    &lt;a class=&quot;LinkItem&quot; href=&quot;/product-list&quot;&gt;product list&lt;/a&gt;
    &lt;a class=&quot;LinkItem&quot; href=&quot;/article-list&quot;&gt;article list&lt;/a&gt;
    &lt;script&gt;
        const route = () =&gt; {
            const { pathname } = window.location;
            const $container = document.querySelector(&#39;#container&#39;);
            console.log(pathname);
            if(pathname === &#39;/&#39;) {
                $container.innerHTML = `&lt;h1&gt;Home&lt;/h1&gt;`
            }else if(pathname === &#39;/product-list&#39;) {
                $container.innerHTML = `&lt;h1&gt;상품 목록&lt;/h1&gt;`
            }else if(pathname === &#39;/article-list&#39;) {
                $container.innerHTML = `&lt;h1&gt;게시글 목록&lt;/h1&gt;`
            }
        }   

        window.addEventListener(&#39;click&#39;, e =&gt; {
            if(e.target.matches(&#39;.LinkItem&#39;)) {
                e.preventDefault();
                const { href } = e.target;
                window.history.pushState(null, null, href);
                route();
            }
        })

        route()
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[소켓(Socket)과 HTTP]]></title>
            <link>https://velog.io/@jwlee_dev/%EC%86%8C%EC%BC%93Socket%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@jwlee_dev/%EC%86%8C%EC%BC%93Socket%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Sun, 18 Dec 2022 07:21:22 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/jwlee_dev/post/4b0f8b21-e3cb-4a99-9a05-3be9d6771e25/image.png" alt=""></p>
<h2 id="1-소켓socket이란">1. 소켓(Socket)이란?</h2>
<ul>
<li><h3 id="소켓은-운영체제에서-제공하는-네트워크-프로그래밍-인터페이스입니다-따라서-응용-프로그램은-네트워크-통신을-위해-소켓을-사용해도-되고-안-해도-됩니다-하지만-소켓을-사용할-경우-개발자는-tcp-udp-같은-프로토콜-제어가-가능합니다-또한-소켓-프로그래밍은-소켓을-사용해-tcpip-bluetooth-irda와-같은-통신-프로토콜을-이용해서-sw를-개발하는-것을-의미합니다">소켓은 운영체제에서 제공하는 네트워크 프로그래밍 인터페이스입니다. 따라서 응용 프로그램은 네트워크 통신을 위해 소켓을 사용해도 되고, 안 해도 됩니다. 하지만 소켓을 사용할 경우, 개발자는 TCP, UDP 같은 프로토콜 제어가 가능합니다. 또한 소켓 프로그래밍은 소켓을 사용해 TCP/IP, Bluetooth, IrDA와 같은 통신 프로토콜을 이용해서, SW를 개발하는 것을 의미합니다.</h3>
</li>
</ul>
<h2 id="2-http와-socket">2. HTTP와 Socket</h2>
<h3 id="2-1-http">2-1) HTTP</h3>
<ul>
<li><h3 id="http는-웹-개발웹-기반-응용-프로그램에서-주로-사용되는-네트워크-통신-프로토콜입니다-http의-주된-특징은-stateless입니다-즉-응용-레이어에-속한-프론트엔드-백엔드-프로그램은-http으로-통신을-하고-한-번의-상호간의-통신이-진행-됐더라도-상대방에-대한-정보를-다음-통신에-활용하지-않습니다-또한-http-통신은-한-번-이상의-클라이언트로-부터-요청이-선행되어야-통신이-가능한-구조입니다-http는-tcp-sctp와-같은-안정적인-연결-지향-프로토콜-위에서-실행될-수-있습니다-클라이언트가-서버에-http-요청을-보내면-클라이언트와-서버-사이에-tcp-연결이-열리고-응답을-받은-후-tcp-연결이-종료됩니다-각-http-요청은-서버에-대한-별도의-tcp-연결을-엽니다-클라이언트가-서버에-10개의-요청을-보내면-10개의-개별-tcp-연결이-열립니다">HTTP는 웹 개발(웹 기반 응용 프로그램)에서 주로 사용되는 네트워크 통신 프로토콜입니다. HTTP의 주된 특징은 Stateless입니다. 즉, 응용 레이어에 속한 프론트엔드, 백엔드 프로그램은 HTTP으로 통신을 하고, 한 번의 상호간의 통신이 진행 됐더라도 상대방에 대한 정보를 다음 통신에 활용하지 않습니다. 또한 HTTP 통신은 한 번 이상의 클라이언트로 부터 요청이 선행되어야 통신이 가능한 구조입니다. HTTP는 TCP, SCTP와 같은 안정적인 연결 지향 프로토콜 위에서 실행될 수 있습니다. 클라이언트가 서버에 HTTP 요청을 보내면 클라이언트와 서버 사이에 TCP 연결이 열리고 응답을 받은 후 TCP 연결이 종료됩니다. 각 HTTP 요청은 서버에 대한 별도의 TCP 연결을 엽니다. 클라이언트가 서버에 10개의 요청을 보내면 10개의 개별 TCP 연결이 열립니다.</h3>
</li>
</ul>
<h3 id="2-2-socket">2-2) Socket</h3>
<ul>
<li><h3 id="소켓은-tcpip기반으로-동작하지만-브라우저-http-등에-제한되지-않습니다-운영체제-상에서-다양한-형태로-통신을-구현할-수-있습니다-따라서-동영상-스트리밍-게임-서비스-등-클라이언트와-서버간-실시간-통신이-필요한-서비스에서-주로-사용됩니다">소켓은 TCP/IP기반으로 동작하지만 브라우저, HTTP 등에 제한되지 않습니다. 운영체제 상에서 다양한 형태로 통신을 구현할 수 있습니다. 따라서 동영상 스트리밍, 게임 서비스 등 클라이언트와 서버간 실시간 통신이 필요한 서비스에서 주로 사용됩니다.</h3>
</li>
</ul>
<h3 id="2-3-stateful-vs-stateless">2-3) Stateful vs Stateless</h3>
<ul>
<li><h3 id="흔히-socket은-stateful하고-http는-stateless하다고-합니다-그런데-socket-http-대부분-tcp-기반에서-작동하는데-그렇다면-tcp는-http-요청일-때-연결마다-맺고-끊음을-반복하고-socket-요청일-때는-연결을-유지하는-것일까요-정답은-아니다-입니다-http는-응용-레이어이고-전송-레이어인-tcp와는-독립적이기-때문에-서로-영향을-주고-받지-않습니다-따라서-http는-응용-레이어에-속하고-단지-요청과-응답을-전송-레이어에-보내는-역할만-하기-때문에-stateless하다고-하는-것입니다-socket은-원래-os에서-제공하는-네트워크-인터페이스이기-때문에-통신-자체를-수행하지-않고-socket-통신이라-함은-os에서-제공하는-socket-데이터-및-api를-사용해서-클라이언트와-서버의-연결이-지속적으로-이어지도록-하는-통신-행위를-의미합니다">흔히 Socket은 Stateful하고 HTTP는 Stateless하다고 합니다. 그런데 Socket, HTTP 대부분 TCP 기반에서 작동하는데 그렇다면 TCP는 HTTP 요청일 때 연결마다 맺고 끊음을 반복하고 Socket 요청일 때는 연결을 유지하는 것일까요? 정답은 아니다 입니다. HTTP는 응용 레이어이고 전송 레이어인 TCP와는 독립적이기 때문에 서로 영향을 주고 받지 않습니다. 따라서 HTTP는 응용 레이어에 속하고 단지 요청과 응답을 전송 레이어에 보내는 역할만 하기 때문에 Stateless하다고 하는 것입니다. Socket은 원래 OS에서 제공하는 네트워크 인터페이스이기 때문에 통신 자체를 수행하지 않고, Socket 통신이라 함은 OS에서 제공하는 Socket 데이터 및 API를 사용해서 클라이언트와 서버의 연결이 지속적으로 이어지도록 하는 통신 행위를 의미합니다.</h3>
</li>
</ul>
<h2 id="3-websocket은-무엇일까">3. WebSocket은 무엇일까?</h2>
<ul>
<li><h3 id="websocket은-응용-레이어에서-http를-사용하지-않고-socket을-직접-핸들링하여-브라우저상에서-웹-서버와의-양방향-통신을-위한-프로토콜입니다-html5-이상-버전에서-호환되며-ws-wss로-시작하는-양방향-상태-저장-프로토콜입니다-한-번-연결을-맺게-되면-클라이언트와-서버-간의-연결을-시작할-때마다-클라이언트-서버는-핸드셰이크를-만들고-새로운-연결과-이-연결을-만들기로-결정합니다-연결이-설정되고-활성-상태이면-종료될-때까지-동일한-연결-채널을-사용하여-통신이-수행됩니다">WebSocket은 응용 레이어에서 HTTP를 사용하지 않고 Socket을 직접 핸들링하여 브라우저상에서 웹 서버와의 양방향 통신을 위한 프로토콜입니다. html5 이상 버전에서 호환되며, ws://, wss://로 시작하는 양방향 상태 저장 프로토콜입니다. 한 번 연결을 맺게 되면 클라이언트와 서버 간의 연결을 시작할 때마다 클라이언트-서버는 핸드셰이크를 만들고 새로운 연결과 이 연결을 만들기로 결정합니다. 연결이 설정되고 활성 상태이면 종료될 때까지 동일한 연결 채널을 사용하여 통신이 수행됩니다.</h3>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Copilot 사용 리뷰]]></title>
            <link>https://velog.io/@jwlee_dev/Copilot-%EC%82%AC%EC%9A%A9-%EB%A6%AC%EB%B7%B0</link>
            <guid>https://velog.io/@jwlee_dev/Copilot-%EC%82%AC%EC%9A%A9-%EB%A6%AC%EB%B7%B0</guid>
            <pubDate>Wed, 30 Nov 2022 04:08:00 GMT</pubDate>
            <description><![CDATA[<p><a href="https://jwleedev.tistory.com/2">https://jwleedev.tistory.com/2</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[hosts 파일과 DNS]]></title>
            <link>https://velog.io/@jwlee_dev/hosts-%ED%8C%8C%EC%9D%BC%EA%B3%BC-DNS</link>
            <guid>https://velog.io/@jwlee_dev/hosts-%ED%8C%8C%EC%9D%BC%EA%B3%BC-DNS</guid>
            <pubDate>Fri, 10 Jun 2022 05:32:18 GMT</pubDate>
            <description><![CDATA[<p>브라우저에서 URL 입력 요청 시, PC에서 DNS서버에 요청을 보내기 전에 hosts 파일을 read하여 도메인 주소에 대한 매핑된 ip주소가 있으면, DNS 요청을 하지 않고 곧 바로 해당 ip 주소로 요청을 합니다.</p>
<p>하지만 hosts파일에 <a href="http://www.google.com">www.google.com</a> 과 같은 도메인에 해커 ip 주소를 매핑 해놓으면 사용자가 로그인 할 경우 개인정보 탈취와 과련된 위험이 있습니다.</p>
]]></description>
        </item>
    </channel>
</rss>