danc
danc*dev
danc
  • 분류 전체보기
    • codestates_BE_bootcamp39
      • 주단위 일기
      • 회고
    • programming
      • JAVA
      • SPRING
      • GENERAL
      • LINUX
      • ALGORITHM
      • ERROR_HANDLING
    • web
      • NETWORK
      • DB
      • HTML
      • CSS
    • kr
    • nz

최근 글

인기 글

태그

  • TIL일기
  • HTTP
  • 일기
  • 회고
  • 윈도우 11 우분투
  • TIL 일기
  • css
  • React에서 Authorization헤더
  • TIL
  • AOP
  • 코드스테이츠
  • 코드스테이츠 백엔드

최근 댓글

티스토리

hELLO · Designed By 정상우.
danc
programming/JAVA

Java - 캡슐화 (Encapsulation)

programming/JAVA

Java - 캡슐화 (Encapsulation)

2022. 5. 12. 12:43

https://www.scientecheasy.com/2020/07/encapsulation-in-java.html/

 

캡슐화란 OOP에서 객체의 데이터와 기능을 하나로 묶고 외부에 노출되지 않도록 숨김 처리하는 것을 말한다.
데이터 보호와 내부적으로 사용되는 데이터에 대한 불필요한 외부 노출을 방지할 수 있다.

 

캡슐화의 가장 큰 이점으로써, 외부로부터 객체의 속성이나 기능이 변경되지 못하게 막고, 데이터가 변경되더라도 다른 객체에 영향을 주지 않는 독립성을 갖는다. 

따라서 OOP의 장점인 코드의 유지보수를 쉽게 하고 코드를 변경하더라도 오류의 범위를 최소화할 수 있다. 


패키지 (Package) 

패키지는 == 클래스와 인터페이스의 묶음

클래스가 관련된 속성과 기능을 묶어 관리하듯이 패키지는 그런 클래스들을 그룹 단위로 다시 묶어준다.

따라서 패키지를 통해 클래스의 관리를 쉽고 효과적으로 할 수 있다. 내가 폴더에 관련 파일들을 모아놓은 거라 같다고 보면 될 듯. 

  지금까지 단순하게 클래스 이름으로만 클래스를 구분했지만, 실제로는 클래스의 full name은 패키지 명을 포함한다. 
예를 들어 String 클래스의 실제 이름은 java.lang.String이다. java.lang 패키지에 속한 String 클래스라는 뜻인데 가끔 에러 창에 java.lang 어쩌고 하는 문구가 나올 때가 있었는데 패키지와 관련된 무언가 였을 것이다. 

이런 이유덕에 같은 이름의 클래스 파일이라도 각자 다른 패키지에 포함되어 있다면 패키지 명으로 구별할 수 있다. 

  클래스가 물리적인. class 파일 이듯이 패키지는 물리적인 하나의 디렉토리 (폴더)이다. 따라서 A라는 패키지 안에 있는 a라는 클래스는 A폴더 안에 존재해야 한다. 폴더 안에 하위 폴더가 있듯이 패키지도 하위 패키지를 가질 수 있다. 위의 java.lang 패키지는 java라는 패키지 안에 lang이라는 하위 패키지가 있다는 말이 된다. 

 

중요 포인트는 다음과 같다. 

 1. 하나의 소스파일에는 첫 번째 문장으로써 단 한 번의 패키지 선언만 할 수 있다.

 2. 모든 클래스는 반드시 하나의 패키지 안에 속해야 한다. 

 3. 패키지는 점(. )으로 계층구조를 구성 가능하다. 예) java.lang (java - 상위패키지 / lang - 하위패키지)

 4. 패키지는 물리적으로 클래스 파일(. class)을 포함하는 하나의 디렉토리 이다. 

**2번에 추가를 좀 더 해보자면 여지까지 소스파일에 패키지를 선언하지 않아도 실행이 되었다. 이는 자바에서 기본적으로 '이름 없는 패키지(unnamed package)'를 자동으로 선언해주기 때문이다. 따라서 결국 패키지에 포함된 것이나 마찬가지 상황이 된다. 


패키지의 선언 

packege 패키지명;      

e.g)
package goginara.brisket; (고기나라 패키지 안의 brisket 패키지)

//패키지 명은 보통 소문자로 쓴다

패키지의 선언은 반드시 소스파일에서 주석과 공백을 제외한 첫 번째 문장 이어야 하고 하나만 선언할 수 있다. 

 


import 문 

다른 패키지 내의 클래스를 사용하기 위해 사용된다. (성능에 영향이 전혀 없다. 컴파일 시간만 조금 더 걸릴 뿐)

즉 컴파일러에게 소스파일에 사용된 클래스의 패키지에 대한 정보를 제공하기 때문에 매번 패키지명을 붙여 작성할 필요가 줄어든다. 

import 패키지명.클래스명;  //해당 클래스만 포함
or
import 패키지명.*;         //패키지 안의 모든 클래스 포함

패키지명.* 은 여러 클래스를 사용할 때 편리하지만 단점으로는 import 한 패키지의 수가 많을 경우 어느 클래스가 어느 패키지에 속하는지 확인이 힘들어진다. 

 

또 주의할 점으로, import문에서 클래스명 대신 .*를 쓰는 것이 하위 패키지의 클래스까지 포함하지 않는다. 해당 패키지의 클래스만 불러온다.

import 상위패키지명.*;   //상위패키지의 모든 클래스 import (하위패키지 클래스 포함 X)

import 하위패키지명.*;   //하위패키지의 모든 클래스 import

 

+tip

import로 패키지를 불러와야 한다고 했는데 java.lang 패키지는 import를 하지 않아도 해당 클래스를 쓸 수 있었다.
그 이유는 매우 자주 쓰이는 중요한 클래스들이 모인 패키지 이기 때문에 저절로 아래처럼 선언이 되어있다. 

import java.lang.*;

 


static import문

import로 클래스의 패키지명을 생략할 수 있는 것처럼, static import문을 쓰면 static 멤버를 호출할 때 해당 클래스 이름을 생략할 숭 있다. 코드도 간결해지면서 특정 클래스의 static멤버를 자주 쓴다면 아주 편리하게 쓸 수 있을 것이다. 

import static java.lang.Integer.*;
import static java.lang.Math.random;
import static java.lang.System.out;

예를 들어 위와 같이 static import를 선언하였다면 

System.out.println(Math.random());

위의 코드를 아래처럼 쓸 수 있다.

out.println(random());

 


제어자(Modifier)

제어자는 클래스, 필드, 메서드, 생성자 등에 부가적인 의미를 부여하는 키워드이다.

 

제어자의 종류는 크게 접근제어자 / 그 외의 제어자로 나뉜다.

접근 제어자 :
public       protected       default       private

그 외 제어자 :
static       final       abstract       native       transient       synchronized       volatile       strictfp

제어자는 하나의 대상에 대해 여러 제어자를 조합해 사용하는 것이 가능하다. 

예) public static void main처럼 

단, 접근 제어자는 한 번에 네 가지 중 하나만 선택 가능하다. 

 


접근 제어자

접근 제어자는 해당하는 멤버 또는 클래스를 외부에서 접근하지 못하게 제한하는 역할을 한다.

캡슐화의 데이터 보호 측면에서 핵심적인 부분으로, 접근 제어자를 통해:


 1. 외부로 불필요한 데이터 노출을 막을 수 있고



 2. 데이터가 임의로 변경되지 않도록 보호할 수 있다

 

대상에 따라 사용 가능한 접근 제어자

대상 사용가능한 접근 제어자
클래스 public, default
메서드 public, protected, default, private
멤버변수
지역변수 사용 불가 

 


접근 제어자의 제한 범위

접근 제어자 접근 제한 범위
private 같은 클래스 내에서만 접근 가능
default 같은 패키지 내에서만 접근 가능
protected 같은 패키지 내에서 + 다른 패키지의 하위 클래스 에서 접근 가능
public 접근제한 X

 

접근 제어자 같은 클래스 같은 패키지 다른 패키지
- 하위 클래스
같은 패키지 외
public O O O O
protected O O O  
default O O    
private O      

 


getter( ) / setter( )

만약 캡슐화를 하면서도 데이터의 변경을 하고 싶다면, 예를 들어 private이 붙은 객체의 변숫값을 외부에서 변경하고 싶을 때 getter( )와 setter( ) 메서드를 사용할 수 있다.

OOP에서 선호하는 방식은 외부에서 데이터로의 직접적인 접근을 막으면서, 메서드를 통해서 데이터에 접근할 수 있게 유도한다. 메서드 내에서 파라미터로 들어온 값을 if문 같은 조건문을 통해 필터링하여 설정할 수 있기 때문인데 이럴 때 setter 메서드가 쓰인다.  메서드 명 앞에 set-를 붙여 정의한다. 

getter 메서드는 setter 메서드로 설정한 객체의 데이터를 외부에서 읽을 때 사용한다. 객체 외부에서 객체 필드 값에 접근하는 건 좋지 않은데 그 이유는 다음과 같다. 

 1. 객체의 데이터에 접근이 가능하면 메서드를 통해 만들어진 데이터의 의미가 없어진다.

 2. 객체의 데이터는 어떤 메서드의 작업 결과를 누적해서 보존하는 경우가 많기에 함부로
    접근이 가능하면 위험하다. 
 

객체의 필드에 직접 접근하면 안되는 이유

이전에는 소프트웨어 개발에 있어서 오로지 문제를 해결하는 알고리즘(절차)를 중요하게 생각했다면 ( 절차지향 ) 소프트웨어가 다루는 데이터가 중요해지면서 로직과 데이터를 묶어둔 하나의

mititch.tistory.com

따라서 이상적인 OOP의 캡슐화 설계를 위해서는 필드 변수로 private를 사용하고 그 접근을 getter나 setter 메서드를 이용해야 하는 것 같다.  

들어오는 값의 종류를 개발자의 통제범위 안에 둔다' 가  보안 관점의 캡슐화의 포인트라고 봐도 될 것이다. 

 

아래 코드를 보면 setName / setAge / setIdnum 메서드로 파라미터 값이 들어가고 그걸 worker 클래스 안의 private 필드 변수에 넣는다. 그리고 getName, getAge, getIdnum 메서드로 private 필드 변수의 값을 리턴 값으로 반환한다.

public class capsule {
    public static void main(String[] args) {

        Worker worker = new Worker();

        worker.setName("DANC");
        worker.setAge(15);
        worker.setIdnum(3311);

        String name = worker.getName();
        System.out.println("name: " + name );
        System.out.println("Age: " + worker.getAge());
        System.out.println("IdNum: " + worker.getIdnum());
    }
}
class Worker
{
    private String name;    //Worker 클래스 외부에서 접근 불가
    private int age;
    private int idnum;

    public String getName(){  //멤버변수의 값
        return name;
    }
    public int getAge(){
        return age;
    }
    public int getIdnum(){
        return idnum;
    }
    public void setName(String name){  //Setter 멤버변수 값 변경
        this.name = name;
    }
    public void setAge(int age){
        if(age < 1) return;
        this.age = age;
    }
    public void setIdnum(int id){
        this.idnum = id;
    }

}
name: DANC
Age: 15
IdNum: 3311

 

저작자표시 (새창열림)

'programming > JAVA' 카테고리의 다른 글

Java - 추상화 / 인터페이스  (0) 2022.05.15
Java - 다형성  (0) 2022.05.13
Java - 상속(Inheritance)  (0) 2022.05.12
Java - 생성자  (0) 2022.05.11
Java - 메서드  (0) 2022.05.10
  • 패키지 (Package) 
  • 패키지의 선언 
  • import 문 
  • 제어자(Modifier)
  • 접근 제어자
  • 대상에 따라 사용 가능한 접근 제어자
  • 접근 제어자의 제한 범위
  • getter( ) / setter( )
'programming/JAVA' 카테고리의 다른 글
  • Java - 추상화 / 인터페이스
  • Java - 다형성
  • Java - 상속(Inheritance)
  • Java - 생성자
danc
danc
Backend 개발자를 목표로 공부 중 입니다.

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.