5 minute read

리액트 구축 흐름

만약 프론트서버와 백앤드서버 개발을 완료했다.
이제 실행하는 큰 관점에서 흐름을 간략하게 알아보자.

흐름1. 각각의 독립된 서버환경에서 운영하기

각각의 서버에서 운영하는 방법이다.

  1. build 시키지 않고
  2. 프론트 서버(리액트)를 실행한다.
  3. 백앤드 서버(톰캣)를 실행한다.

    각각의 서버를 띄우는 가장 간단한 방법이다.
    프론트 서버에서 내부코드 변경분이 일어나면 프론트서버가 독립적으로 운영되므로 컴파일이 빠르게 가능하다. 그리고 백앤드서버는 조작없이 기존과 동일하게 프론트 서버의 자원을 바라만 보면된다. 즉, 백앤드서버 측에서 프론트서버 자원을 build 절차를 거치고 백앤드 서버를 재기동 할 필요도 없다.

흐름2. 백앤드에서 운영하기

프론트 서버를 운영하지 않고, 프론트 자원을 빌드한 리소스를 가지고 백앤드 서버에서 운영하는 방법이다.

  1. 프론트 자원을 build (백앤드 서버 자체가 없다.)
  2. 빌드한 자원은 백앤드 서버로 업로드
  3. 백앤드 서버 측에 업로드한 프론트자원 build/index.html 내용물을 참조하도록 설정한다.
  4. 백앤드 서버 재기동 (끝)

    백앤드 혼자서 프론트 자원까지 관리하는 방법이다.이다.

    1. build 하고 빌드 결과를 서버측에 로드하고 실행 및 확인해야하고
    2. 프론트 서버를 테스트할때 코드를 수정하면 자동 컴파일해주는 nodemo(노드몬)패키지등의 장점을 버려야한다. 백앤드 서버에 올리고 백앤드 서버를 재기동 해야하기 때문이다.

결론

결론은 개발 중일 때에는 흐름1(각각의 독립된 서버환경에서 운영하기)으로 편리하게 백앤드 & 프론트 서버를 실행하고 테스트 하는게 편한듯..!


백앤드 <> 리액트 다양한 연동방법

방법론 종류

  1. 스프링-부트와 create-react-app 함께 사용
  2. 정적 자원을 별도의 디렉토리에 배치
  3. proxy 설정

방법1. 스프링-부트와 create-react-app을 함께 사용하기

사진1

STEP1. 스프링-부트 프로젝트 생성

# 스프링-부트 프로젝트를 생성
# Maven 또는 Gradle을 사용하여 프로젝트를 생성할 수 있다. (이전 포스팅 참조^^)

STEP2. create-react-app 프로젝트 생성

# 스프링-부트 프로젝트 디렉토리 내부에 프론트엔드 리액트 프로젝트를 생성 
# 스프링-부트 프로젝트의 루트 디렉토리에서 다음 명령을 실행 
npx create-react-app frontend 

STEP3. 프로젝트 구조 설정

두 프로젝트를 하나로 통합 해야한다. 즉, 스프링-부트 프로젝트와 리액트 프로젝트를 하나의 프로젝트로 구성하도록 하자.

참고)일반적인 실제 운영환경에서는?
[관리 차원]에서는 스프링-부트 프로젝트와 리액트 프로젝트는 각각 독립적으로 관리 된다.
[배포 차원]에서는 운영 환경에서 빌드된 리액트 정적 자원을 스프링-부트에 포함하여 서빙하는 것이 일반적이다!

  • ( AS-IS ) 스프링 프로젝트

      - src/
      - main/
          - java/
          - resources/
    
  • ( TO-BE ) 스프링 프로젝트

      - src/
      - main/
          - java/
          - resources/
          - webapp/
          - frontend/  # 이곳에 리액트 프로젝트를 넣었다.
              - (리액트 프로젝트 내용)
    

STEP4. 서버 설정

# 백앤드(스프링-부트) 서버 설정을 수정하여 프론트엔드 리액트 애플리케이션을 호스팅할 수 있도록 설정한다.
# (리액트 정적 파일들의 경로를 매핑하여 서빙)

# (application.properties)
spring.resources.static-locations=classpath:/webapp/frontend/build/

위 설정은 스프링-부트가 / 경로로 요청이 오면 리액트 빌드한 정적 파일들이 있는 경로를 제공합니다.

STEP5. 빌드와 배포

# 1. 개발한 리액트 프로젝트를 빌드 
# 2. 개발한 스프링-부트 프로젝트를 빌드 (스프링-부트의 빌드 도구인 Maven 또는 Gradle을 사용하여 빌드)
# 3. 하나의 애플리케이션으로 패키징 
# 4. 패키징된 어플리케이션을 톰캣과 같은 WAS서버에 배포하면 끝 ! 

# 스프링 실행 후 테스트
mvn spring-boot:run # 메이븐
gradle bootRun # 그래들

최종적으로 프론트엔드와 백엔드가 함께 호스팅되는 애플리케이션이 배포되었다.

  • 개발 환경에서는 CORS 이슈가 발생하지 않도록 주의해야 한다.
  • 리액트 개발 서버의 기본 포트인 3000과 스프링-부트 서버의 기본 포트인 8080은 CORS 이슈를 일으킬 수 있으므로, 서로 다른 포트로 실행하거나 CORS 설정을 추가하여 이슈를 회피해야 한다.
  • 본 방법은 개발 환경에서 사용되며, 운영 환경에서는 빌드된 리액트 정적 자원을 스프링-부트에 포함하여 서빙하는 것이 일반적이다.

별첨) 개발 모드에서 실행방법

단순하게 각각 실행하면 끝이다.

  • 백앤드

      cd [프로젝트 루트]
    
      # 백앤드 서버 실행
      mvn spring-boot:run # 메이븐
      gradle bootRun # 그래들
    
    
  • 프론트

      cd [프로젝트 루트]/src/main/frontend
    
      # 프론트 서버 실행
      npm start # 리액트 개발서버 실행
    
    

서버 실행 확인)
웹 브라우저를 열고 각각의 주소로 접속하여 스프링-부트 서버와 리액트 개발 서버가 정상적으로 실행되는지 확인.

  • 스프링-부트 서버는 기본적으로 http://localhost:8080에서 실행
  • 리액트 개발 서버는 기본적으로 http://localhost:3000에서 실행

이렇게 하면 개발 중에 리액트 개발 서버가 hot-reloading 기능을 제공하고, 스프링-부트 서버는 백엔드 로직을 처리하여 프론트엔드와 백엔드가 독립적으로 개발 및 테스트 가능하다. 본 방법은 개발 환경에서 사용되며, 운영 환경에서는 빌드된 리액트 정적 자원을 스프링-부트에 포함하여 서빙하는 것이 일반적이다.

방법2. 정적 자원을 별도의 디렉토리에 배치

사진2

STEP1. 리액트 프로젝트 빌드

# 리액트 프로젝트를 빌드하여 정적 파일들을 생성 (/build 디렉토리가 가 생긴다.)
npm run build

STEP2. 프로젝트 구조 설정

두 프로젝트를 하나로 통합 해야한다. 즉, 스프링-부트 프로젝트와 리액트 프로젝트를 하나의 프로젝트로 구성하도록 하자.

참고)일반적인 실제 운영환경에서는?
[관리 차원]에서는 스프링-부트 프로젝트와 리액트 프로젝트는 각각 독립적으로 관리 된다.
[배포 차원]에서는 운영 환경에서 빌드된 리액트 정적 자원을 스프링-부트에 포함하여 서빙하는 것이 일반적이다!

  • ( AS-IS ) 스프링 프로젝트

      - src/
      - main/
          - java/
          - resources/
    
    
  • ( TO-BE ) 스프링 프로젝트

      - src/
      - main/
          - java/
          - resources/
          - static/     # static 을 생성하고 이곳에 빌드결과(/bulid) 내용물을 넣는다.
              - index.html  # (리액트 빌드 결과물 중 index.html)
              - static/     # (리액트 빌드 결과물 중 static 디렉토리)
    
    

STEP3. 서버 설정

# 백앤드(스프링-부트) 서버 설정을 수정하여 프론트엔드 리액트 애플리케이션을 호스팅할 수 있도록 설정한다.
# (리액트 정적 파일들의 경로를 매핑하여 서빙)

# (application.properties)
# spring.resources.static-locations=classpath:/webapp/frontend/build/
spring.resources.static-locations=classpath:/static/

STEP4. 테스트

# 스프링 실행
mvn spring-boot:run # 메이븐
gradle bootRun # 그래들

http://localhost:포트번호/
# 1. 스프링 프로젝트를 실행하고 접속하면 
# 2. 톰캣이 리액트 빌드한 정적 파일들을 서빙하는 것을 확인할 수 있다. 
# 3. 톰캣자체가 리액트 프론트엔드 소스를 들고있다.

최종적으로 백앤드 내부의 정적자원으로 프론트소스가 백앤드로 흡수된 애플리케이션이 배포되었다.
이와 같이 '정적 자원을 별도의 디렉토리에 배치' 하는 방법을 사용하면

  • 스프링 프로젝트와 리액트 프로젝트를 독립적으로 관리하면서도 하나의 애플리케이션으로 통합하여 개발할 수 있다.
  • 리액트 개발 서버를 사용하지 않고, 톰캣이 리액트 빌드한 정적 자원을 제공하기 때문에 CORS 이슈를 걱정할 필요가 없다.

방법3. proxy 설정 (백앤드<>프론트)

사진3

과정

  1. 스프링-부트 애플리케이션에서는 리액트 서버의 주소로 요청
  2. 리액트 서버에서는 프론트엔드 자원을 서빙

    이 방법은 백앤드(스프링-부트)에서 프록시 설정을 통해 리액트 서버를 호출하는 방법이다.

    • “proxy 설정” 방법을 사용하면 스프링 프로젝트의 톰캣이 빌드한 리액트 자원을 서빙하지 않고,
    • 리액트 개발 서버가 프론트엔드 자원을 서빙하도록 하면서도
    • 스프링 프로젝트에서 리액트 백엔드 API를 호출할 때 CORS 이슈를 회피할 수 있다.
    • 이 방법을 사용하면 개발 환경에서 리액트 개발 서버와 스프링-부트를 함께 실행하여 개발할 수 있다.

STEP1. 리액트 프로젝트 설정

// package.json
{
  // ... (기존 설정)
  "proxy": "http://localhost:8080"  // 스프링 서버 주소
}

/*
위 설정은 리액트 개발 서버가 프론트엔드 자원을 제공할 때 
API 요청은 http://localhost:8080으로 프록시되도록 설정한다.
따라서 리액트 개발 서버가 동작 중일 때, API 요청을 보내면 
스프링 서버로 요청이 전달되며, CORS 이슈를 회피할 수 있다.
*/

STEP2. 스프링 프로젝트 설정

# 스프링-부트 프로젝트는 일반적인 설정으로 진행. 
# 특별한 CORS 설정이 필요 없다.

STEP3. 개발 모드에서 실행

단순하게 각각 실행하면 끝이다.

  • 백앤드

      cd [프로젝트 루트]
    
      # 백앤드 서버 실행
      mvn spring-boot:run # 메이븐
      gradle bootRun # 그래들
    
    
  • 프론트

      cd [프로젝트 루트]/src/main/frontend
    
      # 프론트 서버 실행
      npm start # 리액트 개발서버 실행
    
    

STEP4. 테스트

# 스프링 실행
mvn spring-boot:run # 메이븐
gradle bootRun # 그래들

http://localhost:포트번호/
# 1. 스프링 프로젝트를 실행하고 접속하면 
# 2. 톰캣이 리액트 빌드한 정적 파일들을 서빙하는 것을 확인할 수 있다. 
# 3. 톰캣자체가 리액트 프론트엔드 소스를 들고있다.

최종적으로 백앤드 내부의 정적자원으로 프론트소스가 백앤드로 흡수된 애플리케이션이 배포되었다.

[프론트서버 API요청] - [프록시] - [프록시로 인한 백앤드서버로 전달]

이와 같이 '프록시 설정' 방법을 사용하면

  • 리액트 개발 서버는 프론트엔드 자원을 서빙하고, API 요청은 http://localhost:8080으로 프록시되어 스프링-부트 서버로 전달한다.
  • 따라서 CORS 이슈 없이 리액트 개발 서버와 스프링-부트 서버가 동시에 동작하게 된다.

Tags:

Categories:

Updated:

Leave a comment