· 오늘 공부한 것

RestTemplate으로 Get, Post 요청과 Header에 추가적인 정보를 전달할 때 exchange매서드 사용

Open API 네이버를 검색기능을 활용하여 실습

 

 

· 공부한 내용, 궁금한 내용, 부족한 내용

client에서 보통 서버로 요청을 해서 받은 데이터로 뭔가를 활용을 했다. 하지만 요청한 서버에서도 또 다른 서버로 요청을 보내서 응답을 받아 올 수 있다. 실습에서 client 서버와 server 서버를 만들었고 각 포트를 8080과 7070으로 사용했다. 그러면 Get과 Post 요청을 살펴보자.

Get 요청

1. 먼저 RestTemplate을 주입받는다.

private final RestTemplate restTemplate;

// RestTemplateBuilder의 build()를 사용하여 RestTemplate을 생성합니다.
public RestTemplateService(RestTemplateBuilder builder) {
    this.restTemplate = builder.build();
}

 

2. 요청받은 검색어를 Query String 방식으로 Server 입장의 서버로 RestTemplate를 사용하여 요청받는다.

public ItemDto getCallObject(String query) {
    // 요청 URL 만들기
    URI uri = UriComponentsBuilder
            .fromUriString("http://localhost:7070")
            .path("/api/server/get-call-obj")
            .queryParam("query", query)
            .encode()
            .build()
            .toUri();
    log.info("uri = " + uri);

    ResponseEntity<ItemDto> responseEntity = restTemplate.getForEntity(uri, ItemDto.class);

    log.info("statusCode = " + responseEntity.getStatusCode());

    return responseEntity.getBody();
}

위와 같은 방식으로 다른 서버로 요청할 uri를 만들어서 보내면 데이터를 받아올 수 있는데 만약 받아올 데이터가 1개가 아니라 여러 개일 경우는 아래와 같이 사용한다.

public List<ItemDto> getCallList() {
    // 요청 URL 만들기
    URI uri = UriComponentsBuilder
            .fromUriString("http://localhost:7070")
            .path("/api/server/get-call-list")
            .encode()
            .build()
            .toUri();
    log.info("uri = " + uri);

    ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);

    log.info("statusCode = " + responseEntity.getStatusCode());
    log.info("Body = " + responseEntity.getBody());

    return fromJSONtoItems(responseEntity.getBody());
}

단품 조회와 다르게 여러 개일 경우 일단 String값 그대로 가져온다. 일단 sever 입장 서버의 ItemResponseDto가 어떤 형태인지를 보면 다음과 같다.

{
"items":[
		{"title":"Mac","price":3888000},
		{"title":"iPad","price":1230000},
		{"title":"iPhone","price":1550000},
		{"title":"Watch","price":450000},
		{"title":"AirPods","price":350000}
	]
}

그렇기에 String으로 넘어온 값을 다시 JSON 형태로 만들어 줘야 하기 때문에 아래와 같은 과정을 거쳤다.

public List<ItemDto> fromJSONtoItems(String responseEntity) {
    JSONObject jsonObject = new JSONObject(responseEntity);
    JSONArray items  = jsonObject.getJSONArray("items");
    List<ItemDto> itemDtoList = new ArrayList<>();

    for (Object item : items) {
        ItemDto itemDto = new ItemDto((JSONObject) item);
        itemDtoList.add(itemDto);
    }

    return itemDtoList;
}

 

post 요청

위에서 주입은 했으니 다른 서버로 RestTemplate를 사용하여 요청하는 것은 아래와 같다.

public ItemDto postCall(String query) {
    // 요청 URL 만들기
    URI uri = UriComponentsBuilder
            .fromUriString("http://localhost:7070")
            .path("/api/server/post-call/{query}")
            .encode()
            .build()
            .expand(query)
            .toUri();
    log.info("uri = " + uri);

    User user = new User("Robbie", "1234");

    ResponseEntity<ItemDto> responseEntity = restTemplate.postForEntity(uri, user, ItemDto.class);

    log.info("statusCode = " + responseEntity.getStatusCode());

    return responseEntity.getBody();
}

여기서는 get에서는 첫 번째 uri 두 번째가 전달받은 데이터와 매핑하여 인스턴스화할 클래스의 타입이었는데 post요청의 경우 두 번째가 HTTP Body에 넣어줄 데이터이다.

 

그러면 Header에 정보를 추가하고 싶을 때 다음과 같이 exchange 매서드의 첫 번째 파라미터에 RequestEntity 객체를 만들어 전달해 주면 된다. 이 안에 uri, header, body의 정보를 모두 담아 전달할 수 있다.

public List<ItemDto> exchangeCall(String token) {
    // 요청 URL 만들기
    URI uri = UriComponentsBuilder
            .fromUriString("http://localhost:7070")
            .path("/api/server/exchange-call")
            .encode()
            .build()
            .toUri();
    log.info("uri = " + uri);

    User user = new User("Robbie", "1234");

    RequestEntity<User> requestEntity = RequestEntity
            .post(uri)
            .header("X-Authorization", token)
            .body(user);

    ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);

    return fromJSONtoItems(responseEntity.getBody());
}

 

 

Naver Open ApI

이번 실습에서 네이버 open api를 활용했는데 여기에서 제공하는 것들은 아래와 같다. 나는 이 중에서 검색기능을 사용하였다.

네이버에서 제공하는 Open API

 

일단 사이트에서 애플리케이션을 로컬로 등록하는 과정을 거쳤다.

그리고 JSON 형태로 반환받기 위해 요청 URL은 아래에 있는 것을 사용했다.

curl "https://openapi.naver.com/v1/search/shop.json?query=%EC%A3%BC%EC%8B%9D&display=10&start=1&sort=sim" \
    -H "X-Naver-Client-Id: {애플리케이션 등록 시 발급받은 클라이언트 아이디 값}" \
    -H "X-Naver-Client-Secret: {애플리케이션 등록 시 발급받은 클라이언트 시크릿 값}" -v

query에 검색할 검색어가 들어가게 되고 요청 시 헤더에 애플리케이션 등록할 때 발급받은 아이디 값과 시크릿 값도 들어가야 한다.

그러면 위에서 사용한 RestTemplate으로 코드를 아래와 같이 구현하였다.

먼저 controller에서 NaverApiService를 주입한다.

@RestController
@RequestMapping("/api")
public class NaverApiController {

    private final NaverApiService naverApiService;

    public NaverApiController(NaverApiService naverApiService) {
        this.naverApiService = naverApiService;
    }

    @GetMapping("/search")
    public List<ItemDto> searchItems(@RequestParam String query)  {
        return naverApiService.searchItems(query);
    }
}

그리고 service에서 네이버 검색 api를 보낸다.

@Slf4j(topic = "NAVER API")
@Service
public class NaverApiService {

    private final RestTemplate restTemplate;

    public NaverApiService(RestTemplateBuilder builder) {
        this.restTemplate = builder.build();
    }

    public List<ItemDto> searchItems(String query) {
        // 요청 URL 만들기
        URI uri = UriComponentsBuilder
                .fromUriString("https://openapi.naver.com")
                .path("/v1/search/shop.json")
                .queryParam("display", 15)
                .queryParam("query", query)
                .encode()
                .build()
                .toUri();
        log.info("uri = " + uri);

        RequestEntity<Void> requestEntity = RequestEntity
                .get(uri)
                .header("X-Naver-Client-Id", "Client-Id")
                .header("X-Naver-Client-Secret", "Client-Secret")
                .build();

        ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);

        log.info("NAVER API Status Code : " + responseEntity.getStatusCode());

        return fromJSONtoItems(responseEntity.getBody());
    }

여기서 exchange 메서드를 사용해서 헤더에 아이디와 시크릿 값을 넣어서 보내주고 있다. 그리고 받아온 값이 String이므로 fromJSONtoItems 매서드로 변환하는 과정을 거쳐 itemDto 형태의 리스트로 값을 가져오고 있다.

 

 

 

· 오늘 서칭 한 자료

https://developers.naver.com/docs/serviceapi/search/shopping/shopping.md#%EC%87%BC%ED%95%91

 

검색 > 쇼핑 - Search API

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

developers.naver.com

 

 

· 느낀 점

- 만든 서버로 모든 요청을 해결하는 것이 아니라 외부 서버로 다시 요청을 해서 받아오는 형태로 개발해도 된다. (개발 범위의 확장)

- 이미 만들어져 있는 오픈 api를 활용해서 프로젝트 개발에 사용할 수 있을 거 같다.

- 특히 거의 모든 페이지에서 로그인의 경우 카카오, 네이버, 구글 로그인을 포함하고 있기 때문에 필수적으로 사용할 줄 알아야 한다고 느꼈다.

반응형

'Today I Learned' 카테고리의 다른 글

2023-11-27 TIL  (0) 2023.11.27
2023-11-16 TIL  (0) 2023.11.16
2023-11-14 TIL  (0) 2023.11.14
2023-11-13 TIL  (0) 2023.11.13
2023-11-07 TIL  (0) 2023.11.07

· 오늘 공부한 것

- 접근 불가 페이지 만들기

- Validation

 

 

· 공부한 내용, 궁금한 내용, 부족한 내용

접근 불가 페이지

회원 가입을 할 때 일반유저(USER)와 관리자(ADMIN)를 구분했었다. 그러면 이것을 가지고 일반유저가 관리자권한이 있는 페이지에 접근하려 할 때 막는 과정이 필요하다. 유저에게는 접근불가 페이지라는 것을 보여주는 html을 띄워줘야 한다. 전에 강의를 통해 만든 UserDetailsImple에서 권한 설정이 가능했다. 권한 이름에는 규칙이 있는데 "ROLE_" 로 시작해야 한다. 그래서 UserRoleEnum에서 "ROLE_USER"와 "ROLE_ADMIN"으로 만들어 두었다.

public class UserDetailsImpl implements UserDetails {
		// ...

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        UserRoleEnum role = user.getRole();
        String authority = role.getAuthority();

        SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(authority);
        Collection<GrantedAuthority> authorities = new ArrayList<>();
        authorities.add(simpleGrantedAuthority);

        return authorities;
    }
}

 

그리고 controller 에서  @Secured 애너테이션으로 권한 설정이 가능하다.

    @Secured(UserRoleEnum.Authority.ADMIN) // 관리자용
    @GetMapping("/products/secured")
    public String getProductsByAdmin(@AuthenticationPrincipal UserDetailsImpl userDetails) {
        System.out.println("userDetails.getUsername() = " + userDetails.getUsername());
        for (GrantedAuthority authority : userDetails.getAuthorities()) {
            System.out.println("authority.getAuthority() = " + authority.getAuthority());
        }

        return "redirect:/";
    }

 

이렇게 애너테이션을 걸어두었으면 활성화를 해야 하는데 이것은 전에 만든 WebSecurityConfig 파일에서 @EnableGlobalMethodSecurity(securedEnabled = true) 해주면 된다.

@Configuration
@EnableWebSecurity // 스프링 Security 지원을 가능하게 함
@EnableGlobalMethodSecurity(securedEnabled = true) // @Secured 애너테이션 활성화
public class WebSecurityConfig {
	// ...
    http.exceptionHandling((exceptionHandling) ->
        exceptionHandling.accessDeniedPage("/forbidden.html")
    );
}

그러면 미리 만들어 둔 resources/static/forbidden.html 에 있는 파일을 보여준다.

 

Validation

프로그래밍을 하는데에 있어서 가장 중요한 부분으로 특히 null 값에 대한 부분에서 NullPointerException 오류가 발생할 수 있기 때문에 검증 과정이 필요하다.

그래서 Spring에는 Bean Validation 을 제공하고 있다. 밑에는 Bean Validation에서 제공하는 애너테이션의 일부이다.

@NotNull null, “” 불가
@NotEmpty null, “”. “ “ 불가
@NotBlank null, “”. “ “ 불가
@Size 문자 길이 측정
@Max 최대값
@Min 최소값
@Positive 양수
@Negative 음수
@Email E-mail 형식
@Pattern 정규 표현식

 

SignupRequestDto 에 validation을 적용한 모습이다.

public class SignupRequestDto {
    @NotBlank // 공백금지
    private String username;

    @NotBlank
    private String password;

// 정규표현식 조건
    @Pattern(regexp = "^[a-zA-Z0-9_!#$%&'*+/=?`{|}~^.-]+@[a-zA-Z0-9.-]+$")
    @NotBlank
    private String email;

    private boolean admin = false;
    private String adminToken = "";
}

이메일 부분 검증할 때 사용한 정규표현식은 아래와 같은 단계로 이해할 수 있다.

// @ 기호를 확인합니다. 기호 앞과 뒤 문자는 신경쓰지 않습니다.
String regx1 = "^(.+)@(.+)$";

// @ 기호 앞에 오는 방식에 제한을 추가합니다.
// A-Z, a-z, 0-9, ., _ 를 사용할 수 있습니다.
String regx2 = "^[A-Za-z0-9+_.-]+@(.+)$";

// 이메일 형식에 허용되는 문자를 모두 사용할 수 있습니다.
String regx3 = "^[a-zA-Z0-9_!#$%&'*+/=?`{|}~^.-]+@[a-zA-Z0-9.-]+$";

 

 

· 오늘 서칭 한 자료

 

 

 

· 느낀 점

- 접근 불가 페이지를 만들어서 유저에게 알려주는 것도 유저들에게 있어서 서비스 만족도를 높일 수 있다.

- 보통 결과가 없는 404페이지를 많이 봤었는데 403페이지도 신경 써야겠다.

- 검증 부분을 프런트에서 하고 넘기면 될 것이라고 생각하고 있었는데 백엔드에서도 검증 부분의 필요성을 느꼈다. 검증을 확실히 할수록 빈틈이 없기 때문에 무조건 하면 좋다고 생각한다.

반응형

'Today I Learned' 카테고리의 다른 글

2023-11-16 TIL  (0) 2023.11.16
2023-11-15 TIL  (0) 2023.11.15
2023-11-13 TIL  (0) 2023.11.13
2023-11-07 TIL  (0) 2023.11.07
2023-11-06 TIL  (0) 2023.11.06

· 오늘 공부한 것

Spring Security 프레임 워크

로그인

 

 

· 공부한 내용, 궁금한 내용, 부족한 내용

// Security
implementation 'org.springframework.boot:spring-boot-starter-security'

spring security 프레임워크를 build.gradle 에 추가한 모습이다. 

전에 서버에 요청을 하게 되면 controller에서 맵핑이 되어 들어갔는데 그전에 DispatcherServlet을 통과하게 된다. 여기서 이 보다 더 이전 단계가 앞에서 배운 Filter 부분인데 Spring Security도 이것을 사용한다.

Security가 Filter에서 사용되고 있는 모습이다.

 

Form login 기반을 사용할 때 username과 password를 확인하여 인증한다.

  1. 사용자가 username과 password를 제출하면 UsernamePasswordAuthenticationFilter는 인증된 사용자의 정보가 담기는 인증 객체인 Authentication의 종류 중 하나인 UsernamePasswordAuthenticationToken을 만들어 AuthenticationManager에게 넘겨 인증을 시도합니다.
  2. 실패하면 SecurityContextHolder를 비웁니다.
  3. 성공하면 SecurityContextHolder에 Authentication를 세팅합니다.

UsernamePasswordAuthenticationFilter는 Spring Security의 필터인 AbstractAuthenticationProcessingFilter를 상속한 Filter이다.
SecurityContext는 인증이 완료된 사용자의 상세 정보(Authentication)를 저장한다.

 

Spring Security를 사용한 로그인 처리 과정이다.

WebSecurityConfig 파일에서 아래와 같은 코드를 확인한다.

requestMatchers("/api/user/**").permitAll() 
인증이 필요 없는 URL들을 간편한게 허가할 수 있다.

anyRequest().authenticated()
인증이 필요한 URL들도 간편하게 처리할 수 있다.

 

UserDetailsService 인터페이스를 상속받은 UserDetailsServiceImpl에서 user 정보를 DB에서 가져와서 UserDetails를 상속받은 UserDetailsImpl 객체에 넣어준다. 이러면 로그인을 하게 되면 로그인한(인증된) 유저의 정보가 UserDetailsImpl에 담겨 있게 된다.

이것을 가져와서 사용을 할 때 controller에서 어노테이션을 사용해 주면 되는데 그것이 @AuthenticationPrincipal이다.

@Controller
@RequestMapping("/api")
public class ProductController {

    @GetMapping("/products")
    public String getProducts(@AuthenticationPrincipal UserDetailsImpl userDetails) {
        // Authentication 의 Principal 에 저장된 UserDetailsImpl 을 가져옵니다.
        User user =  userDetails.getUser();
        System.out.println("user.getUsername() = " + user.getUsername());

       return "redirect:/";
    }
}

 

 

 

 

· 오늘 서칭 한 자료

 

 

· 느낀 점

- Spring Security를 사용하면 쉽게 인증을 처리하고 로그인한 유저의 정보를 가져올 수 있었다. 하지만... 혼자서 적용할 수 있을지 의문이 든다.

- 코드스니펫 딸깍... 복붙이다... 복습하며 코드 한 줄씩 이해하는 과정이 필요할 거 같다.

- Filter를 잘 정리해 두면 controller단으로 넘어가기 전에 많은 것을 처리할 수 있을 거 같다.

반응형

'Today I Learned' 카테고리의 다른 글

2023-11-15 TIL  (0) 2023.11.15
2023-11-14 TIL  (0) 2023.11.14
2023-11-07 TIL  (0) 2023.11.07
2023-11-06 TIL  (0) 2023.11.06
2023-11-03 TIL  (0) 2023.11.03

· 오늘 공부한 것

빈(bean)에 대한 학습

 

 

· 공부한 내용, 궁금한 내용, 부족한 내용

Bean : Spring이 관리하는 객체

이전 주차에서 Bean을 등록하고 사용하는 방법을 알아보았다.

여기서 @Component를 사용해서 Bean을 자동으로 등록하는 거나 @Controller, @Service와 같이 역할을 나타내며 등록하는 것을 알아보았는데 이번에는 수동으로 등록하는 방법을 학습했다. 일반적으로는 당연히 자동으로 등록하는 것이 좋으나 기술적인 문제나 공통적인 관심사를 처리할 때 사용하는 객체들은 수동으로 등록하는 것이 좋다.

수동 등록 방법

  • Bean으로 등록하고자 하는 객체를 반환하는 메서드를 선언하고 @Bean을 설정한다.
  • Bean을 등록하는 메서드가 속한 해당 클래스에 @Configuration을 설정한다.
  • Spring 서버가 돌 때 Spring IoC 컨테이너에 Bean으로 저장된다.

 

그러면 같은 타입의 Bean이 있을 때 처리하는 방법을 알아보았다.

  • @Primary 사용하기
    • 이것을 추가하면 같은 타입의 Bean이 여러 개 있어도 우선순위를 가진다.
  • @Qualifier 사용하기
    • 이것을 사용할 때는 name을 지정해줘야 한다.
  • 위에 두 개가 동시에 사용되었다면 Qualifier가 우선순위를 가진다.

 

· 오늘 서칭 한 자료

강의자료

 

 

· 느낀 점

- 앞에 내용들을 확실히 이해하고 넘어가야 할 거 같다.

- 뒤로 갈수록 많은 내용들이 쌓이고 있는데 확실히 이해했다고 느껴지지 않는다.

- 일단 강의를 듣고 빨리 부족한 부분을 채워야겠다.

반응형

'Today I Learned' 카테고리의 다른 글

2023-11-14 TIL  (0) 2023.11.14
2023-11-13 TIL  (0) 2023.11.13
2023-11-06 TIL  (0) 2023.11.06
2023-11-03 TIL  (0) 2023.11.03
2023-10-26 TIL  (0) 2023.10.26

· 오늘 공부한 것

게시판 서버 만들기 => 필수 구현 기능(CRUD) 작업

강의에서 배운 내용을 따라가면 구현

 

 

· 공부한 내용, 궁금한 내용, 부족한 내용

sprint 입문 2주 차까지 내용을 바탕으로 개인과제를 수행하였다. 강의에서 나온 memo프로젝트로 CRUD를 한 것과 유사해서 많은 부분을 복습하며 진행하였다. 필수로 구현해야 하는 부분은 5가지였다.

  1.  게시글 작성 기능 (create)
  2. 선택한 게시글 조회 기능 (read)
  3. 게시글 목록 조회 기능 (read)
  4. 선택한 게시글 수정 기능 (update)
  5. 선택한 게시글 삭제 기능 (delete)

3 Layer Architecture

전에 작성한 Use Case Diagram과 위의 그림의 흐름을 생각하며 진행을 하였다. 먼저 Client가 무언가를 요청을 했을 때 api 구분을 controller에서 진행을 해주었다. 어떤 메서드로 왔는지 무슨 데이터가 같이 왔는지를 보면서 구분을 해주었다. 그리고 여기서 중요한 점은 client관점에서 보면 controller -> service -> repository -> database 순으로 갔다가 오는 것으로 보이지만 작업을 할 때는 DI(의존성 주입)을 통해 IoC(제어의 역전)을 생각하며 진행을 했다. 이것에 대한 부분은 전에 정리한 부분이 있다. https://lsj135779.tistory.com/63

  @PutMapping("/post/{id}")
    public PostResponseDto updatePost(@PathVariable Long id, @RequestBody PostRequestDto requestDto) {
        return postService.updatePost(id, requestDto);
    }

5가지 중에 많은 내용을 포함하고 있는 update인 게시글 수정 요청이 들어왔을 때 controller에서 받는 부분이다. put메서드라고 매핑을 통해 api를 입력해 주고 필요한 게시글의 id는 Path Variable 방식으로 받았고, 나머지 변경가능한 내용(title, username, contents)과 확인을 위한 password는 body로 전달받았다. 그래서 @

PathVariable

과 @RequestBody를 사용했다. 그리고 코드에 나오지 않았지만 제어의 흐름이 역전되었기 때문에 위에서 postService 객체를 만들어서 사용하고 있다.

 

    @Transactional
    public PostResponseDto updatePost(Long id, PostRequestDto requestDto) {
        Post post = findMemo(id);
        // 요청할 때 비밀번호와 DB에 저장된 비밀번호가 일치한지 확인
        if (Objects.equals(post.getPassword(), requestDto.getPassword())) {
            post.update(requestDto);
            PostResponseDto responseDto = new PostResponseDto(post);
            return responseDto;
        } else {
            PostResponseDto responseDto = new PostResponseDto("해당 게시글의 비밀번호와 일치하지 않습니다.");
            return responseDto;
        }
    }
    
    private Post findMemo(Long id) {
    return postRepository.findById(id).orElseThrow(() ->
            new IllegalArgumentException("선택한 게시글은 존재하지 않습니다.")
    );

다음은 service에서 변경내용을 update 하는 로직을 구현한 것이다. 해당 id로 게시글을 찾고 요청을 통해 받아온 비밀 번호와 일치한 지 확인 후에 update를 진행한다. 여기서도 postRepository를 만들어서 사용하고 있다. 그리고 @Transactional 이 붙어 있는데 이것을 해야 변경을 감지해서 update가 가능하다. JPA를 사용하여 DB에 데이터를 수정하고 있기 때문이다.

public interface PostRepository extends JpaRepository<Post, Long> {
    List<Post> findAllByOrderByCreatedAtDesc();
}

마지막으로 repository의 모습인데 JPA를 사용하고 있는 것을 확인할 수 있다. JpaRepository<"@Entity 클래스", "@Id의 데이터 타입">을 상속받는 interface형태이다.

 

 

· 오늘 서칭 한 자료

https://github.com/lsj135779/sparta-post

 

GitHub - lsj135779/sparta-post: 내일배움캠프 개인과제 게시글 CRUD

내일배움캠프 개인과제 게시글 CRUD. Contribute to lsj135779/sparta-post development by creating an account on GitHub.

github.com

 

 

· 느낀 점

강의를 듣는 것도 중요하지만 스스로 해보면서 체득하는 것이 가장 중요하다. 그리고 나만의 언어로 설명할 수 있을 정도가 되어야 완전히 이해했다고 말할 수 있다. (나중에 면접 때 중요!)

입문단계의 과제이기에 강의를 따라가면 충분히 수행할 수 있었지만 처음부터 혼자 했다면 어려운 부분이 많았을 거 같다.

전체적인 흐름을 이해하고 작업을 하는 것이 중요하다. (사전작업이 있는 가장 큰 이유!)

반응형

'Today I Learned' 카테고리의 다른 글

2023-11-13 TIL  (0) 2023.11.13
2023-11-07 TIL  (0) 2023.11.07
2023-11-03 TIL  (0) 2023.11.03
2023-10-26 TIL  (0) 2023.10.26
2023-10-23 TIL  (0) 2023.10.23

· 오늘 공부한 것

프로젝트 진행 시 사전에 진행해야 할 것들

  1. Use Case Diagram
  2. API 명세서
  3. ERD (Entity Relationship Diagram)

 

· 공부한 내용, 궁금한 내용, 부족한 내용

개인과제를 진행하기 전에 사전에 작업할 것들이 필요했다. 사전에 정하지 않고 바로 시작하면 데이터의 흐름도 파악하지 못하고 지금은 개인과제이지만 팀단위로 들어가면 서로 간의 약속이 없어서 많은 충돌이 발생할 수 있다. 그래서 첫 번째로 진행한 것은 Use Case Diagramd인데 이것은 사용자가 내가 만든 시스템에서 무엇을 할 수 있는지와 이것들이 어떻게 진행되는지 흐름을 파악할 수 있는 것이다. 전에 Figma를 사용한 적 있는데 여기서 prototype을 제작하면서 직접 사용자가 무언가를 클릭했을 때 무엇이 진행되는지 알 수 있었다. 하지만 이번에는 서버를 만드는 작업이기에 간단한 다이어그램으로 표현을 해주었다. 간단한 그림이었지만 사용하는데 약속이 있었다. 크게 구성 요소로는 시스템, 액터, 유스케이스, 관계로 나눌 수 있다.

시스템은 개발하고자 하는 것으로 여기서는 게시판 서버라고 생각할 수 있다. 그리고 이것은 사각형의 형태로 표시하고 상단에 시스템이름을 작성한다.

액터는 2가지로 나눌 수 있는데 primary actor, secondary actor이다.

  • 프라이머리 액터 (Primary Actor) : 시스템을 사용하고, 직접 이득을 보는 액터이며 졸라맨으로 표기합니다. 보통 시스템의 왼쪽에 표시합니다.
  • 세컨더리 액터 (Secondary Actor) : 프라이머리 액터가 목적을 달성하기 위해 도움을 주는 액터이며 사각형 박스에 <<actor>>를 입력하여 표기합니다. 보통 시스템의 오른쪽에 표시합니다.

유스케이스는 시스템 내에서 작업을 수행하기 위한 행위를 나타낸다. 보통 타원형으로 표현한다.

마지막으로 관계는 유스케이스 간의 의존성을 나타내며 다음과 같이 나눌 수 있다.

  • 연관간계 (Association)
    • 유스케이스 간의 상호작용을 하고 있다고 보고 실선으로 나타낸다.
  • 포함관계 (Include)
    • 하나의 유스케이스가 실행되면 반드시 실행되는 것을 나타낸다.
    • 화살표를 그리고 중앙에 <<include>>를 표시한다.
  • 확장관계 (Extend)
    • 하나의 유스케이스가 실행되면 특정 상황에만 실행되는 것을 나타낸다.
    • 화살표를 그리고 중앙에 <<extend>>를 표시한다.
  • 일반화관계 (Generalization)
    • 부모 유스케이스와 자식 유스케이스 간의 상속관계를 나타낸다.
    • 자식 유스케이스들은 상속을 받았기 때문에 부모 유스케이스가 해당된 모든 포함, 확장관계를 만족해야 한다.

 

그다음으로 수행한 작업은 API 명세서를 작성한 것이다. 이것은 API명, 요청 값(파라미터), 반환 값, 인증/인가 방식, 데이터 및 전달 형식 등 API를 정확하게 호출하고 그 결과를 명확하게 해석하는데 필요한 정보들을 일관된 형식으로 기술한 것을 의미한다.

전에 GitBook이라는 사이트에서 작성한 경험이 있는데 한글칠 때 계속 깨지는 현상이 있어서 다른 곳에서 작성하고 계속 복붙을 해서 고생했었다. 그래서 이번에는 postman에서 작성을 하였다. postman은 직접 요청을 해서 반응도 바로 볼 수 있어서 훨씬 능률이 올랐다. 이번 개인 과제는 기본적인 CRUD만을 다루었기 때문에 API 5개로 끝낼 수 있었다.

마지막으로 수행한 것은 ERD를 작성하는 것인데 이것은 데이터베이스의 table(entity)의 속성(attribute)과 관계(relationship)를 나타낸 것이다. 이것은 전에 사용했던 dbdiagrm 사이트에서 수행했다. 먼가 코드를 작성해서 table들을 나타내야 하지만 한 번 익히면 익숙한 내용이어서 쉽게 따라 할 수 있다. 그리고 작성한 코드에 따라 바로 눈으로 볼 수가 있어서 틀려도 바로바로 수정할 수 있었다. 이번 과제는 테이블 1개로 끝낼 수 있었기에 간단하게 완료했지만 나중에 테이블 간의 관계가 들어가면 복잡해질 것 같다.

 

 

· 오늘 서칭 한 자료

https://www.figma.com/design-systems/?utm_source=google&utm_medium=cpc&utm_campaign=20410937970&utm_term=&utm_content=667739942608&gclid=Cj0KCQiAuqKqBhDxARIsAFZELmL4OoxBNhIHWbPn6GMBIOeOSig6OzIOy3CwwAgDHdvtlDAR5igTBaUaAjpTEALw_wcB

 

Design System Software | Figma

Design, manage, and deploy your design system components with collaboration and control at scale with Figma. Get started building design systems today.

www.figma.com

https://app.diagrams.net/

 

Flowchart Maker & Online Diagram Software

Flowchart Maker and Online Diagram Software draw.io is free online diagram software. You can use it as a flowchart maker, network diagram software, to create UML online, as an ER diagram tool, to design database schema, to build BPMN online, as a circuit d

app.diagrams.net

https://devjaewoo.tistory.com/15

 

[UML] 유스케이스 다이어그램 (Use-case Diagram)

유스케이스 다이어그램이란? 사용자(Actor)의 관점에서 시스템의 기능, 상호작용과 그들 간의 관계를 표현합니다. 유스케이스 다이어그램을 사용하는 이유는 다음과 같습니다. 제품과 상호작용

devjaewoo.tistory.com

https://www.gitbook.com/

 

GitBook – Knowledge management simplified

GitBook is a knowledge management tool for technical teams. It simplifies knowledge sharing, with an intuitive editor and docs-as-code support. Sign up for free today!

www.gitbook.com

https://learning.postman.com/docs/publishing-your-api/api-documentation-overview/

 

Document your APIs in Postman | Postman Learning Center

Document your APIs in Postman: documentation for Postman, the collaboration platform for API development. Create better APIs—faster.

learning.postman.com

https://dbdiagram.io/home

 

dbdiagram.io - Database Relationship Diagrams Design Tool

 

dbdiagram.io

 

 

· 느낀 점

- 무언가를 진행할 때 사전준비는 정말 중요하다고 생각한다.

- 나중에 팀단위로 뭔가를 수행할 때 사전에 여러 가지 약속을 하고 시작하면 프로젝트할 때 굉장히 좋을 거 같다고 느꼈다.

- 하지만 그만큼 사전단계에 시간이 많이 쓰게 될 거 같다. (중요한 만큼 시간을 갈자!!)

반응형

'Today I Learned' 카테고리의 다른 글

2023-11-07 TIL  (0) 2023.11.07
2023-11-06 TIL  (0) 2023.11.06
2023-10-26 TIL  (0) 2023.10.26
2023-10-23 TIL  (0) 2023.10.23
2023-10-18 TIL  (0) 2023.10.19

· 오늘 공부한 것

팀과제

  • 상품삭제기능
  • 완료 주문목록 기능

 

 

· 공부한 내용, 궁금한 내용, 부족한 내용

개인과제로 진행했던 키오스크 만들기에서 이번에는 팀과제로 좀 더 추가적인 작업을 진행하였다. 그래서 개인이 아닌 팀 프로젝트이기 때문에 먼저 개인들이 진행한 코드리뷰를 진행하였다. 왜냐하면 가장 알맞은 코드로 처음 틀을 작고 시작하기로 했기 때문이다. 그 이후에 해야 할 작업을 정하고 역할을 나누었는데 나는 그중에서도 상품삭제기능과 완료 목록 기능을 하게 되었다. 이 두 기능은 관리자로 들어갔을 때 수행할 수 있는 기능이기에 기존 개인과제에서 진행한 부분과 다른 곳에서 진행하였다.

상품삭제 기능

ManagerApp.java

    private static void deleteProduct() {
        Scanner sc = new Scanner(System.in);
        Menu.printId(KioskApp.menus);
        System.out.println("\u001B[32m[ 상품 삭제 ]\n" +
                "삭제할 상품의 ID를 입력해 주세요\u001B[0m"
        );
        String productId = sc.nextLine();
        Boolean removeCheck = Product.deleteProduct(productId);
        if (removeCheck) {
            System.out.println("\u001B[34m해당상품이 삭제되었습니다\u001B[0m");
        } else {
            System.out.println("\u001B[31m해당상품은 상품목록에 없습니다\u001B[0m");
        }
    }

위에 코드에서 Product 객체에 있는 deleteProduct 메서드를 실행하고 있다. 이것의 출력값은 boolean으로 true면 삭제가 진행한 것이고 false면 삭제하지 못한 것이다. 그러면 deleteProdcut 메서드를 보면 아래와 같다.

 

Product.java

   public static Boolean deleteProduct(String target) {
        ArrayList<Menu> menus = KioskApp.menus;
        String menuId = target.split("#")[0];
        String productId = target.split("#")[1];
        Boolean removeCheck = false;
        for (int i = 0; i < menus.size(); i++) {
            if (Objects.equals(menus.get(i).getId(), menuId)) { // 같은 메뉴
                for (int j = 0; j < menus.get(i).products.size(); j++) {
                    int productIdx;
                    if (Objects.equals(menus.get(i).products.get(j).getId(), productId)) { // 같은 상품
                        productIdx = j;
                        menus.get(i).products.remove(j);
                        removeCheck = true;
                        break;
                    }
                }
                // 메뉴안에 모든 상품이 삭제된 경우 해당 메뉴도 삭제
                if (menus.get(i).products.isEmpty()) {
                    menus.remove(i);
                }
            }
            if (removeCheck) break; // 불필요한 반복문 중지
        }
        return removeCheck;
    }

매개변수로 들어온 productId는 "#"을 기준으로 앞에는 menuId 뒤에는 productId 형태로 구성되어 있다. 그리고 이것들을 가지고 같은 메뉴가 있는지 확인하고 메뉴 안에 같은 상품이 있으면 삭제하는 작업을 진행한다. 그리고 여기서 상품을 삭제했을 때 메뉴 안에 상품이 1개도 없을 경우 해당 메뉴도 삭제하는 작업도 진행하였다.

 

완료 주문 목록 기능

이 기능은 기존 kiosk앱에서 주문 완료를 하는 기능이 있었기에 완료된 목록을 과제에서 주어진 형태로 나타내주는 작업만 해주면 되었다.

    private static void completeOrderList() {
        ArrayList<Order> completedOrders = KioskApp.completedOrders;
        double total = 0;
        System.out.println("\u001B[32m[ 완료 주문목록 ]\u001B[0m");
        for (Order order : completedOrders) {
            System.out.println("------------------------------");
            System.out.println("\u001B[36m대기 번호 : \u001B[0m" + order.getWaitingNum());
            System.out.print("\u001B[36m주문 상품 목록 : \u001B[0m| ");
            for(Product product : order.instanceMenus){
                System.out.print(product.getName() + " |");
                total = total + product.getPrice() * product.getCount();
            }
            System.out.println("\n\u001B[36m주문 총 가격 : W \u001B[0m" + total);
            total = 0;
            System.out.println("\u001B[36m주문 일시 : \u001B[0m" + order.getTime());
            System.out.println("\u001B[36m요청 사항 : \u001B[0m" + order.getOffer());
            System.out.println("\u001B[36m완료주문 일시 : \u001B[0m" + order.getCompleteTime());
            System.out.println("------------------------------");
        }
    }

과제에서 원하는 형태는 다음과 같다.

  1. 대기 번호
  2. 주문 상품 목록
  3. 주문 총 가격
  4. 주문 일시
  5. 요청 사항
  6. 완료주문 일시(날짜는 ISO 8601 형식으로 조합된 UTC 날짜 및 시간 예) 2016-10-27T17:13:40+00:00

 

· 오늘 서칭 한 자료

 

 

· 느낀 점

- 과제 진행 시 각자 맡은 역할을 구현하는 식으로 했기 때문에 나는 후반부에 작업을 시작할 수 있었다. 그렇기에 다른 사람이 만든 코드를 이해하는 작업도 필요했기에 소통의 중요성을 느꼈다.

- 내가 작업을 하고도 다른 사람이 이해할 수 있는 코드로 짜는 것이 중요하다고 느꼈다.

- 누가 읽어도 책 읽듯이 읽어지는 코드가 좋은 코드라고 생각한다.

반응형

'Today I Learned' 카테고리의 다른 글

2023-11-06 TIL  (0) 2023.11.06
2023-11-03 TIL  (0) 2023.11.03
2023-10-23 TIL  (0) 2023.10.23
2023-10-18 TIL  (0) 2023.10.19
2023-10-17 TIL  (0) 2023.10.18

· 오늘 공부한 것

개인 과제 키오스크 만들기

 

 

· 공부한 내용, 궁금한 내용, 부족한 내용

객체를 사용하는 데 있어서 아직 익숙하지 않아 제대로 활용을 못했다. 재사용이라는 것을 생각했어야 했는데 과제에서 요구하는 클래스를 만들고 한 번 생성한 뒤 그것만 계속 사용하는 식으로 코딩을 했다. 아래 사진처럼 메뉴의 이름이나 설명을 리스트가 아닌 String으로 선언하고 여러 객체를 만들어 따로 보관하는 식으로 했으면 더 좋았을 거 같다. 과제에서 안내하는 순서에 따라 코딩을 진행했는데 뒤에서 구조가 계속 꼬였다. 전체적인 틀을 보고 무엇을 클래스로 잡아놓고 할지 생각해 보고 시작하는 게 좋을 거 같다. 그리고 처음 기본 데이터를 어디에 저장해 놓고 사용할지 몰라서 일단 Main에 넣었는데 코딩한 방식이 화면 출력 할 때마다 각 데이터를 다시 넣는 식이여서 비효율적으로 보인다. 일단 필수 요구사항들을 모두 구현을 했지만 코드를 전체적으로 갈아엎어야 할 거 같다. 객체 생성하는 것을 두려워하지 말자!

재사용하는 메서드인지는 나중에 생각해 보고 일단 해당 클래스와 관련된 메소는 해당 클래스에서 만들어서 사용하는 식으로 진행해야 할 거 같다. 이번 개인과제를 하다 보니 클래스에 메서드를 넣지 않고 계속 메인에서만 적다 보니 메인만 코드가 길어지는 사태가 발생했다. 그리고 중간에 3초 딜레이를 요구하는 부분이 있어서 일단 서치 해서 Thread.sleep()을 사용하긴 했는데 예외처리를 요구했다. 이 부분은 다시 강의자료를 보면서 공부할 필요가 있어 보인다.

메뉴라는 클래스를 만든 모습

 

 

· 오늘 서칭 한 자료

https://github.com/lsj135779/sparta-kiosk

 

GitHub - lsj135779/sparta-kiosk: 내일배움캠프 개인과제 키오스크 만들기

내일배움캠프 개인과제 키오스크 만들기. Contribute to lsj135779/sparta-kiosk development by creating an account on GitHub.

github.com

https://www.delftstack.com/ko/howto/java/how-to-delay-few-seconds-in-java/

 

Java에서 몇 초를 지연시키는 방법

이 게시물은 Java에서 지연을 만드는 방법에 관한 것입니다.

www.delftstack.com

 

· 느낀 점

객체를 이해했다고 생각했는데 막상 실제 코딩에 사용해 보니 제대로 활용을 못한 거 같다.

자바와 친해지려면 먼저 기본타입들 위주로 사용하는 게 좋다고 느꼈다.

코딩을 잘하려면 남들이 내 코드를 쉽게 읽을 수 있도록 만드는 게 중요하다. (내 코드를 나만 이해할 수 있다? NO!!!)

지금 단계에서는 주석을 많이 사용하자!!

계속 사용해 보면서 체화시켜야겠다.

반응형

'Today I Learned' 카테고리의 다른 글

2023-11-03 TIL  (0) 2023.11.03
2023-10-26 TIL  (0) 2023.10.26
2023-10-18 TIL  (0) 2023.10.19
2023-10-17 TIL  (0) 2023.10.18
2023-10-16 TIL  (0) 2023.10.17

· 오늘 공부한 것

java 컬렉션에 대해서 학습

 

 

· 공부한 내용, 궁금한 내용, 부족한 내용

Collection 에는 List, Set, Queue, Map이 있다.

List

  • 순서가 있는 데이터의 집합 (데이터 중복 허용)
  • ArrayList, LinkedList, Stack 이 있다.
    • ArrayList : 배열처럼 일렬로 데이터를 저장하고 조회하여 인덱스로 값을 하나씩 조회할 수 있다.
    • Array (배열)은 크기를 고정하여 생성하는 정적배열이고 ArrayList 는 크기가 가변적으로 늘어나는 동적배열이다
// 선언
ArrayList<Integer> intList

// 생성
new ArrayList<Integer>();

// 값 추가
intList.add(추가할 값)

// 값 수정
intList.set(수정할 인덱스, 수정할 값)

// 값 삭제
intList.remove(삭제할 인덱스)

// 전체 출력
intList.toString()

// 전체 제거
intList.clear()
    • LinkedList : 메모리 남는 공간 여러 장소에 실제값을 담아놓고 주소값으로 목록을 구성하고 저장한다.
    • 실제값을 나누어서 담았기 때문에 조회 속도가 느리다. 하지만 값을 추가, 삭제할 때는 속도가 빠르다. 
// 선언
LinkedList<Integer> linkedList

// 생성
new LinkedList<Integer>();

// 값 추가
linkedList.add(추가할 값)

// 값 중간에 추가
linkedList.add(추가할 인덱스, 추가할 값)

// 값 수정
linkedList.set(수정할 인덱스, 수정할 값)

// 값 삭제
linkedList.remove(삭제할 인덱스)

// 전체 출력
linkedList.toString()

// 전체 제거
linkedList.clear()
    • Stack : 탑을 쌓듯이 값을 넣었다가 빼서 조회하는 형식으로 데이터를 관리한다.
    • LIFO(Last-In-First-Out) 나중에 들어간 것이 가장 먼저 나온다.
// 선언
Stack<Integer> intStack

// 생성
new Stack<Integer>();

// 값 추가
intStack.push(추가할 값)

// 값 조회 : 맨 위값을 조회
intStack.peek()

// 값 꺼내기 : 맨 위값을 꺼내기 (꺼내면 삭제됨)
intStack.pop()

 

Queue

  • 터널에 자동차가 들어가서 나오듯이 값을 한쪽으로 넣었다가 반대편으로 빼서 조회하는 형식으로 데이터를 관리한다.
  • FIFO(First-In-First-Out) 먼저 들어간 것이 가장 먼저 나온다.
  • 생성자가 없는 인터페이스라서 LinkedList를 사용하여 생성한다.
// 선언
Queue<Integer> intQueue

// 생성
new LinkedList<Integer>();

// 값 추가
intQueue.add(추가할 값)

// 값 조회 : 맨 아래값을 조회
intQueue.peek()

// 값 꺼내기 : 맨 아래값을 꺼내기 (꺼내면 삭제됨)
intQueue.poll()

Set

  • 순서가 없는 데이터의 집합
  • 데이터 중복을 허용하지 않는다.
  • 생성자가 없는 인터페이스라서 HashSet를 사용하여 생성한다. (TreeSet, LinkedHashSet 도 있음)
  • 순서 보장이 필요하면 LinkedHashSet을 사용한다.
// 선언
Set<Integer> intSet

// 생성
new HashSet<Integer>();

// 값 추가
intSet.add(추가할 값)

// 값 조회 : 해당 인덱스의 값을 조회
intSet.get(조회할 인덱스)

// 값 삭제
intSet.remove(삭제할 인덱스)

// 값 포함확인 : 결과가 boolean 값으로 나온다.
intSet.contains(포함확인할 값)

Map

  • key-value 구조로 구성된 데이터를 저장할 수 있다.
  • key값을 기준으로 value를 조회할 수 있다. (위에 있는 것처럼 index 방식 x)
  • HashMap, TreeMap 등으로 응용하여 사용할 수 있다.
// 선언
Map<String, Integer> intMap

// 생성
new HashMap<>();

// 추가
intMap.put(추가할 key값, 추가할 value값)

// 조회 : 해당 key에 있는 value값을 조회
intMap.get(조회할 key값)

// 전체 key 조회
intMap.keySet()

// 전체 value 조회
intMap.values()

// 삭제
intMap.remove(삭제할 key값)

 

· 오늘 서칭 한 자료

강의 자료

https://www.tcpschool.com/java/java_collectionFramework_concept

 

코딩교육 티씨피스쿨

4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등

tcpschool.com

 

 

· 느낀 점

자료구조에서 공부했던 stack, queue가 자바에서는 class로 구현을 해놨는데 많이 사용해서 그런거 같다.

데이터의 형태를 보고 내가 원하는 방법으로 저장하기 위해서 알아두면 좋을 거 같다.

배열보다 리스트가 크기를 정해놓지 않아서 자주 사용하게 될 거 같다.

해당 컬렉션에서 사용되는 메서드들을 알아두면 생각날 때 사용할 수 있을 거 같다. (암기보다는 자주 사용해서 익히자!)

반응형

'Today I Learned' 카테고리의 다른 글

2023-10-26 TIL  (0) 2023.10.26
2023-10-23 TIL  (0) 2023.10.23
2023-10-17 TIL  (0) 2023.10.18
2023-10-16 TIL  (0) 2023.10.17
2023-10-12 TIL  (0) 2023.10.13

· 오늘 공부한 것

Java 연산자 학습 및 사용방법 익히기

조건문과 반복문을 익히고 간단한 구구단 만들기

배열을 익혀서 데이터를 효율적으로 저장하고 관리하기 (다차원 배열까지)

InteliiJ 사용할 만한 plugin 찾기

 

·  공부한 내용, 궁금한 내용, 부족한 내용

연산자의 종류

산술 연산자 + - * / % << >> 사칙 연산과 비트연산
비교 연산자 > < >= <= == != 크고 작음과 같고 다름을 비교
논리 연산자 && || ! 그리고(AND)와 또는(OR) 으로 조건을 연결
대입 연산자 = ++ —- 우변의 값을 좌변에 저장, 연산 복합 대입
기타 연산자 (type) ? :  instance of 형변환 연산자, 삼항 연산자, instance of 연산자

 

연산자 우선순위

  • 산술 > 비교 > 논리 > 대입

조건문

  • if 문
    • if문 안에 if문이 들어가는 중첩 if문이 가능하다.
if (조건문1) {
	실행문1;
} else if (조건문2) {
	실행문2;
} else {
	실행문3;
}

 

  • switch 문
    • case마다 break를 해줘야 해당케이스에서 멈춘다. 안 하면 case가 끝날 때까지 switch문이 실행된다.
    • default는 if문에 else와 같은 것으로 아무것도 만족하지 않을 때 수행하는 것이다.
switch (변수) {
    case 값1 : 
    	실행문1;
        break;
    case 값2 :
    	실행문2;
        break;
    default :
    	실행문3;
}

 

반복문

break 명령은 가장 가까운 반복문을 중단한다.

반복문에서 순서를 패스하고 싶을 때는 continue 명령을 사용한다.

  • for 문
for (초기값; 조건문; 증가연산) {
	실행문;
}

// 향상된 for 문
// 배열과 같이 사용된다.
for(변수타입 변수명 : 배열) {
	실행문;
}
  • while 문
변수선언
while(조건문) {
	실행문;
}
  • do-while 문
    • do에 있는 실행문을 먼저 실행하고 조건문을 체크해서 반복한다.
변수선언
do {
	실행문;
} while (조건문);

 

구구단 생성하기 (조건문으로 제외할 구구단수를 지정)

Scanner sc = new Scanner(System.in);
int passNum = sc.nextInt(); // 출력제외할 구구단수 값
for (int i = 2; i <= 9; i++) {
	if (i == passNum) {
		continue;
	}
	for (int j = 2; j <= 9; j++) {
		System.out.println(i + " * " + j + " = " + (i * j));
	}
}

 

배열

  • 선언
    • 배열형 변수에는 같은 타입의 변수만 담을 수 있다.
// 1. 타입[] 변수;
int[] intArray;

// 2. 타입 변수[];
int intArray[];
  • 생성
    • new 명령을 통해서 생성하며 [] 안에 크기를 지정해 준다.
//배열 생성후 초기화하면 배열의 주소가 할당된다.
int[] intArray = new int[3]; // {0,0,0}
boolean[] boolArray = new boolean[3]; // {false, false, false}
String[] stringArray = new String[3]; // {"","",""}
		
//배열 선언만 해놓고 나중에 초기화를 시킬수도 있다.
int[] intArray2;
intArray2 = new int[3]; //  {0,0,0}
  • 순회
    • 단건조회 : 인덱스로 접근해서 해당 배열의 값을 가져온다.
    • 다건조회 : 반복문으로 순회하면서 배열의 값에 접근할 수 있다.
  • 초기화
    1. {}를 사용해서 초기화
    2. 반복문 for문을 사용해서 초기화 (향상된 for문도 가능)
    3. Arrays.fill 메서드를 사용해서 초기화
  • 복사
    • 얕은 복사 : 대입 연사자 = 를 사용해서 복사한 경우 주소값만 복사된다.
    • 깊은 복사
      1. for문을 통해서 하나씩 배열의 값을 꺼내서 복사해 주는 방법
      2. clone() 메서드를 사용한 방법 (!! 2차원 이상 배열에서는 얕은 복사로 동작)
      3. Arrays.copyOf(배열, 배열의 길이) 메서드를 사용한 방법

 

 

· 오늘 서칭 한 자료

강의자료

https://opentutorials.org/course/1223/5331

 

연산자 - 생활코딩

연산자란 연산자(演펴다연 算계산산 子, operator)란 특정한 작업을 하기 위해서 사용하는 기호를 의미한다. 작업의 종류에 따라서 대입 연산자, 산술 연산자, 비교 연산자, 논리 연산자 등이 있다.

opentutorials.org

 

개발자 쓸만한 인텔리제이 플러그인 추천 (IntelliJ Plugin)

목차 개인적으로 쓰고 있는 플러그인들 중에 쓸만한 것들을 한번 적어봤다. File -> Settings -> Plugins 에서 검색해서 설치하면 된다. Atom Material Icons IDE 전체적인 아이콘들을 이쁘게 해준다! 일단 깔

nahwasa.com

 

 

구글 번역기 틀어두고 개발하는 분들을 위한 인텔리제이 플러그인

영어가 부족해 개발할 때 구글 번역기를 틀어두면서 변수명, 함수명, 클래스명 등을 정할 때 참고하는 편입니다. reference에 있는 인프런 강의를 보다가 좋은 플러그인을 알게되어 공유해봅니다.

nahwasa.com

· 느낀 점

javascript에서 사용한 문법들이기는 했지만 조금씩 사용방법이 달랐기에 어떻게 다른지 비교하면서 학습을 할 수 있었다.

특히 배열 부분에서 같은 타입의 변수만 담을 수 있었기에 javascript보다 자유도가 떨어져 보이기는 했지만 같은 타입끼리만 있기 때문에 데이터를 저장하고 관리하는 데는 좋다고 느꼈다.

다양한 메서드들을 익혀서 적극적으로 사용해보고 싶다.

 

반응형

'Today I Learned' 카테고리의 다른 글

2023-10-23 TIL  (0) 2023.10.23
2023-10-18 TIL  (0) 2023.10.19
2023-10-16 TIL  (0) 2023.10.17
2023-10-12 TIL  (0) 2023.10.13
2023-10-11 TIL  (0) 2023.10.12

+ Recent posts