<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>거니의 velog</title>
    <link>https://bbbb7788.tistory.com/</link>
    <description>항상 배우고 성장하고 싶은 개발자입니다.</description>
    <language>ko</language>
    <pubDate>Tue, 30 Jun 2026 04:10:30 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Unlimited00</managingEditor>
    <image>
      <title>거니의 velog</title>
      <url>https://tistory1.daumcdn.net/tistory/6481027/attach/202bc6933f2e4d0faabba3215926621a</url>
      <link>https://bbbb7788.tistory.com</link>
    </image>
    <item>
      <title>CRA 환경에서 FSD 아키텍처 적용하기</title>
      <link>https://bbbb7788.tistory.com/613</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 &lt;b&gt;Create React App(CRA)&lt;/b&gt; 환경에서 &lt;b&gt;Feature-Sliced Design(FSD)&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-end=&quot;203&quot; data-start=&quot;189&quot; data-ke-size=&quot;size26&quot;&gt;1. 폴더 구조 예시&lt;/h2&gt;
&lt;p data-end=&quot;248&quot; data-start=&quot;205&quot; data-ke-size=&quot;size16&quot;&gt;FSD에서는 일반적으로 다음과 같은 &lt;b&gt;레이어(layer)&lt;/b&gt; 가 사용됩니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;577&quot; data-start=&quot;250&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;303&quot; data-start=&quot;250&quot;&gt;&lt;b&gt;app/&lt;/b&gt;: 루트 애플리케이션 레벨 설정 (Provider, 라우팅, 전역 스타일 등)&lt;/li&gt;
&lt;li data-end=&quot;359&quot; data-start=&quot;304&quot;&gt;&lt;b&gt;processes/&lt;/b&gt; (선택): 사용자 인증, 빌링 처리 등 전역적&amp;middot;비즈니스 크로스컷 기능&lt;/li&gt;
&lt;li data-end=&quot;393&quot; data-start=&quot;360&quot;&gt;&lt;b&gt;pages/&lt;/b&gt;: 페이지 단위 (URL 단위)로 구성&lt;/li&gt;
&lt;li data-end=&quot;439&quot; data-start=&quot;394&quot;&gt;&lt;b&gt;widgets/&lt;/b&gt;: 화면에서 주요 UI 블록(헤더, 푸터, 사이드바 등)&lt;/li&gt;
&lt;li data-end=&quot;481&quot; data-start=&quot;440&quot;&gt;&lt;b&gt;features/&lt;/b&gt;: 특정 기능(검색, 로그인, 코멘트 작성 등)&lt;/li&gt;
&lt;li data-end=&quot;532&quot; data-start=&quot;482&quot;&gt;&lt;b&gt;entities/&lt;/b&gt;: 도메인 엔티티(사용자, 게시글, 상품 등) + 비즈니스 로직&lt;/li&gt;
&lt;li data-end=&quot;577&quot; data-start=&quot;533&quot;&gt;&lt;b&gt;shared/&lt;/b&gt;: 전역 유틸, 재사용 가능한 컴포넌트, 타입, 함수 등&lt;/li&gt;
&lt;li data-end=&quot;577&quot; data-start=&quot;533&quot;&gt;&lt;b&gt;assets/&lt;/b&gt;: 이미지, 폰트, 글로벌 스타일 등&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;592&quot; data-start=&quot;579&quot; data-ke-size=&quot;size16&quot;&gt;예시는 다음과 같습니다:&lt;/p&gt;
&lt;pre id=&quot;code_1744683428326&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;src/
├── index.js                # [CRA 필수] 앱 진입점
├── app/
│   ├── providers/
│   │   └── store.js          # Redux Store, 혹은 React Query 설정 등
│   ├── App.js                # 전역 라우팅, 레이아웃 등
├── processes/
│   └── &amp;lt;...&amp;gt;                 # (선택) 인증, 빌링 등의 전역적 비즈니스 로직
├── pages/
│   └── HomePage/
│       ├── ui/
│       │   └── HomePage.jsx  # 페이지 UI
│       └── index.js          # HomePage 관련 설정/내보내기
├── widgets/
│   └── Header/
│       ├── ui/
│       │   └── Header.jsx    # 헤더 UI
│       └── index.js
├── features/
│   └── userAuth/
│       ├── ui/
│       │   └── LoginForm.jsx # 로그인 UI 컴포넌트
│       ├── model/
│       │   └── useLogin.js   # 로그인 상태, 훅, 액션 로직 등
│       └── index.js
├── entities/
│   └── user/
│       ├── model/
│       │   └── userSlice.js  # Redux slice, Recoil atom, Zustand store 등
│       ├── lib/
│       │   └── userApi.js    # API 호출 로직, DTO 변환 등
│       ├── types/
│       │   └── index.js      # 사용자 타입 정의(TypeScript 시)
│       └── index.js
├── shared/
│   ├── config/
│   │   └── index.js          # 환경변수, 전역 설정 등
│   ├── api/
│   │   └── httpClient.js     # axios, fetch 래퍼 등
│   ├── ui/
│   │   └── Button.jsx        # 재사용 가능한 디자인 컴포넌트
│   ├── lib/
│   │   └── helpers.js        # 공통 헬퍼함수
│   └── index.js
└── assets/                # 이미지, 폰트, 글로벌 스타일 등&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;폴더 이름과 구조는 FSD의 핵심 개념&lt;br /&gt;을 지키되, 팀의 합의에 따라 조정해도 됩니다.&lt;br /&gt;&lt;br /&gt;예:&lt;br /&gt;&lt;br /&gt;widgets 대신 components 를 쓰는 경우도 있고,&lt;br /&gt;&lt;br /&gt;processes 레이어가 불필요하면 생략할 수도 있습니다.&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-end=&quot;2060&quot; data-start=&quot;2045&quot; data-ke-size=&quot;size26&quot;&gt;2. 예시 코드 스니펫&lt;/h2&gt;
&lt;h3 data-end=&quot;2084&quot; data-start=&quot;2062&quot; data-ke-size=&quot;size23&quot;&gt;2.1 app/index.js&lt;/h3&gt;
&lt;p data-end=&quot;2181&quot; data-start=&quot;2085&quot; data-ke-size=&quot;size16&quot;&gt;CRA에서 기본적으로 제공되는 index.js(또는 main.js) 파일입니다. 전역 Store, Router, Error Boundary 등을 제공할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1744683576205&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;
import ReactDOM from &quot;react-dom/client&quot;;
import App from './app/App';
import { Provider } from &quot;react-redux&quot;;
import { store } from &quot;./providers/store&quot;;

const root = ReactDOM.createRoot(document.getElementById(&quot;root&quot;));
root.render(
  &amp;lt;React.StrictMode&amp;gt;
    &amp;lt;Provider store={store}&amp;gt;
      &amp;lt;App /&amp;gt;
    &amp;lt;/Provider&amp;gt;
  &amp;lt;/React.StrictMode&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-end=&quot;2589&quot; data-start=&quot;2557&quot; data-ke-size=&quot;size23&quot;&gt;2.2 app/providers/store.js&lt;/h3&gt;
&lt;p data-end=&quot;2656&quot; data-start=&quot;2590&quot; data-ke-size=&quot;size16&quot;&gt;Redux를 사용한다고 가정한 예시입니다. (React Query, Zustand 등 다른 상태 관리도 유사하게 구성)&lt;/p&gt;
&lt;pre id=&quot;code_1744683592735&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { configureStore } from &quot;@reduxjs/toolkit&quot;;
import { userReducer } from &quot;entities/user&quot;;

export const store = configureStore({
  reducer: {
    user: userReducer,
  },
});&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-end=&quot;2869&quot; data-start=&quot;2849&quot; data-ke-size=&quot;size23&quot;&gt;2.3 app/App.js&lt;/h3&gt;
&lt;p data-end=&quot;2894&quot; data-start=&quot;2870&quot; data-ke-size=&quot;size16&quot;&gt;전역 라우팅을 담당하는 컴포넌트 예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1744683610834&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;
import { BrowserRouter as Router, Routes, Route } from &quot;react-router-dom&quot;;
import { HomePage } from &quot;pages/HomePage&quot;;
import { Header } from &quot;widgets/Header&quot;;

function App() {
  return (
    &amp;lt;Router&amp;gt;
      &amp;lt;Header /&amp;gt;
      &amp;lt;Routes&amp;gt;
        &amp;lt;Route path=&quot;/&quot; element={&amp;lt;HomePage /&amp;gt;} /&amp;gt;
        {/* 라우트 추가 가능 */}
      &amp;lt;/Routes&amp;gt;
    &amp;lt;/Router&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-end=&quot;3342&quot; data-start=&quot;3302&quot; data-ke-size=&quot;size23&quot;&gt;2.4 pages/HomePage/ui/HomePage.js&lt;/h3&gt;
&lt;p data-end=&quot;3402&quot; data-start=&quot;3343&quot; data-ke-size=&quot;size16&quot;&gt;HomePage에서 필요한 상태나 로직은 features나 entities에서 가져다가 사용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1744683754046&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;
import { LoginForm } from &quot;features/userAuth&quot;;
import &quot;./HomePage.css&quot;;

export const HomePage = () =&amp;gt; {
  return (
    &amp;lt;div className=&quot;home-page&quot;&amp;gt;
      &amp;lt;h1&amp;gt;Welcome to the Home Page&amp;lt;/h1&amp;gt;
      &amp;lt;LoginForm /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-end=&quot;3714&quot; data-start=&quot;3670&quot; data-ke-size=&quot;size23&quot;&gt;2.5 features/userAuth/ui/LoginForm.js&lt;/h3&gt;
&lt;p data-end=&quot;3775&quot; data-start=&quot;3715&quot; data-ke-size=&quot;size16&quot;&gt;실제 로그인 폼 UI와 관련된 로직입니다. 로그인 액션은 model/useLogin.js에서 가져옵니다.&lt;/p&gt;
&lt;pre id=&quot;code_1744683777601&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;
import { useLogin } from &quot;../model/useLogin&quot;;

export const LoginForm = () =&amp;gt; {
  const { login, isLoading, error } = useLogin();
  const [email, setEmail] = useState(&quot;&quot;);
  const [password, setPassword] = useState(&quot;&quot;);

  const handleSubmit = (e) =&amp;gt; {
    e.preventDefault();
    login({ email, password });
  };

  return (
    &amp;lt;form onSubmit={handleSubmit}&amp;gt;
      &amp;lt;label&amp;gt;
        Email
        &amp;lt;input 
          type=&quot;email&quot; 
          value={email}
          onChange={(e) =&amp;gt; setEmail(e.target.value)} 
        /&amp;gt;
      &amp;lt;/label&amp;gt;
      &amp;lt;label&amp;gt;
        Password
        &amp;lt;input 
          type=&quot;password&quot; 
          value={password}
          onChange={(e) =&amp;gt; setPassword(e.target.value)} 
        /&amp;gt;
      &amp;lt;/label&amp;gt;
      {error &amp;amp;&amp;amp; &amp;lt;div&amp;gt;{error}&amp;lt;/div&amp;gt;}
      &amp;lt;button type=&quot;submit&quot; disabled={isLoading}&amp;gt;
        {isLoading ? &quot;Logging in...&quot; : &quot;Login&quot;}
      &amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
  );
};&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-end=&quot;4762&quot; data-start=&quot;4717&quot; data-ke-size=&quot;size23&quot;&gt;2.6 features/userAuth/model/useLogin.js&lt;/h3&gt;
&lt;p data-end=&quot;4823&quot; data-start=&quot;4763&quot; data-ke-size=&quot;size16&quot;&gt;useLogin 훅에서는 API 요청을 처리하거나, Redux와 연결하는 등 비즈니스 로직을 구현합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1744684178175&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { useCallback, useState } from &quot;react&quot;;
import { loginUser } from &quot;entities/user&quot;; // 가령 userSlice 혹은 user API

export function useLogin() {
  const [isLoading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const login = useCallback(async ({ email, password }) =&amp;gt; {
    setLoading(true);
    setError(null);
    try {
      // 실제 API 호출 혹은 Redux 액션 디스패치
      await loginUser({ email, password });
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  }, []);

  return { login, isLoading, error };
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-end=&quot;5462&quot; data-start=&quot;5420&quot; data-ke-size=&quot;size23&quot;&gt;2.7 entities/user/model/userSlice.js&lt;/h3&gt;
&lt;p data-end=&quot;5497&quot; data-start=&quot;5463&quot; data-ke-size=&quot;size16&quot;&gt;Redux Toolkit을 예시로 사용자 데이터를 관리합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1744684194215&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { createSlice, createAsyncThunk } from &quot;@reduxjs/toolkit&quot;;
import { authApi } from &quot;shared/api/authApi&quot;;

// Thunk: 비동기 로그인 로직
export const loginUser = createAsyncThunk(
  &quot;user/loginUser&quot;,
  async ({ email, password }) =&amp;gt; {
    const response = await authApi.login({ email, password });
    return response.data;
  }
);

const userSlice = createSlice({
  name: &quot;user&quot;,
  initialState: {
    userData: null,
    status: &quot;idle&quot;,
    error: null,
  },
  reducers: {
    logout: (state) =&amp;gt; {
      state.userData = null;
    },
  },
  extraReducers: (builder) =&amp;gt; {
    builder
      .addCase(loginUser.pending, (state) =&amp;gt; {
        state.status = &quot;loading&quot;;
      })
      .addCase(loginUser.fulfilled, (state, action) =&amp;gt; {
        state.status = &quot;succeeded&quot;;
        state.userData = action.payload;
      })
      .addCase(loginUser.rejected, (state, action) =&amp;gt; {
        state.status = &quot;failed&quot;;
        state.error = action.error.message;
      });
  },
});

export const { logout } = userSlice.actions;
export const userReducer = userSlice.reducer;&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-end=&quot;6588&quot; data-start=&quot;6573&quot; data-ke-size=&quot;size26&quot;&gt;3. 경로 설정(옵션)&lt;/h2&gt;
&lt;p data-end=&quot;6663&quot; data-start=&quot;6589&quot; data-ke-size=&quot;size16&quot;&gt;CRA에서는 절대 경로(alias)를 쓰려면 jsconfig.json 또는 tsconfig.json에서 설정해야 합니다. 예:&lt;/p&gt;
&lt;pre id=&quot;code_1744684226448&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;compilerOptions&quot;: {
    &quot;baseUrl&quot;: &quot;src&quot;,
    &quot;paths&quot;: {
      &quot;app/*&quot;: [&quot;app/*&quot;],
      &quot;pages/*&quot;: [&quot;pages/*&quot;],
      &quot;widgets/*&quot;: [&quot;widgets/*&quot;],
      &quot;features/*&quot;: [&quot;features/*&quot;],
      &quot;entities/*&quot;: [&quot;entities/*&quot;],
      &quot;shared/*&quot;: [&quot;shared/*&quot;]
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 설정하면 import { LoginForm } from &quot;features/userAuth&quot;; 와 같은 절대 경로를 사용하여 가독성을 높일 수 있습니다.&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-end=&quot;7052&quot; data-start=&quot;7043&quot; data-ke-size=&quot;size26&quot;&gt;4. 마무리&lt;/h2&gt;
&lt;p data-end=&quot;7111&quot; data-start=&quot;7054&quot; data-ke-size=&quot;size16&quot;&gt;위 예시는 &lt;b&gt;CRA 환경&lt;/b&gt;에서 &lt;b&gt;FSD 아키텍처&lt;/b&gt;를 간단히 적용한 것이며, 실제 프로젝트에서는:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;7381&quot; data-start=&quot;7113&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;7159&quot; data-start=&quot;7113&quot;&gt;각 레이어(폴더)의 &lt;b&gt;역할과 책임&lt;/b&gt;을 팀원들이 명확히 이해해야 합니다.&lt;/li&gt;
&lt;li data-end=&quot;7273&quot; data-start=&quot;7160&quot;&gt;&lt;b&gt;pages&lt;/b&gt;, &lt;b&gt;widgets&lt;/b&gt;, &lt;b&gt;features&lt;/b&gt;, &lt;b&gt;entities&lt;/b&gt;, &lt;b&gt;shared&lt;/b&gt; 순으로 의존이 흐르도록(상하 관계 준수) 구조를 지켜야 유지 보수가 수월해집니다.&lt;/li&gt;
&lt;li data-end=&quot;7381&quot; data-start=&quot;7274&quot;&gt;프로젝트 규모가 작으면 processes 폴더를 생략하거나, 반대로 대형 프로젝트라면 app, pages, widgets 아래 하위 레이어를 좀 더 세분화할 수도 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;7467&quot; data-start=&quot;7383&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 FSD를 적용하면 기능과 엔티티별로 코드가 모듈화되어 &lt;b&gt;코드 가독성&lt;/b&gt;, &lt;b&gt;확장성&lt;/b&gt;, &lt;b&gt;유지보수성&lt;/b&gt; 모두 크게 개선될 수 있습니다.&lt;/p&gt;</description>
      <category>etc 이슈</category>
      <author>Unlimited00</author>
      <guid isPermaLink="true">https://bbbb7788.tistory.com/613</guid>
      <comments>https://bbbb7788.tistory.com/613#entry613comment</comments>
      <pubDate>Tue, 15 Apr 2025 11:17:18 +0900</pubDate>
    </item>
    <item>
      <title>시작, 중단, 재시작, 접속 단축 명령</title>
      <link>https://bbbb7788.tistory.com/612</link>
      <description>&lt;pre id=&quot;code_1744680430613&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Apache Control
alias apache-start='/poa/server/web/bin/apachectl start'
alias apache-stop='/poa/server/web/bin/apachectl stop'
alias apache-restart='/poa/server/web/bin/apachectl restart'

# Tomcat Control
alias tomcat-start='/poa/server/was/tomcat-9.0.97/bin/startup.sh'
alias tomcat-stop='/poa/server/was/tomcat-9.0.97/bin/shutdown.sh'

# MariaDB Control
alias mariadb-start='/poa/server/db/mariadb/bin/mysqld_safe --defaults-file=/poa/server/db/mariadb/etc/my.cnf --datadir=/poa/server/db/mariadb/data &amp;amp;'
alias mariadb-stop='/poa/server/db/mariadb/bin/mysqladmin shutdown --socket=/poa/server/db/mariadb/mariadb.sock -u poa -p'
alias mariadb-login='/poa/server/db/mariadb/bin/mysql -u poa -p --socket=/poa/server/db/mariadb/mariadb.sock'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;10&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자세한 설명&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;2493&quot; data-start=&quot;12&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;979&quot; data-start=&quot;12&quot;&gt;&lt;b&gt;Alias 설정&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;979&quot; data-start=&quot;827&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;900&quot; data-start=&quot;827&quot;&gt;&lt;b&gt;alias&lt;/b&gt;: 터미널에서 특정 명령어(별명)를 입력했을 때, 뒤따르는 실제 명령어를 대신 실행하도록 만드는 기능입니다.&lt;/li&gt;
&lt;li data-end=&quot;979&quot; data-start=&quot;904&quot;&gt;위 예시에서는 Apache, Tomcat, MariaDB를 쉽게 시작&amp;middot;중단&amp;middot;접속할 수 있도록 별명(alias)을 지정하고 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;823&quot; data-start=&quot;33&quot;&gt;&lt;b&gt;Apache 관련 alias&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1270&quot; data-start=&quot;1009&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1095&quot; data-start=&quot;1009&quot;&gt;apache-start: /poa/server/web/bin/apachectl start를 실행 &amp;rarr; Apache HTTP Server를 시작&lt;/li&gt;
&lt;li data-end=&quot;1179&quot; data-start=&quot;1099&quot;&gt;apache-stop: /poa/server/web/bin/apachectl stop &amp;rarr; Apache HTTP Server를 중단&lt;/li&gt;
&lt;li data-end=&quot;1270&quot; data-start=&quot;1183&quot;&gt;apache-restart: /poa/server/web/bin/apachectl restart &amp;rarr; Apache HTTP Server를 재시작&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1462&quot; data-start=&quot;1272&quot;&gt;&lt;b&gt;Tomcat 관련 alias&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1462&quot; data-start=&quot;1300&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1379&quot; data-start=&quot;1300&quot;&gt;tomcat-start: /poa/server/was/tomcat-9.0.97/bin/startup.sh &amp;rarr; Tomcat을 시작&lt;/li&gt;
&lt;li data-end=&quot;1462&quot; data-start=&quot;1383&quot;&gt;tomcat-stop: /poa/server/was/tomcat-9.0.97/bin/shutdown.sh &amp;rarr; Tomcat을 중단&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;2493&quot; data-start=&quot;1464&quot;&gt;&lt;b&gt;MariaDB 관련 alias&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2493&quot; data-start=&quot;1493&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1864&quot; data-start=&quot;1493&quot;&gt;mariadb-start:
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1864&quot; data-start=&quot;1693&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1752&quot; data-start=&quot;1693&quot;&gt;mysqld_safe 스크립트를 통해 MariaDB 서버를 안전 모드(백그라운드)로 실행합니다.&lt;/li&gt;
&lt;li data-end=&quot;1830&quot; data-start=&quot;1758&quot;&gt;--defaults-file로 my.cnf 경로를 지정하고, --datadir로 데이터베이스 파일 위치를 설정.&lt;/li&gt;
&lt;li data-end=&quot;1864&quot; data-start=&quot;1836&quot;&gt;마지막에 &amp;amp;로 백그라운드 실행을 의미합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1687&quot; data-start=&quot;1519&quot;&gt;mariadb-stop:
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2217&quot; data-start=&quot;2049&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2106&quot; data-start=&quot;2049&quot;&gt;mysqladmin 명령어로 MariaDB 서버에 종료(shutdown) 명령을 전달합니다.&lt;/li&gt;
&lt;li data-end=&quot;2217&quot; data-start=&quot;2112&quot;&gt;--socket으로 Mariadb 소켓 파일 위치를 지정하고, -u poa -p는 종료 권한이 있는 사용자(여기서는 poa)로 접속하겠다는 의미이며, 비밀번호가 필요(-p).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;2043&quot; data-start=&quot;1893&quot;&gt;mariadb-login:
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2493&quot; data-start=&quot;2389&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2426&quot; data-start=&quot;2389&quot;&gt;명령줄에서 MariaDB에 로그인할 때 사용할 명령어입니다.&lt;/li&gt;
&lt;li data-end=&quot;2493&quot; data-start=&quot;2432&quot;&gt;소켓 파일(mariadb.sock)과 사용자 이름(poa), 비밀번호(-p 필요)를 지정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;2508&quot; data-start=&quot;2500&quot; 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-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;2806&quot; data-start=&quot;2509&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2605&quot; data-start=&quot;2509&quot;&gt;위 Alias들은 &lt;b&gt;Apache&lt;/b&gt;, &lt;b&gt;Tomcat&lt;/b&gt;, &lt;b&gt;MariaDB&lt;/b&gt; 각각을 쉽게 시작, 중단, 재시작, 접속할 수 있도록 돕는 &lt;b&gt;단축 명령&lt;/b&gt;입니다.&lt;/li&gt;
&lt;li data-end=&quot;2710&quot; data-start=&quot;2606&quot;&gt;이 설정이 들어간 스크립트 혹은 쉘 설정 파일(.bashrc 등)을 로드하면, 터미널에서 예를 들어 apache-start만 입력해도 Apache 서버가 손쉽게 시작됩니다.&lt;/li&gt;
&lt;li data-end=&quot;2806&quot; data-start=&quot;2711&quot;&gt;각 별명(alias)이 실제 수행하는 동작은 명령문 뒷부분에 나와 있으며, 서버 관리 및 DB 접속 시 매번 긴 경로를 입력할 필요 없이 간편하게 사용할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>etc 이슈</category>
      <author>Unlimited00</author>
      <guid isPermaLink="true">https://bbbb7788.tistory.com/612</guid>
      <comments>https://bbbb7788.tistory.com/612#entry612comment</comments>
      <pubDate>Tue, 15 Apr 2025 10:28:02 +0900</pubDate>
    </item>
    <item>
      <title>리눅스 개발환경 세팅</title>
      <link>https://bbbb7788.tistory.com/611</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;실무에서는 &lt;b&gt;프로젝트 성격&amp;middot;배포 파이프라인 구성&lt;/b&gt;에 따라 &lt;b&gt;좀 더 합리적인 순서&lt;/b&gt;를 정해놓고 설치&amp;middot;셋업을 진행합니다. 모든 구성요소가 서로 어느 정도 독립적이기 때문에, 순서가 바뀌어도 동작 자체는 가능합니다. 다만, 아래와 같은 &lt;b&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-end=&quot;222&quot; data-start=&quot;200&quot; data-ke-size=&quot;size26&quot;&gt;1. OS 환경 &amp;amp; 기초 도구 세팅&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;388&quot; data-start=&quot;223&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;268&quot; data-start=&quot;223&quot;&gt;&lt;b&gt;리눅스 업데이트&lt;/b&gt; (yum update, apt-get update 등)&lt;/li&gt;
&lt;li data-end=&quot;319&quot; data-start=&quot;269&quot;&gt;&lt;b&gt;필수 패키지/라이브러리&lt;/b&gt; 설치 (Java, gcc, openssl, wget 등)&lt;/li&gt;
&lt;li data-end=&quot;342&quot; data-start=&quot;320&quot;&gt;방화벽 설정, 네트워크 설정 확인&lt;/li&gt;
&lt;li data-end=&quot;388&quot; data-start=&quot;343&quot;&gt;이 부분은 가장 먼저 해야, 이후 각종 서버와 도구 설치 시 충돌이 적습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1744678465064&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo ufw status

sudo ufw allow 9876
sudo ufw allow 9877
sudo ufw allow 9878
sudo ufw allow 9879
sudo ufw allow 9880
sudo ufw allow 9881

#apache tomcat 연결
sudo ufw allow 8009/tcp


#테스트후 was 직접 접근은 차단
sudo ufw deny 9880/tcp
sudo ufw deny 8009/tcp

sudo ufw reload

sudo netstat -tuln | grep 9881&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;11&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자세한 설명:&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1432&quot; data-start=&quot;13&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;162&quot; data-start=&quot;13&quot;&gt;sudo ufw status
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;162&quot; data-start=&quot;39&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;102&quot; data-start=&quot;39&quot;&gt;**ufw(Ubuntu Firewall)**의 현재 상태(활성화 여부, 규칙 등)를 확인하는 명령어입니다.&lt;/li&gt;
&lt;li data-end=&quot;162&quot; data-start=&quot;106&quot;&gt;이 명령어를 통해, 현재 어떤 포트가 열려있는지, 방화벽 정책이 어떤지 등을 확인할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;450&quot; data-start=&quot;164&quot;&gt;sudo ufw allow 9876, sudo ufw allow 9877, sudo ufw allow 9878, sudo ufw allow 9879, sudo ufw allow 9880, sudo ufw allow 9881
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;450&quot; data-start=&quot;309&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;380&quot; data-start=&quot;309&quot;&gt;ufw 방화벽에서 9876, 9877, 9878, 9879, 9880, 9881 포트를 열어주는(Allow) 설정입니다.&lt;/li&gt;
&lt;li data-end=&quot;450&quot; data-start=&quot;384&quot;&gt;기본적으로 Linux 서버에서 필요한 서비스(프로그램)들이 해당 포트를 통해 외부와 통신할 수 있도록 허용해줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;701&quot; data-start=&quot;536&quot;&gt;sudo ufw allow 8009/tcp
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;701&quot; data-start=&quot;570&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;657&quot; data-start=&quot;570&quot;&gt;Apache Tomcat에서 AJP(Apache JServ Protocol) 등을 사용할 때 기본적으로 8009 포트를 사용하는데, 이를 허용합니다.&lt;/li&gt;
&lt;li data-end=&quot;701&quot; data-start=&quot;661&quot;&gt;tcp 프로토콜로 외부에서 접속할 수 있게 허용한다는 의미입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1001&quot; data-start=&quot;819&quot;&gt;sudo ufw deny 9880/tcp, sudo ufw deny 8009/tcp
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1001&quot; data-start=&quot;878&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;932&quot; data-start=&quot;878&quot;&gt;앞서 허용했던 9880/tcp와 8009/tcp를 이제 차단(deny)하겠다는 설정입니다.&lt;/li&gt;
&lt;li data-end=&quot;1001&quot; data-start=&quot;936&quot;&gt;테스트가 끝났으므로 WAS에 대한 직접 접속은 방지하고, 프록시나 다른 방식으로만 접근하도록 하겠다는 의도입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1080&quot; data-start=&quot;1003&quot;&gt;sudo ufw reload
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1080&quot; data-start=&quot;1029&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1080&quot; data-start=&quot;1029&quot;&gt;ufw 방화벽 규칙을 다시 로드(reload)하여, 방금 설정한 규칙들을 적용합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1432&quot; data-start=&quot;1082&quot;&gt;sudo netstat -tuln | grep 9881
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1432&quot; data-start=&quot;1123&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1224&quot; data-start=&quot;1123&quot;&gt;netstat 명령어를 사용하여 TCP/UDP 포트 별 Listen 상태를 확인하고, 그 결과 중에 9881이라는 문자열이 포함된 부분만 grep으로 필터링합니다.&lt;/li&gt;
&lt;li data-end=&quot;1283&quot; data-start=&quot;1228&quot;&gt;9881 포트가 실제로 열려 있고, 어떤 프로세스가 사용 중인지 여부 등을 확인할 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;1432&quot; data-start=&quot;1287&quot;&gt;-tuln 옵션:
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1432&quot; data-start=&quot;1306&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1327&quot; data-start=&quot;1306&quot;&gt;-t: TCP 소켓 정보만 표시&lt;/li&gt;
&lt;li data-end=&quot;1354&quot; data-start=&quot;1333&quot;&gt;-u: UDP 소켓 정보만 표시&lt;/li&gt;
&lt;li data-end=&quot;1387&quot; data-start=&quot;1360&quot;&gt;-l: Listening 중인 소켓만 표시&lt;/li&gt;
&lt;li data-end=&quot;1432&quot; data-start=&quot;1393&quot;&gt;-n: 호스트명 대신 IP, 포트번호 등 숫자로 된 정보를 표시&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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;h2 data-end=&quot;430&quot; data-start=&quot;395&quot; data-ke-size=&quot;size26&quot;&gt;2. 버전 관리 시스템(SVN) &amp;amp; 빌드 도구(Maven)&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;622&quot; data-start=&quot;431&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;517&quot; data-start=&quot;431&quot;&gt;&lt;b&gt;SVN(Subversion) 서버&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;517&quot; data-start=&quot;462&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;483&quot; data-start=&quot;462&quot;&gt;코드 버전을 관리하기 위해 필요&lt;/li&gt;
&lt;li data-end=&quot;517&quot; data-start=&quot;487&quot;&gt;이미 다른 서버에서 운용 중이면 건너뛸 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;622&quot; data-start=&quot;518&quot;&gt;&lt;b&gt;Maven&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;622&quot; data-start=&quot;536&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;555&quot; data-start=&quot;536&quot;&gt;Java 프로젝트 빌드&amp;middot;관리&lt;/li&gt;
&lt;li data-end=&quot;601&quot; data-start=&quot;559&quot;&gt;로컬 개발/빌드 환경에서 먼저 설치 후, 서버(젠킨스 등)에서도 사용&lt;/li&gt;
&lt;li data-end=&quot;622&quot; data-start=&quot;605&quot;&gt;mvn -v로 설치 검증&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;보통 SVN을 먼저 설치 후 Maven을 설치해도 되고, 반대로 해도 문제는 없습니다.&lt;br /&gt;Maven을 설치해둔 뒤, 바로 레포지토리를 연결하거나, SVN에서 코드를 가져와 빌드할 때 필요하므로&amp;nbsp;&lt;br /&gt;같은 시점에 진행하는 경우가 많습니다.&lt;/blockquote&gt;
&lt;pre id=&quot;code_1744678694638&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt update
sudo apt install build-essential libapr1-dev libaprutil1-dev liblz4-dev libutf8proc-dev zlib1g-dev

# 최신 버전의 Subversion 다운로드
cd /poa/data
wget http://archive.apache.org/dist/subversion/subversion-1.14.3.tar.gz
tar -xzvf subversion-1.14.3.tar.gz
cd subversion-1.14.3

cd /poa/data
wget https://www.sqlite.org/2015/sqlite-amalgamation-3081101.zip
unzip sqlite-amalgamation-3081101.zip

mv sqlite-amalgamation-3081101 /poa/data/subversion-1.14.3/sqlite-amalgamation

cd /poa/data/subversion-1.14.3
./configure --prefix=/poa/svn
make
sudo make install

export PATH=/poa/svn/bin:$PATH

svn --version

sudo ss -tulnp | grep 9876

sudo /poa/svn/bin/svnadmin create /poa/svn/poarepo

/poa/svn/bin/svnserve -d -r /poa/svn/poarepo --listen-port 9876

sudo nano /etc/systemd/system/svn.service

sudo systemctl daemon-reload
sudo systemctl enable svn
sudo systemctl restart svn
sudo systemctl status svn

sudo chmod -R 777 /poa/svn/poarepo

svn://10.100.100.137:9876/poa-web&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;12&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자세한 설명&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;3546&quot; data-start=&quot;14&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;318&quot; data-start=&quot;14&quot;&gt;&lt;b&gt;패키지 업데이트 및 설치&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;318&quot; data-start=&quot;179&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;223&quot; data-start=&quot;179&quot;&gt;apt update 명령어로 패키지 리스트를 최신 상태로 갱신합니다.&lt;/li&gt;
&lt;li data-end=&quot;318&quot; data-start=&quot;227&quot;&gt;Subversion(이하 SVN)을 소스에서 빌드하기 위해 필요한 라이브러리와 헤더 파일(build-essential, libapr1-dev 등)을 설치합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;175&quot; data-start=&quot;40&quot;&gt;&lt;b&gt;Subversion 소스 다운로드&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;635&quot; data-start=&quot;522&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;587&quot; data-start=&quot;522&quot;&gt;/poa/data 디렉터리로 이동 후, Subversion 1.14.3 버전의 소스 코드를 다운로드합니다.&lt;/li&gt;
&lt;li data-end=&quot;635&quot; data-start=&quot;591&quot;&gt;다운로드한 tar.gz 파일을 압축 해제하고, 그 디렉터리로 이동합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;518&quot; data-start=&quot;351&quot;&gt;&lt;b&gt;SQLite 다운로드&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;910&quot; data-start=&quot;804&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;840&quot; data-start=&quot;804&quot;&gt;Subversion은 내부적으로 SQLite를 사용합니다.&lt;/li&gt;
&lt;li data-end=&quot;910&quot; data-start=&quot;844&quot;&gt;적절한 버전의 SQLite 코드(sqlite-amalgamation-3081101)를 다운로드해 압축을 풉니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;800&quot; data-start=&quot;661&quot;&gt;&lt;b&gt;SQLite를 Subversion 디렉터리에 이동&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1149&quot; data-start=&quot;1052&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1149&quot; data-start=&quot;1052&quot;&gt;Subversion 빌드 시 참고할 수 있도록, SQLite 소스 코드를 Subversion 소스 트리 내의 sqlite-amalgamation 디렉터리로 이동합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1048&quot; data-start=&quot;952&quot;&gt;&lt;b&gt;Subversion 빌드 및 설치&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1488&quot; data-start=&quot;1296&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1403&quot; data-start=&quot;1296&quot;&gt;configure 스크립트를 이용하여 빌드 환경을 설정합니다. --prefix=/poa/svn 옵션은 Subversion이 /poa/svn 경로에 설치되도록 하는 설정입니다.&lt;/li&gt;
&lt;li data-end=&quot;1488&quot; data-start=&quot;1407&quot;&gt;make 명령어로 소스 코드를 빌드한 뒤, sudo make install으로 실제 파일들을 /poa/svn 디렉터리에 설치합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1292&quot; data-start=&quot;1182&quot;&gt;&lt;b&gt;환경변수 설정&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1661&quot; data-start=&quot;1562&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1661&quot; data-start=&quot;1562&quot;&gt;PATH 환경변수에 Subversion 실행 파일들이 들어있는 /poa/svn/bin 디렉터리를 추가하여, 터미널에서 svn 명령어를 바로 사용할 수 있게 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1558&quot; data-start=&quot;1510&quot;&gt;&lt;b&gt;Subversion 버전 확인&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1777&quot; data-start=&quot;1727&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1777&quot; data-start=&quot;1727&quot;&gt;Subversion이 정상적으로 설치되었는지, 그리고 설치된 버전이 맞는지 확인합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1723&quot; data-start=&quot;1692&quot;&gt;&lt;b&gt;포트 확인&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1986&quot; data-start=&quot;1845&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1924&quot; data-start=&quot;1845&quot;&gt;ss -tulnp로 현재 열려 있는 TCP/UDP 소켓을 확인하고, grep 9876으로 9876 포트 사용 여부를 확인합니다.&lt;/li&gt;
&lt;li data-end=&quot;1986&quot; data-start=&quot;1928&quot;&gt;Subversion 서버가 이 포트를 사용할 계획이므로 사전에 비어 있는지 등을 확인할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1841&quot; data-start=&quot;1797&quot;&gt;&lt;b&gt;SVN 리포지토리 생성&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2205&quot; data-start=&quot;2085&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2136&quot; data-start=&quot;2085&quot;&gt;/poa/svn/poarepo라는 이름으로 새로운 SVN 리포지토리를 생성합니다.&lt;/li&gt;
&lt;li data-end=&quot;2205&quot; data-start=&quot;2140&quot;&gt;svnadmin create 명령어를 사용하면 SVN 저장소 디렉터리가 만들어지고, 필요한 구조가 생성됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;2081&quot; data-start=&quot;2013&quot;&gt;&lt;b&gt;SVN 서버 실행&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2461&quot; data-start=&quot;2319&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2352&quot; data-start=&quot;2319&quot;&gt;svnserve를 데몬(-d) 모드로 실행합니다.&lt;/li&gt;
&lt;li data-end=&quot;2461&quot; data-start=&quot;2357&quot;&gt;-r /poa/svn/poarepo 옵션으로 리포지토리 기본 경로를 /poa/svn/poarepo로 지정하고, --listen-port 옵션으로 9876 포트를 사용합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;2314&quot; data-start=&quot;2231&quot;&gt;&lt;b&gt;Systemd 서비스 파일 생성 및 설정&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2793&quot; data-start=&quot;2566&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2673&quot; data-start=&quot;2566&quot;&gt;nano 편집기를 사용하여 /etc/systemd/system/svn.service 파일을 열어, SVN 서버를 systemd 서비스로 등록할 수 있도록 설정 파일을 작성합니다.&lt;/li&gt;
&lt;li data-end=&quot;2793&quot; data-start=&quot;2678&quot;&gt;일반적으로 svn.service 파일에는 [Unit], [Service], [Install] 섹션 등을 작성해, 위에서 명령했던 svnserve가 systemd로 관리되도록 설정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;2561&quot; data-start=&quot;2500&quot;&gt;&lt;b&gt;Systemd 서비스 리로드 및 활성화&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3131&quot; data-start=&quot;2975&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3025&quot; data-start=&quot;2975&quot;&gt;daemon-reload로 systemd가 새 서비스 파일을 인식하도록 합니다.&lt;/li&gt;
&lt;li data-end=&quot;3074&quot; data-start=&quot;3030&quot;&gt;enable로 부팅 시 자동으로 SVN 서버가 시작되도록 설정합니다.&lt;/li&gt;
&lt;li data-end=&quot;3131&quot; data-start=&quot;3079&quot;&gt;restart 명령어로 서비스를 재시작하고, status로 현재 상태를 확인합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;2970&quot; data-start=&quot;2831&quot;&gt;&lt;b&gt;리포지토리 권한 설정&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3322&quot; data-start=&quot;3218&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3322&quot; data-start=&quot;3218&quot;&gt;리포지토리 디렉터리 전체에 대해 읽기/쓰기/실행 권한을 모두 부여합니다. (테스트 환경에서는 편할 수 있지만, 실제 운영 환경에서는 보안상 문제가 될 수 있으므로 주의가 필요합니다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;3213&quot; data-start=&quot;3159&quot;&gt;&lt;b&gt;SVN 리포지토리 접근&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3546&quot; data-start=&quot;3405&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3506&quot; data-start=&quot;3405&quot;&gt;로컬 네트워크 혹은 서버 환경에서 SVN 클라이언트를 통해 10.100.100.137 서버의 9876 포트로 접근하여, poa-web 리포지토리를 사용할 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;3546&quot; data-start=&quot;3511&quot;&gt;위 주소는 예시이므로 실제 환경에 맞게 변경할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1744678914589&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;wget https://dlcdn.apache.org/maven/maven-3/3.9.4/binaries/apache-maven-3.9.4-bin.tar.gz

sudo tar -zxvf apache-maven-3.9.4-bin.tar.gz -C /poa
sudo mv /poa/apache-maven-3.9.4 /poa/maven


sudo nano /etc/profile.d/maven.sh
 &amp;gt; export M2_HOME=/poa/maven
 &amp;gt; export PATH=$M2_HOME/bin:$PATH

source /etc/profile.d/maven.sh

mvn clean install&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;10&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자세한 설명&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1340&quot; data-start=&quot;12&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;254&quot; data-start=&quot;12&quot;&gt;&lt;b&gt;Maven 다운로드&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;254&quot; data-start=&quot;147&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;203&quot; data-start=&quot;147&quot;&gt;Apache Maven의 3.9.4 버전 바이너리 압축 파일(.tar.gz)을 다운로드합니다.&lt;/li&gt;
&lt;li data-end=&quot;254&quot; data-start=&quot;207&quot;&gt;Maven은 Java 프로젝트를 관리하고 빌드할 때 널리 사용되는 빌드 툴입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;143&quot; data-start=&quot;35&quot;&gt;&lt;b&gt;압축 해제 및 디렉터리 이동&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;560&quot; data-start=&quot;404&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;449&quot; data-start=&quot;404&quot;&gt;다운로드한 압축 파일을 /poa 경로로 해제합니다(-C /poa).&lt;/li&gt;
&lt;li data-end=&quot;516&quot; data-start=&quot;453&quot;&gt;해제 후 생긴 디렉터리 apache-maven-3.9.4를 /poa/maven으로 이름 변경합니다.&lt;/li&gt;
&lt;li data-end=&quot;560&quot; data-start=&quot;520&quot;&gt;결과적으로 Maven의 설치 경로는 /poa/maven이 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;400&quot; data-start=&quot;284&quot;&gt;&lt;b&gt;환경 변수 설정 스크립트 작성&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;865&quot; data-start=&quot;646&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;791&quot; data-start=&quot;646&quot;&gt;maven.sh라는 이름의 스크립트 파일을 생성(또는 열기)하여, 다음 내용을 추가합니다:&lt;/li&gt;
&lt;li data-end=&quot;791&quot; data-start=&quot;706&quot;&gt;
&lt;div&gt;bash&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;복사&lt;/span&gt;&lt;span data-state=&quot;closed&quot;&gt;편집&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;export&lt;/span&gt;&lt;/span&gt;&lt;span&gt; M2_HOME=/poa/maven &lt;/span&gt;&lt;span&gt;&lt;span&gt;export&lt;/span&gt;&lt;/span&gt;&lt;span&gt; PATH=&lt;/span&gt;&lt;span&gt;&lt;span&gt;$M2_HOME&lt;/span&gt;&lt;/span&gt;&lt;span&gt;/bin:&lt;/span&gt;&lt;span&gt;&lt;span&gt;$PATH&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li data-end=&quot;865&quot; data-start=&quot;795&quot;&gt;/etc/profile.d 내의 스크립트는 로그인 시 자동으로 실행되어 시스템 전역의 환경 변수를 설정할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;642&quot; data-start=&quot;591&quot;&gt;&lt;b&gt;설정 적용&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1082&quot; data-start=&quot;937&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;992&quot; data-start=&quot;937&quot;&gt;지금 터미널 세션에서만 즉시 환경 변수를 적용하기 위해 source 명령어를 사용합니다.&lt;/li&gt;
&lt;li data-end=&quot;1082&quot; data-start=&quot;996&quot;&gt;이후에는 새로 로그인하거나 새 터미널을 열었을 때도 자동으로 /etc/profile.d/maven.sh가 실행되어 Maven 경로가 잡히게 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;933&quot; data-start=&quot;885&quot;&gt;&lt;b&gt;Maven 프로젝트 빌드&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1340&quot; data-start=&quot;1149&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1276&quot; data-start=&quot;1149&quot;&gt;Maven 프로젝트 디렉터리 안에서 이 명령을 실행하면, pom.xml 설정에 따라 프로젝트를 클린 빌드(기존 빌드 산출물 제거 후 다시 빌드)하고, 모든 의존성 패키지 다운로드 후 테스트 및 설치 단계를 진행합니다.&lt;/li&gt;
&lt;li data-end=&quot;1340&quot; data-start=&quot;1280&quot;&gt;프로젝트마다 필요한 라이브러리를 자동으로 내려받고, 컴파일, 패키징, 테스트 등을 일괄적으로 수행합니다.&lt;/li&gt;
&lt;/ul&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;h2 data-end=&quot;802&quot; data-start=&quot;769&quot; data-ke-size=&quot;size26&quot;&gt;3. Nexus(혹은 Artifactory 등) 저장소&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;999&quot; data-start=&quot;803&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;838&quot; data-start=&quot;803&quot;&gt;빌드 결과물을 내부 Repository로 관리하려면 필요&lt;/li&gt;
&lt;li data-end=&quot;889&quot; data-start=&quot;839&quot;&gt;Maven이 빌드한 아티팩트(JAR, WAR 등)를 업로드&amp;middot;배포할 저장소이기 때문에&lt;/li&gt;
&lt;li data-end=&quot;999&quot; data-start=&quot;890&quot;&gt;&lt;b&gt;SVN, Maven 설치 후&lt;/b&gt; &amp;ldquo;Nexus에 빌드된 산출물을 배포&amp;rdquo;하는 구조가 될 수 있습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;999&quot; data-start=&quot;953&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;999&quot; data-start=&quot;953&quot;&gt;그래서 보통 SVN, Maven 다음에 Nexus 설치가 논리적으로 이어집니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1744679004127&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;wget https://download.sonatype.com/nexus/3/nexus-3.30.1-01-unix.tar.gz
tar -zxvf nexus-3.30.1-01-unix.tar.gz
sudo mv nexus-3.30.1-01 /poa/nexus
sudo mv sonatype-work /poa/sonatype-work

sudo chown -R poa:poa /poa/nexus
sudo chown -R poa:poa /poa/sonatype-work

sudo nano /poa/nexus/bin/nexus.rc

sudo nano /etc/systemd/system/nexus.service

vi /poa/sonatype-work/nexus3/etc/nexus.properties

sudo nano /poa/nexus/etc/nexus-default.properties

sudo systemctl enable nexus
sudo systemctl start nexus
sudo systemctl status nexus&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;10&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자세한 설명&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;2363&quot; data-start=&quot;12&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;507&quot; data-start=&quot;12&quot;&gt;&lt;b&gt;Nexus 다운로드 및 압축 해제&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;507&quot; data-start=&quot;260&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;306&quot; data-start=&quot;260&quot;&gt;Sonatype Nexus(3.30.1 버전)를 다운로드하고 압축을 풉니다.&lt;/li&gt;
&lt;li data-end=&quot;415&quot; data-start=&quot;310&quot;&gt;압축 해제 후 생성된 nexus-3.30.1-01 디렉터리를 /poa/nexus로, sonatype-work 디렉터리를 /poa/sonatype-work로 이동합니다.&lt;/li&gt;
&lt;li data-end=&quot;507&quot; data-start=&quot;419&quot;&gt;이렇게 하면 Nexus 실행 관련 파일은 /poa/nexus, 데이터(저장소, 설정파일) 등은 /poa/sonatype-work에 위치하게 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;256&quot; data-start=&quot;43&quot;&gt;&lt;b&gt;소유권 변경&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;755&quot; data-start=&quot;628&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;708&quot; data-start=&quot;628&quot;&gt;Nexus 실행 계정(예: poa)으로 /poa/nexus와 /poa/sonatype-work 디렉터리의 소유권을 변경합니다.&lt;/li&gt;
&lt;li data-end=&quot;755&quot; data-start=&quot;712&quot;&gt;이로써 Nexus가 파일을 읽고 쓸 수 있도록 적절한 권한을 갖게 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;624&quot; data-start=&quot;528&quot;&gt;&lt;b&gt;Nexus 설정 파일(nexus.rc) 수정&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;985&quot; data-start=&quot;851&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;913&quot; data-start=&quot;851&quot;&gt;일반적으로 nexus.rc 파일 안에는 run_as_user 환경변수를 설정하는 내용이 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;943&quot; data-start=&quot;917&quot;&gt;예: run_as_user=&quot;poa&quot;&lt;/li&gt;
&lt;li data-end=&quot;985&quot; data-start=&quot;947&quot;&gt;Nexus가 어떤 사용자 계정으로 동작할지를 지정할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;847&quot; data-start=&quot;794&quot;&gt;&lt;b&gt;Systemd 서비스 파일 생성(nexus.service)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1561&quot; data-start=&quot;1099&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1153&quot; data-start=&quot;1099&quot;&gt;Systemd를 통해 Nexus를 서비스(데몬)로 관리하기 위해 서비스 파일을 작성합니다.&lt;/li&gt;
&lt;li data-end=&quot;1498&quot; data-start=&quot;1157&quot;&gt;예시 내용(참고용):&lt;/li&gt;
&lt;li data-end=&quot;1498&quot; data-start=&quot;1176&quot;&gt;
&lt;div&gt;ini&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;복사&lt;/span&gt;&lt;span data-state=&quot;closed&quot;&gt;편집&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;[Unit]&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;Description&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=nexus service &lt;/span&gt;&lt;span&gt;&lt;span&gt;After&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=network.target &lt;/span&gt;&lt;span&gt;&lt;span&gt;[Service]&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;Type&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=forking &lt;/span&gt;&lt;span&gt;&lt;span&gt;LimitNOFILE&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt;65536&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;User&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=poa &lt;/span&gt;&lt;span&gt;&lt;span&gt;Group&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=poa &lt;/span&gt;&lt;span&gt;&lt;span&gt;ExecStart&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=/poa/nexus/bin/nexus start &lt;/span&gt;&lt;span&gt;&lt;span&gt;ExecStop&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=/poa/nexus/bin/nexus stop &lt;/span&gt;&lt;span&gt;&lt;span&gt;Restart&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt;on&lt;/span&gt;&lt;/span&gt;&lt;span&gt;-abort &lt;/span&gt;&lt;span&gt;&lt;span&gt;[Install]&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;WantedBy&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=multi-user.target &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1561&quot; data-start=&quot;1502&quot;&gt;작성 후 저장하면, systemd가 Nexus를 systemctl 명령어로 제어할 수 있게 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1095&quot; data-start=&quot;1032&quot;&gt;&lt;b&gt;포트 및 Nexus 속성 설정(nexus.properties, nexus-default.properties 등)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1986&quot; data-start=&quot;1638&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1693&quot; data-start=&quot;1638&quot;&gt;vi /poa/sonatype-work/nexus3/etc/nexus.properties&lt;/li&gt;
&lt;li data-end=&quot;1752&quot; data-start=&quot;1697&quot;&gt;sudo nano /poa/nexus/etc/nexus-default.properties&lt;/li&gt;
&lt;li data-end=&quot;1827&quot; data-start=&quot;1756&quot;&gt;Nexus가 사용할 포트(기본 8081), 호스트 IP, 데이터 디렉터리 위치 등을 이 파일(들)에 설정할 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;1923&quot; data-start=&quot;1831&quot;&gt;예시(기본 포트 변경 시):&lt;/li&gt;
&lt;li data-end=&quot;1923&quot; data-start=&quot;1854&quot;&gt;
&lt;div&gt;ini&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;복사&lt;/span&gt;&lt;span data-state=&quot;closed&quot;&gt;편집&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;application-port&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt;8081&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;application-host&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt;0.0&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;0.0&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1986&quot; data-start=&quot;1927&quot;&gt;필요에 따라 HTTPS 설정, Reverse Proxy 설정 등을 진행할 때도 이 파일들을 수정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;2363&quot; data-start=&quot;1988&quot;&gt;&lt;b&gt;Nexus 서비스 활성화 및 실행&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2363&quot; data-start=&quot;2131&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2193&quot; data-start=&quot;2131&quot;&gt;systemctl enable nexus로 서버 부팅 시 자동으로 Nexus가 실행되도록 설정합니다.&lt;/li&gt;
&lt;li data-end=&quot;2282&quot; data-start=&quot;2197&quot;&gt;systemctl start nexus로 Nexus 서비스를 실행하고, systemctl status nexus로 현재 상태를 확인합니다.&lt;/li&gt;
&lt;li data-end=&quot;2363&quot; data-start=&quot;2286&quot;&gt;실행 후 Nexus 콘솔 로깅(/poa/sonatype-work/nexus3/log) 등을 통해 문제가 없는지 확인할 수 있습니다.&lt;/li&gt;
&lt;/ul&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;h2 data-end=&quot;1029&quot; data-start=&quot;1006&quot; data-ke-size=&quot;size26&quot;&gt;4. CI/CD 툴 (Jenkins)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1276&quot; data-start=&quot;1030&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1096&quot; data-start=&quot;1030&quot;&gt;Jenkins가 Maven 빌드를 실행하고, SVN에서 코드를 체크아웃하여 Nexus로 올리는 파이프라인을 구성&lt;/li&gt;
&lt;li data-end=&quot;1222&quot; data-start=&quot;1097&quot;&gt;따라서 Jenkins 설치 시점에는 &lt;b&gt;SVN, Maven, Nexus&lt;/b&gt;가 이미 구축돼 있으면 세팅이 쉬워집니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1222&quot; data-start=&quot;1168&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1222&quot; data-start=&quot;1168&quot;&gt;Jenkins &amp;rarr; SVN(코드 가져오기) &amp;rarr; Maven(빌드) &amp;rarr; Nexus(결과물 저장)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1276&quot; data-start=&quot;1223&quot;&gt;Jenkins 이후에는 DB나 WAS와 연동해서 자동 배포 파이프라인을 확장할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1744679167784&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;wget https://get.jenkins.io/war-stable/latest/jenkins.war -P /poa/

java -jar /poa/jenkins.war --httpPort=9878

sudo nano /etc/systemd/system/jenkins.service

[Unit]
Description=Jenkins Daemon
After=network.target

[Service]
User=poa
WorkingDirectory=/poa
Restart=always
Environment=&quot;JAVA_HOME=/poa/java/jdk-17.0.2&quot;
Environment=&quot;PATH=/poa/java/jdk-17.0.2/bin:/usr/bin:/bin&quot;
ExecStart=/poa/java/jdk-17.0.2/bin/java -DJENKINS_HOME=/poa/jenkins -jar /poa/jenkins.war --httpPort=9878
Environment=&quot;JENKINS_HOME=/poa/jenkins&quot;

[Install]
WantedBy=multi-user.target

sudo systemctl daemon-reload
sudo systemctl start jenkins
sudo systemctl enable jenkins&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;10&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자세한 설명&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;2109&quot; data-start=&quot;12&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;199&quot; data-start=&quot;12&quot;&gt;&lt;b&gt;Jenkins WAR 파일 다운로드&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;199&quot; data-start=&quot;134&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;199&quot; data-start=&quot;134&quot;&gt;최신 안정 버전(Stale Release)의 Jenkins WAR 파일을 /poa/ 디렉터리에 다운로드합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;130&quot; data-start=&quot;44&quot;&gt;&lt;b&gt;Jenkins 수동 실행 (테스트용)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;509&quot; data-start=&quot;300&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;363&quot; data-start=&quot;300&quot;&gt;다운로드 받은 jenkins.war를 직접 실행하며, 9878 포트를 통해 접근 가능하도록 설정합니다.&lt;/li&gt;
&lt;li data-end=&quot;449&quot; data-start=&quot;367&quot;&gt;이 상태에서 브라우저로 http://&amp;lt;서버IP&amp;gt;:9878에 접속하면 Jenkins 설치 마법사(초기 설정 페이지)에 접속할 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;509&quot; data-start=&quot;453&quot;&gt;단, 이렇게 실행하면 현재 터미널 세션에 종속되므로, 터미널을 닫으면 Jenkins가 중단됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;296&quot; data-start=&quot;234&quot;&gt;&lt;b&gt;Systemd 서비스 파일 생성&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1585&quot; data-start=&quot;608&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;658&quot; data-start=&quot;608&quot;&gt;jenkins.service라는 systemd 유닛 파일을 생성(또는 열기)합니다.&lt;/li&gt;
&lt;li data-end=&quot;1164&quot; data-start=&quot;663&quot;&gt;작성 예시(사용자 제공 내용):&lt;/li&gt;
&lt;li data-end=&quot;1164&quot; data-start=&quot;688&quot;&gt;
&lt;div&gt;ini&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;복사&lt;/span&gt;&lt;span data-state=&quot;closed&quot;&gt;편집&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;[Unit]&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;Description&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=Jenkins Daemon &lt;/span&gt;&lt;span&gt;&lt;span&gt;After&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=network.target &lt;/span&gt;&lt;span&gt;&lt;span&gt;[Service]&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;User&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=poa &lt;/span&gt;&lt;span&gt;&lt;span&gt;WorkingDirectory&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=/poa &lt;/span&gt;&lt;span&gt;&lt;span&gt;Restart&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=always &lt;/span&gt;&lt;span&gt;&lt;span&gt;Environment&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;JAVA_HOME=/poa/java/jdk-17.0.2&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;Environment&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;PATH=/poa/java/jdk-17.0.2/bin:/usr/bin:/bin&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;ExecStart&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=/poa/java/jdk-&lt;/span&gt;&lt;span&gt;&lt;span&gt;17.0&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;span&gt;/bin/java -DJENKINS_HOME=/poa/jenkins -jar /poa/jenkins.war --httpPort=&lt;/span&gt;&lt;span&gt;&lt;span&gt;9878&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;Environment&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;JENKINS_HOME=/poa/jenkins&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;[Install]&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;WantedBy&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=multi-user.target &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1585&quot; data-start=&quot;1168&quot;&gt;&lt;b&gt;주요 설정&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1585&quot; data-start=&quot;1186&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1235&quot; data-start=&quot;1186&quot;&gt;&lt;b&gt;User=poa&lt;/b&gt;: Jenkins 프로세스를 poa 계정으로 실행합니다.&lt;/li&gt;
&lt;li data-end=&quot;1301&quot; data-start=&quot;1241&quot;&gt;&lt;b&gt;WorkingDirectory=/poa&lt;/b&gt;: Jenkins 프로세스가 동작할 기본 디렉터리입니다.&lt;/li&gt;
&lt;li data-end=&quot;1358&quot; data-start=&quot;1307&quot;&gt;&lt;b&gt;Restart=always&lt;/b&gt;: 프로세스가 종료되면 자동 재시작하도록 설정합니다.&lt;/li&gt;
&lt;li data-end=&quot;1433&quot; data-start=&quot;1364&quot;&gt;&lt;b&gt;Environment&lt;/b&gt;: JAVA_HOME, PATH, JENKINS_HOME 등 필수 환경 변수를 설정합니다.&lt;/li&gt;
&lt;li data-end=&quot;1585&quot; data-start=&quot;1439&quot;&gt;&lt;b&gt;ExecStart&lt;/b&gt;: Jenkins를 실행하는 실제 명령어입니다. -DJENKINS_HOME=/poa/jenkins 옵션을 통해 Jenkins 홈 디렉터리를 /poa/jenkins로 지정하고, --httpPort=9878로 포트를 설정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;604&quot; data-start=&quot;541&quot;&gt;&lt;b&gt;Systemd 데몬 재로드&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1728&quot; data-start=&quot;1664&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1728&quot; data-start=&quot;1664&quot;&gt;새로 생성한 jenkins.service 파일을 systemd가 인식할 수 있도록 데몬 정보를 재로드합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1660&quot; data-start=&quot;1614&quot;&gt;&lt;b&gt;Jenkins 서비스 시작 및 활성화&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1906&quot; data-start=&quot;1848&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1906&quot; data-start=&quot;1848&quot;&gt;Jenkins 서비스를 바로 시작하고, 서버 부팅 시 자동으로 실행되도록 활성화(enable)합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1844&quot; data-start=&quot;1763&quot;&gt;&lt;b&gt;접속 확인&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2109&quot; data-start=&quot;1926&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1997&quot; data-start=&quot;1926&quot;&gt;브라우저에서 http://&amp;lt;서버 IP 또는 도메인&amp;gt;:9878로 접속해서, Jenkins 초기 설정 화면을 확인합니다.&lt;/li&gt;
&lt;li data-end=&quot;2109&quot; data-start=&quot;2001&quot;&gt;최초 실행 시 /poa/jenkins 폴더 내에 initialAdminPassword 파일이 생성되며, 그 암호를 통해 Administrator 계정 초기 설정을 진행할 수 있습니다.&lt;/li&gt;
&lt;/ul&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;h2 data-end=&quot;1302&quot; data-start=&quot;1283&quot; data-ke-size=&quot;size26&quot;&gt;5. DB (Database)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1581&quot; data-start=&quot;1303&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1387&quot; data-start=&quot;1303&quot;&gt;DB가 필요없는 애플리케이션이라면 건너뛸 수 있지만, &lt;b&gt;실제로는 WAS나 애플리케이션 구동 테스트 시 DB 연결&lt;/b&gt;이 필요한 경우가 많습니다.&lt;/li&gt;
&lt;li data-end=&quot;1461&quot; data-start=&quot;1388&quot;&gt;예시:
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1461&quot; data-start=&quot;1396&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1444&quot; data-start=&quot;1396&quot;&gt;MariaDB, MySQL, PostgreSQL, Oracle 등 원하는 DB 설치&lt;/li&gt;
&lt;li data-end=&quot;1461&quot; data-start=&quot;1447&quot;&gt;DB 계정&amp;middot;스키마 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1581&quot; data-start=&quot;1462&quot;&gt;&lt;b&gt;WAS 설치 전&lt;/b&gt;에 DB가 준비돼 있으면, WAS 설정 시 JDBC 연동, 환경설정 파일(application.yml, server.xml 등)에서 DB URL을 바로 입력해 테스트할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1744679271161&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd /poa/data
wget https://downloads.mariadb.com/MariaDB/mariadb-10.11.4/source/mariadb-10.11.4.tar.gz
tar -xvzf mariadb-10.11.4.tar.gz
mv mariadb-10.11.4 /poa/server/db

sudo apt update
sudo apt install cmake gcc g++ libncurses5-dev bison -y

cd /poa/server/db/mariadb-10.11.4
cmake -DCMAKE_INSTALL_PREFIX=/poa/server/db/mariadb
make
sudo make install

mkdir -p /poa/server/db/mariadb/etc
nano /poa/server/db/mariadb/etc/my.cnf
[mysqld]
port = 9880
basedir = /poa/server/db/mariadb
datadir = /poa/server/db/mariadb/data
socket = /poa/server/db/mariadb/mariadb.sock
log-error = /poa/server/db/mariadb/logs/mariadb.err
pid-file = /poa/server/db/mariadb/mariadb.pid
[client]
socket = /poa/server/db/mariadb/mariadb.sock

mkdir -p /poa/server/db/mariadb/data
mkdir -p /poa/server/db/mariadb/logs

/poa/server/db/mariadb/scripts/mysql_install_db --user=poa --basedir=/poa/server/db/mariadb --datadir=/poa/server/db/mariadb/data
sudo -u poa /poa/server/db/mariadb/bin/mysqld_safe --defaults-file=/poa/server/db/mariadb/etc/my.cnf --datadir=/poa/server/db/mariadb/data &amp;amp;

/poa/server/db/mariadb/bin/mysql_secure_installation --socket=/poa/server/db/mariadb/mariadb.sock

/poa/server/db/mariadb/bin/mysql -u root -p --socket=/poa/server/db/mariadb/mariadb.sock&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;10&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자세한 설명&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;2959&quot; data-start=&quot;12&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;361&quot; data-start=&quot;12&quot;&gt;&lt;b&gt;소스 파일 다운로드 및 준비&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;361&quot; data-start=&quot;237&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;301&quot; data-start=&quot;237&quot;&gt;/poa/data 폴더로 이동한 뒤, mariadb-10.11.4 소스를 다운로드하고 압축을 해제합니다.&lt;/li&gt;
&lt;li data-end=&quot;361&quot; data-start=&quot;305&quot;&gt;압축 해제 후 폴더명을 /poa/server/db/mariadb-10.11.4로 옮겨 둡니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;233&quot; data-start=&quot;38&quot;&gt;&lt;b&gt;빌드에 필요한 패키지 설치&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;556&quot; data-start=&quot;484&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;556&quot; data-start=&quot;484&quot;&gt;Mariadb(또는 MySQL) 소스 빌드에 필요한 cmake, gcc, g++, ncurses, bison 등을 설치합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;480&quot; data-start=&quot;388&quot;&gt;&lt;b&gt;MariaDB 빌드 및 설치&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;880&quot; data-start=&quot;723&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;817&quot; data-start=&quot;723&quot;&gt;cmake 실행 시 -DCMAKE_INSTALL_PREFIX 옵션을 통해 MariaDB 설치 경로를 /poa/server/db/mariadb로 지정합니다.&lt;/li&gt;
&lt;li data-end=&quot;880&quot; data-start=&quot;821&quot;&gt;make 명령어로 소스를 빌드하고, sudo make install으로 해당 경로에 설치합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;719&quot; data-start=&quot;584&quot;&gt;&lt;b&gt;설정 파일 작성(my.cnf)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1529&quot; data-start=&quot;1008&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1395&quot; data-start=&quot;1008&quot;&gt;my.cnf에 다음과 같은 설정을 추가할 수 있습니다:&lt;/li&gt;
&lt;li data-end=&quot;1395&quot; data-start=&quot;1048&quot;&gt;
&lt;div&gt;ini&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;복사&lt;/span&gt;&lt;span data-state=&quot;closed&quot;&gt;편집&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;[mysqld]&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;port&lt;/span&gt;&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&lt;span&gt;9880&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;basedir&lt;/span&gt;&lt;/span&gt;&lt;span&gt; = /poa/server/db/mariadb &lt;/span&gt;&lt;span&gt;&lt;span&gt;datadir&lt;/span&gt;&lt;/span&gt;&lt;span&gt; = /poa/server/db/mariadb/data &lt;/span&gt;&lt;span&gt;&lt;span&gt;socket&lt;/span&gt;&lt;/span&gt;&lt;span&gt; = /poa/server/db/mariadb/mariadb.sock &lt;/span&gt;&lt;span&gt;&lt;span&gt;log-error&lt;/span&gt;&lt;/span&gt;&lt;span&gt; = /poa/server/db/mariadb/logs/mariadb.err &lt;/span&gt;&lt;span&gt;&lt;span&gt;pid-file&lt;/span&gt;&lt;/span&gt;&lt;span&gt; = /poa/server/db/mariadb/mariadb.pid &lt;/span&gt;&lt;span&gt;&lt;span&gt;[client]&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;socket&lt;/span&gt;&lt;/span&gt;&lt;span&gt; = /poa/server/db/mariadb/mariadb.sock &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1476&quot; data-start=&quot;1399&quot;&gt;mysqld 섹션에서는 포트(9880), 설치 경로(basedir), 데이터 디렉터리(datadir), 소켓 경로 등을 지정합니다.&lt;/li&gt;
&lt;li data-end=&quot;1529&quot; data-start=&quot;1480&quot;&gt;client 섹션에서는 클라이언트가 사용할 소켓 경로를 동일하게 맞춰줘야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1004&quot; data-start=&quot;909&quot;&gt;&lt;b&gt;데이터 및 로그 디렉터리 생성&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1698&quot; data-start=&quot;1656&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1698&quot; data-start=&quot;1656&quot;&gt;데이터베이스 파일 및 로그 파일을 저장할 디렉터리를 미리 만들어 둡니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1652&quot; data-start=&quot;1558&quot;&gt;&lt;b&gt;DB 초기화&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2040&quot; data-start=&quot;1895&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1936&quot; data-start=&quot;1895&quot;&gt;MariaDB를 처음 사용할 때 필요한 시스템 테이블 등을 생성합니다.&lt;/li&gt;
&lt;li data-end=&quot;1985&quot; data-start=&quot;1940&quot;&gt;--user=poa는 데이터베이스를 실행할 계정(사용자)을 지정합니다.&lt;/li&gt;
&lt;li data-end=&quot;2040&quot; data-start=&quot;1989&quot;&gt;--basedir 및 --datadir를 앞서 지정한 경로와 동일하게 맞춰줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1891&quot; data-start=&quot;1717&quot;&gt;&lt;b&gt;MariaDB 서버 실행&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2423&quot; data-start=&quot;2246&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2301&quot; data-start=&quot;2246&quot;&gt;mysqld_safe 스크립트를 이용해 MariaDB 서버를 백그라운드(&amp;amp;)에서 실행합니다.&lt;/li&gt;
&lt;li data-end=&quot;2352&quot; data-start=&quot;2305&quot;&gt;sudo -u poa는 poa 사용자로 프로세스를 실행하겠다는 의미입니다.&lt;/li&gt;
&lt;li data-end=&quot;2423&quot; data-start=&quot;2356&quot;&gt;--defaults-file 옵션에 우리가 생성한 my.cnf 파일 경로를 지정하여, 해당 설정을 적용합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;2242&quot; data-start=&quot;2066&quot;&gt;&lt;b&gt;보안 설정(mysql_secure_installation)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2719&quot; data-start=&quot;2596&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2667&quot; data-start=&quot;2596&quot;&gt;기본 root 암호 설정, 익명 사용자 삭제, 원격 root 접속 차단 등 보안 관련 설정을 간편하게 해주는 스크립트입니다.&lt;/li&gt;
&lt;li data-end=&quot;2719&quot; data-start=&quot;2671&quot;&gt;--socket 옵션으로 우리가 지정한 소켓 경로를 설정하여 로컬로 연결합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;2592&quot; data-start=&quot;2468&quot;&gt;&lt;b&gt;MariaDB 접속 확인&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2959&quot; data-start=&quot;2864&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2899&quot; data-start=&quot;2864&quot;&gt;설정한 root 암호를 사용하여 MariaDB에 접속합니다.&lt;/li&gt;
&lt;li data-end=&quot;2959&quot; data-start=&quot;2903&quot;&gt;접속 후 show databases; 등의 명령을 통해 정상 작동 여부를 확인할 수 있습니다.&lt;/li&gt;
&lt;/ul&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;h2 data-end=&quot;1622&quot; data-start=&quot;1588&quot; data-ke-size=&quot;size26&quot;&gt;6. WAS (Web Application Server)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1804&quot; data-start=&quot;1623&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1680&quot; data-start=&quot;1623&quot;&gt;예: &lt;b&gt;Tomcat&lt;/b&gt;, &lt;b&gt;WildFly&lt;/b&gt;, &lt;b&gt;WebSphere&lt;/b&gt;, &lt;b&gt;JEUS&lt;/b&gt; 등&lt;/li&gt;
&lt;li data-end=&quot;1749&quot; data-start=&quot;1681&quot;&gt;&lt;b&gt;DB가 준비된 상태&lt;/b&gt;에서 WAS의 데이터소스, 또는 Spring Boot 앱 배포 시 DB 연결 테스트가 가능&lt;/li&gt;
&lt;li data-end=&quot;1804&quot; data-start=&quot;1750&quot;&gt;&amp;ldquo;WAS &amp;rarr; DB&amp;rdquo; 연결이 정상 동작하는지 확인 후, 애플리케이션(WAR/JAR) 배포를 진행&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1744679407141&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd /poa/data
wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.97/bin/apache-tomcat-9.0.97.tar.gz
tar -xvzf apache-tomcat-9.0.97.tar.gz
mv apache-tomcat-9.0.97 /poa/server/was/tomcat-9.0.97

nano /poa/server/was/tomcat-9.0.97/conf/server.xml

/poa/server/was/tomcat-9.0.97/bin/startup.sh&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;10&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자세한 설명&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1017&quot; data-start=&quot;12&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;440&quot; data-start=&quot;12&quot;&gt;&lt;b&gt;Tomcat 9.0.97 다운로드 및 압축 해제&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;440&quot; data-start=&quot;270&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;323&quot; data-start=&quot;270&quot;&gt;/poa/data 디렉터리로 이동한 뒤, Tomcat 9.0.97 버전을 다운로드합니다.&lt;/li&gt;
&lt;li data-end=&quot;379&quot; data-start=&quot;327&quot;&gt;다운로드한 파일(apache-tomcat-9.0.97.tar.gz)을 압축 해제합니다.&lt;/li&gt;
&lt;li data-end=&quot;440&quot; data-start=&quot;383&quot;&gt;압축 해제 후 폴더명을 /poa/server/was/tomcat-9.0.97로 이동&amp;middot;정리합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;266&quot; data-start=&quot;49&quot;&gt;&lt;b&gt;서버 설정 파일(server.xml) 수정&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;763&quot; data-start=&quot;548&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;612&quot; data-start=&quot;548&quot;&gt;Tomcat의 주요 설정(포트, 커넥터, 리스너 등)은 conf/server.xml에서 변경할 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;692&quot; data-start=&quot;616&quot;&gt;예를 들어, 기본 HTTP 포트(8080)를 다른 포트로 바꾸거나, AJP 커넥터(8009) 설정을 변경할 때 이 파일을 수정합니다.&lt;/li&gt;
&lt;li data-end=&quot;763&quot; data-start=&quot;696&quot;&gt;필요에 따라 &amp;lt;Connector port=&quot;8080&quot; ... /&amp;gt; 부분 등을 원하는 값으로 변경한 뒤 저장합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;544&quot; data-start=&quot;476&quot;&gt;&lt;b&gt;Tomcat 서버 실행&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1017&quot; data-start=&quot;854&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;885&quot; data-start=&quot;854&quot;&gt;Tomcat을 백그라운드에서 실행하는 스크립트입니다.&lt;/li&gt;
&lt;li data-end=&quot;957&quot; data-start=&quot;889&quot;&gt;실행 후 브라우저에서 http://&amp;lt;서버IP나도메인&amp;gt;:포트번호/ 로 접속하면 Tomcat 기본 페이지가 표시됩니다.&lt;/li&gt;
&lt;li data-end=&quot;1017&quot; data-start=&quot;961&quot;&gt;기본 포트(8080)를 그대로 두었다면 http://&amp;lt;서버IP&amp;gt;:8080으로 접근 가능합니다.&lt;/li&gt;
&lt;/ul&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;h2 data-end=&quot;1845&quot; data-start=&quot;1811&quot; data-ke-size=&quot;size26&quot;&gt;7. Web Server (Apache, Nginx 등)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2089&quot; data-start=&quot;1846&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1899&quot; data-start=&quot;1846&quot;&gt;보통 &lt;b&gt;Reverse Proxy&lt;/b&gt;나 &lt;b&gt;SSL 종료&lt;/b&gt;(HTTPS) 용도로 많이 사용&lt;/li&gt;
&lt;li data-end=&quot;1940&quot; data-start=&quot;1900&quot;&gt;WAS 앞단에 &amp;ldquo;로드밸런싱&amp;rdquo; 또는 &amp;ldquo;정적 리소스 제공&amp;rdquo; 등을 담당&lt;/li&gt;
&lt;li data-end=&quot;2018&quot; data-start=&quot;1941&quot;&gt;&lt;b&gt;WAS가 먼저 깔려있어야&lt;/b&gt;, Web 서버에서 ProxyPass나 Nginx 설정을 해서 리다이렉트/프록시 기능을 쓸 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;2089&quot; data-start=&quot;2019&quot;&gt;한편, 개발/테스트 환경에서는 굳이 Web 서버 없이 &lt;b&gt;WAS 단독&lt;/b&gt;(Tomcat의 HTTP 포트)으로 쓰기도 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1744679481141&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd /poa/da
wget https://downloads.apache.org/httpd/httpd-2.4.62.tar.gz
tar -xvzf httpd-2.4.62.tar.gz
mv httpd-2.4.62 /poa/server/web/apache

cd /poa/server/web/apache
./configure --prefix=/poa/server/web --enable-ssl --enable-so
make
sudo make install

/poa/server/web/bin/apachectl start&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;10&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자세한 설명&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1062&quot; data-start=&quot;12&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;361&quot; data-start=&quot;12&quot;&gt;&lt;b&gt;Apache HTTP Server 소스 다운로드 및 압축 해제&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;361&quot; data-start=&quot;229&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;286&quot; data-start=&quot;229&quot;&gt;/poa/da 디렉터리로 이동 후, httpd-2.4.62.tar.gz를 다운로드합니다.&lt;/li&gt;
&lt;li data-end=&quot;361&quot; data-start=&quot;290&quot;&gt;다운로드된 파일을 해제(tar -xvzf)한 뒤, /poa/server/web/apache로 디렉터리명을 변경합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;225&quot; data-start=&quot;59&quot;&gt;&lt;b&gt;Apache HTTP Server 빌드&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;812&quot; data-start=&quot;538&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;577&quot; data-start=&quot;538&quot;&gt;configure 스크립트를 이용해 빌드 환경을 설정합니다.&lt;/li&gt;
&lt;li data-end=&quot;657&quot; data-start=&quot;581&quot;&gt;--prefix=/poa/server/web 옵션을 사용하면 Apache가 /poa/server/web 경로에 설치됩니다.&lt;/li&gt;
&lt;li data-end=&quot;754&quot; data-start=&quot;661&quot;&gt;--enable-ssl은 SSL 모듈(HTTPS 기능)을 활성화하고, --enable-so는 동적 모듈 로딩(so 모듈)을 사용할 수 있도록 설정합니다.&lt;/li&gt;
&lt;li data-end=&quot;812&quot; data-start=&quot;758&quot;&gt;make 명령으로 컴파일을 진행한 후, sudo make install으로 설치합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;534&quot; data-start=&quot;397&quot;&gt;&lt;b&gt;Apache 서버 구동&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1062&quot; data-start=&quot;896&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;965&quot; data-start=&quot;896&quot;&gt;설치가 완료되면 /poa/server/web/bin/apachectl 스크립트를 사용해 Apache를 시작합니다.&lt;/li&gt;
&lt;li data-end=&quot;1062&quot; data-start=&quot;969&quot;&gt;웹 브라우저에서 http://&amp;lt;서버 IP&amp;gt;:80 (기본 포트가 80으로 설정되었을 경우)로 접속했을 때 Apache 테스트 페이지가 뜨면 정상 실행된 것입니다.&lt;/li&gt;
&lt;/ul&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;h2 data-end=&quot;2118&quot; data-start=&quot;2096&quot; data-ke-size=&quot;size26&quot;&gt;8. 실제 운영/배포 시나리오 예시&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;2482&quot; data-start=&quot;2120&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;2173&quot; data-start=&quot;2120&quot;&gt;&lt;b&gt;(OS 세팅) &amp;rarr; Maven, SVN&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2173&quot; data-start=&quot;2153&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2173&quot; data-start=&quot;2153&quot;&gt;코드 버전 관리, 빌드 도구 준비&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;2204&quot; data-start=&quot;2174&quot;&gt;&lt;b&gt;Nexus&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2204&quot; data-start=&quot;2192&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2204&quot; data-start=&quot;2192&quot;&gt;빌드 산출물 저장소&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;2266&quot; data-start=&quot;2205&quot;&gt;&lt;b&gt;Jenkins&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2266&quot; data-start=&quot;2225&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2266&quot; data-start=&quot;2225&quot;&gt;빌드 &amp;amp; 배포 자동화 (SVN &amp;rarr; Maven &amp;rarr; Nexus 파이프라인)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;2302&quot; data-start=&quot;2267&quot;&gt;&lt;b&gt;DB 설치&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2302&quot; data-start=&quot;2285&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2302&quot; data-start=&quot;2285&quot;&gt;DB 계정/권한/스키마 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;2394&quot; data-start=&quot;2303&quot;&gt;&lt;b&gt;WAS 설치&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2394&quot; data-start=&quot;2322&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2354&quot; data-start=&quot;2322&quot;&gt;DB 연동 설정, 애플리케이션(WAR/JAR) 배포&lt;/li&gt;
&lt;li data-end=&quot;2394&quot; data-start=&quot;2358&quot;&gt;Jenkins 파이프라인에서 빌드 결과물을 WAS에 자동 배포&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;2482&quot; data-start=&quot;2395&quot;&gt;&lt;b&gt;Web Server 설치(아파치, Nginx)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2482&quot; data-start=&quot;2433&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2482&quot; data-start=&quot;2433&quot;&gt;최종 외부 트래픽 수신, HTTPS(SSL) 적용, 프록시 &amp;rarr; WAS 로 트래픽 전달&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;주의: 실제로는 회사마다 시스템 정책, 네트워크 구조, 서버 리소스 배치에 따라 순서가 달라질 수 있습니다. &amp;ldquo;무조건 이 순서&amp;rdquo;라기보다는,&lt;br /&gt;&lt;br /&gt;빌드&amp;rarr;배포&amp;rarr;운영 흐름에 맞춰 개발/CI/CD 도구(SVN, Maven, Jenkins, Nexus) 먼저, &lt;br /&gt;애플리케이션 구동에 필요한 DB &amp;amp; WAS, &lt;br /&gt;최종 외부 서비스용 Web 서버 순으로 가는 것이 일반적입니다.&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-end=&quot;127&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;Tomcat에서 &lt;b&gt;MariaDB&lt;/b&gt;에 접속하기 위해 &lt;b&gt;JDBC 드라이버&lt;/b&gt;를 Tomcat &lt;b&gt;lib&lt;/b&gt; 폴더에 두고, &lt;b&gt;context.xml&lt;/b&gt;에 데이터소스(JNDI) 정보를 설정하는 과정입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;424&quot; data-start=&quot;129&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;230&quot; data-start=&quot;129&quot;&gt;&lt;b&gt;JDBC 드라이버&lt;/b&gt;를 추가함으로써, Tomcat이 MariaDB에 연결할 때 필요한 클래스( org.mariadb.jdbc.Driver )를 인식할 수 있게 됩니다.&lt;/li&gt;
&lt;li data-end=&quot;344&quot; data-start=&quot;231&quot;&gt;&lt;b&gt;context.xml&lt;/b&gt;의 &amp;lt;Resource&amp;gt; 설정을 통해, 웹 애플리케이션은 java:comp/env/jdbc/MyDB라는 &lt;b&gt;JNDI&lt;/b&gt; 이름으로 DB 커넥션을 받아올 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;424&quot; data-start=&quot;345&quot;&gt;이렇게 하면 각 애플리케이션에서 따로 DB 접속 정보를 관리할 필요 없이, 서버(Tomcat) 레벨에서 통합 관리되어 편리하고 안전합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1744679945948&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;wget https://downloads.mariadb.com/Connectors/java/connector-java-3.2.0/mariadb-java-client-3.2.0.jar

mv mariadb-java-client-3.2.0.jar /poa/server/was/tomcat-9.0.97/lib/mariadb-java-client-3.2.0.jar

nano /poa/server/was/tomcat-9.0.97/conf/context.xml

&amp;lt;Resource name=&quot;jdbc/MyDB&quot;
          auth=&quot;Container&quot;
          type=&quot;javax.sql.DataSource&quot;
          maxTotal=&quot;20&quot;
          maxIdle=&quot;10&quot;
          username=&quot;your_db_user&quot;
          password=&quot;your_db_password&quot;
          driverClassName=&quot;org.mariadb.jdbc.Driver&quot;
          url=&quot;jdbc:mariadb://localhost:3306/your_database_name&quot;/&amp;gt;

/poa/server/web/bin/apachectl start

/poa/server/was/bin/startup.sh

/poa/server/db/mariadb/bin/mysqld_safe --datadir=/poa/server/db/mariadb/data &amp;amp;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;10&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자세한 설명&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;2231&quot; data-start=&quot;12&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;452&quot; data-start=&quot;12&quot;&gt;&lt;b&gt;MariaDB JDBC 드라이버(JAR) 다운로드 및 배치&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;452&quot; data-start=&quot;282&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;367&quot; data-start=&quot;282&quot;&gt;최신 버전의 &lt;b&gt;MariaDB Java Connector&lt;/b&gt;(JDBC 드라이버)를 다운로드한 뒤, Tomcat의 lib 디렉터리에 배치합니다.&lt;/li&gt;
&lt;li data-end=&quot;452&quot; data-start=&quot;371&quot;&gt;이 JAR 파일이 Tomcat 내부에서 동작하는 웹 애플리케이션들이 org.mariadb.jdbc.Driver를 사용할 수 있게 해줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;278&quot; data-start=&quot;57&quot;&gt;&lt;b&gt;Tomcat context.xml 설정&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1234&quot; data-start=&quot;919&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;966&quot; data-start=&quot;919&quot;&gt;Tomcat의 context.xml에 &lt;b&gt;데이터 소스 리소스&lt;/b&gt;를 등록합니다.&lt;/li&gt;
&lt;li data-end=&quot;1057&quot; data-start=&quot;970&quot;&gt;name=&quot;jdbc/MyDB&quot;는 JNDI 리소스 이름이며, 애플리케이션에서 java:comp/env/jdbc/MyDB 형태로 참조할 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;1158&quot; data-start=&quot;1061&quot;&gt;username, password는 DB 접속 정보이며, driverClassName과 url을 통해 MariaDB에 접속할 드라이버와 URL을 지정합니다.&lt;/li&gt;
&lt;li data-end=&quot;1234&quot; data-start=&quot;1162&quot;&gt;maxTotal, maxIdle 등은 커넥션 풀 관련 설정으로, 최대 연결 수, 유휴(Idle) 연결 수를 제한합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;915&quot; data-start=&quot;488&quot;&gt;&lt;b&gt;서버 실행 순서 예시&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1838&quot; data-start=&quot;1431&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1536&quot; data-start=&quot;1431&quot;&gt;&lt;b&gt;Apache&lt;/b&gt;(apachectl start), &lt;b&gt;Tomcat&lt;/b&gt;(startup.sh), &lt;b&gt;MariaDB&lt;/b&gt;(mysqld_safe) 순으로 서비스를 시작하고 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;1711&quot; data-start=&quot;1540&quot;&gt;실제 운영환경에서는 보통 DB가 먼저 구동되고, Tomcat(또는 WAS)이 다음에 구동되며, Apache가 가장 마지막에 구동되는 경우가 많습니다. (즉, DB &amp;rarr; WAS &amp;rarr; Web 순서)
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1711&quot; data-start=&quot;1654&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1711&quot; data-start=&quot;1654&quot;&gt;하지만 여기서는 명령어를 예시로 보여준 것일 수 있으므로, 순서는 상황에 맞게 조정하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1800&quot; data-start=&quot;1715&quot;&gt;MariaDB를 실행할 때 --datadir=/poa/server/db/mariadb/data 옵션으로 데이터가 저장될 경로를 지정하고 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;1838&quot; data-start=&quot;1804&quot;&gt;&amp;amp; 기호로 백그라운드에서 프로세스를 실행하도록 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1427&quot; data-start=&quot;1258&quot;&gt;&lt;b&gt;JNDI 데이터소스 사용&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2231&quot; data-start=&quot;1866&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1948&quot; data-start=&quot;1866&quot;&gt;Tomcat이 실행된 뒤에는, 웹 애플리케이션 내에서 java:comp/env/jdbc/MyDB 리소스를 찾아 커넥션을 얻어올 수 있습니다.&lt;/li&gt;
&lt;/ul&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 data-end=&quot;112&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;이 설정( mod_jk )은 &lt;b&gt;Apache 웹 서버&lt;/b&gt;와 &lt;b&gt;Tomcat&lt;/b&gt;(Java 애플리케이션 서버)을 &lt;b&gt;AJP&lt;/b&gt; 프로토콜로 연결해 주는 다리(브리지) 역할을 합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;675&quot; data-start=&quot;114&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;394&quot; data-start=&quot;114&quot;&gt;&lt;b&gt;왜 필요한가?&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;394&quot; data-start=&quot;132&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;206&quot; data-start=&quot;132&quot;&gt;Apache 웹 서버(HTTPD)는 정적인 컨텐츠(HTML, CSS, JS, 이미지)를 빠르게 제공하는 데 특화되어 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;270&quot; data-start=&quot;209&quot;&gt;Tomcat은 Java 기반 웹 애플리케이션을 구동하고 동적인 요청(서블릿, JSP 등)을 처리합니다.&lt;/li&gt;
&lt;li data-end=&quot;360&quot; data-start=&quot;273&quot;&gt;이 둘을 한 서버에서 함께 사용하거나, 외부에선 Apache만 공개하고 Tomcat은 내부에서만 동작하게 하려면 둘 사이를 연결할 방법이 필요합니다.&lt;/li&gt;
&lt;li data-end=&quot;394&quot; data-start=&quot;363&quot;&gt;그 연결을 담당하는 모듈이 &lt;b&gt;mod_jk&lt;/b&gt;입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;675&quot; data-start=&quot;396&quot;&gt;&lt;b&gt;어떻게 동작하나?&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;675&quot; data-start=&quot;416&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;463&quot; data-start=&quot;416&quot;&gt;사용자가 http://서버/tomcat/무언가 URL로 요청을 보냅니다.&lt;/li&gt;
&lt;li data-end=&quot;545&quot; data-start=&quot;466&quot;&gt;Apache는 JkMount 설정을 보고 /tomcat/으로 시작하는 경로는 &lt;b&gt;mod_jk&lt;/b&gt; 모듈에게 처리하라고 넘깁니다.&lt;/li&gt;
&lt;li data-end=&quot;603&quot; data-start=&quot;548&quot;&gt;&lt;b&gt;mod_jk&lt;/b&gt;는 AJP(8009 포트 등)를 통해 Tomcat으로 요청을 전달합니다.&lt;/li&gt;
&lt;li data-end=&quot;675&quot; data-start=&quot;606&quot;&gt;Tomcat이 요청을 처리한 뒤 응답을 Apache에 되돌려 주면, Apache가 최종적으로 클라이언트에게 전송합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;696&quot; data-start=&quot;677&quot; data-ke-size=&quot;size16&quot;&gt;정리하면, &lt;b&gt;mod_jk&lt;/b&gt;는&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;809&quot; data-start=&quot;697&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;755&quot; data-start=&quot;697&quot;&gt;Apache를 앞단에 두고, Tomcat은 뒤에서 애플리케이션 로직을 처리하도록 구성하고 싶을 때&lt;/li&gt;
&lt;li data-end=&quot;809&quot; data-start=&quot;756&quot;&gt;둘 간의 트래픽(요청/응답)을 AJP 프로토콜로 주고받도록 해 주는 &lt;b&gt;연결 모듈&lt;/b&gt;입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1744680000076&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd /poa/data
wget https://downloads.apache.org/tomcat/tomcat-connectors/jk/tomcat-connectors-1.2.50-src.tar.gz
tar -xvzf tomcat-connectors-1.2.50-src.tar.gz
cd tomcat-connectors-1.2.50-src/native
./buildconf.sh
./configure --with-apxs=/poa/server/web/bin/apxs
make
sudo make install

sudo nano /poa/server/web/conf/httpd.conf

LoadModule jk_module modules/mod_jk.so
JkWorkersFile /poa/server/web/conf/workers.properties
JkLogFile /poa/server/web/logs/mod_jk.log
JkLogLevel info
JkMount /tomcat/* ajp13_worker

sudo nano /poa/server/web/conf/workers.properties

worker.list=ajp13_worker
worker.ajp13_worker.type=ajp13
worker.ajp13_worker.host=localhost
worker.ajp13_worker.port=8009
&quot;apachetomcatconn20241205&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;10&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자세한 설명&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;2858&quot; data-start=&quot;12&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;464&quot; data-start=&quot;12&quot;&gt;&lt;b&gt;mod_jk 소스 다운로드 및 압축 해제&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;464&quot; data-start=&quot;273&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;378&quot; data-start=&quot;273&quot;&gt;Apache Tomcat과 Apache HTTP Server를 연동하기 위해 사용되는 &lt;b&gt;mod_jk&lt;/b&gt;(AJP 커넥터)의 소스 코드(1.2.50 버전)를 다운로드하고 압축 해제합니다.&lt;/li&gt;
&lt;li data-end=&quot;464&quot; data-start=&quot;382&quot;&gt;cd tomcat-connectors-1.2.50-src/native 명령어로 native 디렉터리로 이동합니다. 여기서 빌드를 진행합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;269&quot; data-start=&quot;47&quot;&gt;&lt;b&gt;빌드 준비(buildconf.sh) 및 설정(configure)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;874&quot; data-start=&quot;602&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;640&quot; data-start=&quot;602&quot;&gt;./buildconf.sh를 통해 빌드 환경을 설정합니다.&lt;/li&gt;
&lt;li data-end=&quot;775&quot; data-start=&quot;644&quot;&gt;./configure 스크립트에서 --with-apxs 옵션을 통해, &lt;b&gt;mod_jk&lt;/b&gt;가 컴파일된 후 &lt;b&gt;apxs&lt;/b&gt;(Apache eXtension tool)를 사용하여 Apache 모듈로 설치되도록 경로를 지정합니다.&lt;/li&gt;
&lt;li data-end=&quot;874&quot; data-start=&quot;779&quot;&gt;/poa/server/web/bin/apxs는 이전에 Apache를 /poa/server/web 아래 설치했을 때 함께 생성된 apxs 바이너리 경로입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;598&quot; data-start=&quot;514&quot;&gt;&lt;b&gt;컴파일 및 설치&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1160&quot; data-start=&quot;944&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;974&quot; data-start=&quot;944&quot;&gt;make 명령어로 소스 코드를 컴파일합니다.&lt;/li&gt;
&lt;li data-end=&quot;1056&quot; data-start=&quot;978&quot;&gt;sudo make install을 통해 mod_jk.so 모듈이 Apache 모듈 디렉터리(modules/)로 복사됩니다.&lt;/li&gt;
&lt;li data-end=&quot;1160&quot; data-start=&quot;1060&quot;&gt;설치가 성공적으로 이루어지면 /poa/server/web/modules/mod_jk.so 등의 경로에 모듈이 위치하게 됩니다(설치 설정에 따라 디렉터리가 달라질 수 있음).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;940&quot; data-start=&quot;897&quot;&gt;&lt;b&gt;Apache 설정 파일(httpd.conf) 수정&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1961&quot; data-start=&quot;1463&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1961&quot; data-start=&quot;1463&quot;&gt;&lt;b&gt;mod_jk&lt;/b&gt; 모듈을 Apache에서 사용하기 위해 httpd.conf에 로드 설정을 추가합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1961&quot; data-start=&quot;1532&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1595&quot; data-start=&quot;1532&quot;&gt;LoadModule jk_module modules/mod_jk.so: 방금 설치한 모듈을 불러옵니다.&lt;/li&gt;
&lt;li data-end=&quot;1694&quot; data-start=&quot;1601&quot;&gt;JkWorkersFile /poa/server/web/conf/workers.properties: AJP 워커 정보를 정의할 설정 파일의 위치를 지정합니다.&lt;/li&gt;
&lt;li data-end=&quot;1787&quot; data-start=&quot;1700&quot;&gt;JkLogFile /poa/server/web/logs/mod_jk.log: &lt;b&gt;mod_jk&lt;/b&gt; 관련 로깅을 저장할 로그 파일 경로를 지정합니다.&lt;/li&gt;
&lt;li data-end=&quot;1846&quot; data-start=&quot;1793&quot;&gt;JkLogLevel info: 로그 레벨(verbosity)을 info로 설정합니다.&lt;/li&gt;
&lt;li data-end=&quot;1961&quot; data-start=&quot;1852&quot;&gt;JkMount /tomcat/* ajp13_worker: /tomcat/으로 시작되는 URL 요청을 ajp13_worker라는 이름의 워커에게(AJP 프로토콜) 넘기도록 지정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1459&quot; data-start=&quot;1202&quot;&gt;&lt;b&gt;workers.properties 파일 생성&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2544&quot; data-start=&quot;2205&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2281&quot; data-start=&quot;2205&quot;&gt;worker.list에는 사용할 워커들의 이름을 쉼표로 구분하여 나열합니다(여기서는 ajp13_worker만 하나 사용).&lt;/li&gt;
&lt;li data-end=&quot;2352&quot; data-start=&quot;2285&quot;&gt;worker.ajp13_worker.type=ajp13는 AJP 버전 1.3 프로토콜을 사용한다는 의미입니다.&lt;/li&gt;
&lt;li data-end=&quot;2448&quot; data-start=&quot;2356&quot;&gt;worker.ajp13_worker.host와 port 설정을 통해 Tomcat이 동작 중인 서버(호스트)와 AJP 포트(기본 8009)로 연결합니다.&lt;/li&gt;
&lt;li data-end=&quot;2544&quot; data-start=&quot;2452&quot;&gt;Tomcat 서버 server.xml에서 &amp;lt;Connector port=&quot;8009&quot; protocol=&quot;AJP/1.3&quot; /&amp;gt; 부분이 활성화되어 있어야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;2201&quot; data-start=&quot;2000&quot;&gt;&lt;b&gt;Apache 재시작&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2858&quot; data-start=&quot;2569&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2610&quot; data-start=&quot;2569&quot;&gt;설정 파일을 수정한 후, Apache 서버를 재시작해야 적용됩니다.&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;2858&quot; data-start=&quot;2727&quot;&gt;이제 브라우저에서 http://&amp;lt;서버IP 또는 도메인&amp;gt;/tomcat/으로 접근할 경우, Apache가 AJP를 통해 Tomcat으로 요청을 넘기고, Tomcat이 해당 응답을 다시 Apache에 전달하여 클라이언트로 전송합니다.&lt;/li&gt;
&lt;/ul&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;pre id=&quot;code_1744680077906&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE DATABASE poa_dev;

CREATE USER 'poa_dev'@'%' IDENTIFIED BY 'poa123';

GRANT ALL PRIVILEGES ON poa_dev.* TO 'poa_dev'@'%';

FLUSH PRIVILEGES;

SHOW DATABASES;

SELECT User, Host FROM mysql.user WHERE User = 'poa_dev';

SHOW GRANTS FOR 'poa_dev'@'%';&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;10&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자세한 설명&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1420&quot; data-start=&quot;12&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;115&quot; data-start=&quot;12&quot;&gt;&lt;b&gt;데이터베이스 생성&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;115&quot; data-start=&quot;79&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;115&quot; data-start=&quot;79&quot;&gt;poa_dev라는 이름의 새로운 데이터베이스를 생성합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;75&quot; data-start=&quot;34&quot;&gt;&lt;b&gt;사용자 생성&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;377&quot; data-start=&quot;206&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;258&quot; data-start=&quot;206&quot;&gt;poa_dev라는 사용자 계정을 만들고, 비밀번호를 poa123으로 설정합니다.&lt;/li&gt;
&lt;li data-end=&quot;324&quot; data-start=&quot;262&quot;&gt;'%'는 &lt;b&gt;호스트&lt;/b&gt;를 의미하며, %이면 모든 IP(어디서든)에서 접속할 수 있음을 허용합니다.&lt;/li&gt;
&lt;li data-end=&quot;377&quot; data-start=&quot;328&quot;&gt;로컬에서만 접속하도록 제한하고 싶다면 'localhost'로 지정할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;202&quot; data-start=&quot;136&quot;&gt;&lt;b&gt;권한 부여&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;631&quot; data-start=&quot;469&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;575&quot; data-start=&quot;469&quot;&gt;새로 만든 poa_dev 사용자에게 poa_dev 데이터베이스 내 &lt;b&gt;모든 테이블&lt;/b&gt;(poa_dev.*)에 대한 &lt;b&gt;모든 권한&lt;/b&gt;(ALL PRIVILEGES)을 부여합니다.&lt;/li&gt;
&lt;li data-end=&quot;631&quot; data-start=&quot;579&quot;&gt;예: SELECT, INSERT, UPDATE, DELETE, CREATE, DROP 등.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;465&quot; data-start=&quot;397&quot;&gt;&lt;b&gt;권한 적용&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;815&quot; data-start=&quot;689&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;741&quot; data-start=&quot;689&quot;&gt;MySQL/MariaDB 서버가 현재 부여된 권한 정보를 즉시 다시 로드하도록 합니다.&lt;/li&gt;
&lt;li data-end=&quot;815&quot; data-start=&quot;745&quot;&gt;일반적으로 사용자 또는 권한 관련 변경 후에는 FLUSH PRIVILEGES;를 통해 권한 캐시를 다시 로드해 줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;685&quot; data-start=&quot;651&quot;&gt;
&lt;div&gt;&lt;b&gt;데이터베이스 목록 확인&lt;/b&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;951&quot; data-start=&quot;878&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;914&quot; data-start=&quot;878&quot;&gt;현재 서버에 존재하는 모든 데이터베이스 목록을 보여줍니다.&lt;/li&gt;
&lt;li data-end=&quot;951&quot; data-start=&quot;918&quot;&gt;poa_dev가 잘 생성되었는지 확인할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;874&quot; data-start=&quot;842&quot;&gt;&lt;b&gt;사용자 정보 확인&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1163&quot; data-start=&quot;1053&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1117&quot; data-start=&quot;1053&quot;&gt;mysql.user 테이블에서 'poa_dev' 사용자에 대한 정보(사용자명, 호스트)를 조회합니다.&lt;/li&gt;
&lt;li data-end=&quot;1163&quot; data-start=&quot;1121&quot;&gt;여기서 '%'라는 호스트 값이 잘 설정되었는지를 확인할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1049&quot; data-start=&quot;975&quot;&gt;&lt;b&gt;권한 정보 확인&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1420&quot; data-start=&quot;1237&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1287&quot; data-start=&quot;1237&quot;&gt;특정 사용자('poa_dev'@'%')가 어떤 권한을 가지고 있는지 확인합니다.&lt;/li&gt;
&lt;li data-end=&quot;1420&quot; data-start=&quot;1291&quot;&gt;위에서 GRANT ALL PRIVILEGES ON poa_dev.* 명령어를 내렸으므로, 결과로 GRANT ALL PRIVILEGES ON 'poa_dev'.* TO 'poa_dev'@'%' 같은 내용을 볼 수 있습니다.&lt;/li&gt;
&lt;/ul&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;pre id=&quot;code_1744680139567&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE DATABASE poa_ops;

CREATE USER 'poa_ops'@'%' IDENTIFIED BY 'poa123';

GRANT ALL PRIVILEGES ON poa_ops.* TO 'poa_ops'@'%';

FLUSH PRIVILEGES;

SHOW DATABASES;

SELECT User, Host FROM mysql.user WHERE User = 'poa_ops';

SHOW GRANTS FOR 'poa_ops'@'%';&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;10&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자세한 설명&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1261&quot; data-start=&quot;12&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;115&quot; data-start=&quot;12&quot;&gt;&lt;b&gt;데이터베이스 생성&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;115&quot; data-start=&quot;79&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;115&quot; data-start=&quot;79&quot;&gt;poa_ops라는 이름의 새로운 데이터베이스를 생성합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;75&quot; data-start=&quot;34&quot;&gt;&lt;b&gt;사용자 생성&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;319&quot; data-start=&quot;206&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;256&quot; data-start=&quot;206&quot;&gt;poa_ops 사용자 계정을 만들고, 비밀번호를 poa123으로 설정합니다.&lt;/li&gt;
&lt;li data-end=&quot;319&quot; data-start=&quot;260&quot;&gt;'%'는 호스트를 의미하며, 어느 IP(어디에서나)에서든 이 사용자로 접속을 허용하도록 설정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;202&quot; data-start=&quot;136&quot;&gt;&lt;b&gt;권한 부여&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;577&quot; data-start=&quot;411&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;507&quot; data-start=&quot;411&quot;&gt;poa_ops 사용자가 poa_ops 데이터베이스 내의 모든 테이블(poa_ops.*)에 대해 모든 권한(ALL PRIVILEGES)을 갖도록 설정합니다.&lt;/li&gt;
&lt;li data-end=&quot;577&quot; data-start=&quot;511&quot;&gt;예를 들어 INSERT, SELECT, UPDATE, DELETE, CREATE, DROP 등의 권한이 포함됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;407&quot; data-start=&quot;339&quot;&gt;&lt;b&gt;권한 적용&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;693&quot; data-start=&quot;635&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;693&quot; data-start=&quot;635&quot;&gt;MySQL/MariaDB 서버가 현재 부여된 권한을 즉시 반영할 수 있도록 권한 캐시를 재로드합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;631&quot; data-start=&quot;597&quot;&gt;&lt;b&gt;데이터베이스 목록 확인&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;839&quot; data-start=&quot;756&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;791&quot; data-start=&quot;756&quot;&gt;현재 서버에 생성된 모든 데이터베이스 목록을 표시합니다.&lt;/li&gt;
&lt;li data-end=&quot;839&quot; data-start=&quot;795&quot;&gt;poa_ops 데이터베이스가 정상적으로 생성되었는지 확인할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;752&quot; data-start=&quot;720&quot;&gt;&lt;b&gt;사용자 정보 확인&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1038&quot; data-start=&quot;941&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1005&quot; data-start=&quot;941&quot;&gt;mysql.user 시스템 테이블에서 'poa_ops' 사용자 정보(사용자명, 호스트)를 조회합니다.&lt;/li&gt;
&lt;li data-end=&quot;1038&quot; data-start=&quot;1009&quot;&gt;호스트가 '%'로 설정되어 있음이 확인됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;937&quot; data-start=&quot;863&quot;&gt;&lt;b&gt;권한 정보 확인&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1261&quot; data-start=&quot;1112&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1158&quot; data-start=&quot;1112&quot;&gt;'poa_ops'@'%' 사용자가 어떤 권한을 가지고 있는지 확인합니다.&lt;/li&gt;
&lt;li data-end=&quot;1261&quot; data-start=&quot;1162&quot;&gt;위에서 부여한 대로 GRANT ALL PRIVILEGES ON poa_ops.* TO 'poa_ops'@'%'와 같은 문구가 표시되어야 정상적으로 권한이 부여된 것입니다.&lt;/li&gt;
&lt;/ul&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>etc 이슈</category>
      <author>Unlimited00</author>
      <guid isPermaLink="true">https://bbbb7788.tistory.com/611</guid>
      <comments>https://bbbb7788.tistory.com/611#entry611comment</comments>
      <pubDate>Tue, 15 Apr 2025 09:56:54 +0900</pubDate>
    </item>
    <item>
      <title>MySQL 사용자 정의 함수 &amp;gt; DB 암복호화</title>
      <link>https://bbbb7788.tistory.com/610</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1. 암호화&lt;/p&gt;
&lt;pre id=&quot;code_1744678108605&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE DEFINER=`poa_dev`@`%` FUNCTION `poa_dev`.`ENC`(input TEXT, key_str TEXT) RETURNS text CHARSET latin1 COLLATE latin1_swedish_ci
    DETERMINISTIC
BEGIN
    DECLARE encrypted_data BLOB;
    
    -- 입력 데이터의 문자셋을 UTF-8로 설정
    SET input = CONVERT(input USING utf8);

    -- AES_ENCRYPT로 암호화 (BLOB 타입으로 암호화)
    SET encrypted_data = AES_ENCRYPT(input, key_str);

    -- 암호화된 데이터를 Base64로 인코딩하여 반환
    RETURN TO_BASE64(encrypted_data);
END&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;12&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자세한 설명&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1432&quot; data-start=&quot;14&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;443&quot; data-start=&quot;14&quot;&gt;&lt;b&gt;함수 정의 구문&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;443&quot; data-start=&quot;210&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;230&quot; data-start=&quot;210&quot;&gt;&lt;b&gt;함수 이름&lt;/b&gt;: ENC&lt;/li&gt;
&lt;li data-end=&quot;276&quot; data-start=&quot;234&quot;&gt;&lt;b&gt;인자&lt;/b&gt;: input(TEXT), key_str(TEXT)&lt;/li&gt;
&lt;li data-end=&quot;342&quot; data-start=&quot;280&quot;&gt;&lt;b&gt;리턴 타입&lt;/b&gt;: TEXT (문자셋은 latin1, 정렬은 latin1_swedish_ci)&lt;/li&gt;
&lt;li data-end=&quot;443&quot; data-start=&quot;346&quot;&gt;&lt;b&gt;DETERMINISTIC&lt;/b&gt;: 같은 입력에 대해서 항상 같은 결과를 반환하는 함수임을 의미합니다. (즉, 외부 상태나 시간 등에 따라 결과가 바뀌지 않는 함수로 선언)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;206&quot; data-start=&quot;35&quot;&gt;&lt;b&gt;함수 내용&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1273&quot; data-start=&quot;801&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;882&quot; data-start=&quot;801&quot;&gt;&lt;b&gt;DECLARE encrypted_data BLOB;&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;882&quot; data-start=&quot;843&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;882&quot; data-start=&quot;843&quot;&gt;암호화 수행 후 결과를 임시로 저장할 변수를 선언(BLOB 타입).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1053&quot; data-start=&quot;886&quot;&gt;&lt;b&gt;SET input = CONVERT(input USING utf8);&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1053&quot; data-start=&quot;938&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;974&quot; data-start=&quot;938&quot;&gt;들어온 input 텍스트를 UTF-8 문자셋으로 변환.&lt;/li&gt;
&lt;li data-end=&quot;1053&quot; data-start=&quot;980&quot;&gt;MySQL에서 AES_ENCRYPT를 사용할 때, 입력 데이터를 올바른 인코딩(예: UTF-8)으로 맞춰 주는 것이 중요합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1166&quot; data-start=&quot;1057&quot;&gt;&lt;b&gt;AES_ENCRYPT(input, key_str);&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1166&quot; data-start=&quot;1099&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1166&quot; data-start=&quot;1099&quot;&gt;input(평문)을 key_str(암호화 키)로 &lt;b&gt;AES&lt;/b&gt; 알고리즘을 이용하여 암호화(결과값은 BLOB).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1273&quot; data-start=&quot;1170&quot;&gt;&lt;b&gt;RETURN TO_BASE64(encrypted_data);&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1273&quot; data-start=&quot;1217&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1273&quot; data-start=&quot;1217&quot;&gt;AES_ENCRYPT 결과(이진 데이터)를 &lt;b&gt;Base64&lt;/b&gt;로 인코딩하여 TEXT 형태로 반환.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;797&quot; data-start=&quot;463&quot;&gt;&lt;b&gt;결과적으로&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1432&quot; data-start=&quot;1293&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1380&quot; data-start=&quot;1293&quot;&gt;이 함수는 &lt;b&gt;문자열과 키&lt;/b&gt;를 입력으로 받아, input을 AES 알고리즘으로 암호화한 뒤, 그 암호화 결과를 Base64 문자열로 돌려줍니다.&lt;/li&gt;
&lt;li data-end=&quot;1432&quot; data-start=&quot;1384&quot;&gt;즉, 암호화 + 인코딩 과정을 하나의 함수로 손쉽게 호출할 수 있도록 한 것입니다.&lt;/li&gt;
&lt;/ul&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 data-ke-size=&quot;size16&quot;&gt;2. 복호화&lt;/p&gt;
&lt;pre id=&quot;code_1744678119989&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE DEFINER=`poa_dev`@`%` FUNCTION `poa_dev`.`DECRYPT`(input TEXT, key_str TEXT) RETURNS text CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci
    DETERMINISTIC
BEGIN
    DECLARE decrypted_data BLOB;

    -- AES_DECRYPT 함수로 복호화된 데이터를 BLOB 형식으로 얻기
    SET decrypted_data = AES_DECRYPT(FROM_BASE64(input), key_str);

    -- BLOB 데이터를 UTF-8로 변환하여 반환 (UTF-8로 변환하여 한글 등 멀티바이트 처리)
    RETURN CONVERT(decrypted_data USING utf8mb4);
END;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;10&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자세한 설명&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1203&quot; data-start=&quot;12&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;417&quot; data-start=&quot;12&quot;&gt;&lt;b&gt;함수 정의 구문&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;417&quot; data-start=&quot;214&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;238&quot; data-start=&quot;214&quot;&gt;&lt;b&gt;함수 이름&lt;/b&gt;: DECRYPT&lt;/li&gt;
&lt;li data-end=&quot;284&quot; data-start=&quot;242&quot;&gt;&lt;b&gt;인자&lt;/b&gt;: input(TEXT), key_str(TEXT)&lt;/li&gt;
&lt;li data-end=&quot;352&quot; data-start=&quot;288&quot;&gt;&lt;b&gt;리턴 타입&lt;/b&gt;: TEXT (문자셋은 utf8mb4, 정렬은 utf8mb4_unicode_ci)&lt;/li&gt;
&lt;li data-end=&quot;417&quot; data-start=&quot;356&quot;&gt;&lt;b&gt;DETERMINISTIC&lt;/b&gt;: 동일한 입력에 대해 언제나 동일 결과가 반환되는 함수임을 명시합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;210&quot; data-start=&quot;33&quot;&gt;&lt;b&gt;함수 본문&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1048&quot; data-start=&quot;744&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;898&quot; data-start=&quot;744&quot;&gt;&lt;b&gt;AES_DECRYPT&lt;/b&gt; 함수에, Base64로 인코딩된 암호문(input)을 &lt;b&gt;FROM_BASE64&lt;/b&gt; 함수로 디코딩한 결과와 &lt;b&gt;암호화 키&lt;/b&gt;(key_str)를 인자로 넘겨, 복호화 결과를 decrypted_data라는 &lt;b&gt;BLOB&lt;/b&gt; 변수에 담습니다.&lt;/li&gt;
&lt;li data-end=&quot;987&quot; data-start=&quot;902&quot;&gt;복호화된 이진 데이터를 utf8mb4 문자셋으로 변환( CONVERT(decrypted_data USING utf8mb4) )하여 반환합니다.&lt;/li&gt;
&lt;li data-end=&quot;1048&quot; data-start=&quot;991&quot;&gt;이렇게 하면 한글, 이모지 등 멀티바이트 문자를 비롯한 다양한 문자셋을 제대로 처리할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;740&quot; data-start=&quot;437&quot;&gt;&lt;b&gt;종합&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1203&quot; data-start=&quot;1065&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1203&quot; data-start=&quot;1065&quot;&gt;이 함수 DECRYPT는 Base64로 인코딩된 AES 암호문을 넘겨받아, 이를 디코딩( FROM_BASE64 )하고 &lt;b&gt;AES_DECRYPT&lt;/b&gt;를 통해 평문을 추출한 뒤, 최종적으로 utf8mb4로 인코딩된 텍스트로 반환해 줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>etc 이슈</category>
      <author>Unlimited00</author>
      <guid isPermaLink="true">https://bbbb7788.tistory.com/610</guid>
      <comments>https://bbbb7788.tistory.com/610#entry610comment</comments>
      <pubDate>Tue, 15 Apr 2025 09:48:44 +0900</pubDate>
    </item>
    <item>
      <title>리눅스 &amp;gt; DB 암호화</title>
      <link>https://bbbb7788.tistory.com/609</link>
      <description>&lt;pre id=&quot;code_1744677860152&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input=&quot;jdbc:mariadb://10.100.100.138:9881/poa_dev?characterEncoding=UTF8&amp;amp;autoReconnect=true&amp;amp;useSSL=false&amp;amp;autocommit=false&quot; password=&quot;dev1&quot; algorithm=&quot;PBEWithMD5AndDES&quot;
java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input=&quot;poa_dev&quot; password=&quot;dev1&quot; algorithm=&quot;PBEWithMD5AndDES&quot;
java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input=&quot;poa123&quot; password=&quot;dev1&quot; algorithm=&quot;PBEWithMD5AndDES&quot;



java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input=&quot;jdbc:mariadb://10.100.100.138:9881/poa_ops?characterEncoding=UTF8&amp;amp;autoReconnect=true&amp;amp;useSSL=false&amp;amp;autocommit=false&quot; password=&quot;dev1&quot; algorithm=&quot;PBEWithMD5AndDES&quot;
java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input=&quot;poa_ops&quot; password=&quot;ops1&quot; algorithm=&quot;PBEWithMD5AndDES&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1744677957835&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;위 내용은 Jasypt 라이브러리의 **CLI(Command Line Interface)**를 이용해 문자열을 암호화하는 명령어 예시입니다.
Jasypt(자이십트)는 Spring Boot나 Java 애플리케이션에서 암호를 쉽게 다룰 수 있도록 도와주는 라이브러리입니다.

주의

예시 명령어에서는 password=&quot;&quot; 부분이 암호화를 위한 &amp;ldquo;마스터 패스워드&amp;rdquo; 역할을 합니다.

실제 운영 환경에서는 이 값을 안전한 방식으로 관리(환경변수, 별도 보안 시스템)해야 합니다.

PBEWithMD5AndDES 알고리즘은 비교적 구식(약한) 알고리즘으로 간주됩니다. 더 안전한 알고리즘(PBEWithHmacSHA512AndAES_256 등)을 사용하는 것이 권장됩니다.

아래 명령어는 각각 **입력 문자열(input)**을 Jasypt가 암호화하여 콘솔 출력해줍니다.
출력 결과는 예) ENC(~~...) 형태가 되며, 이를 Spring Boot 설정(application.yml 등)에 넣으면 됩니다.&lt;/code&gt;&lt;/pre&gt;</description>
      <category>etc 이슈</category>
      <author>Unlimited00</author>
      <guid isPermaLink="true">https://bbbb7788.tistory.com/609</guid>
      <comments>https://bbbb7788.tistory.com/609#entry609comment</comments>
      <pubDate>Tue, 15 Apr 2025 09:46:50 +0900</pubDate>
    </item>
    <item>
      <title>리눅스 명령어</title>
      <link>https://bbbb7788.tistory.com/608</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1. 기본&lt;/p&gt;
&lt;pre id=&quot;code_1744677590107&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;- mkdir : 디렉토리 생성
- ls : 목록 확인 (옵션 : -al)
- mv : 파일 잘라서 붙여넣기
- cp : 파일 복사 붙여넣기
- cd : 이동
- vi : 편집 또는 보기 (파일만가능)&lt;/code&gt;&lt;/pre&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;2. 권한 관련&lt;/p&gt;
&lt;pre id=&quot;code_1744677604500&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;- chmod : 파일 또는 디렉터리에 대한 읽기, 쓰기 등 권한 변경
- chown : 파일 또는 디렉터리에 대한 사용자 권한 변경&lt;/code&gt;&lt;/pre&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;3. 로그 등 확인 용도(파일)&lt;/p&gt;
&lt;pre id=&quot;code_1744677624885&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;- cat : 파일 안열고 보기
- tail : 로그 보기 (-f) 옵션시 실시간 확인&lt;/code&gt;&lt;/pre&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;4. 프로세스 확인&lt;/p&gt;
&lt;pre id=&quot;code_1744677637995&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;- ps -ef | grep tomcat&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1744677673605&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt; vi 편집기에서 알고있어야할 딱 기본 명령어
 - a (아무것도 동작안하고 기본 ui에서 클릭시) 현재 커서의 뒤에부터 insert를 할 수 있도록 지원

 &amp;gt; 저장 및 나가기를 할때는 esc를 누른후 : 를 입력 (shift + ;) 명령어 입력
 - wq! (강제저장)
 - q! (강제 나가기)&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1744677684651&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt; 서버 용량 확인
 - df -h&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1744677694095&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; &amp;gt; 재기동 순서
   - 시작
     &amp;gt; db &amp;gt; was &amp;gt; web
   - 종료
     &amp;gt; web &amp;gt; was &amp;gt; db&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1757476653101&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;- 안쓰는 도커 이미지 확인
docker images -f &quot;dangling=true&quot;

- 특정 id 이미지 삭제
docker rmi 1a91df371477

- 빌드 캐시 정리
docker builder prune -af

- 용량 확인
df -h

- 프로세스 모니터링
top -d 1    # 1초 단위로 새로고침
M : 메모리 사용량 순 정렬
h : 도움말
q : 종료

- 메모리 확인
cat /proc/meminfo

- cpu 확인
cat /proc/cpuinfo 

- 기존에 사용한 명령어 보기
history

- 종료된 컨테이너까지 확인
docker ps -a&lt;/code&gt;&lt;/pre&gt;</description>
      <category>etc 이슈</category>
      <author>Unlimited00</author>
      <guid isPermaLink="true">https://bbbb7788.tistory.com/608</guid>
      <comments>https://bbbb7788.tistory.com/608#entry608comment</comments>
      <pubDate>Tue, 15 Apr 2025 09:41:38 +0900</pubDate>
    </item>
    <item>
      <title>톰캣 서버 잡기</title>
      <link>https://bbbb7788.tistory.com/607</link>
      <description>&lt;pre id=&quot;code_1734651482450&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;C:\Windows\System32

netstat /?

netstat -anop -tcp

TASKKILL /?

TASKKILL /F /PID ?????&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;10&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자세한 설명&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1441&quot; data-start=&quot;12&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;213&quot; data-start=&quot;12&quot;&gt;&lt;b&gt;C:\Windows\System32&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;213&quot; data-start=&quot;46&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;121&quot; data-start=&quot;46&quot;&gt;Windows 운영체제에서 시스템 명령어(예: netstat, taskkill, ipconfig 등)가 위치한 기본 디렉터리입니다.&lt;/li&gt;
&lt;li data-end=&quot;213&quot; data-start=&quot;125&quot;&gt;보통 cmd 창(명령 프롬프트)이나 PowerShell에서 이러한 명령어를 실행할 때 자동으로 이 디렉터리를 탐색하므로, 직접 이동할 필요는 없습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;379&quot; data-start=&quot;215&quot;&gt;&lt;b&gt;netstat /?&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;379&quot; data-start=&quot;240&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;289&quot; data-start=&quot;240&quot;&gt;netstat 명령어의 사용법과 옵션들을 확인하는 도움말(Help)을 표시합니다.&lt;/li&gt;
&lt;li data-end=&quot;379&quot; data-start=&quot;293&quot;&gt;예:화면에 netstat 명령의 가능한 스위치나 설명이 나타납니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;903&quot; data-start=&quot;381&quot;&gt;&lt;b&gt;netstat -anop -tcp&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;903&quot; data-start=&quot;414&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;494&quot; data-start=&quot;414&quot;&gt;일반적으로 netstat는 &lt;b&gt;네트워크 연결 상태&lt;/b&gt;, &lt;b&gt;포트&lt;/b&gt;, &lt;b&gt;프로토콜&lt;/b&gt;, &lt;b&gt;프로세스 정보&lt;/b&gt; 등을 보여주는 명령어입니다.&lt;/li&gt;
&lt;li data-end=&quot;554&quot; data-start=&quot;498&quot;&gt;Windows에서는 옵션을 약간 다르게 써야 할 수도 있습니다(예: netstat -ano).&lt;/li&gt;
&lt;li data-end=&quot;741&quot; data-start=&quot;558&quot;&gt;-anop -tcp 같은 옵션을 쓰면, 활성화된 TCP 연결의:
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;741&quot; data-start=&quot;603&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;637&quot; data-start=&quot;603&quot;&gt;-a: 모든 연결 및 포트(리스닝 상태 포함) 표시&lt;/li&gt;
&lt;li data-end=&quot;676&quot; data-start=&quot;643&quot;&gt;-n: 숫자 형식(IP 주소, 포트 번호)로 표시&lt;/li&gt;
&lt;li data-end=&quot;707&quot; data-start=&quot;682&quot;&gt;-o: 프로세스 ID(PID) 표시&lt;/li&gt;
&lt;li data-end=&quot;741&quot; data-start=&quot;713&quot;&gt;-p: 특정 프로토콜 필터(예: TCP)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;799&quot; data-start=&quot;745&quot;&gt;결과적으로, 어떤 프로세스가 어떤 포트를 열어두고 있는지를 PID 단위로 확인할 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;903&quot; data-start=&quot;804&quot;&gt;예:
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;903&quot; data-start=&quot;864&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;903&quot; data-start=&quot;864&quot;&gt;TCP 연결 및 프로세스 ID(PID)를 숫자 형식으로 표시합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1106&quot; data-start=&quot;905&quot;&gt;&lt;b&gt;TASKKILL /?&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1106&quot; data-start=&quot;931&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;960&quot; data-start=&quot;931&quot;&gt;taskkill 명령어의 도움말을 표시합니다.&lt;/li&gt;
&lt;li data-end=&quot;1023&quot; data-start=&quot;964&quot;&gt;taskkill는 Windows에서 특정 PID(프로세스 ID)의 프로세스를 종료할 때 사용합니다.&lt;/li&gt;
&lt;li data-end=&quot;1106&quot; data-start=&quot;1027&quot;&gt;예:화면에 taskkill의 사용법이 표시됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1441&quot; data-start=&quot;1108&quot;&gt;&lt;b&gt;TASKKILL /F /PID ?????&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1441&quot; data-start=&quot;1145&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1190&quot; data-start=&quot;1145&quot;&gt;taskkill 명령어로 특정 프로세스를 강제 종료(/F)하는 예시입니다.&lt;/li&gt;
&lt;li data-end=&quot;1242&quot; data-start=&quot;1194&quot;&gt;????? 자리에 종료할 프로세스의 &lt;b&gt;PID&lt;/b&gt;(프로세스 ID)를 입력합니다.&lt;/li&gt;
&lt;li data-end=&quot;1336&quot; data-start=&quot;1246&quot;&gt;예:
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1336&quot; data-start=&quot;1308&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1336&quot; data-start=&quot;1308&quot;&gt;PID가 1234인 프로세스를 강제 종료합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1380&quot; data-start=&quot;1340&quot;&gt;/F 옵션이 없으면 일반 종료(프로세스가 종료 요청을 받음).&lt;/li&gt;
&lt;li data-end=&quot;1441&quot; data-start=&quot;1384&quot;&gt;/F 옵션이 있으면 강제 종료(SOFT 요청을 거부하거나 무시하더라도 프로세스가 종료됨)입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;1454&quot; data-start=&quot;1448&quot; 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-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;1692&quot; data-start=&quot;1455&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1521&quot; data-start=&quot;1455&quot;&gt;&lt;b&gt;netstat&lt;/b&gt;: 현재 열려있는 포트, 연결 상태, 프로세스 식별자(PID) 등을 확인할 수 있는 명령어.&lt;/li&gt;
&lt;li data-end=&quot;1566&quot; data-start=&quot;1522&quot;&gt;&lt;b&gt;taskkill&lt;/b&gt;: 특정 프로세스를 종료하는 Windows 명령어.&lt;/li&gt;
&lt;li data-end=&quot;1692&quot; data-start=&quot;1567&quot;&gt;-anop -tcp(Windows에선 netstat -ano -p tcp 형태)로 TCP 연결 상태와 PID를 함께 확인한 다음, 그 PID를 taskkill /F /PID &amp;lt;PID번호&amp;gt;로 종료할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>etc 이슈</category>
      <author>Unlimited00</author>
      <guid isPermaLink="true">https://bbbb7788.tistory.com/607</guid>
      <comments>https://bbbb7788.tistory.com/607#entry607comment</comments>
      <pubDate>Fri, 20 Dec 2024 08:38:08 +0900</pubDate>
    </item>
    <item>
      <title>React &amp;gt; 유용한 커스텀 훅</title>
      <link>https://bbbb7788.tistory.com/604</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. useConsolelog&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1730946358419&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { useEffect } from 'react';

// 커스텀 훅 정의
function useConsoleLog(value) {
    useEffect(() =&amp;gt; {
        if(value) {
            console.log(`${value} : `, value);
        }
    }, [value]);
}

export default useConsoleLog;&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;b&gt;2. useCommonCodeList&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1730946484740&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { useState, useEffect } from 'react';
import { getCommonCodeListInfo, tokenGetCommonCodeListInfo } from '../api/adminApi';
import fetchData from '../utils/fetchData';
import useAxiosWithAuth from 'hooks/useAxiosWithAuth';

// 공통 코드 리스트를 불러와 라디오, 셀렉트 옵션으로 변환하는 커스텀 훅
const useCommonCodeList = (groupCode) =&amp;gt; {
    const axiosInstance = useAxiosWithAuth();
    const loginUser = '100';

    const [commonCodeListData, setCommonCodeListData] = useState([]);

    // 공통코드 리스트를 불러오는 함수
    const fetchCommonCodeList = async () =&amp;gt; {
        const postData = { searchComGroupCd: groupCode };
        //await fetchData(getCommonCodeListInfo, setCommonCodeListData, postData);
        try {
            const data = await tokenGetCommonCodeListInfo(axiosInstance, postData);
            setCommonCodeListData(data);
        } catch (error) {
            console.error('Error fetching data: ', error);
        }
    };

    useEffect(() =&amp;gt; {
        fetchCommonCodeList();
    }, []);

    // 공통 코드 리스트 데이터
    const commonCodeResultData = commonCodeListData?.resultData?.cmmnCdList;

    ////////////////////////////////////////

    // 라디오 옵션 변환
    const commonCodeRadioOptionFn = () =&amp;gt; {
        const options = commonCodeResultData?.map(code =&amp;gt; ({
            value: code.comCd,
            title: code.cdNm
        }));
        let commonCodeRadioOption = options;
        return commonCodeRadioOption;
    };

    ////////////////////////////////////////

    // 셀렉트 옵션 변환
    const commonCodeSelectOptionFn = () =&amp;gt; {
        const options = commonCodeResultData?.map(code =&amp;gt; ({
            id: code.comCd,
            name: code.cdNm
        }));
        let commonCodeSelectOption = options;
        return commonCodeSelectOption;
    };

    return {
        commonCodeResultData,
        commonCodeRadioOptionFn,
        commonCodeSelectOptionFn
    };
};

export default useCommonCodeList;&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;b&gt;3. useNavigateWithQuery&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1730946599939&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { useMemo } from 'react';

const useNavigateWithQuery = (path, queryParams) =&amp;gt; {
    // useMemo를 사용하여 쿼리 스트링이 변경될 때만 새로운 URL을 계산합니다.
    const finalUrl = useMemo(() =&amp;gt; {
        const newQueryString = Object.entries(queryParams)
            .map(([key, value]) =&amp;gt; `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
            .join('&amp;amp;');

        return `${path}?${newQueryString}`;
    }, [path, queryParams]);

    return finalUrl;
};

export default useNavigateWithQuery;&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;b&gt;4. JsonDataShowTemp&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1730947713228&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from 'react';

const JsonDataShowTemp = ({ data }) =&amp;gt; {
    return (
        &amp;lt;pre&amp;gt;{JSON.stringify(data, null, 2)}&amp;lt;/pre&amp;gt;
    );
};

export default JsonDataShowTemp;&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;b&gt;5. stringifyJSON&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1732059512475&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 응답 확인용 메서드
export const stringifyJSON = (obj, indent = 2) =&amp;gt; {
    return JSON.stringify(obj, null, indent);
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>etc 이슈</category>
      <author>Unlimited00</author>
      <guid isPermaLink="true">https://bbbb7788.tistory.com/604</guid>
      <comments>https://bbbb7788.tistory.com/604#entry604comment</comments>
      <pubDate>Thu, 7 Nov 2024 11:26:06 +0900</pubDate>
    </item>
    <item>
      <title>CSS 스크롤바 숨기기</title>
      <link>https://bbbb7788.tistory.com/597</link>
      <description>&lt;pre id=&quot;code_1710988081842&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.scrollCover {
    height: 500px;
    overflow-x: hidden;
    overflow-y: auto;
    scrollbar-width: none;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>etc 이슈</category>
      <author>Unlimited00</author>
      <guid isPermaLink="true">https://bbbb7788.tistory.com/597</guid>
      <comments>https://bbbb7788.tistory.com/597#entry597comment</comments>
      <pubDate>Thu, 21 Mar 2024 11:28:08 +0900</pubDate>
    </item>
    <item>
      <title>CSS Flex 속성</title>
      <link>https://bbbb7788.tistory.com/596</link>
      <description>&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&lt;a href=&quot;https://studiomeal.com/archives/197&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;https://studiomeal.com/archives/197&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;이번에야말로 CSS Flex를 익혀보자&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot; &quot; data-og-host=&quot;studiomeal.com&quot; data-og-source-url=&quot;https://studiomeal.com/archives/197&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/YHn5d/hyVADanqjQ/YkoGqR5EH6iFfxKpDUGtrK/img.jpg?width=600&amp;amp;height=315&amp;amp;face=0_0_600_315&quot; data-og-url=&quot;https://studiomeal.com/archives/197&quot;&gt;&lt;a href=&quot;https://studiomeal.com/archives/197&quot; target=&quot;_blank&quot; data-source-url=&quot;https://studiomeal.com/archives/197&quot;&gt;&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/YHn5d/hyVADanqjQ/YkoGqR5EH6iFfxKpDUGtrK/img.jpg?width=600&amp;amp;height=315&amp;amp;face=0_0_600_315')&quot;&gt; &lt;/div&gt;&lt;div class=&quot;og-text&quot;&gt;&lt;p class=&quot;og-title&quot;&gt;이번에야말로 CSS Flex를 익혀보자&lt;/p&gt;&lt;p class=&quot;og-desc&quot;&gt; &lt;/p&gt;&lt;p class=&quot;og-host&quot;&gt;studiomeal.com&lt;/p&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;justify-content: flex-end;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1885&quot; data-origin-height=&quot;678&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/M2AYZ/btsFRtO0o4Z/dS2X9nhx3H1pKelaMg1Z70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/M2AYZ/btsFRtO0o4Z/dS2X9nhx3H1pKelaMg1Z70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/M2AYZ/btsFRtO0o4Z/dS2X9nhx3H1pKelaMg1Z70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FM2AYZ%2FbtsFRtO0o4Z%2FdS2X9nhx3H1pKelaMg1Z70%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;1885&quot; height=&quot;678&quot; data-origin-width=&quot;1885&quot; data-origin-height=&quot;678&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;justify-content: center;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1879&quot; data-origin-height=&quot;662&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d8ZaPY/btsFU9azDa4/9mP9KhYiVyK6VurAk0L2I1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d8ZaPY/btsFU9azDa4/9mP9KhYiVyK6VurAk0L2I1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d8ZaPY/btsFU9azDa4/9mP9KhYiVyK6VurAk0L2I1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd8ZaPY%2FbtsFU9azDa4%2F9mP9KhYiVyK6VurAk0L2I1%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;1879&quot; height=&quot;662&quot; data-origin-width=&quot;1879&quot; data-origin-height=&quot;662&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;justify-content: space-around;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1888&quot; data-origin-height=&quot;566&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTVd9c/btsFT1qQ1qK/MqhRFkDNhmkj4sVqsKIdD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTVd9c/btsFT1qQ1qK/MqhRFkDNhmkj4sVqsKIdD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTVd9c/btsFT1qQ1qK/MqhRFkDNhmkj4sVqsKIdD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTVd9c%2FbtsFT1qQ1qK%2FMqhRFkDNhmkj4sVqsKIdD0%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;1888&quot; height=&quot;566&quot; data-origin-width=&quot;1888&quot; data-origin-height=&quot;566&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;justify-content: space-between;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1895&quot; data-origin-height=&quot;522&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bC0qpN/btsFUDiHPN3/DrVXViA4TVgW7rnhongWVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bC0qpN/btsFUDiHPN3/DrVXViA4TVgW7rnhongWVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bC0qpN/btsFUDiHPN3/DrVXViA4TVgW7rnhongWVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbC0qpN%2FbtsFUDiHPN3%2FDrVXViA4TVgW7rnhongWVk%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;1895&quot; height=&quot;522&quot; data-origin-width=&quot;1895&quot; data-origin-height=&quot;522&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;align-items: flex-end;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1887&quot; data-origin-height=&quot;914&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buIRU3/btsFU6yaeV4/XAkU0jFzV9Zqg8kmu6z4Kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buIRU3/btsFU6yaeV4/XAkU0jFzV9Zqg8kmu6z4Kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buIRU3/btsFU6yaeV4/XAkU0jFzV9Zqg8kmu6z4Kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuIRU3%2FbtsFU6yaeV4%2FXAkU0jFzV9Zqg8kmu6z4Kk%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;1887&quot; height=&quot;914&quot; data-origin-width=&quot;1887&quot; data-origin-height=&quot;914&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;justify-content: center;
&amp;nbsp;&amp;nbsp;align-items: center;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1903&quot; data-origin-height=&quot;913&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRtEyS/btsFQWxvXiO/TATq0TcAWQ3Tx5GLBURWy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRtEyS/btsFQWxvXiO/TATq0TcAWQ3Tx5GLBURWy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRtEyS/btsFQWxvXiO/TATq0TcAWQ3Tx5GLBURWy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRtEyS%2FbtsFQWxvXiO%2FTATq0TcAWQ3Tx5GLBURWy1%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;1903&quot; height=&quot;913&quot; data-origin-width=&quot;1903&quot; data-origin-height=&quot;913&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;justify-content: space-around;
&amp;nbsp;&amp;nbsp;align-items: flex-end;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1901&quot; data-origin-height=&quot;913&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAo3Wc/btsFRiAjZOr/A8ae32VR5hWyghlww9gBd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAo3Wc/btsFRiAjZOr/A8ae32VR5hWyghlww9gBd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAo3Wc/btsFRiAjZOr/A8ae32VR5hWyghlww9gBd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAo3Wc%2FbtsFRiAjZOr%2FA8ae32VR5hWyghlww9gBd1%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;913&quot; data-origin-width=&quot;1901&quot; data-origin-height=&quot;913&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;flex-direction: row-reverse;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1911&quot; data-origin-height=&quot;618&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAxSj8/btsFUlo5zri/nWfvxuzSCqbDoksFdP2io0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAxSj8/btsFUlo5zri/nWfvxuzSCqbDoksFdP2io0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAxSj8/btsFUlo5zri/nWfvxuzSCqbDoksFdP2io0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAxSj8%2FbtsFUlo5zri%2FnWfvxuzSCqbDoksFdP2io0%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;1911&quot; height=&quot;618&quot; data-origin-width=&quot;1911&quot; data-origin-height=&quot;618&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;flex-direction: column;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1893&quot; data-origin-height=&quot;625&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/X9BCt/btsFUCYnYzC/hjuszxViM3UFqwi3gbftwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/X9BCt/btsFUCYnYzC/hjuszxViM3UFqwi3gbftwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/X9BCt/btsFUCYnYzC/hjuszxViM3UFqwi3gbftwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FX9BCt%2FbtsFUCYnYzC%2FhjuszxViM3UFqwi3gbftwK%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;1893&quot; height=&quot;625&quot; data-origin-width=&quot;1893&quot; data-origin-height=&quot;625&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;flex-direction: row-reverse;
&amp;nbsp;&amp;nbsp;justify-content: flex-end;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1892&quot; data-origin-height=&quot;542&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLXvjH/btsFU0Y7j1z/KRA1nFrdkkAdqDXrjOuLK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLXvjH/btsFU0Y7j1z/KRA1nFrdkkAdqDXrjOuLK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLXvjH/btsFU0Y7j1z/KRA1nFrdkkAdqDXrjOuLK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLXvjH%2FbtsFU0Y7j1z%2FKRA1nFrdkkAdqDXrjOuLK1%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;1892&quot; height=&quot;542&quot; data-origin-width=&quot;1892&quot; data-origin-height=&quot;542&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;flex-direction: column;
&amp;nbsp;&amp;nbsp;justify-content: flex-end;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1897&quot; data-origin-height=&quot;909&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvdYRn/btsFUmnZGmK/PJtrE1lHUkOMdr4ByODaek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvdYRn/btsFUmnZGmK/PJtrE1lHUkOMdr4ByODaek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvdYRn/btsFUmnZGmK/PJtrE1lHUkOMdr4ByODaek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvdYRn%2FbtsFUmnZGmK%2FPJtrE1lHUkOMdr4ByODaek%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;1897&quot; height=&quot;909&quot; data-origin-width=&quot;1897&quot; data-origin-height=&quot;909&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;flex-direction: column-reverse;
&amp;nbsp;&amp;nbsp;justify-content: space-between;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1904&quot; data-origin-height=&quot;914&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGguyq/btsFTcFW8pz/iYfcu8155DQkkQXmaPbc91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGguyq/btsFTcFW8pz/iYfcu8155DQkkQXmaPbc91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGguyq/btsFTcFW8pz/iYfcu8155DQkkQXmaPbc91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGguyq%2FbtsFTcFW8pz%2FiYfcu8155DQkkQXmaPbc91%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;1904&quot; height=&quot;914&quot; data-origin-width=&quot;1904&quot; data-origin-height=&quot;914&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;flex-direction: row-reverse;
&amp;nbsp;&amp;nbsp;justify-content: center;
&amp;nbsp;&amp;nbsp;align-items: flex-end;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1895&quot; data-origin-height=&quot;921&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbexoT/btsFSZ7TdOf/KTZ0MssZRcrurYqORZIziK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbexoT/btsFSZ7TdOf/KTZ0MssZRcrurYqORZIziK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbexoT/btsFSZ7TdOf/KTZ0MssZRcrurYqORZIziK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbexoT%2FbtsFSZ7TdOf%2FKTZ0MssZRcrurYqORZIziK%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;1895&quot; height=&quot;921&quot; data-origin-width=&quot;1895&quot; data-origin-height=&quot;921&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
}

.yellow {
&amp;nbsp;&amp;nbsp;order: 1;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1537&quot; data-origin-height=&quot;556&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xzBMP/btsFUDXiFAb/12xPKxbR5s6dcAaIvtzNXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xzBMP/btsFUDXiFAb/12xPKxbR5s6dcAaIvtzNXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xzBMP/btsFUDXiFAb/12xPKxbR5s6dcAaIvtzNXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxzBMP%2FbtsFUDXiFAb%2F12xPKxbR5s6dcAaIvtzNXk%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;1537&quot; height=&quot;556&quot; data-origin-width=&quot;1537&quot; data-origin-height=&quot;556&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
}

.red {
&amp;nbsp;&amp;nbsp;order: -3;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1900&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/L4QxI/btsFUJQLCwL/IxeRFUKldwEJwwxYpVQ390/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/L4QxI/btsFUJQLCwL/IxeRFUKldwEJwwxYpVQ390/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/L4QxI/btsFUJQLCwL/IxeRFUKldwEJwwxYpVQ390/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FL4QxI%2FbtsFUJQLCwL%2FIxeRFUKldwEJwwxYpVQ390%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;1900&quot; height=&quot;512&quot; data-origin-width=&quot;1900&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;align-items: flex-start;
}

.yellow {
&amp;nbsp;&amp;nbsp;align-self: flex-end;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1894&quot; data-origin-height=&quot;901&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFazJe/btsFRrp6gHI/P8PoKzXFkjZfbYQVmEAwSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFazJe/btsFRrp6gHI/P8PoKzXFkjZfbYQVmEAwSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFazJe/btsFRrp6gHI/P8PoKzXFkjZfbYQVmEAwSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFazJe%2FbtsFRrp6gHI%2FP8PoKzXFkjZfbYQVmEAwSk%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;1894&quot; height=&quot;901&quot; data-origin-width=&quot;1894&quot; data-origin-height=&quot;901&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;align-items: flex-start;
}

.yellow {
&amp;nbsp;&amp;nbsp;order: 1;
&amp;nbsp;&amp;nbsp;align-self: flex-end;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1896&quot; data-origin-height=&quot;917&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqNc17/btsFQtIY1A1/90AHkzV3RNNcURyRfhWle1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqNc17/btsFQtIY1A1/90AHkzV3RNNcURyRfhWle1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqNc17/btsFQtIY1A1/90AHkzV3RNNcURyRfhWle1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqNc17%2FbtsFQtIY1A1%2F90AHkzV3RNNcURyRfhWle1%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;1896&quot; height=&quot;917&quot; data-origin-width=&quot;1896&quot; data-origin-height=&quot;917&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;flex-wrap: wrap;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1900&quot; data-origin-height=&quot;703&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgdPe3/btsFRkdSjmW/JXKRk6jnez9nfKRcZ7Thn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgdPe3/btsFRkdSjmW/JXKRk6jnez9nfKRcZ7Thn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgdPe3/btsFRkdSjmW/JXKRk6jnez9nfKRcZ7Thn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgdPe3%2FbtsFRkdSjmW%2FJXKRk6jnez9nfKRcZ7Thn1%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;1900&quot; height=&quot;703&quot; data-origin-width=&quot;1900&quot; data-origin-height=&quot;703&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;flex-direction: column;
&amp;nbsp;&amp;nbsp;flex-wrap: wrap;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1900&quot; data-origin-height=&quot;916&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tbXS7/btsFQWROGOI/n624oV7k6ll5sjKFfXpIdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tbXS7/btsFQWROGOI/n624oV7k6ll5sjKFfXpIdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tbXS7/btsFQWROGOI/n624oV7k6ll5sjKFfXpIdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtbXS7%2FbtsFQWROGOI%2Fn624oV7k6ll5sjKFfXpIdk%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;1900&quot; height=&quot;916&quot; data-origin-width=&quot;1900&quot; data-origin-height=&quot;916&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;flex-flow: column wrap;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1896&quot; data-origin-height=&quot;914&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Vqt07/btsFUG7yr3N/w2tw9dylJg2lcfWAeA0BHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Vqt07/btsFUG7yr3N/w2tw9dylJg2lcfWAeA0BHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Vqt07/btsFUG7yr3N/w2tw9dylJg2lcfWAeA0BHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVqt07%2FbtsFUG7yr3N%2Fw2tw9dylJg2lcfWAeA0BHk%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;1896&quot; height=&quot;914&quot; data-origin-width=&quot;1896&quot; data-origin-height=&quot;914&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;flex-wrap: wrap;
&amp;nbsp;&amp;nbsp;align-content: flex-start;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1902&quot; data-origin-height=&quot;912&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tT0E1/btsFRiUCSaR/kBE8NdETi75seVrkON5kK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tT0E1/btsFRiUCSaR/kBE8NdETi75seVrkON5kK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tT0E1/btsFRiUCSaR/kBE8NdETi75seVrkON5kK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtT0E1%2FbtsFRiUCSaR%2FkBE8NdETi75seVrkON5kK1%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;912&quot; data-origin-width=&quot;1902&quot; data-origin-height=&quot;912&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;flex-wrap: wrap;
&amp;nbsp;&amp;nbsp;align-content: flex-end;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1892&quot; data-origin-height=&quot;911&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k0un6/btsFT0Fwm78/stJ7K0azOjjLGpjG4ZoGi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k0un6/btsFT0Fwm78/stJ7K0azOjjLGpjG4ZoGi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k0un6/btsFT0Fwm78/stJ7K0azOjjLGpjG4ZoGi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk0un6%2FbtsFT0Fwm78%2FstJ7K0azOjjLGpjG4ZoGi0%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;1892&quot; height=&quot;911&quot; data-origin-width=&quot;1892&quot; data-origin-height=&quot;911&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;flex-wrap: wrap;
&amp;nbsp;&amp;nbsp;flex-direction: column-reverse;
&amp;nbsp;&amp;nbsp;align-content: center;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1896&quot; data-origin-height=&quot;900&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JwBhc/btsFUl3HRMm/E4nIJZYmviGg3ZyAKD0SHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JwBhc/btsFUl3HRMm/E4nIJZYmviGg3ZyAKD0SHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JwBhc/btsFUl3HRMm/E4nIJZYmviGg3ZyAKD0SHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJwBhc%2FbtsFUl3HRMm%2FE4nIJZYmviGg3ZyAKD0SHK%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;1896&quot; height=&quot;900&quot; data-origin-width=&quot;1896&quot; data-origin-height=&quot;900&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;flex-flow: column-reverse wrap-reverse;
&amp;nbsp;&amp;nbsp;align-content: space-between;
&amp;nbsp;&amp;nbsp;justify-content: center;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1910&quot; data-origin-height=&quot;917&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LnGMt/btsFR0FXmUF/hiGCwQuihILSV6oy35mP30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LnGMt/btsFR0FXmUF/hiGCwQuihILSV6oy35mP30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LnGMt/btsFR0FXmUF/hiGCwQuihILSV6oy35mP30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLnGMt%2FbtsFR0FXmUF%2FhiGCwQuihILSV6oy35mP30%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;1910&quot; height=&quot;917&quot; data-origin-width=&quot;1910&quot; data-origin-height=&quot;917&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;#pond {
&amp;nbsp;&amp;nbsp;display: flex;
&amp;nbsp;&amp;nbsp;flex-direction: column-reverse;
&amp;nbsp;&amp;nbsp;flex-wrap: wrap-reverse;
&amp;nbsp;&amp;nbsp;align-content: space-between;
&amp;nbsp;&amp;nbsp;justify-content: center;
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1901&quot; data-origin-height=&quot;909&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crpVZq/btsFTY8J5hs/vr8YZmDokRPUoN61zFA6b1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crpVZq/btsFTY8J5hs/vr8YZmDokRPUoN61zFA6b1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crpVZq/btsFTY8J5hs/vr8YZmDokRPUoN61zFA6b1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrpVZq%2FbtsFTY8J5hs%2Fvr8YZmDokRPUoN61zFA6b1%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;909&quot; data-origin-width=&quot;1901&quot; data-origin-height=&quot;909&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr 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;</description>
      <category>etc 이슈</category>
      <author>Unlimited00</author>
      <guid isPermaLink="true">https://bbbb7788.tistory.com/596</guid>
      <comments>https://bbbb7788.tistory.com/596#entry596comment</comments>
      <pubDate>Mon, 18 Mar 2024 20:16:14 +0900</pubDate>
    </item>
  </channel>
</rss>