반응형

 

예제로, 특정 버튼을 클릭하면 홈화면이 뜨도록 해보자.

나는 IntroActivity 를 생성하고 버튼을 클릭하면 MainActivity 가 뜨도록 수정할것이다.

 

1. Intro Activity 생성

지난 포스팅에서와 같이, Activity 는 화면이라고 이해하면 되겠다.

 

MainActivity 의 상위 패키지에서 New > Activity > Empty Views Activity 를 선택한다

 

새로운 Activity 이름은 IntroActivity 로 설정하자

Layout Name 은 자동으로 바뀔텐데 혹시 자동으로 바뀌지않았다면 activity_intro 라고 입력해주자

 

2. Intro 꾸미기

 

아래와 같이 깔끔하게 기본세팅해준다

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

</layout>

 

이곳이 Intro Activity 임을 알수있게 꾸며주자.

 

간단하게 텍스트를 추가해보겠다. 웹에서는 <input> 태그를 사용했다면, 안드로이드에서는 EditText, 혹은 TextView 를 사용한다.

EditText는 수정가능한 <input> 이고, TextVeiw 는 수정불가한 <p> 태그와 비슷하다

 

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

////추가////
    <TextView
        android:text="This is Intro"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</layout>

 

이렇게하면 우측 미리보기화면에 글자가 나와있는것을 볼 수 있다.

만약 layout_width, height 를 설정하지않으면 글자가 안보인다. 해당 설정을 해줘야만 보인다

 

여기에, 버튼을 하나 추가해보자.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">
    <TextView
        android:text="This is Intro"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

///추가/////
    <Button
        android:text="버튼"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</layout>

 

이상하게도 버튼이 보이지않는다.

이럴때 필요한게 웹에서의 <li> 와 같은 기능이다.

 

안드로이드는 여러가지 요소를 세로, 혹은 가로로 나타나고싶을때 부모태그를 추가해줘야한다.

 

ConstraintLayout 을 쓰면 자동완성으로 아래와 같은 태가 보인다.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

////추가/////
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:text="This is Intro"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

        <Button
            android:text="버튼"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

 

width, height 를 match_parent로 해준다. 높이 넓이를 부모요소와 같게 하겠다는 뜻이다.

나는 텍스트와 버튼을 세로정렬로 해주고싶어서 orientation = vertical 인데, 세로정렬은 horizontal 이다

 

하지만 이렇게하면 버튼이 TextView를 덮어버리므로 버튼을 맨 아래로 보내고 TextView 를 정가운데로 보내보자.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:text="This is Intro"
            android:layout_width="wrap_content" ////수정////
            android:layout_height="wrap_content" ////수정////
            app:layout_constraintTop_toTopOf="parent" ////추가////
            app:layout_constraintBottom_toBottomOf="parent" ////추가////
            app:layout_constraintStart_toStartOf="parent" ////추가////
            app:layout_constraintEnd_toEndOf="parent"/> ////추가////

        <Button
            android:text="버튼"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"/> ////추가////
    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

 

이렇게 인트로 화면을 만들었다.

TextView 를 wrap_content 로 바꾼이유는, 상위요소 기준으로 가운데로 보내야되는데 넓이가 부모만큼 크면 어디로 보내야할지 모르게 된다.

 

그래서 TextView 범위는 content 를 감쌀정도, 작게 만들고 상위요소를 기준으로 해당 컨텐츠 위치를 조정하는 의미이다

 

 

3. Main Activity 로 이동하기

버튼을 누르면 MainActivity 로 이동시켜주려고 한다.

그러려면 버튼에 클릭이벤트를 주어야한다.

 

우선 버튼에 id를 할당하자.

//activity_intro.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:text="This is Intro"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"/>

        <Button
            android:id="@+id/btn_go_main" //// 추가 ////
            android:text="버튼"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"/>
    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

 

해당 xml 의 이벤트등록 및 데이터바인딩은 모두 activity_intro.xml 의 짝꿍 IntroActivity.kt 에서 할수있다.

//introActivity

class IntroActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_intro)
        
        //버튼 정의
        val goMainBtn = findViewById<Button>(R.id.btn_go_main)
        
        //버튼 클릭 이벤트
        goMainBtn.setOnClickListener {
            val intent = Intent(this, MainActivity::class.java)
            startActivity(intent)
        }
        
    }
}

 

버튼 정의 부분을 보면

findViewById<Button>(R.id.btn_go_main)

 

findViewById  : id를 기준으로 찾을건데

<Button> : 버튼 요소이며

R.id.btn_go_main : id 는 btn_go_main 

 

버튼을 goMainBtn 이라는 변수에 넣고 클릭이벤트를 준것이다.

 

Activity 간의 이동을 할때는 intent 정의 후 startActivity 로 이동한다. 이것은 공식!

 

외전) 버튼 정의 우아하게 하기

버튼정의할때 위의 방법은 기초적인 방법이고...실무에서 자주 쓰이는 binding 방법으로 수정하

 

1) build.gradle 수정

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
}
android {
    namespace 'com.example.basic_mobile'
    compileSdk 34
...
..
.

    kotlinOptions {
        jvmTarget = '1.8'
    }
    
    buildFeatures { ////추가////
        viewBinding = true
        dataBinding true
    }
}

 

buildfeatrures 를 추가해준다. 이것은 데이터바인딩을 하겠다는 의미.

build.gradle 수정하고 Sync now 를 클릭해준다.

 

2) IntroActivity 수정

class IntroActivity : AppCompatActivity() {

    private lateinit var binding : ActivityIntroBinding ////추가////
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

         ////수정////
        //binding 초기화 
        binding = ActivityIntroBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        //버튼 정의
        val goMainBtn = binding.btnGoMain ////수정////

        //버튼 클릭 이벤트
        goMainBtn.setOnClickListener {
            val intent = Intent(this, MainActivity::class.java)
            startActivity(intent)
        }
    }

}

 

binding 이라는 변수를 추가해주고, activity_intro.xml과 연결시킨다.

 

본인의 나는 activity_intro.xml 이라서 ActivityIntroBinding 이지만

만약 activity_sample,xml 이라면 ActivitySampleBinding 일것이다.

 

어짜피 자동완성되므로 괜춘.

 

4. 앱 실행 시 Intro Activity 실행

AndroidManifest.xml로 가서 앱 첫진입대상을 바꿔주자

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Basic_mobile"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity" //// 수정 ////
            android:exported="false" />
        <activity
            android:name=".IntroActivity" //// 수정 ////
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

 

이렇게하면, 앱 첫진입은 intro에서하고 버튼누르면 MainActivity 로 페이지 이동하는것을볼 수 있다.

 

 

 

만약 에러가 발생한다면 Logcat 을 확인하자

좌측 상단에 현재 내 에뮬레이터 기기가 맞는지 유의할것!!

 

디버깅이 필요하다면 벌레모양 클릭~

 

원하는 코드에 breack point 생성~

 

 

최종적으로 아래와 같은 동작을 확인할 수 있다.

728x90
반응형

1.  프로젝트 생성

안드로이드 스튜디오 -> New Project -> Empty Views Activity 

 

2. 화면 생성

Empty View Activity 로 프로젝트를 생성하면 아래와 같은 프로젝트를 확인할 수 있다.

 

 

자 이제 그러면 이 괴상하게 생긴 프로젝트를 뜯어보자.

 

애뮬레이터관련 세팅은 모두 완료했다고 가정하고, 프로젝트를 시작시키면 hello world 페이지가 나온다.

이 페이지는 어떻게 나온걸까?

 

 

1) activity_main.xml

바로 이곳을 통해서 나왓다. 이곳은 프로젝트를 생성하면 기본적으로 주어지는 페이지이다.

 

아래와 같은 파일이 보일텐데 겁먹지말고 우측의 Split 을 눌러주자.

 

 

그러면 아래와 같이 코딩을 할 수 있는 화면과 우측의 미리보기 화면이 제공된다

 

앞으로 개발할때는 이 화면을 기본으로 두고 개발하면 된다.

 

왼쪽 코드영역에서 TextView 태그를 자세히 보면 android:text = "Hello World!" 가 보일텐데, 이것이 앱에 보이는 글씨다.

 

그렇다면 어떤 원리로 이 화면이 나오게 되는걸까?

 

2) MainActivity.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

 

onCreate 라는 함수를 통해서 View 즉 화면을 생성한다.

 

create 를 할건데, 어떤 view를 보여줄것이냐? setContentView( ) 괄호를 보여줄것이다. 

괄호에 들어가는 파라미터는 R.layout. ~~ 이런 형식인데 R은 root 라고 생각하자.

 

프로젝트 root 에서 layout 폴더에 들어있는 xml들을 해당 파라미터에 넣을 수 있다.

현재는 activity_main 밖에없으므로 R.layout. 을 입력하면 자동완성으로 acitivity_main 이 보여질것이다.

(activity_main 을 Ctrl +우클릭 혹은 Ctrl + Alt 해보면 activity_main.xml로 이동됨)

 

이렇게 activity 를 통해서 view 화면이 앱에 보여지는데 정작 MainActivity는 어디서 실행되는걸까?

 

3) AndroidManifest.xml

 

이곳은 안드로이드 앱권한, intro 화면 설정, Activity 종류를 나열하는 곳이다.

새로운 Activity 를 생성하면 이곳에도 추가된다.

 

<activity> 태그를 보면 name 으로 MainActivity 가 적혀있는데, 이 태그는 MainActivity 에 대한 설정이라는 뜻

그리고 intent-filter 로

<action android:name="android.intent.action.MAIN" />

 

이것은 앱을 실행 시켰을 때 처음으로 진입하는 진입점이라는 표시다.

 

즉 해석하자면, MainActivity 가 있으며 이것은 앱을 실행했을때 가장 처음으로 노출되는 화면이라는 뜻이다.

 

 

3. 구조 정리

 

이렇게 프로젝트 생성과 어떻게 앱 화면이 노출되는지 순서대로 살펴보았다.

 

주요 개념은 아래와 같다.

 

build.gradle

dependencies 추가

 

manifests

앱권한, intro, mainActivity, splash 화면 설정

 

java

Activity 파일 위치하며, 로직을 작성하는 곳

 

res

이미지, 레이아웃, 화면을 그리는 xml 파일 등 resources가 위치함

 

728x90
반응형

Main 수정

저번 포스팅에서 만들었던 demo-main 모듈의 Main 클래스명을 변경하고 어노테이션을 달아주었다

@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }
}

 

해당 클래스 위치는 아래와 같다

application.yml 추가

그리고 나는 admin 과 main 모듈을 각각 실행시키고싶어서 port 설정을 추가해야하는 상황이라 application.yml을 추가해주었다

server:
  port: 8080

 

위치는 아래와 같이 resources 폴더를 만들고 그 안에 application.yml 을 추가하였다

 

Controller 생성

간단하게 테스트하기위하여 Restcontroller 로 생성하였다

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/main")
public class MainController {
    @ResponseBody
    @GetMapping("")
    public ResponseEntity index() {
        String result = "SUCCESS!!";

        return ApiResponseEntity
                .data()
                .put("result", result)
                .ok();
    }
}

 

위치는 아래와 같이 위치하면 된다

 

위 코드에 리턴타입이 ApiResponseentity 라고 되어있는데 해당 클래스는 core에 만들었다

 

Core 공통모듈 사용

 

이렇게 core 쪽에 내가 사용하고싶은 클래스를  추가하고 다른 모듈에서 자유롭게 불러서 사용가능하다

 

참고로 root 경로의 build.gradle 의  설정에 따라 타 모듈 -> core 연결이 가능한것이기 때문에

core -> 타 모듈 의 클래스를 import하는것은 불가능하다

728x90
반응형

 

spring boot 프로젝트 생성

 

intellij 에서 하든 spring 에서 하든.. 편한 방법으로 프로젝트를 생성한다

 

혹시 모르는 사람을 위하여 링크를 남겨둠

spring Initializr :  https://start.spring.io/

 

 

프로젝트 구조 수정

우선 root 경로의 src 폴더를 삭제한다

 

그리고 root 폴더 -> 우클릭 -> new -> Module 을 추가해준다

 

이때 내가 원하는 모듈갯수만큼 추가하면 된다

 

module name을 설정해주고

Build System 이 기본적으로 Maven 에 가있을건데 gradle로 해주자

아래 group Id 까지 설정해주면 완료

 

나는 총 3개의 모듈을 생성하였다

demo-main -> 사용자단 api 

demo-admin -> 관리자단 api

demo-core -> 공통 로직

 

 

전부 생성하게 되면 이런식의 구조를 확인할 수 있을것이다.

 

모듈 관계 설정

settings.gradle 설정

root 폴더 경로에 위치한 settings.gradle 에 모듈 설정을 추가해준다

rootProject.name = 'demo'
include 'demo-main', 'demo-admin', 'demo-core'

 

build.gradle 설정

모듈 별 공통 libraries 들을 설정해주고 각 모듈 별 관계성을 정리해주자

 

아래 내가 작업한 코드인데 눈여겨볼점은 project 설정부분이다

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.1.2'
	id 'io.spring.dependency-management' version '1.1.4'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
	sourceCompatibility = '17'
}

configurations {
	implementation {
		extendsFrom annotationProcessor
	}
}

subprojects {
	apply plugin: 'java'
	apply plugin: 'java-library'
	apply plugin: 'org.springframework.boot'
	apply plugin: 'io.spring.dependency-management'

	configurations {
		compileOnly {
			extendsFrom annotationProcessor
		}
	}

	repositories {
		mavenCentral()
	}

	// 관리하는 모듈의 공통 dependencies
	dependencies {
		implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
		implementation 'org.springframework.boot:spring-boot-starter-web'
		compileOnly 'org.projectlombok:lombok'
		developmentOnly 'org.springframework.boot:spring-boot-devtools'
		implementation "org.mariadb.jdbc:mariadb-java-client:2.1.2"
		implementation 'org.springframework.boot:spring-boot-starter-validation'
		annotationProcessor 'org.projectlombok:lombok'
		testImplementation 'org.springframework.boot:spring-boot-starter-test'

	}

	test {
		useJUnitPlatform()
	}
}

project(':demo-main') {
	jar {
		archivesBaseName = 'demo-main'
	}
	dependencies {
		//컴파일 시 core 로드
		compileOnly project(':demo-core')
	}
}

project(':demo-admin') {
	jar {
		archivesBaseName = 'demo-admin'
	}
	dependencies {
		//컴파일 시 core 로드
		compileOnly project(':demo-core')
	}
}

project(':demo-core') {
	//bootJar로 패키징 할 필요 없음 Main() 메서드 필요없기때문
	bootJar { enabled = false }
	jar { enabled = true }
}

clean {
	delete file('src/main/generated')
}

 

 

configurations 에 compileOnly가 꼭 있어야 멀티모듈 dependencies 의 compileOnly 설정을 사용할 수 있다

subprojects {
	apply plugin: 'java'
	apply plugin: 'java-library'
	apply plugin: 'org.springframework.boot'
	apply plugin: 'io.spring.dependency-management'

	configurations {
		compileOnly {
			extendsFrom annotationProcessor
		}
	}
}

 

 

 

개별 모듈 build.gradle 설정

 

공통로직 모듈을 제외한 다른 모듈의 경우 아래와 같이 작성하면 된다

dependencies 에 core 모듈을 implementation 에 추가한다

plugins {
    id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    implementation project(':demo-core')

    testImplementation platform('org.junit:junit-bom:5.9.1')
    testImplementation 'org.junit.jupiter:junit-jupiter'
}

test {
    useJUnitPlatform()
}

 

core 모듈은 build.gradle 없애놓고 저장!

 

여기까지하면 모듈간 관계설정 세팅이 완료되었다.

 

다음 포스팅에서 실제로 활용해보자

 

728x90
반응형

 

Preferences -> Android -> SDK location 설정

 

Project -> 버전선택

728x90
반응형

 

이클립스..안드로이드....

 

jar 파일 import 했는데 적용이 안됐다

 

하나씩 확인해보자

 

1. jar 파일 까보면 .class 가 아닌 .java 로 되어있는지

2. libs 폴더에 넣고 해당 jar 파일 우클릭 -> build path -> add build path 했는지

3. 프로젝트 우클릭 -> properties -> Java Build Path -> Order and Export 에서 해당 jar 파일 체크 되어있는지

 

나는 마지막 3번.. import 시켜놧더니만 이클립스 툴 자체의 properties 에서 체크를 안해놔서 import가 안됐었다..

인텔리제이만 써가지고..;; 이런경우보니까 너무 당황스럽다 ㅠㅠ

 

참고로 Android private libraries 체크해제 안하면 에러뜬다; 쟤도 꼭 체크해제 해주길

728x90
반응형

 

그런일이 일어나서는 안되겠지만

혹시 이클립스로 안드로이드를 작업하는 일이 생긴다면...

 

아래와 같은 오류메세지를 볼수도있다

 

Android Dx Error1, Failed to convert to Dalvik format

 

그럴때는 프로젝트 우클릭 -> Properties -> Java Build Path -> Order and export 클릭

 

Android Private Libraries 체크를 해제해주자

 

728x90
반응형

 

 

react 프로젝트에서 svg를 import 시키고 컴포넌트를 아래와 같이 추가하였다

import {useRouter} from "next/router";

import GoogleSignIn from '@/assets/googleIcon.svg'

export const JoinGoogle = () => {

    function socialLoginGoogle() {
        ///////
    }

    return (
        <>
            <button onClick={socialLoginGoogle}>
                <GoogleSignIn />
                구글로 가입하기
            </button>
        </>
    )
}


별다른 문제가 없을거라 생각했는데, 오류가 발생하였다

 

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

 

터미널 로그에서는 <GoogleSignIn/>을 확인하라고 보여진다

 

Check your code at JoinGoogle.tsx:21.

 

확인해보니, svg파일을 사용하려면 별도의 플러그인을 install 해야한다고 함...

 

해결방법

 

1. install svgr webpack 

npm install -D @svgr/webpack

 

터미널에서 svgr webpack 을 다운받는다

 

2. next.config.js 수정

/** @type {import('next').NextConfig} */
const nextConfig = {

....
  webpack(config) {
    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack'],
    })
    return config
  },
  
  .....
}

module.exports = nextConfig

 

webpack 설정을 추가해준다

728x90
반응형

localhost:3000 이라는 포트로 만들어진 react 프로젝트에서

다른 포트번호로 실행된 백단 프로젝트를 연결할때 api cors error 를 필연적으로 만나게된다.

 

해결방법은 간단하다

 

1. next.config.js 수정

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: false, //true 면 next dev 실행할때 useEffect 2번씩 실행
  swcMinify: true,
  eslint: {
    ignoreDuringBuilds: true,
  },
  compiler: {
    styledComponents: true,
  },
  images: {
    unoptimized: true,
    domains: ['picsum.photos', 'img.dmitory.com', 'image.edaily.co.kr'],
  },
  webpack(config) {
    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack'],
    })
    return config
  },
  //api cors 에러 프록시 설정
  async rewrites() {
    return [
      {
        source: '/api-aaa/:path*',
        destination: 'http://localhost:8080/api-aaa/:path*',
      },
      {
        source: '/api-bbb/:path*',
        destination: 'http://localhost:8090/api-bbb/:path*',
      },
      {
        source: '/api-ccc/:path*',
        destination: 'http://localhost:8443/api-ccc/:path*',
      },
      {
        source: '/upload/:path*',
        destination: 'http://localhost:8443/upload/:path*',
      },
    ]
  },
}

module.exports = nextConfig

 

 

rewrites 안쪽에 내가 통신하려고 하는 서버의 포트번호를 넣어주면 된다

나의 경우 멀티모듈을 사용했기때문에 저렇게 많은 포트가 필요했다

 

source 설정

지난 포스팅에 있는것처럼 api 호출할때 아래와 같은식으로 호출되는 부분이 있다고 한다면, 

getMenu = async ()=> {
    return await client.get('/api-aaa/menu/list')
}

 

/api-aaa/ 를 prefix로 삼고 api-aaa 로 통신하는 모든 uri들은 포트 8080으로 가게끔 경로를 틀어준다는 의미이다

 

destination 설정

만약 로컬에서 프론트/백단 소스를 모두 띄운다면 위 코드는 문제가 없겠지만

 

로컬에서 프론트 실행하고, 다른 서버에서 백단을  실행하거나

프론트/백단 소스코드를 모두 다른 서버(aws, linux 등..) 에서 실행한다면 destination 을 변경해야한다

...

async rewrites() {
    return [
      {
        source: '/api-aaa/:path*',
        destination: 'http://서버IP:8080/api-aaa/:path*',
      },
      {
        source: '/api-bbb/:path*',
        destination: 'http://서버IP:8090/api-bbb/:path*',
      },
      {
        source: '/api-ccc/:path*',
        destination: 'http://서버IP:8443/api-ccc/:path*',
      },
      {
        source: '/upload/:path*',
        destination: 'http://서버IP:8443/upload/:path*',
      },
    ]
  },

...

 

localhost 부분을 서버IP로 바꿔주면 된다.

 

 

2. 백단 소스코드수정

만약 WebConfig 를 설정하는 소스코드가 있다면 해당부분을 수정하고 없다면 새로만들어주자

@Configuration 으로 전체검색했을때 없으면 없는것

 

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Value("${config.server-url}")
    String serverUrl;

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://" + serverUrl + ":3000") // 프론트의 주소와 포트번호
                .allowedMethods("GET", "POST")
                .allowCredentials(true);
    }

}

 

 

나는 get 과 post만 열어줬고 이 설정만 추가하면 잘될것!!

 

혹시 allowedOrigins에 다른 ip주소도 추가해야한다면 아래와같이 콤마로 추가할수있다

.allowedOrigins("http://" + serverUrl + ":3000", "http://어쩌고ip:3000")

 

 

그래도 안된다면, spring security 사용하고있는경우 security 설정에서 막고있는게 아닌지 확인해야 한다.

 

그래도 안된다면!! IP주소 혹은 API PATH 오타가 있지는 않은지 확인해보자

728x90
반응형

 

 

 

 [webpack.cache.PackFileCacheStrategy] Caching failed for pack: Error: Cannot find module 'mini-css-extract-plugin/dist/CssDependency'

 

.next 의 cache 폴더 삭제

728x90

+ Recent posts