웹 페이지를 꾸며야하는데, 저처럼 디자인적 감각이 거의 없는 경우에 선택하는 방법은

부트스트랩 테마를 적용하는 것 입니다.


* 오늘 정리할 내용은 아래와 같습니다.

1. 부트스트랩 적용하기

2. 타일즈 적용하기



부트스트랩을 이용하면 디자인적인 기본 기능들이 이미 구현되어 있기 때문에 가져다 쓰기만 하면되서

굉장히 편리합니다.

물론 유료로 사용하는것이 기능으로나 디자인으로나 훨-씬 좋겠지만,

저는 무료로 제공하는 아래 디자인을 다운받아 사용하려고 합니다.

(다운로드 링크 -> https://startbootstrap.com/template-overviews/sb-admin/)

그림1) 예제에 사용 할 부트스트랩 이미지


그럼 다운로드 한 부트스트랩을 프로젝트에 적용해보도록 하겠습니다.


1. 부트스트랩 적용하기


1.1 압축풀기

다운받은 파일을 압출을 풀면 다음과 같이 정리 되어 있을 것 입니다.

html을 코드를 보면 어떤식으로 사용하는지 확인할 수 있습니다!


그림2) 부트스트랩 내용물


1.2 resources 폴더에 복사하기

그림2) 사진에 있는 폴더 css/js/scss/vendor 폴더를 작업중인 프로젝트 내의 resources에 복사합니다.

그림3) resources 폴더


1.3 servlet-context.xml 수정하기

이제 부트스트랩을 사용하려면 코드를 작성할때 <link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet"> 과 같은 방식으로 작성하게 됩니다.

그래서 이 경로를 Spring에서 원할하게 찾을 수 있도록 servlet-context.xml 을 수정해 주어야 합니다.

resources mapping 부분을 아래와 같이 변경 합니다.

<resources mapping="/**" location="/resources/" />

그림4) Servlet.xml 수정


(xml 파일은 수정 후 서버를 재시작해야 적용됩니다.)


1.4 적용 확인하기

이제 정상적으로 동작하는지 확인하기 위해 그림2) 에있던 폴더에서 index.html에 있는 코드를 home.jsp에 붙여넣습니다.

이후 서버 시작해서 확인하기

그림5) 부트스트랩 적용 확인


1.5 정장 작동을 확인했으면 Git에 commit하기!

git의 순서는 언제다 add-> commit -> push 입니다.

add to index 이후 commit message 작성 후 commit!


그림 6) 부트스트랩 적용 후 commit



2. Tiles 적용하기

home.jsp에 코드를 복사하게되면 코드의 양이 상당히 많습니다.

왜냐하면 그 코드에는 위쪽 메뉴바, 왼쪽 메뉴바, 중앙 내용, 하단 내용이 모두 들어가 있기 때문입니다.


새로운 페이지마다 그 긴 코드를 모두 작성하긴 힘들 것 입니다.

그래서 타일즈를 이용하여 고정적으로 사용되는 부분은 한번만 작성하여 계속 가지고 다니게 만드려고 합니다!


타일즈 적용에 필요한 것은 아래와 같습니다.


2.1 pom.xml에 tiles dependency 추가


<!-- tiles -->

<dependency>

<groupId>org.apache.tiles</groupId>

<artifactId>tiles-core</artifactId>

<version>2.2.2</version>

</dependency>

<dependency>

<groupId>org.apache.tiles</groupId>

<artifactId>tiles-api</artifactId>

<version>2.2.2</version>

</dependency>

<dependency>

<groupId>org.apache.tiles</groupId>

<artifactId>tiles-extras</artifactId>

<version>2.2.2</version>

</dependency>

<dependency>

<groupId>org.apache.tiles</groupId>

<artifactId>tiles-servlet</artifactId>

<version>2.2.2</version>

</dependency>

<dependency>

<groupId>org.apache.tiles</groupId>

<artifactId>tiles-jsp</artifactId>

<version>2.2.2</version>

</dependency>



2.2 WEB-INF/tiles 폴더 생성

- 내용 구성은 layout, tile , tiles.xml 파일







2.2.1  layout에 header / content / footer로 상단 / 중단 / 하단부를 정의해줍니다.

아래 형식이 기본 작성 방법입니다.


하지만 저는 제가 원하는 방식으로 화면에 출력하고 싶기 때문에 아래와 같이 수정했습니다.







2.2.2 tile 폴더 내에는 상단 중단 하단부에 고정으로 보여 주고 싶은 내용을 입력 합니다.

(jsp파일 작성하듯이 똑같이 작성하면 됩니다. 아래 사진은 header.jsp 내용)




2.2.3 마지막으로 tiles.xml 작성

- layout.jsp 위치 header.jsp footer.jsp 파일 위치, content 부분에 적용될 jsp 설정 부분을 작성하여 tiles.xml을 만듭니다.



- tiles 페이지 설정 / 비설정 (2019.06.25 추가)

페이지를 설정 하던 중 로그인 페이지에는 타일즈를 제외 해야 할 일이 생겼습니다.

그래서 내용 추가 합니다.


타일즈 적용 부를 위에처럼 하나씩 다 설정해주어도 괜찮지만 페이지가 많아질수록 관리하기 귀찮겠죠?

그래서 아래와 같이 설정을 변경합니다.

--------------------------------------------------------------------------------------------

<!-- 타일즈 제외 선언부를 제외한 나머지는 모두 타일즈로 적용 됨 -->

<definition name="*/*" extends ="layout">

<put-attribute name="content" value ="/WEB-INF/views/{1}/{2}.jsp"/>

</definition>

--------------------------------------------------------------------------------------------

"*/*" -> 모든 페이지를 layout으로 적용하겠다는 말입니다.


그리고 제외 할 페이지를 설정해줍니다. 

페이지 선언 이전에, 비어있는 layout인 emtpy.jsp를 추가해줍니다. (loyout 폴더 아래)





empty.jsp의 내용은 아래와 같이 타일즈 layout 설정을 다 빼버림 되겠죠!





그리고 tiles.xml에 제외할 페이지들을 선언해줍니다.

아래 사진은 제외할 페이지가 들어있는 폴더 views/logInfo 입니다.


--------------------------------------------------------------------------------------------------------

<!-- 타일즈 제외 선언부 -->

<definition name="logInfo/login" extends ="empty">

<put-attribute name="content" value ="/WEB-INF/views/logInfo/login.jsp"/>

</definition>

<definition name="logInfo/memberJoin" extends ="empty">

<put-attribute name="content" value ="/WEB-INF/views/logInfo/memberJoin.jsp"/>

</definition>


--------------------------------------------------------------------------------------------------------


tiles.xml 전체 소스

-----------------------------------------------------------------------------------------------------------------------------

<?xml version="1.0" encoding="UTF-8"?>

 <!DOCTYPE tiles-definitions PUBLIC

      "-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"

      "http://tiles.apache.org/dtds/tiles-config_2_1.dtd">



<tiles-definitions>

<!-- tiles layout 적용 정의부 -->

<definition name ="layout" template ="/WEB-INF/tiles/layout/layout.jsp">

<put-attribute name="header" value ="/WEB-INF/tiles/tile/header.jsp"/>

<put-attribute name="sidebar" value ="/WEB-INF/tiles/tile/sidebar.jsp"/>

<put-attribute name="content" value =""/>

<put-attribute name="footer" value ="/WEB-INF/tiles/tile/footer.jsp"/>

<put-attribute name="footer-menu" value ="/WEB-INF/tiles/tile/footer-menu.jsp"/>

</definition>

<!-- tiles 적용 제외 부분 정의부 -->

<definition name="empty" template ="/WEB-INF/tiles/layout/empty.jsp">

<put-attribute name="content" value =""/>

</definition>

<!-- 타일즈 제외 선언부를 제외한 나머지는 모두 타일즈로 적용 됨 -->

<definition name="*/*" extends ="layout">

<put-attribute name="content" value ="/WEB-INF/views/{1}/{2}.jsp"/>

</definition>

<!-- 타일즈 제외 선언부 -->

<definition name="logInfo/login" extends ="empty">

<put-attribute name="content" value ="/WEB-INF/views/logInfo/login.jsp"/>

</definition>

<definition name="logInfo/memberJoin" extends ="empty">

<put-attribute name="content" value ="/WEB-INF/views/logInfo/memberJoin.jsp"/>

</definition>

</tiles-definitions>

-----------------------------------------------------------------------------------------------------------------------------


이렇게 tiles 변경 후 적용을 변경하면 로그인 페이지를 제외한 나머지 페이지들만 타일즈가 적용됩니다!








2.3 servlet-context.xml에 tiles 정보 추가

이제 생성한 폴더를 서블릿에서 인식해주기 위해서 servlet-context.xml 파일에 tiles 정보와 폴더의 경로를 아래와 같이 내용을 추가해줍니다.


<!-- 부트스트랩 링크를 위해 resources 경로를 루트부터 찾도록 변경해줍니다 -->  

<!-- <resources mapping="/resources/**" location="/resources/" />  -->

<resources mapping="/**" location="/resources/" />

<!-- Tiles--> 

<beans:bean id="tilesViewResolver" class="org.springframework.web.servlet.view.tiles2.TilesViewResolver" >

</beans:bean>

<beans:bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">

<beans:property name ="definitions">

<beans:list>

<beans:value>/WEB-INF/tiles/tiles.xml</beans:value>

</beans:list>

</beans:property>

</beans:bean>









2.4 root-coontext tiles 내용 추가

이제 root-context.xml 파일에도 아래와 같이 tiles 정보를 추가 입력해줍니다.


<!-- tiles--> 

<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">

     <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView" />

     <property name="order" value="2" />

</bean>













2.5 이제 타일즈를 적용할 파일에 중앙부 내용을 입력하고 타일즈가 적용이 되었는지를 확인합니다.

   (지금 예제의 경우는 home에 적용을 했기 때문에 home.jsp가 정상 동작하는지 확인합니다.)

적용이 안되가지구 보니 tiles.xml 작성할때 /WEB-INF/views/home.jsp 로 작성했기 때문에 homecontroller에 return 값을 "home" ->"/home"으로 변경하니 정상 작동하는것을 확인 했습니다.




이렇게하면 Tiles까지 적용 완료! 

새로운 페이지를 만들때에 타일즈를 적용할거면 페이지.jsp 작성 후 tiles.xml에 페이지.jsp 경로를 추가해주면 될 것입니다.

이제 정상동작 확인했으니 commit 후 push!



이제 본격적으로 기능들을 만들어 볼 차례가 된 것 같습니다.

오늘은 여기까지 정리하겠습니다!






SpringFramewokr를 이용하여 웹 프로젝트에 사용되는 기본 예제들을 하나씩 정리해 볼까 합니다.


환경설정은 아래와 같습니다.

- Spring 3.1.1

- MySQL 5.7

- Apache Tomcat 7.0

- JDK 1.8


시작합니다!


오늘 정리할 것은 세가지!

- githup.com에 repositroy 생성하기

- 프로젝트 생성 하기 

- Git 적용하기


1. Github 홈페이지에 repository 생성하기


1.1 github 계정이 있다면 로그인 후 New를 클릭하여 repository를 생성합니다.


1.2 이후 repository 이름을 설정 후 Create repository를 생성합니다.


1.3 Creating a new file을 클릭해주세요.

- 단, 기존 프로젝트를 git 프로젝트로 진행하고자 한다면 uploading an existing file을 클릭해주세요

(저는 처음부터 진행 할 예정이기에 creating a new fille을 선택했습니다.)


1.4 commit 하기 위해선 우선 파일을 하나 생성해야 하기 때문에 ReadMe file을 생성하고 내용을 입력합니다.



1.5 이후 최초 1회 커밋이 되어야 repository 생성이 가능하기 때문에 아래 Commit message를 적고 change commit을 클릭해주시면 완료됩니다.


1.6 이렇게 하면 repository가 생성 되었습니다.


이제 github을 STS와 연동합니다.



1.7 File -> import 클릭 후 Git -> project from Git을 선택합니다.


1.8 이후 Clone URI를 클릭 후 github에 있던 clone 주소를 복사하여 설정합니다.


1.9 URI 입력 후 계정 비밀번호 입력하고 NEXT를 누르면 연동이 됩니다.

이후 next 누르면 아직 project는 없기에 finish는 클릭이 안되는데, 그냥 cancel 누르면 됩니다.

이렇게 하면 일단 repo와 sts 연동 성공!


2. 프로젝트 생성하기

/*

Spring에서 프로젝트를 생성할때 주로 아래와 같은 프로젝트 중 선택을 하게 됩니다. 

- Spring Legacy Project (일반적으로 사용하는 MVC SpringFramework ->유지보수가 편해서 큰 프로젝트 만들때 유용)

- Dynamic Web Project (Wep application 개발시 사용하는 프로젝트 -> 단순 기능동작하는 작은 프로젝트에 유용)

- java Project ( Java application 개발시 사용.. 저는 코딩테스트 연습할때 자주 씁니다)

근데 이것들이 차이가 궁금해서 보니 차이는 프로젝트 폴더 구조의 차이였습니다. 

상황에 따라 관리하기 유용한 프로젝트를 선택하면 되는것이라는 말이지요.

복잡하게 하나하나 분석하면 길어질 것 같기때문에 간단히 정리해봤습니다.

*/


2.1 Spring Legacy Project를 생성합니다. 

- 프로젝트명을 작성합니다. 저는 "Spring_WEB_Basic"로 생성하려 합니다.

- 이후 Spring MVC Project를 선택하고 Next를 눌러주세요.

2.



2.2 패키지 이름을 설정합니다.

패키지 이름은 아래 형식에 맞게 원하는 이름으로 설정합니다.


2.3 MVC 프로젝트의 폴더 구성은 다음과 같습니다.

( MVC 개념 관련 내용은 따로 정리 하겠습니다. )




3. STS에서 생성한 프로젝트 Git에 추가하기

- 생성 되었으면 이제 Git으로 버전을 관리할 수 있도록 설정하겠습니다.

- Git에 관련된 명령어 및 개념들은 Git 메뉴에 따로 정리할 예정입니다.


3.1  프로젝트 오른쪽 클릭 후 Team -> Share Project 클릭


3.2 Share Project를 누르게 되면 저장소를 설정하게 되는데, 원하는 위치에 설정하면 됩니다.



3.3 이후 다시 Share Project를 누르고 Add to index 누르고 commit message 작성 후 commit & push 눌러서 성공하면 설정 끝!


3.4 git 홈페이지에서 repository에 정상 등록 되었는지 확인하면 완료입니다.



다음 내용은 이제 부트스트랩 적용 및 타일즈 설정하기!





상속!!!!

 

면접 단골 질문!

Q. 객체지향 프로그래밍(OOP)의 특징이 무엇인가요?

A. 객체지향 프로그래밍의 특징은 추상화, 캡슐화, 상속과 다형성 입니다. 

 

이 중에서 오늘 다루어볼 내용은 상속! 입니다.

또, 자바 시험볼 때 상속 관련 문제가 상당히 많이 출제되는 것 같습니다.

헷깔리거든요 ㅋㅋ (알면 아니지만)

 

어쨋건! 그래서 오늘 정리할 내용은 "상속 + 다형성" 입니다.

- 목차
1. 상속 개념
2. 생성자
3. OverLoading (다형성)
4. OverRiding
5. super

 

 

 

 

1. 상속 개념

Q. 상속이란 ?  

A. 상속을 통해 부모 클래스에 선언된 메서드나 변수를 자식 클래스에서 사용, 확장시킬 수 있는 것을 말합니다.
extends 라는 키워드를 통해 상속 받을 수 있습니다.

 

- 간단한 예로 살펴봅시다.

사진 1. 상속 예제 1

 

부모 클래스인 Parent class와 자식 클래스인 Child class를 생성 후 사진 1과 같이 Child class에 Parent를 상속 받습니다.

그러면 부모 클래스에 있는 print_parent()라는 메서드 및 변수들을 사용할 수 있게 됩니다. 

 

그러면, 궁금한 것이 생기죠. 부모 클래스의 어디까지 쓸 수 있는가!?

-> private으로 선언되지 않은 나머지는 받아 쓸 수 있습니다.

 

큼..심플하군.. 다음!

 

2. 생성자

상속을 배울때 나오는 개념 중 하나는 생성자!

Q. 생성자란 무엇이냐?

A. 클래스와 동일한 이름을 가진 메서드로, return 값이 없고, 초기화 목적으로 사용되는 메서드를 말합니다.

(전 이해 안하고 그냥 기계마냥 이렇게 외웠었음..)

 

맞는말이지만 제가 궁금한건 왜? 생성자를 쓰냐는 것이지요.
이유를 찾아보니, 단순했습니다. 

1. 초기값을 강제하기 위해서
2. 값을 초기화 하기 위해서

 

물론 생성자를 통하지 않고 값을 초기화 할 수 있습니다.

Child 객체를 3개 만들고 값을 초기화 하는 코드 입니다.

public class Child extends Parent{
		
	public static void main(String args[]) {
		
		Child c1 = new Child();
		Child c2 = new Child();
		Child c3 = new Child();
		
		c1.name = "c1 name";
		c1.age = 1;
		c1.assets = 1;
		c2.name = "c2 name";
		c2.age = 2;
		c2.assets = 2;
		c3.name = "c3 name";
		c3.age = 3;
		c3.assets = 3;
	}
}

객체가 늘어날수록 개판이 될것같네여

생성자를 통해 초기화 한다면? (물론, 생성자를 통한 초기화를 위해, Parent와 Child에 생성자를 선언해줍니다.)

사진 2. 생성자 초기화를 위한 코드수정

 

깔끔하군여!

이렇게 초기화와 값의 입력을 강제하면 보다 통일된 형태와 깔끔한 코드로 작성할 수 있습니다. 그렇기 때문에 생성자를 사용하는 것이지요.

 

- 생성자 만들기

그러면, 생성자는 어떻게 만드는가? 가 궁금해집니다.
(아래 예제는 맨 위 '사진 1. 상속예제' 기준으로 작성했습니다.)

먼저 기본 생성자를 알아봅시다. 기본 생성자의 형태는 다음과 같습니다.

클래스이름(){

}

겁나 간단하군요. 


일반적으로 클래스를 생성하고, 객체를 생성할 때 우리는 Child c = new Child(); 이렇게 씁니다.

당연한거아닌가!?

여기서 주목할 점은 new Child() 입니다. 하나씩 명령어를 살펴봅니다.

new Child() -> new '객체'를 생성하겠다 -> 객체 'Child()'를 생성하겠다 -> Child()는 method 로군. 
-> ? -> 나는 Child() 라는 메서드를 생성한 기억이 없다!!!

일반적으로 클래스를 생성하면 자동으로 생성자가 생성됩니다. (직접 생성 안해도 자바 컴파일러가 알아서 만들어줌)
그래서 따로 생성자를 선언하지 않고, 클래스를 생성 해도 객체가 생성 될 수 있었던 이유입니다.

Class가 선언되고 실행하려면 동작 메서드가 필요한데 아무것도 없으면 곤란합니다.
그래서 만약 아무것도 작성되있지 않다면 기본 생성자를 생성하게 되는 것 입니다.

 

 

- 생성자의 생성 조건은 다음과 같습니다.

1. 클래스의 이름과 동일해야 한다.
2. return 값이 없어야 한다.
3. 생성자는 매개 변수값이 다르면 여러개 생성이 가능하다.

'사진 2. 생성자 초기화를 위한 코드수정' 생성자를 기준으로 봅시다.
기본적으로 생성자가 생성이 되었는데, Child(String name), Child(String name, int age, int assets) 과 같이 또 작성이 되어있습니다.

이게 무엇인가!? 생성 조건 3을 보듯 생성자는 매개 변수가 다르면 생성자는 여러가지로 생성될 수 있습니다.

이것을 설명하는 이유는 자바 필ㄹㄹㄹㄹㄹ수 개념 OverLoadig 과 관련이 있기 때문입니다.

 

 

 

 

3. OverLoading

Q. OverLoading이 뭔데?
A. 생성자의 파라미터의 타입이나, 개수로 구분이 되기 때문에 생성자의 초기화 목적에 따라 같은 이름으로 여러개를 구현할 수 있죠. 이것을 오버로딩(OverLoading) 이라고 합니다.

바로 예시 들어갑니다.

public class Child extends Parent{
	
	String name;
	int age;
	Child(String name){
		System.out.println("set Child name");
	}
	Child(int age){
		System.out.println("set Child age");
	}
	Child(String name, int assets) {
		//super(name, assets);
		System.out.println("set Child name,assets");
	}

	public static void main(String args[]) {
		
		Child c1 = new Child("c1_name",1);
		Child C2 = new Child("c2_name");
		Child C3 = new Child(3);
	}
}

 

Q. 출력 값은 무엇일까요?
A.
set Child name,assets
set Child name
set Child age

이렇듯, 파라미터의 타입, 개수에 따라 구분이 가능하게 하고, 이름이 같은 생성자를 여러개 만드는 것
이것을 "짐을 더 실어준다"라고 해서 = OverLoading 이라고 말합니다.

 

[★○@!!] 여러가지 형태로 사용 할 수 있는 '오버로딩(OverLoading), 오버라이딩(OverRiding)'은 OOP 특징이 중 하나인 '다형성'을 지원하기 위한 장치이기도 합니다.

 

 

 

4. OverRiding

Q. 그럼 OverRide는 뭔가요?
A. '재정의'요

맞습니다!! 재정의하는것을 OverRide라고 합니다.
근데, 무엇은 재정의 한다는거지?

부모 클래스로 부터 상속받은 메서드를 다른 방식으로 사용하도록 다시 사용하는 것을 재정의 라고 합니다.

Q. 아래 사진과 같이 작성을 했을때 출력값은 무엇일까요? Parent_print vs Child_print

사진 3. 오버로딩 예제

A. Child_print 입니다.

위 예제와 같이 부모 클래스에서 상속받은 print_parent()라는 메서드를 자식 클래스에서 다시 정의해서 사용하는 것
이것을 OverRide라고 합니다. 

추상 클래스를 상속받아 사용할때 오버라이드를 주로 사용합니다.

이렇게 오버로딩과 오버라이딩의 차이를 알아 보았습니다.
상속 문제가 장난치기 참 좋은것 같습니다. 장난에 말리지 않게 꼼꼼히 정리해 두면 좋을 것 같네요 

 

 

5. super

위 예시(사진 2)를 보다보면, super() 라는 메서드를 볼 수 있습니다.

이건 또 뭐야!?

super()를 보기 전에 예제를 하나 봅시다.

public class GrandParent {
	GrandParent(){System.out.println("GrandParent_Constructor"); }
}

public class Parent extends GrandParent{
	Parent(){ System.out.println("Parent_Constructor");}
}

public class Child extends Parent{
	Child(){System.out.println("Child_Constructor");}
	
	public static void main(String args[]) {
		Child c = new Child();
	}
}

Q. 이거 실행하면 결과값이 뭘까요?

A.
GrandParent_Constructor
Parent_Constructor
Child_Constructor

상속을 받는 경우 생성자는 부모 클래스를 찾아가도록 설정이 되어있습니다.
생성자를 생성하지 않으면 Default 생성자를 생성하듯,

부모생성자를 부르지 않아도 알아서 부르도록 설정이 되어있지요.
저기서 보이지 않지는 않지만 부모 클래스를 참조하도록 super() 메서드가 작성되어 있습니다!

참 재미있지요?

 

그럼 대체 super가 무엇이냐 하면

정의는 다음과 같습니다.
super 키워드는 부모 클래스로부터 상속받은 필드나 메소드를 자식 클래스에서 참조하는 데 사용하는 참조 변수이다.

 

super는 기본적으로 부모 클래스를 메서드를 참조합니다. 그래서 위에서 예시를 볼때
GrandParent 까지 참조하는 이유는 아래와 같습니다.

1. Child에서 부모 참조(super())를 통해 Parent를 참조하면서 생성자 Parent()가 실행됨
2. Parent() 실행되면서 안에 보이진 않지만 작성 된 super()로 인해 GrandParent를 참조함
3. GrandParent를 참조 하면서 GrandParent()가 실행 됨. GrandParent는 상속받지 않았으므로, super()가 생성되지 않음. 

그리고, 결과적으로 메모리는 스택으로 실행되기 때문에 GrandParent -> Parent -> Child 순서로 출력이 되는 것 입니다!

 

참고,
상속을 받게되면 super()가 생성되기 때문에 부모를 참조하려 합니다.  그래서 부모 클래스에 적절한 생성자가 없다면 자식클래스의 생성자를 만들었을때 오류가 생긴다는 점 참고하면 좋을 것 같습니다!

기본형이 아닌, 파라미터로 구분가능 부모 생성자를 호출하고 싶다면 표기 아래와 같이 사용 가능 합니다!

사진 4. super 사용법 1

 

이상 상속 정리 끝

 

 

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

String to Date , Date to String, Time add  (0) 2020.10.19
Eclipse java Working Set 설정  (0) 2020.03.07
interface와 상속 차이 (미완)  (0) 2019.12.22
Java 다중 반복문 빠져나가기  (0) 2019.10.05
01. 자바 접근제어  (0) 2019.01.08


DB를 공부하다 보면 가장 이해하기 어려웠던 부분이 정규화 였습니다.

- 도메인 원자값 (1NF)

- 부분적 함수 종속 제거 (2NF)

- 이행적 함수 종속 제거 (3NF)

- 결정자이면서 후보키가 아닌 것 제거 (BCNF)

- 다치 종속 제거 (4NF)

- 조인 종속성 이용 (5NF)


정보처리기사를 공부하면서 암기했던 도부이결다조를 외웠지만 사실 이렇게 외우면 시간지나면 까먹기 마련입니다.

또 헷깔려서 여기저기 내용을 찾아보면 각 정규화 마다 다른 테이블로 진행하여 이해는 되지만 뭔가 찝찝한(?)기 분이들어

한개의 테이블을 정규화를 통해 변화해 가는 모습을 통해 쉽게 이해하고자 합니다.


그럼 시작!


* 제 1 정규화 (비정규형 -> 1NF)


수강내역

학번

이름

메일

대학

전공

수강학기

과목명

성적

제한인원

101

Tom

tom@naver.com

이과대학

생물학과

2016.1

생물1

A

20

101

Tom

tom@naver.com

이과대학

생물학과

2016.1

생물2

B

30

102

Dan

Dan@naver.com

IT대학

컴퓨터과

2016.2

C++

A

40

102

Dan

Dan@naver.com

IT대학

컴퓨터과

2017.1

C언어

C

40

103

Jin

jin@google.com

정경대학

경제학과

2017.2

경제

A

30

그림1) 비정규형 테이블


제 1정규형을 갖추려면 도메인 원자값 이라는 조건이 만족해야 합니다.

도메인 원자값을 만족시킨다는 것은 아래와 조건과 같습니다.


1) 반복 그룹이 존재하면 안된다.

- Tom이라는 학생에 대한 정보인 이름,메일,대학,전공은 초기 설정하면 이후 계속 따라오게 됩니다.

그렇기 때문에 해당 정보는 수강 내역을 확인하기 위해서 계속 반복되기에 테이블을 분리합니다.

2) 모든 행은 식별자로 완전하게 구분되어야 한다.


그렇다면 이 비정규형 테이블 예제를 1정규화 시켜 보도록 정리해 보도록 하겠습니다.


1. 반복되는 부분을 체크합니다. -> 학번, 이름, 메일 ,대학, 전공 (Prime key : 학번)

2. 반복되는 부분과 그렇지 않은 부분을 분리합니다. (단, prime key는 그대로 가져갑니다.)

3. 테이블을 나눈 후 반복되는 행은 삭제합니다.


이 과정을 거치면 아래와 같은 테이블로 변경이 됩니다.


학생

수강내역

학번

이름

메일

대학

전공

학번

수강학기

과목명

성적

제한인원

101

Tom

tom@naver.com

이과대학

생물학과

101

2016.1

생물1

A

20

102

Dan

Dan@naver.com

IT대학

컴퓨터과

101

2016.1

생물2

B

30

103

Jin

jin@google.com

정경대학

경제학과

102

2016.2

C++

A

40

102

2017.1

C언어

C

40

103

2017.2

경제

A

30

그림2)  제 1정규화 이후 테이블1


그런데, '학생' 테이블은 2번 조건인 "모든 행은 식별자로 완전하게 구분되어야 한다." 라는 조건이 만족하는 반면

수강내역은 prime key인 '학번'만으로는 모든 행이 구분되지 않습니다. 

그렇기 때문에 추가적으로 key를 설정 해 주어야 합니다.

그래서  '수강 내역' 테이블의 '학번'+'수강학기'+'과목명'복합하여 식별자로 두면서 문제를 해결하면 제 1 정규화는 마무리 됩니다.


* 제 1 정규형 테이블

학생

수강내역

학번

이름

메일

대학

전공

학번

수강학기

과목명

성적

제한인원

101

Tom

tom@naver.com

이과대학

생물학과

101

2016.1

생물1

A

20

102

Dan

Dan@naver.com

IT대학

컴퓨터과

101

2016.1

생물2

B

30

103

Jin

jin@google.com

정경대학

경제학과

102

2016.2

C++

A

40

102

2017.1

C언어

C

40

103

2017.2

경제

A

30

그림3)  제 1정규화 이후 테이블2


* 제 2 정규화 - 부분함수 종속 제거

필요 충분 조건 : 후보키 K와 K에 속하지 않는 속성 A가 있을 때, A를 결정하기 위해 K의 일부가 아닌 K 전체를 참조해야만 하는 경우 1NF 테이블은 2NF이다.

뭔 소리야? 

간단하게 말하면 Key가 아닌 값들은 모두 key에 종속 되어야한다는 말입니다.
이래도 말이 어렵기 때문에 그림으로 이해해보도록 하져

조건은 다음과 같습니다.
1) key가 아닌 컬럼(속성)은 key 컬럼이에 종속 되어야 한다.
2) key가 아닌 컬럼(속성)은 key 컬럼에! 종속 되어야 한다. 그래서
3) 복합키 일때만! 제 2정규형의 조건이 되는것이지요. (복합키가 아니면 제 2정규형을 넘어 제 3정규형을 보면 됩니다)
TiP) 결과적으로 Key 값에 주목하는것이 제2 정규화의 핵심!

제 1정규형을 마친 '수강내역' 테이블을 보겠습니다.

수강내역

학번

수강학기

과목명

성적

제한인원

101

2016.1

생물1

A

20

101

2016.1

생물2

B

30

102

2016.2

C++

A

40

102

2017.1

C언어

C

40

103

2017.2

경제

A

30


그림 4) 제2 정규화 대상인 '수강내역' 테이블


'수강내역' 테이블은 '학번+수강학기+ 과목명'(이하 학+수+과)으로 이루어진 복합키 입니다.
그러면 제2 정규형에 만족을 하려면 복합키인 학+수+과에 성적과 제한 인원이 확실하게 종속 돼야 한다는 것인데
살펴봅시다.

'성적'의 경우는 학번과 수강학기 과목명을 알아야 해당 학기 성적을 알 수 있기때문에 key에 종속이 되는것을 확인했는데,
'제한인원'의 경우는 학번과는 딱히 관계가 없어 보입니다.

그렇기 때문에 이것을 한번 더 나눌 수 있다는 것! 이겠지요
그러면 분리 해봅시다.



Key '수강학기+ 과목명' non-key '제한인원'으로 구성된 테이블 '개설 과목'으로 분리가 됩니다.

개설과목

수강학기

과목명

제한인원

2016.1

생물1

20

2016.1

생물2

30

2016.2

C++

40

2017.1

C언어

40

2017.2

경제

30

그림5) 새로 생성된 '개설과목' 테이블



그래서 제 2정규화를 하게 되면 수강내역 테이블은 수강내역 + 개설과목 2개 테이블로 나누어 집니다.

수강내역

개설과목

학번

수강학기

과목명

성적

수강학기

과목명

제한인원

101

2016.1

생물1

A

2016.1

생물1

20

101

2016.1

생물2

B

2016.1

생물2

30

102

2016.2

C++

A

2016.2

C++

40

102

2017.1

C언어

C

2017.1

C언어

40

103

2017.2

경제

A

2017.2

경제

30

그림6) 제2 정규화 이후 테이블

이렇게 제2 정규형 테이블이 되었습니다.
컬럼이 많을경우 경우의수를 다 따져가며 확인해야하는 불편함이 있겠네여
학번/수강학기/과목명/ 학번+수강학기/수강학기+과목명/학번+과목명/....  ㅠㅠ
복합키가 많아지면 귀찮아질듯 ㅎ



* 제 3정규화 - 이행적 함수 종속 제거

필요 충분 조건 : 제 2정규형을 만족하고, 테이블 내의 모든 속성이 키에만 의존하며 다른 후보키에 의존하지 않는다.

정리하면
1) 모든 key가 아닌 컬럼(non-key)은 key 컬럼(속성)에 완전히 종속 되어야 한다.
2) 모든 non-key 컬럼은 key 컬럼(속성)에만 종속 되어야 한다.
3) 그래서 key가 아닌 값에 주목!


제 2정규형 조건을 만족하는 '학생' 테이블을 확인해보져

학생

학번

이름

메일

대학

전공

101

Tom

tom@naver.com

이과대학

생물학과

102

Dan

Dan@naver.com

IT대학

컴퓨터과

103

Jin

jin@google.com

정경대학

경제학과

그림7) 제3 정규화 대상인 '학생' 테이블


위에서 보게되면 non key 컬럼인 '대학'과 '전공'을 보게되면 key가 아닌 컬럼인데도 불구하고

종속 관계가 성립이 됩니다.

'대학'의 경우 '전공'을 포함하기 때문입니다. 

즉, 생물학과면 무조건 이과대학에 포함되고, 컴퓨터 학과의 경우 IT대학의 부분으로 포함이 되지요.


정규화가 잘 된 테이블은 갑-을 관계만 있는 것 입니다.

그런데 '학생'테이블의 경우 갑(key:학번)-을(non-key:대학)-병(non-key : 전공) 관계가 있기 때문에  이 관계를 깔끔하게 정리 해주어야 합니다.


학번/이름/메일/전공  -  대학/전공으로 테이블이 나뉘게 됩니다.


대학정보

전공

대학

생물학과

이과대학

컴퓨터과

IT대학

경제학과

정경대학

정치학과

정경대학

그림8) 제3 정규화로 인해 생성된 '대학정보' 테이블


'대학정보' 테이블의 경우 대학이 전공을 포함합니다. 하지만 key는 테이블의 튜플을 구분해 낼 수 있어야 합니다.

그래서튜플을 구분하기 위해서는 '전공'key 값이 되겠지요.

 

'대학' 정보를 참조하기 위해서는 학생 테이블의 '전공'을 외래키(foreign key)로 설정하여 '대학정보' 테이블을 참조 할 수 있게 해야 합니다.

그래서 제 3정규화를 마친 '학생' 테이블은 다음과 같이 분리 하게 됩니다.


학생

대학정보

학번

이름

메일

전공(FK)

전공

대학

101

Tom

tom@naver.com

생물학과

생물학과

이과대학

102

Dan

Dan@naver.com

컴퓨터과

컴퓨터과

IT대학

103

Jin

jin@google.com

경제학과

경제학과

정경대학

정치학과

정경대학

그림9) 제3 정규화를 마친 '학생' 테이블


* 결론!! 테이블 정리

그래서 비정규형 테이블이였던 '학생' 테이블을 제 3정규화까지 마치게 될 경우 아래와 같이 정리가 됩니다.


- 비정규형 테이블

수강내역

학번

이름

메일

대학

전공

수강학기

과목명

성적

제한인원

101

Tom

tom@naver.com

이과대학

생물학과

2016.1

생물1

A

20

101

Tom

tom@naver.com

이과대학

생물학과

2016.1

생물2

B

30

102

Dan

Dan@naver.com

IT대학

컴퓨터과

2016.2

C++

A

40

102

Dan

Dan@naver.com

IT대학

컴퓨터과

2017.1

C언어

C

40

103

Jin

jin@google.com

정경대학

경제학과

2017.2

경제

A

30

그림10) 비정규형


- 제 1정규형 테이블 (제1 정규화) 

학생

수강내역

학번

이름

메일

대학

학번

수강학기

과목명

성적

제한인원

101

Tom

tom@naver.com

이과대학

101

2016.1

생물1

A

20

102

Dan

Dan@naver.com

IT대학

101

2016.1

생물2

B

30

103

Jin

jin@google.com

정경대학

102

2016.2

C++

A

40

102

2017.1

C언어

C

40

103

2017.2

경제

A

30


- 제 2정규화 테이블 (제2 정규화 이후)

수강내역

개설과목

학번

수강학기

과목명

성적

수강학기

과목명

제한인원

101

2016.1

생물1

A

2016.1

생물1

20

101

2016.1

생물2

B

2016.1

생물2

30

102

2016.2

C++

A

2016.2

C++

40

102

2017.1

C언어

C

2017.1

C언어

40

103

2017.2

경제

A

2017.2

경제

30



- 제 3정규화 테이블 (제 3 정규화 이후)

학생

대학정보

학번

이름

메일

전공(FK)

전공

대학

101

Tom

tom@naver.com

생물학과

생물학과

이과대학

102

Dan

Dan@naver.com

컴퓨터과

컴퓨터과

IT대학

103

Jin

jin@google.com

경제학과

경제학과

정경대학

정치학과

정경대학


- 최종 테이블

학생

대학정보

학번

이름

메일

전공(FK)

전공

대학

101

Tom

tom@naver.com

생물학과

생물학과

이과대학

102

Dan

Dan@naver.com

컴퓨터과

컴퓨터과

IT대학

103

Jin

jin@google.com

경제학과

경제학과

정경대학

정치학과

정경대학


수강내역

개설과목

학번

수강학기

과목명

성적

수강학기

과목명

제한인원

101

2016.1

생물1

A

2016.1

생물1

20

101

2016.1

생물2

B

2016.1

생물2

30

102

2016.2

C++

A

2016.2

C++

40

102

2017.1

C언어

C

2017.1

C언어

40

103

2017.2

경제

A

2017.2

경제

30



결과적으로 시험에 잘 나오는 정규화는 1~3 정규화 입니다. 

그래서 이렇게 하나의 이야기처럼 정리해두면 머릿속에 오래 남을것 같아 기록해둡니다 ㅎㅎ


다음편에 BCNF부터 제5 정규화까지 정리해보도록 하겠습니다.

(사실 제3정규화까지 잘 되었다면 나머지 4,5 정규형도 만족하게 되는 경우가 많기 때문에

BCNF ~ 제5 정규화는 각 예시에 어울리는 테이블로 정리 해볼 예정입니다!)




'DataBase > DataBase 이론 공부' 카테고리의 다른 글

면접 보러가기 전! DB 용어 정리 하기  (0) 2019.02.14

자바의 기본 개념들이 생각이 안나거나 이해가 잘 안되었던 부분들을 

여기에 하나씩 정리해 볼 예정 입니다. 그렇기 때문에 보통 책에 나오는 목차들과는 달리 마구잡이로

정리될 것 같네요 ㅠㅠ


어쨋건 시작해 보겠습니다!


#접근 제어


이클립스(Eclipse)를 설치하고  코딩 예제를 시작하고

Hello World!를 출력하고자 한다면 다음과 같은 예제를 많이 사용합니다.

------------------------------------------------------------

Public class hello

public static void main(String[] args){

System.out.println("Hello World!");

}

}

------------------------------------------------------------

그러면 오늘은 위에서 밑줄이 그어진 public과 같은 접근 제어자에 관해서 정리해 볼 예정입니다.


* 자바의 접근 제어 지정자

멤버 접근 제어는 public, private, protected 이렇게 3가지 지정자로 이루어집니다. 

그럼 이 접근 지정자를 표로 정리해 보면 다음과 같습니다.

접근 지정자 

클래스 

패키지 

자식 클래스 

전체 세계 

public 

O

O

O

O

protected 

O

O

O

X

 없음

O

O

X

X

 private

O

X

X

X


사실 이것만 보면 뚜렷하게 와닿지가 않습니다.

- 간단하게 그림으로 정리하기

이렇게 정리하면 어디서 사용 되고, 또 안되는지를 확인 할 수 있을 것 같습니다.

(자식 클래스의 경우 상속 개념을 알면 따로 설명하지 않아도 될 것 같아서 표기하진 않았습니다.)


- 클래스 끼리는 객체를 생성하면 사용 가능 합니다.

- 패키지로 떨어진 것은 import를 사용하면 사용 가능 합니다.

- 전체 세계 즉, 다른 프로젝트에 있는 클래스를 사용하고자 한다면 프로젝트 속성 -> Build Path 설정 -> "사용할 클래스가 있는 프로젝트" 추가

   한 후 import 하면 사용할 수 있습니다.


쉽지만 중요한 개념이기 때문에 정리 해봤습니다.

또 1차 자바를 주력으로 하는 회사에서 필기 시험에서 가끔 나오기 때문에 위에 표를 외워두면 두면 좋을 것 같네요 


끝!



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

String to Date , Date to String, Time add  (0) 2020.10.19
Eclipse java Working Set 설정  (0) 2020.03.07
interface와 상속 차이 (미완)  (0) 2019.12.22
Java 다중 반복문 빠져나가기  (0) 2019.10.05
02. 상속  (0) 2019.01.15

숫자를 한글로 읽기


메이플스토리를 하다보면 한글날에 데미지 스킨을 주는데,  이 데미지 스킨을 사용하면

숫자로 출력하던 데미지들이 한글로 변경이 됩니다!


그럼 자바를 통해서 숫자를 한글로 읽을 수 있도록 하는 문제를 풀어봅시다.


[제한사항]

주어진 숫자 num는 1조 미만의 숫자 입니다.

1의 자릿수 이상에서의 1은 "일"로 읽지 않고 공백으로 취급합니다.

ex)1231 의 경우 

"일천이백삼십일" (X)

"천이백삼십일" (O)


[입출력 예]

1234

"천이백삼십사" 


49032

 "사만구천삼십이"


[문제 풀이]

import java.util.*;

public static void main(String[] args) {

// TODO Auto-generated method stub

int num;

Scanner s = new Scanner(System.in);  //숫자 num을 입력 받습니다.

num = s.nextInt();

String answer = "";

    

    String num_string = String.valueOf(num);  //int형은 substring이 안되기 때문에 문자형으로 받아 주어야 합니다.


        String[] han1 = {"","일","이","삼","사","오","육","칠","팔","구"};

        String[] han2 = {"","십","백","천"}; //십, 백,천 단위를 구분하기 위해 배열을 선언 합니다.

        String[] han3 = {"","만","억"};  // 천단위로 끊어서 단위가 올라가기 때문에 만이상 단를 구분해 줄 배열을 선언합니다.


        StringBuffer result = new StringBuffer();  // StringBuffer 선언

        int num_len = num_string.length();      // num의 길이 측정


        for(int i=num_len-1; i>=0; i--){  

           // 십단위 이상의 1은 읽지 않기 때문에 마지막 일을 제외한 1의 경우 "일"로 읽지 않음

            if(han1[Integer.parseInt(num_string.substring(num_len-i-1, num_len-i))]=="일" && num_len-i != num_len) {

                result.append(han1[0]);

            //System.out.println(result.append(han1[0])); 디버깅용

            }

            else { 

                result.append(han1[Integer.parseInt(num_string.substring(num_len-i-1, num_len-i))]);

            //System.out.println(result.append(han1[Integer.parseInt(num_string.substring(num_len-i-1, num_len-i))])); //디버깅용

            }

            // i는 자릿 수 이기 떄문에 4로 나눈 나머지가  3이면  천 / 나머지가 2이면 백 / 나머지가 1이면 십 /4로 나누어떨어지면 안읽음

   // 9090과 같이 0을 제외한 백단위 이상 숫자를 구분하여 읽기 위한 조건문

                if(Integer.parseInt(num_string.substring(num_len-i-1, num_len-i))>0);

                result.append(han2[i%4]);

            //System.out.println(result.append(han2[i%4])); //디버깅용

            //만단위 이상으로 올라갈 경우 처리하기 위함

            if(i%4==0)

            //System.out.println(result.append(han3[i/3])); //디버깅용

            result.append(han3[i/3]); 

            

        }

      //   result.append(han1[Integer.parseInt(num_string.substring(num_len-1, num_len))]); //디버깅용

        answer = result.toString(); // String Buffer랑 String이랑 다르기 때문에 String Buffer를 String으로 변경해주어야 합니다.

   //System.out.println(restult); // String으로 retrun할거 아니면 result 그대로 출력하면 됩니다.

     System.out.println(answer);

}

----------------------------------------------------------------------------------------------------------------------------------------------

for문을 돌릴때 0부터 시작하게 한다면 어떻게 작성해야할지 궁금해서 for문의 조건문 중 i를 0부터 시작하도록 변경 해 보았습니다.


[for문 0부터 시작 차이점]

 for(int i=0; i<num_len; i++){

        // 십단위 이상의 1은 읽지 않기때문에 0으로 설정하고 마지막 자리가 1일때만 읽도록 수정

    /* 초록색으로 표기된 부분이 변경된 부분입니다. */

   // num은 0부터 시작하기에 1을 빼주어야 정확한 계산이 가능 해집니다.

            if(han1[Integer.parseInt(num_string.substring(i, i+1))]=="일" && i != num_len-1) {

                result.append(han1[0]);

            //System.out.println(result.append(han1[0]));

            }

            else {

                result.append(han1[Integer.parseInt(num_string.substring(i, i+1))]);            

            }

           //i는 자릿 수 이기 떄문에 4로 나눈 나머지가  3이면  천 / 나머지가 2이면 백 / 나머지가 1이면 십 /4로 나누어떨어지면 안읽음

                if(Integer.parseInt(num_string.substring(i, i+1)));

                result.append(han2[(num_len-1-i)%4]);

              //System.out.println("천 단위 계산 :"+result.append(han2[(num_len-1-i)%4]));

           

            //만단위 이상으로 올라갈 경우 처리하기 위함

            if((num_len-1-i)%4==0)

            result.append(han3[(num_len-1-i)/3]);

//%로 계산하면 나머지가 다시 1로 떨어지는 경우 만을 출력하기 때문에 나눈 값의 몫으로 계산해야 만단위 이상에도 에러가 나지 않습니다.

            //System.out.println("만 단위 계산 : "+result.append(han3[(num_len-1-i)/3])); 

            //result.append(han3[i/3]);

        }

        


결국 조건문만 변경하면 똑같은 문제인것 같습니다.  계산 속도에서 당연 차이는 없어보이네요..

실행 시간은 O(n)이 되겠네요








 

오늘은 ssh서버로 이용할 수 있도록 셋팅을 해보도록 하겠습니다.


오늘 할일

1. 설치하기

2. ssh 설정 하기

3. 포트 열어주기

4. ip 주소 확인하고 접속하기



1.  ssh 설치 및 설정 


1-1. 설치하기

$sudo apt-get install ssh

사진1. ssh 설치


설치된 ssh의 위치는 /etc/ssh 에 설치가 됩니다.

사진2. ssh 설치 목록


빨간색 네모박스로 표시한  sshd_config 파일은 접근 권한을 설정하기 위해 자주 사용하게 될 것입니다.

그럼 바로 sshd_config를 확인 해 보도록 하죠

sshd_config 설정에서 주로 사용하는 것은 포트 설정과 사용자들에게 접근 권한을 부여할때 주로 사용하게 됩니다.

그래서 주로 봐야 할 것은 아래 3가지


1-2 포트 설정하기

1) 포트 설정 

 - 5번째 라인에 있는 포트를 수정하면 원하는 포트로 변경할 수 있습니다. (ssh 지정포트는 22번 이기 때문에 저는 그냥 22번포트 사용할 예정입니다.)

사진3. ssh port 변경


2) PermitRootLogin

 - 루트 계정으로 접근을 허용할지 여부를 설정하는 부분 입니다. 

 28번째 라인의 prohibit-password를 그대로 두거나 허용하고 싶은경우 'yes' 허용하지 않을 경우 'no'로 설정 해 주세요.

사진4. PermitRootLogin 설정


3)  유저 접속 권한 부여

 - 맨 아래에 아래 사진과 같이 AllowUsers와 AllowGroups를 작성해 주시고

   접속을 허용하고자 하는 계정과 그룹을 작성 해 주시면 됩니다. (구분자는 띄어쓰기로 하는것 참고 해주세요.)

사진5. 유저 접속 권한 부여


변경된 사항을 저장하고 저장된 내용을 적용하기 위해서 sshd를 재시작 해주어야 합니다.

사진6. sshd 재시작


이렇게 하면 ssh 설정은 완료 됩니다.

이제 서버 방화벽에서 해당 포트를 열어주어야 접속이 가능하기 때문에 포트를 열어주도록 하겠습니다.


1-3. 포트 열어주기

먼저 방화벽을 확인하는 명령어는 다음과 같습니다.

ufw status - 상태 확인

ufw enable - 활성화 (포트를 열어주기 위해 활성화를 시켜야 합니다.)

ufw disable - 비활성화 (defualt 값이며 이 경우 모든 포트를 차단합니다.)

ufw allow {port or ip} - 특정 포트를 오픈 합니다.

ufw deny {port or ip} - 특정 포트를 거부 합니다.

사진7. UFW 설정하기


ufw enable하여 포트를 열어준 뒤 접속 가능한 포트를 설정 해 주어야 합니다.

사진8. 22번 포트 open


netstat -tlnp 명령어를 통해 확인 하면 포트가 열린것을 확인할 수 있습니다.

사진9. 포트 확인


2. 서버 IP 확인하기


Linux에서 IP 확인하기 -> ifconfig


서버 컴퓨터가 존재한다면 IP 이제 해당 IP를 통해 ssh로 접근이 가능한 것을 확인 할 수 있습니다.

Local 컴퓨터에서 putty 혹은 teraterm과 같은 툴을 통해서 서버에 접속하여 편리하게 작업할 수 있도록 설정 해 주었습니다.


개인적으로 본인만 접속 가능한 서버 컴퓨터를 만들고 싶다면 iptime의 포트 포워딩을 통해서 외부에서 접속 가능한데

이 작업을 진행해 보도록 하겠습니다.






'IT > Linux(ubuntu)' 카테고리의 다른 글

ubuntu 계정생성  (0) 2021.11.26
ubuntu 웹서버 구축해보기  (0) 2021.11.26
우분투 계정 생성하기  (0) 2018.12.10
Windows PC 에서 ubuntu linux 시작하기  (0) 2018.12.06

설치를 완료 하였으니, 이제 계정을 생성하려고 합니다.

그래서 오늘은!

1. 비밀번호 설정

2. 계정 생성 방법 ( adduser / useradd)에 관하여 정리를 해보도록 하죠.


제 리눅스에서는 

최고 권환 계정 - root

마스터 권한 계정 - dan

일반 계정 - user1 으로 관리 할 계획 입니다.


일단 처음 os를 설치 했으니, root 비밀번호 설정부터 합니다.


1. 비밀번호 설정

[root 비밀번호 설정]

사진1. root 비밀번호 설정


$ sudo passwd root

위 사진과 같이 비밀번호를 설정하면 완료!


* su 와 sudo 명령어 (ubuntu와 Centos에서 지원하는 명령어 입니다.)

- su 명령어는 Super User 의 약자로  su 명령어를 사용하면 현재 사용중인 터미널에 일시적으로 "최고 권한"을 부여합니다.

- sudo 명령어는 Super User do의 약자로 관리자 권한으로 실행한다는 명령어 입니다.

  그래서 일반 계정에서 sudo 명령어를 입력하면 관리자 권한으로 실행 가능하기 때문에 보안상 관리자 계정에서만 sudo 명령어를 사용할 수 있도록    설정 해야 합니다.


2. 계정 생성

[User 생성]

* User 생성에는 adduser / useradd  2가지 방법이 있습니다.  차이점은?


결론 부터 말하면 아래와 같습니다.

- adduser : 자동 설정 (주로 사용)

- useradd : 수동 설정


이제 좀 더 자세한 차이를 확인 해 봅시다.


[adduser로 계정 생성하기]

사진2. adduser 계정 생성


* 생성 후 /etc/passwd 파일을 확인해 보면 생성 여부를 확인할 수 있습니다.

사진3. /etc/passwd 에서 adduser 계정 생성 확인


계정 정보를 보면 adduser1 계정 생성 시 작성한 정보와 defualt로 home directory는 /home/adduser1 , 은 /bin/bash로 설정된 것을 볼 수 있습니다.


이제 home directory에 무엇이 생성 되었는지 확인해 봅시다.

사진4. adduser로 생성한 계정 home dir 내용

기본적인 파일들이 생성된 것을 확인할 수 있습니다.

이렇듯 adduser로 생성하면 기본적으로 필요한 폴더와 파일들이 자동으로 생성되는 것을 확인 할 수 있습니다.


[useradd로 생성하기]

그렇다면 useradd는 어떻게 다른지 확인해 보도록 하죠.

사진5. useradd 계정 생성


아주 심플합니다.


* etc/passwd를 확인하면 ?

사진6. /etc/passwd에서 useradd 계정 생성 확인


아무런 정보도 입력하지 않았기 때문에 home dir만 설정 되어있습니다.

그래서 비밀번호 또한 root 권한으로 설정해 주어야 접속할 수 있습니다.

계정생성하면 default로 잡히는 home directory는 설정 되어있지만, /home으로 이동해보면 아무것도 생성되지 않음을 확인할 수 있습니다.

(home으로 이동하는 명령어 '~' 를 사용하면 No such file or directory 라는 메세지가 출력됩니다.)

* home directory 확인 해보기

사진7. useradd로 생성한 계정 home directroy 확인

.

(비밀번호 설정은 처음에 root 비밀번호 설정했듯이 passwd 명령어로 설정 해 주세요.)  스샷 까먹은거 아님


그래서 home 폴덜를 생성 해 주어야 합니다.


[useradd - mkdir 폴더 생성하기]

"mkdir 폴더이름" 으로 폴더를 생성 해 줍니다.

(폴더를 생성할 땐 접속한 계정의 소유자 폴더 내에서 폴더를 생성할 수 있고 폴더 소유자 역시 접속한 계정으로 자동 설정 됩니다.

하지만 소유자가 아닌 폴더에서 폴더를 생성 하고 싶은 경우 해당 폴더 소유자의 권한을 빌리거나 root 권한을 빌려야 합니다.

저 같은 경우 sudo 명령어로 root 권한을 빌려 폴더를 생성했는데, 이럴 경우 관리자 계정 권한을 빌렸기에 생성된 폴더 소유자는 root로 지정 됩니다.)


사진8. useradd1 home dir 생성하기


root 권한으로 생성했기 때문에 폴더 소유권이 root로 잡혀있습니다.

그래서 useradd1이 사용할 수 있돌록 소유권을 변경시켜야 합니다.


폴더 소유권 설정하는 chown 명령어를 통해 설정해 줍니다.

명령어는 다음과 같이 사용합니다.


[useradd - 폴더 소유권 변경 chown ]

 - $chown 계정:계정그룹 폴더이름

사진9. useradd1 home dir 설정


bash를 설정하지 않으면 순수 ubuntu에서 제공하는 기본 템플릿만 사용할 수 있기 때문에

사용자의 편의를 위해 bash를 설정해 주어야 합니다. 


이제 etc/passwd 파일에서 bash를 설정 해 줍니다.


그리고 home dirctory인 /home/useradd1 로 이동하여

 .bashrc 파일을 생성하여 자신의 입맛대로 설정 해 주시면 됩니다!

(bash에 관한 내용은 추후에 공부해 보도록 합시다.)

이렇게 하면 일단 기~본 설정은 끝.


[결론]

adduser와 다르게 useradd는 결국 기본 설정이 자동으로 생성되냐 아니냐의 차이 라는것을 확인 했고

useradd로 생성할 경우 기본 설정하는 과정을 살펴 보았습니다.

설정하는 과정에서 mkdir 명령어와 chown 명령어를 다루어 볼 수 있었습니다. 서버 관리에 자주 사용되는 명령어이기 때문에

알아 두도록 합시다.


이렇게 오늘은 비밀번호 설정과 계정 생성에 관해서 공부했고

useradd와 adduser의 차이점을 살펴 보았습니다.

저와 같은 초보자는 그냥 adduser로 계정 생성해서 관리하면 될 것 같군여 ㅎㅎ

이상으로 오늘 스터디를 마치겠습니다!




'IT > Linux(ubuntu)' 카테고리의 다른 글

ubuntu 계정생성  (0) 2021.11.26
ubuntu 웹서버 구축해보기  (0) 2021.11.26
외부접속 설정하기  (0) 2018.12.12
Windows PC 에서 ubuntu linux 시작하기  (0) 2018.12.06

+ Recent posts