<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ni_market_dev.log</title>
        <link>https://velog.io/</link>
        <description>엔아이 마케팅 개발팀입니다</description>
        <lastBuildDate>Wed, 04 Oct 2023 05:20:33 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>ni_market_dev.log</title>
            <url>https://velog.velcdn.com/images/ni_market_dev/profile/ddf75103-d53b-48b3-bf6d-8f4eab1a6337/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ni_market_dev.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ni_market_dev" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[프로젝트 디렉터리 구조 규칙]]></title>
            <link>https://velog.io/@ni_market_dev/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%94%94%EB%A0%89%ED%84%B0%EB%A6%AC-%EA%B5%AC%EC%A1%B0-%EA%B7%9C%EC%B9%99</link>
            <guid>https://velog.io/@ni_market_dev/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%94%94%EB%A0%89%ED%84%B0%EB%A6%AC-%EA%B5%AC%EC%A1%B0-%EA%B7%9C%EC%B9%99</guid>
            <pubDate>Wed, 04 Oct 2023 05:20:33 GMT</pubDate>
            <description><![CDATA[<p>프로젝트를 진행하려면 폴더 구조를 잡는 것은 필수이고 기본적인 사항입니다. 종류 별로 기본적인 폴더 구조를 잡는 방법에 대해 간략하게 정리해 보겠습니다.</p>
<h3 id="1-react-디렉터리-구조">1. react 디렉터리 구조</h3>
<pre><code class="language-bash">my-app/
│
├── public/                # 정적 파일들을 저장합니다.
│   ├── index.html         # 메인 HTML 파일입니다.
│   └── favicon.ico        # 웹사이트의 파비콘 아이콘입니다.
│
├── src/                   # 소스 코드를 저장하는 디렉터리입니다.
│   ├── components/        # 재사용 가능한 UI 컴포넌트들을 저장합니다.
│   │   ├── Layout/        # 레이아웃과 관련된 컴포넌트들입니다.
│   │   ├── Button/        # 버튼과 관련된 컴포넌트들입니다.
│   │   ├── Form/          # 폼과 관련된 컴포넌트들입니다.
│   │   ├── ListItem/      # 리스트 아이템과 관련된 컴포넌트들입니다.
│   │   └── Popup/         # 팝업과 관련된 컴포넌트들입니다.
│   │
│   ├── pages/             # 페이지 컴포넌트들을 저장합니다.
│   │
│   ├── services/          # API 호출이나 외부 서비스 로직을 저장합니다.
│   │
│   ├── contexts/          # React context를 사용한 전역 상태 관리 로직을 저장합니다.
│   │
│   ├── assets/            # 이미지, 폰트 등의 정적 리소스를 저장합니다.
│   │
│   ├── styles/            # SCSS 스타일 파일들을 저장합니다.
│   │
│   ├── utils/             # 유틸리티 함수를 저장합니다.
│   │
│   │
│   ├── mocks/             # 가짜 API 응답이나 테스트 데이터를 저장합니다.
│   │   └── users.js       # 사용자 데이터의 목업입니다.
│   │
│   ├── tests/             # 테스트 코드를 저장합니다.
│   │
│   ├── index.js           # 애플리케이션의 엔트리 포인트입니다.
│   └── App.js             # 메인 App 컴포넌트입니다.
│
├── .storybook/             # Storybook 설정 파일을 저장하는 디렉터리입니다.
│   ├── main.js             # Storybook의 기본 설정 파일입니다.
│   └── preview.js          # 컴포넌트 미리보기를 커스터마이징하는 파일입니다.
│
├── stories/                # Storybook 스토리 파일을 저장하는 디렉터리입니다.
│   ├── Button.stories.js   # Button 컴포넌트의 스토리 파일입니다.
│   └── ...
│
├── package.json           # 프로젝트의 의존성과 스크립트를 정의합니다.
├── README.md              # 프로젝트에 대한 설명을 담은 README 파일입니다.
└── ...</code></pre>
<h3 id="2-express-디렉터리-구조">2. express 디렉터리 구조</h3>
<pre><code class="language-bash">my-express-app/
│
├── routes/                 # 라우터 파일들을 저장합니다.
│   ├── index.js            # 기본 라우트를 정의합니다.
│   └── users.js            # 사용자 관련 라우트를 정의합니다.
│
├── controllers/            # 컨트롤러를 저장합니다.
│   ├── indexController.js  # &#39;index&#39; 경로의 컨트롤러입니다.
│   └── userController.js   # &#39;user&#39; 경로의 컨트롤러입니다.
│
├── services/               # 서비스 로직을 저장합니다.
│   └── userService.js      # 사용자 관련 서비스 로직입니다.
│
├── models/                 # 데이터 모델 파일들을 저장합니다.
│
├── utils/                  # 유틸리티 함수를 저장합니다.
│   └── helpers.js          # 다양한 유틸리티 함수를 포함합니다.
│
├── middleware/             # 미들웨어 파일들을 저장합니다.
│
├── tests/                  # 테스트 코드를 저장합니다.
│   ├── unit/               # 유닛 테스트 코드를 저장합니다.
│   └── integration/        # 통합 테스트 코드를 저장합니다.
│
├── docs/                   # 문서화 관련 파일들을 저장합니다.
│   ├── api/                # API 문서를 저장합니다.
│   └── setup.md            # 개발 환경 설정 문서입니다.
│
├── app.js                  # 앱 설정과 미들웨어를 정의합니다.
│
├── package.json            # 프로젝트의 의존성과 스크립트를 정의합니다.
│
└── README.md               # 프로젝트에 대한 설명을 담은 README 파일입니다.</code></pre>
<h3 id="3-nest-디렉터리-구조">3. nest 디렉터리 구조</h3>
<pre><code class="language-bash">src/
|-- app.controller.ts             # 기본 컨트롤러 파일
|-- app.controller.spec.ts        # 기본 컨트롤러 테스트 파일
|-- app.module.ts                 # 기본 모듈 파일
|-- app.service.ts                # 기본 서비스 파일
|-- app.service.spec.ts           # 기본 서비스 테스트 파일
|-- main.ts                       # 애플리케이션의 엔트리 포인트
|-- common/                       # 공통 코드 폴더
|   |-- interfaces/               # 공통 인터페이스
|   |   |-- user.interface.ts
|   |   |-- product.interface.ts
|-- modules/                      # 모듈 폴더
|   |-- users/                    
|   |   |-- dto/                  
|   |   |   |-- create-user.dto.ts
|   |   |-- user-validator.ts     # 사용자 관련 컴포넌트(서비스나 공통 로직)
|   |   |-- user-validator.spec.ts # 컴포넌트 테스트 파일
|   |   |-- users.controller.ts  
|   |   |-- users.controller.spec.ts
|   |   |-- users.module.ts      
|   |   |-- users.service.ts     
|   |   |-- users.service.spec.ts 
|   |-- products/                 
|   |   |-- dto/                  
|   |   |   |-- create-product.dto.ts
|   |   |-- product-validator.ts   # 제품 관련 컴포넌트(서비스나 공통 로직)
|   |   |-- product-validator.spec.ts # 컴포넌트 테스트 파일
|   |   |-- products.controller.ts
|   |   |-- products.controller.spec.ts
|   |   |-- products.module.ts  
|   |   |-- products.service.ts 
|   |   |-- products.service.spec.ts  
|-- middlewares/                  # 미들웨어 폴더
|   |-- logger.middleware.ts
|   |-- logger.middleware.spec.ts # 미들웨어 테스트 파일
|-- utils/                        # 유틸리티 폴더
    |-- helpers.ts
    |-- helpers.spec.ts           # 유틸리티 테스트 파일</code></pre>
<h3 id="4-next-디렉터리-구조v12">4. next 디렉터리 구조(v12)</h3>
<pre><code class="language-bash">my-next-app/
│
├── .next/                     # 빌드 생성 디렉터리
│   ├── cache/
│   └── ...
│
├── api-lib/                   # API 호출과 관련된 로직 라이브러리
│   ├── userApi.js
│   └── postApi.js
│
├── assets/                    # 다양한 미디어 자원을 저장하는 디렉터리
│   ├── images/
│   └── icons/
│
├── docs/                      # 필요한 참고문서를 저장하는 디렉터리
│   ├── Frontend/
│   ├── Backend/
│   └── Design/
│
├── components/                # 재사용 가능한 UI 컴포넌트를 저장하는 디렉터리
│   ├── Header.js
│   ├── Footer.js
│   └── ...
│
├── hooks/                     # 커스텀훅을 저장하는 디렉터리
│   ├── useTimeFormat.js
│   └── ...
│
├── lib/                       # 외부 라이브러리 또는 프로젝트 내부에서 사용하는 유틸리티 함수
│   ├── util.js
│   └── helper.js
│
├── page-components/           # 특정 페이지에서만 사용되는 컴포넌트를 저장하는 디렉터리
│   ├── HomePageComponents/
│   └── AboutPageComponents/
│
├── pages/                     # 페이지 컴포넌트 및 API 라우트를 저장하는 디렉터리
│   ├── _app.js
│   ├── _document.js
│   ├── index.js
│   └── api/                   # API를 저장하는 디렉터리
│       └── user.js
│
├── styles/                    # scss, 스타일을 저장하는 디렉터리
│   ├── globals.scss
│   ├── Home.module.scss
│   └── ...
│
├── mocks/                     # 더미 객체를 저장하는 디렉터리 (api 연결 전에 테스트)
│   ├── handler.js
│   └── ...
│
├── public/                    # 정적 파일을 저장하는 디렉터리
│   ├── favicon.ico
│   └── logo.png
│
├── package.json               # 프로젝트의 의존성과 스크립트를 정의하는 파일
└── README.md                  # 프로젝트에 대한 정보 및 사용 방법을 설명하는 파일</code></pre>
<hr>
<p>이런 식으로 프로젝트별로 디렉터리 구조를 나눌 수 있고 보편적으로 많이 사용하는 구조도 존재합니다.
<img src="https://velog.velcdn.com/images/ni_market_dev/post/d87c2c6f-02ba-48f4-b140-a7921ddb6a71/image.png" alt="">
<img src="https://velog.velcdn.com/images/ni_market_dev/post/f5a1b16a-3c84-4216-9204-42f4f04fc29f/image.png" alt=""></p>
<p>프로젝트마다 다양한 방식으로 컴포넌트를 설계합니다. 회사에서 좀 더 큰 프로젝트를 할 때 팀원들 간 컴포넌트, 아키텍처, 컨벤션을 설정하여 프로젝트에 알맞은 구조를 설계하는 방식이 제일 좋을 것 같습니다. 
이렇게 컴포넌트 구조에는 정답이 없다 보니, 여러 가지 패턴들이 많습니다. 그래서 다양한 문서를 참고해서 자신에게 맞는 방법으로 설계해 보는 연습이 필요합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[백엔드 배포 시 DB 연결하기]]></title>
            <link>https://velog.io/@ni_market_dev/%EB%B0%B1%EC%97%94%EB%93%9C-%EB%B0%B0%ED%8F%AC-%EC%8B%9C-DB-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ni_market_dev/%EB%B0%B1%EC%97%94%EB%93%9C-%EB%B0%B0%ED%8F%AC-%EC%8B%9C-DB-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 04 Oct 2023 05:08:40 GMT</pubDate>
            <description><![CDATA[<p>백앤드 배포 시 express, nest, next에서는 api를 만들어서 사용해야 합니다. 개발 서버에서 docker로 띄워져 있는 DB에 연결하는 방법을 알아보겠습니다.</p>
<h3 id="1-express-db-연결">1. express DB 연결</h3>
<ol>
<li><p>mongoose 추가(DB 커넥트 모듈 추가)</p>
<pre><code class="language-bash">npm install mongoose</code></pre>
</li>
<li><p>코드 추가</p>
<pre><code class="language-bash">const mongoose = require(&quot;mongoose&quot;);
</code></pre>
</li>
</ol>
<p>require(&quot;dotenv&quot;).config();</p>
<p>mongoose.connect(<code>${process.env.DATABASE_URL}</code>, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});</p>
<p>const db = mongoose.connection;</p>
<p>db.on(&quot;error&quot;, console.error.bind(console, &quot;MongoDB connection error:&quot;));
db.once(&quot;open&quot;, function () {
  console.log(&quot;Connected to MongoDB&quot;);
});</p>
<p>app.get(&quot;/&quot;, (req, res) =&gt; {
  res.send(<code>자동 배포 확인</code>);
});</p>
<pre><code>
3. DB_URL 시크릿 추가
```bash
docker inspect -f &#39;{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}&#39; mongodb</code></pre><p>DATABASE_URL = mongodb://172.17.0.2:27017/test
<img src="https://velog.velcdn.com/images/ni_market_dev/post/18531a0c-2a71-4b14-8ee4-04756331dade/image.png" alt=""></p>
<ol start="4">
<li>배포 확인 </li>
</ol>
<hr>
<h3 id="2-nest-db-연결">2. nest DB 연결</h3>
<ol>
<li><p>mongodb 모듈 추가(DB 커넥트 모듈 추가)</p>
<pre><code class="language-bash">npm install @nestjs/mongoose mongoose</code></pre>
</li>
<li><p>코드 추가</p>
<pre><code class="language-bash">import { Module } from &#39;@nestjs/common&#39;;
import { AppController } from &#39;./app.controller&#39;;
import { AppService } from &#39;./app.service&#39;;
import { ConfigModule, ConfigService } from &#39;@nestjs/config&#39;;
import { MongooseModule } from &#39;@nestjs/mongoose&#39;;
@Module({
imports: [
 ConfigModule.forRoot(),
 MongooseModule.forRootAsync({
   imports: [ConfigModule],
   useFactory: async (configService: ConfigService) =&gt; ({
     uri: configService.get&lt;string&gt;(&#39;DATABASE_URL&#39;),
     useNewUrlParser: true,
     useUnifiedTopology: true,
   }),
   inject: [ConfigService],
 }),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}</code></pre>
</li>
<li><p>DB_URL 시크릿 추가
<img src="https://velog.velcdn.com/images/ni_market_dev/post/2c49852b-a6a4-493d-aba2-f1d3ff00ae9c/image.png" alt=""></p>
</li>
</ol>
<ol start="4">
<li>배포 확인</li>
</ol>
<hr>
<h3 id="3-nextjs-api-db-연결">3. Nextjs api DB 연결</h3>
<ol>
<li><p>코드 추가</p>
<pre><code class="language-bash">const router = useRouter();
async function addMeetupHandler(enteredMeetupData) {
const response = await fetch(&quot;/api/new-meetup&quot;,{            // 1.
 method:&quot;POST&quot;,
 body: JSON.stringify(enteredMeetupData),
 headers:{
   &quot;Content-Type&quot;:&quot;application/json&quot;
 }
});
const data = await response.json();
router.replace(&quot;/&quot;);
}
return(
&lt;NewMeetupForm onAddMeetup={addMeetupHandler}/&gt;            // 2.
)</code></pre>
</li>
<li><p>DB_URL 시크릿 추가
<img src="https://velog.velcdn.com/images/ni_market_dev/post/b7729831-de33-48f2-b668-55edddcd241b/image.png" alt=""></p>
</li>
<li><p>배포 확인</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[Github 환경 변수 세팅 및 env 파일 읽어오기]]></title>
            <link>https://velog.io/@ni_market_dev/Github-%ED%99%98%EA%B2%BD-%EB%B3%80%EC%88%98-%EC%84%B8%ED%8C%85-%EB%B0%8F-env-%ED%8C%8C%EC%9D%BC-%EC%9D%BD%EC%96%B4%EC%98%A4%EA%B8%B0</link>
            <guid>https://velog.io/@ni_market_dev/Github-%ED%99%98%EA%B2%BD-%EB%B3%80%EC%88%98-%EC%84%B8%ED%8C%85-%EB%B0%8F-env-%ED%8C%8C%EC%9D%BC-%EC%9D%BD%EC%96%B4%EC%98%A4%EA%B8%B0</guid>
            <pubDate>Wed, 04 Oct 2023 04:49:35 GMT</pubDate>
            <description><![CDATA[<p>GitHub에서 환경 변수(environment variables)를 설정하는 주된 이유는 보안과 설정의 편리성입니다. 환경 변수를 이용함으로써 코드 내에 특정 값을 하드코딩하는 대신, 외부에서 이 값들을 조정하고 관리할 수 있습니다. 다음은 환경 변수를 설정하는 주요한 이유에 대해서 알아보겠습니다.</p>
<h4 id="1-보안">1. 보안</h4>
<p>비밀번호 및 액세스 키: 코드 내에 직접 비밀번호나 API 키 같은 민감한 정보를 작성하는 것은 큰 보안 위험을 가지고 있습니다. 이 정보가 외부에 노출되면, 악의적인 사용자들이 그 정보를 이용해 손상을 줄 수 있습니다. 환경 변수를 사용하면 이러한 중요한 정보를 코드 밖으로 분리시키며, 코드 자체는 공개적으로 공유하더라도 민감한 데이터는 보호할 수 있습니다.</p>
<h4 id="2-설정의-일관성과-유연성">2. 설정의 일관성과 유연성</h4>
<p>다양한 환경에서의 사용: 개발, 스테이징, 및 프로덕션과 같이 다양한 환경에서 동작하는 애플리케이션의 경우, 각 환경마다 설정값이 다를 수 있습니다. 환경 변수를 사용함으로써 동일한 코드베이스를 유지하면서, 각 환경의 특성에 맞는 설정값을 적용할 수 있습니다.</p>
<h4 id="3-코드의-재사용">3. 코드의 재사용</h4>
<p>코드의 재사용성 증가: 환경 변수를 통해 설정값을 외부에서 주입받을 수 있게 만듦으로서, 코드는 좀 더 범용적으로 사용될 수 있습니다. 즉, 동일한 코드를 다양한 프로젝트나 환경에서 재사용할 수 있으며, 각기 다른 환경 변수 설정으로 다르게 동작하게 할 수 있습니다.</p>
<h4 id="4-유지보수">4. 유지보수</h4>
<p>유지보수의 용이성: 환경 변수를 사용함으로써, 설정값을 변경해야 할 경우 코드 자체를 수정하지 않고 환경 변수만 업데이트하면 됩니다. 이렇게 함으로써 유지보수가 용이해지며, 코드 변경 없이도 설정의 수정이 가능합니다. 
GitHub Actions과 환경 변수 GitHub에서 제공하는 CI/CD 도구인 &quot;GitHub Actions&quot;에서도 환경 변수를 설정하고 사용하는 것은 중요합니다. GitHub Actions의 워크플로우에서 환경 변수를 설정하면, 실행되는 각 작업이나 단계에서 이 변수들을 사용할 수 있게 됩니다. 이는 위에서 언급한 보안, 설정의 일관성, 코드의 재사용, 및 유지보수 측면에서의 이점들을 모두 가져올 수 있습니다.</p>
<p>이러한 장점들로 환경 변수를 설정하는 것이 굉장히 유용하고 생산적인 걸 알 수 있습니다. 다음으로 환경 변수를 설정하는 방법을 알아보겠습니다.</p>
<hr>
<h3 id="github-secrets-설정하기">Github Secrets 설정하기</h3>
<ol>
<li>GitHub 저장소의 &quot;Settings&quot;로 이동합니다.</li>
<li>왼쪽 메뉴에서 &quot;Secrets and variables&quot; 클릭 후 &quot;Actions&quot;을 선택합니다.</li>
<li>&quot;New repository secret&quot; 버튼을 클릭하여 새 시크릿을 추가합니다. 예를 들어, <code>DATABASE_URL</code> 이라는 이름의 시크릿에 데이터베이스 URL을 저장할 수 있습니다.</li>
<li>github actions + watch tower로 개발 환경에 대한 세팅을 확인합니다.</li>
<li>각 환경에 맞게 git secret을 사용 환경 변수에 맞게 읽어와서 적용 되는지 확인합니다.
<img src="https://velog.velcdn.com/images/ni_market_dev/post/584944d0-3ea2-4436-941a-c44cbb004ff9/image.png" alt="">
<img src="https://velog.velcdn.com/images/ni_market_dev/post/6b1be583-334a-4d70-8333-6c0e055e0a0c/image.png" alt=""></li>
</ol>
<hr>
<h3 id="1-reactjs-develop-브런치-secret">1. React.js develop 브런치 secret</h3>
<ol>
<li><p>시크릿 세팅
<img src="https://velog.velcdn.com/images/ni_market_dev/post/5ca16b7f-bdcb-433c-a287-084e475dfbeb/image.png" alt=""></p>
</li>
<li><p>workflow 세팅
```bash</p>
</li>
</ol>
<ul>
<li>name: Create .env file<pre><code>run: |
  echo REACT_APP_DEV_PUBLIC_API_URI=${{ secrets.DEV_PUBLIC_API_URI }} &gt;&gt; .env</code></pre><pre><code></code></pre></li>
</ul>
<ol start="3">
<li>리액트쪽에서 환경 변수
<img src="https://velog.velcdn.com/images/ni_market_dev/post/7e29b584-50c4-413a-afee-79a58a50259d/image.png" alt="">
<img src="https://velog.velcdn.com/images/ni_market_dev/post/cca68177-f1ce-4a5e-9b96-96301ffb894e/image.png" alt=""></li>
</ol>
<hr>
<h3 id="2-nest-js-환경-변수-세팅">2. Nest js 환경 변수 세팅</h3>
<ol>
<li><p>시크릿 세팅
<img src="https://velog.velcdn.com/images/ni_market_dev/post/589d64f5-831d-4add-8b84-2bde14bbb2a2/image.png" alt=""></p>
</li>
<li><p>workflows 세팅
```bash</p>
</li>
</ol>
<ul>
<li>name: Create .env file<pre><code>run: |
  echo DATABASE_URL=${{ secrets.DEV_DATABASE_URL }} &gt;&gt; .env</code></pre><pre><code></code></pre></li>
</ul>
<ol start="3">
<li><p>nestjs config 패키지 설치</p>
<pre><code class="language-bash">npm install @nestjs/config</code></pre>
</li>
<li><p>configModule 추가
<img src="https://velog.velcdn.com/images/ni_market_dev/post/ad3ac1e3-64d8-4d23-9daf-9e325afd7d42/image.png" alt=""></p>
</li>
<li><p>환경 변수 사용하기
<img src="https://velog.velcdn.com/images/ni_market_dev/post/33ac493c-4833-4383-8e5d-caa9bc945c2c/image.png" alt=""></p>
</li>
<li><p>확인
<img src="https://velog.velcdn.com/images/ni_market_dev/post/63e60f3b-2cbe-47e7-88ad-a64cf4014e34/image.png" alt=""></p>
</li>
</ol>
<hr>
<h3 id="3-express-환경-변수-세팅">3. express 환경 변수 세팅</h3>
<ol>
<li><p>시크릿 세팅
<img src="https://velog.velcdn.com/images/ni_market_dev/post/a574f662-3083-4f1e-9290-fb6952c67704/image.png" alt=""></p>
</li>
<li><p>workflow 세팅
```bash</p>
</li>
</ol>
<ul>
<li>name: Create .env file<pre><code>run: |
  echo DATABASE_URL=${{ secrets.DEV_DATABASE_URL }} &gt;&gt; .env</code></pre><pre><code></code></pre></li>
</ul>
<ol start="3">
<li><p>dotenv 설치</p>
<pre><code class="language-bash">npm install dotenv</code></pre>
</li>
<li><p>config 사용</p>
<pre><code class="language-bash">require(&quot;dotenv&quot;).config();
</code></pre>
</li>
</ol>
<p>app.get(&quot;/&quot;, (req, res) =&gt; {
  res.send(<code>자동 배포 확인 ${process.env.DEV_DATABASE_URL}</code>);
});</p>
<pre><code>
5. 확인
![](https://velog.velcdn.com/images/ni_market_dev/post/818ed470-d032-4365-a147-4ffb0c9fe1d6/image.png)

---

### 4. Next js 환경 변수 세팅
1. 시크릿 세팅
![](https://velog.velcdn.com/images/ni_market_dev/post/bf20825a-a317-4c90-ae2f-352ae9a5afa0/image.png)

2. workflow 세팅
```bash
- name: Create .env file
      run: |
        echo REACT_APP_DEV_PUBLIC_API_URI=${{ secrets.DEV_PUBLIC_API_URI }} &gt;&gt; .env</code></pre><ol start="3">
<li>환경 변수 가져오기<pre><code class="language-bash">import Image from &#39;next/image&#39;
</code></pre>
</li>
</ol>
<p>export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <h1>자동 배포 테스트${process.env.API_URL}</h1>
    </main>
  );
}</p>
<pre><code>
4. 확인
![](https://velog.velcdn.com/images/ni_market_dev/post/ed0bdd8f-9a0a-4018-8e1c-fdf3e8873fea/image.png)
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Github actions +watch tower 개발 서버 자동 배포]]></title>
            <link>https://velog.io/@ni_market_dev/%EA%B0%9C%EB%B0%9C-%EC%84%9C%EB%B2%84-%EC%9E%90%EB%8F%99-%EB%B0%B0%ED%8F%AC-%EC%84%B8%ED%8C%85%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@ni_market_dev/%EA%B0%9C%EB%B0%9C-%EC%84%9C%EB%B2%84-%EC%9E%90%EB%8F%99-%EB%B0%B0%ED%8F%AC-%EC%84%B8%ED%8C%85%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Wed, 04 Oct 2023 02:35:55 GMT</pubDate>
            <description><![CDATA[<h3 id="개발-서버-자동배포-세팅하는-방법">개발 서버 자동배포 세팅하는 방법</h3>
<h4 id="개발-서버-자동-배포-세팅을-하기-위해서는-우선">개발 서버 자동 배포 세팅을 하기 위해서는 우선</h4>
<ol>
<li>개발서버 자동 배포를 세팅하기 위해서 watchtower을 세팅합니다.</li>
<li>Github actions를 사용하면서 자동으로 빌드 된 이미지를 docker hub(harbor)에 push 진행합니다.</li>
<li>push 된 이미지를 자동으로 감지해서 자동으로 컨테이너를 업데이트하는 로직을 구축합니다.</li>
</ol>
<h5 id="-사용한-이미지-경로">* 사용한 이미지 경로</h5>
<p><a href="https://containrrr.dev/watchtower/">Watchtower</a></p>
<pre><code class="language-bash">docker run -d \
    --name watchtower \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -e WATCHTOWER_POLL_INTERVAL=300 \
    -e DOCKER_USERNAME=tenxtube \
    -e DOCKER_PASSWORD=72quf6!!22 \
    containrrr/watchtower</code></pre>
<hr>
<h3 id="1-react-cicd">1. react ci/cd</h3>
<ol>
<li><p>리액트 프로젝트에 대한 레퍼지토리를 만듭니다.
<img src="https://velog.velcdn.com/images/ni_market_dev/post/d03e1347-2593-4ca8-a696-f4b6439b65ae/image.png" alt=""></p>
</li>
<li><p>Github actions으로 develop 브랜치에 push가 되었을 때 Github actions에 빌드 해서 docker hub에 올라갈 수 있도록 세팅합니다.
일단 Github 시크릿에 DOCKER_HUB_USERNAME/DOCKER_HUB_PASSWORD를 등록해서 사용합니다.
<img src="https://velog.velcdn.com/images/ni_market_dev/post/3d8582ed-46e4-468e-9161-3978ff2f305b/image.png" alt=""></p>
</li>
<li><p>빌드 테스트
.github\workflows\react_build.yml</p>
<pre><code class="language-yaml">name: React Build Workflow
</code></pre>
</li>
</ol>
<p>on:
  push:
    branches:
      - develop</p>
<p>jobs:
  build:
    runs-on: ubuntu-latest</p>
<pre><code>steps:
- name: Check out code
  uses: actions/checkout@v2

- name: Set up Node.js
  uses: actions/setup-node@v2
  with:
    node-version: &#39;14&#39;  # You can specify your Node.js version here

- name: Install dependencies
  run: npm install

- name: Build
  run: npm run build</code></pre><pre><code>![](https://velog.velcdn.com/images/ni_market_dev/post/245417a1-365b-45ce-9cd1-1d0c1a2470eb/image.png)

4. 빌드 + docker hub에 push 진행
```yaml
name: React Build and Docker Push Workflow

on:
  push:
    branches:
      - develop

jobs:
  build_and_push:
    runs-on: ubuntu-latest

    steps:
    - name: Check out code
      uses: actions/checkout@v2

    - name: Set up Node.js
      uses: actions/setup-node@v2
      with:
        node-version: &#39;16&#39;  # You can specify your Node.js version here

    - name: Install dependencies
      run: npm install

    - name: Build React Project
      run: npm run build

    - name: Login to Docker Hub
      uses: docker/login-action@v1
      with:
        username: ${{ secrets.DOCKER_HUB_USERNAME }}
        password: ${{ secrets.DOCKER_HUB_PASSWORD }}

    - name: Build and push Docker image
      run: |
        docker build -t tenxtube/react-test:develop .
        docker push tenxtube/react-test:develop</code></pre><ol start="5">
<li>docker file 추가<pre><code class="language-yaml"># React Dockerfile
FROM node:16
</code></pre>
</li>
</ol>
<p>WORKDIR /app</p>
<p>COPY package*.json ./</p>
<p>RUN npm install</p>
<p>COPY . .</p>
<p>EXPOSE 3000</p>
<p>CMD [&quot;npm&quot;, &quot;start&quot;]</p>
<pre><code>![](https://velog.velcdn.com/images/ni_market_dev/post/7fa3ee32-3122-4281-833b-c3391c4cf65b/image.png)
```bash
docker run -p 3000:3000 tenxtube:develop -d</code></pre><p><img src="https://velog.velcdn.com/images/ni_market_dev/post/ed3f91c3-1aee-4559-ac0b-394c1d89c067/image.png" alt=""></p>
<ol start="6">
<li>수정 후에 업데이트 했을 때 자동으로 잘 되는지 확인
<img src="https://velog.velcdn.com/images/ni_market_dev/post/fdc93197-8a84-46ae-86ff-82a3c735fa17/image.png" alt="">
<img src="https://velog.velcdn.com/images/ni_market_dev/post/4c18b918-2723-4504-8c52-9e7fd5124401/image.png" alt=""></li>
</ol>
<hr>
<h3 id="2-nest-cicd">2. nest ci/cd</h3>
<pre><code class="language-bash">nest new nest-test</code></pre>
<ol>
<li>nest 프로젝트 main push 합니다.</li>
<li>docker file, workflows 설정합니다.</li>
<li>포트 및 외부 접속 허용합니다.</li>
</ol>
<pre><code class="language-bash">import { NestFactory } from &#39;@nestjs/core&#39;;
import { AppModule } from &#39;./app.module&#39;;

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3001, &#39;0.0.0.0&#39;);
}
bootstrap();</code></pre>
<p><img src="https://velog.velcdn.com/images/ni_market_dev/post/1ca34e18-31b9-4f60-afae-ae6ba55a75e9/image.png" alt="">
<img src="https://velog.velcdn.com/images/ni_market_dev/post/3805300f-bdd3-4cd9-8c25-4ef484e6fa32/image.png" alt=""></p>
<hr>
<h3 id="3-express-cicd">3. express ci/cd</h3>
<ol>
<li>express 프로젝트 main 기본 push 합니다.</li>
<li>docker file, workflows 작성합니다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/ni_market_dev/post/f90662e5-1a5a-47d1-a073-61bf11687e5c/image.png" alt=""></p>
<h4 id="자동-배포-테스트">자동 배포 테스트</h4>
<p><img src="https://velog.velcdn.com/images/ni_market_dev/post/ffece4f7-0b89-415d-a2cc-d545f03b0490/image.png" alt=""></p>
<hr>
<h3 id="4-next-cicd">4. next ci/cd</h3>
<ol>
<li>Next main 브랜치에 기본 push 합니다.</li>
<li>docker file, workflows 작성합니다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/ni_market_dev/post/741ec3ec-57f2-411b-bcb4-b0f50dc0fbf0/image.png" alt=""></p>
<ol start="3">
<li>자동 배포 테스트</li>
</ol>
<p><img src="https://velog.velcdn.com/images/ni_market_dev/post/02690864-cd7e-4632-8223-bf676044028e/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[사용하는 개발 및 배포 전략!]]></title>
            <link>https://velog.io/@ni_market_dev/%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EA%B0%9C%EB%B0%9C-%EB%B0%8F-%EB%B0%B0%ED%8F%AC-%EC%A0%84%EB%9E%B5</link>
            <guid>https://velog.io/@ni_market_dev/%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EA%B0%9C%EB%B0%9C-%EB%B0%8F-%EB%B0%B0%ED%8F%AC-%EC%A0%84%EB%9E%B5</guid>
            <pubDate>Wed, 04 Oct 2023 01:41:23 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ni_market_dev/post/40546b01-a996-49aa-9db6-f4dc69fa0d39/image.png" alt="">
일반적으로 개발을 시작할 때 여러 명의 작업자가 같이 작업을 진행하는 경우가 많습니다. 그럴 경우 작업이 겹치지 않도록 각자의 로컬에서 개발하고 확인 후 Github를 이용해서 작업을 하게 됩니다. 그 순서를 알아보도록 하자!</p>
<p>우선 개발을 하려면, 각자 개발자 PC에 개발 및 테스트 환경이 셋업 되어 있어야 합니다. 각 개발자마다, 설치된 서버 환경을 local 환경이라고 하고 이 local 환경을 구축할 시에 가장 주의해야 할 점은 모든 개발자가 같은 개발 환경을 사용해야 한다는 것입니다. 실제로 많이 일어나는 문제인데, 다른 version은 JVM를 사용하거나, 다른 버전의 Tomcat을 사용하거나 Lang (문자 local 설정)을 서로 다르게 해서, 정작 코드를 합칠 때, local에서 잘 작동했던 코드가 작동하지 않는 경우가 많습니다.</p>
<hr>
<p><img src="https://velog.velcdn.com/images/ni_market_dev/post/e674e65a-95fe-44e4-a6bf-3cc887787127/image.png" alt="">
로컬 개발 환경을 맞추었다면 Github develop 브랜치에 push를 해서 확인을 하고 Github actions에서 이미지 빌드 후 docker hub, habor에 이미지를 push를 합니다. 현재는 public으로 docker hub를 사용하고 있지만 추후에 habor로 변경할 계획입니다.</p>
<hr>
<p><img src="https://velog.velcdn.com/images/ni_market_dev/post/3fb1fe2f-dc47-4231-87bd-d4a96844f729/image.png" alt="">
개발 서버에 push 되어있는 watchtower에서 업데이트된 이미지 감지 및 배포하고 개발 서버에서 확인을 진행 후 develop 브랜치에서 main 브랜치로 merge 후 Github action에서 이미지를 빌드하고 빌드 된 이미지를 ECR에 push 하게 됩니다.</p>
<hr>
<h4 id="배포를-하는-과정에서-무중단-배포를-진행을-알아보면">배포를 하는 과정에서 무중단 배포를 진행을 알아보면</h4>
<pre><code class="language-bash">name: Deploy hyeon9mak assignment
on:
  push:
    branches:
      - master

jobs:
  deploy:
    runs-on: ubuntu-latest

    env:
      AWS_REGION: ap-northeast-2
      ECS_CLUSTER_NAME: backend
      ECR_REPOSITORY_NAME: hyeon9mak-dev
      ECS_CONTAINER_NAME: hyeon9mak-container
      ECS_SERVICE_NAME: hyeon9mak-service-dev
      TASK_DEFINITION_NAME: hyeon9mak-task-dev
      # Github actions 자동배포 과정에서 사용할 환경변수들
      # AWS ECS 콘솔에서 이름이 모두 일치하는지 확인이 필요하다.

    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Configure AWS credentials For Devzone
        uses: aws-actions/configure-aws-credentials@v1
        with:
          # Github Repository Secrets에 값 등록 필요!
          aws-access-key-id: $
          aws-secret-access-key: $
          aws-region: $

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1

      - name: Install JDK 11
        uses: actions/setup-java@v2
        with:
          distribution: &#39;temurin&#39;
          java-version: 11
          cache: &#39;gradle&#39; # https://github.com/actions/setup-java#caching-packages-dependencies

      - name: build gradle
        run: ./gradlew clean build

      - name: Download dd-java-agent
        run: wget -O assignment-api/dd-java-agent.jar https://dtdg.co/latest-java-tracer
        # wget 명령의 -O 옵션을 통해 파일의 
        # 경로 및 이름을 지정하여 datadog agent 다운로드

      - name: Build, tag, and push image to Amazon ECR
        id: build-image
        env:
          ECR_REGISTRY: $
          SERVICE_TAG: . # Dockerfile의 경로
          IMAGE_TAG: $ # Github가 제공하는 SHA 암호화 사용
        run: |
          # Build a docker container and
          # push it to ECR so that it can
          # be deployed to ECS.
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY_NAME:$IMAGE_TAG $SERVICE_TAG
          docker push $ECR_REGISTRY/$ECR_REPOSITORY_NAME:$IMAGE_TAG
          echo &quot;::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY_NAME:$IMAGE_TAG&quot;

      - name: Download Task Definition Template
        run: |
          aws ecs describe-task-definition \
            --task-definition $ \
            --query taskDefinition \
            &gt; task-definition.json

      - name: Fill in the new image ID in the Amazon ECS task definition
        id: task-def
        uses: aws-actions/amazon-ecs-render-task-definition@v1
        with:
          task-definition: task-definition.json
          container-name: $
          image: $

      - name: Deploy Amazon ECS task definition
        uses: aws-actions/amazon-ecs-deploy-task-definition@v1
        with:
          task-definition: $
          service: $
          cluster: $
          wait-for-service-stability: true</code></pre>
<p>AWS 액세스 키와 보안 키의 경우 yml 파일에 노출되기 민감한 정보이므로, Github Secrets를 통해서 관리를 합니다. 애플리케이션 Repository &gt; Settings &gt; Secrets &gt; Actions 메뉴로 접근해서 Repository secret으로 등록합니다.</p>
<p><img src="https://velog.velcdn.com/images/ni_market_dev/post/25eab4c6-f79e-4ce7-8d5b-c861b5438956/image.png" alt="">
해당 키의 값들은 아래 명령을 통해서 확인할 수 있습니다.</p>
<pre><code class="language-bash">$ ~/.aws/credentials

[default]
aws_access_key_id = {액세스 키}
aws_secret_access_key = {보안 키}</code></pre>
<p>애플리케이션 Repository에 자동배포용 yml 파일이 준비되면, 이후 브랜치에 커밋내용이 푸시가 될 때마다 자동으로 ECS 수동배포 과정이 반복됩니다.</p>
<p><img src="https://velog.velcdn.com/images/ni_market_dev/post/761018b2-acc7-4394-a293-187fd1179516/image.png" alt="">
이후 로드밸런서(ALB)를 사용해서 관리를 진행합니다.</p>
<hr>
<h4 id="위-과정들을-요약해-보면-이렇게-정리할-수-있습니다">위 과정들을 요약해 보면 이렇게 정리할 수 있습니다.</h4>
<ol>
<li><p>로컬에서 개발</p>
</li>
<li><p>develop 브랜치에 push</p>
</li>
<li><p>github actions에서 이미지 빌드</p>
</li>
<li><p>docker hub, harbor에 이미지 push</p>
</li>
<li><p>개발 서버에 떠있는 watchtower에서 업데이트된 이미지 감지 및 배포</p>
</li>
<li><p>개발 서버 확인</p>
</li>
<li><p>develop 브랜치에서 main 브랜치로 merge</p>
</li>
<li><p>github actions에서 이미지 빌드</p>
</li>
<li><p>빌드 된 이미지 ECR에 push</p>
</li>
<li><p>무중단 배포를 위한 ECS 서비스 업데이트</p>
<ol>
<li>ECS 클러스터 생성 시 CODE_DEPLOY로 설정</li>
<li>aws codedeploy를 사용하여 블루/그린 배포를 설정</li>
<li>서비스 업데이트를 시작할 때 새 태스크 정의를 사용하여 서비스를 업데이트함</li>
<li>codedeploy는 기존 태스크를 종료하기 전에 새 태스크를 시작하여 무중단 배포를 보장</li>
</ol>
</li>
<li><p>로드밸런서(ALB) 사용</p>
</li>
</ol>
<p>이렇게 현재 사용하고있는 개발 및 배포 전략을 알아봤습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[주식회사 엔아이 개발팀 시작]]></title>
            <link>https://velog.io/@ni_market_dev/%EC%A3%BC%EC%8B%9D%ED%9A%8C%EC%82%AC-%EC%97%94%EC%95%84%EC%9D%B4-%EA%B0%9C%EB%B0%9C%ED%8C%80-%EC%8B%9C%EC%9E%91</link>
            <guid>https://velog.io/@ni_market_dev/%EC%A3%BC%EC%8B%9D%ED%9A%8C%EC%82%AC-%EC%97%94%EC%95%84%EC%9D%B4-%EA%B0%9C%EB%B0%9C%ED%8C%80-%EC%8B%9C%EC%9E%91</guid>
            <pubDate>Tue, 19 Sep 2023 09:38:51 GMT</pubDate>
            <description><![CDATA[<p>서버 관제 2년에 풀스택 개발자 3년차에 스타트업 팀장으로 들어와
개발팀을 처음 꾸리면서 어떤 기술을 사용하고 어떻게 개발을 진행해 나갈 것인지 고민하면서 생각한 것들을 정리할 예정</p>
<h1 id="1-개발-환경-세팅">1. 개발 환경 세팅</h1>
<p>github, aws(ec2,eks,ecr,s3), github action ,watchtower</p>
<h1 id="2-사용-툴">2. 사용 툴</h1>
<p>vscode, github coplit, figma , notion... 이외 google docs로 공유 및 정리 
<img src="https://velog.velcdn.com/images/ni_market_dev/post/57d875d7-0c81-493d-afb2-d2a645160147/image.png" alt=""></p>
<h1 id="3-사용할-수-있는-기술">3. 사용할 수 있는 기술</h1>
<h3 id="프론트---react-next-storybook">프론트 - react, next, storybook</h3>
<p><img src="https://velog.velcdn.com/images/ni_market_dev/post/0e2a43ae-72b3-46a6-9b69-99bd1e55e19b/image.png" alt=""></p>
<h3 id="백엔드---nodeexpress-nest">백엔드 - node,express, nest</h3>
<p><img src="https://velog.velcdn.com/images/ni_market_dev/post/480e3217-4c45-470f-bd32-575684e47817/image.png" alt=""></p>
<h3 id="tdd---jest">TDD - jest</h3>
<p><img src="https://velog.velcdn.com/images/ni_market_dev/post/3c4a34ff-34fe-4463-b6b8-ee5438aeca04/image.png" alt=""></p>
<h3 id="서버---linux--awsec2-">서버 - linux , aws(ec2 ...)</h3>
<p><img src="https://velog.velcdn.com/images/ni_market_dev/post/f5511286-35a0-41f4-b25b-0bc573b79b52/image.png" alt=""></p>
<h3 id="컨테이너-기술---docker-kuberneteseksrook-ceph-helm">컨테이너 기술 - docker, kubernetes(eks),rook-ceph, helm</h3>
<p><img src="https://velog.velcdn.com/images/ni_market_dev/post/72f2e38e-4950-415a-b856-fec1d9d4eb70/image.png" alt=""></p>
<h3 id="cicd---github-action-watchtowerharborecr">CI/CD - github action, watchtower,Harbor,ECR</h3>
<p><img src="https://velog.velcdn.com/images/ni_market_dev/post/d7e283ea-89cc-40fa-a77d-488bfde72279/image.png" alt=""></p>
<h3 id="웹-서버-or-프록시---nginx-alb-route-53">웹 서버 or 프록시 - nginx, alb, Route 53</h3>
<p><img src="https://velog.velcdn.com/images/ni_market_dev/post/715cc4ab-23df-45a5-b89a-634296ef45b0/image.png" alt=""></p>
<h3 id="사용-언어-및-프레임워크">사용 언어 및 프레임워크</h3>
<ul>
<li>javascript, typescript, python, kotlin, flutter
<img src="https://velog.velcdn.com/images/ni_market_dev/post/a56dd380-4d13-46af-9486-08995139b578/image.png" alt=""></li>
</ul>
<h1 id="4-개발-환경을-어떻게-세팅">4. 개발 환경을 어떻게 세팅?</h1>
<ul>
<li>스타트업에서 돈을 아끼면서 회사 내부 개발서버를 구축<ul>
<li>데스크탑 하나에 우분투 20.04 설치</li>
<li>ssh 세팅(ssh key를 가지고 회사 내부 망에서만 연결할 수 있도록 설정)</li>
<li>포트 포워딩 설정(웹 - 80,443) 이외의 포트는 비밀.. ㅎㅎ</li>
<li>nginx, docker, docker-compose, nvm 기타 .... 세팅</li>
<li>도메인 구매 및 ssl 설정(let&#39;s encrypt- 와일드 카드로)
<img src="https://velog.velcdn.com/images/ni_market_dev/post/c8649b1f-0875-41f4-9ff3-291ea7c35738/image.png" alt="">
일단은 위 과정으로 개발 서버 세팅을 진행 함</li>
</ul>
</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>