pm2 는 javascript 런타임 node.js 프로세스 관리자이다.
사내 서비스 중에 pm2 가 vue 프로젝트를 실행시키고, nginx 가 reverse proxy 역할만 수행하는 서비스가 있다.
node 앱은 백엔드 서비스만 의미하는 줄 알았는데, FE에서도 쓰이는 용어인지 궁금했다.

결론부터 이야기 하면 vue 로 구현된 서비스도 node 앱이 될 수  있다.

즉, node.js 환경에서 실행되는 서비스이면 node 애플리케이션이다.

라이브러리, 프레임워크와 상관이 없는 것이다.

 

node 앱의 의미에 대해서 알아보자.

 

node 앱이란?

node.js 로 실행되는 프로그램

  • node.js: 브라우저 밖에서 javascript를 실행할 수 있게 만든 런타임 환경. 원래 javascript는 브라우저에서만 동작했지만, node.js는 서버나 터미날에서 js를 동작할 수 있게 한다.
  • node app.js 를 하게 되면, app.js 의 javascript 코드가 node.js 위에서 실행된다.

pm2 실행환경으로 본 정체

pm2 자체가 node.js 에서 실행되는 프로그램, 즉 node 앱.
pm2는 여러 node 앱을 관리하는 node 앱
그렇기 때문에 시스템 내에 node.js 가 반드시 설치되어 있어야 한다.

[시스템] → [Node.js 런타임] → [PM2 CLI 스크립트] → [PM2 Daemon] → [Node.js 앱]

pm2 실행 시 내부 동작 구조

  1. pm2 start app.js 명렁어 실행
  2. 운영체제(OS) 는 $PATH 안에 있는 pm2 실행 파일을 찾음
# pm2 실행 파일 내부
#!/usr/bin/env node
require('../lib/ProcessContainerFork.js');

이 파일은 node.js 로 만든 스크립트
#!/usr/bin/env node : node로 실행하라
즉 pm2는 node.js 인터프리터로 실행

  1. node.js 런타임이 pm2 스크립트 해석 -> pm2 내부에서 "app.js를 백그라운드로 실행"하라는 명령을 daemon에 전달
  2. node.js 는 새로운 node.js 프로세스를 fork(자식 프로세스 실행) 하여 아래와 같이 node.js 런타임 실행
node /path/to/app.js

실제 프로세스 구조 확인

pm2 start app.js
ps -ef | grep node
ubuntu   1234  1  0  pm2: God Daemon (/usr/lib/node_modules/pm2/lib/Daemon.js)
ubuntu   1250 1234 0  node /home/user/app.js

PID 1234 : pm2 daemon으로 실행 -> node로 실행 됨
PID 1250 -> pm2 가 fork한 실제 node 앱 -> node로 실행 됨
즉, node.js 가 pm2 자신과 app.js를 모두 구동

요약 구조

┌──────────────────────────────────────────┐
│              Node.js 런타임              │
│  ┌────────────────────────────────────┐  │
│  │            PM2 CLI                │  │
│  │  (node로 실행됨)                  │  │
│  └──────────────┬────────────────────┘  │
│                 │ IPC 통신 (Unix Socket)│
│  ┌──────────────▼────────────────────┐  │
│  │         PM2 Daemon(Node 앱)       │  │
│  ├──────────────┬────────────────────┤  │
│  │              │ fork()              │
│  └──────────────▼────────────────────┘  │
│          Node 앱들 (app.js 등)         │
└──────────────────────────────────────────┘

Node.js 런타임이 PM2를 실행
PM2가 다시 Node.js를 이용해 앱들을 실행

정리

| 항목                | 내용                                          |
| ----------------- | ------------------------------------------- |
| **PM2 실행 기반**     | Node.js 런타임 위에서 동작                          |
| **Node.js 제공 방식** | 시스템에 설치된 Node.js 실행 파일(`/usr/bin/node`)을 이용 |
| **실행 명령 구조**      | `#!/usr/bin/env node` 로 Node 런타임을 호출        |
| **결과**            | Node.js → PM2 → (다른 Node 앱) 형태로 계층 실행       |

'#개발 > node.js' 카테고리의 다른 글

npm의 git:// 프로토콜 오류  (0) 2025.11.09

사용 중인 spring security 버전 확인 방법

  1. build.gradle 확인
  2. Project Structure > Libraries 에서 spring-security 관련 라이브러리들의 버전 확인

spring security 동작 원리

모든 http 요청 -> spring security filter chain -> 인가 규칙에 맞는 요청에 대해서만 controller 로 요청이 전달

소스코드 예시

public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        // 1. CORS(교차 출처 리소스 공유) 설정을 활성화하고, 커스텀 cors 설정을 주입합니다.
        .cors(cors -> cors.configurationSource(corsConfigurationSource))

        // 2. HTTP Basic 인증(브라우저 팝업 아이디/비밀번호 방식) 비활성화
        .httpBasic(httpBasic -> httpBasic.disable())

        // 3. CSRF(사이트 간 요청 위조) 방어기능 비활성화
        .csrf(csrf -> csrf.disable())

        // 4. 폼 로그인(기본 로그인 페이지) 비활성화
        .formLogin(formLogin -> formLogin.disable())

        // 5. 세션 사용 정책을 'STATELESS'(무상태)로 설정 (세션 저장 X, JWT처럼 토큰 인증을 쓸 때)
        .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))

        // 6. 경로(URL) 별 인가(Authorization) 정책
        .authorizeHttpRequests(auth -> auth
            // 6-1. 아래 경로는 인증 없이 누구나 접근 허용
            .requestMatchers(
                "/api/v1/auth/login", 
                "/api/v1/chatbot/process-log", 
                "/api/v1/auth/change-password",
                "/api/v1/auth/reset-password", 
                "/api/v1/term",
                "/swagger-ui/**", 
                "/v3/api-docs/**"
            ).permitAll()
            // 6-2. 아래 경로는 로그인 인증한 사용자만 접근 허용
            .requestMatchers("/api/v1/auth/user-info").authenticated()
            // 6-3. 아래 경로는 ADMIN 역할을 가진 사용자만 접근 허용
            .requestMatchers("/api/v1/admin/**").hasRole("ADMIN")
            // 6-4. 그 외 나머지 모든 요청도 인증 필요(로그인 필요)
            .anyRequest().authenticated()
        );
    // 7. 커스텀 필터를 UsernamePasswordAuthenticationFilter 이전에 등록
    http.addFilterBefore(loggingApiKeyFilter, UsernamePasswordAuthenticationFilter.class);
    http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    // 8. 최종적으로 SecurityFilterChain을 build해서 빈으로 등록
    return http.build();
}

SecurityFilterChain

  .authorizeHttpRequests((auth) -> auth
    .requestMatchers("/public/**").permitAll() // 1. 누구나 접근
    .requestMatchers("/admin/**").hasRole("ADMIN") // 2. ADMIN만 접근
    .anyRequest().authenticated() // 3. 그 외는 로그인 필요
  );
  • authorizeHttpRequests → 인가 설정의 시작점, 체이닝 방식으로 여러 규칙 설정
  • spring6부터 authorizeReuqests 대신 authorizeHttpRequests 사용
// 1. 공개 경로 설정
.requestMatchers("/", "/login", "/signup").permitAll()


// 2. 특정 API 경로는 관리자만  
.requestMatchers("/admin/\*\*").hasRole("ADMIN")

// 3. 나머지는 로그인한 사용자만  
.anyRequest().authenticated()
  • requestMatchers : 어떤 url 패턴에 대해 규칙을 적용할지 지정
  • 괄호 안에 url 패턴(경로, 와일드카드 지정 가능)을 적으면, 그 url에 대한 권한을 바로 뒤에서 설정 (permitAll, hasRole 등)
  • 예전에는 antMatchers, 최신은 requestMatchers. 동작 방식은 비슷
  • 동작 순서: 요청 URL → 설정된 패턴과 매칭 → 허용/차단 결정
http.addFilterBefore(loggingApiKeyFilter, UsernamePasswordAuthenticationFilter.class);  
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
  • addFilterBefore, addFilterAfter, addFilter: security filter chain에 커스텀 필터를 삽입하기 위한 HttpSecurity 객체의 메서드
  • 필터 순서 중요성: 인증(JWT, 세션 등) 필터가 인가(권한) 검사보다 먼저 실행되어야 함
  • 예외 처리, 로그 남기기 등은 시점에 따라 적절한 위치에 삽입 필요

정리

  • 설정 코드는 위에서 아래로 순서대로 적용
  • 필터 실행은 addFilter/체인 기준 순서로 동작
  • 경로별 인가(permitAll, authenticated, hasRole)는 필터 실행 이후 판단됨
  • 애플리케이션이 구동될 때 설정코드 및 필터 순서에 대한 필터 체인 구성
  • HTTP 요청이 들어올 때 마다 미리 정해진 필터 순서에 따라 필터 실행

'#개발 > spring' 카테고리의 다른 글

java.lang.NoClassDefFoundError  (0) 2025.10.17
spring-boot-devtools  (0) 2025.10.08
H2 Database  (0) 2025.10.08
Thymeleaf  (0) 2025.10.08
프랙티스 가이드  (0) 2025.10.08

+ Recent posts