숫자 사이에 콤마( , )를 찍는 방법은 대표적으로 java.text.DecimalFormat 클래스를 활용하는 방법과 정규식을 활용하는 방법이 있다.

 

1. java.text.DecimalFormat 클래스를 활용

int amount = 1000000000;
DecimalFormat decimal = new DecimalFormat("###,###");
String money = decimal.format(amount);
System.out.println(money);

 

 

2. 정규식 활용방법

String amount = "1000000000";
amount = amount.replaceAll("\\B(?=(\\d{3})+(?!\\d))", ",");
System.out.println(amount);

'Study > Java' 카테고리의 다른 글

Java - 배열관련 메서드  (0) 2023.04.17
Java - String split(String regex) 메서드  (0) 2023.04.17
JSON Object 생성 시 한글 (???) 깨지는 현상 해결  (0) 2023.03.22
애너테이션 / 스트림  (0) 2022.11.15
컬렉션  (0) 2022.11.10

AWS에서 과금되지 않도록 RDS생성시 설정하는 방법을 공유한다.

 

 

AWS RDS를 들어가서 데이터베이스 생성한다.

 

 

 

상세설정

1. 본인이 원하는 DB유형을 선택한다.

 

 

2. 프리티어로 만들것이기 때문에 프리티어를 선택한다.

 

 

3. 

  • DB 인스턴스 식별자 : 현재 AWS 리전에서 AWS 계정이 소유하는 모든 DB 인스턴스에 대해 고유한 이름을 작성합니다.
  • 자격 증명 설정 : 마스터 사용자의 아이디/비번을 작성합니다.

 

 

4. 사용 목적에 맞는 성능을 고려하여 인스턴스를 선택한다.

프리티어는 선택할것 없이 기본값을 고르고 넘어간다.

 

 

5. (필수!) 스토리지는 20으로 반드시 설정 ->  스토리지 자동 조정 활성화를 꺼준다.

- 스토리지 자동조정 기본값이 1000Gib로 되어있는데 이상태로 사용하면 요금폭탄을 맞을 수 있다. 

스토리지 자동 조정기능은 스토리지 용량을 동적으로 조정하는 기능이다.

프리티어

  • -단일 AZ db.t2.micro 인스턴스에서 Amazon RDS의 750시간.
  • 20GB의 범용 스토리지(SSD).
  • 20GB의 자동 백업 스토리지 및 사용자가 시작한 모든 DB 스냅샷.

 

6. 연결설정 퍼블릭 액세스 예로 선택 -> VPC보안그룹은 설정한 것이 있다면 선택, 없다면 새로생성을 선택하여 아래의 글을 참고

 

보안규칙에 내 IP 추가하기

- 설정을 마쳐야 내 IP에서 접속할 수 있다.

https://kjsu1994.tistory.com/38 

 

 

7. 가용 영역

  • 서울 Region에는 ap-northeast-2a, ap-northeast-2c 두 개의 가용영역(AZ)이 존재한다.

 

 

8. 보안그룹은 설정된 것이 있다면 선택하고 없다면 추후에 설정해준다.

 

 

 

9. 암호인증

 

 

10. 보존기간 0일로 설정한다.

이설정기간이 길게 되어있으면 한참후에 요금이 폭탄으로 청구될 수 있다고 함.

 

 

11. 혹시몰라 유지관리설정도 꺼줬다. (자율)

 

 

 

엔드포인트는 RDS접속 주소이고 기본 포트번호는 3306이다

패스워드는 RDS생성시 입력했던 패스워드를 사용한다.

 

 

 

yml 설정

spring:
  datasource:
    url: jdbc:mysql://[엔드포인트]:3306/[DB명]?serverTimezone=Asia/Seoul
    username: [마스터이름]
    password: [패스워드]
  jpa:
    hibernate:
      ddl-auto: create
    show-sql: true
    properties:
      hibernate:
        format_sql: true
        default_batch_fetch_size: 1000 # N+1문제 해결

기존에는 직접 Dto나 Parameter을 통해 유저의 Id를 받아오는 방식사용하였지만

 

Security를 적용한 이후 헤더에 입력된 토큰값을 통해서  해당 유저의 로그인 아이디를 받아올 수 있다.

- SecurityContextHolder.getContext().getAuthentication().getName()

 

 

아래 메서드를 통해 헤더값에 넣어주는 토큰을 통하여

토큰을 발급받아 사용하는 유저가 로그인시 입력한 이메일 정보를 얻어오고

이메일 정보를 이용해서 해당유저의 엔티티를 가져올 수 있는 코드이다. 

 

원하는 곳에 추가하여 사용하면 된다.

private Member loginMemberFindByToken(){
    String loginEmail = SecurityContextHolder.getContext().getAuthentication().getName(); // 토큰에서 유저 email 확인
    return memberService.findMemberByEmail(loginEmail); //이메일을 통해 유저 엔티티 반환
}

 

 

 

필요한 코드 -

Service 

public Member findMemberByEmail(String email){ //로그인 이메일을 통해 유저 엔티티 반환 메서드
    Optional<Member> foundMember = memberRepository.findByEmail(email);
    return foundMember.orElseThrow(()-> new BusinessLogicException(ExceptionCode.MEMBER_NOT_FOUND));
}

 

Repository - 이메일에 대한 회원정보 찾기

public interface MemberRepository extends JpaRepository<Member, Long> {
    Optional<Member> findByEmail(String email);
}

 

네이버 검색 API연동해서 뉴스 크롤링.

 

https://developers.naver.com/docs/serviceapi/search/news/news.md#%EB%89%B4%EC%8A%A4

 

검색 > 뉴스 - Search API

검색 > 뉴스 뉴스 검색 개요 개요 검색 API와 뉴스 검색 개요 검색 API는 네이버 검색 결과를 뉴스, 백과사전, 블로그, 쇼핑, 영화, 웹 문서, 전문정보, 지식iN, 책, 카페글 등 분야별로 볼 수 있는 API

developers.naver.com

예시까지 친절하게 설명해준다.

 

먼저 내 애플리케이션을 등록하고 API에 대한 id와 key를 받아야한다.

 

나는 400/401에러가 계속났는데 yml의 id와 key를 잘못 입력하고 원인을 다른곳에서 찾아 몇시간을 헤맸다.

 

 

yml 설정부

naver:  #naver API 설정
  url:
    search:
      news: https://openapi.naver.com/v1/search/news.json   #뉴스검색 URL
      image: https://openapi.naver.com/v1/search/image    #이미지검색
  client:
    id: ENC(rbiCFlHAp11Uusawse9EDX4NTmpRvfEJewqabaeeqefvZM=) #암호화된 키
    secret: ENC(CbqkdospKojXkFsiY2OueQOdLpMbveCTJkbKN9/)

 

Dto

public class SearchNewsDto {
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class Post { //검색 쿼리
        private String query = ""; //검색어. UTF-8로 인코딩되어야 합니다.
        private int display = 20; //한 번에 표시할 검색 결과 개수(기본값: 10, 최댓값: 100)
        private int start = 1; //검색 시작 위치(기본값: 1, 최댓값: 1000)
        private String sort = "sim"; // sim: 정확도순 , date: 날짜순

        /*데이터를 한꺼번에 들어가게 해주는 메서드*/
        public MultiValueMap<String, String> toMultiValueMap() {
            var map = new LinkedMultiValueMap<String, String>();

            map.add("query", query);
            map.add("display", String.valueOf(display));
            map.add("start", String.valueOf(start));
            map.add("sort", sort);

            return map;
        }
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class Response { //반환값
        private String lastBuildDate; //검색한 결과를 생성한 시간
        private int total; // 총 검색결과 갯수
        private int start; // 검색 시작 위치
        private int display; // 한번에 표시할 검색결과 갯수
        private List<NewsItem> items;
        @Data
        @NoArgsConstructor
        @AllArgsConstructor
        public static class NewsItem {
            private String title; //제목
            private String originallink; // 뉴스기사 원문 URL
            private String link; //뉴스 기사의 네이버 뉴스 URL. 네이버에 제공되지 않은 기사라면 기사 원문의 URL을 반환합니다.
            private String description; // 뉴스기사 내용을 요약한 정보
            private String pubDate;
        }
    }
}

 

Controller

@RequiredArgsConstructor
@RequestMapping("/news")
@RestController
public class NaverSearchController {
    private final NaverClient naverClient;
    @GetMapping
    public ResponseEntity searchNews(@RequestParam(required = false, defaultValue = "환경") String query,
                                     @RequestParam(required = false, defaultValue = "1") int start,
                                     @RequestParam(required = false, defaultValue = "20") int display,
                                     @RequestParam(required = false, defaultValue = "sim") String sort){

         SearchNewsDto.Response response = naverClient.searchQuerySet(query, start, display, sort);

        return new ResponseEntity<>(response, HttpStatus.OK);
    }
}

 

Service

@Service
public class NaverClient {
    @Value("${naver.client.id}")
    private String naverClientId; //id
    @Value("${naver.client.secret}")
    private String naverClientSecret; //시크릿키
    @Value("${naver.url.search.news}")
    private String naverNewSearchUrl; //뉴스 검색주소
    @Value("${naver.url.search.image}")
    private String naverImageSearchUrl; //이미지 검색주소

    /* 뉴스검색 메서드*/
    public SearchNewsDto.Response searchNews(SearchNewsDto.Post post){
        var uri = UriComponentsBuilder.fromUriString(naverNewSearchUrl) //뉴스검색 주소
                .queryParams(post.toMultiValueMap())
                .build()
                .encode()
                .toUri();

        var headers = new HttpHeaders(); //http헤더에 키값을 넣어줌
        headers.set("X-Naver-Client-Id", naverClientId);
        headers.set("X-Naver-Client-Secret", naverClientSecret);
        headers.setContentType(MediaType.APPLICATION_JSON); //Json형식으로 변환

        var httpEntity = new HttpEntity<>(headers); //요청하는 부분
        var responseType = new ParameterizedTypeReference<SearchNewsDto.Response>(){}; //응답값

        var responseEntity = new RestTemplate().exchange( //모든 정보를 담아주는 부분
                uri,
                HttpMethod.GET,
                httpEntity,
                responseType
        );
        return responseEntity.getBody();
    }

    public SearchNewsDto.Response searchQuerySet(String query, int display, String sort){
        SearchNewsDto.Post post = new SearchNewsDto.Post();
        post.setQuery(query);
        post.setStart(start);
        post.setDisplay(display);
        post.setSort(sort);

        return searchNews(post);
    }
}

 

결과화면

스프링 시큐리티 로그인 시 출력값에 대한 작업중 objectMapper.writeValueAsString()로 변환했을때 한글로 입력한 name이 ???로 출력되는것을 확인하였다.

 

writeValueAsString 도입이후 발생한 인코딩문제로 확인하였으며 이에 대한 해결 방안을 찾아본 결과 

 

다음과 같은 코드를 추가해주면 해결된다.

//HttpServletResponse response
response.setCharacterEncoding("UTF-8"); // objectMapper.writeValueAsString 한글깨지는 것에 대한 대응코드

 

 

 

메서드 전체코드

public class MemberAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
                                        HttpServletResponse response, //<- 적용할 파라미터
                                        Authentication authentication) throws IOException, ServletException {
        Member member = (Member) authentication.getPrincipal();

        response.setCharacterEncoding("UTF-8"); // objectMapper.writeValueAsString 한글깨지는 것에 대한 대응코드

        /*MemberDetails에서 유저정보를 가져와서 리스폰스에 뿌려주는 부분*/
        Map<String, Object> loginResponse = new HashMap<>();
        loginResponse.put("memberId", member.getMemberId());
        loginResponse.put("email", member.getEmail());
        loginResponse.put("roles", member.getRoles());
        loginResponse.put("level", member.getLevel().getLevel());
        loginResponse.put("name", member.getName());


        ObjectMapper objectMapper = new ObjectMapper();
        String responseBody = objectMapper.writeValueAsString(loginResponse);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);

        response.getWriter().write(responseBody);

        log.info("# Authenticated successfully");
        log.info("name:{}, email: {}, role: {}", member.getName(), member.getEmail(), member.getRoles() );
    }
}

'Study > Java' 카테고리의 다른 글

Java - String split(String regex) 메서드  (0) 2023.04.17
Java - 문자열 3자리마다 콤마찍기 (금액 표기하기)  (0) 2023.03.24
애너테이션 / 스트림  (0) 2022.11.15
컬렉션  (0) 2022.11.10
제네릭 / 예외처리  (0) 2022.11.10

Jasypt를 통해 암호화를 하였다. https://kjsu1994.tistory.com/41

자동배포를 위해 암호화에 사용한 패스워드를 깃허브 액션에서 환경변수로 관리하는 방법을 공유한다.

 

 

1. 자동배포하려는 레포지토리에서 Settings 클릭 ->

Secrets and variables -> Actions 클릭 -> 우측의 초록색 버튼 클릭

 

 

2. 이곳에서 환경변수 명 / 시크릿 키를 입력하고 Add Secret버튼을 누른다.

 

3. 환경변수로 등록된 것을 확인한다.

 

 

4. yml 설정 / 저장된 환경변수 사용하기

jasypt: #패스워드 암호화/복호화 키
  encryptor:
    password: ${{secrets.SECRET_KEY}} # 깃허브액션에 등록된 환경변수 사용

${{secrets.환경변수명}} 형식으로 저장해주면 된다.

yml설정에서 AWS나 DB와 관련된 키값을 암호화 하려고 한다.

 

JASYPT 는 암호화에 관해 잘 모르는 개발자도 손쉽게 암호화를 할 수 있도록 돕는다.

 

 

1.  우선 gradle설정을 추가한다.

implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.3' // yml Secret Key 암호화

 

 

2.  암호화 관련 설정 클래스파일 만들기

https://github.com/ulisesbocchio/jasypt-spring-boot#use-you-own-custom-encryptor

에서 확인할 수 있다.

 

GitHub - ulisesbocchio/jasypt-spring-boot: Jasypt integration for Spring boot

Jasypt integration for Spring boot. Contribute to ulisesbocchio/jasypt-spring-boot development by creating an account on GitHub.

github.com

@Configuration
public class JasyptConfig {

    @Value("${jasypt.encryptor.password}")
    private String password;

    @Bean("jasyptStringEncryptor")
    public StringEncryptor stringEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword(password);
        config.setAlgorithm("PBEWithMD5AndDES");
        config.setKeyObtentionIterations("1000");
        config.setPoolSize("1");
        config.setProviderName("SunJCE");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
        config.setStringOutputType("base64");
        encryptor.setConfig(config);
        return encryptor;
    }
}

-  나는 외부에서 키값을 입력받는 방식을 사용하였다.

 

 

3. 키값 암호화 하기

https://www.devglan.com/online-tools/jasypt-online-encryption-decryption

- 암호화하려는 키를 입력한다

- Two Way 방식을 선택

- 패스워드를 임의로 입력한다(패스워드 기억해야함) / 패스워드는 복호화시 필요하다.

 

4. 암호화된 키로 yml 설정하기

cloud:
  aws:
    region:
      static: ap-northeast-2
    s3:
      credentials:
        access-key: ENC(xFO5USJEzJjHL8RB+a7IREpyQOoHp4HZhL2OFzzKIBs=)
        secret-key: ENC(PtaZU3cqX2thf4/AeCsoMF+XCJRo3WR8q3U1iGexhAqLXaFIQ5JKn8CKkO3uRyKipF9cb/Qy4W8=)
    stack:
      auto: false
     
      
#jasypt: #패스워드 암호화/복호화 키
#  encryptor:
#    password: 설정한 패스워드

나는 AWS의 S3키를 암호화 하였다.

 

암호화된 키를 넣어줄때는  ENC(암호화된 키) 형식으로 넣어줘야 한다.

 

맨 아랫줄 패스워드에 설정한 패스워드를 넣어줘도 동작하지만 보안에 취약함으로 따로 설정하여 관리한다.

 

 

5. 패스워드 관리하기

- 직접 실행할 때 java -jar 명령어 뒤에 붙여주는 방법

--jasypt.encryptor.password=패스워드

 

- intellij 환경변수를 설정하는 방법

 

실행버튼 옆 점세개 클릭 -> 편집 -> 옵션수정 -> 환경변수 클릭 -> 환경변수 입력 후 적용 및 확인

 

 

 

- Github Actions 환경변수로 관리하는 방법

https://kjsu1994.tistory.com/42

 

결론적으로 intellij에서 새로운 환경에 대한 SDK가 저장된 경로를 읽어오지 못해서 발생하는 에러이다.

 

다음 순서에 따라 해결하면 된다

 

 

1. 실행을 하려고 버튼을 누르면 한쪽구석에 다음과 같은 메세지가 뜬다.

 

-> 구성 클릭

 

2. 클릭하면 다음과 같은 창이 뜨는데 우리가 원하는곳은 모듈이 아니다.

 

플랫폼 설정 -> SDK 클릭

 

3. 클릭하면 다음과 같은 창이 뜬다. 위에있는 +, - 버튼이 있다.

 

-> 등록된 sdk를 클릭하고 - 버튼 클릭 -> 설정되어있는 sdk버전을 모두 지워준다.

 

-> 그후 적용 및 확인 클릭

 

4. 다음과 같은 메세지가 뜬다. 

 

-> SDK설정을 누르고 SDK가 설치되어있는 폴더를 선택해주면 해결된다.

'Study > 프로젝트 일지' 카테고리의 다른 글

pre_02.22  (0) 2023.02.22
pre_02.21  (0) 2023.02.21
pre_02.20  (0) 2023.02.21
pre_02.17  (0) 2023.02.18
pre_02.16  (0) 2023.02.17

AWS RDS(mysql)를 기존 컴퓨터 외에 개인 노트북에서 작업하기 위해 연결하려는데 연결이 되지 않아서 해결하는 과정을 공유한다.

 

AWS의 서비스들은 VPC 보안그룹에서 인바운드 규칙에 의해서 접속을 허용할 IP 및 포트번호 설정들을 추가해야 연결할 수 있다.

 

1. 먼저 AWS - RDS에서 연결할 데이터베이스를 선택한다.

연결 & 보안에서 VPC 보안그룹을 선택한다.

 

 

2. 보안그룹 목록에서 본인의 데이터베이스에 해당하는 보안그룹을 선택한다.

 

3. 선택된 보안그룹에서 아래의 인바운드 규칙을 클릭 ->

인바운드 규칙 편집을 선택한다.

 

4. 인바운드 규칙편집창에서 규칙추가 클릭  -> 

본인의 아이피주소를 추가하기 위해 설정을 다음과같이 입력한다.

 

유형 : 본인이 선택한 데이터베이스선택(나는 MYSQL) ,

프로토콜 : TCP,

포트번호 : 3306,

소스 : 내IP선택

 

이후 규칙저장!

 

이제 내 IP가 보안규칙에 허가되어 연결할 수 있다. 

'Study > Git' 카테고리의 다른 글

Git - Fork 한 Repository 최신으로 동기화 하는 방법  (0) 2023.03.24
커밋 되돌리고 서버에 반영하기  (0) 2023.03.15
Git 기초  (0) 2022.11.03

git Bash 또는 EC2 등의 환경에서 진행한다.

 

ssh 키 페어 생성하기

ssh-keygen

[명령어] ssh 키를 생성

ssh-keygen 명령어는 경로 ~/.ssh./ 에 두 파일 id_rsa 와 id_rsa.pub 를 생성한다. 이 두 파일은 ssh 키 페어라고 하며, 이 중 id_rsa.pub는 누구에게나 공개해도 되는 공개키(Public Key) 라고 한다.. 그리고 id_rsa는 공개되면 안 되고 나만 보관하고 있어야 하는 키라고 하여 개인키(Private Key) 또는 비밀키(Secret Key) 라고 한다.

ssh 키 페어를 생성하였으므로, 생성된 키 페어 중 공개키를 복사하여 gitub에 등록한다.

공개키(Public Key) 복사

다음의 명령어를 프롬프트에 입력하여, 공개키를 복사

cat ~/.ssh/id_rsa.pub

[명령어] ssh 키를 출력

화면에 출력된 키를 마우스로 드래그한 다음 복사한다.

 

Github에 공개키 등록

브라우저에서 Github로 이동하여 로그인하고 우측 상단의 프로필 이미지를 클릭하고, Settings 에 진입한다.

왼쪽의 내비게이션에서 SSH and GPG keys 를 선택

나타난 화면에서 SSH Keys 옆의 초록색 버튼 New SSH Key 를 클릭

 

등록한 SSH 공개키를 구분할 수 있도록 사용자 임의로 Title을 작성합니다. 그리고 Key에는 복사해둔 공개키를 붙여 넣고, Add SSH Key 버튼을 클릭

Confirm access에서 Github 로그인에 필요한 비밀번호를 입력해 SSH key 등록을 승인하고

SSH 공개키가 정상적으로 등록되었는지 확인하려면, 다음의 단계를 따라 레포지토리를 clone한다.

scp 를 사용한 방법이 있지만 어찌된 이유인지 Permission denied (publickey) 에러가 발생하여 연결하지 못했고 툴을 사용하여 편하게 옮기는 방법을 공유한다.

 

1. 우선 파일질라 설치를 위해 아래 링크로 접속한다(내가 받은 버전 첨부)

FileZilla_3.63.2.1_win64_sponsored2-setup.exe
12.01MB

.

https://filezilla-project.org/

 

클라이언트용으로 설치한다.

 

2. 왼쪽 상단의 버튼 클릭

 

 

3. 연결할 EC2 서버에 대한 정보들을 적는다

1. 새사이트에서 원하는 이름을 설정한다.

 

2. SFTP를 선택한다 ssh형식으로 연결된다.

 

3.

- 나는 EC2 탄력적 ip를 사용하여 연결하였으며 public 주소를 연결하여도 무방하다.

- 포트번호는 22(ssh)를 적는다.

 

4.

- 로그온 유형 :  키파일을 선택

- 사용자 : EC2 로그인시 사용자 이름 입력, 나는 ubuntu였다.

- 키파일 : EC2 접속을 위한 키페어를 등록한다.

 

5. 편하게 이동할 파일들을 업로드 또는 다운로드 하면 된다.

- 업로드 : 로컬 -> 서버

- 다운로드 : 서버 -> 로컬 

1. 빌드하여 배포파일 만들기

 

*로컬에서 빌드하여 배포파일 만들기

  • Windows 터미널의 경우,
1
PS D:\codestates\project\section3-week4-build> .\gradlew bootJar

 

  • Git Bash의 경우
1
2
MINGW64 /d/codestates/project/kdt/for-ese/section3-week4-build (main)
$ ./gradlew build

 

빌드가 정상적으로 종료되면 IntelliJ에서 빌드를 진행 할 때와 마찬가지로 build/libs 디렉토리에 Jar 파일 하나가 생성된다.

 

생성된 파일을 파일질라 or scp명령어를 통해 ec2로 옮긴다.

 

 

* EC2에서 빌드하여 배포파일 만들기

1. java 설치

$ sudo apt update

어느 정도 시간이 지나고 업데이트 과정이 끝나면 java를 설치

$ sudo apt install openjdk-11-jre-headless

아래와 같은 확인창이 나올경우 "Y"를 입력

Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libasound2 libasound2-data libgraphite2-3 libharfbuzz0b
Suggested packages:
  libasound2-plugins alsa-utils libnss-mdns fonts-dejavu-extra fonts-ipafont-gothic fonts-ipafont-mincho fonts-wqy-microhei
  | fonts-wqy-zenhei fonts-indic
The following NEW packages will be installed:
  libasound2 libasound2-data libgraphite2-3 libharfbuzz0b openjdk-11-jre-headless
0 upgraded, 5 newly installed, 0 to remove and 70 not upgraded.
Need to get 37.9 MB of archives.
After this operation, 173 MB of additional disk space will be used.
Do you want to continue? [Y/n]

설치 과정이 마무리되면, java -version 명령어를 입력하여 java 라이브러리가 설치가 완료되었는지 확인

 

2. 깃에서 배포할 서버 클론받기

먼저 EC2상에서 SSH키를 깃허브 레파지토리에 등록해야한다.

등록방법은 이곳에서 확인할 수 있다.

 

SSH 등록을 마쳤다면 인스턴스 시작시 기본 경로가 아닌 홈 경로(~)로 이동하여 clone

ssm-user@ip-172-31-41-164:/var/snap/amazon-ssm-agent/1234 $ cd ~
ssm-user@ip-172-31-41-164:~$ git clone git@github.com.git
Cloning into 'git'...
Username for 'https://jinsu.com': jinsu
Password for 'https://jinsu@github.com:
...

클론 진행 여부에 대한 질문이 나올 경우 yes를 입력해 실습 코드를 클론하고 

ls명령어를 통해 클론받은 디렉터리명을 확인

cd명령어를 통해 해당 디렉터리로 이동

cd [클론받은 디렉터리명]

이후 빌드작업을 진행합니다.

./gradlew build

정상적으로 빌드가 완료되었으면 터미널에 ls명령어를 입력하면, build폴더를 확인할 수 있습니다.

 

 

2. EC2에서 서버 실행하기

로컬이나 EC2환경 둘중의 한가지 방식을 선택하여 jar형식의 배포파일을 EC2에 생성했다면

 

EC2에서 서버 실행 :  java -jar [파일명.jar] 

 

이방식을 사용하면 ctrl + c를 사용하거나 쉘을 닫으면 서버도 종료된다.

 

* 그렇기 때문에 사용할 방법은 백그라운드에서 서버 돌리기

 

1. nohup java -jar [파일명].jar &   

을 입력하면 백그라운드 상황에서 서버가 실행된다.

 

& 은 백그라운드로 돌아가게 해주고

nohup은 서버 구동 시 기본적으로 쌓이는 로그들을 파일로 만들어준다.

 

2. cat nohup.out 으로 쌓인 로그들을 볼 수 있다.

 

3. 종료를 위해서는 PID가 필요하다.

grep으로 걸러서 쓰자

ps -ef | grep '[원하는 단어]'

예를 들면 ps -ef | grep 'java' 

 

4. PID를 찾았으면

kill [PID 번호]

== kill -15 [PID 번호]

kill -9 는 강제 종료이니 -15로 일반 종료임을 알려주자. 

물론 kill이랑 똑같다. 

 

이렇게 하면 프로세스가 죽는다.

'Study > 기타' 카테고리의 다른 글

AWS RDS - RDS 프리티어 생성하기  (0) 2023.03.23
AWS 로컬 < -- > EC2 파일 복사하기  (0) 2023.03.18
AWS- IAM 사용자 추가 후 엑세스키 생성  (0) 2023.03.14
AWS EC2 - 배포 자동화를 위한 사용설명  (0) 2023.03.02
HTTP  (1) 2022.11.30

java.sql.SQLIntegrityConstraintViolationException: Column 'user_id' cannot be null 오류를 해결

 

원인은 필수적으로 입력되어야 하는 컬럼에 null값이 들어갔기 때문이다

 

 

아래 코드에서 optional = false이기 null일 수 없어서 에러가 발생하였다.

@Setter @ManyToOne(optional = false) @JoinColumn(name = "userId")
private UserAccount userAccount; //유저 정보(id) 매핑

 

정확하게 매핑이 될 때까지는 optional=true를 사용해 null값을 허용하도록 하자

@Setter @ManyToOne(optional = true) @JoinColumn(name = "userId") //매핑이 완료되면 필수옵션(false)으로 바꿔줘야함
private UserAccount userAccount; //유저 정보(id) 매핑

 

순환참조에 관련된 에러이다.

 

양쪽에 @JsonIgnore을 사용하면 해결할 수 있다.

@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "board_id")
private Board board;
@JsonIgnore // 순환참조 방지
@OneToMany(mappedBy = "board",cascade = CascadeType.ALL, orphanRemoval = true) // 게시판과 생명주기 동일하게 관리
@ToString.Exclude // ToString
private List<UploadFile> uploadFiles = new ArrayList<>();

이미지 파일업로드를 기존 게시글과 함께 포스트 하기위해 @ModelAttribute 애너테이션을 사용하려는데 NullPointException : null이 떠서 해결과정을 공유한다.

 

@ModelAttribute 는 @RequestBody 와 다르게 form-data형식으로 전달하기 때문에 Json타입으로 Dto에 넘어가지 않고 역직렬화 과정을 통해 매핑되어 전달이 된다. 

 

결론적으로 매핑을 하기 위해서는 결론 Dto클래스에 @NoargsContructor(혹은 생성자를 만들기) / @Setter가 필요하다 

 

나는 다음과 같이 설정해 사용했다.

 

* Controller

@PostMapping
public ResponseEntity<?> upload(@ModelAttribute MultipartFile[] files,
                                @ModelAttribute BoardDto.Post boardPostDto) throws Exception {
    Board board = boardMapper.boardPostToBoard(boardPostDto);
    board.setMember(memberService.findVerifiedMember(boardPostDto.getMemberId()));
    Board boardCreate = boardService.createBoard(board);

    List<UploadFile> uploadFiles = s3Service.uploadFiles(files, boardCreate); // aws s3업로드

    BoardDto.TotalPageResponse response = boardMapper.boardToBoardTotalPageResponse(boardCreate, uploadFiles);

    return new ResponseEntity<>(new SingleResponseDto<>(response), HttpStatus.CREATED);
}

 

@Dto

@Getter @Setter //@ModelAttribute 사용하기위함
@NoArgsConstructor //@ModelAttribute 사용하기위함
@ToString
public static class Post {
    @Positive
    @NotNull
    private Long memberId;
    @NotBlank(message = "제목을 작성해주세요")
    @Size(max = 100, message = "100자 이내로 작성해 주세요.")
    private String title;
    @NotBlank(message = "내용은 공백이 아니어야 합니다.")
    private String contents;

    public Post(Long memberId, String title, String contents) {
        this.memberId = memberId;
        this.title = title;
        this.contents = contents;
    }
}

 

 

Postman을 통해 다음과 같이 테스트하면 결과가 잘 전달되는것을 확인할 수 있었다.

 

참고 https://blog.karsei.pe.kr/59

+ Recent posts