728x90
반응형

얼마 전 면접에서 기술질문을 받았는데 큰 틀만 알고 있어서

제대로 설명을 하지 못한 것에 큰 아쉬움이 있어 살짝 기록해 본다. 

진정한 자바 메모리에 대해 깊게 공부한 내용은 아니지만

일단 기본 내용부터 점점 심화하는 것도 이해를 높이는 좋은 방법이지 않을까 생각한다.

(기술 질문에 약한 편이라 계속 공부중..ㅠ)


자바에 대해 살짝 맛보기 내용부터!

 

JVM (Java Virtual Muchine)

- 자바 가상 머신

- 자바의 바이트 코드를 해석하고 실행하는 역할

 

자바 프로그램의 실행 구조

프로그램

JVM

운영체제

하드웨어

 

자바는 JVM에 의해 실행되므로 어떤 운영체제에서도 동일한 결과를 갖는 것이 큰 장점이다.

단, 한 단계 더 거쳐서 실행되기 때문에 실행 속도면에서 뒤처질 수 있다.

 

런타임 데이터 영역 (Runtime Data Area)

1. Static Area (Method Area)

2. Heap Area

3. Stack Area

4. PC Register

5. Native Method Stack

 

이 글에서는 2, 3번 힙과 스택에 대해서만 정리한다.


Stack Heap
원시타입의 데이터가 값과 저장 Object 타입의 데이터가 저장
Heap 영역에 생성된 Object 타입의 데이터의 참조값이 저장 애플리케이션의 모든 메모리 중 Stack을 제외한 부분
함수가 호출될 때 사용하는 메모리
기능 수행이 끝나면 자동으로 반환되는 메모리
자동으로 관리되지 않는 메모리 영역 (가비지 컬렉터)

 

 

Stack 영역

public class Stack {
	public static void main(String[] args) {
    	int num1 = 20;
        int num2 = 30;
        int sum = 0;
        
        sum = addNum(num1, num2);
        System.out.println(sum);
    }
    
    public static int addNum(int n1, int n2) {
    	int result = n1 + n2;
        return result;
    }
}

 

 

Heap 영역

public class Heap {
	public static void main(String[] args) {
    	int age = 19;
        String name = "mimi";
    }
}

 

Heap 영역에서 GC (Garbage Collection)

- 메모리 누수를 막기 위한 가비지 컬렉션

public class Heap {
	public static void main(String[] args) {
    	String url = "http://";
        url += "mimi.github.io/";
    }
}

url += 부분 코드를 실행하면 기존 문자열에 덧붙이는 것이 아닌

새로운 String 객체를 생성하고 참조하게 되어

기존의 문자열"https://"는 unreachable object가 되어

가비지 컬렉터unreachable object를 제거한다. 

 

위 코드를 실행하면 힙 영역에는 결과적으로 2만 남게 된다.

 

*unreachable object : 스택에 도달할 수 없는 힙 영역의 객체

728x90
반응형

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

[IT 용어] API (Application Programming Interface)  (0) 2023.10.14
[JAVA] 람다식 Lambda  (0) 2023.10.05
[JSP] JSP 강의평가 웹 사이트 개발하기 완료  (0) 2023.10.02
[GitHub] 깃, 깃허브  (0) 2023.09.28
[Kotlin] 코틀린 맛보기  (0) 2023.09.22
728x90
반응형

생각보다 적은 시간 동안 삽질 끝에 스프링부트 프로젝트 배포에 성공했다.

수동 배포이다 보니 상시 실행 중 상태가 아니라

수정사항이 있을 경우라던지 한 번 서버를 가동할 때 손이 많이 가는 만큼

빠른 시일 내에 자동 배포어떤 방식으로 할지 고민해 보고 적용시켜 보아야겠다.

 

기존에 EC2, RDS는 생성해 두었던 상태고

RDS는 프로젝트에 미리 적용시켜 사용 중이었기 때문에

본론부터 바로! 서버 접속부터~어떤 과정으로 배포하였는지 기록해 본다.


먼저, 나는 node.js 프로젝트에서 사용한 3000번 포트만 열어둔 상태라

EC2 / 보안 그룹 / 인바운드 규칙에 8080 포트를 추가해 주었다. (본인 프로젝트 포트에 맞게 설정)

 

 

1. 서버에 접속 후 자바 설치

sudo apt-get install openjdk-11-jdk

// 설치된 자바 버전 확인
java --version

 

 

2. 깃허브 Repository에서 git clone / git pull

본인 Repository 들어가서 코드 클릭 후 HTTPS 링크 복사 (링크 우측에 창 아이콘 클릭 시 copy)

 

 

콘솔에서 아래 코드를 입력하여 프로젝트를 git clone, pull을 진행한다.

git clone https://github.com/jangmimi/LectureEvaluation-SpringBoot.git
git pull

 

 

3. 프로젝트 디렉터리로 이동

- ls로 현재 디렉토리의 폴더 및 파일 확인(보기)

- cd로 디렉토리 이동

 

 

4. Gradlew에 권한 부여 후 빌드

sudo chmod 777 ./gradlew
./gradlew build

여기서 테스트 코드 관련 에러가 발생헀는데

아래 에러 해결 부분에서 테스트 코드 제외 빌드에 관해 설명하였다.

 

 

5. 빌드 후 생성된 jar 파일을 java로 실행

빌드를 성공적으로 마친다면 build/libs 폴더에. jar 파일이 생성되었을 것이다.

나는 LectureEvaluationSpring-0.0.1-SNAPSHOT.jar 파일과 plane이 붙은 2개의 jar 파일이 생성되었다.

(plane jar 파일 생성에 대해서는 좀 더 알아보고, 다루는 글을 올려야겠다.)

 

 

./build/libs 폴더까지 진입해서 아래 코드와 같이 실행해도 되고

 

java -jar LectureEvaluationSpring-0.0.1-SNAPSHOT.jar

 

프로젝트 루트 폴더에서 경로를 같이 입력하고 실행해도 된다.

// jar 파일에 plane이 붙지 않은 파일로 선택
java -jar ./build/libs/생성된jar파일.jar

// 본인 프로젝트 예시
java -jar ./build/libs/LectureEvaluationSpring-0.0.1-SNAPSHOT.jar

 

이렇게 실행하면 매우 반가운 모습을 볼 수 있다.

 

URL창에 서버주소:8080(포트번호)를 입력하면 프로젝트 사이트가 정상적으로 가동된다.

 

아 물론, 위 내용은 정말 단순하게 기본적인 내용으로 작성된 글이다.

나는 프로젝트의 yml 파일에 중요한 정보들을  암호화했었고,

VM Options에 암호 키를 적용해서 프로젝트를 빌드해 왔어서

서버에 올린 프로젝트를 암호화 관련 설정 없이 빌드하면서

당연하게도 몇몇 에러를 마주하게 되었다.

아래에서 마주한 에러 내용들을 다뤄보겠다.


일단, 모든 코드에서 오타를 주의하도록 하자.

사소한 실수로 삽질하는 시간낭비는 최소화하는 것이 좋다. (경험에서 몸소 깨달은 바ㅎ)

 

1. 처음에 마주했던 에러 아닌 에러는 빌드 중 76% 정도에서 멈춤(무한대기) 현상이었는데

EC2 서버를 재부팅하고 다시 우분투 접속 후 빌드해 보니 해당 문제는 해결되었다.

 

2. 또다시 마주한 에러는 테스트코드에서의 빌드 실패였는데,

테스트 코드 빌드를 제외하고 실제 프로젝트 내용만 빌드하도록 설정하였다.

(테스트 코드가 완성되지 않은 것도 있고

본 스프링부트 프로젝트는 일단 배포하는 방식을 익혀보자는 목표로

테스트코드 빌드를 제외하게 되었다.)

 

*테스트코드 제외 빌드*

./gradlew build -x test

 

*여기서 나는 VM Options 설정 때문에 실제로 빌드 시에는 위 코드에 추가로 암호화 키 관련 코드를 넣어주었다.

(자바 실행할 때도 동일하게 암호화 키 관련 코드 삽입)

java -jar -Djasypt.encryptor.키변수명=키값 생성된jar파일명.jar

// 빌드에서도 동일하게 '-Djasypt.encryptor.키변수명=키값' 이부분을 추가

서버에서 실행 화면

 

 

이 내용은 모두에게 해결책이 될 수는 없을 것이다.

나와 유사하게 yml 혹은 properties 파일의 중요 정보를 jasypt로 암호화하고

VM Options에 설정하고 빌드한 경우에만 유사한 에러를 마주하고

이와 같은 방식으로 해결이 될 수도 있을 것이며

다양하게 검색을 해보고 정확하게 원인을 파악한다면 생각보다 간단하게 해결할 수 있을 것이다.

물론 오랜 시간이 걸릴 수도 있지만...(예전에 STS 세팅만 반나절 해본 경험 有 ^^)


+

파이널 프로젝트에서 한 팀원이 채팅 관련 배포를 하게 되면서 마주했던 에러가 있었는데

컨트롤러의 매핑에서 경로 부분 return 값의 '/' 문제로 페이지 호출이 되지 았던 것이었고

이 부분은 이미 숙지한 상태라서 연관 에러는 전혀 발생하지 않았다. (뿌듯)

원인은 찾아보니 리눅스에서 파일 위치를 찾아 못하는 상황이 발생해서 그렇다고 한다.

(Thymeleaf 템플릿 엔진을 사용할 경우 발생한다고 하는 것 같다.)

// 에러 발생 가능성 코드
@RequestMapping("/join")
public String join() {
    return "/user/join";
}
    
// 정상 작동 코드
@RequestMapping("/join")
public String join() {
    return "user/join";
}

// return에서 맨 앞 '/' 제거
// redirect의 경우는 정상적으로
// return 'redirect:/'; 로 해주면 된다.

 

728x90
반응형
728x90
반응형

날씨가 많이 쌀쌀해졌다. (추위 많이 타는 편)
역시 가을은 순식간에 지나가고 겨울이 오나 보다.


SQLD 시험 접수가 엊그제 같은데
벌써 다음 주면 진짜 시험이다.
노랑이책은 어렵다. 개념 유튜브 강의를 먼저 볼걸!

자격증 한방에 획득하길 기대 중..


앞으로의 회고는 작성법에 맞게 써보려고 한다.

다양한 회고 작성방법이 있었는데 나는 5F 회고로 작성해 보았다.

무작정 써 내려가는 것보다 절차적으로 쓰는 것
쓴 글을 다시 되돌아보기에도 좋을 듯하다.

여유가 생긴다면 하루 단위의 회고 작성을 시도해 보아야겠다.

 

TMI

얼마 전 발생한 일.

4월 정도에 집들이 선물로 받은 휴지 보관을 잘못했던 건지

새로 뜯은 휴지에서 쉰내가 났다. 예리한 나의 촉으로 벌레 발견.

쌀과 휴지가 있던 공간에도 먼지다듬이벌레가 있는 것을 발견하고

며칠 내내 개인 방역(?)을 굉장히 열심히 하는 중이다. (ing)

청소를 자주 하는 편인데도 왜 때문에 눈치를 못 챘을까? 충격..

조만간 대청소하면서 물건들을 최소화하고 수납함에 넣어야겠다.

 


5F 회고


Fact (사실)

- 어느덧 국비 학원을 수료 한 지도 2개월이 다 되어간다.

- 루틴 관리 어플로 하루 루틴을 세우고 이행 여부를 매일 체크하고 있다. (한 달 차)

- 곧 있을 SQLD 시험 개념 강의를 듣고, 필기하고, 기출문제를 풀고 있다.

- 취업하기 위해 다방면으로 노력하고 있다.

   지원서 제출 / 개인 프로젝트 / 개념 학습 및 개발 블로그 작성 / SQLD 시험 준비

- 두 번째 프로젝트를 마무리하는 단계에 있다.

   AWS RDS는 연결 완료.
   서버 배포와 코드 리팩토링,

   필요한 주석 추가 및 불필요한 주석 삭제,

   소셜로그인 기능 추가(깃허브 로그인은 구현 완료) 등

   일부분 남은 상태로 진행하고 있다. (마무리 후딱 하기)


Feeling (느낀 점)

- 개인 프로젝트를 하면서 개발을 하면 할수록 개선되어 가는 것에 대한 만족감이 컸다.

- 추상적인 개념보다는 코드를 직접 작성하는 것과 연관된 개념은 이해하기 쉬웠다.

- 루틴을 이행하고, 하루를 마무리하면서 돌이켜보는 게 굉장히 즐겁다.

- SQLD 기출문제를 보니 정확하게 '이해'를 해야 풀 수 있는 것들이 많아서 생각보다 어려웠다.

 

Finding (배운 점)

- 막연하게 기능을 구현해 내는 것보다 기능 동작 원리를 이해하는 것이 더 중요한 것을 몸소 깨달았다.

- 생각이 많을 때, 나 자신을 내려놓고 마인드 컨트롤을 하는 팁을 배웠다.

- 세분화된 루틴을 세우고 실천하면 하루를 보다 효율적으로 보낼 수 있다.

- SQLD 시험 준비를 하면서 데이터베이스에 대한 이해도가 조금 향상되었다. (join, 구체적인 이론 내용들)

 

Future Action (향후 계획)

- 리팩토링, 클린코드에 대해 관심이 많았지만 제대로 적용하는 방법은 아직 익숙하지 않으므로

  꾸준하게 학습하고 적용해 보면서 오픈소스들에 대해 찾아서 관찰해 보아야겠다.
- 진행 중인 프로젝트의 남은 기능들은 구현 완료하고, 전반적인 코드들은 더 개선할 것이다.
- 더 적극적으로 구직활동에 힘쓸 것이다. (얼른 취업하고 싶다.. 열심히 잘할 자신 있는데!)

- 코딩테스트 꾸준히 해서 알고리즘 부분 실력을 향상해야겠다.

- SQLD 시험 한 번에 합격할 것!

 

Feedback (피드백)

- 다음 회고부터 피드백 작성 예정

728x90
반응형
728x90
반응형

얼마전 새로운 언어에 대한 맛보기로 node.js 기초를 학습하고 배포까지 해보게 되었다.

이 경험을 토대로 현재 고도화 단계인 스프링부트 개인 프로젝트를 RDS 연결부터 진행해보았다.

연결 시 에러가 발생했는데 URL부분 작성 착오로 발생한 것이었고 해결하게 되었다.

 

처음에 에러 원인을 검색해보면서 다양한 원인들이 있다는 내용을 보았고

주 원인들인 퍼블릭 엑세스 설정, 보안 인바운드 규칙은 이미 알맞게 설정이 된 상태였다.

 

처음부터 여러 에러 메세지 중에서 link failure에 초점을 맞추지 못했지만

계속 시도하다보니 url문제인 것을 파악하게 되었다.

 

 

에러 내용 :

java.lang.RuntimeException: Driver cohttp://m.mysql.cj.jdbc.Driver claims to not accept jdbcUrl,...

 

 

해결 :

url 부분에서 jdbc:mysql:// 부분과 :포트 그리고 데이터베이스명 부분을 제대로 작성해주니

RDS 연결에 정상적으로 성공하여 Entity 테이블들이 생성되는 것을 확인했다.

spring:
  # Database 설정
  datasource:
    url: jdbc:mysql://엔드포인트:포트/데이터베이스명
    username: 사용자이름
    password: 비밀번호
    driver-class-name: com.mysql.cj.jdbc.Driver

 

 

프로젝트를 서버에 배포한 후에는 다시 이 url을 배포 주소로 바꿔줘야하니 잊지 않고 기억해두어야겠다.

728x90
반응형
728x90
반응형
개발에 있어서 매우 중요한 것 중 하나, 보안!

 

이전 팀 프로젝트와 개인 프로젝트에서는 아직 제대로 된 프로퍼티 암호화를 적용하지 않았어서

아이디와 비밀번호가 기재된 계정이나 DB 접속 정보와 같은 민감한 내용을

GitHub에 공백 또는 임의의 값으로 올리거나 .gitignore로 처리하는 번거로움이 있었다.

이번 개인 프로젝트에는 이 부분에 대한 개선을 위해 Jasypt를 활용한 프로퍼티 암호화를 적용해보아서 기록해 둔다.

 

Jasypt (Java Simplified Encryption)

Jasypt는 개발자가 암호화 작동 방식에 대한 깊은 지식이 없어도

최소한의 노력으로 프로젝트에 기본 암호화 기능을 추가할 수 있게 해주는 자바 라이브러리이다.

 

 

유튜브로 강의도 보고, 검색도 많이 해보았는데

대부분이 설명하는 글이라서 암호화하는 키(password)를

String = "my_key_value" 이런 식으로 프로퍼티 내부에 명시를 해두었는데

이럴 경우에 해당 값으로 누구나 디코딩이 가능하게 되어서 결국 암호화 한 의미가 없다.

더 나은 방법으로, 인텔리제이에서 JVM Option을 설정할 수 있어서

VM Option으로 값을 전달하는 방식으로 적용했다.


먼저 의존성을 추가해 준다. (gradle 기준)

implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.4'	// jasypt 의존성 추가 (프로퍼티 암호화)

Jasypt 설정 및 Bean 등록

package com.springproject.config;

import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JasyptConfig {

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

    @Bean(name = "jasyptStringEncryptor")
    public StringEncryptor stringEncryptor() {
//        String password = "비밀번호";    // VM Option으로 전달하는 방식이 더 안전해서 변경 적용 완료
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();

        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword(password);   // 암호화할 때 사용하는 키
        config.setAlgorithm("PBEWithMD5AndDES");    // 암호화 알고리즘
        config.setKeyObtentionIterations("1000");   // 반복할 해싱 횟수
        config.setPoolSize("1");    // 인스턴스 pool
        config.setProviderName("SunJCE");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");    // salt 생성 클래스
        config.setStringOutputType("base64");   // 인코딩 방식

        encryptor.setConfig(config);
        return encryptor;
    }
}

간단한 테스트에서는 위 내용에서 stringEncryptor() 내부에

주석처리된 password="비밀번호" 부분에 원하는 값을 넣어 key를 설정하면 되지만,

실제로 프로젝트에 적용하고자 하면 key 또한 별도로 감추어주는 것이 좋다.


프로퍼티 암호화

프로퍼티 암호화를 위해 암·복호화 사이트에 방문해서

① 암호화할 값을 입력

② Two Way Encryption(With Secret Text) 선택

③ Key값을 입력

마지막으로 Encrypt 버튼을 클릭하면 암호화 값을 확인할 수 있다.

 

아래 이미지는 암호화 사이트 모습으로

우측에 암호화된 값과 Key(password로 언급했던) 값을 넣어주면

암호화 전 원래의 값을 확인할 수 있다. (복호화)

암호화 사이트 모습(좌-암호화, 우-복호화)

Key 값은 잊어버리지 않도록 별도로 작성 후 저장해 두는 것이 좋다.


application.yml에 반영

실제로 프로젝트에 적용하기 위해 application.yml 파일 내 DB 접속정보 값을 ENC(암호화 값)로 수정한다. 

spring:
  datasource:
    url: ENC(zQVsiPgBkSc0hJ2pb/Gjf6D9xTou+FFqEE6Eb6hvWy9fJ3jO6LisA2hjK9LB52cL7LbZCs+EJqk=)
    username: ENC(yc/9dYuj6thDEZmI5/N5iA==)
    password: ENC(8HxW/0iGqW6VJtzhVoX3qw==)
    driver-class-name: com.mysql.cj.jdbc.Driver

VM Options 추가

-Djasypt.encryptor.password=암호화에 사용할 키 값


테스트 코드로 암호화 결과 확인해 보기

테스트 코드 실행 시에도 위 내용처럼 VM Options을 통해 암호화 Key값을 전달해 주어도 된다.

아래는 작성한 테스트 코드이다.

package com.springproject.config;

import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class JasyptConfigTest {

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

    @Test
    void encryptTest() {
        String url = "enc_test_url";
        String id = "enc_test_id";
        String password = "enc_test_pw";

        System.out.println("db_url : " + jasyptEncoding(url));
        System.out.println("db_id : " + jasyptEncoding(id));
        System.out.println("db_password : " + jasyptEncoding(password));
    }

    public String jasyptEncoding(String value) {
        StandardPBEStringEncryptor pbeEnc = new StandardPBEStringEncryptor();
        pbeEnc.setAlgorithm("PBEWithMD5AndDES");
        pbeEnc.setPassword(password);
        return pbeEnc.encrypt(value);
    }
}

위 테스트 코드를 실행하여 암호화 된 값을 결과로 확인한다.

테스트 실행 결과

실행할 때 마다 결과 값은 항상 다르다.

Why?

Jasypt보안을 강화하기 위해 Salt 값을 사용한다,

Salt는 암호화된 데이터의 보안성을 높이기 위해 사용되며, 매번 실행할 때마다 랜덤한 Salt 값을 생성하여 데이터를 암호화한다.

이렇게 하면 동일한 데이터라도 매번 다른 암호화 결과가 생성된다.

(동일한 데이터에 대해 매번 같은 결과라면 암호화 의미가 없음!!)

 

 

참고 사이트
 

[Spring] Jasypt를 이용한 암호화

Jasypt는 자바에서 암호화를 쉽게 할 수 있도록 도와주는 라이브러리이다. When? Spring에서 datasource를 연동할 때, application.yml 파일에 다음과 같이 설정할 수 있다. spring: datasource: url: jdbc:mysql://... user

gksdudrb922.tistory.com

 

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

 

Jasypt: Java simplified encryption - Jasypt: Java simplified encryption - Main

Jasypt 1.9.3 RELEASED! (May 25th, 2019) [DOWNLOAD and ChangeLogs] [WHAT'S NEW IN JASYPT 1.9] Java Simplified Encryption Jasypt is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and wi

www.jasypt.org

암호화/복호화 사이트 (Free)
 

Programming Blog Article Feeds as per your Interest | DevGlan

Best programming article feeds as per your Interest on different technologies. Subscribe to any technology and explore the best articles from around the web.

www.devglan.com

 

728x90
반응형

+ Recent posts